diff --git a/board/src/board.rs b/board/src/board.rs index 63c0ad5..7433f08 100644 --- a/board/src/board.rs +++ b/board/src/board.rs @@ -14,7 +14,7 @@ pub type FullMoveClock = u32; #[derive(Clone, Debug, Default, Eq, PartialEq)] pub struct Board { - pub active_color: Color, + active_color: Color, pieces: PieceSet, pub castling_rights: castle::Rights, pub en_passant_target: Option, @@ -58,6 +58,19 @@ impl Board { } impl Board { + #[must_use] + pub fn active_color(&self) -> Color { + self.active_color + } + + pub fn set_active_color(&mut self, color: Color) { + if color == self.active_color { + return; + } + + self.active_color = color; + } + #[must_use] pub fn get_piece(&self, square: Square) -> Option { self.pieces.get(square) diff --git a/board/src/castle.rs b/board/src/castle.rs index ef3a901..02228d1 100644 --- a/board/src/castle.rs +++ b/board/src/castle.rs @@ -78,13 +78,13 @@ impl Board { } pub(crate) fn castling_king(&self, square: Square) -> Option { - let active_color = self.active_color; + let active_color = self.active_color(); self.get_piece(square) .filter(|piece| piece.color == active_color && piece.is_king()) } pub(crate) fn castling_rook(&self, square: Square) -> Option { - let active_color = self.active_color; + let active_color = self.active_color(); self.get_piece(square) .filter(|piece| piece.color == active_color && piece.is_rook()) } diff --git a/board/src/check.rs b/board/src/check.rs index 6873cf4..ba9f06d 100644 --- a/board/src/check.rs +++ b/board/src/check.rs @@ -7,7 +7,7 @@ use chessfriend_core::{Color, Piece}; impl Board { #[must_use] pub fn active_color_is_in_check(&self) -> bool { - self.unwrapped_color_is_in_check(self.active_color) + self.unwrapped_color_is_in_check(self.active_color()) } #[must_use] diff --git a/board/src/fen.rs b/board/src/fen.rs index 42d5656..9a70391 100644 --- a/board/src/fen.rs +++ b/board/src/fen.rs @@ -113,7 +113,7 @@ impl ToFenStr for Board { } } - write!(fen_string, " {}", self.active_color.to_fen_str()?) + write!(fen_string, " {}", self.active_color().to_fen_str()?) .map_err(ToFenStrError::FmtError)?; let castling = [ @@ -224,7 +224,7 @@ impl FromFenStr for Board { .next() .ok_or(FromFenStrError::MissingField(Field::PlayerToMove))?, )?; - board.active_color = active_color; + board.set_active_color(active_color); let castling_rights = fields .next() diff --git a/board/src/macros.rs b/board/src/macros.rs index da1984b..e6a5c3a 100644 --- a/board/src/macros.rs +++ b/board/src/macros.rs @@ -13,7 +13,7 @@ macro_rules! test_board { chessfriend_core::Square::$square, $crate::PlacePieceStrategy::default()); )* - board.active_color = chessfriend_core::Color::$to_move; + board.set_active_color(chessfriend_core::Color::$to_move); board.en_passant_target = Some(chessfriend_core::Square::$en_passant); println!("{}", board.display()); diff --git a/board/src/sight.rs b/board/src/sight.rs index 8518300..bb6f8e1 100644 --- a/board/src/sight.rs +++ b/board/src/sight.rs @@ -32,7 +32,7 @@ impl Board { } pub fn active_sight(&self) -> BitBoard { - self.friendly_sight(self.active_color) + self.friendly_sight(self.active_color()) } /// A [`BitBoard`] of all squares the given color can see. @@ -45,7 +45,7 @@ impl Board { } pub fn active_color_opposing_sight(&self) -> BitBoard { - self.opposing_sight(self.active_color) + self.opposing_sight(self.active_color()) } /// A [`BitBoard`] of all squares visible by colors that oppose the given color. diff --git a/explorer/src/main.rs b/explorer/src/main.rs index 4a86a00..6fc13cf 100644 --- a/explorer/src/main.rs +++ b/explorer/src/main.rs @@ -283,7 +283,7 @@ fn main() -> Result<(), String> { loop { if should_print_position { println!("{}", &state.position); - println!("{} to move.", state.position.board.active_color); + println!("{} to move.", state.position.board.active_color()); } let readline = editor.readline("\n? "); diff --git a/moves/src/make_move.rs b/moves/src/make_move.rs index ed79fa4..d92cb43 100644 --- a/moves/src/make_move.rs +++ b/moves/src/make_move.rs @@ -227,7 +227,7 @@ impl MakeMoveInternal for T { board.color_can_castle(wing, None)?; - let active_color = board.active_color; + let active_color = board.active_color(); let parameters = Board::castling_parameters(wing, active_color); let king = board.remove_piece(parameters.origin.king).unwrap(); @@ -289,9 +289,11 @@ impl MakeMoveInternal for T { HalfMoveClock::Advance => board.half_move_clock += 1, } - board.active_color = board.active_color.next(); + let previous_active_color = board.active_color(); + let active_color = previous_active_color.next(); + board.set_active_color(active_color); - if board.active_color == Color::White { + if active_color == Color::White { board.full_move_number += 1; } } @@ -343,7 +345,7 @@ impl MakeMoveInternal for T { .get_piece(origin_square) .ok_or(MakeMoveError::NoPiece(origin_square))?; - if active_piece.color != board.active_color { + if active_piece.color != board.active_color() { return Err(MakeMoveError::NonActiveColor { piece: active_piece, square: origin_square, @@ -379,17 +381,17 @@ mod tests { assert_eq!(board.get_piece(Square::C2), None); assert_eq!(board.get_piece(Square::C3), Some(piece!(White Pawn))); - assert_eq!(board.active_color, Color::Black); + assert_eq!(board.active_color(), Color::Black); assert_eq!(board.half_move_clock, 1); - board.active_color = Color::White; + board.set_active_color(Color::White); let ply = Move::quiet(Square::C3, Square::C4); board.make_move(ply, ValidateMove::Yes)?; assert_eq!(board.get_piece(Square::C3), None); assert_eq!(board.get_piece(Square::C4), Some(piece!(White Pawn))); - assert_eq!(board.active_color, Color::Black); + assert_eq!(board.active_color(), Color::Black); assert_eq!(board.half_move_clock, 2); Ok(()) @@ -405,7 +407,7 @@ mod tests { assert!(result.is_err()); assert_eq!(board.get_piece(Square::C2), Some(piece!(White Pawn))); assert_eq!(board.get_piece(Square::D2), None); - assert_eq!(board.active_color, Color::White); + assert_eq!(board.active_color(), Color::White); assert_eq!(board.half_move_clock, 0); } @@ -423,7 +425,7 @@ mod tests { assert_eq!(board.get_piece(Square::C2), None); assert_eq!(board.get_piece(Square::F5), Some(piece!(White Bishop))); - assert_eq!(board.active_color, Color::Black); + assert_eq!(board.active_color(), Color::Black); assert_eq!(board.half_move_clock, 0); Ok(()) @@ -448,7 +450,7 @@ mod tests { Some(Square::E3), "en passant square not set" ); - assert_eq!(board.active_color, Color::Black); + assert_eq!(board.active_color(), Color::Black); assert_eq!(board.half_move_clock, 1); let ply = Move::en_passant_capture(Square::F4, Square::E3); @@ -477,7 +479,7 @@ mod tests { let result = board.make_move(ply, ValidateMove::Yes); assert!(result.is_err()); - assert_eq!(board.active_color, Color::White); + assert_eq!(board.active_color(), Color::White); assert_eq!(board.get_piece(Square::A7), Some(piece!(White Pawn))); assert_eq!(board.get_piece(Square::A8), None); assert_eq!(board.half_move_clock, 0); @@ -495,7 +497,7 @@ mod tests { assert_eq!(board.get_piece(Square::F7), None); assert_eq!(board.get_piece(Square::F8), Some(piece!(White Queen))); - assert_eq!(board.active_color, Color::Black); + assert_eq!(board.active_color(), Color::Black); assert_eq!(board.half_move_clock, 0); Ok(()) @@ -511,7 +513,7 @@ mod tests { let ply = Move::castle(Wing::KingSide); board.make_move(ply, ValidateMove::Yes)?; - assert_eq!(board.active_color, Color::Black); + assert_eq!(board.active_color(), Color::Black); assert_eq!(board.get_piece(Square::E1), None); assert_eq!(board.get_piece(Square::H1), None); assert_eq!(board.get_piece(Square::G1), Some(piece!(White King))); @@ -533,7 +535,7 @@ mod tests { let ply = Move::castle(Wing::QueenSide); board.make_move(ply, ValidateMove::Yes)?; - assert_eq!(board.active_color, Color::Black); + assert_eq!(board.active_color(), Color::Black); assert_eq!(board.get_piece(Square::E1), None); assert_eq!(board.get_piece(Square::A1), None); assert_eq!(board.get_piece(Square::C1), Some(piece!(White King))); diff --git a/moves/src/record.rs b/moves/src/record.rs index 3c91867..139f2d4 100644 --- a/moves/src/record.rs +++ b/moves/src/record.rs @@ -32,7 +32,7 @@ impl MoveRecord { #[must_use] pub fn new(board: &Board, ply: Move, capture: Option) -> Self { Self { - color: board.active_color, + color: board.active_color(), ply, en_passant_target: board.en_passant_target, castling_rights: board.castling_rights, diff --git a/moves/src/unmake_move.rs b/moves/src/unmake_move.rs index 368ba6d..b3df2ca 100644 --- a/moves/src/unmake_move.rs +++ b/moves/src/unmake_move.rs @@ -69,7 +69,7 @@ impl UnmakeMove for T { } let board = self.board_mut(); - board.active_color = record.color; + board.set_active_color(record.color); board.en_passant_target = record.en_passant_target; board.castling_rights = record.castling_rights; board.half_move_clock = record.half_move_clock; @@ -238,14 +238,14 @@ mod tests { // Verify move was made assert_eq!(board.get_piece(Square::C2), None); assert_eq!(board.get_piece(Square::C3), Some(piece!(White Pawn))); - assert_eq!(board.active_color, Color::Black); + assert_eq!(board.active_color(), Color::Black); board.unmake_move(&record)?; // Verify original state restored assert_eq!(board.get_piece(Square::C2), Some(piece!(White Pawn))); assert_eq!(board.get_piece(Square::C3), None); - assert_eq!(board.active_color, Color::White); + assert_eq!(board.active_color(), Color::White); Ok(()) } @@ -261,7 +261,7 @@ mod tests { assert_eq!(board.get_piece(Square::E2), None); assert_eq!(board.get_piece(Square::E4), Some(piece!(White Pawn))); assert_eq!(board.en_passant_target, Some(Square::E3)); - assert_eq!(board.active_color, Color::Black); + assert_eq!(board.active_color(), Color::Black); board.unmake_move(&record)?; @@ -269,7 +269,7 @@ mod tests { assert_eq!(board.get_piece(Square::E2), Some(piece!(White Pawn))); assert_eq!(board.get_piece(Square::E4), None); assert_eq!(board.en_passant_target, None); - assert_eq!(board.active_color, Color::White); + assert_eq!(board.active_color(), Color::White); Ok(()) } @@ -288,14 +288,14 @@ mod tests { assert_eq!(board.get_piece(Square::C2), None); assert_eq!(board.get_piece(Square::F5), Some(piece!(White Bishop))); assert_eq!(record.captured_piece, Some(piece!(Black Rook))); - assert_eq!(board.active_color, Color::Black); + assert_eq!(board.active_color(), Color::Black); board.unmake_move(&record)?; // Verify original state restored assert_eq!(board.get_piece(Square::C2), Some(piece!(White Bishop))); assert_eq!(board.get_piece(Square::F5), Some(piece!(Black Rook))); - assert_eq!(board.active_color, Color::White); + assert_eq!(board.active_color(), Color::White); Ok(()) } @@ -335,7 +335,7 @@ mod tests { Some(piece!(White Pawn)), "captured pawn was not restored" ); - assert_eq!(board.active_color, Color::Black); + assert_eq!(board.active_color(), Color::Black); Ok(()) } @@ -352,14 +352,14 @@ mod tests { // Verify promotion was made assert_eq!(board.get_piece(Square::F7), None); assert_eq!(board.get_piece(Square::F8), Some(piece!(White Queen))); - assert_eq!(board.active_color, Color::Black); + assert_eq!(board.active_color(), Color::Black); board.unmake_move(&record)?; // Verify original pawn is restored assert_eq!(board.get_piece(Square::F7), Some(piece!(White Pawn))); assert_eq!(board.get_piece(Square::F8), None); - assert_eq!(board.active_color, Color::White); + assert_eq!(board.active_color(), Color::White); Ok(()) } @@ -384,7 +384,7 @@ mod tests { // Verify original state restored assert_eq!(board.get_piece(Square::F7), Some(piece!(White Pawn))); assert_eq!(board.get_piece(Square::G8), Some(piece!(Black Rook))); - assert_eq!(board.active_color, Color::White); + assert_eq!(board.active_color(), Color::White); Ok(()) } @@ -418,7 +418,7 @@ mod tests { assert_eq!(board.get_piece(Square::G1), None); assert_eq!(board.get_piece(Square::F1), None); assert_eq!(board.castling_rights, original_castling_rights); - assert_eq!(board.active_color, Color::White); + assert_eq!(board.active_color(), Color::White); Ok(()) } @@ -452,7 +452,7 @@ mod tests { assert_eq!(board.get_piece(Square::C1), None); assert_eq!(board.get_piece(Square::D1), None); assert_eq!(board.castling_rights, original_castling_rights); - assert_eq!(board.active_color, Color::White); + assert_eq!(board.active_color(), Color::White); Ok(()) } @@ -463,7 +463,7 @@ mod tests { Black King on E8, Black Rook on H8, ]; - board.active_color = Color::Black; + board.set_active_color(Color::Black); let original_castling_rights = board.castling_rights; @@ -484,7 +484,7 @@ mod tests { assert_eq!(board.get_piece(Square::G8), None); assert_eq!(board.get_piece(Square::F8), None); assert_eq!(board.castling_rights, original_castling_rights); - assert_eq!(board.active_color, Color::Black); + assert_eq!(board.active_color(), Color::Black); Ok(()) }