feat: Correctly apply castles

This commit is contained in:
overflowerror 2024-01-07 13:15:13 +01:00
parent 11d9e04f07
commit 90077fdb37
2 changed files with 65 additions and 11 deletions

View file

@ -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();

View file

@ -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
);
}
}