[board, explorer, moves] Make Board::active_color private

Make the struct attribute private, and export two new methods. A getter, active_color(),
and a setter, set_active_color().

Update all references to the attribute to use the methods.
This commit is contained in:
Eryn Wells 2025-06-02 17:29:52 -07:00
parent cae93cb090
commit eaab34587c
10 changed files with 55 additions and 40 deletions

View file

@ -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<Square>,
@ -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<Piece> {
self.pieces.get(square)

View file

@ -78,13 +78,13 @@ impl Board {
}
pub(crate) fn castling_king(&self, square: Square) -> Option<Piece> {
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<Piece> {
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())
}

View file

@ -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]

View file

@ -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()

View file

@ -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());

View file

@ -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.

View file

@ -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? ");

View file

@ -227,7 +227,7 @@ impl<T: BoardProvider> 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<T: BoardProvider> 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<T: BoardProvider> 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)));

View file

@ -32,7 +32,7 @@ impl MoveRecord {
#[must_use]
pub fn new(board: &Board, ply: Move, capture: Option<Piece>) -> Self {
Self {
color: board.active_color,
color: board.active_color(),
ply,
en_passant_target: board.en_passant_target,
castling_rights: board.castling_rights,

View file

@ -69,7 +69,7 @@ impl<T: BoardProvider> 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(())
}