[board, explorer, moves] Clean up the castling rights API

Reorganize castling rights API on Board into methods named according to
conventions applied to other API.

Board::has_castling_right
Board::has_castling_right_active
Board::has_castling_right_unwrapped

    These all check if a color has the right to castle on a particular side
    (wing) of the board. The first takes an Option<Color>, the latter two
    operate on bare Colors: the active color, or an explicit Color.

Board::grant_castling_right
Board::grant_castling_right_active
Board::grant_castling_right_unwrapped

    Grant castling rights to a color. Color arguments follow the pattern above.

Board::revoke_castling_right
Board::revoke_castling_right_active
Board::revoke_castling_right_unwrapped

    Revoke castling rights from a color. Color arguments follow the pattern
    above.

The latter two groups of methods take a new CastleRightsOption type that
specifies either a single Wing or All.

Rework the implementation of CastleRights to take a CastleRightsOption. Update
the unit tests and make sure everything builds.
This commit is contained in:
Eryn Wells 2025-06-18 23:44:40 +00:00
parent 933924d37a
commit 4ce7e89cdb
8 changed files with 177 additions and 124 deletions

View file

@ -3,7 +3,8 @@
use crate::{Move, MoveRecord};
use chessfriend_board::{
Board, BoardProvider, CastleParameters, PlacePieceError, PlacePieceStrategy,
castle::CastleEvaluationError, movement::Movement,
castle::{CastleEvaluationError, CastleRightsOption},
movement::Movement,
};
use chessfriend_core::{Color, Piece, Rank, Shape, Square, Wing};
use thiserror::Error;
@ -251,7 +252,7 @@ impl<T: BoardProvider> MakeMoveInternal for T {
// original board state is preserved.
let record = MoveRecord::new(board, ply, None);
board.revoke_castling_right_unwrapped(active_color, wing);
board.revoke_castling_rights_active(wing.into());
self.advance_board_state(&ply, &king, None, HalfMoveClock::Advance);
@ -307,23 +308,22 @@ impl<T: BoardProvider> MakeMoveInternal for T {
Shape::Rook => {
let origin = ply.origin_square();
if board.color_has_castling_right(None, Wing::KingSide) {
if board.has_castling_right(None, Wing::KingSide) {
let kingside_parameters =
CastleParameters::get(board.active_color(), Wing::KingSide);
if origin == kingside_parameters.origin.rook {
board.revoke_castling_right(None, Wing::KingSide);
board.revoke_castling_rights(None, Wing::KingSide.into());
}
}
let queenside_parameters =
CastleParameters::get(board.active_color(), Wing::QueenSide);
if origin == queenside_parameters.origin.rook {
board.revoke_castling_right(None, Wing::QueenSide);
board.revoke_castling_rights(None, Wing::QueenSide.into());
}
}
Shape::King => {
board.revoke_castling_right(None, Wing::KingSide);
board.revoke_castling_right(None, Wing::QueenSide);
board.revoke_castling_rights(None, CastleRightsOption::All);
}
_ => {}
}
@ -562,7 +562,7 @@ mod tests {
assert_eq!(board.get_piece(Square::H1), None);
assert_eq!(board.get_piece(Square::G1), Some(piece!(White King)));
assert_eq!(board.get_piece(Square::F1), Some(piece!(White Rook)));
assert!(!board.color_has_castling_right_unwrapped(Color::White, Wing::KingSide));
assert!(!board.has_castling_right_unwrapped(Color::White, Wing::KingSide));
Ok(())
}
@ -582,7 +582,7 @@ mod tests {
assert_eq!(board.get_piece(Square::A1), None);
assert_eq!(board.get_piece(Square::C1), Some(piece!(White King)));
assert_eq!(board.get_piece(Square::D1), Some(piece!(White Rook)));
assert!(!board.color_has_castling_right_unwrapped(Color::White, Wing::QueenSide));
assert!(!board.has_castling_right_unwrapped(Color::White, Wing::QueenSide));
Ok(())
}

View file

@ -1,7 +1,7 @@
// Eryn Wells <eryn@erynwells.me>
use crate::Move;
use chessfriend_board::{board::HalfMoveClock, Board, CastleRights};
use chessfriend_board::{Board, CastleRights, board::HalfMoveClock};
use chessfriend_core::{Color, Piece, Square};
/// A record of a move made on a board. This struct contains all the information
@ -35,7 +35,7 @@ impl MoveRecord {
color: board.active_color(),
ply,
en_passant_target: board.en_passant_target(),
castling_rights: board.castling_rights(),
castling_rights: *board.castling_rights(),
half_move_clock: board.half_move_clock,
captured_piece: capture,
}

View file

@ -396,7 +396,7 @@ mod tests {
White Rook on H1,
];
let original_castling_rights = board.castling_rights();
let original_castling_rights = *board.castling_rights();
let ply = Move::castle(Color::White, Wing::KingSide);
let record = board.make_move(ply, ValidateMove::Yes)?;
@ -406,7 +406,7 @@ mod tests {
assert_eq!(board.get_piece(Square::H1), None);
assert_eq!(board.get_piece(Square::G1), Some(piece!(White King)));
assert_eq!(board.get_piece(Square::F1), Some(piece!(White Rook)));
assert!(!board.color_has_castling_right_unwrapped(Color::White, Wing::KingSide));
assert!(!board.has_castling_right_unwrapped(Color::White, Wing::KingSide));
board.unmake_move(&record)?;
@ -415,7 +415,7 @@ mod tests {
assert_eq!(board.get_piece(Square::H1), Some(piece!(White Rook)));
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.castling_rights(), original_castling_rights);
assert_eq!(board.active_color(), Color::White);
Ok(())
@ -428,7 +428,7 @@ mod tests {
White Rook on A1,
];
let original_castling_rights = board.castling_rights();
let original_castling_rights = *board.castling_rights();
let ply = Move::castle(Color::White, Wing::QueenSide);
let record = board.make_move(ply, ValidateMove::Yes)?;
@ -438,7 +438,7 @@ mod tests {
assert_eq!(board.get_piece(Square::A1), None);
assert_eq!(board.get_piece(Square::C1), Some(piece!(White King)));
assert_eq!(board.get_piece(Square::D1), Some(piece!(White Rook)));
assert!(!board.color_has_castling_right_unwrapped(Color::White, Wing::QueenSide));
assert!(!board.has_castling_right_unwrapped(Color::White, Wing::QueenSide));
board.unmake_move(&record)?;
@ -447,7 +447,7 @@ mod tests {
assert_eq!(board.get_piece(Square::A1), Some(piece!(White Rook)));
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.castling_rights(), original_castling_rights);
assert_eq!(board.active_color(), Color::White);
Ok(())
@ -460,7 +460,7 @@ mod tests {
Black Rook on H8,
]);
let original_castling_rights = board.castling_rights();
let original_castling_rights = *board.castling_rights();
let ply = Move::castle(Color::Black, Wing::KingSide);
let record = board.make_move(ply, ValidateMove::Yes)?;
@ -478,7 +478,7 @@ mod tests {
assert_eq!(board.get_piece(Square::H8), Some(piece!(Black Rook)));
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.castling_rights(), original_castling_rights);
assert_eq!(board.active_color(), Color::Black);
Ok(())