mirror of
https://github.com/sigmasternchen/php-chess
synced 2025-03-15 07:58:54 +00:00
fix: En passant only works the move after
This commit is contained in:
parent
e965c8b5af
commit
c43de25f9e
4 changed files with 153 additions and 9 deletions
|
@ -171,7 +171,7 @@ class Game {
|
||||||
if ($this->isCapture($target, $captureableForPawn)) {
|
if ($this->isCapture($target, $captureableForPawn)) {
|
||||||
$candidate->captures = $this->findCapturedPiece($piece, $opponentPieces, $target);
|
$candidate->captures = $this->findCapturedPiece($piece, $opponentPieces, $target);
|
||||||
}
|
}
|
||||||
if ($piece->canPromote($target)) {
|
if ($piece instanceof Pawn && $piece->promotes($target)) {
|
||||||
$candidates = array_merge($candidates, $this->generatePromotionMoves($candidate));
|
$candidates = array_merge($candidates, $this->generatePromotionMoves($candidate));
|
||||||
} else {
|
} else {
|
||||||
$candidates[] = $candidate;
|
$candidates[] = $candidate;
|
||||||
|
@ -216,23 +216,35 @@ class Game {
|
||||||
$this->current,
|
$this->current,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
$game->applyInPlace($move);
|
||||||
|
|
||||||
|
return $game;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function tick(): void {
|
||||||
|
foreach ($this->pieces as $piece) {
|
||||||
|
$piece->tick();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function applyInPlace(Move $move): void {
|
||||||
|
$this->tick();
|
||||||
|
|
||||||
if ($move->captures) {
|
if ($move->captures) {
|
||||||
$game->removePiece($move->captures);
|
$this->removePiece($move->captures);
|
||||||
}
|
}
|
||||||
if ($move->promoteTo) {
|
if ($move->promoteTo) {
|
||||||
$game->removePiece($move->piece);
|
$this->removePiece($move->piece);
|
||||||
|
|
||||||
$promoted = $move->piece->promote($move->promoteTo);
|
$promoted = $move->piece->promote($move->promoteTo);
|
||||||
$promoted->move($move->target);
|
$promoted->move($move->target);
|
||||||
$game->pieces[] = $promoted;
|
$this->pieces[] = $promoted;
|
||||||
} else {
|
} else {
|
||||||
$piece = $game->findPiece($move->piece);
|
$piece = $this->findPiece($move->piece);
|
||||||
$piece->move($move->target);
|
$piece->move($move->target);
|
||||||
}
|
}
|
||||||
|
|
||||||
$game->current = $game->current->getNext();
|
$this->current = $this->current->getNext();
|
||||||
|
|
||||||
return $game;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getGameState(bool $onlyIsLegal = false): GameState {
|
public function getGameState(bool $onlyIsLegal = false): GameState {
|
||||||
|
|
|
@ -71,7 +71,7 @@ class Pawn extends Piece {
|
||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function canPromote(Position $position): bool {
|
public function promotes(Position $position): bool {
|
||||||
return ($this->side == Side::WHITE) ? ($position->rank == 7) : ($position->rank == 0);
|
return ($this->side == Side::WHITE) ? ($position->rank == 7) : ($position->rank == 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -301,4 +301,103 @@ final class GameTest extends TestCase {
|
||||||
new Queen(new Position(1, 1), Side::WHITE), null,
|
new Queen(new Position(1, 1), Side::WHITE), null,
|
||||||
), $legalMoves);
|
), $legalMoves);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testLegalMoves_enPassantNotPossibleBecauseMoveInBetween() {
|
||||||
|
$subject = new Game(
|
||||||
|
[
|
||||||
|
new King(new Position(0, 1), Side::BLACK),
|
||||||
|
new King(new Position(0, 7), Side::WHITE),
|
||||||
|
new Queen(new Position(1, 3), Side::WHITE),
|
||||||
|
new Pawn(new Position(5, 1), Side::WHITE),
|
||||||
|
new Pawn(new Position(6, 2), Side::WHITE),
|
||||||
|
new Pawn(new Position(6, 3), Side::BLACK, true),
|
||||||
|
],
|
||||||
|
Side::WHITE
|
||||||
|
);
|
||||||
|
$subject->applyInPlace(new Move(
|
||||||
|
new Pawn(new Position(5, 1), Side::WHITE),
|
||||||
|
new Position(5, 3)
|
||||||
|
));
|
||||||
|
$subject->applyInPlace(new Move(
|
||||||
|
new King(new Position(0, 1), Side::BLACK),
|
||||||
|
new Position(0, 0)
|
||||||
|
));
|
||||||
|
$subject->applyInPlace(new Move(
|
||||||
|
new Queen(new Position(1, 3), Side::WHITE),
|
||||||
|
new Position(1, 4)
|
||||||
|
));
|
||||||
|
|
||||||
|
$legalMoves = $subject->getLegalMoves();
|
||||||
|
|
||||||
|
$this->assertCount(1, $legalMoves);
|
||||||
|
|
||||||
|
$this->assertContainsEqualsOnce(new Move(
|
||||||
|
new King(new Position(0, 0), Side::BLACK),
|
||||||
|
new Position(0, 1),
|
||||||
|
), $legalMoves);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testLegalMoves_enPassantNotPossibleBecausePawnDidntMove2Squares() {
|
||||||
|
$subject = new Game(
|
||||||
|
[
|
||||||
|
new King(new Position(0, 0), Side::BLACK),
|
||||||
|
new King(new Position(0, 7), Side::WHITE),
|
||||||
|
new Queen(new Position(1, 3), Side::WHITE),
|
||||||
|
new Pawn(new Position(5, 1), Side::WHITE),
|
||||||
|
new Pawn(new Position(6, 2), Side::WHITE),
|
||||||
|
new Pawn(new Position(6, 3), Side::BLACK, true),
|
||||||
|
],
|
||||||
|
Side::WHITE
|
||||||
|
);
|
||||||
|
$subject->applyInPlace(new Move(
|
||||||
|
new Pawn(new Position(5, 1), Side::WHITE),
|
||||||
|
new Position(5, 2)
|
||||||
|
));
|
||||||
|
$subject->applyInPlace(new Move(
|
||||||
|
new King(new Position(0, 0), Side::BLACK),
|
||||||
|
new Position(0, 1)
|
||||||
|
));
|
||||||
|
$subject->applyInPlace(new Move(
|
||||||
|
new Pawn(new Position(5, 2), Side::WHITE),
|
||||||
|
new Position(5, 3)
|
||||||
|
));
|
||||||
|
|
||||||
|
$legalMoves = $subject->getLegalMoves();
|
||||||
|
|
||||||
|
$this->assertCount(1, $legalMoves);
|
||||||
|
|
||||||
|
$this->assertContainsEqualsOnce(new Move(
|
||||||
|
new King(new Position(0, 1), Side::BLACK),
|
||||||
|
new Position(0, 0),
|
||||||
|
), $legalMoves);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testLegalMoves_enPassantPossible() {
|
||||||
|
$subject = new Game(
|
||||||
|
[
|
||||||
|
new King(new Position(0, 0), Side::BLACK),
|
||||||
|
new King(new Position(0, 7), Side::WHITE),
|
||||||
|
new Queen(new Position(1, 2), Side::WHITE),
|
||||||
|
new Pawn(new Position(5, 1), Side::WHITE),
|
||||||
|
new Pawn(new Position(6, 2), Side::WHITE),
|
||||||
|
new Pawn(new Position(6, 3), Side::BLACK, true),
|
||||||
|
],
|
||||||
|
Side::WHITE
|
||||||
|
);
|
||||||
|
|
||||||
|
$subject->applyInPlace(new Move(
|
||||||
|
new Pawn(new Position(5, 1), Side::WHITE),
|
||||||
|
new Position(5, 3)
|
||||||
|
));
|
||||||
|
|
||||||
|
$legalMoves = $subject->getLegalMoves();
|
||||||
|
|
||||||
|
$this->assertCount(1, $legalMoves);
|
||||||
|
|
||||||
|
$this->assertContainsEqualsOnce(new Move(
|
||||||
|
new Pawn(new Position(6, 3), Side::BLACK),
|
||||||
|
new Position(5, 2),
|
||||||
|
new Pawn(new Position(5, 3), Side::WHITE),
|
||||||
|
), $legalMoves);
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -243,4 +243,37 @@ final class PawnTest extends TestCase {
|
||||||
]))
|
]))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testPromotes_no() {
|
||||||
|
$subject = new Pawn(
|
||||||
|
new Position(3, 4),
|
||||||
|
Side::WHITE,
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->assertFalse(
|
||||||
|
$subject->promotes(new Position(3, 5))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testPromotes_white() {
|
||||||
|
$subject = new Pawn(
|
||||||
|
new Position(3, 6),
|
||||||
|
Side::WHITE,
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->assertTrue(
|
||||||
|
$subject->promotes(new Position(3, 7))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testPromotes_black() {
|
||||||
|
$subject = new Pawn(
|
||||||
|
new Position(3, 1),
|
||||||
|
Side::BLACK,
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->assertTrue(
|
||||||
|
$subject->promotes(new Position(3, 0))
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
Loading…
Reference in a new issue