[board] Implement Position::is_king_in_check()

Returns true if the king of the current player is in check.
This commit is contained in:
Eryn Wells 2024-01-15 17:43:27 -08:00
parent 81d544f0d5
commit 96b04379a4

View file

@ -4,8 +4,10 @@ use super::{flags::Flags, Pieces};
use crate::{
moves::Moves,
piece::{Color, Piece, PiecePlacementError, PlacedPiece, Shape},
sight::Sight,
BitBoard, Square,
};
use std::cell::OnceCell;
use std::fmt;
use std::fmt::Write;
@ -26,7 +28,7 @@ macro_rules! position {
};
}
#[derive(Clone, Eq, Hash, PartialEq)]
#[derive(Clone, Eq, PartialEq)]
pub struct Position {
color_to_move: Color,
@ -46,6 +48,8 @@ pub struct Position {
pieces_per_type: [[BitBoard; 6]; 2],
en_passant_square: Option<Square>,
sight: [OnceCell<BitBoard>; 2],
}
impl Position {
@ -73,6 +77,7 @@ impl Position {
],
],
en_passant_square: None,
sight: [OnceCell::new(), OnceCell::new()],
}
}
@ -105,6 +110,7 @@ impl Position {
],
pieces_per_type: [white_pieces, black_pieces],
en_passant_square: None,
sight: [OnceCell::new(), OnceCell::new()],
}
}
@ -213,6 +219,25 @@ impl Position {
pub fn en_passant_square(&self) -> Option<Square> {
self.en_passant_square
}
pub(crate) fn sight_of_player(&self, color: Color) -> BitBoard {
*self.sight[color as usize].get_or_init(|| {
self.pieces(color).fold(BitBoard::empty(), |acc, pp| {
acc | pp.sight_in_position(&self)
})
})
}
pub(crate) fn is_king_in_check(&self) -> bool {
let sight_of_opposing_player = self.sight_of_player(self.color_to_move.other());
let king_square = self
.bitboard_for_piece(Piece::king(self.color_to_move))
.occupied_squares()
.next()
.unwrap();
sight_of_opposing_player.is_set(king_square)
}
}
}
impl Default for Position {
@ -288,4 +313,22 @@ mod tests {
.place_piece(piece, square)
.expect_err("Placed white queen on e4 a second time?!");
}
#[test]
fn king_is_in_check() {
let pos = position![
White King on E1,
Black Rook on E8,
];
assert!(pos.is_king_in_check());
}
#[test]
fn king_is_not_in_check() {
let pos = position![
White King on F1,
Black Rook on E8,
];
assert!(!pos.is_king_in_check());
}
}