Change History and Mailbox to tuple structs, use builder pattern for Move_Info
This commit is contained in:
@@ -7,7 +7,7 @@ use String as FenError;
|
||||
|
||||
use super::{
|
||||
board::{Board, Color, PieceType},
|
||||
history::{History, MoveParameters},
|
||||
history::{History, MoveInfo},
|
||||
mailbox::Mailbox,
|
||||
square::Square,
|
||||
state::Castle,
|
||||
@@ -57,8 +57,17 @@ impl Game {
|
||||
}
|
||||
|
||||
pub fn make_move(&mut self, mv: &Move) {
|
||||
self.history
|
||||
.push_move_parameters(MoveParameters::build(self, mv));
|
||||
let move_info = MoveInfo::new()
|
||||
.with_move(*mv)
|
||||
.with_castling_ability(self.board.state.castling_ability)
|
||||
.with_en_passant_square(self.board.state.en_passant_square)
|
||||
.with_halfmove_clock(self.board.state.halfmove_clock)
|
||||
.with_moving_piece(&self.mailbox, mv)
|
||||
.with_captured_piece(&self.mailbox, mv)
|
||||
.with_promoted_piece(mv, self.current_player())
|
||||
.with_zobrist_hash(&self.hash);
|
||||
|
||||
self.history.push_move_info(move_info);
|
||||
|
||||
let board = &mut self.board;
|
||||
let hash = &mut self.hash;
|
||||
@@ -167,27 +176,27 @@ impl Game {
|
||||
pub fn unmake_move(&mut self) {
|
||||
let board = &mut self.board;
|
||||
let mailbox = &mut self.mailbox;
|
||||
let move_parameters = &mut self
|
||||
let move_info = &mut self
|
||||
.history
|
||||
.pop_move_parameters()
|
||||
.pop_move_info()
|
||||
.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;
|
||||
board.state.en_passant_square = move_info.en_passant_square;
|
||||
|
||||
if let Some(hash) = move_parameters.zobrist_hash {
|
||||
if let Some(hash) = move_info.zobrist_hash {
|
||||
self.hash = hash;
|
||||
}
|
||||
|
||||
if let Some(new_castling_ability) = move_parameters.castling_ability {
|
||||
if let Some(new_castling_ability) = move_info.castling_ability {
|
||||
board.state.castling_ability = new_castling_ability;
|
||||
}
|
||||
|
||||
if let Some(new_halfmove_clock) = move_parameters.halfmove_clock {
|
||||
if let Some(new_halfmove_clock) = move_info.halfmove_clock {
|
||||
board.state.halfmove_clock = new_halfmove_clock;
|
||||
}
|
||||
|
||||
let mv = move_parameters
|
||||
let mv = move_info
|
||||
.mv
|
||||
.expect("Expected move parameters from history stack");
|
||||
let piece_at_dst = mailbox.piece_at(mv.dst()).expect("No piece at dst.");
|
||||
@@ -198,19 +207,19 @@ impl Game {
|
||||
mailbox.set_piece_at(mv.dst(), None);
|
||||
}
|
||||
MoveType::Capture => {
|
||||
let captured_piece = move_parameters
|
||||
let captured_piece = move_info
|
||||
.captured_piece
|
||||
.expect("Expected captured piece to unmake Capture");
|
||||
board.move_piece(mv.dst(), mv.src(), piece_at_dst.0);
|
||||
board.insert_opponent_piece(mv.dst(), captured_piece.0);
|
||||
mailbox.set_piece_at(mv.src(), move_parameters.moving_piece);
|
||||
mailbox.set_piece_at(mv.src(), move_info.moving_piece);
|
||||
mailbox.set_piece_at(mv.dst(), Some(captured_piece));
|
||||
}
|
||||
MoveType::PromotionKnight
|
||||
| MoveType::PromotionBishop
|
||||
| MoveType::PromotionRook
|
||||
| MoveType::PromotionQueen => {
|
||||
let promoted_piece = move_parameters
|
||||
let promoted_piece = move_info
|
||||
.promoted_piece
|
||||
.expect("Expected promoted piece to unmake Promotion");
|
||||
board.remove_own_piece(mv.dst(), promoted_piece.0);
|
||||
@@ -223,10 +232,10 @@ impl Game {
|
||||
| MoveType::PromotionCaptureBishop
|
||||
| MoveType::PromotionCaptureRook
|
||||
| MoveType::PromotionCaptureQueen => {
|
||||
let promoted_piece = move_parameters
|
||||
let promoted_piece = move_info
|
||||
.promoted_piece
|
||||
.expect("Expected promoted piece to unmake PromotionCapture");
|
||||
let captured_piece = move_parameters
|
||||
let captured_piece = move_info
|
||||
.captured_piece
|
||||
.expect("Expected captured piece to unmake PromotionCapture");
|
||||
board.remove_own_piece(mv.dst(), promoted_piece.0);
|
||||
@@ -266,10 +275,14 @@ impl Game {
|
||||
}
|
||||
|
||||
pub fn make_null_move(&mut self) {
|
||||
let move_params = MoveParameters::build_null(self);
|
||||
self.history.push_move_parameters(move_params);
|
||||
self.hash.update_side_to_move_key();
|
||||
let move_info = MoveInfo::new()
|
||||
.with_castling_ability(self.board.state.castling_ability)
|
||||
.with_en_passant_square(self.board.state.en_passant_square)
|
||||
.with_halfmove_clock(self.board.state.halfmove_clock)
|
||||
.with_zobrist_hash(&self.hash);
|
||||
|
||||
self.history.push_move_info(move_info);
|
||||
self.hash.update_side_to_move_key();
|
||||
self.board
|
||||
.state
|
||||
.update_null_game_state(self.current_player());
|
||||
@@ -277,25 +290,25 @@ impl Game {
|
||||
|
||||
pub fn unmake_null_move(&mut self) {
|
||||
let board = &mut self.board;
|
||||
let move_parameters = &mut self
|
||||
let move_info = &mut self
|
||||
.history
|
||||
.pop_move_parameters()
|
||||
.pop_move_info()
|
||||
.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;
|
||||
board.state.en_passant_square = move_info.en_passant_square;
|
||||
|
||||
if let Some(hash) = move_parameters.zobrist_hash {
|
||||
if let Some(hash) = move_info.zobrist_hash {
|
||||
self.hash = hash;
|
||||
}
|
||||
|
||||
if let Some(new_castling_ability) = move_parameters.castling_ability {
|
||||
if let Some(new_castling_ability) = move_info.castling_ability {
|
||||
board.state.castling_ability = new_castling_ability;
|
||||
}
|
||||
|
||||
if let Some(new_halfmove_clock) = move_parameters.halfmove_clock {
|
||||
if let Some(new_halfmove_clock) = move_info.halfmove_clock {
|
||||
board.state.halfmove_clock = new_halfmove_clock;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,34 +2,29 @@ use crate::movegen::r#move::{Move, MoveType};
|
||||
|
||||
use super::{
|
||||
board::{Color, PieceType},
|
||||
game::Game,
|
||||
mailbox::Mailbox,
|
||||
state::{Castle, State},
|
||||
state::Castle,
|
||||
zobrist::ZobristHash,
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct History {
|
||||
pub move_parameters: Vec<MoveParameters>,
|
||||
}
|
||||
pub struct History(Vec<MoveInfo>);
|
||||
|
||||
impl History {
|
||||
pub const fn new() -> Self {
|
||||
Self {
|
||||
move_parameters: Vec::new(),
|
||||
}
|
||||
Self(Vec::new())
|
||||
}
|
||||
|
||||
pub fn push_move_parameters(&mut self, move_parameters: MoveParameters) {
|
||||
self.move_parameters.push(move_parameters);
|
||||
pub fn push_move_info(&mut self, move_info: MoveInfo) {
|
||||
self.0.push(move_info);
|
||||
}
|
||||
|
||||
pub fn pop_move_parameters(&mut self) -> Option<MoveParameters> {
|
||||
self.move_parameters.pop()
|
||||
pub fn pop_move_info(&mut self) -> Option<MoveInfo> {
|
||||
self.0.pop()
|
||||
}
|
||||
|
||||
pub fn in_repetition(&self, hash: ZobristHash) -> bool {
|
||||
self.move_parameters
|
||||
self.0
|
||||
.iter()
|
||||
.rev()
|
||||
.skip(1)
|
||||
@@ -38,8 +33,8 @@ impl History {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct MoveParameters {
|
||||
#[derive(Default, Debug, Clone, PartialEq, Eq)]
|
||||
pub struct MoveInfo {
|
||||
pub mv: Option<Move>,
|
||||
pub moving_piece: Option<(PieceType, Color)>,
|
||||
pub captured_piece: Option<(PieceType, Color)>,
|
||||
@@ -50,55 +45,37 @@ pub struct MoveParameters {
|
||||
pub zobrist_hash: Option<ZobristHash>,
|
||||
}
|
||||
|
||||
impl MoveParameters {
|
||||
pub const fn new() -> Self {
|
||||
Self {
|
||||
mv: None,
|
||||
moving_piece: None,
|
||||
captured_piece: None,
|
||||
promoted_piece: None,
|
||||
castling_ability: None,
|
||||
en_passant_square: None,
|
||||
halfmove_clock: None,
|
||||
zobrist_hash: None,
|
||||
}
|
||||
impl MoveInfo {
|
||||
pub fn new() -> Self {
|
||||
Self::default()
|
||||
}
|
||||
|
||||
pub fn build(game: &Game, mv: &Move) -> Self {
|
||||
let mut move_parameters = Self::new();
|
||||
move_parameters.add_move(*mv);
|
||||
move_parameters.add_irreversible_parameters(&game.board.state);
|
||||
move_parameters.add_moving_piece(&game.mailbox, mv);
|
||||
move_parameters.add_captured_piece(&game.mailbox, mv);
|
||||
move_parameters.add_promoted_piece(mv, game.current_player());
|
||||
move_parameters.add_zobrist_hash(&game.hash);
|
||||
|
||||
move_parameters
|
||||
}
|
||||
|
||||
pub fn build_null(game: &Game) -> Self {
|
||||
let mut move_parameters = Self::new();
|
||||
move_parameters.add_irreversible_parameters(&game.board.state);
|
||||
move_parameters.add_zobrist_hash(&game.hash);
|
||||
|
||||
move_parameters
|
||||
}
|
||||
|
||||
fn add_move(&mut self, mv: Move) {
|
||||
pub const fn with_move(mut self, mv: Move) -> Self {
|
||||
self.mv = Some(mv);
|
||||
self
|
||||
}
|
||||
|
||||
fn add_irreversible_parameters(&mut self, state: &State) {
|
||||
self.castling_ability = Some(state.castling_ability);
|
||||
self.en_passant_square = state.en_passant_square;
|
||||
self.halfmove_clock = Some(state.halfmove_clock);
|
||||
pub const fn with_castling_ability(mut self, castling_ability: [Castle; 2]) -> Self {
|
||||
self.castling_ability = Some(castling_ability);
|
||||
self
|
||||
}
|
||||
|
||||
fn add_moving_piece(&mut self, mailbox: &Mailbox, mv: &Move) {
|
||||
pub const fn with_en_passant_square(mut self, en_passant_square: Option<usize>) -> Self {
|
||||
self.en_passant_square = en_passant_square;
|
||||
self
|
||||
}
|
||||
|
||||
pub const fn with_halfmove_clock(mut self, halfmove_clock: u8) -> Self {
|
||||
self.halfmove_clock = Some(halfmove_clock);
|
||||
self
|
||||
}
|
||||
|
||||
pub const fn with_moving_piece(mut self, mailbox: &Mailbox, mv: &Move) -> Self {
|
||||
self.moving_piece = mailbox.piece_at(mv.src());
|
||||
self
|
||||
}
|
||||
|
||||
fn add_captured_piece(&mut self, mailbox: &Mailbox, mv: &Move) {
|
||||
pub fn with_captured_piece(mut self, mailbox: &Mailbox, mv: &Move) -> Self {
|
||||
if let MoveType::Capture
|
||||
| MoveType::PromotionCaptureKnight
|
||||
| MoveType::PromotionCaptureBishop
|
||||
@@ -107,21 +84,18 @@ impl MoveParameters {
|
||||
{
|
||||
self.captured_piece = mailbox.piece_at(mv.dst())
|
||||
}
|
||||
self
|
||||
}
|
||||
|
||||
fn add_promoted_piece(&mut self, mv: &Move, color: Color) {
|
||||
pub fn with_promoted_piece(mut self, mv: &Move, color: Color) -> Self {
|
||||
if mv.is_promotion() {
|
||||
self.promoted_piece = Some((mv.promotion_type().into_piece_type(), color));
|
||||
}
|
||||
self
|
||||
}
|
||||
|
||||
fn add_zobrist_hash(&mut self, zobrist_hash: &ZobristHash) {
|
||||
self.zobrist_hash = Some(zobrist_hash.to_owned())
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for MoveParameters {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
pub fn with_zobrist_hash(mut self, zobrist_hash: &ZobristHash) -> Self {
|
||||
self.zobrist_hash = Some(zobrist_hash.to_owned());
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,9 +6,7 @@ use super::{
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct Mailbox {
|
||||
pub mailbox: [Option<(PieceType, Color)>; 64],
|
||||
}
|
||||
pub struct Mailbox([Option<(PieceType, Color)>; 64]);
|
||||
|
||||
impl Mailbox {
|
||||
pub fn from_board(board: &Board) -> Self {
|
||||
@@ -22,15 +20,15 @@ impl Mailbox {
|
||||
});
|
||||
}
|
||||
|
||||
Self { mailbox }
|
||||
Self(mailbox)
|
||||
}
|
||||
|
||||
pub fn set_piece_at(&mut self, square: usize, piece: Option<(PieceType, Color)>) {
|
||||
self.mailbox[square] = piece;
|
||||
self.0[square] = piece;
|
||||
}
|
||||
|
||||
pub const fn piece_at(&self, square: usize) -> Option<(PieceType, Color)> {
|
||||
self.mailbox[square]
|
||||
self.0[square]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,7 +66,7 @@ mod tests {
|
||||
Some((PieceType::King, Color::Black)), Some((PieceType::Bishop, Color::Black)), Some((PieceType::Knight, Color::Black)), Some((PieceType::Rook, Color::Black)),
|
||||
];
|
||||
|
||||
assert_eq!(expected, mailbox.mailbox);
|
||||
assert_eq!(expected, mailbox.0);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user