#[allow(unused_imports)]
use crate::{
AllMoves, BitBoard, Board, CastleRights, Color, Move, MoveType, Piece, PieceType, SanBuffered,
Square, Zobrist, gen_moves, get_rook_castling, to_san,
};
impl Board {
pub fn make_move(&self, mv: Move) -> Board {
let mut board: Board = *self;
assert_ne!(mv.get_src(), mv.get_dest());
let src: Square = mv.get_src();
let dest: Square = mv.get_dest();
let move_type: MoveType = mv.get_type();
let is_capture: bool = mv.is_capture();
let piece: Piece = self.piece_on(src).unwrap();
let piece_type: PieceType = piece.piece_type();
board.remove_piece(src);
board.fifty_move = if is_capture || piece_type == PieceType::Pawn {
0
} else {
board.fifty_move + 1
};
if board.side == Color::Black {
board.full_move = board.full_move.saturating_add(1);
}
match move_type {
MoveType::EnPassant => {
board.remove_piece(dest.forward(!self.side));
}
MoveType::KingCastle | MoveType::QueenCastle => {
let rook: Piece = Piece::new(PieceType::Rook, self.side);
let (rook_src, rook_dest) = get_rook_castling(dest);
board.remove_piece(rook_src);
board.set_piece(rook, rook_dest);
}
_ if is_capture => {
board.remove_piece(dest);
}
_ => {}
}
if mv.is_promotion() {
board.set_piece(mv.get_prom(self.side), dest);
} else {
board.set_piece(piece, dest);
}
if let Some(square) = self.enpassant_square {
board.enpassant_square = None;
board.zobrist.hash_enpassant(square);
}
if move_type == MoveType::DoublePawn {
let enpassant_target: Square = src.forward(self.side);
board.enpassant_square = Some(enpassant_target);
board.zobrist.hash_enpassant(enpassant_target);
}
let new_castling_rights: CastleRights = self.castling.update(src, dest);
board.castling = new_castling_rights;
board
.zobrist
.swap_castle_hash(self.castling, new_castling_rights);
board.side = !self.side;
board.zobrist.hash_side();
board.checkers = board.checkers();
board
}
pub fn null_move(&self) -> Board {
assert!(self.checkers.is_empty());
let mut board: Board = *self;
board.side = !self.side;
board.zobrist.hash_side();
board.enpassant_square = None;
if let Some(square) = self.enpassant_square {
board.zobrist.hash_enpassant(square);
}
board.checkers = BitBoard::EMPTY;
board
}
#[inline]
pub fn find_move(&self, move_str: &str) -> Option<Move> {
gen_moves::<AllMoves>(self)
.iter()
.find(|&mv| *mv == move_str)
.copied()
}
pub fn make_uci_move(&self, uci_move: &str) -> Result<Board, &str> {
self.find_move(uci_move)
.map(|mv| self.make_move(mv))
.ok_or("Ilegal UCI move from the current board")
}
pub fn to_san(&self, mv: Move) -> SanBuffered {
to_san(mv, self)
}
}