1
0
Fork 0

new quad-bitboard representation

This commit is contained in:
Paul-Nicolas Madelaine 2025-11-29 14:12:20 +01:00
parent 57b78880f2
commit 4c137d3c95
3 changed files with 43 additions and 39 deletions

View file

@ -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 {

View file

@ -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<Self> {
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;

View file

@ -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<Piece> {
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<Piece>) {
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<Position, IllegalPosition> {
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) }
}
}