diff --git a/src/Game/Game.php b/src/Game/Game.php index d79efdc..57709cc 100644 --- a/src/Game/Game.php +++ b/src/Game/Game.php @@ -19,7 +19,15 @@ class Game { $this->blackKing = current(array_filter($this->pieces, fn($p) => ($p instanceof King) && $p->getSide() == Side::BLACK)); } - private function getPieces(Side $side): array { + public function getCurrentSide(): Side { + return $this->current; + } + + public function getAllPieces(): array { + return $this->pieces; + } + + public function getPieces(Side $side): array { return array_filter($this->pieces, fn($p) => $p->getSide() == $side); } @@ -267,18 +275,30 @@ class Game { public function applyInPlace(Move $move): void { $this->tick(); - if ($move->captures) { - $this->removePiece($move->captures); - } - if ($move->promoteTo) { - $this->removePiece($move->piece); + if ($move->castleWith) { + $king = $this->findPiece($move->piece); + $rook = $this->findPiece($move->castleWith); - $promoted = $move->piece->promote($move->promoteTo); - $promoted->move($move->target); - $this->pieces[] = $promoted; + // move rook first to avoid temporary variable + $rook->move(new Position( + ($king->getPosition()->file + $move->target->file) / 2, + $rook->getPosition()->rank, + )); + $king->move($move->target); } else { - $piece = $this->findPiece($move->piece); - $piece->move($move->target); + if ($move->captures) { + $this->removePiece($move->captures); + } + if ($move->promoteTo) { + $this->removePiece($move->piece); + + $promoted = $move->piece->promote($move->promoteTo); + $promoted->move($move->target); + $this->pieces[] = $promoted; + } else { + $piece = $this->findPiece($move->piece); + $piece->move($move->target); + } } $this->current = $this->current->getNext(); diff --git a/tests/Game/GameTest.php b/tests/Game/GameTest.php index b5b3b67..992f0b7 100644 --- a/tests/Game/GameTest.php +++ b/tests/Game/GameTest.php @@ -448,4 +448,38 @@ final class GameTest extends TestCase { new Rook(new Position(7, 1), Side::BLACK), ), $legalMoves); } + + public function testApply_castles() { + $subject = new Game( + [ + new King(new Position(0, 7), Side::BLACK), + new King(new Position(4, 0), Side::WHITE), + new Rook(new Position(7, 0), Side::WHITE), + ], + Side::WHITE + ); + + $subject->applyInPlace(new Move( + new King(new Position(4, 0), Side::WHITE), + new Position(6, 0), + null, + null, + new Rook(new Position(7, 0), Side::WHITE), + )); + + $this->assertEquals(Side::BLACK, $subject->getCurrentSide()); + + $pieces = $subject->getPieces(Side::WHITE); + $this->assertCount(2, $pieces); + + $this->assertContainsEqualsOnce( + new King(new Position(6, 0), Side::WHITE), + $pieces + ); + $this->assertContainsEqualsOnce( + new Rook(new Position(5, 0), Side::WHITE), + $pieces + ); + + } } \ No newline at end of file