const lookup table
This commit is contained in:
parent
752150107e
commit
0d22c59cc3
8 changed files with 573 additions and 542 deletions
195
src/magics.rs
195
src/magics.rs
|
|
@ -1,193 +1,7 @@
|
|||
use crate::bitboard::*;
|
||||
use crate::board::*;
|
||||
use crate::rays::Rays;
|
||||
use crate::board::Square;
|
||||
|
||||
const BISHOP_SHR: u8 = 55;
|
||||
const ROOK_SHR: u8 = 52;
|
||||
|
||||
pub(crate) struct Magics {
|
||||
bishop: BySquare<Magic>,
|
||||
rook: BySquare<Magic>,
|
||||
table: Box<[Bitboard]>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
struct Magic {
|
||||
premask: Bitboard,
|
||||
factor: u64,
|
||||
offset: isize,
|
||||
}
|
||||
|
||||
impl Magics {
|
||||
pub(crate) fn compute(rays: &Rays) -> Self {
|
||||
let mut data = Vec::new();
|
||||
|
||||
let mut aux =
|
||||
|shr,
|
||||
factors: fn(Square) -> u64,
|
||||
make_table: fn(&Rays, Square) -> (Bitboard, Vec<(Bitboard, Bitboard)>)| {
|
||||
BySquare::new(|square| {
|
||||
let (premask, table) = make_table(rays, square);
|
||||
let factor = factors(square);
|
||||
let offset = fill_table(&mut data, shr, factor, table);
|
||||
Magic {
|
||||
premask,
|
||||
factor,
|
||||
offset,
|
||||
}
|
||||
})
|
||||
};
|
||||
|
||||
let bishop = aux(BISHOP_SHR, bishop_factors, make_bishop_table);
|
||||
let rook = aux(ROOK_SHR, rook_factors, make_rook_table);
|
||||
|
||||
let mut table = Box::new_uninit_slice(data.len());
|
||||
for (i, entry) in data.into_iter().enumerate() {
|
||||
table[i].write(entry);
|
||||
}
|
||||
|
||||
Self {
|
||||
bishop,
|
||||
rook,
|
||||
table: unsafe { table.assume_init() },
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn bishop(&self, square: Square, blockers: Bitboard) -> Bitboard {
|
||||
unsafe { self.get_unchecked(BISHOP_SHR, *self.bishop.get(square), blockers) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn rook(&self, square: Square, blockers: Bitboard) -> Bitboard {
|
||||
unsafe { self.get_unchecked(ROOK_SHR, *self.rook.get(square), blockers) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn get_unchecked(&self, shr: u8, magic: Magic, blockers: Bitboard) -> Bitboard {
|
||||
let Magic {
|
||||
premask,
|
||||
factor,
|
||||
offset,
|
||||
} = magic;
|
||||
*self.table.get_unchecked(
|
||||
((hash(shr, factor, blockers | premask) as isize).unchecked_add(offset)) as usize,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fn fill_table(
|
||||
data: &mut Vec<Bitboard>,
|
||||
shr: u8,
|
||||
factor: u64,
|
||||
table: Vec<(Bitboard, Bitboard)>,
|
||||
) -> isize {
|
||||
let offset = data.len() as isize
|
||||
- table
|
||||
.iter()
|
||||
.map(|(x, _)| hash(shr, factor, *x) as isize)
|
||||
.min()
|
||||
.unwrap();
|
||||
for (x, y) in &table {
|
||||
let i = (hash(shr, factor, *x) as isize + offset) as usize;
|
||||
while data.len() <= i {
|
||||
data.push(Bitboard::new());
|
||||
}
|
||||
if data[i] != Bitboard::new() && data[i] != *y {
|
||||
panic!();
|
||||
}
|
||||
data[i] = *y;
|
||||
}
|
||||
offset
|
||||
}
|
||||
|
||||
fn make_bishop_table(rays: &Rays, square: Square) -> (Bitboard, Vec<(Bitboard, Bitboard)>) {
|
||||
let mut premask = Bitboard::new();
|
||||
for direction in [
|
||||
Direction::NorthWest,
|
||||
Direction::SouthWest,
|
||||
Direction::SouthEast,
|
||||
Direction::NorthEast,
|
||||
] {
|
||||
premask |= rays.ray(square, direction);
|
||||
}
|
||||
premask &= !Rank::First.bitboard();
|
||||
premask &= !Rank::Eighth.bitboard();
|
||||
premask &= !File::A.bitboard();
|
||||
premask &= !File::H.bitboard();
|
||||
|
||||
let mut table = make_table(premask, |blockers| {
|
||||
let mut res = Bitboard::new();
|
||||
for direction in [
|
||||
Direction::NorthWest,
|
||||
Direction::SouthWest,
|
||||
Direction::SouthEast,
|
||||
Direction::NorthEast,
|
||||
] {
|
||||
res |= rays.blocked(square, direction, blockers);
|
||||
}
|
||||
res
|
||||
});
|
||||
|
||||
premask = !premask;
|
||||
for (x, _) in &mut table {
|
||||
*x |= premask;
|
||||
}
|
||||
|
||||
(premask, table)
|
||||
}
|
||||
|
||||
fn make_rook_table(rays: &Rays, square: Square) -> (Bitboard, Vec<(Bitboard, Bitboard)>) {
|
||||
let mut premask = Bitboard::new();
|
||||
premask |= rays.ray(square, Direction::North) & !Rank::Eighth.bitboard();
|
||||
premask |= rays.ray(square, Direction::West) & !File::A.bitboard();
|
||||
premask |= rays.ray(square, Direction::South) & !Rank::First.bitboard();
|
||||
premask |= rays.ray(square, Direction::East) & !File::H.bitboard();
|
||||
|
||||
let mut table = make_table(premask, |blockers| {
|
||||
let mut res = Bitboard::new();
|
||||
for direction in [
|
||||
Direction::North,
|
||||
Direction::West,
|
||||
Direction::South,
|
||||
Direction::East,
|
||||
] {
|
||||
res |= rays.blocked(square, direction, blockers);
|
||||
}
|
||||
res
|
||||
});
|
||||
|
||||
premask = !premask;
|
||||
for (x, _) in &mut table {
|
||||
*x |= premask;
|
||||
}
|
||||
|
||||
(premask, table)
|
||||
}
|
||||
|
||||
fn make_table<T, F>(premask: Bitboard, f: F) -> Vec<(Bitboard, T)>
|
||||
where
|
||||
F: Fn(Bitboard) -> T,
|
||||
{
|
||||
let mut res = Vec::new();
|
||||
let mut subset: u64 = 0;
|
||||
loop {
|
||||
subset = subset.wrapping_sub(premask.0) & premask.0;
|
||||
let x = Bitboard(subset);
|
||||
let y = f(x);
|
||||
res.push((x, y));
|
||||
if subset == 0 {
|
||||
break;
|
||||
}
|
||||
}
|
||||
res
|
||||
}
|
||||
|
||||
fn hash(shr: u8, factor: u64, x: Bitboard) -> usize {
|
||||
(x.0.wrapping_mul(factor) >> shr) as usize
|
||||
}
|
||||
|
||||
fn bishop_factors(square: Square) -> u64 {
|
||||
pub(crate) const BISHOP_SHR: u8 = 55;
|
||||
pub(crate) const fn bishop_factor(square: Square) -> u64 {
|
||||
match square {
|
||||
Square::A1 => 0x0000404040404040,
|
||||
Square::B1 => 0x0040C100081000E8,
|
||||
|
|
@ -256,7 +70,8 @@ fn bishop_factors(square: Square) -> u64 {
|
|||
}
|
||||
}
|
||||
|
||||
fn rook_factors(square: Square) -> u64 {
|
||||
pub(crate) const ROOK_SHR: u8 = 52;
|
||||
pub(crate) const fn rook_factor(square: Square) -> u64 {
|
||||
match square {
|
||||
Square::A1 => 0x002000A28110000C,
|
||||
Square::B1 => 0x0018000C01060001,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue