use crate::prelude::*;
#[derive(Copy, Debug, Eq)]
#[derive_const(Clone, PartialEq)]
#[must_use]
pub struct CastlingPath {
pub variety: CastlingVariety,
pub path: Bitboard,
king: Square,
rook: Square,
}
impl CastlingPath {
#[inline]
#[must_use]
pub const fn new(color: Color, king: File, rook: File) -> Option<Self> {
let side = CastlingSide::new(king, rook)?;
let variety = CastlingVariety::new(color, side);
let rank = color.rank();
let king = rank | king;
let rook = rank | rook;
let path = (
crate::accelerate::between(king, variety.king_destination()) |
crate::accelerate::between(rook, variety.rook_destination())
) & !(king | rook);
Some(Self {
variety,
path,
king,
rook,
})
}
#[inline]
pub const fn color(self) -> Color {
self.variety.color()
}
#[inline]
pub const fn side(self) -> CastlingSide {
self.variety.side()
}
#[inline]
pub const fn king_origin(self) -> Square {
self.king
}
#[inline]
pub const fn king_destination(self) -> Square {
self.variety.king_destination()
}
#[inline]
pub const fn rook_origin(self) -> Square {
self.rook
}
#[inline]
pub const fn rook_destination(self) -> Square {
self.variety.rook_destination()
}
#[inline]
pub const fn rights(self) -> CastlingRights {
self.variety.rights()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn derives() {
let path = CastlingPath::new(Color::Black, File::_A, File::_H);
assert_eq!(path, path.clone());
assert_ne!("", format!("{path:?}"));
}
#[test]
fn new_same_file() {
assert_eq!(None, CastlingPath::new(Color::White, File::_D, File::_D));
}
#[test]
fn color() {
let color = Color::Black;
let path = CastlingPath::new(color, File::_A, File::_H).unwrap();
assert_eq!(color, path.color());
}
#[test]
fn side() {
assert_eq!(
CastlingSide::King,
CastlingPath::new(Color::White, File::_A, File::_H).unwrap().side()
);
assert_eq!(
CastlingSide::Queen,
CastlingPath::new(Color::White, File::_B, File::_A).unwrap().side()
);
}
#[test]
fn origin() {
let king = File::_E;
let rook = File::_H;
let path = CastlingPath::new(Color::White, king, rook);
assert_eq!(king | Rank::_1, path.unwrap().king_origin());
assert_eq!(rook | Rank::_1, path.unwrap().rook_origin());
}
#[test]
fn destination() {
let king = File::_E;
let rook = File::_A;
let path = CastlingPath::new(Color::Black, king, rook);
assert_eq!(Square::C8, path.unwrap().king_destination());
assert_eq!(Square::D8, path.unwrap().rook_destination());
}
#[test]
fn rights() {
let path = CastlingPath::new(Color::White, File::_A, File::_H);
assert_eq!(CastlingRights::WHITE_OO, path.unwrap().rights());
}
}