From 96b04379a4d501faf631362bbead99c4ffcabb8b Mon Sep 17 00:00:00 2001 From: Eryn Wells Date: Mon, 15 Jan 2024 17:43:27 -0800 Subject: [PATCH] [board] Implement Position::is_king_in_check() Returns true if the king of the current player is in check. --- board/src/position/position.rs | 45 +++++++++++++++++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) diff --git a/board/src/position/position.rs b/board/src/position/position.rs index c9e4fe6..0557c27 100644 --- a/board/src/position/position.rs +++ b/board/src/position/position.rs @@ -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, + + sight: [OnceCell; 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 { 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()); + } }