use crate::defs::{BitBoard, Square};
use crate::{ChessBoard, Color, PieceType, Rank};
use std::mem::MaybeUninit;
#[derive(Clone, Copy, Debug)]
pub struct PieceMoves {
pub location: Square,
pub targets: BitBoard,
}
impl PieceMoves {
pub const fn new(location: Square, targets: BitBoard) -> Self {
Self { location, targets }
}
}
#[derive(Debug)]
pub struct MoveList {
data: MaybeUninit<[PieceMoves; 18]>,
length: usize,
}
impl MoveList {
pub const fn new() -> Self {
MoveList {
data: MaybeUninit::uninit(),
length: 0,
}
}
pub fn is_empty(&self) -> bool {
self.length == 0
}
pub fn push(&mut self, piece_moves: PieceMoves) {
if !piece_moves.targets.is_empty() {
unsafe {
*self.data.assume_init_mut().get_unchecked_mut(self.length) = piece_moves;
}
self.length += 1;
}
}
pub fn pop(&mut self) -> Option<PieceMoves> {
if self.length == 0 {
return None;
}
self.length -= 1;
unsafe { Some(*self.data.assume_init_ref().get_unchecked(self.length)) }
}
pub fn back(&self) -> Option<&PieceMoves> {
if self.is_empty() {
return None;
}
unsafe { Some(self.data.assume_init_ref().get_unchecked(self.length - 1)) }
}
pub fn back_mut(&mut self) -> Option<&mut PieceMoves> {
if self.is_empty() {
return None;
}
unsafe {
Some(
self.data
.assume_init_mut()
.get_unchecked_mut(self.length - 1),
)
}
}
pub fn count_moves(&self, chessboard: &ChessBoard) -> u32 {
let mut total = 0;
for i in 0..self.length {
let piece_moves = unsafe { self.data.assume_init_ref().get_unchecked(i) };
let piece_sq = piece_moves.location;
let moving = chessboard.piece_at(piece_sq).unwrap().kind;
if moving == PieceType::Pawn {
let promote_rank = match chessboard.turn() {
Color::White => BitBoard::from_rank(Rank::Eighth),
Color::Black => BitBoard::from_rank(Rank::First),
};
let promotions = piece_moves.targets & promote_rank;
let normal = piece_moves.targets & !promotions;
total += 4 * promotions.popcnt() as u32;
total += normal.popcnt() as u32;
} else {
total += piece_moves.targets.popcnt() as u32;
}
}
total
}
}