Change History and Mailbox to tuple structs, use builder pattern for Move_Info

This commit is contained in:
stefiosif
2025-02-04 19:19:17 +02:00
parent 77660d21f8
commit 55056537f3
3 changed files with 79 additions and 94 deletions

View File

@@ -7,7 +7,7 @@ use String as FenError;
use super::{ use super::{
board::{Board, Color, PieceType}, board::{Board, Color, PieceType},
history::{History, MoveParameters}, history::{History, MoveInfo},
mailbox::Mailbox, mailbox::Mailbox,
square::Square, square::Square,
state::Castle, state::Castle,
@@ -57,8 +57,17 @@ impl Game {
} }
pub fn make_move(&mut self, mv: &Move) { pub fn make_move(&mut self, mv: &Move) {
self.history let move_info = MoveInfo::new()
.push_move_parameters(MoveParameters::build(self, mv)); .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 board = &mut self.board;
let hash = &mut self.hash; let hash = &mut self.hash;
@@ -167,27 +176,27 @@ impl Game {
pub fn unmake_move(&mut self) { pub fn unmake_move(&mut self) {
let board = &mut self.board; let board = &mut self.board;
let mailbox = &mut self.mailbox; let mailbox = &mut self.mailbox;
let move_parameters = &mut self let move_info = &mut self
.history .history
.pop_move_parameters() .pop_move_info()
.expect("History stack is empty"); .expect("History stack is empty");
let color_before_move = board.state.change_side(); let color_before_move = board.state.change_side();
board.state.revert_full_move(color_before_move); 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; 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; 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; board.state.halfmove_clock = new_halfmove_clock;
} }
let mv = move_parameters let mv = move_info
.mv .mv
.expect("Expected move parameters from history stack"); .expect("Expected move parameters from history stack");
let piece_at_dst = mailbox.piece_at(mv.dst()).expect("No piece at dst."); 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); mailbox.set_piece_at(mv.dst(), None);
} }
MoveType::Capture => { MoveType::Capture => {
let captured_piece = move_parameters let captured_piece = move_info
.captured_piece .captured_piece
.expect("Expected captured piece to unmake Capture"); .expect("Expected captured piece to unmake Capture");
board.move_piece(mv.dst(), mv.src(), piece_at_dst.0); board.move_piece(mv.dst(), mv.src(), piece_at_dst.0);
board.insert_opponent_piece(mv.dst(), captured_piece.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)); mailbox.set_piece_at(mv.dst(), Some(captured_piece));
} }
MoveType::PromotionKnight MoveType::PromotionKnight
| MoveType::PromotionBishop | MoveType::PromotionBishop
| MoveType::PromotionRook | MoveType::PromotionRook
| MoveType::PromotionQueen => { | MoveType::PromotionQueen => {
let promoted_piece = move_parameters let promoted_piece = move_info
.promoted_piece .promoted_piece
.expect("Expected promoted piece to unmake Promotion"); .expect("Expected promoted piece to unmake Promotion");
board.remove_own_piece(mv.dst(), promoted_piece.0); board.remove_own_piece(mv.dst(), promoted_piece.0);
@@ -223,10 +232,10 @@ impl Game {
| MoveType::PromotionCaptureBishop | MoveType::PromotionCaptureBishop
| MoveType::PromotionCaptureRook | MoveType::PromotionCaptureRook
| MoveType::PromotionCaptureQueen => { | MoveType::PromotionCaptureQueen => {
let promoted_piece = move_parameters let promoted_piece = move_info
.promoted_piece .promoted_piece
.expect("Expected promoted piece to unmake PromotionCapture"); .expect("Expected promoted piece to unmake PromotionCapture");
let captured_piece = move_parameters let captured_piece = move_info
.captured_piece .captured_piece
.expect("Expected captured piece to unmake PromotionCapture"); .expect("Expected captured piece to unmake PromotionCapture");
board.remove_own_piece(mv.dst(), promoted_piece.0); board.remove_own_piece(mv.dst(), promoted_piece.0);
@@ -266,10 +275,14 @@ impl Game {
} }
pub fn make_null_move(&mut self) { pub fn make_null_move(&mut self) {
let move_params = MoveParameters::build_null(self); let move_info = MoveInfo::new()
self.history.push_move_parameters(move_params); .with_castling_ability(self.board.state.castling_ability)
self.hash.update_side_to_move_key(); .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 self.board
.state .state
.update_null_game_state(self.current_player()); .update_null_game_state(self.current_player());
@@ -277,25 +290,25 @@ impl Game {
pub fn unmake_null_move(&mut self) { pub fn unmake_null_move(&mut self) {
let board = &mut self.board; let board = &mut self.board;
let move_parameters = &mut self let move_info = &mut self
.history .history
.pop_move_parameters() .pop_move_info()
.expect("History stack is empty"); .expect("History stack is empty");
let color_before_move = board.state.change_side(); let color_before_move = board.state.change_side();
board.state.revert_full_move(color_before_move); 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; 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; 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; board.state.halfmove_clock = new_halfmove_clock;
} }
} }

View File

@@ -2,34 +2,29 @@ use crate::movegen::r#move::{Move, MoveType};
use super::{ use super::{
board::{Color, PieceType}, board::{Color, PieceType},
game::Game,
mailbox::Mailbox, mailbox::Mailbox,
state::{Castle, State}, state::Castle,
zobrist::ZobristHash, zobrist::ZobristHash,
}; };
#[derive(Debug, Clone, PartialEq, Eq)] #[derive(Debug, Clone, PartialEq, Eq)]
pub struct History { pub struct History(Vec<MoveInfo>);
pub move_parameters: Vec<MoveParameters>,
}
impl History { impl History {
pub const fn new() -> Self { pub const fn new() -> Self {
Self { Self(Vec::new())
move_parameters: Vec::new(),
}
} }
pub fn push_move_parameters(&mut self, move_parameters: MoveParameters) { pub fn push_move_info(&mut self, move_info: MoveInfo) {
self.move_parameters.push(move_parameters); self.0.push(move_info);
} }
pub fn pop_move_parameters(&mut self) -> Option<MoveParameters> { pub fn pop_move_info(&mut self) -> Option<MoveInfo> {
self.move_parameters.pop() self.0.pop()
} }
pub fn in_repetition(&self, hash: ZobristHash) -> bool { pub fn in_repetition(&self, hash: ZobristHash) -> bool {
self.move_parameters self.0
.iter() .iter()
.rev() .rev()
.skip(1) .skip(1)
@@ -38,8 +33,8 @@ impl History {
} }
} }
#[derive(Debug, Clone, PartialEq, Eq)] #[derive(Default, Debug, Clone, PartialEq, Eq)]
pub struct MoveParameters { pub struct MoveInfo {
pub mv: Option<Move>, pub mv: Option<Move>,
pub moving_piece: Option<(PieceType, Color)>, pub moving_piece: Option<(PieceType, Color)>,
pub captured_piece: Option<(PieceType, Color)>, pub captured_piece: Option<(PieceType, Color)>,
@@ -50,55 +45,37 @@ pub struct MoveParameters {
pub zobrist_hash: Option<ZobristHash>, pub zobrist_hash: Option<ZobristHash>,
} }
impl MoveParameters { impl MoveInfo {
pub const fn new() -> Self { pub fn new() -> Self {
Self { Self::default()
mv: None,
moving_piece: None,
captured_piece: None,
promoted_piece: None,
castling_ability: None,
en_passant_square: None,
halfmove_clock: None,
zobrist_hash: None,
}
} }
pub fn build(game: &Game, mv: &Move) -> Self { pub const fn with_move(mut self, 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) {
self.mv = Some(mv); self.mv = Some(mv);
self
} }
fn add_irreversible_parameters(&mut self, state: &State) { pub const fn with_castling_ability(mut self, castling_ability: [Castle; 2]) -> Self {
self.castling_ability = Some(state.castling_ability); self.castling_ability = Some(castling_ability);
self.en_passant_square = state.en_passant_square; self
self.halfmove_clock = Some(state.halfmove_clock);
} }
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.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 if let MoveType::Capture
| MoveType::PromotionCaptureKnight | MoveType::PromotionCaptureKnight
| MoveType::PromotionCaptureBishop | MoveType::PromotionCaptureBishop
@@ -107,21 +84,18 @@ impl MoveParameters {
{ {
self.captured_piece = mailbox.piece_at(mv.dst()) 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() { if mv.is_promotion() {
self.promoted_piece = Some((mv.promotion_type().into_piece_type(), color)); self.promoted_piece = Some((mv.promotion_type().into_piece_type(), color));
} }
self
} }
fn add_zobrist_hash(&mut self, zobrist_hash: &ZobristHash) { pub fn with_zobrist_hash(mut self, zobrist_hash: &ZobristHash) -> Self {
self.zobrist_hash = Some(zobrist_hash.to_owned()) self.zobrist_hash = Some(zobrist_hash.to_owned());
} self
}
impl Default for MoveParameters {
fn default() -> Self {
Self::new()
} }
} }

View File

@@ -6,9 +6,7 @@ use super::{
}; };
#[derive(Debug, Clone, PartialEq, Eq)] #[derive(Debug, Clone, PartialEq, Eq)]
pub struct Mailbox { pub struct Mailbox([Option<(PieceType, Color)>; 64]);
pub mailbox: [Option<(PieceType, Color)>; 64],
}
impl Mailbox { impl Mailbox {
pub fn from_board(board: &Board) -> Self { 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)>) { 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)> { 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)), 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(()) Ok(())
} }