[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::fmt;
|
||||||
use std::ops::{BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Not};
|
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
|
/// 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.
|
/// 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,
|
/// Squares are laid out as follows, starting at the bottom left, going row-wise,
|
||||||
|
@ -103,21 +106,21 @@ impl BitBoard {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BitBoard {
|
impl BitBoard {
|
||||||
/// Converts this [BitBoard] to an unsigned 64-bit integer.
|
/// 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 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`].
|
/// of [`BitBoard::is_populated`].
|
||||||
///
|
///
|
||||||
/// ## Examples
|
/// ## Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use chessfriend_bitboard::BitBoard;
|
/// use chessfriend_bitboard::BitBoard;
|
||||||
/// assert!(BitBoard::EMPTY.is_empty());
|
/// assert!(BitBoard::empty().is_empty());
|
||||||
/// assert!(!BitBoard::FULL.is_empty());
|
/// assert!(!BitBoard::full().is_empty());
|
||||||
/// assert!(!BitBoard::new(0b1000).is_empty());
|
/// assert!(!BitBoard::new(0b1000).is_empty());
|
||||||
/// ```
|
/// ```
|
||||||
#[must_use]
|
#[must_use]
|
||||||
|
@ -125,17 +128,18 @@ impl BitBoard {
|
||||||
self.0 == 0
|
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`].
|
/// opposite of [`BitBoard::is_empty`].
|
||||||
///
|
///
|
||||||
/// ## Examples
|
/// ## Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use chessfriend_bitboard::BitBoard;
|
/// use chessfriend_bitboard::BitBoard;
|
||||||
/// assert!(!BitBoard::EMPTY.is_populated());
|
/// assert!(!BitBoard::empty().is_populated());
|
||||||
/// assert!(BitBoard::FULL.is_populated());
|
/// assert!(BitBoard::full().is_populated());
|
||||||
/// assert!(BitBoard::new(0b1).is_populated());
|
/// assert!(BitBoard::new(0b1).is_populated());
|
||||||
/// ```
|
/// ```
|
||||||
|
#[must_use]
|
||||||
pub const fn is_populated(&self) -> bool {
|
pub const fn is_populated(&self) -> bool {
|
||||||
self.0 != 0
|
self.0 != 0
|
||||||
}
|
}
|
||||||
|
@ -154,21 +158,23 @@ impl BitBoard {
|
||||||
/// assert!(bitboard.contains(Square::C1));
|
/// assert!(bitboard.contains(Square::C1));
|
||||||
/// assert!(!bitboard.contains(Square::B1));
|
/// assert!(!bitboard.contains(Square::B1));
|
||||||
/// ```
|
/// ```
|
||||||
|
#[must_use]
|
||||||
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()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Counts the number of set squares (1 bits) in this [BitBoard].
|
/// Counts the number of set squares (1 bits) in this [`BitBoard`].
|
||||||
///
|
///
|
||||||
/// ## Examples
|
/// ## Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use chessfriend_bitboard::BitBoard;
|
/// 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::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 {
|
pub const fn population_count(&self) -> u32 {
|
||||||
self.0.count_ones()
|
self.0.count_ones()
|
||||||
}
|
}
|
||||||
|
@ -188,10 +194,10 @@ impl BitBoard {
|
||||||
/// ```
|
/// ```
|
||||||
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
|
/// Clear a square (set it to 0) in this [`BitBoard`]. This always succeeds
|
||||||
/// even if the bit is not set.
|
/// even if the bit is not set.
|
||||||
///
|
///
|
||||||
/// ## Examples
|
/// ## Examples
|
||||||
|
@ -206,20 +212,21 @@ impl BitBoard {
|
||||||
/// ```
|
/// ```
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns `true` if this BitBoard represents a single square.
|
/// Returns `true` if this [`BitBoard`] represents a single square.
|
||||||
///
|
///
|
||||||
/// ## Examples
|
/// ## Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use chessfriend_bitboard::BitBoard;
|
/// use chessfriend_bitboard::BitBoard;
|
||||||
/// assert!(!BitBoard::EMPTY.is_single_square(), "Empty bitboards represent no 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::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(0b010011110101101100).is_single_square(), "This bitboard represents a bunch of squares");
|
||||||
/// assert!(BitBoard::new(0b10000000000000).is_single_square());
|
/// assert!(BitBoard::new(0b10000000000000).is_single_square());
|
||||||
/// ```
|
/// ```
|
||||||
|
#[must_use]
|
||||||
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()
|
||||||
}
|
}
|
||||||
|
@ -228,8 +235,9 @@ impl BitBoard {
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn occupied_squares(
|
pub fn occupied_squares(
|
||||||
&self,
|
&self,
|
||||||
direction: IterationDirection,
|
direction: &IterationDirection,
|
||||||
) -> Box<dyn Iterator<Item = Square>> {
|
) -> Box<dyn Iterator<Item = Square>> {
|
||||||
|
#[allow(clippy::cast_possible_truncation)]
|
||||||
fn index_to_square(index: usize) -> Square {
|
fn index_to_square(index: usize) -> Square {
|
||||||
unsafe { Square::from_index_unchecked(index as u8) }
|
unsafe { Square::from_index_unchecked(index as u8) }
|
||||||
}
|
}
|
||||||
|
@ -245,7 +253,7 @@ impl BitBoard {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn first_occupied_square(&self, direction: IterationDirection) -> Option<Square> {
|
pub fn first_occupied_square(&self, direction: &IterationDirection) -> Option<Square> {
|
||||||
match direction {
|
match direction {
|
||||||
IterationDirection::Leading => self.first_occupied_square_leading(),
|
IterationDirection::Leading => self.first_occupied_square_leading(),
|
||||||
IterationDirection::Trailing => self.first_occupied_square_trailing(),
|
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
|
/// board, starting at the leading (most-significant) end of the board. If
|
||||||
/// the board is empty, returns `None`.
|
/// the board is empty, returns `None`.
|
||||||
#[must_use]
|
#[must_use]
|
||||||
fn first_occupied_square_leading(&self) -> Option<Square> {
|
fn first_occupied_square_leading(self) -> Option<Square> {
|
||||||
let leading_zeros = self.0.leading_zeros() as u8;
|
let leading_zeros = self._leading_zeros();
|
||||||
if leading_zeros < Square::NUM as u8 {
|
if leading_zeros < SQUARES_NUM {
|
||||||
unsafe {
|
unsafe {
|
||||||
Some(Square::from_index_unchecked(
|
Some(Square::from_index_unchecked(
|
||||||
Square::NUM as u8 - leading_zeros - 1,
|
SQUARES_NUM - leading_zeros - 1,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -273,9 +281,10 @@ impl BitBoard {
|
||||||
/// board, starting at the trailing (least-significant) end of the board.
|
/// board, starting at the trailing (least-significant) end of the board.
|
||||||
/// If the board is empty, returns `None`.
|
/// If the board is empty, returns `None`.
|
||||||
#[must_use]
|
#[must_use]
|
||||||
fn first_occupied_square_trailing(&self) -> Option<Square> {
|
fn first_occupied_square_trailing(self) -> Option<Square> {
|
||||||
let trailing_zeros = self.0.trailing_zeros() as u8;
|
let trailing_zeros = self._trailing_zeros();
|
||||||
if trailing_zeros < Square::NUM as u8 {
|
|
||||||
|
if trailing_zeros < SQUARES_NUM {
|
||||||
unsafe { Some(Square::from_index_unchecked(trailing_zeros)) }
|
unsafe { Some(Square::from_index_unchecked(trailing_zeros)) }
|
||||||
} else {
|
} else {
|
||||||
None
|
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 {
|
impl Default for BitBoard {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
BitBoard::EMPTY
|
BitBoard::EMPTY
|
||||||
|
@ -341,7 +364,7 @@ impl TryFrom<BitBoard> for Square {
|
||||||
return Err(TryFromBitBoardError::NotSingleSquare);
|
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;
|
let mut ranks_written = 0;
|
||||||
for rank in binary_ranks.chunks(8).rev() {
|
for rank in binary_ranks.chunks(8).rev() {
|
||||||
let joined_rank = rank.join(" ");
|
write!(f, "{}", rank.join(" "))?;
|
||||||
write!(f, "{}", joined_rank)?;
|
|
||||||
|
|
||||||
ranks_written += 1;
|
ranks_written += 1;
|
||||||
if ranks_written < 8 {
|
if ranks_written < 8 {
|
||||||
|
@ -456,6 +478,7 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
#[allow(clippy::unreadable_literal)]
|
||||||
fn rank() {
|
fn rank() {
|
||||||
assert_eq!(BitBoard::rank(&0).0, 0xFF, "Rank 1");
|
assert_eq!(BitBoard::rank(&0).0, 0xFF, "Rank 1");
|
||||||
assert_eq!(BitBoard::rank(&1).0, 0xFF00, "Rank 2");
|
assert_eq!(BitBoard::rank(&1).0, 0xFF00, "Rank 2");
|
||||||
|
@ -469,11 +492,13 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn single_rank_occupancy() {
|
fn single_rank_occupancy() {
|
||||||
|
#[allow(clippy::unreadable_literal)]
|
||||||
let bb = BitBoard(0b01010100);
|
let bb = BitBoard(0b01010100);
|
||||||
|
|
||||||
let expected_squares = [Square::G1, Square::E1, Square::C1];
|
let expected_squares = [Square::G1, Square::E1, Square::C1];
|
||||||
for (a, b) in bb
|
for (a, b) in bb
|
||||||
.occupied_squares(IterationDirection::Leading)
|
.occupied_squares(&IterationDirection::Leading)
|
||||||
.zip(expected_squares.iter().cloned())
|
.zip(expected_squares.iter().copied())
|
||||||
{
|
{
|
||||||
assert_eq!(a, b);
|
assert_eq!(a, b);
|
||||||
}
|
}
|
||||||
|
@ -481,13 +506,14 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn occupancy_spot_check() {
|
fn occupancy_spot_check() {
|
||||||
|
#[allow(clippy::unreadable_literal)]
|
||||||
let bb =
|
let bb =
|
||||||
BitBoard(0b10000000_00000000_00100000_00000100_00000000_00000000_00010000_00001000);
|
BitBoard(0b10000000_00000000_00100000_00000100_00000000_00000000_00010000_00001000);
|
||||||
|
|
||||||
let expected_squares = [Square::H8, Square::F6, Square::C5, Square::E2, Square::D1];
|
let expected_squares = [Square::H8, Square::F6, Square::C5, Square::E2, Square::D1];
|
||||||
|
|
||||||
for (a, b) in bb
|
for (a, b) in bb
|
||||||
.occupied_squares(IterationDirection::Leading)
|
.occupied_squares(&IterationDirection::Leading)
|
||||||
.zip(expected_squares.iter().cloned())
|
.zip(expected_squares.iter().cloned())
|
||||||
{
|
{
|
||||||
assert_eq!(a, b);
|
assert_eq!(a, b);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue