diff --git a/src/movegen/magic/magic.rs b/src/movegen/magic/magic.rs index 6fe0400..f59bde2 100644 --- a/src/movegen/magic/magic.rs +++ b/src/movegen/magic/magic.rs @@ -1,7 +1,6 @@ use crate::board::Bitboard; /// A type representing the magic board indexing a given [Square]. -#[allow(unused)] // FIXME: remove once used pub struct Magic { /// Magic number. pub(crate) magic: u64, @@ -14,7 +13,6 @@ pub struct Magic { } impl Magic { - #[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..48e80e1 --- /dev/null +++ b/src/movegen/wizardry/generation.rs @@ -0,0 +1,68 @@ +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}; + +type MagicGenerationType = (Vec, Vec); + +#[allow(unused)] // FIXME: remove when used +pub fn generate_bishop_magics(rng: &mut dyn random::Source) -> MagicGenerationType { + generate_magics(rng, generate_bishop_mask, bishop_moves) +} + +#[allow(unused)] // FIXME: remove when used +pub fn generate_rook_magics(rng: &mut dyn random::Source) -> MagicGenerationType { + generate_magics(rng, generate_rook_mask, rook_moves) +} + +fn generate_magics( + rng: &mut dyn random::Source, + mask_fn: impl Fn(Square) -> Bitboard, + moves_fn: impl Fn(Square, Bitboard) -> Bitboard, +) -> MagicGenerationType { + let mut offset = 0; + + let mut magics = Vec::new(); + let mut boards = Vec::new(); + + for square in Square::iter() { + let mask = mask_fn(square); + let mut candidate: Magic; + let potential_occupancy: Vec<_> = mask.iter_power_set().collect(); + let moves_len = potential_occupancy.len(); + + 'candidate_search: loop { + candidate = Magic { + magic: magic_candidate(rng), + offset, + mask, + shift: (64 - mask.count()) as u8, + }; + let mut candidate_moves = Vec::new(); + candidate_moves.resize(moves_len, Bitboard::EMPTY); + + for occupancy in potential_occupancy.iter().cloned() { + let index = candidate.get_index(occupancy); + let moves = moves_fn(square, occupancy); + if candidate_moves[index] != Bitboard::EMPTY && candidate_moves[index] != moves { + continue 'candidate_search; + } + candidate_moves[index] = moves; + } + + boards.append(&mut candidate_moves); + break; + } + + magics.push(candidate); + offset += moves_len; + } + + (magics, boards) +} + +fn magic_candidate(rng: &mut dyn random::Source) -> u64 { + rng.read_u64() & rng.read_u64() & rng.read_u64() +} diff --git a/src/movegen/wizardry/mask.rs b/src/movegen/wizardry/mask.rs index 13d7cd6..0c0bbdf 100644 --- a/src/movegen/wizardry/mask.rs +++ b/src/movegen/wizardry/mask.rs @@ -2,7 +2,6 @@ use crate::board::{Bitboard, File, Rank, Square}; use crate::movegen::bishop::bishop_moves; use crate::movegen::rook::rook_moves; -#[allow(unused)] // FIXME: remove once used pub fn generate_bishop_mask(square: Square) -> Bitboard { let rays = bishop_moves(square, Bitboard::EMPTY); @@ -14,7 +13,6 @@ pub fn generate_bishop_mask(square: Square) -> Bitboard { rays - mask } -#[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;