[bitboard] Move everything in board::bitboard to the bitboard crate
This commit is contained in:
parent
32100b9553
commit
625bfb2446
7 changed files with 25 additions and 25 deletions
189
bitboard/src/library.rs
Normal file
189
bitboard/src/library.rs
Normal file
|
@ -0,0 +1,189 @@
|
|||
// Eryn Wells <eryn@erynwells.me>
|
||||
|
||||
use super::BitBoard;
|
||||
use chess_core::{Direction, Square};
|
||||
use std::sync::Once;
|
||||
|
||||
pub(super) const RANKS: [BitBoard; 8] = [
|
||||
BitBoard(0xFF << 0 * 8),
|
||||
BitBoard(0xFF << 1 * 8),
|
||||
BitBoard(0xFF << 2 * 8),
|
||||
BitBoard(0xFF << 3 * 8),
|
||||
BitBoard(0xFF << 4 * 8),
|
||||
BitBoard(0xFF << 5 * 8),
|
||||
BitBoard(0xFF << 6 * 8),
|
||||
BitBoard(0xFF << 7 * 8),
|
||||
];
|
||||
|
||||
pub(super) const FILES: [BitBoard; 8] = [
|
||||
BitBoard(0x0101010101010101 << 0),
|
||||
BitBoard(0x0101010101010101 << 1),
|
||||
BitBoard(0x0101010101010101 << 2),
|
||||
BitBoard(0x0101010101010101 << 3),
|
||||
BitBoard(0x0101010101010101 << 4),
|
||||
BitBoard(0x0101010101010101 << 5),
|
||||
BitBoard(0x0101010101010101 << 6),
|
||||
BitBoard(0x0101010101010101 << 7),
|
||||
];
|
||||
|
||||
pub(super) const LIGHT_SQUARES: BitBoard =
|
||||
BitBoard(0x5555 | 0x5555 << 16 | 0x5555 << 32 | 0x5555 << 48);
|
||||
pub(super) const DARK_SQUARES: BitBoard = BitBoard(!LIGHT_SQUARES.0);
|
||||
|
||||
pub(super) fn library() -> &'static MoveLibrary {
|
||||
static MOVE_LIBRARY_INIT: Once = Once::new();
|
||||
static mut MOVE_LIBRARY: MoveLibrary = MoveLibrary::new();
|
||||
|
||||
unsafe {
|
||||
MOVE_LIBRARY_INIT.call_once(|| {
|
||||
MOVE_LIBRARY.init();
|
||||
});
|
||||
|
||||
&MOVE_LIBRARY
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! library_getter {
|
||||
($name:ident) => {
|
||||
pub(super) fn $name(&self, sq: Square) -> BitBoard {
|
||||
self.$name[sq as usize]
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(super) struct MoveLibrary {
|
||||
// Rays
|
||||
rays: [[BitBoard; 8]; Square::NUM],
|
||||
|
||||
// Piecewise move tables
|
||||
knight_moves: [BitBoard; 64],
|
||||
bishop_moves: [BitBoard; 64],
|
||||
rook_moves: [BitBoard; 64],
|
||||
queen_moves: [BitBoard; 64],
|
||||
king_moves: [BitBoard; 64],
|
||||
}
|
||||
|
||||
impl MoveLibrary {
|
||||
const fn new() -> MoveLibrary {
|
||||
MoveLibrary {
|
||||
rays: [[BitBoard::empty(); 8]; Square::NUM],
|
||||
knight_moves: [BitBoard::empty(); 64],
|
||||
bishop_moves: [BitBoard::empty(); 64],
|
||||
rook_moves: [BitBoard::empty(); 64],
|
||||
queen_moves: [BitBoard::empty(); 64],
|
||||
king_moves: [BitBoard::empty(); 64],
|
||||
}
|
||||
}
|
||||
|
||||
fn init(&mut self) {
|
||||
for sq in Square::ALL {
|
||||
self.init_orthogonal_rays(sq);
|
||||
self.init_diagonal_rays(sq);
|
||||
self.init_knight_moves(sq as usize);
|
||||
self.init_bishop_moves(sq);
|
||||
self.init_rook_moves(sq);
|
||||
self.init_queen_moves(sq);
|
||||
self.init_king_moves(sq as usize);
|
||||
}
|
||||
}
|
||||
|
||||
fn init_orthogonal_rays(&mut self, sq: Square) {
|
||||
let sq_bb: BitBoard = sq.into();
|
||||
let rays = &mut self.rays[sq as usize];
|
||||
rays[Direction::North as usize] = Self::generate_ray(sq_bb, BitBoard::shift_north_one);
|
||||
rays[Direction::South as usize] = Self::generate_ray(sq_bb, BitBoard::shift_south_one);
|
||||
rays[Direction::East as usize] = Self::generate_ray(sq_bb, BitBoard::shift_east_one);
|
||||
rays[Direction::West as usize] = Self::generate_ray(sq_bb, BitBoard::shift_west_one);
|
||||
}
|
||||
|
||||
fn init_diagonal_rays(&mut self, sq: Square) {
|
||||
let sq_bb: BitBoard = sq.into();
|
||||
let rays = &mut self.rays[sq as usize];
|
||||
rays[Direction::NorthEast as usize] =
|
||||
Self::generate_ray(sq_bb, BitBoard::shift_north_east_one);
|
||||
rays[Direction::NorthWest as usize] =
|
||||
Self::generate_ray(sq_bb, BitBoard::shift_north_west_one);
|
||||
rays[Direction::SouthWest as usize] =
|
||||
Self::generate_ray(sq_bb, BitBoard::shift_south_west_one);
|
||||
rays[Direction::SouthEast as usize] =
|
||||
Self::generate_ray(sq_bb, BitBoard::shift_south_east_one);
|
||||
}
|
||||
|
||||
fn init_king_moves(&mut self, idx: usize) {
|
||||
let king = BitBoard::new(1 << idx);
|
||||
let mut attacks = king.shift_east_one() | king.shift_west_one();
|
||||
|
||||
let king = king | attacks;
|
||||
attacks |= king.shift_north_one() | king.shift_south_one();
|
||||
|
||||
self.king_moves[idx] = attacks;
|
||||
}
|
||||
|
||||
/// Calculate bitboards representing knight moves from each square on the
|
||||
/// board. The algorithm is described on the [Chess Programming Wiki][cpw].
|
||||
///
|
||||
/// [cpw]: https://www.chessprogramming.org/Knight_Pattern
|
||||
fn init_knight_moves(&mut self, idx: usize) {
|
||||
let knight = BitBoard::new(1 << idx);
|
||||
|
||||
let east = knight.shift_east_one();
|
||||
let west = knight.shift_west_one();
|
||||
|
||||
let mut attacks = (east | west).shift_north(2);
|
||||
attacks |= (east | west).shift_south(2);
|
||||
|
||||
let east = east.shift_east_one();
|
||||
let west = west.shift_west_one();
|
||||
|
||||
attacks |= (east | west).shift_north_one();
|
||||
attacks |= (east | west).shift_south_one();
|
||||
|
||||
self.knight_moves[idx] = attacks;
|
||||
}
|
||||
|
||||
fn init_bishop_moves(&mut self, sq: Square) {
|
||||
let rays = self.rays[sq as usize];
|
||||
self.bishop_moves[sq as usize] = rays[Direction::NorthWest as usize]
|
||||
| rays[Direction::NorthEast as usize]
|
||||
| rays[Direction::SouthEast as usize]
|
||||
| rays[Direction::SouthWest as usize];
|
||||
}
|
||||
|
||||
fn init_rook_moves(&mut self, sq: Square) {
|
||||
let rays = self.rays[sq as usize];
|
||||
self.rook_moves[sq as usize] = rays[Direction::North as usize]
|
||||
| rays[Direction::East as usize]
|
||||
| rays[Direction::South as usize]
|
||||
| rays[Direction::West as usize];
|
||||
}
|
||||
|
||||
fn init_queen_moves(&mut self, sq: Square) {
|
||||
let rook_moves = self.rook_moves[sq as usize];
|
||||
let bishop_moves = self.bishop_moves[sq as usize];
|
||||
self.queen_moves[sq as usize] = rook_moves | bishop_moves;
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn generate_ray(sq: BitBoard, shift: fn(&BitBoard) -> BitBoard) -> BitBoard {
|
||||
let mut ray = BitBoard::empty();
|
||||
|
||||
let mut iter = shift(&sq);
|
||||
while !iter.is_empty() {
|
||||
ray |= iter;
|
||||
iter = shift(&iter);
|
||||
}
|
||||
|
||||
ray
|
||||
}
|
||||
|
||||
pub(super) fn ray(&self, sq: Square, dir: Direction) -> BitBoard {
|
||||
self.rays[sq as usize][dir as usize]
|
||||
}
|
||||
|
||||
library_getter!(knight_moves);
|
||||
library_getter!(bishop_moves);
|
||||
library_getter!(rook_moves);
|
||||
library_getter!(queen_moves);
|
||||
library_getter!(king_moves);
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue