diff --git a/board/src/position/flags.rs b/board/src/position/flags.rs new file mode 100644 index 0000000..2aa389d --- /dev/null +++ b/board/src/position/flags.rs @@ -0,0 +1,73 @@ +// Eryn Wells + +use super::position::BoardSide; +use crate::piece::Color; + +#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] +pub(super) struct Flags(u8); + +impl Flags { + #[inline] + pub(super) fn player_has_right_to_castle_flag_offset(color: Color, side: BoardSide) -> u8 { + ((color as u8) << 1) + side as u8 + } + + pub(super) fn player_has_right_to_castle(&self, color: Color, side: BoardSide) -> bool { + (self.0 & (1 << Self::player_has_right_to_castle_flag_offset(color, side))) != 0 + } + + pub(super) fn set_player_has_right_to_castle_flag(&mut self, color: Color, side: BoardSide) { + self.0 |= 1 << Self::player_has_right_to_castle_flag_offset(color, side); + } + + pub(super) fn clear_player_has_right_to_castle_flag(&mut self, color: Color, side: BoardSide) { + self.0 &= !(1 << Self::player_has_right_to_castle_flag_offset(color, side)); + } +} + +impl Default for Flags { + fn default() -> Self { + Flags(0b00001111) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::Color; + + #[test] + fn castle_flags() { + assert_eq!( + Flags::player_has_right_to_castle_flag_offset(Color::White, BoardSide::King), + 0 + ); + assert_eq!( + Flags::player_has_right_to_castle_flag_offset(Color::White, BoardSide::Queen), + 1 + ); + assert_eq!( + Flags::player_has_right_to_castle_flag_offset(Color::Black, BoardSide::King), + 2 + ); + assert_eq!( + Flags::player_has_right_to_castle_flag_offset(Color::Black, BoardSide::Queen), + 3 + ); + } + + #[test] + fn defaults() { + let mut flags: Flags = Default::default(); + assert!(flags.player_has_right_to_castle(Color::White, BoardSide::King)); + assert!(flags.player_has_right_to_castle(Color::White, BoardSide::Queen)); + assert!(flags.player_has_right_to_castle(Color::Black, BoardSide::King)); + assert!(flags.player_has_right_to_castle(Color::Black, BoardSide::Queen)); + + flags.clear_player_has_right_to_castle_flag(Color::White, BoardSide::Queen); + assert!(flags.player_has_right_to_castle(Color::White, BoardSide::King)); + assert!(!flags.player_has_right_to_castle(Color::White, BoardSide::Queen)); + assert!(flags.player_has_right_to_castle(Color::Black, BoardSide::King)); + assert!(flags.player_has_right_to_castle(Color::Black, BoardSide::Queen)); + } +} diff --git a/board/src/position/mod.rs b/board/src/position/mod.rs index 1b9998f..650959d 100644 --- a/board/src/position/mod.rs +++ b/board/src/position/mod.rs @@ -1,6 +1,7 @@ // Eryn Wells mod diagram_formatter; +mod flags; mod pieces; mod position; diff --git a/board/src/position/position.rs b/board/src/position/position.rs index 7c8d75c..3ff2db6 100644 --- a/board/src/position/position.rs +++ b/board/src/position/position.rs @@ -1,6 +1,6 @@ // Eryn Wells -use super::Pieces; +use super::{flags::Flags, Pieces}; use crate::{ bitboard::BitBoard, moves::Moves, @@ -38,7 +38,7 @@ pub struct Position { /// 1. white can castle queen-side /// 2. black can castle king-side /// 3. black can castle queen-side - flags: u8, + flags: Flags, /// Composite bitboards for all the pieces of a particular color. pieces_per_color: [BitBoard; 2], @@ -51,7 +51,7 @@ impl Position { pub fn empty() -> Position { Position { color_to_move: Color::White, - flags: 0b00001111, + flags: Default::default(), pieces_per_color: [BitBoard::empty(); 2], pieces_per_type: [ [ @@ -96,7 +96,7 @@ impl Position { Position { color_to_move: Color::White, - flags: 0b00001111, + flags: Default::default(), pieces_per_color: [ white_pieces.iter().fold(BitBoard::empty(), |a, b| a | *b), black_pieces.iter().fold(BitBoard::empty(), |a, b| a | *b), @@ -119,20 +119,16 @@ impl Position { /// 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 + self.flags.player_has_right_to_castle(color, side) } 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); + self.flags.set_player_has_right_to_castle_flag(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 + self.flags + .clear_player_has_right_to_castle_flag(color, side); } pub fn place_piece(&mut self, piece: Piece, square: Square) -> Result<(), PiecePlacementError> { @@ -277,34 +273,6 @@ mod tests { } #[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)); } }