use crate::board::Board;
use super::attackers::{get_attackers, get_direct_attackers, with_side_to_move};
use super::types::BoardPiece;
pub fn get_defenders(board: &Board, piece: &BoardPiece, transitive: bool) -> Vec<BoardPiece> {
let attacker_color = piece.piece.color.opposite();
let direct_attackers = get_direct_attackers(board, piece.square, attacker_color);
if direct_attackers.is_empty() {
let flipped_piece = BoardPiece::new(
crate::types::Piece::new(piece.piece.piece_type, attacker_color),
piece.square,
);
let mut scratch = board.clone();
scratch.set_piece(piece.square, Some(flipped_piece.piece));
return get_attackers_of(&scratch, &flipped_piece, transitive);
}
let smallest_recapturers = direct_attackers
.iter()
.filter_map(|attacker| {
let capture_board = with_side_to_move(board, attacker_color);
let capture_mv = crate::types::Move::new(attacker.square, piece.square);
let pseudo = crate::movegen::generate_pseudo_legal_moves(&capture_board);
if !pseudo.iter().any(|m| m == &capture_mv) {
return None;
}
let after_capture = crate::movegen::apply_move(&capture_board, &capture_mv);
let recaptured_piece = BoardPiece::new(attacker.piece, piece.square);
let recapturers = get_attackers_of(&after_capture, &recaptured_piece, transitive);
Some(recapturers)
})
.min_by_key(|recapturers| recapturers.len());
smallest_recapturers.unwrap_or_default()
}
fn get_attackers_of(board: &Board, piece: &BoardPiece, transitive: bool) -> Vec<BoardPiece> {
let defending_color = piece.piece.color.opposite();
if transitive {
get_attackers(board, piece.square, defending_color)
} else {
get_direct_attackers(board, piece.square, defending_color)
}
}