use core::*;
use std::fmt;
use core::masks::*;
use core::sq::SQ;
const ALL_CASTLING: u8 = 0b0000_1111;
bitflags! {
pub struct Castling: u8 {
const WHITE_K = C_WHITE_K_MASK; const WHITE_Q = C_WHITE_Q_MASK; const BLACK_K = C_BLACK_K_MASK; const BLACK_Q = C_BLACK_Q_MASK; const WHITE_ALL = Self::WHITE_K.bits | Self::WHITE_Q.bits;
const BLACK_ALL = Self::BLACK_K.bits | Self::BLACK_Q.bits;
}
}
impl Castling {
#[inline]
pub fn remove_player_castling(&mut self, player: Player) {
match player {
Player::White => self.bits &= Self::BLACK_ALL.bits,
Player::Black => self.bits &= Self::WHITE_ALL.bits,
}
}
#[doc(hidden)]
#[inline]
pub const fn all_castling() -> Self {
Castling {bits: ALL_CASTLING}
}
#[doc(hidden)]
#[inline]
pub const fn empty_set() -> Self {
Castling {bits: 0}
}
#[inline]
pub fn remove_king_side_castling(&mut self, player: Player) {
match player {
Player::White => self.bits &= !Self::WHITE_K.bits,
Player::Black => self.bits &= !Self::BLACK_K.bits,
}
}
#[inline]
pub fn remove_queen_side_castling(&mut self, player: Player) {
match player {
Player::White => self.bits &= !Self::WHITE_Q.bits,
Player::Black => self.bits &= !Self::BLACK_Q.bits,
}
}
#[inline]
pub fn castle_rights(self, player: Player, side: CastleType) -> bool {
match player {
Player::White => {
match side {
CastleType::KingSide => self.contains(Self::WHITE_K),
CastleType::QueenSide => self.contains(Self::WHITE_Q),
}
}
Player::Black => {
match side {
CastleType::KingSide => self.contains(Self::BLACK_K),
CastleType::QueenSide => self.contains(Self::BLACK_Q),
}
}
}
}
#[inline]
pub fn player_can_castle(self, player: Player) -> Castling {
Castling {
bits: self.bits & (Castling::WHITE_ALL.bits >> (2 * player as u16))
}
}
#[inline]
pub fn no_castling(self) -> bool {
!self.contains(Castling::WHITE_K) &&
!self.contains(Castling::WHITE_Q) &&
!self.contains(Castling::BLACK_K) &&
!self.contains(Castling::BLACK_Q)
}
#[inline]
pub fn update_castling(&mut self, to: SQ, from: SQ) -> u8 {
let mask_change: u8 = to.castle_rights_mask() | from.castle_rights_mask();
let to_return: u8 = self.bits & mask_change;
self.bits &= !mask_change;
to_return
}
pub fn add_castling_char(&mut self, c: char) {
self.bits |= match c {
'K' => Castling::WHITE_K.bits,
'Q' => Castling::WHITE_Q.bits,
'k' => Castling::BLACK_K.bits,
'q' => Castling::BLACK_Q.bits,
'-' => {0}
_ => panic!(),
};
}
pub fn pretty_string(self) -> String {
if self.no_castling() {
"-".to_owned()
} else {
let mut s = String::default();
if self.contains(Castling::WHITE_K) {
s.push('K');
}
if self.contains(Castling::WHITE_Q) {
s.push('Q');
}
if self.contains(Castling::BLACK_K) {
s.push('k');
}
if self.contains(Castling::BLACK_Q) {
s.push('q');
}
assert!(!s.is_empty());
s
}
}
}
impl fmt::Display for Castling {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.pretty_string())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
pub fn const_test() {
let c = Castling::all();
let c_const = Castling::all_castling();
assert_eq!(c, c_const);
}
}