WIP
This commit is contained in:
parent
d5cdf273c8
commit
091cc99cb3
42 changed files with 805 additions and 1662 deletions
|
@ -1,8 +1,10 @@
|
|||
// Eryn Wells <eryn@erynwells.me>
|
||||
|
||||
use chessfriend_core::Square;
|
||||
|
||||
macro_rules! bit_scanner {
|
||||
($name:ident) => {
|
||||
pub(crate) struct $name {
|
||||
pub struct $name {
|
||||
bits: u64,
|
||||
shift: usize,
|
||||
}
|
||||
|
@ -18,8 +20,15 @@ macro_rules! bit_scanner {
|
|||
bit_scanner!(LeadingBitScanner);
|
||||
bit_scanner!(TrailingBitScanner);
|
||||
|
||||
fn _index_to_square(index: usize) -> Square {
|
||||
unsafe {
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
Square::from_index_unchecked(index as u8)
|
||||
}
|
||||
}
|
||||
|
||||
impl Iterator for LeadingBitScanner {
|
||||
type Item = usize;
|
||||
type Item = Square;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
let u64bits = u64::BITS as usize;
|
||||
|
@ -40,12 +49,12 @@ impl Iterator for LeadingBitScanner {
|
|||
// Shift 1 additional place to account for the 1 that `leading_zeros` found.
|
||||
self.shift += leading_zeros + 1;
|
||||
|
||||
Some(position)
|
||||
Some(_index_to_square(position))
|
||||
}
|
||||
}
|
||||
|
||||
impl Iterator for TrailingBitScanner {
|
||||
type Item = usize;
|
||||
type Item = Square;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
let u64bits = u64::BITS as usize;
|
||||
|
@ -66,7 +75,7 @@ impl Iterator for TrailingBitScanner {
|
|||
// Shift 1 additional place to account for the 1 that `leading_zeros` found.
|
||||
self.shift += trailing_zeros + 1;
|
||||
|
||||
Some(position)
|
||||
Some(_index_to_square(position))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -83,17 +92,17 @@ mod tests {
|
|||
#[test]
|
||||
fn leading_one() {
|
||||
let mut scanner = LeadingBitScanner::new(1);
|
||||
assert_eq!(scanner.next(), Some(0));
|
||||
assert_eq!(scanner.next(), Some(Square::A1));
|
||||
assert_eq!(scanner.next(), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn leading_complex() {
|
||||
let mut scanner = LeadingBitScanner::new(0b_1100_0101);
|
||||
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(), Some(Square::H1));
|
||||
assert_eq!(scanner.next(), Some(Square::G1));
|
||||
assert_eq!(scanner.next(), Some(Square::C1));
|
||||
assert_eq!(scanner.next(), Some(Square::A1));
|
||||
assert_eq!(scanner.next(), None);
|
||||
}
|
||||
|
||||
|
@ -106,17 +115,17 @@ mod tests {
|
|||
#[test]
|
||||
fn trailing_one() {
|
||||
let mut scanner = TrailingBitScanner::new(1);
|
||||
assert_eq!(scanner.next(), Some(0));
|
||||
assert_eq!(scanner.next(), Some(Square::A1));
|
||||
assert_eq!(scanner.next(), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn trailing_complex() {
|
||||
let mut scanner = TrailingBitScanner::new(0b_1100_0101);
|
||||
assert_eq!(scanner.next(), Some(0));
|
||||
assert_eq!(scanner.next(), Some(2));
|
||||
assert_eq!(scanner.next(), Some(6));
|
||||
assert_eq!(scanner.next(), Some(7));
|
||||
assert_eq!(scanner.next(), Some(Square::A1));
|
||||
assert_eq!(scanner.next(), Some(Square::C1));
|
||||
assert_eq!(scanner.next(), Some(Square::G1));
|
||||
assert_eq!(scanner.next(), Some(Square::H1));
|
||||
assert_eq!(scanner.next(), None);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -144,7 +144,7 @@ impl BitBoard {
|
|||
self.0 != 0
|
||||
}
|
||||
|
||||
/// Returns `true` if this [BitBoard] has the bit corresponding to `square` set.
|
||||
/// Returns `true` if this [`BitBoard`] has the bit corresponding to `square` set.
|
||||
///
|
||||
/// ## Examples
|
||||
///
|
||||
|
@ -179,7 +179,7 @@ impl BitBoard {
|
|||
self.0.count_ones()
|
||||
}
|
||||
|
||||
/// Set a square in this [BitBoard] by toggling the corresponding bit to 1.
|
||||
/// Set a square in this [`BitBoard`] by toggling the corresponding bit to 1.
|
||||
/// This always succeeds, even if the bit was already set.
|
||||
///
|
||||
/// ## Examples
|
||||
|
@ -237,21 +237,20 @@ impl BitBoard {
|
|||
&self,
|
||||
direction: &IterationDirection,
|
||||
) -> Box<dyn Iterator<Item = Square>> {
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
fn index_to_square(index: usize) -> Square {
|
||||
unsafe { Square::from_index_unchecked(index as u8) }
|
||||
}
|
||||
|
||||
match direction {
|
||||
IterationDirection::Leading => {
|
||||
Box::new(LeadingBitScanner::new(self.0).map(index_to_square))
|
||||
}
|
||||
IterationDirection::Trailing => {
|
||||
Box::new(TrailingBitScanner::new(self.0).map(index_to_square))
|
||||
}
|
||||
IterationDirection::Leading => Box::new(self.occupied_squares_leading()),
|
||||
IterationDirection::Trailing => Box::new(self.occupied_squares_trailing()),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn occupied_squares_leading(&self) -> LeadingBitScanner {
|
||||
LeadingBitScanner::new(self.0)
|
||||
}
|
||||
|
||||
pub fn occupied_squares_trailing(&self) -> TrailingBitScanner {
|
||||
TrailingBitScanner::new(self.0)
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn first_occupied_square(&self, direction: &IterationDirection) -> Option<Square> {
|
||||
match direction {
|
||||
|
@ -264,7 +263,7 @@ impl BitBoard {
|
|||
/// board, starting at the leading (most-significant) end of the board. If
|
||||
/// the board is empty, returns `None`.
|
||||
#[must_use]
|
||||
fn first_occupied_square_leading(self) -> Option<Square> {
|
||||
pub fn first_occupied_square_leading(self) -> Option<Square> {
|
||||
let leading_zeros = self._leading_zeros();
|
||||
if leading_zeros < SQUARES_NUM {
|
||||
unsafe {
|
||||
|
@ -281,7 +280,7 @@ impl BitBoard {
|
|||
/// board, starting at the trailing (least-significant) end of the board.
|
||||
/// If the board is empty, returns `None`.
|
||||
#[must_use]
|
||||
fn first_occupied_square_trailing(self) -> Option<Square> {
|
||||
pub fn first_occupied_square_trailing(self) -> Option<Square> {
|
||||
let trailing_zeros = self._trailing_zeros();
|
||||
|
||||
if trailing_zeros < SQUARES_NUM {
|
||||
|
@ -496,12 +495,9 @@ mod tests {
|
|||
let bb = BitBoard(0b01010100);
|
||||
|
||||
let expected_squares = [Square::G1, Square::E1, Square::C1];
|
||||
for (a, b) in bb
|
||||
.occupied_squares(&IterationDirection::Leading)
|
||||
.zip(expected_squares.iter().copied())
|
||||
{
|
||||
assert_eq!(a, b);
|
||||
}
|
||||
bb.occupied_squares(&IterationDirection::Leading)
|
||||
.zip(expected_squares)
|
||||
.for_each(|(a, b)| assert_eq!(a, b));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -512,12 +508,9 @@ mod tests {
|
|||
|
||||
let expected_squares = [Square::H8, Square::F6, Square::C5, Square::E2, Square::D1];
|
||||
|
||||
for (a, b) in bb
|
||||
.occupied_squares(&IterationDirection::Leading)
|
||||
.zip(expected_squares.iter().cloned())
|
||||
{
|
||||
assert_eq!(a, b);
|
||||
}
|
||||
bb.occupied_squares(&IterationDirection::Leading)
|
||||
.zip(expected_squares)
|
||||
.for_each(|(a, b)| assert_eq!(a, b));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue