implement is_square_attacked and is_king_attacked

This commit is contained in:
Moritz 2025-11-13 22:59:26 +01:00
parent 1ddc38165f
commit e305a3556f
6 changed files with 463 additions and 12 deletions

View file

@ -0,0 +1,89 @@
#!/usr/bin/env python3
def generate_pawn_attacked_by():
"""
Generates a list of 64 u64 bitboards for each color (White, Black),
where each bitboard represents the squares FROM WHICH a pawn
can attack a given TARGET square.
Uses Little-Endian File-Rank (LEFR) mapping: A1=0, H1=7, A2=8, ..., H8=63.
Returns:
[[u64; 64]; 2] (represented as a list of two lists)
Index 0: White attackers (squares where a White pawn attacks the target)
Index 1: Black attackers (squares where a Black pawn attacks the target)
"""
# all_attacks[0] = White, all_attacks[1] = Black
all_attacks = [[], []]
for sq in range(64):
rank = sq // 8
file = sq % 8
white_attackers_bb = 0
black_attackers_bb = 0
# --- White Attackers (Index 0) ---
# A white pawn attacks "up" the board to reach the target square 'sq'.
# This means the attacking pawn must be "below" 'sq'.
# We only check if the target is not on the 1st rank
if rank > 0:
# Attacker from Down-Left (relative to target sq)
# Not possible if target is on the A-file
if file > 0:
white_attackers_bb |= (1 << (sq - 9))
# Attacker from Down-Right (relative to target sq)
# Not possible if target is on the H-file
if file < 7:
white_attackers_bb |= (1 << (sq - 7))
# --- Black Attackers (Index 1) ---
# A black pawn attacks "down" the board to reach the target square 'sq'.
# This means the attacking pawn must be "above" 'sq'.
# We only check if the target is not on the 8th rank
if rank < 7:
# Attacker from Up-Left (relative to target sq)
# Not possible if target is on the A-file
if file > 0:
black_attackers_bb |= (1 << (sq + 7))
# Attacker from Up-Right (relative to target sq)
# Not possible if target is on the H-file
if file < 7:
black_attackers_bb |= (1 << (sq + 9))
all_attacks[0].append(white_attackers_bb)
all_attacks[1].append(black_attackers_bb)
return all_attacks
def print_rust_array(attacks_by_color, const_name):
"""
Prints the list of attack bitboards as a nested Rust array.
"""
print(f"pub const {const_name}: [[u64; 64]; 2] = [")
# --- Print White Attacks ---
print(" [ // Color 0: White (Squares a White pawn attacks FROM)")
for i, attacks_bb in enumerate(attacks_by_color[0]):
raw_binary_string = f"{attacks_bb:064b}"
chunks = [raw_binary_string[i:i+8] for i in range(0, 64, 8)]
binary_string = f"0b{'_'.join(chunks)}"
print(f" {binary_string}, // Target Square {i} ({'ABCDEFGH'[i%8]}{i//8 + 1})")
print(" ],")
# --- Print Black Attacks ---
print(" [ // Color 1: Black (Squares a Black pawn attacks FROM)")
for i, attacks_bb in enumerate(attacks_by_color[1]):
raw_binary_string = f"{attacks_bb:064b}"
chunks = [raw_binary_string[i:i+8] for i in range(0, 64, 8)]
binary_string = f"0b{'_'.join(chunks)}"
print(f" {binary_string}, // Target Square {i} ({'ABCDEFGH'[i%8]}{i//8 + 1})")
print(" ]")
print("];")
if __name__ == "__main__":
attacks = generate_pawn_attacked_by()
print_rust_array(attacks, "ATTACKING_PAWNS")

View file

