[bitboard] Fix some random clippy issues
This commit is contained in:
parent
867deafd13
commit
d5cdf273c8
1 changed files with 57 additions and 31 deletions
|
@ -8,6 +8,9 @@ use forward_ref::{forward_ref_binop, forward_ref_op_assign, forward_ref_unop};
|
|||
use std::fmt;
|
||||
use std::ops::{BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Not};
|
||||
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
const SQUARES_NUM: u8 = Square::NUM as u8;
|
||||
|
||||
/// 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,
|
||||
|
@ -103,21 +106,21 @@ impl BitBoard {
|
|||
}
|
||||
|
||||
impl BitBoard {
|
||||
/// Converts this [BitBoard] to an unsigned 64-bit integer.
|
||||
/// Converts this [`BitBoard`] to an unsigned 64-bit integer.
|
||||
#[must_use]
|
||||
pub const fn as_bits(&self) -> u64 {
|
||||
self.0
|
||||
}
|
||||
|
||||
/// Returns `true` if this [BitBoard] has no bits set. This is the opposite
|
||||
/// Returns `true` if this [`BitBoard`] has no bits set. This is the opposite
|
||||
/// of [`BitBoard::is_populated`].
|
||||
///
|
||||
/// ## Examples
|
||||
///
|
||||
/// ```
|
||||
/// use chessfriend_bitboard::BitBoard;
|
||||
/// assert!(BitBoard::EMPTY.is_empty());
|
||||
/// assert!(!BitBoard::FULL.is_empty());
|
||||
/// assert!(BitBoard::empty().is_empty());
|
||||
/// assert!(!BitBoard::full().is_empty());
|
||||
/// assert!(!BitBoard::new(0b1000).is_empty());
|
||||
/// ```
|
||||
#[must_use]
|
||||
|
@ -125,17 +128,18 @@ impl BitBoard {
|
|||
self.0 == 0
|
||||
}
|
||||
|
||||
/// Returns `true` if the [BitBoard] has at least one bit set. This is the
|
||||
/// Returns `true` if the [`BitBoard`] has at least one bit set. This is the
|
||||
/// opposite of [`BitBoard::is_empty`].
|
||||
///
|
||||
/// ## Examples
|
||||
///
|
||||
/// ```
|
||||
/// use chessfriend_bitboard::BitBoard;
|
||||
/// assert!(!BitBoard::EMPTY.is_populated());
|
||||
/// assert!(BitBoard::FULL.is_populated());
|
||||
/// assert!(!BitBoard::empty().is_populated());
|
||||
/// assert!(BitBoard::full().is_populated());
|
||||
/// assert!(BitBoard::new(0b1).is_populated());
|
||||
/// ```
|
||||
#[must_use]
|
||||
pub const fn is_populated(&self) -> bool {
|
||||
self.0 != 0
|
||||
}
|
||||
|
@ -154,21 +158,23 @@ impl BitBoard {
|
|||
/// assert!(bitboard.contains(Square::C1));
|
||||
/// assert!(!bitboard.contains(Square::B1));
|
||||
/// ```
|
||||
#[must_use]
|
||||
pub fn contains(self, square: Square) -> bool {
|
||||
let square_bitboard: BitBoard = square.into();
|
||||
!(self & square_bitboard).is_empty()
|
||||
}
|
||||
|
||||
/// Counts the number of set squares (1 bits) in this [BitBoard].
|
||||
/// Counts the number of set squares (1 bits) in this [`BitBoard`].
|
||||
///
|
||||
/// ## Examples
|
||||
///
|
||||
/// ```
|
||||
/// use chessfriend_bitboard::BitBoard;
|
||||
/// assert_eq!(BitBoard::EMPTY.population_count(), 0);
|
||||
/// assert_eq!(BitBoard::empty().population_count(), 0);
|
||||
/// assert_eq!(BitBoard::new(0b01011110010).population_count(), 6);
|
||||
/// assert_eq!(BitBoard::FULL.population_count(), 64);
|
||||
/// assert_eq!(BitBoard::full().population_count(), 64);
|
||||
/// ```
|
||||
#[must_use]
|
||||
pub const fn population_count(&self) -> u32 {
|
||||
self.0.count_ones()
|
||||
}
|
||||
|
@ -188,10 +194,10 @@ impl BitBoard {
|
|||
/// ```
|
||||
pub fn set(&mut self, square: Square) {
|
||||
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
|
||||
/// Clear a square (set it to 0) in this [`BitBoard`]. This always succeeds
|
||||
/// even if the bit is not set.
|
||||
///
|
||||
/// ## Examples
|
||||
|
@ -206,20 +212,21 @@ impl BitBoard {
|
|||
/// ```
|
||||
pub fn clear(&mut self, square: Square) {
|
||||
let square_bitboard: BitBoard = square.into();
|
||||
self.0 &= !square_bitboard.0
|
||||
self.0 &= !square_bitboard.0;
|
||||
}
|
||||
|
||||
/// Returns `true` if this BitBoard represents a single square.
|
||||
/// Returns `true` if this [`BitBoard`] represents a single square.
|
||||
///
|
||||
/// ## Examples
|
||||
///
|
||||
/// ```
|
||||
/// use chessfriend_bitboard::BitBoard;
|
||||
/// assert!(!BitBoard::EMPTY.is_single_square(), "Empty bitboards represent no squares");
|
||||
/// assert!(!BitBoard::FULL.is_single_square(), "Full bitboards represent all the squares");
|
||||
/// assert!(!BitBoard::empty().is_single_square(), "Empty bitboards represent no squares");
|
||||
/// assert!(!BitBoard::full().is_single_square(), "Full bitboards represent all the squares");
|
||||
/// assert!(!BitBoard::new(0b010011110101101100).is_single_square(), "This bitboard represents a bunch of squares");
|
||||
/// assert!(BitBoard::new(0b10000000000000).is_single_square());
|
||||
/// ```
|
||||
#[must_use]
|
||||
pub fn is_single_square(&self) -> bool {
|
||||
self.0.is_power_of_two()
|
||||
}
|
||||
|
@ -228,8 +235,9 @@ impl BitBoard {
|
|||
#[must_use]
|
||||
pub fn occupied_squares(
|
||||
&self,
|
||||
direction: IterationDirection,
|
||||
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) }
|
||||
}
|
||||
|
@ -245,7 +253,7 @@ impl BitBoard {
|
|||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn first_occupied_square(&self, direction: IterationDirection) -> Option<Square> {
|
||||
pub fn first_occupied_square(&self, direction: &IterationDirection) -> Option<Square> {
|
||||
match direction {
|
||||
IterationDirection::Leading => self.first_occupied_square_leading(),
|
||||
IterationDirection::Trailing => self.first_occupied_square_trailing(),
|
||||
|
@ -256,12 +264,12 @@ 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> {
|
||||
let leading_zeros = self.0.leading_zeros() as u8;
|
||||
if leading_zeros < Square::NUM as u8 {
|
||||
fn first_occupied_square_leading(self) -> Option<Square> {
|
||||
let leading_zeros = self._leading_zeros();
|
||||
if leading_zeros < SQUARES_NUM {
|
||||
unsafe {
|
||||
Some(Square::from_index_unchecked(
|
||||
Square::NUM as u8 - leading_zeros - 1,
|
||||
SQUARES_NUM - leading_zeros - 1,
|
||||
))
|
||||
}
|
||||
} else {
|
||||
|
@ -273,9 +281,10 @@ 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> {
|
||||
let trailing_zeros = self.0.trailing_zeros() as u8;
|
||||
if trailing_zeros < Square::NUM as u8 {
|
||||
fn first_occupied_square_trailing(self) -> Option<Square> {
|
||||
let trailing_zeros = self._trailing_zeros();
|
||||
|
||||
if trailing_zeros < SQUARES_NUM {
|
||||
unsafe { Some(Square::from_index_unchecked(trailing_zeros)) }
|
||||
} else {
|
||||
None
|
||||
|
@ -283,6 +292,20 @@ impl BitBoard {
|
|||
}
|
||||
}
|
||||
|
||||
impl BitBoard {
|
||||
#[must_use]
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
fn _leading_zeros(self) -> u8 {
|
||||
self.0.leading_zeros() as u8
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
fn _trailing_zeros(self) -> u8 {
|
||||
self.0.trailing_zeros() as u8
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for BitBoard {
|
||||
fn default() -> Self {
|
||||
BitBoard::EMPTY
|
||||
|
@ -341,7 +364,7 @@ impl TryFrom<BitBoard> for Square {
|
|||
return Err(TryFromBitBoardError::NotSingleSquare);
|
||||
}
|
||||
|
||||
unsafe { Ok(Square::from_index_unchecked(value.0.trailing_zeros() as u8)) }
|
||||
unsafe { Ok(Square::from_index_unchecked(value._trailing_zeros())) }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -376,8 +399,7 @@ impl fmt::Display for BitBoard {
|
|||
|
||||
let mut ranks_written = 0;
|
||||
for rank in binary_ranks.chunks(8).rev() {
|
||||
let joined_rank = rank.join(" ");
|
||||
write!(f, "{}", joined_rank)?;
|
||||
write!(f, "{}", rank.join(" "))?;
|
||||
|
||||
ranks_written += 1;
|
||||
if ranks_written < 8 {
|
||||
|
@ -456,6 +478,7 @@ mod tests {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[allow(clippy::unreadable_literal)]
|
||||
fn rank() {
|
||||
assert_eq!(BitBoard::rank(&0).0, 0xFF, "Rank 1");
|
||||
assert_eq!(BitBoard::rank(&1).0, 0xFF00, "Rank 2");
|
||||
|
@ -469,11 +492,13 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn single_rank_occupancy() {
|
||||
#[allow(clippy::unreadable_literal)]
|
||||
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().cloned())
|
||||
.occupied_squares(&IterationDirection::Leading)
|
||||
.zip(expected_squares.iter().copied())
|
||||
{
|
||||
assert_eq!(a, b);
|
||||
}
|
||||
|
@ -481,13 +506,14 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn occupancy_spot_check() {
|
||||
#[allow(clippy::unreadable_literal)]
|
||||
let bb =
|
||||
BitBoard(0b10000000_00000000_00100000_00000100_00000000_00000000_00010000_00001000);
|
||||
|
||||
let expected_squares = [Square::H8, Square::F6, Square::C5, Square::E2, Square::D1];
|
||||
|
||||
for (a, b) in bb
|
||||
.occupied_squares(IterationDirection::Leading)
|
||||
.occupied_squares(&IterationDirection::Leading)
|
||||
.zip(expected_squares.iter().cloned())
|
||||
{
|
||||
assert_eq!(a, b);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue