fix: King can not castle out of check

This commit is contained in:
overflowerror 2024-01-07 12:39:42 +01:00
parent ebda02a121
commit 5c1bab71df
2 changed files with 63 additions and 6 deletions

View file

@ -45,6 +45,9 @@ class King extends Piece {
if ($this->hasMoved || $rook->hasMoved) { if ($this->hasMoved || $rook->hasMoved) {
return false; return false;
} }
if ($threatened->has($this->position)) {
return false;
}
$increment = $rook->position->file <=> $this->position->file; $increment = $rook->position->file <=> $this->position->file;
for ($file = $this->position->file + $increment; $file != $rook->position->file; $file += $increment) { for ($file = $this->position->file + $increment; $file != $rook->position->file; $file += $increment) {

View file

@ -121,6 +121,7 @@ final class KingTest extends TestCase {
FieldBitMap::full()->intersect((new FieldBitMap([ FieldBitMap::full()->intersect((new FieldBitMap([
new Position(2, 0), new Position(2, 0),
new Position(3, 0), new Position(3, 0),
new Position(4, 0),
]))->invert()); ]))->invert());
$this->assertTrue($king->canCastle( $this->assertTrue($king->canCastle(
@ -142,16 +143,23 @@ final class KingTest extends TestCase {
Side::WHITE, Side::WHITE,
); );
$maximumMap =
$maximumOccupiedMap =
FieldBitMap::full()->intersect((new FieldBitMap([ FieldBitMap::full()->intersect((new FieldBitMap([
new Position(6, 0),
new Position(5, 0), new Position(5, 0),
new Position(6, 0),
]))->invert());
$maximumThreatenedMap =
FieldBitMap::full()->intersect((new FieldBitMap([
new Position(4, 0),
new Position(5, 0),
new Position(6, 0),
]))->invert()); ]))->invert());
$this->assertTrue($king->canCastle( $this->assertTrue($king->canCastle(
$maximumMap, $maximumOccupiedMap,
$maximumMap, $maximumOccupiedMap,
$maximumMap, $maximumThreatenedMap,
$rook, $rook,
)); ));
} }
@ -182,6 +190,7 @@ final class KingTest extends TestCase {
FieldBitMap::full()->intersect((new FieldBitMap([ FieldBitMap::full()->intersect((new FieldBitMap([
new Position(2, 0), new Position(2, 0),
new Position(3, 0), new Position(3, 0),
new Position(4, 0),
]))->invert()); ]))->invert());
$this->assertFalse($king->canCastle( $this->assertFalse($king->canCastle(
@ -217,6 +226,7 @@ final class KingTest extends TestCase {
FieldBitMap::full()->intersect((new FieldBitMap([ FieldBitMap::full()->intersect((new FieldBitMap([
new Position(2, 0), new Position(2, 0),
new Position(3, 0), new Position(3, 0),
new Position(4, 0),
]))->invert()); ]))->invert());
$this->assertFalse($king->canCastle( $this->assertFalse($king->canCastle(
@ -253,6 +263,7 @@ final class KingTest extends TestCase {
FieldBitMap::full()->intersect((new FieldBitMap([ FieldBitMap::full()->intersect((new FieldBitMap([
new Position(2, 0), new Position(2, 0),
new Position(3, 0), new Position(3, 0),
new Position(4, 0),
]))->invert()); ]))->invert());
$this->assertFalse($king->canCastle( $this->assertFalse($king->canCastle(
@ -289,6 +300,7 @@ final class KingTest extends TestCase {
FieldBitMap::full()->intersect((new FieldBitMap([ FieldBitMap::full()->intersect((new FieldBitMap([
new Position(2, 0), new Position(2, 0),
new Position(3, 0), new Position(3, 0),
new Position(4, 0),
]))->invert()); ]))->invert());
$this->assertFalse($king->canCastle( $this->assertFalse($king->canCastle(
@ -325,6 +337,7 @@ final class KingTest extends TestCase {
FieldBitMap::full()->intersect((new FieldBitMap([ FieldBitMap::full()->intersect((new FieldBitMap([
new Position(2, 0), new Position(2, 0),
new Position(3, 0), new Position(3, 0),
new Position(4, 0),
]))->invert()); ]))->invert());
$this->assertFalse($king->canCastle( $this->assertFalse($king->canCastle(
@ -361,6 +374,7 @@ final class KingTest extends TestCase {
FieldBitMap::full()->intersect((new FieldBitMap([ FieldBitMap::full()->intersect((new FieldBitMap([
new Position(2, 0), new Position(2, 0),
new Position(3, 0), new Position(3, 0),
new Position(4, 0),
]))->invert()); ]))->invert());
$this->assertFalse($king->canCastle( $this->assertFalse($king->canCastle(
@ -397,6 +411,7 @@ final class KingTest extends TestCase {
$maximumThreatenedMap = $maximumThreatenedMap =
FieldBitMap::full()->intersect((new FieldBitMap([ FieldBitMap::full()->intersect((new FieldBitMap([
new Position(3, 0), new Position(3, 0),
new Position(4, 0),
]))->invert()); ]))->invert());
$this->assertFalse($king->canCastle( $this->assertFalse($king->canCastle(
@ -433,6 +448,7 @@ final class KingTest extends TestCase {
$maximumThreatenedMap = $maximumThreatenedMap =
FieldBitMap::full()->intersect((new FieldBitMap([ FieldBitMap::full()->intersect((new FieldBitMap([
new Position(2, 0), new Position(2, 0),
new Position(4, 0),
]))->invert()); ]))->invert());
$this->assertFalse($king->canCastle( $this->assertFalse($king->canCastle(
@ -471,6 +487,7 @@ final class KingTest extends TestCase {
FieldBitMap::full()->intersect((new FieldBitMap([ FieldBitMap::full()->intersect((new FieldBitMap([
new Position(2, 0), new Position(2, 0),
new Position(3, 0), new Position(3, 0),
new Position(4, 0),
]))->invert()); ]))->invert());
$this->assertFalse($king->canCastle( $this->assertFalse($king->canCastle(
@ -486,7 +503,6 @@ final class KingTest extends TestCase {
new Position(4, 0), new Position(4, 0),
Side::WHITE, Side::WHITE,
); );
$king->move(new Position(4, 0));
$rook = new Rook( $rook = new Rook(
new Position(0, 0), new Position(0, 0),
@ -494,6 +510,44 @@ final class KingTest extends TestCase {
true, true,
); );
$maximumOccupiedMap =
FieldBitMap::full()->intersect((new FieldBitMap([
new Position(1, 0),
new Position(2, 0),
new Position(3, 0),
]))->invert());
$maximumCaptureableMap =
FieldBitMap::full()->intersect((new FieldBitMap([
new Position(1, 0),
new Position(2, 0),
new Position(3, 0),
]))->invert());
$maximumThreatenedMap =
FieldBitMap::full()->intersect((new FieldBitMap([
new Position(2, 0),
new Position(3, 0),
new Position(4, 0),
]))->invert());
$this->assertFalse($king->canCastle(
$maximumOccupiedMap,
$maximumCaptureableMap,
$maximumThreatenedMap,
$rook,
));
}
public function testCanCastle_long_kingInCheck() {
$king = new King(
new Position(4, 0),
Side::WHITE,
);
$rook = new Rook(
new Position(0, 0),
Side::WHITE,
);
$maximumOccupiedMap = $maximumOccupiedMap =
FieldBitMap::full()->intersect((new FieldBitMap([ FieldBitMap::full()->intersect((new FieldBitMap([
new Position(1, 0), new Position(1, 0),