Skip to content

Commit

Permalink
Fixed unsoundness in Board parsing, fixed capturable king detection
Browse files Browse the repository at this point in the history
  • Loading branch information
miestrode committed Dec 23, 2023
1 parent 8bcd7e1 commit 3aadccd
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 7 deletions.
26 changes: 22 additions & 4 deletions hash-core/src/board.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ impl Board {
Self::from_str("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1").unwrap()
}

pub fn is_attacked(&self, square: Square) -> bool {
pub fn is_attacked_by_them(&self, square: Square) -> bool {
let mut attackers = BitBoard::EMPTY;
let occupation = self.occupation() & !self.us.king;

Expand All @@ -53,6 +53,25 @@ impl Board {
!attackers.is_empty()
}

pub fn is_attacked_by_us(&self, square: Square) -> bool {
let mut attackers = BitBoard::EMPTY;
let occupation = self.occupation() & !self.them.king;

attackers |= index::rook_slides(square, occupation) & (self.us.rooks | self.us.queens);
attackers |= index::bishop_slides(square, occupation) & (self.us.bishops | self.us.queens);

attackers |= index::knight_attacks(square) & self.us.knights;
attackers |= index::king_attacks(square) & self.us.king;

let square: BitBoard = square.into();

attackers |= (square.move_one_up_left(!self.playing_color)
| square.move_one_up_right(!self.playing_color))
& self.us.pawns;

!attackers.is_empty()
}

pub fn in_check(&self) -> bool {
!self.checkers.is_empty()
}
Expand Down Expand Up @@ -97,8 +116,7 @@ impl Board {
}

pub fn update_move_restrictions(&mut self) {
// SAFETY: The board is assumed to be validly constructed
let king_square = unsafe { Square::try_from(self.us.king).unwrap_unchecked() };
let king_square = Square::try_from(self.us.king).unwrap();

self.checkers ^= index::knight_attacks(king_square) & self.them.knights;
self.checkers ^= index::pawn_attacks(king_square, self.playing_color) & self.them.pawns;
Expand Down Expand Up @@ -451,7 +469,7 @@ impl FromStr for Board {
Err(ParseBoardError::PawnsOnEdgeRanks)
} else if is_impossible_en_passant_square {
Err(ParseBoardError::InvalidEnPassantSquare(None))
} else if board.is_attacked(Square::try_from(board.them.king).unwrap()) {
} else if board.is_attacked_by_us(Square::try_from(board.them.king).unwrap()) {
Err(ParseBoardError::CapturableKing)
} else {
Ok(board)
Expand Down
6 changes: 3 additions & 3 deletions hash-core/src/mg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -385,7 +385,7 @@ impl Gen for King {
board.playing_color,
)
.bits()
.filter(|square| !board.is_attacked(*square))
.filter(|square| !board.is_attacked_by_them(*square))
.map(|target| ChessMove {
origin: king_square,
target,
Expand All @@ -401,7 +401,7 @@ impl Gen for King {
&& (king_side_castle_mask & board.occupation()).is_empty()
&& (king_side_castle_mask
.bits()
.all(|square| !board.is_attacked(square)))
.all(|square| !board.is_attacked_by_them(square)))
{
moves.push(ChessMove {
origin: king_square,
Expand All @@ -419,7 +419,7 @@ impl Gen for King {
.is_empty()
&& (BitBoard::queen_side_castle_attack_mask(board.playing_color)
.bits()
.all(|square| !board.is_attacked(square)))
.all(|square| !board.is_attacked_by_them(square)))
{
moves.push(ChessMove {
origin: king_square,
Expand Down

0 comments on commit 3aadccd

Please sign in to comment.