aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authoreug-vs <eugene@eug-vs.xyz>2023-01-23 08:47:23 +0300
committereug-vs <eugene@eug-vs.xyz>2023-01-23 08:55:01 +0300
commit6719e247a3e0c75261665eca166fc5c8c8fdaf27 (patch)
tree29e286f0c7b7886a97737cddf0a2d303bfa1bbf9 /src
parent208b35121f9dab4c60c82813b051eeabc9d502cd (diff)
downloadchessnost-6719e247a3e0c75261665eca166fc5c8c8fdaf27.tar.gz
refactor: separately store pawn double pushes
Diffstat (limited to 'src')
-rw-r--r--src/attacks.rs28
-rw-r--r--src/board.rs21
2 files changed, 33 insertions, 16 deletions
diff --git a/src/attacks.rs b/src/attacks.rs
index 5399c96..6762bb3 100644
--- a/src/attacks.rs
+++ b/src/attacks.rs
@@ -45,6 +45,7 @@ pub struct Attacks {
/// TODO: compute pawn attacks set-wise
pub pawn: [AttackTable; 2],
pub pawn_pushes: [AttackTable; 2],
+ pub pawn_double_pushes: [AttackTable; 2],
pub first_rank_attacks: FirstRankAttacks,
/// Should be indexed by Direction
@@ -59,13 +60,14 @@ impl Attacks {
let first_rank_attacks = Self::precompute_first_rank_attacks();
let ray_attacks = Self::precompute_ray_attacks();
let pawn = Self::precompute_pawn_attacks();
- let pawn_pushes = Self::precompute_pawn_pushes();
+ let (pawn_pushes, pawn_double_pushes) = Self::precompute_pawn_pushes();
Self {
knight,
king,
pawn,
pawn_pushes,
+ pawn_double_pushes,
first_rank_attacks,
ray_attacks,
}
@@ -81,14 +83,19 @@ impl Attacks {
attacks
}
- fn precompute_pawn_pushes() -> [AttackTable; 2] {
+ fn precompute_pawn_pushes() -> ([AttackTable; 2], [AttackTable; 2]) {
let mut pushes = [[0; 64]; 2];
+ let mut double_pushes = [[0; 64]; 2];
+
for index in 0..64 {
let square = 1u64 << index;
- pushes[Color::White as usize][index] = (square << 8) | ((square & RANK_2) << 16);
- pushes[Color::Black as usize][index] = (square >> 8) | ((square & RANK_6) >> 16);
+ pushes [Color::White as usize][index] = (square << 8);
+ double_pushes[Color::White as usize][index] = ((square & RANK_2) << 16);
+
+ pushes [Color::Black as usize][index] = (square >> 8);
+ double_pushes[Color::Black as usize][index] = ((square & RANK_6) >> 16);
}
- pushes
+ (pushes, double_pushes)
}
fn precompute_knight_attacks() -> AttackTable {
@@ -332,11 +339,16 @@ mod tests {
#[test]
fn test_pawn_pushes() {
- let pushes = Attacks::precompute_pawn_pushes();
+ let (pushes, double_pushes) = Attacks::precompute_pawn_pushes();
assert_eq!(pushes[Color::White as usize][Square::E4 as usize], Square::E5.to_bitboard());
- assert_eq!(pushes[Color::White as usize][Square::A2 as usize], Square::A3.to_bitboard() | Square::A4.to_bitboard());
+ assert_eq!(pushes[Color::White as usize][Square::A2 as usize], Square::A3.to_bitboard());
assert_eq!(pushes[Color::Black as usize][Square::E4 as usize], Square::E3.to_bitboard());
- assert_eq!(pushes[Color::Black as usize][Square::H6 as usize], Square::H5.to_bitboard() | Square::H4.to_bitboard());
+ assert_eq!(pushes[Color::Black as usize][Square::H6 as usize], Square::H5.to_bitboard());
+
+ assert_eq!(double_pushes[Color::White as usize][Square::E4 as usize], 0);
+ assert_eq!(double_pushes[Color::White as usize][Square::A2 as usize], Square::A4.to_bitboard());
+ assert_eq!(double_pushes[Color::Black as usize][Square::E4 as usize], 0);
+ assert_eq!(double_pushes[Color::Black as usize][Square::H6 as usize], Square::H4.to_bitboard());
}
#[test]
diff --git a/src/board.rs b/src/board.rs
index 625711e..24bdefa 100644
--- a/src/board.rs
+++ b/src/board.rs
@@ -144,7 +144,8 @@ impl Board {
pub fn generate_moves(&self, color: Color) -> Vec<Move> {
let mut moves = Vec::with_capacity(1024);
let opponent_occupancy = self.color_occupancy(Color::from(1 - color as u8));
- let available_targets = opponent_occupancy | self.empty();
+ let empty = self.empty();
+ let available_targets = opponent_occupancy | empty;
for (piece_type, piece) in self.pieces_by_color(color).iter().enumerate() {
match PieceType::from(piece_type) {
PieceType::Pawn => {
@@ -152,14 +153,18 @@ impl Board {
for target in serialize_bitboard(self.attacks.pawn[color as usize][source as usize] & opponent_occupancy) {
moves.push(Move { source, target });
};
- }
- for source in serialize_bitboard(*piece) {
for target in serialize_bitboard(self.attacks.pawn_pushes[color as usize][source as usize] & available_targets) {
- // Exclude double pushes in a monkey way
- // TODO: properly rewrite this storing a separate bitboard for double pushes
- if !((source as u8 / 8 == 1) && (target as u8 / 8 == 3) && (self.occupancy & (1 << (source as u8 + 8)) > 0)) {
- moves.push(Move { source, target });
- }
+ moves.push(Move { source, target });
+ };
+ }
+
+ 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) {
+ for target in serialize_bitboard(self.attacks.pawn_double_pushes[color as usize][source as usize] & available_targets) {
+ moves.push(Move { source, target });
};
}
}