2022-07-24 13:40:01 +02:00
|
|
|
pub(crate) mod generation;
|
2022-07-22 10:37:56 +02:00
|
|
|
mod mask;
|
2024-03-29 02:43:27 +01:00
|
|
|
|
2024-03-29 03:56:01 +01:00
|
|
|
use crate::board::{Bitboard, Square};
|
2024-03-29 02:43:27 +01:00
|
|
|
|
|
|
|
/// A type representing the magic board indexing a given [crate::board::Square].
|
2024-03-29 03:54:24 +01:00
|
|
|
#[derive(Clone, Debug)]
|
2024-03-29 03:55:03 +01:00
|
|
|
pub(crate) struct Magic {
|
2024-03-29 02:43:27 +01:00
|
|
|
/// Magic number.
|
|
|
|
pub(crate) magic: u64,
|
|
|
|
/// Base offset into the magic square table.
|
|
|
|
pub(crate) offset: usize,
|
|
|
|
/// Mask to apply to the blocker board before applying the magic.
|
|
|
|
pub(crate) mask: Bitboard,
|
|
|
|
/// Length of the resulting mask after applying the magic.
|
|
|
|
pub(crate) shift: u8,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Magic {
|
|
|
|
/// Compute the index into the magics database for this set of `blockers`.
|
|
|
|
pub fn get_index(&self, blockers: Bitboard) -> usize {
|
|
|
|
let relevant_occupancy = (blockers & self.mask).0;
|
|
|
|
let base_index = ((relevant_occupancy.wrapping_mul(self.magic)) >> self.shift) as usize;
|
|
|
|
base_index + self.offset
|
|
|
|
}
|
|
|
|
}
|
2024-03-29 03:56:01 +01:00
|
|
|
|
|
|
|
/// A type encapsulating a database of [Magic] bitboard moves.
|
|
|
|
#[derive(Clone, Debug)]
|
|
|
|
#[allow(unused)] // FIXME: remove when used
|
|
|
|
pub(crate) struct MagicMoves {
|
|
|
|
magics: Vec<Magic>,
|
|
|
|
moves: Vec<Bitboard>,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[allow(unused)] // FIXME: remove when used
|
|
|
|
impl MagicMoves {
|
|
|
|
/// Initialize a new [MagicMoves] given a matching list of [Magic] and its corresponding moves
|
|
|
|
/// as a [Bitboard].
|
|
|
|
///
|
|
|
|
/// # Safety
|
|
|
|
///
|
|
|
|
/// This should only be called with values generated by [crate::movegen::wizardry::generation].
|
|
|
|
pub unsafe fn new(magics: Vec<Magic>, moves: Vec<Bitboard>) -> Self {
|
|
|
|
Self { magics, moves }
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Get the set of valid moves for a piece standing on a [Square], given a set of blockers.
|
|
|
|
pub fn query(&self, square: Square, blockers: Bitboard) -> Bitboard {
|
|
|
|
// SAFETY: indices are in range by construction
|
|
|
|
unsafe {
|
|
|
|
let index = self
|
|
|
|
.magics
|
|
|
|
.get_unchecked(square.index())
|
|
|
|
.get_index(blockers);
|
|
|
|
*self.moves.get_unchecked(index)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|