use crate::prelude::*;
use std::ops::BitAnd;
use bitflags::bitflags;
bitflags! {
#[derive_const(Default)]
#[must_use]
pub struct CastlingRights: u8 {
const NONE = 0;
const WHITE_OO = 1 << 0;
const WHITE_OOO = 1 << 1;
const BLACK_OO = 1 << 2;
const BLACK_OOO = 1 << 3;
const WHITE = Self::WHITE_OO .bits | Self::WHITE_OOO.bits;
const BLACK = Self::BLACK_OO .bits | Self::BLACK_OOO.bits;
const KING_SIDE = Self::WHITE_OO .bits | Self::BLACK_OO .bits;
const QUEEN_SIDE = Self::WHITE_OOO.bits | Self::BLACK_OOO.bits;
const ANY = Self::WHITE .bits | Self::BLACK .bits;
}
}
impl CastlingRights {
pub const COUNT: usize = Self::ANY.bits as usize + 1;
pub const VARIANTS: [CastlingRights; CastlingRights::COUNT] = [
Self::NONE,
Self::WHITE_OO,
Self::WHITE_OOO,
Self::BLACK_OO,
Self::BLACK_OOO,
Self::WHITE,
Self::BLACK,
Self::KING_SIDE,
Self::QUEEN_SIDE,
Self::from_bits_truncate(Self::WHITE_OO.bits | Self::BLACK_OOO.bits),
Self::from_bits_truncate(Self::WHITE_OOO.bits | Self::BLACK_OO .bits),
Self::from_bits_truncate(Self::WHITE.bits | Self::BLACK_OO .bits),
Self::from_bits_truncate(Self::WHITE.bits | Self::BLACK_OOO.bits),
Self::from_bits_truncate(Self::BLACK.bits | Self::WHITE_OO .bits),
Self::from_bits_truncate(Self::BLACK.bits | Self::WHITE_OOO.bits),
Self::ANY,
];
#[must_use]
pub fn iter() -> std::array::IntoIter<Self, 16> {
Self::VARIANTS.into_iter()
}
}
impl BitAnd<Color> for CastlingRights {
type Output = Self;
#[inline]
fn bitand(self, rhs: Color) -> Self::Output {
match rhs {
Color::White => self & Self::WHITE,
Color::Black => self & Self::BLACK,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn default() {
assert_eq!(CastlingRights::NONE, CastlingRights::default());
}
#[test]
fn bitand_color() {
assert_eq!(CastlingRights::WHITE_OOO, CastlingRights::QUEEN_SIDE & Color::White);
assert_eq!(CastlingRights::BLACK_OO, CastlingRights::KING_SIDE & Color::Black);
}
}