From 066d4428231629605399607ad2173a12de3f38e5 Mon Sep 17 00:00:00 2001 From: Bruno BELANYI Date: Fri, 22 Jul 2022 18:42:05 +0200 Subject: [PATCH] Add magic bitboard generation --- src/movegen/magic/mod.rs | 1 - src/movegen/wizardry/generation.rs | 74 ++++++++++++++++++++++++++++++ src/movegen/wizardry/mask.rs | 2 - src/movegen/wizardry/mod.rs | 1 + 4 files changed, 75 insertions(+), 3 deletions(-) create mode 100644 src/movegen/wizardry/generation.rs diff --git a/src/movegen/magic/mod.rs b/src/movegen/magic/mod.rs index f9d01d1..242a0b4 100644 --- a/src/movegen/magic/mod.rs +++ b/src/movegen/magic/mod.rs @@ -14,7 +14,6 @@ pub struct Magic { impl Magic { /// Compute the index into the magics database for this set of `blockers`. - #[allow(unused)] // FIXME: remove once used 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; diff --git a/src/movegen/wizardry/generation.rs b/src/movegen/wizardry/generation.rs new file mode 100644 index 0000000..a5e47e2 --- /dev/null +++ b/src/movegen/wizardry/generation.rs @@ -0,0 +1,74 @@ +use crate::board::{Bitboard, Square}; +use crate::movegen::bishop::bishop_moves; +use crate::movegen::rook::rook_moves; +use crate::movegen::Magic; + +use super::mask::{generate_bishop_mask, generate_rook_mask}; + +/// A trait to represent RNG for u64 values. +#[allow(unused)] // FIXME: remove when used +pub(crate) trait RandGen { + fn gen(&mut self) -> u64; +} + +type MagicGenerationType = (Vec, Vec); + +#[allow(unused)] // FIXME: remove when used +pub fn generate_bishop_magics(rng: &mut dyn RandGen) -> MagicGenerationType { + generate_magics(rng, generate_bishop_mask, bishop_moves) +} + +#[allow(unused)] // FIXME: remove when used +pub fn generate_rook_magics(rng: &mut dyn RandGen) -> MagicGenerationType { + generate_magics(rng, generate_rook_mask, rook_moves) +} + +fn generate_magics( + rng: &mut dyn RandGen, + mask_fn: impl Fn(Square) -> Bitboard, + moves_fn: impl Fn(Square, Bitboard) -> Bitboard, +) -> MagicGenerationType { + let mut magics = Vec::new(); + let mut boards = Vec::new(); + + for square in Square::iter() { + let mask = mask_fn(square); + + let occupancy_to_moves: Vec<_> = mask + .iter_power_set() + .map(|occupancy| (occupancy, moves_fn(square, occupancy))) + .collect(); + + 'candidate_search: loop { + let mut candidate = Magic { + magic: magic_candidate(rng), + offset: 0, + mask, + shift: (64 - mask.count()) as u8, + }; + let mut candidate_moves = vec![Bitboard::EMPTY; occupancy_to_moves.len()]; + + for (occupancy, moves) in occupancy_to_moves.iter().cloned() { + let index = candidate.get_index(occupancy); + // Non-constructive collision, try with another candidate + if !candidate_moves[index].is_empty() && candidate_moves[index] != moves { + continue 'candidate_search; + } + candidate_moves[index] = moves; + } + + // We have filled all candidate boards, record the correct offset and add the moves + candidate.offset = boards.len(); + magics.push(candidate); + boards.append(&mut candidate_moves); + break; + } + } + + (magics, boards) +} + +fn magic_candidate(rng: &mut dyn RandGen) -> u64 { + // Few bits makes for better candidates + rng.gen() & rng.gen() & rng.gen() +} diff --git a/src/movegen/wizardry/mask.rs b/src/movegen/wizardry/mask.rs index af1b8fa..aca9f4f 100644 --- a/src/movegen/wizardry/mask.rs +++ b/src/movegen/wizardry/mask.rs @@ -3,7 +3,6 @@ use crate::movegen::bishop::bishop_moves; use crate::movegen::rook::rook_moves; /// Compute the relevancy mask for a bishop on a given [Square]. -#[allow(unused)] // FIXME: remove once used pub fn generate_bishop_mask(square: Square) -> Bitboard { let rays = bishop_moves(square, Bitboard::EMPTY); @@ -16,7 +15,6 @@ pub fn generate_bishop_mask(square: Square) -> Bitboard { } /// Compute the relevancy mask for a rook on a given [Square]. -#[allow(unused)] // FIXME: remove once used pub fn generate_rook_mask(square: Square) -> Bitboard { let rays = rook_moves(square, Bitboard::EMPTY); diff --git a/src/movegen/wizardry/mod.rs b/src/movegen/wizardry/mod.rs index f6053c6..8b5ba4e 100644 --- a/src/movegen/wizardry/mod.rs +++ b/src/movegen/wizardry/mod.rs @@ -1 +1,2 @@ +mod generation; mod mask;