[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:
parent
933924d37a
commit
4ce7e89cdb
8 changed files with 177 additions and 124 deletions
|
@ -1,13 +1,13 @@
|
||||||
// Eryn Wells <eryn@erynwells.me>
|
// Eryn Wells <eryn@erynwells.me>
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
PieceSet, castle,
|
CastleRights, PieceSet,
|
||||||
display::DiagramFormatter,
|
display::DiagramFormatter,
|
||||||
piece_sets::{PlacePieceError, PlacePieceStrategy},
|
piece_sets::{PlacePieceError, PlacePieceStrategy},
|
||||||
zobrist::{ZobristHash, ZobristState},
|
zobrist::{ZobristHash, ZobristState},
|
||||||
};
|
};
|
||||||
use chessfriend_bitboard::BitBoard;
|
use chessfriend_bitboard::BitBoard;
|
||||||
use chessfriend_core::{Color, Piece, Shape, Square, Wing};
|
use chessfriend_core::{Color, Piece, Shape, Square};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
pub type HalfMoveClock = u32;
|
pub type HalfMoveClock = u32;
|
||||||
|
@ -17,7 +17,7 @@ pub type FullMoveClock = u32;
|
||||||
pub struct Board {
|
pub struct Board {
|
||||||
active_color: Color,
|
active_color: Color,
|
||||||
pieces: PieceSet,
|
pieces: PieceSet,
|
||||||
castling_rights: castle::Rights,
|
castling_rights: CastleRights,
|
||||||
en_passant_target: Option<Square>,
|
en_passant_target: Option<Square>,
|
||||||
pub half_move_clock: HalfMoveClock,
|
pub half_move_clock: HalfMoveClock,
|
||||||
pub full_move_number: FullMoveClock,
|
pub full_move_number: FullMoveClock,
|
||||||
|
@ -92,59 +92,27 @@ impl Board {
|
||||||
|
|
||||||
impl Board {
|
impl Board {
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn castling_rights(&self) -> castle::Rights {
|
pub fn castling_rights(&self) -> &CastleRights {
|
||||||
self.castling_rights
|
&self.castling_rights
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_castling_rights(&mut self, rights: castle::Rights) {
|
pub(crate) fn castling_rights_mut(&mut self) -> &mut CastleRights {
|
||||||
|
&mut self.castling_rights
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Replace castling rights with new rights wholesale.
|
||||||
|
pub fn set_castling_rights(&mut self, rights: CastleRights) {
|
||||||
if rights == self.castling_rights {
|
if rights == self.castling_rights {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let old_rights = self.castling_rights;
|
let old_rights = self.castling_rights;
|
||||||
self.castling_rights = rights;
|
self.castling_rights = rights;
|
||||||
|
|
||||||
self.update_zobrist_hash_castling_rights(old_rights);
|
self.update_zobrist_hash_castling_rights(old_rights);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[must_use]
|
pub(crate) fn update_zobrist_hash_castling_rights(&mut self, old_rights: CastleRights) {
|
||||||
pub fn active_color_has_castling_right(&self, wing: Wing) -> bool {
|
|
||||||
self.color_has_castling_right_unwrapped(self.active_color, wing)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[must_use]
|
|
||||||
pub fn color_has_castling_right(&self, color: Option<Color>, wing: Wing) -> bool {
|
|
||||||
self.color_has_castling_right_unwrapped(self.unwrap_color(color), wing)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[must_use]
|
|
||||||
pub fn color_has_castling_right_unwrapped(&self, color: Color, wing: Wing) -> bool {
|
|
||||||
self.castling_rights.color_has_right(color, wing)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn grant_castling_right(&mut self, color: Color, wing: Wing) {
|
|
||||||
let old_rights = self.castling_rights;
|
|
||||||
self.castling_rights.grant(color, wing);
|
|
||||||
self.update_zobrist_hash_castling_rights(old_rights);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn revoke_all_castling_rights(&mut self) {
|
|
||||||
let old_rights = self.castling_rights;
|
|
||||||
self.castling_rights.revoke_all();
|
|
||||||
self.update_zobrist_hash_castling_rights(old_rights);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn revoke_castling_right(&mut self, color: Option<Color>, wing: Wing) {
|
|
||||||
let color = self.unwrap_color(color);
|
|
||||||
self.revoke_castling_right_unwrapped(color, wing);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn revoke_castling_right_unwrapped(&mut self, color: Color, wing: Wing) {
|
|
||||||
let old_rights = self.castling_rights;
|
|
||||||
self.castling_rights.revoke(color, wing);
|
|
||||||
self.update_zobrist_hash_castling_rights(old_rights);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn update_zobrist_hash_castling_rights(&mut self, old_rights: castle::Rights) {
|
|
||||||
let new_rights = self.castling_rights;
|
let new_rights = self.castling_rights;
|
||||||
if old_rights == new_rights {
|
if old_rights == new_rights {
|
||||||
return;
|
return;
|
||||||
|
@ -154,6 +122,18 @@ impl Board {
|
||||||
zobrist.update_modifying_castling_rights(new_rights, old_rights);
|
zobrist.update_modifying_castling_rights(new_rights, old_rights);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn castling_king(&self, square: Square) -> Option<Piece> {
|
||||||
|
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();
|
||||||
|
self.get_piece(square)
|
||||||
|
.filter(|piece| piece.color == active_color && piece.is_rook())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Board {
|
impl Board {
|
||||||
|
|
|
@ -4,10 +4,10 @@ mod parameters;
|
||||||
mod rights;
|
mod rights;
|
||||||
|
|
||||||
pub use parameters::Parameters;
|
pub use parameters::Parameters;
|
||||||
pub use rights::Rights;
|
pub use rights::{CastleRightsOption, Rights};
|
||||||
|
|
||||||
use crate::{Board, CastleParameters};
|
use crate::{Board, CastleParameters};
|
||||||
use chessfriend_core::{Color, Piece, Square, Wing};
|
use chessfriend_core::{Color, Wing};
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, Error, Eq, PartialEq)]
|
#[derive(Clone, Copy, Debug, Error, Eq, PartialEq)]
|
||||||
|
@ -46,7 +46,7 @@ impl Board {
|
||||||
|
|
||||||
let color = self.unwrap_color(color);
|
let color = self.unwrap_color(color);
|
||||||
|
|
||||||
if !self.color_has_castling_right_unwrapped(color, wing) {
|
if !self.has_castling_right_unwrapped(color, wing.into()) {
|
||||||
return Err(CastleEvaluationError::NoRights { color, wing });
|
return Err(CastleEvaluationError::NoRights { color, wing });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -76,17 +76,60 @@ impl Board {
|
||||||
|
|
||||||
Ok(parameters)
|
Ok(parameters)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn castling_king(&self, square: Square) -> Option<Piece> {
|
impl Board {
|
||||||
let active_color = self.active_color();
|
#[must_use]
|
||||||
self.get_piece(square)
|
pub fn has_castling_right(&self, color: Option<Color>, wing: Wing) -> bool {
|
||||||
.filter(|piece| piece.color == active_color && piece.is_king())
|
self.has_castling_right_unwrapped(self.unwrap_color(color), wing)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn castling_rook(&self, square: Square) -> Option<Piece> {
|
#[must_use]
|
||||||
let active_color = self.active_color();
|
pub fn has_castling_right_active(&self, wing: Wing) -> bool {
|
||||||
self.get_piece(square)
|
self.has_castling_right_unwrapped(self.active_color(), wing)
|
||||||
.filter(|piece| piece.color == active_color && piece.is_rook())
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub fn has_castling_right_unwrapped(&self, color: Color, wing: Wing) -> bool {
|
||||||
|
self.castling_rights().get(color, wing.into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Board {
|
||||||
|
pub fn grant_castling_rights(&mut self, color: Option<Color>, rights: CastleRightsOption) {
|
||||||
|
let color = self.unwrap_color(color);
|
||||||
|
self.grant_castling_rights_unwrapped(color, rights);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn grant_castling_rights_active(&mut self, rights: CastleRightsOption) {
|
||||||
|
self.grant_castling_rights_unwrapped(self.active_color(), rights);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn grant_castling_rights_unwrapped(&mut self, color: Color, rights: CastleRightsOption) {
|
||||||
|
let old_rights = *self.castling_rights();
|
||||||
|
self.castling_rights_mut().grant(color, rights);
|
||||||
|
self.update_zobrist_hash_castling_rights(old_rights);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Board {
|
||||||
|
pub fn revoke_all_castling_rights(&mut self) {
|
||||||
|
self.castling_rights_mut().revoke_all();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn revoke_castling_rights(&mut self, color: Option<Color>, rights: CastleRightsOption) {
|
||||||
|
let color = self.unwrap_color(color);
|
||||||
|
self.revoke_castling_rights_unwrapped(color, rights);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn revoke_castling_rights_active(&mut self, rights: CastleRightsOption) {
|
||||||
|
self.revoke_castling_rights_unwrapped(self.active_color(), rights);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn revoke_castling_rights_unwrapped(&mut self, color: Color, rights: CastleRightsOption) {
|
||||||
|
let old_rights = *self.castling_rights();
|
||||||
|
self.castling_rights_mut().revoke(color, rights);
|
||||||
|
self.update_zobrist_hash_castling_rights(old_rights);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -104,8 +147,8 @@ mod tests {
|
||||||
White Rook on H1
|
White Rook on H1
|
||||||
);
|
);
|
||||||
|
|
||||||
assert!(board.color_has_castling_right_unwrapped(Color::White, Wing::KingSide));
|
assert!(board.has_castling_right_unwrapped(Color::White, Wing::KingSide));
|
||||||
assert!(board.color_has_castling_right_unwrapped(Color::White, Wing::QueenSide));
|
assert!(board.has_castling_right_unwrapped(Color::White, Wing::QueenSide));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
@ -1,6 +1,14 @@
|
||||||
|
// Eryn Wells <eryn@erynwells.me>
|
||||||
|
|
||||||
use chessfriend_core::{Color, Wing};
|
use chessfriend_core::{Color, Wing};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||||
|
pub enum CastleRightsOption {
|
||||||
|
Wing(Wing),
|
||||||
|
All,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Eq, Hash, PartialEq)]
|
#[derive(Clone, Copy, Eq, Hash, PartialEq)]
|
||||||
pub struct Rights(u8);
|
pub struct Rights(u8);
|
||||||
|
|
||||||
|
@ -12,16 +20,16 @@ impl Rights {
|
||||||
/// as long as they have not moved their king, or the rook on that side of
|
/// as long as they have not moved their king, or the rook on that side of
|
||||||
/// the board.
|
/// the board.
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn color_has_right(self, color: Color, wing: Wing) -> bool {
|
pub fn get(self, color: Color, option: CastleRightsOption) -> bool {
|
||||||
(self.0 & (1 << Self::flag_offset(color, wing))) != 0
|
(self.0 & Self::flags(color, option)) != 0
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn grant(&mut self, color: Color, wing: Wing) {
|
pub fn grant(&mut self, color: Color, option: CastleRightsOption) {
|
||||||
self.0 |= 1 << Self::flag_offset(color, wing);
|
self.0 |= Self::flags(color, option);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn revoke(&mut self, color: Color, wing: Wing) {
|
pub fn revoke(&mut self, color: Color, option: CastleRightsOption) {
|
||||||
self.0 &= !(1 << Self::flag_offset(color, wing));
|
self.0 &= !Self::flags(color, option);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Revoke castling rights for all colors and all sides of the board.
|
/// Revoke castling rights for all colors and all sides of the board.
|
||||||
|
@ -31,14 +39,14 @@ impl Rights {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Rights {
|
impl Rights {
|
||||||
pub(crate) fn as_index(&self) -> usize {
|
pub(crate) fn as_index(self) -> usize {
|
||||||
self.0 as usize
|
self.0 as usize
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Rights {
|
impl Rights {
|
||||||
fn flag_offset(color: Color, wing: Wing) -> usize {
|
const fn flags(color: Color, option: CastleRightsOption) -> u8 {
|
||||||
((color as usize) << 1) + wing as usize
|
option.as_flags() << (color as u8 * 2)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,36 +62,55 @@ impl Default for Rights {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl CastleRightsOption {
|
||||||
|
#[must_use]
|
||||||
|
pub const fn as_flags(self) -> u8 {
|
||||||
|
match self {
|
||||||
|
Self::Wing(wing) => 1 << (wing as u8),
|
||||||
|
Self::All => (1 << Wing::KingSide as u8) | (1 << Wing::QueenSide as u8),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Wing> for CastleRightsOption {
|
||||||
|
fn from(value: Wing) -> Self {
|
||||||
|
Self::Wing(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn bitfield_offsets() {
|
fn bitfield_offsets() {
|
||||||
assert_eq!(Rights::flag_offset(Color::White, Wing::KingSide), 0);
|
assert_eq!(Rights::flags(Color::White, Wing::KingSide.into()), 1);
|
||||||
assert_eq!(Rights::flag_offset(Color::White, Wing::QueenSide), 1);
|
assert_eq!(Rights::flags(Color::White, Wing::QueenSide.into()), 1 << 1);
|
||||||
assert_eq!(Rights::flag_offset(Color::Black, Wing::KingSide), 2);
|
assert_eq!(Rights::flags(Color::Black, Wing::KingSide.into()), 1 << 2);
|
||||||
assert_eq!(Rights::flag_offset(Color::Black, Wing::QueenSide), 3);
|
assert_eq!(Rights::flags(Color::Black, Wing::QueenSide.into()), 1 << 3);
|
||||||
|
|
||||||
|
assert_eq!(Rights::flags(Color::White, CastleRightsOption::All), 0b11);
|
||||||
|
assert_eq!(Rights::flags(Color::Black, CastleRightsOption::All), 0b1100);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn default_rights() {
|
fn default_rights() {
|
||||||
let mut rights = Rights::default();
|
let mut rights = Rights::default();
|
||||||
assert!(rights.color_has_right(Color::White, Wing::KingSide));
|
assert!(rights.get(Color::White, Wing::KingSide.into()));
|
||||||
assert!(rights.color_has_right(Color::White, Wing::QueenSide));
|
assert!(rights.get(Color::White, Wing::QueenSide.into()));
|
||||||
assert!(rights.color_has_right(Color::Black, Wing::KingSide));
|
assert!(rights.get(Color::Black, Wing::KingSide.into()));
|
||||||
assert!(rights.color_has_right(Color::Black, Wing::QueenSide));
|
assert!(rights.get(Color::Black, Wing::QueenSide.into()));
|
||||||
|
|
||||||
rights.revoke(Color::White, Wing::QueenSide);
|
rights.revoke(Color::White, Wing::QueenSide.into());
|
||||||
assert!(rights.color_has_right(Color::White, Wing::KingSide));
|
assert!(rights.get(Color::White, Wing::KingSide.into()));
|
||||||
assert!(!rights.color_has_right(Color::White, Wing::QueenSide));
|
assert!(!rights.get(Color::White, Wing::QueenSide.into()));
|
||||||
assert!(rights.color_has_right(Color::Black, Wing::KingSide));
|
assert!(rights.get(Color::Black, Wing::KingSide.into()));
|
||||||
assert!(rights.color_has_right(Color::Black, Wing::QueenSide));
|
assert!(rights.get(Color::Black, Wing::QueenSide.into()));
|
||||||
|
|
||||||
rights.grant(Color::White, Wing::QueenSide);
|
rights.grant(Color::White, Wing::QueenSide.into());
|
||||||
assert!(rights.color_has_right(Color::White, Wing::KingSide));
|
assert!(rights.get(Color::White, Wing::KingSide.into()));
|
||||||
assert!(rights.color_has_right(Color::White, Wing::QueenSide));
|
assert!(rights.get(Color::White, Wing::QueenSide.into()));
|
||||||
assert!(rights.color_has_right(Color::Black, Wing::KingSide));
|
assert!(rights.get(Color::Black, Wing::KingSide.into()));
|
||||||
assert!(rights.color_has_right(Color::Black, Wing::QueenSide));
|
assert!(rights.get(Color::Black, Wing::QueenSide.into()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,12 +24,16 @@ pub enum ToFenStrError {
|
||||||
pub enum FromFenStrError {
|
pub enum FromFenStrError {
|
||||||
#[error("missing {0} field")]
|
#[error("missing {0} field")]
|
||||||
MissingField(Field),
|
MissingField(Field),
|
||||||
|
|
||||||
#[error("missing piece placement")]
|
#[error("missing piece placement")]
|
||||||
MissingPlacement,
|
MissingPlacement,
|
||||||
|
|
||||||
#[error("invalid value")]
|
#[error("invalid value")]
|
||||||
InvalidValue,
|
InvalidValue,
|
||||||
|
|
||||||
#[error("{0}")]
|
#[error("{0}")]
|
||||||
ParseIntError(#[from] std::num::ParseIntError),
|
ParseIntError(#[from] std::num::ParseIntError),
|
||||||
|
|
||||||
#[error("{0}")]
|
#[error("{0}")]
|
||||||
ParseSquareError(#[from] ParseSquareError),
|
ParseSquareError(#[from] ParseSquareError),
|
||||||
}
|
}
|
||||||
|
@ -122,12 +126,12 @@ impl ToFenStr for Board {
|
||||||
(Color::Black, Wing::KingSide),
|
(Color::Black, Wing::KingSide),
|
||||||
(Color::Black, Wing::QueenSide),
|
(Color::Black, Wing::QueenSide),
|
||||||
]
|
]
|
||||||
.map(|(color, castle)| {
|
.map(|(color, wing)| {
|
||||||
if !self.color_has_castling_right_unwrapped(color, castle) {
|
if !self.has_castling_right_unwrapped(color, wing) {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
match (color, castle) {
|
match (color, wing) {
|
||||||
(Color::White, Wing::KingSide) => "K",
|
(Color::White, Wing::KingSide) => "K",
|
||||||
(Color::White, Wing::QueenSide) => "Q",
|
(Color::White, Wing::QueenSide) => "Q",
|
||||||
(Color::Black, Wing::KingSide) => "k",
|
(Color::Black, Wing::KingSide) => "k",
|
||||||
|
@ -226,19 +230,23 @@ impl FromFenStr for Board {
|
||||||
)?;
|
)?;
|
||||||
board.set_active_color(active_color);
|
board.set_active_color(active_color);
|
||||||
|
|
||||||
|
let color_wing_from_char = |ch| match ch {
|
||||||
|
'K' => Some((Color::White, Wing::KingSide)),
|
||||||
|
'Q' => Some((Color::White, Wing::QueenSide)),
|
||||||
|
'k' => Some((Color::Black, Wing::KingSide)),
|
||||||
|
'q' => Some((Color::Black, Wing::QueenSide)),
|
||||||
|
_ => None,
|
||||||
|
};
|
||||||
|
|
||||||
let castling_rights = fields
|
let castling_rights = fields
|
||||||
.next()
|
.next()
|
||||||
.ok_or(FromFenStrError::MissingField(Field::CastlingRights))?;
|
.ok_or(FromFenStrError::MissingField(Field::CastlingRights))?;
|
||||||
board.revoke_all_castling_rights();
|
board.revoke_all_castling_rights();
|
||||||
if castling_rights != "-" {
|
if castling_rights != "-" {
|
||||||
for ch in castling_rights.chars() {
|
for ch in castling_rights.chars() {
|
||||||
match ch {
|
let (color, wing) =
|
||||||
'K' => board.grant_castling_right(Color::White, Wing::KingSide),
|
color_wing_from_char(ch).ok_or(FromFenStrError::InvalidValue)?;
|
||||||
'Q' => board.grant_castling_right(Color::White, Wing::QueenSide),
|
board.grant_castling_rights_unwrapped(color, wing.into());
|
||||||
'k' => board.grant_castling_right(Color::Black, Wing::KingSide),
|
|
||||||
'q' => board.grant_castling_right(Color::Black, Wing::QueenSide),
|
|
||||||
_ => return Err(FromFenStrError::InvalidValue),
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,16 +1,11 @@
|
||||||
// Eryn Wells <eryn@erynwells.me>
|
// Eryn Wells <eryn@erynwells.me>
|
||||||
|
|
||||||
use chessfriend_board::castle::CastleEvaluationError;
|
use chessfriend_board::{Board, ZobristState, fen::FromFenStr};
|
||||||
use chessfriend_board::{Board, fen::FromFenStr};
|
use chessfriend_core::{Color, Piece, Shape, Square, Wing, random::RandomNumberGenerator};
|
||||||
use chessfriend_board::{CastleParameters, ZobristState};
|
use chessfriend_moves::{GeneratedMove, ValidateMove, algebraic::AlgebraicMoveComponents};
|
||||||
use chessfriend_core::random::RandomNumberGenerator;
|
|
||||||
use chessfriend_core::{Color, Piece, Shape, Square, Wing};
|
|
||||||
use chessfriend_moves::algebraic::AlgebraicMoveComponents;
|
|
||||||
use chessfriend_moves::{GeneratedMove, ValidateMove};
|
|
||||||
use chessfriend_position::{PlacePieceStrategy, Position, fen::ToFenStr};
|
use chessfriend_position::{PlacePieceStrategy, Position, fen::ToFenStr};
|
||||||
use clap::{Arg, Command, value_parser};
|
use clap::{Arg, Command, value_parser};
|
||||||
use rustyline::DefaultEditor;
|
use rustyline::{DefaultEditor, error::ReadlineError};
|
||||||
use rustyline::error::ReadlineError;
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
|
@ -202,7 +197,7 @@ fn do_flags_command(state: &mut State, _matches: &clap::ArgMatches) -> CommandRe
|
||||||
(Color::Black, Wing::KingSide),
|
(Color::Black, Wing::KingSide),
|
||||||
(Color::Black, Wing::QueenSide),
|
(Color::Black, Wing::QueenSide),
|
||||||
] {
|
] {
|
||||||
let has_right = board.color_has_castling_right_unwrapped(color, wing);
|
let has_right = board.has_castling_right_unwrapped(color, wing.into());
|
||||||
let can_castle = board.color_can_castle(wing, Some(color));
|
let can_castle = board.color_can_castle(wing, Some(color));
|
||||||
|
|
||||||
let can_castle_message = match can_castle {
|
let can_castle_message = match can_castle {
|
||||||
|
|
|
@ -3,7 +3,8 @@
|
||||||
use crate::{Move, MoveRecord};
|
use crate::{Move, MoveRecord};
|
||||||
use chessfriend_board::{
|
use chessfriend_board::{
|
||||||
Board, BoardProvider, CastleParameters, PlacePieceError, PlacePieceStrategy,
|
Board, BoardProvider, CastleParameters, PlacePieceError, PlacePieceStrategy,
|
||||||
castle::CastleEvaluationError, movement::Movement,
|
castle::{CastleEvaluationError, CastleRightsOption},
|
||||||
|
movement::Movement,
|
||||||
};
|
};
|
||||||
use chessfriend_core::{Color, Piece, Rank, Shape, Square, Wing};
|
use chessfriend_core::{Color, Piece, Rank, Shape, Square, Wing};
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
@ -251,7 +252,7 @@ impl<T: BoardProvider> MakeMoveInternal for T {
|
||||||
// original board state is preserved.
|
// original board state is preserved.
|
||||||
let record = MoveRecord::new(board, ply, None);
|
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);
|
self.advance_board_state(&ply, &king, None, HalfMoveClock::Advance);
|
||||||
|
|
||||||
|
@ -307,23 +308,22 @@ impl<T: BoardProvider> MakeMoveInternal for T {
|
||||||
Shape::Rook => {
|
Shape::Rook => {
|
||||||
let origin = ply.origin_square();
|
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 =
|
let kingside_parameters =
|
||||||
CastleParameters::get(board.active_color(), Wing::KingSide);
|
CastleParameters::get(board.active_color(), Wing::KingSide);
|
||||||
if origin == kingside_parameters.origin.rook {
|
if origin == kingside_parameters.origin.rook {
|
||||||
board.revoke_castling_right(None, Wing::KingSide);
|
board.revoke_castling_rights(None, Wing::KingSide.into());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let queenside_parameters =
|
let queenside_parameters =
|
||||||
CastleParameters::get(board.active_color(), Wing::QueenSide);
|
CastleParameters::get(board.active_color(), Wing::QueenSide);
|
||||||
if origin == queenside_parameters.origin.rook {
|
if origin == queenside_parameters.origin.rook {
|
||||||
board.revoke_castling_right(None, Wing::QueenSide);
|
board.revoke_castling_rights(None, Wing::QueenSide.into());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Shape::King => {
|
Shape::King => {
|
||||||
board.revoke_castling_right(None, Wing::KingSide);
|
board.revoke_castling_rights(None, CastleRightsOption::All);
|
||||||
board.revoke_castling_right(None, Wing::QueenSide);
|
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
@ -562,7 +562,7 @@ mod tests {
|
||||||
assert_eq!(board.get_piece(Square::H1), None);
|
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::G1), Some(piece!(White King)));
|
||||||
assert_eq!(board.get_piece(Square::F1), Some(piece!(White Rook)));
|
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(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -582,7 +582,7 @@ mod tests {
|
||||||
assert_eq!(board.get_piece(Square::A1), None);
|
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::C1), Some(piece!(White King)));
|
||||||
assert_eq!(board.get_piece(Square::D1), Some(piece!(White Rook)));
|
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(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
// Eryn Wells <eryn@erynwells.me>
|
// Eryn Wells <eryn@erynwells.me>
|
||||||
|
|
||||||
use crate::Move;
|
use crate::Move;
|
||||||
use chessfriend_board::{board::HalfMoveClock, Board, CastleRights};
|
use chessfriend_board::{Board, CastleRights, board::HalfMoveClock};
|
||||||
use chessfriend_core::{Color, Piece, Square};
|
use chessfriend_core::{Color, Piece, Square};
|
||||||
|
|
||||||
/// A record of a move made on a board. This struct contains all the information
|
/// 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(),
|
color: board.active_color(),
|
||||||
ply,
|
ply,
|
||||||
en_passant_target: board.en_passant_target(),
|
en_passant_target: board.en_passant_target(),
|
||||||
castling_rights: board.castling_rights(),
|
castling_rights: *board.castling_rights(),
|
||||||
half_move_clock: board.half_move_clock,
|
half_move_clock: board.half_move_clock,
|
||||||
captured_piece: capture,
|
captured_piece: capture,
|
||||||
}
|
}
|
||||||
|
|
|
@ -396,7 +396,7 @@ mod tests {
|
||||||
White Rook on H1,
|
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 ply = Move::castle(Color::White, Wing::KingSide);
|
||||||
let record = board.make_move(ply, ValidateMove::Yes)?;
|
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::H1), None);
|
||||||
assert_eq!(board.get_piece(Square::G1), Some(piece!(White King)));
|
assert_eq!(board.get_piece(Square::G1), Some(piece!(White King)));
|
||||||
assert_eq!(board.get_piece(Square::F1), Some(piece!(White Rook)));
|
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)?;
|
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::H1), Some(piece!(White Rook)));
|
||||||
assert_eq!(board.get_piece(Square::G1), None);
|
assert_eq!(board.get_piece(Square::G1), None);
|
||||||
assert_eq!(board.get_piece(Square::F1), 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);
|
assert_eq!(board.active_color(), Color::White);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -428,7 +428,7 @@ mod tests {
|
||||||
White Rook on A1,
|
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 ply = Move::castle(Color::White, Wing::QueenSide);
|
||||||
let record = board.make_move(ply, ValidateMove::Yes)?;
|
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::A1), None);
|
||||||
assert_eq!(board.get_piece(Square::C1), Some(piece!(White King)));
|
assert_eq!(board.get_piece(Square::C1), Some(piece!(White King)));
|
||||||
assert_eq!(board.get_piece(Square::D1), Some(piece!(White Rook)));
|
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)?;
|
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::A1), Some(piece!(White Rook)));
|
||||||
assert_eq!(board.get_piece(Square::C1), None);
|
assert_eq!(board.get_piece(Square::C1), None);
|
||||||
assert_eq!(board.get_piece(Square::D1), 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);
|
assert_eq!(board.active_color(), Color::White);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -460,7 +460,7 @@ mod tests {
|
||||||
Black Rook on H8,
|
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 ply = Move::castle(Color::Black, Wing::KingSide);
|
||||||
let record = board.make_move(ply, ValidateMove::Yes)?;
|
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::H8), Some(piece!(Black Rook)));
|
||||||
assert_eq!(board.get_piece(Square::G8), None);
|
assert_eq!(board.get_piece(Square::G8), None);
|
||||||
assert_eq!(board.get_piece(Square::F8), 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);
|
assert_eq!(board.active_color(), Color::Black);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue