chessfriend/board/src/castle/rights.rs

81 lines
2.6 KiB
Rust

use super::Castle;
use chessfriend_core::Color;
use std::fmt;
#[derive(Clone, Copy, Eq, Hash, PartialEq)]
pub struct Rights(u8);
impl Rights {
/// Returns `true` if the player has the right to castle on the given side
/// of the board.
///
/// A player retains the right to castle on a particular side of the board
/// as long as they have not moved their king, or the rook on that side of
/// the board.
#[must_use]
pub fn is_set(self, color: Color, castle: Castle) -> bool {
(self.0 & (1 << Self::flag_offset(color, castle))) != 0
}
pub fn set(&mut self, color: Color, castle: Castle) {
self.0 |= 1 << Self::flag_offset(color, castle);
}
pub fn clear(&mut self, color: Color, castle: Castle) {
self.0 &= !(1 << Self::flag_offset(color, castle));
}
pub fn clear_all(&mut self) {
self.0 = 0;
}
fn flag_offset(color: Color, castle: Castle) -> usize {
((color as usize) << 1) + castle as usize
}
}
impl fmt::Debug for Rights {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "Flags({:08b})", self.0)
}
}
impl Default for Rights {
fn default() -> Self {
Self(0b0000_1111)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn bitfield_offsets() {
assert_eq!(Rights::flag_offset(Color::White, Castle::KingSide), 0);
assert_eq!(Rights::flag_offset(Color::White, Castle::QueenSide), 1);
assert_eq!(Rights::flag_offset(Color::Black, Castle::KingSide), 2);
assert_eq!(Rights::flag_offset(Color::Black, Castle::QueenSide), 3);
}
#[test]
fn default_rights() {
let mut rights = Rights::default();
assert!(rights.is_set(Color::White, Castle::KingSide));
assert!(rights.is_set(Color::White, Castle::QueenSide));
assert!(rights.is_set(Color::Black, Castle::KingSide));
assert!(rights.is_set(Color::Black, Castle::QueenSide));
rights.clear(Color::White, Castle::QueenSide);
assert!(rights.is_set(Color::White, Castle::KingSide));
assert!(!rights.is_set(Color::White, Castle::QueenSide));
assert!(rights.is_set(Color::Black, Castle::KingSide));
assert!(rights.is_set(Color::Black, Castle::QueenSide));
rights.set(Color::White, Castle::QueenSide);
assert!(rights.is_set(Color::White, Castle::KingSide));
assert!(rights.is_set(Color::White, Castle::QueenSide));
assert!(rights.is_set(Color::Black, Castle::KingSide));
assert!(rights.is_set(Color::Black, Castle::QueenSide));
}
}