mirror of
https://github.com/sigmasternchen/php-chess
synced 2025-03-15 07:58:54 +00:00
feat: Add fifty-move-rule
This commit is contained in:
parent
78f6ba6ef2
commit
1d9f6f5736
2 changed files with 136 additions and 0 deletions
|
@ -13,6 +13,9 @@ class Game {
|
||||||
|
|
||||||
private ?array $moveCache = null;
|
private ?array $moveCache = null;
|
||||||
|
|
||||||
|
private int $movesSinceLastCapture = 0;
|
||||||
|
private int $movesSinceLastPawnMove = 0;
|
||||||
|
|
||||||
public function __construct(array $pieces, Side $current) {
|
public function __construct(array $pieces, Side $current) {
|
||||||
$this->pieces = $pieces;
|
$this->pieces = $pieces;
|
||||||
$this->current = $current;
|
$this->current = $current;
|
||||||
|
@ -281,6 +284,9 @@ class Game {
|
||||||
public function applyInPlace(Move $move): void {
|
public function applyInPlace(Move $move): void {
|
||||||
$this->tick();
|
$this->tick();
|
||||||
|
|
||||||
|
$this->movesSinceLastPawnMove++;
|
||||||
|
$this->movesSinceLastCapture++;
|
||||||
|
|
||||||
if ($move->castleWith) {
|
if ($move->castleWith) {
|
||||||
$king = $this->findPiece($move->piece);
|
$king = $this->findPiece($move->piece);
|
||||||
$rook = $this->findPiece($move->castleWith);
|
$rook = $this->findPiece($move->castleWith);
|
||||||
|
@ -294,7 +300,12 @@ class Game {
|
||||||
} else {
|
} else {
|
||||||
if ($move->captures) {
|
if ($move->captures) {
|
||||||
$this->removePiece($move->captures);
|
$this->removePiece($move->captures);
|
||||||
|
$this->movesSinceLastCapture = 0;
|
||||||
}
|
}
|
||||||
|
if ($move->piece instanceof Pawn) {
|
||||||
|
$this->movesSinceLastPawnMove = 0;
|
||||||
|
}
|
||||||
|
|
||||||
if ($move->promoteTo) {
|
if ($move->promoteTo) {
|
||||||
$this->removePiece($move->piece);
|
$this->removePiece($move->piece);
|
||||||
|
|
||||||
|
@ -352,6 +363,15 @@ class Game {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function _testFiftyMoveRule(int $movesSinceLastCapture, int $movesSinceLastPawnMove) {
|
||||||
|
$this->movesSinceLastPawnMove = $movesSinceLastPawnMove;
|
||||||
|
$this->movesSinceLastCapture = $movesSinceLastCapture;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function isFiftyMoveRule(): bool {
|
||||||
|
return $this->movesSinceLastCapture >= 50 && $this->movesSinceLastPawnMove >= 50;
|
||||||
|
}
|
||||||
|
|
||||||
public function getGameState(bool $onlyIsLegal = false): GameState {
|
public function getGameState(bool $onlyIsLegal = false): GameState {
|
||||||
$allOccupied = $this->getAllOccupied();
|
$allOccupied = $this->getAllOccupied();
|
||||||
|
|
||||||
|
@ -371,6 +391,10 @@ class Game {
|
||||||
return GameState::DEAD_POSITION;
|
return GameState::DEAD_POSITION;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($this->isFiftyMoveRule()) {
|
||||||
|
return GameState::FIFTY_MOVE_RULE;
|
||||||
|
}
|
||||||
|
|
||||||
$legalMoves = $this->getLegalMoves();
|
$legalMoves = $this->getLegalMoves();
|
||||||
|
|
||||||
if ($this->isCheck($allOccupied)) {
|
if ($this->isCheck($allOccupied)) {
|
||||||
|
|
|
@ -351,6 +351,118 @@ final class GameTest extends TestCase {
|
||||||
$this->assertEquals(GameState::DEFAULT, $subject->getGameState());
|
$this->assertEquals(GameState::DEFAULT, $subject->getGameState());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testGameState_fiftyMoveRule() {
|
||||||
|
$subject = new Game(
|
||||||
|
[
|
||||||
|
new King(new Position(2, 7), Side::WHITE, true),
|
||||||
|
new King(new Position(0, 0), Side::BLACK, true),
|
||||||
|
new Rook(new Position(1, 0), Side::BLACK),
|
||||||
|
],
|
||||||
|
Side::BLACK
|
||||||
|
);
|
||||||
|
$subject->_testFiftyMoveRule(49, 49);
|
||||||
|
$this->assertEquals(GameState::DEFAULT, $subject->getGameState());
|
||||||
|
|
||||||
|
$subject->applyInPlace(new Move(
|
||||||
|
new Rook(new Position(1, 0), Side::BLACK),
|
||||||
|
new Position(3, 0)
|
||||||
|
));
|
||||||
|
|
||||||
|
echo $subject->visualize();
|
||||||
|
|
||||||
|
$this->assertEquals(GameState::FIFTY_MOVE_RULE, $subject->getGameState());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testGameState_fiftyMoveRule_notLongEnoughSincePawnMove() {
|
||||||
|
$subject = new Game(
|
||||||
|
[
|
||||||
|
new King(new Position(2, 7), Side::WHITE, true),
|
||||||
|
new King(new Position(0, 0), Side::BLACK, true),
|
||||||
|
new Rook(new Position(1, 0), Side::BLACK),
|
||||||
|
],
|
||||||
|
Side::BLACK
|
||||||
|
);
|
||||||
|
$subject->_testFiftyMoveRule(49, 48);
|
||||||
|
$this->assertEquals(GameState::DEFAULT, $subject->getGameState());
|
||||||
|
|
||||||
|
$subject->applyInPlace(new Move(
|
||||||
|
new Rook(new Position(1, 0), Side::BLACK),
|
||||||
|
new Position(3, 0)
|
||||||
|
));
|
||||||
|
|
||||||
|
echo $subject->visualize();
|
||||||
|
|
||||||
|
$this->assertEquals(GameState::DEFAULT, $subject->getGameState());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testGameState_fiftyMoveRule_notLongEnoughSinceCapture() {
|
||||||
|
$subject = new Game(
|
||||||
|
[
|
||||||
|
new King(new Position(2, 7), Side::WHITE, true),
|
||||||
|
new King(new Position(0, 0), Side::BLACK, true),
|
||||||
|
new Rook(new Position(1, 0), Side::BLACK),
|
||||||
|
],
|
||||||
|
Side::BLACK
|
||||||
|
);
|
||||||
|
$subject->_testFiftyMoveRule(48, 49);
|
||||||
|
$this->assertEquals(GameState::DEFAULT, $subject->getGameState());
|
||||||
|
|
||||||
|
$subject->applyInPlace(new Move(
|
||||||
|
new Rook(new Position(1, 0), Side::BLACK),
|
||||||
|
new Position(3, 0)
|
||||||
|
));
|
||||||
|
|
||||||
|
echo $subject->visualize();
|
||||||
|
|
||||||
|
$this->assertEquals(GameState::DEFAULT, $subject->getGameState());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testGameState_fiftyMoveRule_capture() {
|
||||||
|
$subject = new Game(
|
||||||
|
[
|
||||||
|
new King(new Position(2, 7), Side::WHITE, true),
|
||||||
|
new King(new Position(0, 0), Side::BLACK, true),
|
||||||
|
new Rook(new Position(1, 0), Side::BLACK),
|
||||||
|
new Bishop(new Position(3, 0), Side::WHITE),
|
||||||
|
],
|
||||||
|
Side::BLACK
|
||||||
|
);
|
||||||
|
$subject->_testFiftyMoveRule(49, 49);
|
||||||
|
$this->assertEquals(GameState::DEFAULT, $subject->getGameState());
|
||||||
|
|
||||||
|
$subject->applyInPlace(new Move(
|
||||||
|
new Rook(new Position(1, 0), Side::BLACK),
|
||||||
|
new Position(3, 0),
|
||||||
|
new Bishop(new Position(3, 0), Side::WHITE)
|
||||||
|
));
|
||||||
|
|
||||||
|
echo $subject->visualize();
|
||||||
|
|
||||||
|
$this->assertEquals(GameState::DEFAULT, $subject->getGameState());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testGameState_fiftyMoveRule_pawnMove() {
|
||||||
|
$subject = new Game(
|
||||||
|
[
|
||||||
|
new King(new Position(2, 7), Side::WHITE, true),
|
||||||
|
new King(new Position(0, 0), Side::BLACK, true),
|
||||||
|
new Pawn(new Position(6, 5), Side::BLACK, true)
|
||||||
|
],
|
||||||
|
Side::BLACK
|
||||||
|
);
|
||||||
|
$subject->_testFiftyMoveRule(49, 49);
|
||||||
|
$this->assertEquals(GameState::DEFAULT, $subject->getGameState());
|
||||||
|
|
||||||
|
$subject->applyInPlace(new Move(
|
||||||
|
new Pawn(new Position(6, 5), Side::BLACK),
|
||||||
|
new Position(6, 4),
|
||||||
|
));
|
||||||
|
|
||||||
|
echo $subject->visualize();
|
||||||
|
|
||||||
|
$this->assertEquals(GameState::DEFAULT, $subject->getGameState());
|
||||||
|
}
|
||||||
|
|
||||||
public function testLegalMoves_pawnPinnedBecauseOfCheckKingRestrictedByQueenAndPawn() {
|
public function testLegalMoves_pawnPinnedBecauseOfCheckKingRestrictedByQueenAndPawn() {
|
||||||
$subject = new Game(
|
$subject = new Game(
|
||||||
[
|
[
|
||||||
|
|
Loading…
Reference in a new issue