use super::board::Board;
use super::board_map::BoardMap;
use super::movement::{self, PieceMove};
use super::side::Side;
use chess_notation_parser::Square;
#[derive(PartialEq)]
pub enum KingState {
Safe,
Check,
SoftCheckmate,
}
pub fn get_state(board: &mut Board, side: Side) -> KingState {
let square = board.get_king_pos(side);
if is_safe(&board.map, square, side) {
return KingState::Safe;
}
match any_safe_moves(&mut board.map, square, side) {
true => KingState::Check,
_ => KingState::SoftCheckmate,
}
}
fn any_safe_moves(map: &mut BoardMap, square: Square, side: Side) -> bool {
let king_moves =
movement::possible_squares_for_src(&map, square, side, PieceMove::King);
let king = map.remove(&square);
let mut any_safe_moves = false;
for square in king_moves {
if is_safe(map, square, side) {
any_safe_moves = true;
break;
}
}
map.insert(square, king.unwrap());
any_safe_moves
}
pub fn is_safe(map: &BoardMap, pos: Square, side: Side) -> bool {
let opponent = side.opponent();
!(is_attacked_by(map, pos, opponent, PieceMove::Queen)
|| is_attacked_by(map, pos, opponent, PieceMove::Knight)
|| is_attacked_by(map, pos, opponent, PieceMove::Bishop)
|| is_attacked_by(map, pos, opponent, PieceMove::Rook)
|| is_attacked_by(map, pos, opponent, PieceMove::PawnCapture)
|| is_attacked_by(map, pos, opponent, PieceMove::King))
}
fn is_attacked_by(
map: &BoardMap,
pos: Square,
side: Side,
piece_move: PieceMove,
) -> bool {
let squares =
movement::possible_squares_for_dst(&map, pos, side, piece_move);
for square in squares.iter() {
if let Some((p, _)) = map.get(&square) {
match p {
piece if piece == piece_move.to_piece() => return true,
_ => continue,
}
}
}
false
}