[BitBoard] Build out the documentation
This commit is contained in:
parent
daf5c86792
commit
7e45e49502
2 changed files with 81 additions and 46 deletions
|
@ -7,6 +7,25 @@ use forward_ref::{forward_ref_binop, forward_ref_op_assign, forward_ref_unop};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::ops::{BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Not};
|
use std::ops::{BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Not};
|
||||||
|
|
||||||
|
/// A bitfield representation of a chess board that uses the bits of a 64-bit
|
||||||
|
/// unsigned integer to represent whether a square on the board is occupied.
|
||||||
|
/// Squares are laid out as follows, starting at the bottom left, going row-wise,
|
||||||
|
/// and ending at the top right corner:
|
||||||
|
///
|
||||||
|
/// ```text
|
||||||
|
/// +-------------------------+
|
||||||
|
/// 8 | 56 57 58 59 60 61 62 63 |
|
||||||
|
/// 7 | 48 49 50 51 52 53 54 55 |
|
||||||
|
/// 6 | 40 41 42 43 44 45 46 47 |
|
||||||
|
/// 5 | 32 33 34 35 36 37 38 39 |
|
||||||
|
/// 4 | 24 25 26 27 28 29 30 31 |
|
||||||
|
/// 3 | 16 17 18 19 20 21 22 23 |
|
||||||
|
/// 2 | 8 9 10 11 12 13 14 15 |
|
||||||
|
/// 1 | 0 1 2 3 4 5 6 7 |
|
||||||
|
/// +-------------------------+
|
||||||
|
/// A B C D E F G H
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
#[derive(Clone, Copy, Eq, Hash, PartialEq)]
|
#[derive(Clone, Copy, Eq, Hash, PartialEq)]
|
||||||
pub struct BitBoard(pub(crate) u64);
|
pub struct BitBoard(pub(crate) u64);
|
||||||
|
|
||||||
|
@ -78,27 +97,30 @@ impl BitBoard {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BitBoard {
|
impl BitBoard {
|
||||||
|
/// Converts this [BitBoard] to an unsigned 64-bit integer.
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub const fn as_bits(&self) -> u64 {
|
pub const fn as_bits(&self) -> u64 {
|
||||||
self.0
|
self.0
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns `true` if the [`BitBoard`] has no bits set.
|
/// Returns `true` if this [BitBoard] has no bits set. This is the opposite
|
||||||
|
/// of [`BitBoard::is_populated`].
|
||||||
///
|
///
|
||||||
/// ## Examples
|
/// ## Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use chessfriend_bitboard::BitBoard;
|
/// use chessfriend_bitboard::BitBoard;
|
||||||
/// assert!(BitBoard::EMPTY.is_populated());
|
/// assert!(BitBoard::EMPTY.is_empty());
|
||||||
/// assert!(!BitBoard::FULL.is_populated());
|
/// assert!(!BitBoard::FULL.is_empty());
|
||||||
/// assert!(!BitBoard::new(0b1000).is_populated());
|
/// assert!(!BitBoard::new(0b1000).is_empty());
|
||||||
/// ```
|
/// ```
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub const fn is_empty(&self) -> bool {
|
pub const fn is_empty(&self) -> bool {
|
||||||
self.0 == 0
|
self.0 == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns `true` if the [`BitBoard`] has at least one bit set.
|
/// Returns `true` if the [BitBoard] has at least one bit set. This is the
|
||||||
|
/// opposite of [`BitBoard::is_empty`].
|
||||||
///
|
///
|
||||||
/// ## Examples
|
/// ## Examples
|
||||||
///
|
///
|
||||||
|
@ -112,13 +134,26 @@ impl BitBoard {
|
||||||
self.0 != 0
|
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
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// use chessfriend_bitboard::BitBoard;
|
||||||
|
/// use chessfriend_core::Square;
|
||||||
|
///
|
||||||
|
/// let square = Square::E4;
|
||||||
|
/// let mut bitboard = BitBoard::new(0b1001100);
|
||||||
|
///
|
||||||
|
/// assert!(bitboard.contains(Square::C1));
|
||||||
|
/// assert!(!bitboard.contains(Square::B1));
|
||||||
|
/// ```
|
||||||
pub fn contains(self, square: Square) -> bool {
|
pub fn contains(self, square: Square) -> bool {
|
||||||
let square_bitboard: BitBoard = square.into();
|
let square_bitboard: BitBoard = square.into();
|
||||||
!(self & square_bitboard).is_empty()
|
!(self & square_bitboard).is_empty()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The number of 1 bits in the BitBoard.
|
/// Counts the number of set squares (1 bits) in this [BitBoard].
|
||||||
///
|
///
|
||||||
/// ## Examples
|
/// ## Examples
|
||||||
///
|
///
|
||||||
|
@ -132,11 +167,37 @@ impl BitBoard {
|
||||||
self.0.count_ones()
|
self.0.count_ones()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set a square in this [BitBoard] by toggling the corresponding bit to 1.
|
||||||
|
/// This always succeeds, even if the bit was already set.
|
||||||
|
///
|
||||||
|
/// ## Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// use chessfriend_bitboard::BitBoard;
|
||||||
|
/// use chessfriend_core::Square;
|
||||||
|
///
|
||||||
|
/// let mut bitboard = BitBoard::new(0b1001100);
|
||||||
|
/// bitboard.set(Square::E4);
|
||||||
|
/// assert!(bitboard.contains(Square::E4));
|
||||||
|
/// ```
|
||||||
pub fn set(&mut self, square: Square) {
|
pub fn set(&mut self, square: Square) {
|
||||||
let square_bitboard: BitBoard = square.into();
|
let square_bitboard: BitBoard = square.into();
|
||||||
self.0 |= square_bitboard.0
|
self.0 |= square_bitboard.0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Clear a square (set it to 0) in this [BitBoard]. This always succeeds
|
||||||
|
/// even if the bit is not set.
|
||||||
|
///
|
||||||
|
/// ## Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// use chessfriend_bitboard::BitBoard;
|
||||||
|
/// use chessfriend_core::Square;
|
||||||
|
///
|
||||||
|
/// let mut bitboard = BitBoard::new(0b1001100);
|
||||||
|
/// bitboard.clear(Square::C1);
|
||||||
|
/// assert!(!bitboard.contains(Square::C1));
|
||||||
|
/// ```
|
||||||
pub fn clear(&mut self, square: Square) {
|
pub fn clear(&mut self, square: Square) {
|
||||||
let square_bitboard: BitBoard = square.into();
|
let square_bitboard: BitBoard = square.into();
|
||||||
self.0 &= !square_bitboard.0
|
self.0 &= !square_bitboard.0
|
||||||
|
@ -156,25 +217,25 @@ impl BitBoard {
|
||||||
pub fn is_single_square(&self) -> bool {
|
pub fn is_single_square(&self) -> bool {
|
||||||
self.0.is_power_of_two()
|
self.0.is_power_of_two()
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl BitBoard {
|
/// Return an Iterator over the occupied squares. The Iterator yields
|
||||||
/// Returns an Iterator over the occupied squares.
|
/// squares starting from the leading (most-significant bit) end of the
|
||||||
///
|
/// board.
|
||||||
/// The Iterator yields squares starting from the leading (most-significant bit) end of the
|
|
||||||
/// board to the trailing (least-significant bit) end.
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn occupied_squares(&self) -> impl Iterator<Item = Square> {
|
pub fn occupied_squares(&self) -> impl Iterator<Item = Square> {
|
||||||
LeadingBitScanner::new(self.0).map(|idx| unsafe { Square::from_index(idx as u8) })
|
LeadingBitScanner::new(self.0).map(|idx| unsafe { Square::from_index(idx as u8) })
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return an Iterator over the occupied squares, starting from the trailing
|
/// Return an Iterator over the occupied squares. The Iterator yields
|
||||||
/// (least-significant bit) end of the field.
|
/// squares starting from the trailing (least-significant bit) end of the
|
||||||
#[must_use]
|
/// board.
|
||||||
pub fn occupied_squares_trailing(&self) -> impl Iterator<Item = Square> {
|
pub fn occupied_squares_trailing(&self) -> impl Iterator<Item = Square> {
|
||||||
TrailingBitScanner::new(self.0).map(|idx| unsafe { Square::from_index(idx as u8) })
|
TrailingBitScanner::new(self.0).map(|idx| unsafe { Square::from_index(idx as u8) })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// If the board is not empty, returns the first occupied square on the
|
||||||
|
/// board, starting at the leading (most-significant) end of the board. If
|
||||||
|
/// the board is empty, returns `None`.
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn first_occupied_square(&self) -> Option<Square> {
|
pub fn first_occupied_square(&self) -> Option<Square> {
|
||||||
let leading_zeros = self.0.leading_zeros() as u8;
|
let leading_zeros = self.0.leading_zeros() as u8;
|
||||||
|
@ -185,6 +246,9 @@ impl BitBoard {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// If the board is not empty, returns the first occupied square on the
|
||||||
|
/// board, starting at the trailing (least-significant) end of the board.
|
||||||
|
/// If the board is empty, returns `None`.
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn first_occupied_square_trailing(&self) -> Option<Square> {
|
pub fn first_occupied_square_trailing(&self) -> Option<Square> {
|
||||||
let trailing_zeros = self.0.trailing_zeros() as u8;
|
let trailing_zeros = self.0.trailing_zeros() as u8;
|
||||||
|
@ -380,35 +444,6 @@ mod tests {
|
||||||
assert_eq!(BitBoard::rank(&7).0, 0xFF00000000000000, "Rank 8");
|
assert_eq!(BitBoard::rank(&7).0, 0xFF00000000000000, "Rank 8");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn is_empty() {
|
|
||||||
assert!(BitBoard(0).is_empty());
|
|
||||||
assert!(!BitBoard(0xFF).is_empty());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn has_piece_at() {
|
|
||||||
let bb = BitBoard(0b1001100);
|
|
||||||
assert!(bb.is_set(Square::C1));
|
|
||||||
assert!(!bb.is_set(Square::B1));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn set_square() {
|
|
||||||
let sq = Square::E4;
|
|
||||||
let mut bb = BitBoard(0b1001100);
|
|
||||||
bb.set_square(sq);
|
|
||||||
assert!(bb.is_set(sq));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn clear_square() {
|
|
||||||
let sq = Square::A3;
|
|
||||||
let mut bb = BitBoard(0b1001100);
|
|
||||||
bb.clear_square(sq);
|
|
||||||
assert!(!bb.is_set(sq));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn single_rank_occupancy() {
|
fn single_rank_occupancy() {
|
||||||
let bb = BitBoard(0b01010100);
|
let bb = BitBoard(0b01010100);
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
//! # The Bitboard Library
|
//! # The Bitboard Library
|
||||||
//!
|
//!
|
||||||
//! This module implements a collection of commonly used bitboards that can be
|
//! This module implements a collection of commonly used bitboards that can be
|
||||||
//! looked up efficiently as needed.
|
//! looked up efficiently.
|
||||||
//!
|
//!
|
||||||
//! The `library()` method returns a static instance of a `Library`, which
|
//! The `library()` method returns a static instance of a `Library`, which
|
||||||
//! provides getters for all available bitboards.
|
//! provides getters for all available bitboards.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue