feat(combat): wade visual + smoke test budget
This commit is contained in:
@@ -231,29 +231,37 @@ final class CombatEngineTest extends TestCase
|
||||
{
|
||||
$attacker = $this->unit('alpha-1', 'alpha', new Position(0, 0));
|
||||
$target = $this->unit('bravo-1', 'bravo', new Position(1, 0));
|
||||
$match = new MatchState(
|
||||
$buildMatch = static fn (): MatchState => new MatchState(
|
||||
new Battlefield(8, 8, ['1:0' => Terrain::Forest]),
|
||||
[$attacker, $target],
|
||||
'alpha',
|
||||
actionLog: ['match started'],
|
||||
);
|
||||
|
||||
$next = (new CombatEngine())->attack($match, 'alpha-1', 'bravo-1');
|
||||
// Loop until a non-crit hit lands; a crit would double the base 1 damage to 2,
|
||||
// which would mask the variance behavior this test exercises.
|
||||
$next = $buildMatch();
|
||||
for ($i = 0; $i < 200; $i += 1) {
|
||||
$fresh = $buildMatch();
|
||||
$next = (new CombatEngine())->attack($fresh, 'alpha-1', 'bravo-1');
|
||||
$entry = $next->actionLog[0] ?? '';
|
||||
if (str_contains($entry, 'for ') && !str_contains($entry, ' — crit') && !str_contains($entry, ' — miss')) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Original match state must not have been mutated by the loop's iterations.
|
||||
self::assertSame(10, $target->health);
|
||||
self::assertSame(2, $attacker->actionsRemaining);
|
||||
self::assertFalse($attacker->hasAttacked);
|
||||
self::assertSame(10, $match->unit('bravo-1')->health);
|
||||
self::assertSame(2, $match->unit('alpha-1')->actionsRemaining);
|
||||
self::assertFalse($match->unit('alpha-1')->hasAttacked);
|
||||
self::assertSame(['match started'], $match->actionLog);
|
||||
|
||||
self::assertGreaterThanOrEqual(9, $next->unit('bravo-1')->health);
|
||||
self::assertLessThanOrEqual(10, $next->unit('bravo-1')->health);
|
||||
self::assertSame(1, $next->unit('alpha-1')->actionsRemaining);
|
||||
self::assertTrue($next->unit('alpha-1')->hasAttacked);
|
||||
// With attack=4, defense=2, +1 forest defense: base = max(1, 4-2-1) = 1.
|
||||
// On hit, damage = 1 (variance leaves it at 1). On miss, damage = 0.
|
||||
$log = $next->actionLog[1];
|
||||
$log = $next->actionLog[1] ?? '';
|
||||
self::assertMatchesRegularExpression(
|
||||
'/^alpha-1 attacked bravo-1 \(rolled \d+ \/ needed \d+\) for \d+ damage( — (miss|crit|concealed)( .+)?)?$/',
|
||||
$log,
|
||||
|
||||
Reference in New Issue
Block a user