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::{
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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(())
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user