You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

80 lines
1.9 KiB
Go

package game
import (
"io"
"log/slog"
"testing"
"time"
"github.com/denisovdennis/autohero/internal/model"
)
func TestResolveCombat_MatchesEngineOutcome(t *testing.T) {
baseHero := &model.Hero{
ID: 1,
Level: 5,
MaxHP: 320,
HP: 320,
Attack: 25,
Defense: 8,
Speed: 1.0,
Strength: 10,
Constitution: 12,
Agility: 8,
Luck: 5,
Potions: 0,
State: model.StateWalking,
}
tmpl, ok := model.EnemyBySlug("wolf")
if !ok {
tmpl = model.Enemy{
Slug: "wolf",
Archetype: "wolf",
Name: "Forest Wolf",
MaxHP: 40,
HP: 40,
Attack: 8,
Defense: 2,
Speed: 1.2,
BaseLevel: 1,
LevelVariance: 0.3,
MaxHeroLevelDiff: 5,
HPPerLevel: 5,
AttackPerLevel: 1.5,
DefensePerLevel: 1.0,
}
}
enemy := ScaleEnemyTemplate(tmpl, baseHero.Level)
logger := slog.New(slog.NewTextHandler(io.Discard, nil))
eventCh := make(chan model.CombatEvent, 8)
engine := NewEngine(100*time.Millisecond, eventCh, logger)
heroEngine := *baseHero
enemyEngine := enemy
engine.StartCombat(&heroEngine, &enemyEngine)
now := time.Now()
for i := 0; i < 20000; i++ {
now = now.Add(100 * time.Millisecond)
engine.processCombatTick(now)
if _, ok := engine.GetCombat(heroEngine.ID); !ok {
break
}
}
heroResolve := *baseHero
enemyResolve := enemy
survived := ResolveCombatToEnd(&heroResolve, &enemyResolve, time.Now(), CombatSimOptions{
TickRate: 100 * time.Millisecond,
})
engineSurvived := heroEngine.HP > 0
if survived != engineSurvived {
t.Fatalf("survival mismatch: resolve=%v engine=%v", survived, engineSurvived)
}
// Final HP can differ: engine applies debuff ticks for all combats before the attack queue each tick,
// while ResolveCombatToEnd interleaves tick vs attacks on one timeline. Survival is the parity signal.
}