aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/attacks.rs48
-rw-r--r--src/bitboard.rs163
-rw-r--r--src/board/engine.rs14
-rw-r--r--src/board/mod.rs131
-rw-r--r--src/moves.rs4
5 files changed, 188 insertions, 172 deletions
diff --git a/src/attacks.rs b/src/attacks.rs
index eafaf01..d32ac64 100644
--- a/src/attacks.rs
+++ b/src/attacks.rs
@@ -307,7 +307,7 @@ impl Attacks {
#[cfg(test)]
mod tests {
- use crate::{bitboard::{pop_count, print}, square::Square};
+ use crate::{bitboard::BitboardFns, square::Square};
use super::*;
@@ -323,15 +323,15 @@ mod tests {
let square = Square::E4 as usize;
let white_attacks = attacks[Color::White as usize][square];
- print(white_attacks, "Pawn e4");
+ white_attacks.print("Pawn e4");
assert_eq!(white_attacks, Square::D5.to_bitboard() | Square::F5.to_bitboard());
assert_eq!(attacks[Color::White as usize][Square::H4 as usize], Square::G5.to_bitboard());
assert_eq!(attacks[Color::White as usize][Square::A4 as usize], Square::B5.to_bitboard());
- assert_eq!(pop_count(attacks[Color::White as usize][Square::E8 as usize]), 0);
- assert_eq!(pop_count(attacks[Color::Black as usize][Square::E1 as usize]), 0);
+ assert_eq!(attacks[Color::White as usize][Square::E8 as usize].pop_count(), 0);
+ assert_eq!(attacks[Color::Black as usize][Square::E1 as usize].pop_count(), 0);
}
#[test]
@@ -353,7 +353,7 @@ mod tests {
let attacks = Attacks::precompute_knight_attacks();
let e4_attacks = attacks[Square::E4 as usize];
- print(e4_attacks, "Knight e4");
+ e4_attacks.print("Knight e4");
assert_ne!(e4_attacks & Square::G5.to_bitboard(), 0);
assert_ne!(e4_attacks & Square::G3.to_bitboard(), 0);
@@ -368,27 +368,27 @@ mod tests {
assert_eq!(e4_attacks & Square::D4.to_bitboard(), 0);
assert_eq!(e4_attacks & Square::A1.to_bitboard(), 0);
- assert_eq!(pop_count(attacks[Square::G1 as usize]), 3);
- assert_eq!(pop_count(attacks[Square::H8 as usize]), 2);
+ assert_eq!(attacks[Square::G1 as usize].pop_count(), 3);
+ assert_eq!(attacks[Square::H8 as usize].pop_count(), 2);
}
#[test]
fn king_attacks() {
let attacks = Attacks::precompute_king_attacks();
- print(attacks[Square::E4 as usize], "King e4");
+ attacks[Square::E4 as usize].print("King e4");
- assert_eq!(pop_count(attacks[Square::E4 as usize]), 8);
+ assert_eq!(attacks[Square::E4 as usize].pop_count(), 8);
- assert_eq!(pop_count(attacks[Square::A1 as usize]), 3);
- assert_eq!(pop_count(attacks[Square::A8 as usize]), 3);
- assert_eq!(pop_count(attacks[Square::H1 as usize]), 3);
- assert_eq!(pop_count(attacks[Square::H8 as usize]), 3);
+ assert_eq!(attacks[Square::A1 as usize].pop_count(), 3);
+ assert_eq!(attacks[Square::A8 as usize].pop_count(), 3);
+ assert_eq!(attacks[Square::H1 as usize].pop_count(), 3);
+ assert_eq!(attacks[Square::H8 as usize].pop_count(), 3);
- assert_eq!(pop_count(attacks[Square::E1 as usize]), 5);
- assert_eq!(pop_count(attacks[Square::E8 as usize]), 5);
- assert_eq!(pop_count(attacks[Square::A4 as usize]), 5);
- assert_eq!(pop_count(attacks[Square::H4 as usize]), 5);
+ assert_eq!(attacks[Square::E1 as usize].pop_count(), 5);
+ assert_eq!(attacks[Square::E8 as usize].pop_count(), 5);
+ assert_eq!(attacks[Square::A4 as usize].pop_count(), 5);
+ assert_eq!(attacks[Square::H4 as usize].pop_count(), 5);
}
#[test]
@@ -421,7 +421,7 @@ mod tests {
attacks[5][square] |
attacks[6][square] |
attacks[7][square];
- print(bitboard, "Rays from e4");
+ bitboard.print("Rays from e4");
}
#[test]
@@ -430,8 +430,8 @@ mod tests {
let square = Square::E4;
let bb = attacks.bishop(DEFAULT_OCCUPANCY, square);
- print(DEFAULT_OCCUPANCY, "Occupancy");
- print(bb, "Bishop e4");
+ DEFAULT_OCCUPANCY.print("Occupancy");
+ bb.print("Bishop e4");
assert_ne!(bb & Square::C2.to_bitboard(), 0);
assert_eq!(bb & Square::B1.to_bitboard(), 0);
@@ -454,8 +454,8 @@ mod tests {
Square::F3.to_bitboard();
let bb = attacks.rook(occupancy, square);
- print(occupancy, "Occupancy");
- print(bb, "Rook e4");
+ occupancy.print("Occupancy");
+ bb.print("Rook e4");
assert_ne!(bb & Square::E8.to_bitboard(), 0);
assert_ne!(bb & Square::E7.to_bitboard(), 0);
@@ -474,7 +474,7 @@ mod tests {
let attacks = Attacks::new();
let square = Square::E4;
let bb = attacks.queen(DEFAULT_OCCUPANCY, square);
- print(DEFAULT_OCCUPANCY, "Occupancy");
- print(bb, "Queen e4");
+ DEFAULT_OCCUPANCY.print("Occupancy");
+ bb.print("Queen e4");
}
}
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));
}
}
-
diff --git a/src/board/engine.rs b/src/board/engine.rs
index ad2b3b2..5168350 100644
--- a/src/board/engine.rs
+++ b/src/board/engine.rs
@@ -1,5 +1,5 @@
use std::{time::{Instant, Duration}, f32::INFINITY, cmp::Ordering};
-use crate::{bitboard::pop_count, board::*};
+use crate::board::*;
use super::ttable::{NodeType, TranspositionTableItem};
@@ -171,7 +171,7 @@ impl Board {
_ => panic!("Unreachable")
};
- material += serialize_bitboard(*bitboard).iter().fold(0., |acc, square| {
+ material += bitboard.serialize().iter().fold(0., |acc, square| {
acc + piece_type.static_eval() + bonus_table[
match color {
Color::White => square.mirror() as usize,
@@ -195,7 +195,7 @@ impl Board {
for file in 0..8 {
let file_mask = A_FILE << file;
- let pawns_on_file = pop_count(pawns & file_mask) as f32;
+ let pawns_on_file = (pawns & file_mask).pop_count() as f32;
// Doubled pawns (-1 because one pawn on a file is ok)
result += (pawns_on_file - 1.).max(0.0);
@@ -214,7 +214,7 @@ impl Board {
Color::White => self.occupancy >> 8,
Color::Black => self.occupancy << 8,
};
- result += pop_count(pawns & blocked_mask) as f32;
+ result += (pawns & blocked_mask).pop_count() as f32;
result
}
@@ -224,14 +224,14 @@ impl Board {
pub fn king_tropism(&self, color: Color) -> f32 {
let mut result = 0.0;
- let king_square = bitscan(match color {
+ let king_square = match color {
Color::White => self.pieces[PieceType::King as usize],
Color::Black => self.pieces[PieceType::KingBlack as usize],
- });
+ }.bitscan();
for (piece_type, bitboard) in self.pieces_by_color(color.flip()).iter().enumerate() {
if piece_type != PieceType::King as usize && piece_type != PieceType::Pawn as usize {
- for square in serialize_bitboard(*bitboard) {
+ for square in bitboard.serialize() {
let distance =
(king_square.rank() as f32 - square.rank() as f32).abs() +
(king_square.file() as f32 - square.file() as f32).abs();
diff --git a/src/board/mod.rs b/src/board/mod.rs
index a1166d6..1533ea2 100644
--- a/src/board/mod.rs
+++ b/src/board/mod.rs
@@ -1,7 +1,7 @@
use std::io::{stdin, stdout, Write};
use rand::{rngs::StdRng,SeedableRng,Rng};
-use crate::{bitboard::{Bitboard, serialize_bitboard, bitscan, pop_count}, moves::{Move, MoveKind}, attacks::Attacks, square::Square};
+use crate::{bitboard::{Bitboard, BitboardFns}, moves::{Move, MoveKind}, attacks::Attacks, square::Square};
use self::ttable::{TranspositionTable, TTABLE_SIZE};
mod engine;
@@ -210,7 +210,7 @@ impl Board {
}
for (piece_id, bitboard) in self.pieces.iter().enumerate() {
- for square in serialize_bitboard(*bitboard) {
+ for square in bitboard.serialize() {
self.hash ^= self.zobrist_seed[piece_id * 64 + square as usize];
}
}
@@ -267,7 +267,7 @@ impl Board {
for (piece_id, piece) in player_pieces.iter().enumerate() {
match PieceType::from(piece_id) {
PieceType::Pawn => {
- for source in serialize_bitboard(*piece) {
+ for source in piece.serialize() {
let ep_bitboard = match self.ep_target {
Some(square) => {
let rank = square.rank();
@@ -279,7 +279,7 @@ impl Board {
}
None => 0,
};
- for target in serialize_bitboard(self.attacks.pawn[color as usize][source as usize] & capture_targets) {
+ for target in (self.attacks.pawn[color as usize][source as usize] & capture_targets).serialize() {
moves.push(Move { source, target, kind: MoveKind::Capture });
if target.rank() == 7 {
for promo_type in [PieceType::Bishop, PieceType::Knight, PieceType::Rook, PieceType::Queen] {
@@ -291,10 +291,10 @@ impl Board {
}
}
};
- for target in serialize_bitboard(self.attacks.pawn[color as usize][source as usize] & ep_bitboard) {
+ for target in (self.attacks.pawn[color as usize][source as usize] & ep_bitboard).serialize() {
moves.push(Move { source, target, kind: MoveKind::EnPassant });
}
- for target in serialize_bitboard(self.attacks.pawn_pushes[color as usize][source as usize] & empty) {
+ for target in (self.attacks.pawn_pushes[color as usize][source as usize] & empty).serialize() {
moves.push(Move { source, target, kind: MoveKind::Quiet });
if target.rank() == 7 {
for promo_type in [PieceType::Bishop, PieceType::Knight, PieceType::Rook, PieceType::Queen] {
@@ -314,18 +314,18 @@ impl Board {
Color::White => empty >> 8,
Color::Black => empty << 8,
};
- for source in serialize_bitboard(*piece & able_to_double_push_mask) {
- for target in serialize_bitboard(self.attacks.pawn_double_pushes[color as usize][source as usize] & empty) {
+ for source in (*piece & able_to_double_push_mask).serialize() {
+ for target in (self.attacks.pawn_double_pushes[color as usize][source as usize] & empty).serialize() {
moves.push(Move { source, target, kind: MoveKind::DoublePush });
};
}
}
PieceType::King => {
- for source in serialize_bitboard(*piece) {
- for target in serialize_bitboard(self.attacks.king[source as usize] & empty) {
+ for source in piece.serialize() {
+ for target in (self.attacks.king[source as usize] & empty).serialize() {
moves.push(Move { source, target, kind: MoveKind::Quiet });
};
- for target in serialize_bitboard(self.attacks.king[source as usize] & capture_targets) {
+ for target in (self.attacks.king[source as usize] & capture_targets).serialize() {
moves.push(Move { source, target, kind: MoveKind::Capture });
};
@@ -335,7 +335,7 @@ impl Board {
Color::Black => Square::E8,
};
if *piece == king_home_position.to_bitboard() {
- for rook_square in serialize_bitboard(player_pieces[PieceType::Rook as usize])
+ for rook_square in (player_pieces[PieceType::Rook as usize]).serialize()
.iter()
.filter(|rook_square| rook_square.rank() == king_home_position.rank())
{
@@ -390,43 +390,43 @@ impl Board {
}
}
PieceType::Knight => {
- for source in serialize_bitboard(*piece) {
- for target in serialize_bitboard(self.attacks.knight[source as usize] & empty) {
+ for source in piece.serialize() {
+ for target in (self.attacks.knight[source as usize] & empty).serialize() {
moves.push(Move { source, target, kind: MoveKind::Quiet });
};
- for target in serialize_bitboard(self.attacks.knight[source as usize] & capture_targets) {
+ for target in (self.attacks.knight[source as usize] & capture_targets).serialize() {
moves.push(Move { source, target, kind: MoveKind::Capture });
};
}
}
PieceType::Bishop => {
- for source in serialize_bitboard(*piece) {
- for target in serialize_bitboard(self.attacks.bishop(self.occupancy, source) & empty) {
+ for source in piece.serialize() {
+ for target in (self.attacks.bishop(self.occupancy, source) & empty).serialize() {
moves.push(Move { source, target, kind: MoveKind::Quiet });
};
- for target in serialize_bitboard(self.attacks.bishop(self.occupancy, source) & capture_targets) {
+ for target in (self.attacks.bishop(self.occupancy, source) & capture_targets).serialize() {
moves.push(Move { source, target, kind: MoveKind::Capture });
};
}
}
PieceType::Rook => {
- for source in serialize_bitboard(*piece) {
- for target in serialize_bitboard(self.attacks.rook(self.occupancy, source) & empty) {
+ for source in piece.serialize() {
+ for target in (self.attacks.rook(self.occupancy, source) & empty).serialize() {
moves.push(Move { source, target, kind: MoveKind::Quiet });
};
}
- for source in serialize_bitboard(*piece) {
- for target in serialize_bitboard(self.attacks.rook(self.occupancy, source) & capture_targets) {
+ for source in piece.serialize() {
+ for target in (self.attacks.rook(self.occupancy, source) & capture_targets).serialize() {
moves.push(Move { source, target, kind: MoveKind::Capture });
};
}
}
PieceType::Queen => {
- for source in serialize_bitboard(*piece) {
- for target in serialize_bitboard(self.attacks.queen(self.occupancy, source) & empty) {
+ for source in piece.serialize() {
+ for target in (self.attacks.queen(self.occupancy, source) & empty).serialize() {
moves.push(Move { source, target, kind: MoveKind::Quiet });
};
- for target in serialize_bitboard(self.attacks.queen(self.occupancy, source) & capture_targets) {
+ for target in (self.attacks.queen(self.occupancy, source) & capture_targets).serialize() {
moves.push(Move { source, target, kind: MoveKind::Capture });
};
}
@@ -449,7 +449,7 @@ impl Board {
Color::White => self.pieces[PieceType::PawnBlack as usize],
};
- let pawn_attacked_squares = serialize_bitboard(opponent_pawns).iter().fold(0u64, |acc, square| {
+ let pawn_attacked_squares = opponent_pawns.serialize().iter().fold(0u64, |acc, square| {
acc | self.attacks.pawn[color.flip() as usize][*square as usize]
});
@@ -459,7 +459,7 @@ impl Board {
for (piece_type, piece) in player_pieces.iter().enumerate() {
match PieceType::from(piece_type) {
PieceType::Pawn => {
- for source in serialize_bitboard(*piece) {
+ for source in piece.serialize() {
let ep_bitboard = match self.ep_target {
Some(square) => {
let rank = square.rank();
@@ -471,20 +471,20 @@ impl Board {
}
None => 0,
};
- mobility += pop_count(self.attacks.pawn[color as usize][source as usize] & (opponent_occupancy | ep_bitboard)) as f32;
- mobility += pop_count(self.attacks.pawn_pushes[color as usize][source as usize] & empty) as f32;
+ mobility += (self.attacks.pawn[color as usize][source as usize] & (opponent_occupancy | ep_bitboard)).pop_count() as f32;
+ mobility += (self.attacks.pawn_pushes[color as usize][source as usize] & empty).pop_count() as f32;
}
let able_to_double_push_mask = match color {
Color::White => empty >> 8,
Color::Black => empty << 8,
};
- for source in serialize_bitboard(*piece & able_to_double_push_mask) {
- mobility += pop_count(self.attacks.pawn_double_pushes[color as usize][source as usize] & empty) as f32;
+ for source in (*piece & able_to_double_push_mask).serialize() {
+ mobility += (self.attacks.pawn_double_pushes[color as usize][source as usize] & empty).pop_count() as f32;
}
}
PieceType::King => {
- for source in serialize_bitboard(*piece) {
- mobility += pop_count(self.attacks.king[source as usize] & (empty | opponent_occupancy)) as f32;
+ for source in piece.serialize() {
+ mobility += (self.attacks.king[source as usize] & (empty | opponent_occupancy)).pop_count() as f32;
// Castling
let king_home_position = match color {
@@ -492,7 +492,8 @@ impl Board {
Color::Black => Square::E8,
};
if *piece == king_home_position.to_bitboard() {
- for rook_square in serialize_bitboard(player_pieces[PieceType::Rook as usize])
+ for rook_square in player_pieces[PieceType::Rook as usize]
+ .serialize()
.iter()
.filter(|rook_square| rook_square.rank() == king_home_position.rank())
{
@@ -530,18 +531,18 @@ impl Board {
}
}
PieceType::Knight => {
- for source in serialize_bitboard(*piece) {
- mobility += pop_count(self.attacks.knight[source as usize] & (empty | opponent_occupancy)) as f32;
+ for source in piece.serialize() {
+ mobility += (self.attacks.knight[source as usize] & (empty | opponent_occupancy)).pop_count() as f32;
}
}
PieceType::Bishop => {
- for source in serialize_bitboard(*piece) {
- mobility += pop_count(self.attacks.bishop(self.occupancy, source) & (empty | opponent_occupancy)) as f32;
+ for source in piece.serialize() {
+ mobility += (self.attacks.bishop(self.occupancy, source) & (empty | opponent_occupancy)).pop_count() as f32;
}
}
PieceType::Rook => {
- for source in serialize_bitboard(*piece) {
- mobility += pop_count(self.attacks.rook(self.occupancy, source) & (empty | opponent_occupancy)) as f32;
+ for source in piece.serialize() {
+ mobility += (self.attacks.rook(self.occupancy, source) & (empty | opponent_occupancy)).pop_count() as f32;
}
}
PieceType::Queen => {
@@ -836,7 +837,7 @@ impl Board {
Color::White => self.pieces[PieceType::King as usize],
Color::Black => self.pieces[PieceType::KingBlack as usize],
};
- let square = bitscan(king_bb);
+ let square = king_bb.bitscan();
self.is_square_attacked(square, color.flip())
}
}
@@ -868,7 +869,7 @@ impl Color {
#[cfg(test)]
mod tests {
use super::*;
- use crate::{bitboard::{pop_count, bitscan, print}, square::Square};
+ use crate::{bitboard::BitboardFns, square::Square};
#[test]
fn square_enum() {
@@ -882,29 +883,29 @@ mod tests {
let board = Board::new();
board.print();
- print(board.empty(), "Empty squares");
-
- assert_eq!(pop_count(board.pieces[PieceType::Pawn as usize]), 8);
- assert_eq!(pop_count(board.pieces[PieceType::Knight as usize]), 2);
- assert_eq!(pop_count(board.pieces[PieceType::Bishop as usize]), 2);
- assert_eq!(pop_count(board.pieces[PieceType::Rook as usize]), 2);
- assert_eq!(pop_count(board.pieces[PieceType::Queen as usize]), 1);
- assert_eq!(pop_count(board.pieces[PieceType::King as usize]), 1);
-
- assert_eq!(pop_count(board.pieces[PieceType::PawnBlack as usize]), 8);
- assert_eq!(pop_count(board.pieces[PieceType::KnightBlack as usize]), 2);
- assert_eq!(pop_count(board.pieces[PieceType::BishopBlack as usize]), 2);
- assert_eq!(pop_count(board.pieces[PieceType::RookBlack as usize]), 2);
- assert_eq!(pop_count(board.pieces[PieceType::QueenBlack as usize]), 1);
- assert_eq!(pop_count(board.pieces[PieceType::KingBlack as usize]), 1);
-
- assert_eq!(bitscan(board.pieces[PieceType::King as usize]), Square::E1);
- assert_eq!(bitscan(board.pieces[PieceType::QueenBlack as usize]), Square::D8);
-
- assert_eq!(pop_count(board.occupancy), 32);
- assert_eq!(pop_count(board.empty()), 32);
- assert_eq!(pop_count(board.color_occupancy(Color::White)), 16);
- assert_eq!(pop_count(board.color_occupancy(Color::Black)), 16);
+ board.empty().print("Empty squares");
+
+ assert_eq!(board.pieces[PieceType::Pawn as usize].pop_count(), 8);
+ assert_eq!(board.pieces[PieceType::Knight as usize].pop_count(), 2);
+ assert_eq!(board.pieces[PieceType::Bishop as usize].pop_count(), 2);
+ assert_eq!(board.pieces[PieceType::Rook as usize].pop_count(), 2);
+ assert_eq!(board.pieces[PieceType::Queen as usize].pop_count(), 1);
+ assert_eq!(board.pieces[PieceType::King as usize].pop_count(), 1);
+
+ assert_eq!(board.pieces[PieceType::PawnBlack as usize].pop_count(), 8);
+ assert_eq!(board.pieces[PieceType::KnightBlack as usize].pop_count(), 2);
+ assert_eq!(board.pieces[PieceType::BishopBlack as usize].pop_count(), 2);
+ assert_eq!(board.pieces[PieceType::RookBlack as usize].pop_count(), 2);
+ assert_eq!(board.pieces[PieceType::QueenBlack as usize].pop_count(), 1);
+ assert_eq!(board.pieces[PieceType::KingBlack as usize].pop_count(), 1);
+
+ assert_eq!(board.pieces[PieceType::King as usize].bitscan(), Square::E1);
+ assert_eq!(board.pieces[PieceType::QueenBlack as usize].bitscan(), Square::D8);
+
+ assert_eq!(board.occupancy.pop_count(), 32);
+ assert_eq!(board.empty().pop_count(), 32);
+ assert_eq!(board.color_occupancy(Color::White).pop_count(), 16);
+ assert_eq!(board.color_occupancy(Color::Black).pop_count(), 16);
}
#[test]
diff --git a/src/moves.rs b/src/moves.rs
index 57103d0..58fb979 100644
--- a/src/moves.rs
+++ b/src/moves.rs
@@ -1,4 +1,4 @@
-use crate::{square::Square, bitboard::print, board::PieceType};
+use crate::{square::Square, bitboard::BitboardFns, board::PieceType};
#[derive(Debug, Clone, PartialEq, Eq, Copy)]
pub enum MoveKind {
@@ -20,7 +20,7 @@ pub struct Move {
impl Move {
pub fn print(&self) {
let bb = self.source.to_bitboard() | self.target.to_bitboard();
- print(bb, format!("{:?}", self).as_str());
+ bb.print(format!("{:?}", self).as_str());
}
/// Tactical move is a move that changes material score