diff --git a/src/bitboard.rs b/src/bitboard.rs index b4c18d3..3c920ca 100644 --- a/src/bitboard.rs +++ b/src/bitboard.rs @@ -1,22 +1,28 @@ +//! Sets of squares. + use crate::board::*; use std::iter::ExactSizeIterator; use std::iter::FusedIterator; +/// A set of squares. #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] -pub struct Bitboard(pub(crate) u64); +pub struct Bitboard(pub u64); impl Bitboard { + /// Returns an empty bitboard. #[inline] pub fn new() -> Self { Self(0) } + /// Returns `true` if the bitboard is empty. #[inline] pub fn is_empty(&self) -> bool { self.0 == 0 } + /// Returns the square with the smallest index that is present in the bitboard. #[inline] pub const fn first(&self) -> Option { let mask = self.0; @@ -27,7 +33,7 @@ impl Bitboard { } #[inline] - pub const fn last(&self) -> Option { + pub(crate) const fn last(&self) -> Option { let mask = self.0; match mask { 0 => None, @@ -37,6 +43,7 @@ impl Bitboard { } } + /// Removes the square with the smallest index and returns it, or `None` if the bitboard is empty. #[inline] pub fn pop(&mut self) -> Option { let Self(ref mut mask) = self; @@ -48,13 +55,33 @@ impl Bitboard { square } + /// Inserts a square in the bitboard. #[inline] pub const fn insert(&mut self, square: Square) { self.0 |= 1 << square as u8; } + /// Removes a square from the bitboard. #[inline] - pub fn trans(&self, direction: Direction) -> Self { + pub const fn remove(&mut self, square: Square) { + self.0 &= !(1 << square as u8); + } + + /// Returns `true` if the bitboard contains the given square. + #[inline] + pub const fn contains(&self, square: Square) -> bool { + self.0 & (1 << square as u8) != 0 + } + + /// Returns the vertical symmetry of the bitboard. + #[inline] + pub fn mirror(self) -> Self { + let [a, b, c, d, e, f, g, h] = self.0.to_le_bytes(); + Self(u64::from_le_bytes([h, g, f, e, d, c, b, a])) + } + + #[inline] + pub(crate) fn trans(&self, direction: Direction) -> Self { match direction { Direction::North => Self(self.0 << 8), Direction::NorthEast => Self(self.0 << 9) & !File::A.bitboard(), @@ -66,16 +93,39 @@ impl Bitboard { Direction::NorthWest => Self(self.0 << 7) & !File::H.bitboard(), } } +} - #[inline] - pub const fn contains(&self, square: Square) -> bool { - self.0 & (1 << square as u8) != 0 - } - - #[inline] - pub fn mirror(self) -> Bitboard { - let [a, b, c, d, e, f, g, h] = self.0.to_le_bytes(); - Self(u64::from_le_bytes([h, g, f, e, d, c, b, a])) +impl std::fmt::Debug for Bitboard { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { + f.write_str("Bitboard(")?; + if f.alternate() { + for rank in Rank::all().into_iter().rev() { + f.write_str("\n ")?; + for file in File::all() { + f.write_str(if self.contains(Square::new(file, rank)) { + " 1" + } else { + " ." + })?; + } + } + f.write_str("\n)")?; + } else { + for rank in Rank::all().into_iter().rev() { + if rank != Rank::Eighth { + f.write_str("/")?; + } + for file in File::all() { + f.write_str(if self.contains(Square::new(file, rank)) { + "1" + } else { + "." + })?; + } + } + f.write_str(")")?; + } + Ok(()) } } diff --git a/src/board.rs b/src/board.rs index 9833d61..7f41659 100644 --- a/src/board.rs +++ b/src/board.rs @@ -136,7 +136,7 @@ impl File { } #[inline] - pub(crate) const fn bitboard(self) -> Bitboard { + pub const fn bitboard(self) -> Bitboard { Bitboard(0x0101010101010101 << (self as u8)) } @@ -213,7 +213,7 @@ impl Rank { } #[inline] - pub(crate) const fn bitboard(self) -> Bitboard { + pub const fn bitboard(self) -> Bitboard { Bitboard(0xFF << ((self as u64) << 3)) } @@ -294,7 +294,7 @@ impl Square { } #[inline] - pub(crate) const fn bitboard(self) -> Bitboard { + pub const fn bitboard(self) -> Bitboard { Bitboard(1 << self as u8) } diff --git a/src/lib.rs b/src/lib.rs index 6b5e3c5..7df0d27 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -73,10 +73,10 @@ //! - etc. pub(crate) mod array_vec; -pub(crate) mod bitboard; pub(crate) mod lookup; pub(crate) mod magics; +pub mod bitboard; pub mod board; pub mod position; pub mod san;