[board] Implement a BitScanner on u64

This struct implements an Iterator that returns the positions of the 1 bits in the u64.
BitBoard takes this iterator and maps it into Squares in the pieces() method.

This is laying the groundwork for an iterator over the pieces in a Position. 👀
This commit is contained in:
Eryn Wells 2023-12-23 23:04:18 -07:00
parent a2f88f0fde
commit 1da827a3bb
3 changed files with 91 additions and 23 deletions

View file

@ -0,0 +1,67 @@
// Eryn Wells <eryn@erynwells.me>
use super::BitBoard;
use crate::square::Square;
pub(crate) struct BitScanner {
bits: u64,
shift: u32,
}
impl BitScanner {
pub(crate) fn new(bits: u64) -> BitScanner {
BitScanner { bits, shift: 0 }
}
}
impl Iterator for BitScanner {
type Item = u32;
fn next(&mut self) -> Option<Self::Item> {
if self.shift == u64::BITS {
return None;
}
let shifted_bits = self.bits << self.shift;
let leading_zeros = shifted_bits.leading_zeros();
if leading_zeros == u64::BITS {
self.shift = leading_zeros;
return None;
}
let position = u64::BITS - (self.shift + leading_zeros + 1);
// Shift 1 additional place to account for the 1 that `leading_zeros` found.
self.shift += leading_zeros + 1;
Some(position)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn zero() {
let mut scanner = BitScanner::new(0);
assert_eq!(scanner.next(), None);
}
#[test]
fn one() {
let mut scanner = BitScanner::new(1);
assert_eq!(scanner.next(), Some(0));
assert_eq!(scanner.next(), None);
}
#[test]
fn complex() {
let mut scanner = BitScanner::new(0b11000101);
assert_eq!(scanner.next(), Some(7));
assert_eq!(scanner.next(), Some(6));
assert_eq!(scanner.next(), Some(2));
assert_eq!(scanner.next(), Some(0));
assert_eq!(scanner.next(), None);
}
}