use crate::chess::bitboard::Bitboard;
use crate::chess::movegen::types::{FromAndMoves, KingType, MoveList, Mover};
use crate::chess::movegen::utils::{
get_bishop_moves, get_king_moves, get_kingside_castle_through_squares, get_knight_moves,
get_pawn_attacks, get_queenside_castle_throught_squares, get_rook_moves,
};
use crate::chess::{Color, Position, Role, Square};
impl Mover for KingType {
#[inline]
fn into_piece() -> Role {
Role::King
}
#[inline]
fn pseudo_legal_moves<const BLACK: bool>(from: Square, pos: &Position) -> Bitboard {
let side = match BLACK {
true => Color::Black,
false => Color::White,
};
get_king_moves(from) & !pos.by_color[side]
}
#[inline]
fn legal_moves<const CHECK: bool, const BLACK: bool>(pos: &Position, movelist: &mut MoveList) {
let side = match BLACK {
true => Color::Black,
false => Color::White,
};
let ksq = Square::from(pos.king_of(side));
let mut moves = Self::pseudo_legal_moves::<BLACK>(ksq, pos);
for m in moves {
if !Self::legal_king_move::<BLACK>(pos, m) {
moves ^= Bitboard::from(m);
}
}
if !CHECK {
if pos.castling.can_castle_kingside(side)
&& (get_kingside_castle_through_squares(side) & pos.occupancy).none()
{
let middle = ksq.east().unwrap();
let end = middle.east().unwrap();
if KingType::legal_king_move::<BLACK>(pos, middle)
&& KingType::legal_king_move::<BLACK>(pos, end)
{
moves ^= Bitboard::from(end);
}
}
if pos.castling.can_castle_queenside(side)
&& (get_queenside_castle_throught_squares(side) & pos.occupancy).none()
{
let middle = ksq.west().unwrap();
let end = middle.west().unwrap();
if KingType::legal_king_move::<BLACK>(pos, middle)
&& KingType::legal_king_move::<BLACK>(pos, middle)
&& KingType::legal_king_move::<BLACK>(pos, end)
{
moves ^= Bitboard::from(end);
}
}
}
if moves != Bitboard::EMPTY {
unsafe {
movelist.push_unchecked(FromAndMoves::new(ksq, moves, false, false));
}
}
}
}
impl KingType {
#[inline]
pub fn legal_king_move<const BLACK: bool>(pos: &Position, sq: Square) -> bool {
let side = match BLACK {
true => Color::Black,
false => Color::White,
};
let mask = pos.occupancy ^ pos.king_of(side);
let mut attackers = Bitboard::EMPTY;
let rooks = pos.by_color_role(side.opponent(), Role::Rook)
| pos.by_color_role(side.opponent(), Role::Queen);
attackers |= get_rook_moves(sq, mask) & rooks;
if attackers != Bitboard::EMPTY {
return false;
}
let bishops = pos.their(Role::Bishop) | pos.by_color_role(side.opponent(), Role::Queen);
attackers |= get_bishop_moves(sq, mask) & bishops;
if attackers != Bitboard::EMPTY {
return false;
}
attackers |= get_knight_moves(sq) & pos.by_color_role(side.opponent(), Role::Knight);
if attackers != Bitboard::EMPTY {
return false;
}
attackers |= get_pawn_attacks(sq, side) & pos.by_color_role(side.opponent(), Role::Pawn);
if attackers != Bitboard::EMPTY {
return false;
}
attackers |= get_king_moves(sq) & pos.by_color_role(side.opponent(), Role::King);
if attackers != Bitboard::EMPTY {
return false;
}
true
}
}