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
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.
|
|
}
|