new quad-bitboard representation
This commit is contained in:
parent
57b78880f2
commit
4c137d3c95
3 changed files with 43 additions and 39 deletions
|
|
@ -73,6 +73,12 @@ impl Color {
|
||||||
Self::Black => Direction::South,
|
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 {
|
impl core::ops::Not for Color {
|
||||||
|
|
|
||||||
|
|
@ -90,7 +90,7 @@ impl Position {
|
||||||
Bitboard(0x2CFF00000000FF2C),
|
Bitboard(0x2CFF00000000FF2C),
|
||||||
Bitboard(0x7600000000000076),
|
Bitboard(0x7600000000000076),
|
||||||
Bitboard(0x9900000000000099),
|
Bitboard(0x9900000000000099),
|
||||||
Bitboard(0x000000000000FFFF),
|
Bitboard(0xFFFF000000000000),
|
||||||
],
|
],
|
||||||
turn: Color::White,
|
turn: Color::White,
|
||||||
castling_rights: CastlingRights::full(),
|
castling_rights: CastlingRights::full(),
|
||||||
|
|
@ -230,7 +230,7 @@ impl Position {
|
||||||
/// play and discards the en passant square.
|
/// play and discards the en passant square.
|
||||||
pub fn pass(&self) -> Option<Self> {
|
pub fn pass(&self) -> Option<Self> {
|
||||||
let Setup {
|
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,
|
turn,
|
||||||
en_passant: _,
|
en_passant: _,
|
||||||
castling_rights: _,
|
castling_rights: _,
|
||||||
|
|
@ -243,8 +243,8 @@ impl Position {
|
||||||
let r = r_q_k ^ q ^ k;
|
let r = r_q_k ^ q ^ k;
|
||||||
let p = p_b_q ^ b ^ q;
|
let p = p_b_q ^ b ^ q;
|
||||||
let (us, them) = match turn {
|
let (us, them) = match turn {
|
||||||
Color::White => (w, blockers ^ w),
|
Color::White => (blockers ^ black, black),
|
||||||
Color::Black => (blockers ^ w, w),
|
Color::Black => (black, blockers ^ black),
|
||||||
};
|
};
|
||||||
let king_square = (us & k).next().unwrap();
|
let king_square = (us & k).next().unwrap();
|
||||||
let checkers = them
|
let checkers = them
|
||||||
|
|
@ -580,7 +580,7 @@ impl Position {
|
||||||
let global_mask_to = moves.to();
|
let global_mask_to = moves.to();
|
||||||
|
|
||||||
let Setup {
|
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,
|
turn,
|
||||||
en_passant,
|
en_passant,
|
||||||
castling_rights,
|
castling_rights,
|
||||||
|
|
@ -588,8 +588,8 @@ impl Position {
|
||||||
|
|
||||||
let blockers = p_b_q | n_b_k | r_q_k;
|
let blockers = p_b_q | n_b_k | r_q_k;
|
||||||
let (us, them) = match turn {
|
let (us, them) = match turn {
|
||||||
Color::White => (w, blockers ^ w),
|
Color::White => (blockers ^ black, black),
|
||||||
Color::Black => (blockers ^ w, w),
|
Color::Black => (black, blockers ^ black),
|
||||||
};
|
};
|
||||||
|
|
||||||
let k = n_b_k & r_q_k;
|
let k = n_b_k & r_q_k;
|
||||||
|
|
@ -938,9 +938,9 @@ impl Position {
|
||||||
MoveType::EnPassant => {
|
MoveType::EnPassant => {
|
||||||
let direction = !setup.turn.forward();
|
let direction = !setup.turn.forward();
|
||||||
let x = (unsafe { to.trans_unchecked(direction) }).bitboard();
|
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;
|
*p_b_q ^= x;
|
||||||
*w &= !x;
|
*black &= !x;
|
||||||
aux_play_pawn_advance(setup, Role::Pawn, from, to);
|
aux_play_pawn_advance(setup, Role::Pawn, from, to);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -952,7 +952,7 @@ impl Position {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn aux_play_normal(
|
fn aux_play_normal(
|
||||||
Setup {
|
Setup {
|
||||||
bitboards: [p_b_q, n_b_k, r_q_k, w],
|
bitboards: [p_b_q, n_b_k, r_q_k, black],
|
||||||
turn,
|
turn,
|
||||||
en_passant: _,
|
en_passant: _,
|
||||||
castling_rights,
|
castling_rights,
|
||||||
|
|
@ -967,7 +967,7 @@ fn aux_play_normal(
|
||||||
*p_b_q &= mask;
|
*p_b_q &= mask;
|
||||||
*n_b_k &= mask;
|
*n_b_k &= mask;
|
||||||
*r_q_k &= mask;
|
*r_q_k &= mask;
|
||||||
*w &= mask;
|
*black &= mask;
|
||||||
if target == Square::from_coords(File::H, turn.promotion_rank()) {
|
if target == Square::from_coords(File::H, turn.promotion_rank()) {
|
||||||
castling_rights.unset(!*turn, CastlingSide::Short);
|
castling_rights.unset(!*turn, CastlingSide::Short);
|
||||||
}
|
}
|
||||||
|
|
@ -1005,15 +1005,15 @@ fn aux_play_normal(
|
||||||
*p_b_q |= to;
|
*p_b_q |= to;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let Color::White = *turn {
|
if let Color::Black = *turn {
|
||||||
*w |= to;
|
*black |= to;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn aux_play_pawn_advance(
|
fn aux_play_pawn_advance(
|
||||||
Setup {
|
Setup {
|
||||||
bitboards: [p_b_q, n_b_k, r_q_k, w],
|
bitboards: [p_b_q, n_b_k, r_q_k, black],
|
||||||
turn,
|
turn,
|
||||||
en_passant: _,
|
en_passant: _,
|
||||||
castling_rights: _,
|
castling_rights: _,
|
||||||
|
|
@ -1044,15 +1044,15 @@ fn aux_play_pawn_advance(
|
||||||
}
|
}
|
||||||
Role::Pawn => *p_b_q ^= from | to,
|
Role::Pawn => *p_b_q ^= from | to,
|
||||||
}
|
}
|
||||||
if let Color::White = *turn {
|
if let Color::Black = *turn {
|
||||||
*w ^= from | to;
|
*black ^= from | to;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn aux_play_castle(
|
fn aux_play_castle(
|
||||||
Setup {
|
Setup {
|
||||||
bitboards: [_, n_b_k, r_q_k, w],
|
bitboards: [_, n_b_k, r_q_k, black],
|
||||||
turn,
|
turn,
|
||||||
en_passant: _,
|
en_passant: _,
|
||||||
castling_rights,
|
castling_rights,
|
||||||
|
|
@ -1075,8 +1075,8 @@ fn aux_play_castle(
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Color::White = *turn {
|
if let Color::Black = *turn {
|
||||||
*w ^= king_flip | rook_flip;
|
*black ^= king_flip | rook_flip;
|
||||||
}
|
}
|
||||||
*n_b_k ^= king_flip;
|
*n_b_k ^= king_flip;
|
||||||
*r_q_k ^= king_flip | rook_flip;
|
*r_q_k ^= king_flip | rook_flip;
|
||||||
|
|
|
||||||
38
src/setup.rs
38
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).
|
/// [`from_text_record`](Setup::from_text_record) and [`to_text_record`](Setup::to_text_record).
|
||||||
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord)]
|
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord)]
|
||||||
pub struct Setup {
|
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) bitboards: [Bitboard; 4],
|
||||||
pub(crate) turn: Color,
|
pub(crate) turn: Color,
|
||||||
pub(crate) en_passant: OptionSquare,
|
pub(crate) en_passant: OptionSquare,
|
||||||
|
|
@ -221,15 +221,12 @@ impl Setup {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the occupancy of a square.
|
/// Returns the piece on the square, if any.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn get(&self, square: Square) -> Option<Piece> {
|
pub fn get(&self, square: Square) -> Option<Piece> {
|
||||||
Some(Piece {
|
Some(Piece {
|
||||||
role: self.role(square)?,
|
role: self.role(square)?,
|
||||||
color: match self.is_white(square) {
|
color: self.color(square),
|
||||||
true => Color::White,
|
|
||||||
false => Color::Black,
|
|
||||||
},
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -255,11 +252,11 @@ impl Setup {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn set(&mut self, square: Square, piece: Option<Piece>) {
|
pub fn set(&mut self, square: Square, piece: Option<Piece>) {
|
||||||
let mask = !square.bitboard();
|
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;
|
*p_b_q &= mask;
|
||||||
*n_b_k &= mask;
|
*n_b_k &= mask;
|
||||||
*r_q_k &= mask;
|
*r_q_k &= mask;
|
||||||
*w &= mask;
|
*black &= mask;
|
||||||
if let Some(piece) = piece {
|
if let Some(piece) = piece {
|
||||||
let to = square.bitboard();
|
let to = square.bitboard();
|
||||||
match piece.role {
|
match piece.role {
|
||||||
|
|
@ -286,8 +283,8 @@ impl Setup {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
match piece.color {
|
match piece.color {
|
||||||
Color::White => *w |= to,
|
Color::White => (),
|
||||||
Color::Black => (),
|
Color::Black => *black |= to,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -319,7 +316,7 @@ impl Setup {
|
||||||
/// - pawns, bishops and queens
|
/// - pawns, bishops and queens
|
||||||
/// - knights, bishops and kings
|
/// - knights, bishops and kings
|
||||||
/// - rooks, queens and kings
|
/// - rooks, queens and kings
|
||||||
/// - white pieces
|
/// - black pieces
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn bitboards(&self) -> [Bitboard; 4] {
|
pub fn bitboards(&self) -> [Bitboard; 4] {
|
||||||
self.bitboards
|
self.bitboards
|
||||||
|
|
@ -335,13 +332,13 @@ impl Setup {
|
||||||
/// is `rnbqkbnr/pppp1ppp/8/4p3/8/8/PPPPPPPP/RNBQKBNR w Qk e6`.
|
/// is `rnbqkbnr/pppp1ppp/8/4p3/8/8/PPPPPPPP/RNBQKBNR w Qk e6`.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn mirror(&self) -> Self {
|
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 {
|
Self {
|
||||||
bitboards: [
|
bitboards: [
|
||||||
p_b_q.mirror(),
|
p_b_q.mirror(),
|
||||||
n_b_k.mirror(),
|
n_b_k.mirror(),
|
||||||
r_q_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,
|
turn: !self.turn,
|
||||||
en_passant: self
|
en_passant: self
|
||||||
|
|
@ -359,9 +356,9 @@ impl Setup {
|
||||||
pub fn into_position(self) -> Result<Position, IllegalPosition> {
|
pub fn into_position(self) -> Result<Position, IllegalPosition> {
|
||||||
let mut reasons = IllegalPositionReasons::new();
|
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());
|
debug_assert!((p_b_q & n_b_k & r_q_k).is_empty());
|
||||||
|
|
||||||
let k = n_b_k & r_q_k;
|
let k = n_b_k & r_q_k;
|
||||||
|
|
@ -372,8 +369,8 @@ impl Setup {
|
||||||
let p = p_b_q ^ b ^ q;
|
let p = p_b_q ^ b ^ q;
|
||||||
let pieces = ByColor::with(|color| {
|
let pieces = ByColor::with(|color| {
|
||||||
let mask = match color {
|
let mask = match color {
|
||||||
Color::White => w,
|
Color::White => !black,
|
||||||
Color::Black => !w,
|
Color::Black => black,
|
||||||
};
|
};
|
||||||
ByRole::with(|role| {
|
ByRole::with(|role| {
|
||||||
mask & match 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]
|
#[inline]
|
||||||
pub(crate) fn is_white(&self, square: Square) -> bool {
|
pub(crate) fn color(&self, square: Square) -> Color {
|
||||||
let [_, _, _, w] = self.bitboards;
|
let [_, _, _, black] = self.bitboards;
|
||||||
w.contains(square)
|
unsafe { Color::new_unchecked(((black & square.bitboard()).0 >> square as u8) as u8) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue