1
0
Fork 0

update board representation

This commit is contained in:
Paul-Nicolas Madelaine 2025-11-26 23:03:23 +01:00
parent 9a74ac0123
commit 85c7c8eb52
3 changed files with 184 additions and 147 deletions

View file

@ -86,10 +86,12 @@ impl Position {
#[inline]
pub fn new() -> Self {
Self(Setup {
w: Bitboard(0x000000000000FFFF),
p_b_q: Bitboard(0x2CFF00000000FF2C),
n_b_k: Bitboard(0x7600000000000076),
r_q_k: Bitboard(0x9900000000000099),
bitboards: [
Bitboard(0x2CFF00000000FF2C),
Bitboard(0x7600000000000076),
Bitboard(0x9900000000000099),
Bitboard(0x000000000000FFFF),
],
turn: Color::White,
castling_rights: CastlingRights::full(),
en_passant: OptionSquare::None,
@ -227,29 +229,34 @@ impl Position {
/// and `None` if the king in check. On success, this inverts the color to
/// play and discards the en passant square.
pub fn pass(&self) -> Option<Self> {
let setup = &self.0;
let blockers = setup.p_b_q | setup.n_b_k | setup.r_q_k;
let k = setup.n_b_k & setup.r_q_k;
let q = setup.p_b_q & setup.r_q_k;
let b = setup.p_b_q & setup.n_b_k;
let n = setup.n_b_k ^ b ^ k;
let r = setup.r_q_k ^ q ^ k;
let p = setup.p_b_q ^ b ^ q;
let (us, them) = match setup.turn {
Color::White => (setup.w, blockers ^ setup.w),
Color::Black => (blockers ^ setup.w, setup.w),
let Setup {
bitboards: [p_b_q, n_b_k, r_q_k, w],
turn,
en_passant: _,
castling_rights: _,
} = self.0;
let blockers = p_b_q | n_b_k | r_q_k;
let k = n_b_k & r_q_k;
let q = p_b_q & r_q_k;
let b = p_b_q & n_b_k;
let n = n_b_k ^ b ^ k;
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),
};
let king_square = (us & k).next().unwrap();
let checkers = them
& (lookup::pawn_attack(setup.turn, king_square) & p
& (lookup::pawn_attack(turn, king_square) & p
| lookup::knight(king_square) & n
| lookup::bishop(king_square, blockers) & (q | b)
| lookup::rook(king_square, blockers) & (q | r));
checkers.is_empty().then(|| {
Self(Setup {
turn: !setup.turn,
turn: !turn,
en_passant: OptionSquare::None,
..setup.clone()
..self.0.clone()
})
})
}
@ -573,10 +580,7 @@ impl Position {
let global_mask_to = moves.to();
let Setup {
w,
p_b_q,
n_b_k,
r_q_k,
bitboards: [p_b_q, n_b_k, r_q_k, w],
turn,
en_passant,
castling_rights,
@ -934,8 +938,9 @@ impl Position {
MoveType::EnPassant => {
let direction = !setup.turn.forward();
let x = (unsafe { to.trans_unchecked(direction) }).bitboard();
setup.p_b_q ^= x;
setup.w &= !x;
let [p_b_q, _, _, w] = &mut setup.bitboards;
*p_b_q ^= x;
*w &= !x;
aux_play_pawn_advance(setup, Role::Pawn, from, to);
}
}
@ -945,90 +950,116 @@ impl Position {
}
#[inline]
fn aux_play_normal(setup: &mut Setup, role: Role, from: Square, target: Square) {
fn aux_play_normal(
Setup {
bitboards: [p_b_q, n_b_k, r_q_k, w],
turn,
en_passant: _,
castling_rights,
}: &mut Setup,
role: Role,
from: Square,
target: Square,
) {
let from = from.bitboard();
let to = target.bitboard();
let mask = !(from | to);
setup.w &= mask;
setup.p_b_q &= mask;
setup.n_b_k &= mask;
setup.r_q_k &= mask;
if target == Square::from_coords(File::H, setup.turn.promotion_rank()) {
setup
.castling_rights
.unset(!setup.turn, CastlingSide::Short);
*p_b_q &= mask;
*n_b_k &= mask;
*r_q_k &= mask;
*w &= mask;
if target == Square::from_coords(File::H, turn.promotion_rank()) {
castling_rights.unset(!*turn, CastlingSide::Short);
}
if target == Square::from_coords(File::A, setup.turn.promotion_rank()) {
setup.castling_rights.unset(!setup.turn, CastlingSide::Long);
if target == Square::from_coords(File::A, turn.promotion_rank()) {
castling_rights.unset(!*turn, CastlingSide::Long);
}
match role {
Role::King => {
setup.n_b_k |= to;
setup.r_q_k |= to;
setup.castling_rights.unset(setup.turn, CastlingSide::Short);
setup.castling_rights.unset(setup.turn, CastlingSide::Long);
*n_b_k |= to;
*r_q_k |= to;
castling_rights.unset(*turn, CastlingSide::Short);
castling_rights.unset(*turn, CastlingSide::Long);
}
Role::Queen => {
setup.p_b_q |= to;
setup.r_q_k |= to;
*p_b_q |= to;
*r_q_k |= to;
}
Role::Bishop => {
setup.p_b_q |= to;
setup.n_b_k |= to;
*p_b_q |= to;
*n_b_k |= to;
}
Role::Knight => {
setup.n_b_k |= to;
*n_b_k |= to;
}
Role::Rook => {
setup.r_q_k |= to;
if from == Square::from_coords(File::H, setup.turn.home_rank()).bitboard() {
setup.castling_rights.unset(setup.turn, CastlingSide::Short);
*r_q_k |= to;
if from == Square::from_coords(File::H, turn.home_rank()).bitboard() {
castling_rights.unset(*turn, CastlingSide::Short);
}
if from == Square::from_coords(File::A, setup.turn.home_rank()).bitboard() {
setup.castling_rights.unset(setup.turn, CastlingSide::Long);
if from == Square::from_coords(File::A, turn.home_rank()).bitboard() {
castling_rights.unset(*turn, CastlingSide::Long);
}
}
Role::Pawn => {
setup.p_b_q |= to;
*p_b_q |= to;
}
}
if setup.turn == Color::White {
setup.w |= to;
if let Color::White = *turn {
*w |= to;
}
}
#[inline]
fn aux_play_pawn_advance(setup: &mut Setup, role: Role, from: Square, to: Square) {
fn aux_play_pawn_advance(
Setup {
bitboards: [p_b_q, n_b_k, r_q_k, w],
turn,
en_passant: _,
castling_rights: _,
}: &mut Setup,
role: Role,
from: Square,
to: Square,
) {
let from = from.bitboard();
let to = to.bitboard();
match role {
Role::King => unreachable!(),
Role::Queen => {
setup.p_b_q ^= from | to;
setup.r_q_k |= to;
*p_b_q ^= from | to;
*r_q_k |= to;
}
Role::Bishop => {
setup.p_b_q ^= from | to;
setup.n_b_k |= to;
*p_b_q ^= from | to;
*n_b_k |= to;
}
Role::Knight => {
setup.p_b_q ^= from;
setup.n_b_k |= to;
*p_b_q ^= from;
*n_b_k |= to;
}
Role::Rook => {
setup.p_b_q ^= from;
setup.r_q_k |= to;
*p_b_q ^= from;
*r_q_k |= to;
}
Role::Pawn => setup.p_b_q ^= from | to,
Role::Pawn => *p_b_q ^= from | to,
}
if setup.turn == Color::White {
setup.w ^= from | to;
if let Color::White = *turn {
*w ^= from | to;
}
}
#[inline]
fn aux_play_castle(setup: &mut Setup, side: CastlingSide) {
let rank = setup.turn.home_rank();
fn aux_play_castle(
Setup {
bitboards: [_, n_b_k, r_q_k, w],
turn,
en_passant: _,
castling_rights,
}: &mut Setup,
side: CastlingSide,
) {
let rank = turn.home_rank();
let (king_flip, rook_flip) = match side {
CastlingSide::Short => (
Square::from_coords(File::E, rank).bitboard()
@ -1044,14 +1075,14 @@ fn aux_play_castle(setup: &mut Setup, side: CastlingSide) {
),
};
if setup.turn == Color::White {
setup.w ^= king_flip | rook_flip;
if let Color::White = *turn {
*w ^= king_flip | rook_flip;
}
setup.n_b_k ^= king_flip;
setup.r_q_k ^= king_flip | rook_flip;
*n_b_k ^= king_flip;
*r_q_k ^= king_flip | rook_flip;
setup.castling_rights.unset(setup.turn, CastlingSide::Short);
setup.castling_rights.unset(setup.turn, CastlingSide::Long);
castling_rights.unset(*turn, CastlingSide::Short);
castling_rights.unset(*turn, CastlingSide::Long);
}
pub(crate) struct MateMoveGenImpl {