@ -1,6 +1,7 @@
use std::fmt;
use crate::board::{Board, Color, PieceType}; use crate::board::{Board, Color, PieceType};
use crate::r#move::{Move, MoveList, MOVE_FLAG_BK_CASTLE, MOVE_FLAG_BQ_CASTLE, MOVE_FLAG_PROMO_B, MOVE_FLAG_PROMO_B_CAP, MOVE_FLAG_PROMO_N, MOVE_FLAG_PROMO_N_CAP, MOVE_FLAG_PROMO_Q, MOVE_FLAG_PROMO_Q_CAP, MOVE_FLAG_PROMO_R, MOVE_FLAG_PROMO_R_CAP, MOVE_FLAG_WK_CASTLE, MOVE_FLAG_WQ_CASTLE, MOVE_FROM_MASK, MOVE_TO_MASK}; use crate::r#move::MoveList;
use crate::square::Square;
use std::fmt;
impl Board { impl Board {
/// Prints the board as a human-readable ASCII grid. /// Prints the board as a human-readable ASCII grid.
@ -12,7 +13,7 @@ impl Board {
let sq = (rank * 8 + file) as u8; let sq = (rank * 8 + file) as u8;
let mask = 1u64 << sq; let mask = 1u64 << sq;
if let Some(piece) = self.get_piece_at(mask) { if let Some(piece) = self.get_piece_at_unicode(mask) {
print!("{} ", piece); print!("{} ", piece);
} else { } else {
print!(". "); print!(". ");
@ -45,7 +46,7 @@ impl Board {
println!(); println!();
} }
/// Helper function to find which piece (as a char) is on a given square mask. /// Helper function to find which piece (as a FEN char) is on a given square mask.
pub fn get_piece_at(&self, sq_mask: u64) -> Option<char> { pub fn get_piece_at(&self, sq_mask: u64) -> Option<char> {
let white = Color::White as usize; let white = Color::White as usize;
let black = Color::Black as usize; let black = Color::Black as usize;
@ -90,6 +91,51 @@ impl Board {
None None
} }
/// Helper function to find which piece (as a unicode char) is on a given square mask.
pub fn get_piece_at_unicode(&self, sq_mask: u64) -> Option<char> {
let white = Color::White as usize;
let black = Color::Black as usize;
if (self.pieces[PieceType::Pawn as usize][white] & sq_mask) != 0 {
return Some('♙');
}
if (self.pieces[PieceType::Pawn as usize][black] & sq_mask) != 0 {
return Some('♟');
}
if (self.pieces[PieceType::Knight as usize][white] & sq_mask) != 0 {
return Some('♘');
}
if (self.pieces[PieceType::Knight as usize][black] & sq_mask) != 0 {
return Some('♞');
}
if (self.pieces[PieceType::Bishop as usize][white] & sq_mask) != 0 {
return Some('♗');
}
if (self.pieces[PieceType::Bishop as usize][black] & sq_mask) != 0 {
return Some('♝');
}
if (self.pieces[PieceType::Rook as usize][white] & sq_mask) != 0 {
return Some('♖');
}
if (self.pieces[PieceType::Rook as usize][black] & sq_mask) != 0 {
return Some('♜');
}
if (self.pieces[PieceType::Queen as usize][white] & sq_mask) != 0 {
return Some('♕');
}
if (self.pieces[PieceType::Queen as usize][black] & sq_mask) != 0 {
return Some('♛');
}
if (self.pieces[PieceType::King as usize][white] & sq_mask) != 0 {
return Some('♔');
}
if (self.pieces[PieceType::King as usize][black] & sq_mask) != 0 {
return Some('♚');
}
None
}
/// Prints all internal bitboards for debugging purposes. /// Prints all internal bitboards for debugging purposes.
pub fn pretty_print_internals(&self) { pub fn pretty_print_internals(&self) {
println!("\n========= BOARD INTERNAL BITBOARDS ========="); println!("\n========= BOARD INTERNAL BITBOARDS =========");
@ -145,6 +191,85 @@ impl Board {
impl fmt::Display for MoveList { impl fmt::Display for MoveList {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", &self.iter().map(|mv| mv.to_algebraic()).collect::<Vec<String>>().join(" ")) write!(
f,
"{}",
&self
.iter()
.map(|mv| mv.to_algebraic())
.collect::<Vec<String>>()
.join(" ")
)
}
}
impl fmt::Display for Square {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Square::A1 => write!(f, "A1"),
Square::B1 => write!(f, "B1"),
Square::C1 => write!(f, "C1"),
Square::D1 => write!(f, "D1"),
Square::E1 => write!(f, "E1"),
Square::F1 => write!(f, "F1"),
Square::G1 => write!(f, "G1"),
Square::H1 => write!(f, "H1"),
Square::A2 => write!(f, "A2"),
Square::B2 => write!(f, "B2"),
Square::C2 => write!(f, "C2"),
Square::D2 => write!(f, "D2"),
Square::E2 => write!(f, "E2"),
Square::F2 => write!(f, "F2"),
Square::G2 => write!(f, "G2"),
Square::H2 => write!(f, "H2"),
Square::A3 => write!(f, "A3"),
Square::B3 => write!(f, "B3"),
Square::C3 => write!(f, "C3"),
Square::D3 => write!(f, "D3"),
Square::E3 => write!(f, "E3"),
Square::F3 => write!(f, "F3"),
Square::G3 => write!(f, "G3"),
Square::H3 => write!(f, "H3"),
Square::A4 => write!(f, "A4"),
Square::B4 => write!(f, "B4"),
Square::C4 => write!(f, "C4"),
Square::D4 => write!(f, "D4"),
Square::E4 => write!(f, "E4"),
Square::F4 => write!(f, "F4"),
Square::G4 => write!(f, "G4"),
Square::H4 => write!(f, "H4"),
Square::A5 => write!(f, "A5"),
Square::B5 => write!(f, "B5"),
Square::C5 => write!(f, "C5"),
Square::D5 => write!(f, "D5"),
Square::E5 => write!(f, "E5"),
Square::F5 => write!(f, "F5"),
Square::G5 => write!(f, "G5"),
Square::H5 => write!(f, "H5"),
Square::A6 => write!(f, "A6"),
Square::B6 => write!(f, "B6"),
Square::C6 => write!(f, "C6"),
Square::D6 => write!(f, "D6"),
Square::E6 => write!(f, "E6"),
Square::F6 => write!(f, "F6"),
Square::G6 => write!(f, "G6"),
Square::H6 => write!(f, "H6"),
Square::A7 => write!(f, "A7"),
Square::B7 => write!(f, "B7"),
Square::C7 => write!(f, "C7"),
Square::D7 => write!(f, "D7"),
Square::E7 => write!(f, "E7"),
Square::F7 => write!(f, "F7"),
Square::G7 => write!(f, "G7"),
Square::H7 => write!(f, "H7"),
Square::A8 => write!(f, "A8"),
Square::B8 => write!(f, "B8"),
Square::C8 => write!(f, "C8"),
Square::D8 => write!(f, "D8"),
Square::E8 => write!(f, "E8"),
Square::F8 => write!(f, "F8"),
Square::G8 => write!(f, "G8"),
Square::H8 => write!(f, "H8")
}
} }
} }

View file

@ -0,0 +1,74 @@
use crate::board::{Board, Color, PieceType};
use crate::movegen::tables::{get_bishop_attacks, get_rook_attacks, ATTACKING_PAWNS, KING_ATTACKS, KNIGHT_ATTACKS, MAGICS_BISHOP, MAGICS_ROOK, PREMASKS_BISHOP, PREMASKS_ROOK, RELEVANT_BITS_BISHOP, RELEVANT_BITS_ROOK};
use crate::square::{Square, SQUARES};
/// Checks if the king of the side that is NOT to move is in check
pub fn is_king_attacked(board: &Board) -> bool {
let king = board.pieces[PieceType::King as usize][!board.side_to_move as usize];
is_square_attacked(board, SQUARES[king.trailing_zeros() as usize], board.side_to_move)
}
// TODO check if castle is legal (squares in between)
/// calculate if a square on the board is attacked by a color
pub fn is_square_attacked(board: &Board, square: Square, color: Color) -> bool {
// 1. Non sliding
// 1.1 Pawn
let pawns = board.pieces[PieceType::Pawn as usize][color as usize];
if (pawns & ATTACKING_PAWNS[color as usize][square as usize]) != 0 {
return true;
}
// 1.2 Knight
let knights = board.pieces[PieceType::Knight as usize][color as usize];
if (knights & KNIGHT_ATTACKS[square as usize]) != 0 {
return true;
}
// 1.3 King
let king = board.pieces[PieceType::King as usize][color as usize];
if (king & KING_ATTACKS[square as usize]) != 0 {
return true;
}
// 2. Sliding
let blockers = board.all_occupied;
// 2.1 Bishop (and part of Queen)
let premask_bishop = PREMASKS_BISHOP[square as usize];
let magic_bishop = MAGICS_BISHOP[square as usize];
let relevant_bits_bishop = RELEVANT_BITS_BISHOP[square as usize];
let shift_bishop = 64 - relevant_bits_bishop;
let attack_table_bishop = get_bishop_attacks();
let magic_index_bishop = ((blockers & premask_bishop).wrapping_mul(magic_bishop)) >> shift_bishop;
let bishop_attackable_squares = attack_table_bishop[square as usize][magic_index_bishop as usize];
let bishops = board.pieces[PieceType::Bishop as usize][color as usize];
if (bishop_attackable_squares & bishops) != 0 {
return true;
}
// 2.2 Rooks (and part of Queen)
let premask_rook = PREMASKS_ROOK[square as usize];
let magic_rook = MAGICS_ROOK[square as usize];
let relevant_bits_rook = RELEVANT_BITS_ROOK[square as usize];
let shift_rook = 64 - relevant_bits_rook;
let attack_table_rook = get_rook_attacks();
let magic_index_rook = ((blockers & premask_rook).wrapping_mul(magic_rook)) >> shift_rook;
let rook_attackable_squares = attack_table_rook[square as usize][magic_index_rook as usize];
let rooks = board.pieces[PieceType::Rook as usize][color as usize];
if (rook_attackable_squares & rooks) != 0 {
return true;
}
// 2.3 Queens
let queen_attackable_squares = bishop_attackable_squares | rook_attackable_squares;
let queens = board.pieces[PieceType::Queen as usize][color as usize];
if (queen_attackable_squares & queens) != 0 {
return true;
}
// No attackers found
false
}

View file

@ -1,13 +1,14 @@
use crate::board::Board;
use crate::movegen::non_sliders::{generate_king_moves, generate_knight_moves};
use crate::movegen::pawns::generate_pawn_moves;
use crate::movegen::sliders::{generate_bishop_moves, generate_queen_moves, generate_rook_moves};
use crate::r#move::MoveList;
pub mod non_sliders; pub mod non_sliders;
pub mod sliders; pub mod sliders;
pub mod pawns; pub mod pawns;
pub mod tables; pub mod tables;
pub mod legal_check;
use crate::board::Board;
use crate::r#move::*;
use non_sliders::*;
use sliders::*;
use pawns::*;
pub fn generate_pseudo_legal_moves(board: &Board, list: &mut MoveList) { pub fn generate_pseudo_legal_moves(board: &Board, list: &mut MoveList) {
generate_pawn_moves(board, list); generate_pawn_moves(board, list);

View file

@ -1,6 +1,141 @@
use std::sync::OnceLock; use std::sync::OnceLock;
pub const ATTACKING_PAWNS: [[u64; 64]; 2] = [
[ // Color 0: White (Squares a White pawn attacks FROM)
0b00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000, // Target Square 0 (A1)
0b00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000, // Target Square 1 (B1)
0b00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000, // Target Square 2 (C1)
0b00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000, // Target Square 3 (D1)
0b00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000, // Target Square 4 (E1)
0b00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000, // Target Square 5 (F1)
0b00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000, // Target Square 6 (G1)
0b00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000, // Target Square 7 (H1)
0b00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000010, // Target Square 8 (A2)
0b00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000101, // Target Square 9 (B2)
0b00000000_00000000_00000000_00000000_00000000_00000000_00000000_00001010, // Target Square 10 (C2)
0b00000000_00000000_00000000_00000000_00000000_00000000_00000000_00010100, // Target Square 11 (D2)
0b00000000_00000000_00000000_00000000_00000000_00000000_00000000_00101000, // Target Square 12 (E2)
0b00000000_00000000_00000000_00000000_00000000_00000000_00000000_01010000, // Target Square 13 (F2)
0b00000000_00000000_00000000_00000000_00000000_00000000_00000000_10100000, // Target Square 14 (G2)
0b00000000_00000000_00000000_00000000_00000000_00000000_00000000_01000000, // Target Square 15 (H2)
0b00000000_00000000_00000000_00000000_00000000_00000000_00000010_00000000, // Target Square 16 (A3)
0b00000000_00000000_00000000_00000000_00000000_00000000_00000101_00000000, // Target Square 17 (B3)
0b00000000_00000000_00000000_00000000_00000000_00000000_00001010_00000000, // Target Square 18 (C3)
0b00000000_00000000_00000000_00000000_00000000_00000000_00010100_00000000, // Target Square 19 (D3)
0b00000000_00000000_00000000_00000000_00000000_00000000_00101000_00000000, // Target Square 20 (E3)
0b00000000_00000000_00000000_00000000_00000000_00000000_01010000_00000000, // Target Square 21 (F3)
0b00000000_00000000_00000000_00000000_00000000_00000000_10100000_00000000, // Target Square 22 (G3)
0b00000000_00000000_00000000_00000000_00000000_00000000_01000000_00000000, // Target Square 23 (H3)
0b00000000_00000000_00000000_00000000_00000000_00000010_00000000_00000000, // Target Square 24 (A4)
0b00000000_00000000_00000000_00000000_00000000_00000101_00000000_00000000, // Target Square 25 (B4)
0b00000000_00000000_00000000_00000000_00000000_00001010_00000000_00000000, // Target Square 26 (C4)
0b00000000_00000000_00000000_00000000_00000000_00010100_00000000_00000000, // Target Square 27 (D4)
0b00000000_00000000_00000000_00000000_00000000_00101000_00000000_00000000, // Target Square 28 (E4)
0b00000000_00000000_00000000_00000000_00000000_01010000_00000000_00000000, // Target Square 29 (F4)
0b00000000_00000000_00000000_00000000_00000000_10100000_00000000_00000000, // Target Square 30 (G4)
0b00000000_00000000_00000000_00000000_00000000_01000000_00000000_00000000, // Target Square 31 (H4)
0b00000000_00000000_00000000_00000000_00000010_00000000_00000000_00000000, // Target Square 32 (A5)
0b00000000_00000000_00000000_00000000_00000101_00000000_00000000_00000000, // Target Square 33 (B5)
0b00000000_00000000_00000000_00000000_00001010_00000000_00000000_00000000, // Target Square 34 (C5)
0b00000000_00000000_00000000_00000000_00010100_00000000_00000000_00000000, // Target Square 35 (D5)
0b00000000_00000000_00000000_00000000_00101000_00000000_00000000_00000000, // Target Square 36 (E5)
0b00000000_00000000_00000000_00000000_01010000_00000000_00000000_00000000, // Target Square 37 (F5)
0b00000000_00000000_00000000_00000000_10100000_00000000_00000000_00000000, // Target Square 38 (G5)
0b00000000_00000000_00000000_00000000_01000000_00000000_00000000_00000000, // Target Square 39 (H5)
0b00000000_00000000_00000000_00000010_00000000_00000000_00000000_00000000, // Target Square 40 (A6)
0b00000000_00000000_00000000_00000101_00000000_00000000_00000000_00000000, // Target Square 41 (B6)
0b00000000_00000000_00000000_00001010_00000000_00000000_00000000_00000000, // Target Square 42 (C6)
0b00000000_00000000_00000000_00010100_00000000_00000000_00000000_00000000, // Target Square 43 (D6)
0b00000000_00000000_00000000_00101000_00000000_00000000_00000000_00000000, // Target Square 44 (E6)
0b00000000_00000000_00000000_01010000_00000000_00000000_00000000_00000000, // Target Square 45 (F6)
0b00000000_00000000_00000000_10100000_00000000_00000000_00000000_00000000, // Target Square 46 (G6)
0b00000000_00000000_00000000_01000000_00000000_00000000_00000000_00000000, // Target Square 47 (H6)
0b00000000_00000000_00000010_00000000_00000000_00000000_00000000_00000000, // Target Square 48 (A7)
0b00000000_00000000_00000101_00000000_00000000_00000000_00000000_00000000, // Target Square 49 (B7)
0b00000000_00000000_00001010_00000000_00000000_00000000_00000000_00000000, // Target Square 50 (C7)
0b00000000_00000000_00010100_00000000_00000000_00000000_00000000_00000000, // Target Square 51 (D7)
0b00000000_00000000_00101000_00000000_00000000_00000000_00000000_00000000, // Target Square 52 (E7)
0b00000000_00000000_01010000_00000000_00000000_00000000_00000000_00000000, // Target Square 53 (F7)
0b00000000_00000000_10100000_00000000_00000000_00000000_00000000_00000000, // Target Square 54 (G7)
0b00000000_00000000_01000000_00000000_00000000_00000000_00000000_00000000, // Target Square 55 (H7)
0b00000000_00000010_00000000_00000000_00000000_00000000_00000000_00000000, // Target Square 56 (A8)
0b00000000_00000101_00000000_00000000_00000000_00000000_00000000_00000000, // Target Square 57 (B8)
0b00000000_00001010_00000000_00000000_00000000_00000000_00000000_00000000, // Target Square 58 (C8)
0b00000000_00010100_00000000_00000000_00000000_00000000_00000000_00000000, // Target Square 59 (D8)
0b00000000_00101000_00000000_00000000_00000000_00000000_00000000_00000000, // Target Square 60 (E8)
0b00000000_01010000_00000000_00000000_00000000_00000000_00000000_00000000, // Target Square 61 (F8)
0b00000000_10100000_00000000_00000000_00000000_00000000_00000000_00000000, // Target Square 62 (G8)
0b00000000_01000000_00000000_00000000_00000000_00000000_00000000_00000000, // Target Square 63 (H8)
],
[ // Color 1: Black (Squares a Black pawn attacks FROM)
0b00000000_00000000_00000000_00000000_00000000_00000000_00000010_00000000, // Target Square 0 (A1)
0b00000000_00000000_00000000_00000000_00000000_00000000_00000101_00000000, // Target Square 1 (B1)
0b00000000_00000000_00000000_00000000_00000000_00000000_00001010_00000000, // Target Square 2 (C1)
0b00000000_00000000_00000000_00000000_00000000_00000000_00010100_00000000, // Target Square 3 (D1)
0b00000000_00000000_00000000_00000000_00000000_00000000_00101000_00000000, // Target Square 4 (E1)
0b00000000_00000000_00000000_00000000_00000000_00000000_01010000_00000000, // Target Square 5 (F1)
0b00000000_00000000_00000000_00000000_00000000_00000000_10100000_00000000, // Target Square 6 (G1)
0b00000000_00000000_00000000_00000000_00000000_00000000_01000000_00000000, // Target Square 7 (H1)
0b00000000_00000000_00000000_00000000_00000000_00000010_00000000_00000000, // Target Square 8 (A2)
0b00000000_00000000_00000000_00000000_00000000_00000101_00000000_00000000, // Target Square 9 (B2)
0b00000000_00000000_00000000_00000000_00000000_00001010_00000000_00000000, // Target Square 10 (C2)
0b00000000_00000000_00000000_00000000_00000000_00010100_00000000_00000000, // Target Square 11 (D2)
0b00000000_00000000_00000000_00000000_00000000_00101000_00000000_00000000, // Target Square 12 (E2)
0b00000000_00000000_00000000_00000000_00000000_01010000_00000000_00000000, // Target Square 13 (F2)
0b00000000_00000000_00000000_00000000_00000000_10100000_00000000_00000000, // Target Square 14 (G2)
0b00000000_00000000_00000000_00000000_00000000_01000000_00000000_00000000, // Target Square 15 (H2)
0b00000000_00000000_00000000_00000000_00000010_00000000_00000000_00000000, // Target Square 16 (A3)
0b00000000_00000000_00000000_00000000_00000101_00000000_00000000_00000000, // Target Square 17 (B3)
0b00000000_00000000_00000000_00000000_00001010_00000000_00000000_00000000, // Target Square 18 (C3)
0b00000000_00000000_00000000_00000000_00010100_00000000_00000000_00000000, // Target Square 19 (D3)
0b00000000_00000000_00000000_00000000_00101000_00000000_00000000_00000000, // Target Square 20 (E3)
0b00000000_00000000_00000000_00000000_01010000_00000000_00000000_00000000, // Target Square 21 (F3)
0b00000000_00000000_00000000_00000000_10100000_00000000_00000000_00000000, // Target Square 22 (G3)
0b00000000_00000000_00000000_00000000_01000000_00000000_00000000_00000000, // Target Square 23 (H3)
0b00000000_00000000_00000000_00000010_00000000_00000000_00000000_00000000, // Target Square 24 (A4)
0b00000000_00000000_00000000_00000101_00000000_00000000_00000000_00000000, // Target Square 25 (B4)
0b00000000_00000000_00000000_00001010_00000000_00000000_00000000_00000000, // Target Square 26 (C4)
0b00000000_00000000_00000000_00010100_00000000_00000000_00000000_00000000, // Target Square 27 (D4)
0b00000000_00000000_00000000_00101000_00000000_00000000_00000000_00000000, // Target Square 28 (E4)
0b00000000_00000000_00000000_01010000_00000000_00000000_00000000_00000000, // Target Square 29 (F4)
0b00000000_00000000_00000000_10100000_00000000_00000000_00000000_00000000, // Target Square 30 (G4)
0b00000000_00000000_00000000_01000000_00000000_00000000_00000000_00000000, // Target Square 31 (H4)
0b00000000_00000000_00000010_00000000_00000000_00000000_00000000_00000000, // Target Square 32 (A5)
0b00000000_00000000_00000101_00000000_00000000_00000000_00000000_00000000, // Target Square 33 (B5)
0b00000000_00000000_00001010_00000000_00000000_00000000_00000000_00000000, // Target Square 34 (C5)
0b00000000_00000000_00010100_00000000_00000000_00000000_00000000_00000000, // Target Square 35 (D5)
0b00000000_00000000_00101000_00000000_00000000_00000000_00000000_00000000, // Target Square 36 (E5)
0b00000000_00000000_01010000_00000000_00000000_00000000_00000000_00000000, // Target Square 37 (F5)
0b00000000_00000000_10100000_00000000_00000000_00000000_00000000_00000000, // Target Square 38 (G5)
0b00000000_00000000_01000000_00000000_00000000_00000000_00000000_00000000, // Target Square 39 (H5)
0b00000000_00000010_00000000_00000000_00000000_00000000_00000000_00000000, // Target Square 40 (A6)
0b00000000_00000101_00000000_00000000_00000000_00000000_00000000_00000000, // Target Square 41 (B6)
0b00000000_00001010_00000000_00000000_00000000_00000000_00000000_00000000, // Target Square 42 (C6)
0b00000000_00010100_00000000_00000000_00000000_00000000_00000000_00000000, // Target Square 43 (D6)
0b00000000_00101000_00000000_00000000_00000000_00000000_00000000_00000000, // Target Square 44 (E6)
0b00000000_01010000_00000000_00000000_00000000_00000000_00000000_00000000, // Target Square 45 (F6)
0b00000000_10100000_00000000_00000000_00000000_00000000_00000000_00000000, // Target Square 46 (G6)
0b00000000_01000000_00000000_00000000_00000000_00000000_00000000_00000000, // Target Square 47 (H6)
0b00000010_00000000_00000000_00000000_00000000_00000000_00000000_00000000, // Target Square 48 (A7)
0b00000101_00000000_00000000_00000000_00000000_00000000_00000000_00000000, // Target Square 49 (B7)
0b00001010_00000000_00000000_00000000_00000000_00000000_00000000_00000000, // Target Square 50 (C7)
0b00010100_00000000_00000000_00000000_00000000_00000000_00000000_00000000, // Target Square 51 (D7)
0b00101000_00000000_00000000_00000000_00000000_00000000_00000000_00000000, // Target Square 52 (E7)
0b01010000_00000000_00000000_00000000_00000000_00000000_00000000_00000000, // Target Square 53 (F7)
0b10100000_00000000_00000000_00000000_00000000_00000000_00000000_00000000, // Target Square 54 (G7)
0b01000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000, // Target Square 55 (H7)
0b00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000, // Target Square 56 (A8)
0b00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000, // Target Square 57 (B8)
0b00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000, // Target Square 58 (C8)
0b00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000, // Target Square 59 (D8)
0b00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000, // Target Square 60 (E8)
0b00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000, // Target Square 61 (F8)
0b00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000, // Target Square 62 (G8)
0b00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000, // Target Square 63 (H8)
]
];
pub const KNIGHT_ATTACKS: [u64; 64] = [ pub const KNIGHT_ATTACKS: [u64; 64] = [
0b00000000_00000000_00000000_00000000_00000000_00000010_00000100_00000000, // Square 0 (A1) 0b00000000_00000000_00000000_00000000_00000000_00000010_00000100_00000000, // Square 0 (A1)
0b00000000_00000000_00000000_00000000_00000000_00000101_00001000_00000000, // Square 1 (B1) 0b00000000_00000000_00000000_00000000_00000000_00000101_00001000_00000000, // Square 1 (B1)

View file

@ -0,0 +1,27 @@
use chess_engine::board::{Board, Color};
use chess_engine::movegen::legal_check::is_square_attacked;
use chess_engine::square::Square;
fn assert_square_attacked(board: &mut Board, square: Square, white: bool, black: bool) {
assert_eq!(is_square_attacked(board, square, Color::White), white, "{}", square);
assert_eq!(is_square_attacked(board, square, Color::Black), black, "{}", square);
}
#[test]
fn test_is_attacked_kiwipete() {
let mut board = Board::from_fen("r3k2r/p1ppqpb1/bn2pnp1/3PN3/1p2P3/2N2Q1p/PPPBBPPP/R3K2R w KQkq - 0 1");
assert_square_attacked(&mut board, Square::B1, true, false);
assert_square_attacked(&mut board, Square::C1, true, false);
assert_square_attacked(&mut board, Square::D1, true, false);
assert_square_attacked(&mut board, Square::F1, true, false);
assert_square_attacked(&mut board, Square::G1, true, false);
assert_square_attacked(&mut board, Square::A3, true, true);
assert_square_attacked(&mut board, Square::B3, true, false);
assert_square_attacked(&mut board, Square::D3, true, true);
assert_square_attacked(&mut board, Square::E3, true, false);
assert_square_attacked(&mut board, Square::G3, true, false);
// TODO keep going with the rest
}