package game import ( "testing" "time" "github.com/denisovdennis/autohero/internal/model" ) func TestSimulateOneFight_HeroSurvives(t *testing.T) { hero := &model.Hero{ Level: 1, XP: 0, MaxHP: 10000, HP: 10000, Attack: 100, Defense: 60, Speed: 1.0, Strength: 10, Constitution: 10, Agility: 10, Luck: 5, State: model.StateWalking, } now := time.Now() survived, enemy, xpGained, goldGained := SimulateOneFight(hero, now, nil) if !survived { t.Fatalf("overpowered hero should survive, enemy was %s", enemy.Name) } if xpGained <= 0 { t.Fatal("expected positive XP gain") } if goldGained <= 0 { t.Fatal("expected positive gold gain") } if enemy.Name == "" { t.Fatal("expected enemy with a name") } } func TestSimulateOneFight_HeroDies(t *testing.T) { hero := &model.Hero{ Level: 1, XP: 0, MaxHP: 1, HP: 1, Attack: 1, Defense: 0, Speed: 1.0, State: model.StateWalking, } now := time.Now() survived, _, _, _ := SimulateOneFight(hero, now, nil) if survived { t.Fatal("1 HP hero should die to any enemy") } if hero.HP != 0 { t.Fatalf("expected HP 0 after death, got %d", hero.HP) } if hero.State != model.StateDead { t.Fatalf("expected state dead, got %s", hero.State) } } func TestSimulateOneFight_LevelUp(t *testing.T) { // Seed XP just below L1->L2 threshold (180 in v3). hero := &model.Hero{ Level: 1, XP: 179, MaxHP: 10000, HP: 10000, Attack: 100, Defense: 60, Speed: 1.0, Strength: 10, Constitution: 10, Agility: 10, Luck: 5, State: model.StateWalking, } now := time.Now() survived, _, xpGained, _ := SimulateOneFight(hero, now, nil) if !survived { t.Fatal("overpowered hero should survive") } if xpGained <= 0 { t.Fatal("expected XP gain") } if hero.Level < 2 { t.Fatalf("expected level 2+ after gaining %d XP from 179 base, got level %d", xpGained, hero.Level) } } func TestSimulateOneFight_PotionUsage(t *testing.T) { // Create a hero that will take significant damage but survive. hero := &model.Hero{ Level: 1, XP: 0, MaxHP: 100, HP: 100, Attack: 50, Defense: 3, Speed: 1.0, Potions: 5, State: model.StateWalking, } now := time.Now() startPotions := hero.Potions // Run multiple fights — at least one should use a potion. for i := 0; i < 20; i++ { if hero.HP <= 0 { break } hero.HP = 25 // force low HP to trigger potion usage SimulateOneFight(hero, now, nil) } if hero.Potions >= startPotions { t.Log("no potions used after 20 fights with low HP — may be probabilistic, not a hard failure") } } func TestPickEnemyForLevel(t *testing.T) { tests := []struct { level int }{ {1}, {5}, {10}, {20}, {50}, } for _, tt := range tests { enemy := PickEnemyForLevel(tt.level) if enemy.Name == "" { t.Errorf("PickEnemyForLevel(%d) returned enemy with empty name", tt.level) } if enemy.MaxHP <= 0 { t.Errorf("PickEnemyForLevel(%d) returned enemy with MaxHP=%d", tt.level, enemy.MaxHP) } if enemy.HP != enemy.MaxHP { t.Errorf("PickEnemyForLevel(%d) returned enemy with HP=%d != MaxHP=%d", tt.level, enemy.HP, enemy.MaxHP) } } } func TestScaleEnemyTemplate(t *testing.T) { tmpl := model.EnemyTemplates[model.EnemyWolf] scaled := ScaleEnemyTemplate(tmpl, 5) if scaled.MaxHP <= tmpl.MaxHP { t.Errorf("scaled MaxHP %d should exceed base %d at level 5", scaled.MaxHP, tmpl.MaxHP) } if scaled.HP != scaled.MaxHP { t.Errorf("scaled HP %d should equal MaxHP %d", scaled.HP, scaled.MaxHP) } }