aboutsummaryrefslogtreecommitdiff
path: root/src/bitboard.rs
diff options
context:
space:
mode:
authoreug-vs <eugene@eug-vs.xyz>2023-02-21 05:22:54 +0300
committereug-vs <eugene@eug-vs.xyz>2023-02-21 05:28:45 +0300
commit46e9fcdcce5730827355db9449c41dc0a0e42b1f (patch)
tree7b9903446bd7884df6a22ddd2c6a2b8a6dcc3d44 /src/bitboard.rs
parent02ebad55af6c76ac9e36832f9be041f547f63b7c (diff)
downloadchessnost-46e9fcdcce5730827355db9449c41dc0a0e42b1f.tar.gz
refactor: use bitboard trait
Diffstat (limited to 'src/bitboard.rs')
-rw-r--r--src/bitboard.rs163
1 files changed, 89 insertions, 74 deletions
diff --git a/src/bitboard.rs b/src/bitboard.rs
index ed7ec1b..ad21664 100644
--- a/src/bitboard.rs
+++ b/src/bitboard.rs
@@ -3,40 +3,32 @@ use crate::square::Square;
/// Finite set of up to 64 bits representing chess board squares
pub type Bitboard = u64;
-/// Print bitboard on screen in the same way squares appear in memory
-/// (i.e the board is actually flipped along X)
-#[allow(dead_code)]
-pub fn print(bb: Bitboard, title: &str) {
- println!("\n {}", title);
- for rank in (0..8).rev() {
- print!("{}|", rank + 1);
- for file in 0..8 {
- let index = rank * 8 + file;
- print!("{}", if bb >> index & 1 == 1 { "⚫" } else { ". " });
- if file == 7 {
- println!();
- }
- }
- }
- return println!(" a b c d e f g h");
-}
+pub trait BitboardFns {
+ /// Print bitboard on the screen
+ fn print(self, title: &str) -> ();
-/// Return bitboard cardinality, aka number of elements in the set
-pub fn pop_count(mut bb: Bitboard) -> u8 {
- let mut count = 0;
- while bb > 0 {
- count += 1;
- bb &= bb - 1;
- }
- return count;
-}
+ /// Return bitboard cardinality, aka number of elements in the set
+ fn pop_count(self) -> u8;
-/// Return Bitboard with only Least Single Bit
-pub fn ls1b(bb: Bitboard) -> Bitboard {
- if bb == 0 {
- return 0
- }
- bb & !(bb - 1)
+ /// Return Bitboard with only Least Single Bit
+ fn ls1b(self) -> Self;
+
+ /// Return the square corresponding to Least Single Bit
+ /// using De Brujin method. For single Bitboards it works
+ /// like a mapper from Bitboards to Squares.
+ ///
+ /// ```rust
+ /// # use chessnost::{bitboard::BitboardFns, square::Square};
+ /// assert_eq!(5.bitscan(), Square::from(0));
+ /// assert_eq!(4.bitscan(), Square::C1);
+ /// ```
+ fn bitscan(self) -> Square;
+
+ /// Perform bitscan and reset the *ls1b*
+ fn bitscan_and_reset(&mut self) -> Square;
+
+ /// Convert bitboard into the list of squares
+ fn serialize(self) -> Vec<Square>;
}
const DE_BRUJIN_SEQUENCE: [u8; 64] = [
@@ -50,38 +42,62 @@ const DE_BRUJIN_SEQUENCE: [u8; 64] = [
25, 14, 19, 9, 13, 8, 7, 6
];
-/// Return the square corresponding to Least Single Bit
-/// using De Brujin method. For single Bitboards it works
-/// like a mapper from Bitboards to Squares.
-///
-/// ```rust
-/// # use chessnost::{bitboard::bitscan, square::Square};
-/// assert_eq!(bitscan(5), Square::from(0));
-/// assert_eq!(bitscan(4), Square::C1);
-/// ```
-pub fn bitscan(bb: Bitboard) -> Square {
- // TODO: generate private De Brujin routine
- debug_assert!(bb != 0, "Can not bitscan empty bitboard");
- let magic: u64 = 0x03f79d71b4cb0a89;
- let ls1b = ls1b(bb);
- let index = DE_BRUJIN_SEQUENCE[(((ls1b as u128 * magic as u128) as u64) >> 58) as usize];
- Square::from(index)
-}
+impl BitboardFns for Bitboard {
+ fn print(self, title: &str) -> () {
+ println!("\n {}", title);
+ for rank in (0..8).rev() {
+ print!("{}|", rank + 1);
+ for file in 0..8 {
+ let index = rank * 8 + file;
+ print!("{}", if self >> index & 1 == 1 { "⚫" } else { ". " });
+ if file == 7 {
+ println!();
+ }
+ }
+ }
+ return println!(" a b c d e f g h");
+ }
-/// Perform bitscan and reset the *ls1b*
-pub fn bitscan_and_reset(bb: &mut Bitboard) -> Square {
- let square = bitscan(*bb);
- *bb &= *bb - 1; // Reset ls1b
- square
-}
+ fn pop_count(mut self) -> u8 {
+ let mut count = 0;
+ while self > 0 {
+ count += 1;
+ self &= self - 1;
+ }
+ return count;
+ }
+
+
+ fn ls1b(self) -> Self {
+ if self == 0 {
+ return 0
+ }
+ self & !(self - 1)
+ }
-/// Convert bitboard into the list of squares
-pub fn serialize_bitboard(mut bb: Bitboard) -> Vec<Square> {
- let mut serialized = Vec::with_capacity(64);
- while bb > 0 {
- serialized.push(bitscan_and_reset(&mut bb));
+
+ fn bitscan(self) -> Square {
+ // TODO: generate private De Brujin routine
+ debug_assert!(self != 0, "Can not bitscan empty bitboard");
+ let magic: u64 = 0x03f79d71b4cb0a89;
+ let ls1b = self.ls1b();
+ let index = DE_BRUJIN_SEQUENCE[(((ls1b as u128 * magic as u128) as u64) >> 58) as usize];
+ Square::from(index)
+ }
+
+ fn bitscan_and_reset(&mut self) -> Square {
+ let square = self.bitscan();
+ *self &= *self - 1; // Reset ls1b
+ square
+ }
+
+ fn serialize(mut self) -> Vec<Square> {
+ let mut serialized = Vec::with_capacity(64);
+ while self > 0 {
+ serialized.push(self.bitscan_and_reset());
+ }
+ serialized
}
- serialized
}
#[cfg(test)]
@@ -90,38 +106,37 @@ mod tests {
#[test]
fn test_pop_count() {
- assert_eq!(pop_count(127), 7);
+ assert_eq!(127.pop_count(), 7);
}
#[test]
fn test_ls1b() {
- assert_eq!(ls1b(38), 2);
- assert_eq!(ls1b(16), 16);
- assert_eq!(ls1b(20), 4);
+ assert_eq!(38.ls1b(), 2);
+ assert_eq!(16.ls1b(), 16);
+ assert_eq!(20.ls1b(), 4);
}
#[test]
fn test_bitscan() {
- assert_eq!(bitscan(4), Square::from(2));
- assert_eq!(bitscan(16), Square::from(4));
- assert_eq!(bitscan(64), Square::from(6));
- assert_eq!(bitscan(128), Square::from(7));
+ assert_eq!(4.bitscan(), Square::from(2));
+ assert_eq!(16.bitscan(), Square::from(4));
+ assert_eq!(64.bitscan(), Square::from(6));
+ assert_eq!(128.bitscan(), Square::from(7));
}
#[test]
fn test_bitscan_with_non_single_bb() {
- assert_eq!(bitscan(5), Square::from(0));
- assert_eq!(bitscan(6), Square::from(1));
- assert_eq!(bitscan(7), Square::from(0));
+ assert_eq!(5.bitscan(), Square::from(0));
+ assert_eq!(6.bitscan(), Square::from(1));
+ assert_eq!(7.bitscan(), Square::from(0));
}
#[test]
fn test_serialize_bitboard() {
let bb = 1 << 4 | 1 << 15 | 1 << 60;
- let serialized = serialize_bitboard(bb);
+ let serialized = bb.serialize();
assert_eq!(serialized[0], Square::from(4));
assert_eq!(serialized[1], Square::from(15));
assert_eq!(serialized[2], Square::from(60));
}
}
-