use super::*;
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[repr(u8)]
#[derive(PartialEq, Eq, Clone, Copy, Debug, Hash)]
pub enum CastleRights {
None = 0,
KingSide = 1,
QueenSide = 2,
Both = 3,
}
const CASTLES_PER_SQUARE: [[usize; 64]; 2] = [
[
2, 0, 0, 0, 3, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ],
[
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 1, ],
];
impl CastleRights {
#[inline]
pub const fn has_kingside(self) -> bool {
self.to_index() & 1 == 1
}
#[inline]
pub const fn has_queenside(self) -> bool {
self.to_index() & 2 == 2
}
#[inline]
pub fn square_to_castle_rights(color: Color, square: Square) -> Self {
Self::from_index(*get_item_unchecked!(
CASTLES_PER_SQUARE,
color.to_index(),
square.to_index()
))
}
#[inline]
pub fn kingside_squares(self, color: Color) -> BitBoard {
*get_item_unchecked!(KINGSIDE_CASTLE_SQUARES, color.to_index())
}
#[inline]
pub fn queenside_squares(self, color: Color) -> BitBoard {
*get_item_unchecked!(QUEENSIDE_CASTLE_SQUARES, color.to_index())
}
#[inline]
pub const fn remove(self, remove: Self) -> Self {
Self::from_index(self.to_index() & !remove.to_index())
}
#[inline]
pub const fn to_index(self) -> usize {
self as usize
}
#[inline]
pub const fn from_index(i: usize) -> Self {
match i {
0 => Self::None,
1 => Self::KingSide,
2 => Self::QueenSide,
3 => Self::Both,
_ => unreachable!(),
}
}
#[inline]
pub fn unmoved_rooks(self, color: Color) -> BitBoard {
match self {
Self::None => BB_EMPTY,
Self::KingSide => BitBoard::from_rank_and_file(color.to_my_backrank(), File::H),
Self::QueenSide => BitBoard::from_rank_and_file(color.to_my_backrank(), File::A),
Self::Both => {
BitBoard::from_rank_and_file(color.to_my_backrank(), File::A)
^ BitBoard::from_rank_and_file(color.to_my_backrank(), File::H)
}
}
}
pub fn to_string(self, color: Color) -> String {
let result = match self {
Self::None => "",
Self::KingSide => "k",
Self::QueenSide => "q",
Self::Both => "kq",
};
if color == White {
result.to_uppercase()
} else {
result.to_string()
}
}
#[inline]
pub fn rook_square_to_castle_rights(square: Square) -> Self {
match square.get_file() {
File::A => Self::QueenSide,
File::H => Self::KingSide,
_ => unreachable!(),
}
}
}
impl Add for CastleRights {
type Output = Self;
#[allow(clippy::suspicious_arithmetic_impl)]
#[inline]
fn add(self, rhs: Self) -> Self::Output {
Self::from_index(self.to_index() | rhs.to_index())
}
}
impl AddAssign for CastleRights {
#[inline]
fn add_assign(&mut self, rhs: Self) {
*self = *self + rhs;
}
}
impl Sub for CastleRights {
type Output = Self;
#[inline]
fn sub(self, rhs: Self) -> Self::Output {
self.remove(rhs)
}
}
impl SubAssign for CastleRights {
#[inline]
fn sub_assign(&mut self, rhs: Self) {
*self = *self - rhs;
}
}