Implement redundant mailbox representation
This commit is contained in:
@@ -8,6 +8,7 @@ use super::{
|
||||
bitboard::square_to_bitboard,
|
||||
board::{Board, Color, PieceType},
|
||||
history::{History, MoveParameters},
|
||||
mailbox::Mailbox,
|
||||
square::Square,
|
||||
state::Castle,
|
||||
};
|
||||
@@ -20,17 +21,19 @@ impl PartialEq for Game {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Eq)]
|
||||
#[derive(Debug, Clone, Eq)]
|
||||
pub struct Game {
|
||||
pub board: Board,
|
||||
pub history: History,
|
||||
pub mailbox: Mailbox,
|
||||
}
|
||||
|
||||
impl Game {
|
||||
pub const fn new() -> Self {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
board: Board::new(),
|
||||
history: History::new(),
|
||||
mailbox: Mailbox::new_from_board(&Board::new()),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,24 +46,34 @@ impl Game {
|
||||
}
|
||||
|
||||
pub fn make_move(&mut self, mv: &Move) {
|
||||
self.history
|
||||
.push_move_parameters(MoveParameters::build(&self, mv));
|
||||
|
||||
let board = &mut self.board;
|
||||
let mailbox = &mut self.mailbox;
|
||||
let color = board.state.current_player();
|
||||
let pawn_move = board.is_pawn_move(mv.src);
|
||||
let mut en_passant_square = None;
|
||||
self.history
|
||||
.push_move_parameters(MoveParameters::build(board, mv));
|
||||
|
||||
match &mv.move_type {
|
||||
MoveType::Quiet => {
|
||||
board.move_piece(mv.src, mv.dst);
|
||||
mailbox.set_piece_at(mv.dst, mailbox.find_piece_at(mv.src));
|
||||
}
|
||||
MoveType::Capture => {
|
||||
board.move_piece(mv.src, mv.dst);
|
||||
board.remove_opponent_piece(mv.dst);
|
||||
mailbox.set_piece_at(mv.dst, mailbox.find_piece_at(mv.src));
|
||||
}
|
||||
MoveType::EnPassant => {
|
||||
board.move_piece(mv.src, mv.dst);
|
||||
board.remove_pawn_enpassant(mv.dst, color);
|
||||
let piece_to_remove = match color {
|
||||
Color::White => mv.dst - 8,
|
||||
Color::Black => mv.dst + 8,
|
||||
};
|
||||
board.remove_opponent_piece(piece_to_remove);
|
||||
mailbox.set_piece_at(mv.dst, mailbox.find_piece_at(mv.src));
|
||||
mailbox.set_piece_at(piece_to_remove, None);
|
||||
}
|
||||
MoveType::DoublePush => {
|
||||
board.move_piece(mv.src, mv.dst);
|
||||
@@ -68,29 +81,45 @@ impl Game {
|
||||
Color::White => Some(mv.src + 8),
|
||||
Color::Black => Some(mv.src.saturating_sub(8)),
|
||||
};
|
||||
mailbox.set_piece_at(mv.dst, mailbox.find_piece_at(mv.src));
|
||||
}
|
||||
MoveType::Promotion(promote) => {
|
||||
board.remove_own_piece(mv.src);
|
||||
board.promote_piece(mv.dst, promote);
|
||||
mailbox.set_piece_at(mv.dst, Some(promote.into_piece_type()));
|
||||
}
|
||||
MoveType::PromotionCapture(promote) => {
|
||||
board.remove_own_piece(mv.src);
|
||||
board.remove_opponent_piece(mv.dst);
|
||||
board.promote_piece(mv.dst, promote);
|
||||
mailbox.set_piece_at(mv.dst, Some(promote.into_piece_type()));
|
||||
}
|
||||
MoveType::Castle => {
|
||||
board.move_piece(mv.src, mv.dst);
|
||||
board.move_rook_castle(mv.dst);
|
||||
let (rook_src, rook_dst) = match mv.dst {
|
||||
Square::C1 | Square::C8 => (mv.dst - 2, mv.dst + 1),
|
||||
Square::G1 | Square::G8 => (mv.dst + 1, mv.dst - 1),
|
||||
_ => return,
|
||||
};
|
||||
board.move_piece(rook_src, rook_dst);
|
||||
board.state.set_castling_ability(color, Castle::None);
|
||||
mailbox.set_piece_at(mv.dst, mailbox.find_piece_at(mv.src));
|
||||
mailbox.set_piece_at(rook_src, None);
|
||||
mailbox.set_piece_at(rook_dst, Some(PieceType::Rook));
|
||||
}
|
||||
}
|
||||
|
||||
mailbox.set_piece_at(mv.src, None);
|
||||
Board::update_game_state(&mut board.state, mv, color, pawn_move, en_passant_square);
|
||||
}
|
||||
|
||||
pub fn unmake_move(&mut self) {
|
||||
let board = &mut self.board;
|
||||
let move_parameters = &mut self.history.pop_move_parameters().unwrap_or_default();
|
||||
let mailbox = &mut self.mailbox;
|
||||
let move_parameters = &mut self
|
||||
.history
|
||||
.pop_move_parameters()
|
||||
.expect("History stack is empty");
|
||||
let color_before_move = board.state.change_side();
|
||||
board.state.revert_full_move(color_before_move);
|
||||
board.state.en_passant_square = move_parameters.en_passant_square;
|
||||
@@ -108,27 +137,42 @@ impl Game {
|
||||
match &mv.move_type {
|
||||
MoveType::Quiet | MoveType::DoublePush => {
|
||||
board.move_piece(mv.dst, mv.src);
|
||||
mailbox.set_piece_at(mv.src, mailbox.find_piece_at(mv.dst));
|
||||
mailbox.set_piece_at(mv.dst, None);
|
||||
}
|
||||
MoveType::Capture | MoveType::Promotion(_) | MoveType::PromotionCapture(_) => {
|
||||
if let (Some(captured_piece_type), Some(promoted_piece_type)) = (
|
||||
move_parameters.captured_piece,
|
||||
move_parameters.promoted_piece,
|
||||
) {
|
||||
let (own_pieces, opponent_pieces) = board.all_pieces();
|
||||
|
||||
opponent_pieces[captured_piece_type].bitboard |= square_to_bitboard(mv.dst);
|
||||
own_pieces[promoted_piece_type].bitboard &= !square_to_bitboard(mv.dst);
|
||||
own_pieces[PieceType::Pawn].bitboard |= square_to_bitboard(mv.src);
|
||||
} else if let Some(captured_piece_type) = move_parameters.captured_piece {
|
||||
board.move_piece(mv.dst, mv.src);
|
||||
let opponent_pieces = board.opponent_pieces();
|
||||
opponent_pieces[captured_piece_type].bitboard |= square_to_bitboard(mv.dst);
|
||||
} else if let Some(promoted_piece_type) = move_parameters.promoted_piece {
|
||||
let own_pieces = board.own_pieces();
|
||||
|
||||
own_pieces[promoted_piece_type].bitboard &= !square_to_bitboard(mv.dst);
|
||||
own_pieces[PieceType::Pawn].bitboard |= square_to_bitboard(mv.src);
|
||||
}
|
||||
MoveType::Capture => {
|
||||
let captured_piece = move_parameters
|
||||
.captured_piece
|
||||
.expect("Expected captured piece to unmake Capture");
|
||||
board.move_piece(mv.dst, mv.src);
|
||||
let opponent_pieces = board.opponent_pieces();
|
||||
opponent_pieces[captured_piece].bitboard |= square_to_bitboard(mv.dst);
|
||||
mailbox.set_piece_at(mv.src, move_parameters.moved_piece);
|
||||
mailbox.set_piece_at(mv.dst, Some(captured_piece));
|
||||
}
|
||||
MoveType::Promotion(_) => {
|
||||
let promoted_piece = move_parameters
|
||||
.promoted_piece
|
||||
.expect("Expected promoted piece to unmake Promotion");
|
||||
let own_pieces = board.own_pieces();
|
||||
own_pieces[promoted_piece].bitboard &= !square_to_bitboard(mv.dst);
|
||||
own_pieces[PieceType::Pawn].bitboard |= square_to_bitboard(mv.src);
|
||||
mailbox.set_piece_at(mv.src, Some(PieceType::Pawn));
|
||||
mailbox.set_piece_at(mv.dst, None);
|
||||
}
|
||||
MoveType::PromotionCapture(_) => {
|
||||
let promoted_piece = move_parameters
|
||||
.promoted_piece
|
||||
.expect("Expected promoted piece to unmake PromotionCapture");
|
||||
let captured_piece = move_parameters
|
||||
.captured_piece
|
||||
.expect("Expected captured piece to unmake PromotionCapture");
|
||||
let (own_pieces, opponent_pieces) = board.all_pieces();
|
||||
opponent_pieces[captured_piece].bitboard |= square_to_bitboard(mv.dst);
|
||||
own_pieces[promoted_piece].bitboard &= !square_to_bitboard(mv.dst);
|
||||
own_pieces[PieceType::Pawn].bitboard |= square_to_bitboard(mv.src);
|
||||
mailbox.set_piece_at(mv.src, Some(PieceType::Pawn));
|
||||
mailbox.set_piece_at(mv.dst, Some(captured_piece));
|
||||
}
|
||||
MoveType::EnPassant => {
|
||||
board.move_piece(mv.dst, mv.src);
|
||||
@@ -138,6 +182,8 @@ impl Game {
|
||||
};
|
||||
let opponent_pieces = board.opponent_pieces();
|
||||
opponent_pieces[PieceType::Pawn].bitboard |= square_to_bitboard(enemy_pawn_square);
|
||||
mailbox.set_piece_at(mv.src, Some(PieceType::Pawn));
|
||||
mailbox.set_piece_at(enemy_pawn_square, Some(PieceType::Pawn));
|
||||
}
|
||||
MoveType::Castle => {
|
||||
board.move_piece(mv.dst, mv.src);
|
||||
@@ -149,6 +195,10 @@ impl Game {
|
||||
let own_pieces = board.own_pieces();
|
||||
own_pieces[PieceType::Rook].bitboard &= !square_to_bitboard(rook_dst);
|
||||
own_pieces[PieceType::Rook].bitboard |= square_to_bitboard(rook_src);
|
||||
mailbox.set_piece_at(mv.src, mailbox.find_piece_at(mv.dst));
|
||||
mailbox.set_piece_at(mv.dst, None);
|
||||
mailbox.set_piece_at(rook_src, Some(PieceType::Rook));
|
||||
mailbox.set_piece_at(rook_dst, None);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user