diff --git a/src/attack.rs b/src/attack.rs index 9a7d2ff..37a1ba0 100644 --- a/src/attack.rs +++ b/src/attack.rs @@ -370,6 +370,14 @@ pub fn init_rook_attacks() { } } +pub fn init_attacks() { + init_pawn_attacks(); + init_knight_attacks(); + init_king_attacks(); + init_bishop_attacks(); + init_rook_attacks() +} + #[cfg(test)] mod tests { use super::*; diff --git a/src/board.rs b/src/board.rs index 71cfbba..dcce0bd 100644 --- a/src/board.rs +++ b/src/board.rs @@ -1,6 +1,11 @@ use std::fmt; use u64 as Bitboard; +use crate::attack::{ + get_bishop_attacks, get_king_attacks, get_knight_attacks, get_pawn_attacks, get_queen_attacks, + get_rook_attacks, +}; + #[derive(Debug, PartialEq, Eq)] pub struct Board { white_pieces: [Piece; 6], @@ -12,17 +17,17 @@ impl Board { Self { white_pieces: [ Piece::new(0xff00, Kind::Pawn, Color::White), - Piece::new(0x81, Kind::Rook, Color::White), Piece::new(0x42, Kind::Knight, Color::White), Piece::new(0x24, Kind::Bishop, Color::White), + Piece::new(0x81, Kind::Rook, Color::White), Piece::new(0x8, Kind::Queen, Color::White), Piece::new(0x10, Kind::King, Color::White), ], black_pieces: [ Piece::new(0xff000000000000, Kind::Pawn, Color::Black), - Piece::new(0x8100000000000000, Kind::Rook, Color::Black), Piece::new(0x4200000000000000, Kind::Knight, Color::Black), Piece::new(0x2400000000000000, Kind::Bishop, Color::Black), + Piece::new(0x8100000000000000, Kind::Rook, Color::Black), Piece::new(0x800000000000000, Kind::Queen, Color::Black), Piece::new(0x1000000000000000, Kind::King, Color::Black), ], @@ -33,17 +38,17 @@ impl Board { Self { white_pieces: [ Piece::new(0x0, Kind::Pawn, Color::White), - Piece::new(0x0, Kind::Rook, Color::White), Piece::new(0x0, Kind::Knight, Color::White), Piece::new(0x0, Kind::Bishop, Color::White), + Piece::new(0x0, Kind::Rook, Color::White), Piece::new(0x0, Kind::Queen, Color::White), Piece::new(0x0, Kind::King, Color::White), ], black_pieces: [ Piece::new(0x0, Kind::Pawn, Color::Black), - Piece::new(0x0, Kind::Rook, Color::Black), Piece::new(0x0, Kind::Knight, Color::Black), Piece::new(0x0, Kind::Bishop, Color::Black), + Piece::new(0x0, Kind::Rook, Color::Black), Piece::new(0x0, Kind::Queen, Color::Black), Piece::new(0x0, Kind::King, Color::Black), ], @@ -52,10 +57,32 @@ impl Board { pub fn set_piece(&mut self, piece: Piece) { match piece.color { - Color::Black => self.black_pieces[piece.kind as usize].bitboard |= piece.bitboard, - Color::White => self.white_pieces[piece.kind as usize].bitboard |= piece.bitboard, + Color::Black => self.black_pieces[piece.kind.idx()].bitboard |= piece.bitboard, + Color::White => self.white_pieces[piece.kind.idx()].bitboard |= piece.bitboard, }; } + + pub fn get_all_occupancies(&self) -> Bitboard { + let white_blockers = self.white_pieces.iter().fold(0, |acc, p| p.bitboard | acc); + let black_blockers = self.black_pieces.iter().fold(0, |acc, p| p.bitboard | acc); + + white_blockers | black_blockers + } + + pub fn is_attacked(&self, sq: usize, opponent_color: Color) -> bool { + let all_occupancies = self.get_all_occupancies(); + let enemy = match opponent_color { + Color::Black => &self.black_pieces, + Color::White => &self.white_pieces, + }; + + enemy[Kind::Pawn.idx()].bitboard & get_pawn_attacks(sq, opponent_color) != 0 + || enemy[Kind::Knight.idx()].bitboard & get_knight_attacks(sq) != 0 + || enemy[Kind::Bishop.idx()].bitboard & get_bishop_attacks(all_occupancies, sq) != 0 + || enemy[Kind::Rook.idx()].bitboard & get_rook_attacks(all_occupancies, sq) != 0 + || enemy[Kind::Queen.idx()].bitboard & get_queen_attacks(all_occupancies, sq) != 0 + || enemy[Kind::King.idx()].bitboard & get_king_attacks(sq) != 0 + } } impl Default for Board { @@ -116,18 +143,52 @@ impl fmt::Display for Piece { } } -#[derive(Debug, PartialEq, Eq)] +#[derive(Debug, PartialEq, Eq, Copy, Clone)] pub enum Kind { Pawn, - Rook, Knight, Bishop, + Rook, Queen, King, } +impl Kind { + fn idx(&self) -> usize { + *self as usize + } +} + #[derive(Debug, PartialEq, Eq)] pub enum Color { White, Black, } + +#[cfg(test)] +mod tests { + use crate::{attack::init_attacks, fen::from_fen}; + + use super::*; + + const FEN_EXAMPLE: [&str; 1] = [ + "8/6P1/4n2b/1p6/1Kp5/6n1/4b3/1k6 w - - 0 1", + ]; + + #[test] + fn test_get_all_occupancies() -> Result<(), String> { + let new_game = from_fen(FEN_EXAMPLE[0])?; + assert_eq!(new_game.board.get_all_occupancies(), 0x40900206401002); + + Ok(()) + } + + #[test] + fn test_is_attacked() -> Result<(), String> { + let new_game = from_fen(FEN_EXAMPLE[0])?; + init_attacks(); + assert!(new_game.board.is_attacked(54, Color::Black)); + + Ok(()) + } +}