diff --git a/src/board.rs b/src/board.rs index 6e7b98b..3c2ab21 100644 --- a/src/board.rs +++ b/src/board.rs @@ -73,6 +73,12 @@ impl Color { Self::Black => Direction::South, } } + + #[inline] + pub(crate) unsafe fn new_unchecked(color: u8) -> Self { + debug_assert!(color < 2); + unsafe { core::mem::transmute(color) } + } } impl core::ops::Not for Color { diff --git a/src/position.rs b/src/position.rs index 6277c65..f3501e8 100644 --- a/src/position.rs +++ b/src/position.rs @@ -90,7 +90,7 @@ impl Position { Bitboard(0x2CFF00000000FF2C), Bitboard(0x7600000000000076), Bitboard(0x9900000000000099), - Bitboard(0x000000000000FFFF), + Bitboard(0xFFFF000000000000), ], turn: Color::White, castling_rights: CastlingRights::full(), @@ -230,7 +230,7 @@ impl Position { /// play and discards the en passant square. pub fn pass(&self) -> Option { let Setup { - bitboards: [p_b_q, n_b_k, r_q_k, w], + bitboards: [p_b_q, n_b_k, r_q_k, black], turn, en_passant: _, castling_rights: _, @@ -243,8 +243,8 @@ impl Position { let r = r_q_k ^ q ^ k; let p = p_b_q ^ b ^ q; let (us, them) = match turn { - Color::White => (w, blockers ^ w), - Color::Black => (blockers ^ w, w), + Color::White => (blockers ^ black, black), + Color::Black => (black, blockers ^ black), }; let king_square = (us & k).next().unwrap(); let checkers = them @@ -580,7 +580,7 @@ impl Position { let global_mask_to = moves.to(); let Setup { - bitboards: [p_b_q, n_b_k, r_q_k, w], + bitboards: [p_b_q, n_b_k, r_q_k, black], turn, en_passant, castling_rights, @@ -588,8 +588,8 @@ impl Position { let blockers = p_b_q | n_b_k | r_q_k; let (us, them) = match turn { - Color::White => (w, blockers ^ w), - Color::Black => (blockers ^ w, w), + Color::White => (blockers ^ black, black), + Color::Black => (black, blockers ^ black), }; let k = n_b_k & r_q_k; @@ -938,9 +938,9 @@ impl Position { MoveType::EnPassant => { let direction = !setup.turn.forward(); let x = (unsafe { to.trans_unchecked(direction) }).bitboard(); - let [p_b_q, _, _, w] = &mut setup.bitboards; + let [p_b_q, _, _, black] = &mut setup.bitboards; *p_b_q ^= x; - *w &= !x; + *black &= !x; aux_play_pawn_advance(setup, Role::Pawn, from, to); } } @@ -952,7 +952,7 @@ impl Position { #[inline] fn aux_play_normal( Setup { - bitboards: [p_b_q, n_b_k, r_q_k, w], + bitboards: [p_b_q, n_b_k, r_q_k, black], turn, en_passant: _, castling_rights, @@ -967,7 +967,7 @@ fn aux_play_normal( *p_b_q &= mask; *n_b_k &= mask; *r_q_k &= mask; - *w &= mask; + *black &= mask; if target == Square::from_coords(File::H, turn.promotion_rank()) { castling_rights.unset(!*turn, CastlingSide::Short); } @@ -1005,15 +1005,15 @@ fn aux_play_normal( *p_b_q |= to; } } - if let Color::White = *turn { - *w |= to; + if let Color::Black = *turn { + *black |= to; } } #[inline] fn aux_play_pawn_advance( Setup { - bitboards: [p_b_q, n_b_k, r_q_k, w], + bitboards: [p_b_q, n_b_k, r_q_k, black], turn, en_passant: _, castling_rights: _, @@ -1044,15 +1044,15 @@ fn aux_play_pawn_advance( } Role::Pawn => *p_b_q ^= from | to, } - if let Color::White = *turn { - *w ^= from | to; + if let Color::Black = *turn { + *black ^= from | to; } } #[inline] fn aux_play_castle( Setup { - bitboards: [_, n_b_k, r_q_k, w], + bitboards: [_, n_b_k, r_q_k, black], turn, en_passant: _, castling_rights, @@ -1075,8 +1075,8 @@ fn aux_play_castle( ), }; - if let Color::White = *turn { - *w ^= king_flip | rook_flip; + if let Color::Black = *turn { + *black ^= king_flip | rook_flip; } *n_b_k ^= king_flip; *r_q_k ^= king_flip | rook_flip; diff --git a/src/setup.rs b/src/setup.rs index 4be387c..a3ad660 100644 --- a/src/setup.rs +++ b/src/setup.rs @@ -29,7 +29,7 @@ use alloc::string::String; /// [`from_text_record`](Setup::from_text_record) and [`to_text_record`](Setup::to_text_record). #[derive(Clone, PartialEq, Eq, PartialOrd, Ord)] pub struct Setup { - /// bitboards = [pawns | bishops | queens, knights | bishops | kings, rooks | queens | kings, white] + /// bitboards = [pawns | bishops | queens, knights | bishops | kings, rooks | queens | kings, black] pub(crate) bitboards: [Bitboard; 4], pub(crate) turn: Color, pub(crate) en_passant: OptionSquare, @@ -221,15 +221,12 @@ impl Setup { Ok(()) } - /// Returns the occupancy of a square. + /// Returns the piece on the square, if any. #[inline] pub fn get(&self, square: Square) -> Option { Some(Piece { role: self.role(square)?, - color: match self.is_white(square) { - true => Color::White, - false => Color::Black, - }, + color: self.color(square), }) } @@ -255,11 +252,11 @@ impl Setup { #[inline] pub fn set(&mut self, square: Square, piece: Option) { let mask = !square.bitboard(); - let [p_b_q, n_b_k, r_q_k, w] = &mut self.bitboards; + let [p_b_q, n_b_k, r_q_k, black] = &mut self.bitboards; *p_b_q &= mask; *n_b_k &= mask; *r_q_k &= mask; - *w &= mask; + *black &= mask; if let Some(piece) = piece { let to = square.bitboard(); match piece.role { @@ -286,8 +283,8 @@ impl Setup { } } match piece.color { - Color::White => *w |= to, - Color::Black => (), + Color::White => (), + Color::Black => *black |= to, } } } @@ -319,7 +316,7 @@ impl Setup { /// - pawns, bishops and queens /// - knights, bishops and kings /// - rooks, queens and kings - /// - white pieces + /// - black pieces #[inline] pub fn bitboards(&self) -> [Bitboard; 4] { self.bitboards @@ -335,13 +332,13 @@ impl Setup { /// is `rnbqkbnr/pppp1ppp/8/4p3/8/8/PPPPPPPP/RNBQKBNR w Qk e6`. #[inline] pub fn mirror(&self) -> Self { - let [p_b_q, n_b_k, r_q_k, w] = self.bitboards; + let [p_b_q, n_b_k, r_q_k, black] = self.bitboards; Self { bitboards: [ p_b_q.mirror(), n_b_k.mirror(), r_q_k.mirror(), - (w ^ (p_b_q | n_b_k | r_q_k)).mirror(), + (black ^ (p_b_q | n_b_k | r_q_k)).mirror(), ], turn: !self.turn, en_passant: self @@ -359,9 +356,9 @@ impl Setup { pub fn into_position(self) -> Result { let mut reasons = IllegalPositionReasons::new(); - let [p_b_q, n_b_k, r_q_k, w] = self.bitboards; + let [p_b_q, n_b_k, r_q_k, black] = self.bitboards; - debug_assert!((!(p_b_q | n_b_k | r_q_k) & w).is_empty()); + debug_assert!((!(p_b_q | n_b_k | r_q_k) & black).is_empty()); debug_assert!((p_b_q & n_b_k & r_q_k).is_empty()); let k = n_b_k & r_q_k; @@ -372,8 +369,8 @@ impl Setup { let p = p_b_q ^ b ^ q; let pieces = ByColor::with(|color| { let mask = match color { - Color::White => w, - Color::Black => !w, + Color::White => !black, + Color::Black => black, }; ByRole::with(|role| { mask & match role { @@ -518,10 +515,11 @@ impl Setup { } } + /// Returns the color of the piece on the square if any, and `Black` if the square is not occupied. #[inline] - pub(crate) fn is_white(&self, square: Square) -> bool { - let [_, _, _, w] = self.bitboards; - w.contains(square) + pub(crate) fn color(&self, square: Square) -> Color { + let [_, _, _, black] = self.bitboards; + unsafe { Color::new_unchecked(((black & square.bitboard()).0 >> square as u8) as u8) } } }