diff options
author | eug-vs <eugene@eug-vs.xyz> | 2023-01-21 04:34:32 +0300 |
---|---|---|
committer | eug-vs <eugene@eug-vs.xyz> | 2023-01-21 04:42:44 +0300 |
commit | 56f80a81852ef9fa6c1654c8548751fb898f2fb3 (patch) | |
tree | 2eb1fc091237f1eef2909a3802cf1728e41e9dd0 /src | |
parent | d788e73ea5240f72d3ca64a5ce2bad5026643ebd (diff) | |
download | chessnost-56f80a81852ef9fa6c1654c8548751fb898f2fb3.tar.gz |
feat: precompute knight and king attacks
Diffstat (limited to 'src')
-rw-r--r-- | src/attacks.rs | 99 | ||||
-rw-r--r-- | src/bitboard.rs | 1 | ||||
-rw-r--r-- | src/board.rs | 6 | ||||
-rw-r--r-- | src/main.rs | 1 |
4 files changed, 104 insertions, 3 deletions
diff --git a/src/attacks.rs b/src/attacks.rs new file mode 100644 index 0000000..ece87b6 --- /dev/null +++ b/src/attacks.rs @@ -0,0 +1,99 @@ +use crate::bitboard::Bitboard; + +static NOT_A_FILE: Bitboard = 0xFEFEFEFEFEFEFEFE; +static NOT_B_FILE: Bitboard = 0xFDFDFDFDFDFDFDFD; +static NOT_G_FILE: Bitboard = 0xBFBFBFBFBFBFBFBF; +static NOT_H_FILE: Bitboard = 0x7F7F7F7F7F7F7F7F; + +type AttackTable = [Bitboard; 64]; + +#[derive(Debug)] +pub struct Attacks { + pub knight: AttackTable, + pub king: AttackTable, +} + +impl Attacks { + pub fn new() -> Self { + let mut knight = [0; 64]; + let mut king = [0; 64]; + Self::precompute_knight_attacks(&mut knight); + Self::precompute_king_attacks(&mut king); + Self { knight, king } + } + + fn precompute_knight_attacks(attacks: &mut AttackTable) { + for index in 0..64 { + let position = 1u64 << index; + attacks[index] = + ((position & NOT_A_FILE & NOT_B_FILE) << 6) | + ((position & NOT_G_FILE & NOT_H_FILE) << 10) | + ((position & NOT_A_FILE) << 15) | + ((position & NOT_H_FILE) << 17) | + ((position & NOT_G_FILE & NOT_H_FILE) >> 6) | + ((position & NOT_A_FILE & NOT_B_FILE) >> 10) | + ((position & NOT_H_FILE) >> 15) | + ((position & NOT_A_FILE) >> 17); + } + } + + fn precompute_king_attacks(attacks: &mut AttackTable) { + for index in 0..64 { + let position = 1u64 << index; + attacks[index] = + ((position & NOT_A_FILE) >> 1) | + ((position & NOT_A_FILE) << 7) | + ((position & NOT_A_FILE) >> 9) | + ((position & NOT_H_FILE) << 1) | + ((position & NOT_H_FILE) >> 7) | + ((position & NOT_H_FILE) << 9) | + (position << 8) | + (position >> 8); + } + } +} + +#[cfg(test)] +mod tests { + use crate::{bitboard::pop_count, board::Square}; + + use super::*; + + #[test] + fn test_knight_attacks() { + let attacks = Attacks::new(); + let e4_attacks = attacks.knight[Square::E4 as usize]; + + assert_ne!(e4_attacks & 1 << Square::G5 as usize, 0); + assert_ne!(e4_attacks & 1 << Square::G3 as usize, 0); + assert_ne!(e4_attacks & 1 << Square::C5 as usize, 0); + assert_ne!(e4_attacks & 1 << Square::C3 as usize, 0); + assert_ne!(e4_attacks & 1 << Square::D2 as usize, 0); + assert_ne!(e4_attacks & 1 << Square::F2 as usize, 0); + assert_ne!(e4_attacks & 1 << Square::D6 as usize, 0); + assert_ne!(e4_attacks & 1 << Square::F6 as usize, 0); + + assert_eq!(e4_attacks & 1 << Square::E5 as usize, 0); + assert_eq!(e4_attacks & 1 << Square::D4 as usize, 0); + assert_eq!(e4_attacks & 1 << Square::A1 as usize, 0); + + assert_eq!(pop_count(attacks.knight[Square::G1 as usize]), 3); + assert_eq!(pop_count(attacks.knight[Square::H8 as usize]), 2); + } + + #[test] + fn test_king_attacks() { + let attacks = Attacks::new(); + assert_eq!(pop_count(attacks.king[Square::E4 as usize]), 8); + + assert_eq!(pop_count(attacks.king[Square::A1 as usize]), 3); + assert_eq!(pop_count(attacks.king[Square::A8 as usize]), 3); + assert_eq!(pop_count(attacks.king[Square::H1 as usize]), 3); + assert_eq!(pop_count(attacks.king[Square::H8 as usize]), 3); + + assert_eq!(pop_count(attacks.king[Square::E1 as usize]), 5); + assert_eq!(pop_count(attacks.king[Square::E8 as usize]), 5); + assert_eq!(pop_count(attacks.king[Square::A4 as usize]), 5); + assert_eq!(pop_count(attacks.king[Square::H4 as usize]), 5); + } +} diff --git a/src/bitboard.rs b/src/bitboard.rs index 4a1ef50..6481863 100644 --- a/src/bitboard.rs +++ b/src/bitboard.rs @@ -1,3 +1,4 @@ +/// 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 diff --git a/src/board.rs b/src/board.rs index 991820a..13f86ec 100644 --- a/src/board.rs +++ b/src/board.rs @@ -6,7 +6,7 @@ pub struct Board { } -enum PieceTypes { +pub enum PieceTypes { Pawn, PawnBlack, Knight, @@ -107,14 +107,14 @@ impl Board { } -enum Color { +pub enum Color { White, Black, } /// Aliases to board square indexes #[allow(dead_code)] -enum Square { +pub enum Square { A1, B1, C1, D1, E1, F1, G1, H1, A2, B2, C2, D2, E2, F2, G2, H2, A3, B3, C3, D3, E3, F3, G3, H3, diff --git a/src/main.rs b/src/main.rs index 11ac972..dc04d4b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,6 @@ mod bitboard; mod board; +mod attacks; fn main() { println!("Hello, world!"); |