fix: guard invalid turn transitions
This commit is contained in:
@@ -564,14 +564,21 @@ final class CombatEngineTest extends TestCase
|
||||
(new CombatEngine())->endTurn($match);
|
||||
}
|
||||
|
||||
public function testEndTurnRejectsMatchesWithoutExactlyAlphaAndBravoTeams(): void
|
||||
/**
|
||||
* @param list<string> $teamIds
|
||||
*/
|
||||
#[DataProvider('invalidEndTurnTeamProvider')]
|
||||
public function testEndTurnRejectsMatchesWithoutExactlyAlphaAndBravoTeams(array $teamIds): void
|
||||
{
|
||||
$units = [];
|
||||
|
||||
foreach ($teamIds as $index => $teamId) {
|
||||
$units[] = $this->unit("{$teamId}-{$index}", $teamId, new Position($index, 0));
|
||||
}
|
||||
|
||||
$match = new MatchState(
|
||||
new Battlefield(8, 8),
|
||||
[
|
||||
$this->unit('alpha-1', 'alpha', new Position(0, 0)),
|
||||
$this->unit('charlie-1', 'charlie', new Position(7, 7)),
|
||||
],
|
||||
$units,
|
||||
'alpha',
|
||||
);
|
||||
|
||||
@@ -581,6 +588,109 @@ final class CombatEngineTest extends TestCase
|
||||
(new CombatEngine())->endTurn($match);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return iterable<string, array{list<string>}>
|
||||
*/
|
||||
public static function invalidEndTurnTeamProvider(): iterable
|
||||
{
|
||||
yield 'only alpha' => [['alpha']];
|
||||
yield 'alpha and charlie' => [['alpha', 'charlie']];
|
||||
yield 'alpha, bravo, and charlie' => [['alpha', 'bravo', 'charlie']];
|
||||
}
|
||||
|
||||
#[DataProvider('eliminatedEndTurnTeamProvider')]
|
||||
public function testEndTurnRejectsEliminatedTeam(string $activeTeamId, string $eliminatedTeamId): void
|
||||
{
|
||||
$match = new MatchState(
|
||||
new Battlefield(8, 8),
|
||||
[
|
||||
$this->unit(
|
||||
'alpha-1',
|
||||
'alpha',
|
||||
new Position(0, 0),
|
||||
health: $eliminatedTeamId === 'alpha' ? 0 : 10,
|
||||
),
|
||||
$this->unit(
|
||||
'bravo-1',
|
||||
'bravo',
|
||||
new Position(7, 7),
|
||||
health: $eliminatedTeamId === 'bravo' ? 0 : 10,
|
||||
),
|
||||
],
|
||||
$activeTeamId,
|
||||
);
|
||||
|
||||
$this->expectException(CombatException::class);
|
||||
$this->expectExceptionMessage('Cannot end turn while a team is eliminated.');
|
||||
|
||||
(new CombatEngine())->endTurn($match);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return iterable<string, array{string, string}>
|
||||
*/
|
||||
public static function eliminatedEndTurnTeamProvider(): iterable
|
||||
{
|
||||
yield 'incoming team' => ['alpha', 'bravo'];
|
||||
yield 'active team' => ['alpha', 'alpha'];
|
||||
}
|
||||
|
||||
public function testEndTurnRejectsEliminatedTeamBeforeRoundLimit(): void
|
||||
{
|
||||
$match = new MatchState(
|
||||
new Battlefield(8, 8),
|
||||
[
|
||||
$this->unit('alpha-1', 'alpha', new Position(0, 0), health: 0),
|
||||
$this->unit('bravo-1', 'bravo', new Position(7, 7)),
|
||||
],
|
||||
'bravo',
|
||||
round: PHP_INT_MAX,
|
||||
);
|
||||
|
||||
$this->expectException(CombatException::class);
|
||||
$this->expectExceptionMessage('Cannot end turn while a team is eliminated.');
|
||||
|
||||
(new CombatEngine())->endTurn($match);
|
||||
}
|
||||
|
||||
public function testEndTurnRejectsRoundIncrementBeyondIntegerLimit(): void
|
||||
{
|
||||
$match = new MatchState(
|
||||
new Battlefield(8, 8),
|
||||
[
|
||||
$this->unit('alpha-1', 'alpha', new Position(0, 0)),
|
||||
$this->unit('bravo-1', 'bravo', new Position(7, 7)),
|
||||
],
|
||||
'bravo',
|
||||
round: PHP_INT_MAX,
|
||||
);
|
||||
|
||||
$this->expectException(CombatException::class);
|
||||
$this->expectExceptionMessage('Match round limit reached.');
|
||||
|
||||
(new CombatEngine())->endTurn($match);
|
||||
}
|
||||
|
||||
public function testEndTurnAllowsAlphaToPassAtIntegerRoundLimit(): void
|
||||
{
|
||||
$match = new MatchState(
|
||||
new Battlefield(8, 8),
|
||||
[
|
||||
$this->unit('alpha-1', 'alpha', new Position(0, 0)),
|
||||
$this->unit('bravo-1', 'bravo', new Position(7, 7), actionsRemaining: 0),
|
||||
],
|
||||
'alpha',
|
||||
round: PHP_INT_MAX,
|
||||
);
|
||||
|
||||
$next = (new CombatEngine())->endTurn($match);
|
||||
|
||||
self::assertSame('bravo', $next->activeTeamId);
|
||||
self::assertSame(PHP_INT_MAX, $next->round);
|
||||
self::assertSame(2, $next->unit('bravo-1')->actionsRemaining);
|
||||
self::assertSame(['alpha ended turn'], $next->actionLog);
|
||||
}
|
||||
|
||||
public function testEndTurnDoesNotRefreshDefeatedUnitsOnIncomingTeam(): void
|
||||
{
|
||||
$match = new MatchState(
|
||||
|
||||
Reference in New Issue
Block a user