From 55056537f3deadc51465adb214d8c38aec379b25 Mon Sep 17 00:00:00 2001 From: stefiosif Date: Tue, 4 Feb 2025 19:19:17 +0200 Subject: [PATCH] Change `History` and `Mailbox` to tuple structs, use builder pattern for `Move_Info` --- src/board/game.rs | 61 +++++++++++++++----------- src/board/history.rs | 100 ++++++++++++++++--------------------------- src/board/mailbox.rs | 12 +++--- 3 files changed, 79 insertions(+), 94 deletions(-) diff --git a/src/board/game.rs b/src/board/game.rs index 954ac57..cbf6662 100644 --- a/src/board/game.rs +++ b/src/board/game.rs @@ -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; } } diff --git a/src/board/history.rs b/src/board/history.rs index ef7a8b9..fb21a77 100644 --- a/src/board/history.rs +++ b/src/board/history.rs @@ -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, -} +pub struct History(Vec); 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 { - self.move_parameters.pop() + pub fn pop_move_info(&mut self) -> Option { + 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, pub moving_piece: Option<(PieceType, Color)>, pub captured_piece: Option<(PieceType, Color)>, @@ -50,55 +45,37 @@ pub struct MoveParameters { pub zobrist_hash: Option, } -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) -> 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 } } diff --git a/src/board/mailbox.rs b/src/board/mailbox.rs index ad17d8e..b1096c1 100644 --- a/src/board/mailbox.rs +++ b/src/board/mailbox.rs @@ -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(()) }