diff --git a/src/movegen/magic/magic.rs b/src/movegen/magic/magic.rs deleted file mode 100644 index f59bde2..0000000 --- a/src/movegen/magic/magic.rs +++ /dev/null @@ -1,21 +0,0 @@ -use crate::board::Bitboard; - -/// A type representing the magic board indexing a given [Square]. -pub struct Magic { - /// 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 { - 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 - } -} diff --git a/src/movegen/magic/mod.rs b/src/movegen/magic/mod.rs index 068c6e7..251a5d9 100644 --- a/src/movegen/magic/mod.rs +++ b/src/movegen/magic/mod.rs @@ -1,2 +1,21 @@ -pub mod magic; -pub use magic::*; +use crate::board::Bitboard; + +/// A type representing the magic board indexing a given [crate::board::Square]. +pub struct Magic { + /// 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 { + 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 + } +} diff --git a/src/movegen/wizardry/generation.rs b/src/movegen/wizardry/generation.rs index 48e80e1..ee75d57 100644 --- a/src/movegen/wizardry/generation.rs +++ b/src/movegen/wizardry/generation.rs @@ -22,42 +22,42 @@ fn generate_magics( 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(); + + let occupancy_to_moves: Vec<_> = mask + .iter_power_set() + .map(|occupancy| (occupancy, moves_fn(square, occupancy))) + .collect(); 'candidate_search: loop { candidate = Magic { magic: magic_candidate(rng), - offset, + offset: 0, mask, shift: (64 - mask.count()) as u8, }; - let mut candidate_moves = Vec::new(); - candidate_moves.resize(moves_len, Bitboard::EMPTY); + let mut candidate_moves = vec![Bitboard::EMPTY; occupancy_to_moves.len()]; - for occupancy in potential_occupancy.iter().cloned() { + for (occupancy, moves) in occupancy_to_moves.iter().cloned() { let index = candidate.get_index(occupancy); - let moves = moves_fn(square, occupancy); + // Non-constructive collision, try with another candidate if candidate_moves[index] != Bitboard::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(); boards.append(&mut candidate_moves); + magics.push(candidate); break; } - - magics.push(candidate); - offset += moves_len; } (magics, boards)