[board] Implement all the bit twiddling to track whether castling is allowed for each player and side of the board
This commit is contained in:
parent
8cc7e64ba6
commit
31e5771d30
3 changed files with 100 additions and 7 deletions
|
@ -10,10 +10,27 @@ use crate::{
|
|||
use std::fmt;
|
||||
use std::fmt::Write;
|
||||
|
||||
/// A lateral side of the board relative to the player. Kingside is the side the
|
||||
/// player's king starts on. Queenside is the side of the board the player's
|
||||
/// queen starts on.
|
||||
pub(crate) enum BoardSide {
|
||||
King,
|
||||
Queen,
|
||||
}
|
||||
|
||||
#[derive(Clone, Eq, Hash, PartialEq)]
|
||||
pub struct Position {
|
||||
color_to_move: Color,
|
||||
|
||||
/// Position flags indicating various bits of game state. The flags are as
|
||||
/// follows:
|
||||
///
|
||||
/// 0. white can castle king-side
|
||||
/// 1. white can castle queen-side
|
||||
/// 2. black can castle king-side
|
||||
/// 3. black can castle queen-side
|
||||
flags: u8,
|
||||
|
||||
/// Composite bitboards for all the pieces of a particular color.
|
||||
pieces_per_color: [BitBoard; 2],
|
||||
|
||||
|
@ -25,7 +42,8 @@ impl Position {
|
|||
pub fn empty() -> Position {
|
||||
Position {
|
||||
color_to_move: Color::White,
|
||||
pieces_per_color: [BitBoard::empty(), BitBoard::empty()],
|
||||
flags: 0b00001111,
|
||||
pieces_per_color: [BitBoard::empty(); 2],
|
||||
pieces_per_type: [
|
||||
[
|
||||
BitBoard::empty(),
|
||||
|
@ -69,6 +87,7 @@ impl Position {
|
|||
|
||||
Position {
|
||||
color_to_move: Color::White,
|
||||
flags: 0b00001111,
|
||||
pieces_per_color: [
|
||||
white_pieces.iter().fold(BitBoard::empty(), |a, b| a | *b),
|
||||
black_pieces.iter().fold(BitBoard::empty(), |a, b| a | *b),
|
||||
|
@ -77,6 +96,36 @@ impl Position {
|
|||
}
|
||||
}
|
||||
|
||||
/// Returns true if the player has the right to castle on the given side of
|
||||
/// the board.
|
||||
///
|
||||
/// The right to castle on a particular side of the board is retained as
|
||||
/// long as the player has not moved their king, or the rook on that side of
|
||||
/// the board.
|
||||
///
|
||||
/// The following requirements must also be met:
|
||||
///
|
||||
/// 1. The spaces between the king and rook must be clear
|
||||
/// 2. The king must not be in check
|
||||
/// 3. In the course of castling on that side, the king must not pass
|
||||
/// through a square that an enemy piece can see
|
||||
pub(crate) fn player_has_right_to_castle(&self, color: Color, side: BoardSide) -> bool {
|
||||
(self.flags & (1 << Self::player_has_right_to_castle_flag_offset(color, side))) != 0
|
||||
}
|
||||
|
||||
fn set_player_has_right_to_castle_flag(&mut self, color: Color, side: BoardSide) {
|
||||
self.flags |= 1 << Self::player_has_right_to_castle_flag_offset(color, side);
|
||||
}
|
||||
|
||||
fn clear_player_has_right_to_castle_flag(&mut self, color: Color, side: BoardSide) {
|
||||
self.flags &= !(1 << Self::player_has_right_to_castle_flag_offset(color, side));
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn player_has_right_to_castle_flag_offset(color: Color, side: BoardSide) -> u8 {
|
||||
((color as u8) << 1) + side as u8
|
||||
}
|
||||
|
||||
pub fn place_piece(&mut self, piece: Piece, square: Square) -> Result<(), PiecePlacementError> {
|
||||
let type_bb = self.bitboard_for_piece_mut(piece);
|
||||
|
||||
|
@ -200,4 +249,36 @@ mod tests {
|
|||
.place_piece(piece, square)
|
||||
.expect_err("Placed white queen on e4 a second time?!");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn castle_flags() {
|
||||
assert_eq!(
|
||||
Position::player_has_right_to_castle_flag_offset(Color::White, BoardSide::King),
|
||||
0
|
||||
);
|
||||
assert_eq!(
|
||||
Position::player_has_right_to_castle_flag_offset(Color::White, BoardSide::Queen),
|
||||
1
|
||||
);
|
||||
assert_eq!(
|
||||
Position::player_has_right_to_castle_flag_offset(Color::Black, BoardSide::King),
|
||||
2
|
||||
);
|
||||
assert_eq!(
|
||||
Position::player_has_right_to_castle_flag_offset(Color::Black, BoardSide::Queen),
|
||||
3
|
||||
);
|
||||
|
||||
let mut pos = Position::starting();
|
||||
assert!(pos.player_has_right_to_castle(Color::White, BoardSide::King));
|
||||
assert!(pos.player_has_right_to_castle(Color::White, BoardSide::Queen));
|
||||
assert!(pos.player_has_right_to_castle(Color::Black, BoardSide::King));
|
||||
assert!(pos.player_has_right_to_castle(Color::Black, BoardSide::Queen));
|
||||
|
||||
pos.clear_player_has_right_to_castle_flag(Color::White, BoardSide::Queen);
|
||||
assert!(pos.player_has_right_to_castle(Color::White, BoardSide::King));
|
||||
assert!(!pos.player_has_right_to_castle(Color::White, BoardSide::Queen));
|
||||
assert!(pos.player_has_right_to_castle(Color::Black, BoardSide::King));
|
||||
assert!(pos.player_has_right_to_castle(Color::Black, BoardSide::Queen));
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue