From 2a7943c6975b45062319ff6734582cba3cc9b849 Mon Sep 17 00:00:00 2001 From: Ethan Barry Date: Mon, 25 Nov 2024 17:07:45 -0600 Subject: [PATCH] Everything changed. This overhauls the way MoveTable is used by boxing it in a new struct NoArc. NoArc is a thread-safe way to read a block of memory. Essentially every file in the engine had to change, because essentially every file used GameManager or MoveTable in some way. It shouldn't be too horrible to sort through, though! --- src/gamemanager/legal_moves.rs | 170 +++++++------------ src/gamemanager/legal_moves/perft.rs | 26 +-- src/gamemanager/mod.rs | 27 ++- src/gamemanager/pseudolegal_moves/bishops.rs | 15 +- src/gamemanager/pseudolegal_moves/kings.rs | 19 ++- src/gamemanager/pseudolegal_moves/knights.rs | 10 +- src/gamemanager/pseudolegal_moves/mod.rs | 28 +-- src/gamemanager/pseudolegal_moves/pawns.rs | 7 +- src/gamemanager/pseudolegal_moves/queens.rs | 7 +- src/gamemanager/pseudolegal_moves/rooks.rs | 10 +- src/main.rs | 29 +--- src/movetable/noarc.rs | 2 +- 12 files changed, 148 insertions(+), 202 deletions(-) diff --git a/src/gamemanager/legal_moves.rs b/src/gamemanager/legal_moves.rs index c1f3e35..a7ac53b 100644 --- a/src/gamemanager/legal_moves.rs +++ b/src/gamemanager/legal_moves.rs @@ -4,7 +4,6 @@ use crate::{ bitboard::*, gamemanager::*, types::{CastlingRights, Color, MoveType, PieceType, Square}, - MOVETABLE, }; pub mod perft; @@ -14,7 +13,10 @@ impl GameManager { /// This results in a list of possible GameManagers that could result from /// the possible moves, which are also returned. Each can be evaluated for /// strengths and weaknesses. - pub fn legal_moves(&self) -> Vec<(PieceType, Square, Square, MoveType, GameManager)> { + pub fn legal_moves( + &self, + tbl: &NoArc, + ) -> Vec<(PieceType, Square, Square, MoveType, GameManager)> { /* ************************************************************************************* */ /* WARNING: THIS FUNCTION WILL ERROR SILENTLY IF ANY COLOR-DEPENDENT LOGIC IS USED HERE. */ /* ALL LOGIC IN THIS FUNCTION MUST BE COLOR-AGNOSTIC. */ @@ -27,69 +29,15 @@ impl GameManager { let mut legal_moves: Vec<(PieceType, Square, Square, MoveType, GameManager)> = vec![]; - // Based on color, union all the friendly and enemy pieces, and determine - // which squares the enemy is attacking. We'll need that info for checking - // whether the king is in danger. - let (friendly_pieces, enemy_pieces, currently_attacked) = match color { - Color::Black => { - let friendly_pieces = self.bitboard.pawns_black - | self.bitboard.rooks_black - | self.bitboard.knights_black - | self.bitboard.bishops_black - | self.bitboard.queens_black - | self.bitboard.king_black; - let enemy_pieces = self.bitboard.pawns_white - | self.bitboard.rooks_white - | self.bitboard.knights_white - | self.bitboard.bishops_white - | self.bitboard.queens_white - | self.bitboard.king_white; - - let enemy_attacked = self.attacked_by(Color::White); - - (friendly_pieces, enemy_pieces, enemy_attacked) - } - Color::White => { - let friendly_pieces = self.bitboard.pawns_white - | self.bitboard.rooks_white - | self.bitboard.knights_white - | self.bitboard.bishops_white - | self.bitboard.queens_white - | self.bitboard.king_white; - let enemy_pieces = self.bitboard.pawns_black - | self.bitboard.rooks_black - | self.bitboard.knights_black - | self.bitboard.bishops_black - | self.bitboard.queens_black - | self.bitboard.king_black; - - let enemy_attacked = self.attacked_by(Color::Black); - - (friendly_pieces, enemy_pieces, enemy_attacked) - } - }; - - // Based on color, extract the friendly and enemy kings. - let (friendly_king, enemy_king) = match color { - Color::Black => (self.bitboard.king_black, self.bitboard.king_white), - Color::White => (self.bitboard.king_white, self.bitboard.king_black), - }; - - // Based on color, extract the friendly and enemy rooks. - let (friendly_rooks, enemy_rooks) = match color { - Color::Black => (self.bitboard.rooks_black, self.bitboard.rooks_white), - Color::White => (self.bitboard.rooks_white, self.bitboard.rooks_black), - }; - // First get all the pseudolegal moves. let pslm = pseudolegal_moves::pseudolegal_moves( color, self.bitboard, - &MOVETABLE, self.castling_rights, &self.en_passant_target, self.halfmoves, self.fullmoves, + &tbl, ); // ASSERT: We will never have Super moves in the pseudolegal moves vector. @@ -137,10 +85,13 @@ impl GameManager { } // TODO: Test mask and king intersection. - let enemy_attacked = modified_gm.attacked_by(match color { - Color::Black => Color::White, - Color::White => Color::Black, - }); + let enemy_attacked = modified_gm.attacked_by( + &tbl, + match color { + Color::Black => Color::White, + Color::White => Color::Black, + }, + ); match color { Color::Black => { @@ -191,7 +142,6 @@ impl GameManager { }, castling_rights: self.castling_rights.clone(), en_passant_target: self.en_passant_target.clone(), - movetable: &MOVETABLE, ..*self }, MoveType::Capture => { @@ -209,7 +159,7 @@ impl GameManager { }, castling_rights: self.castling_rights.clone(), en_passant_target: self.en_passant_target.clone(), - movetable: &MOVETABLE, + ..*self } } @@ -239,7 +189,7 @@ impl GameManager { }, castling_rights: new_castling_rights, en_passant_target: self.en_passant_target.clone(), - movetable: &MOVETABLE, + ..*self }, MoveType::Capture => { @@ -257,7 +207,7 @@ impl GameManager { }, castling_rights: new_castling_rights, en_passant_target: self.en_passant_target.clone(), - movetable: &MOVETABLE, + ..*self } } @@ -276,7 +226,7 @@ impl GameManager { }, castling_rights: self.castling_rights.clone(), en_passant_target: self.en_passant_target.clone(), - movetable: &MOVETABLE, + ..*self }, MoveType::QueenCastle => GameManager { @@ -288,7 +238,7 @@ impl GameManager { }, castling_rights: self.castling_rights.clone(), en_passant_target: self.en_passant_target.clone(), - movetable: &MOVETABLE, + ..*self }, MoveType::Capture => { @@ -305,7 +255,7 @@ impl GameManager { }, castling_rights: self.castling_rights.clone(), en_passant_target: self.en_passant_target.clone(), - movetable: &MOVETABLE, + ..*self } } @@ -316,7 +266,7 @@ impl GameManager { }, castling_rights: self.castling_rights.clone(), en_passant_target: self.en_passant_target.clone(), - movetable: &MOVETABLE, + ..*self }, _ => unreachable!("Kings will never make another type of move."), @@ -329,7 +279,7 @@ impl GameManager { }, castling_rights: self.castling_rights.clone(), en_passant_target: self.en_passant_target.clone(), - movetable: &MOVETABLE, + ..*self }, MoveType::Capture => { @@ -347,7 +297,7 @@ impl GameManager { }, castling_rights: self.castling_rights.clone(), en_passant_target: self.en_passant_target.clone(), - movetable: &MOVETABLE, + ..*self } } @@ -363,7 +313,7 @@ impl GameManager { }, castling_rights: self.castling_rights.clone(), en_passant_target: self.en_passant_target.clone(), - movetable: &MOVETABLE, + ..*self }, MoveType::RPromotion => GameManager { @@ -374,7 +324,7 @@ impl GameManager { }, castling_rights: self.castling_rights.clone(), en_passant_target: self.en_passant_target.clone(), - movetable: &MOVETABLE, + ..*self }, MoveType::NPromotion => GameManager { @@ -385,7 +335,7 @@ impl GameManager { }, castling_rights: self.castling_rights.clone(), en_passant_target: self.en_passant_target.clone(), - movetable: &MOVETABLE, + ..*self }, MoveType::QPromotion => GameManager { @@ -396,7 +346,7 @@ impl GameManager { }, castling_rights: self.castling_rights.clone(), en_passant_target: self.en_passant_target.clone(), - movetable: &MOVETABLE, + ..*self }, // On a promotion capture to X delete all enemy pieces @@ -416,7 +366,7 @@ impl GameManager { }, castling_rights: self.castling_rights.clone(), en_passant_target: self.en_passant_target.clone(), - movetable: &MOVETABLE, + ..*self } } @@ -435,7 +385,7 @@ impl GameManager { }, castling_rights: self.castling_rights.clone(), en_passant_target: self.en_passant_target.clone(), - movetable: &MOVETABLE, + ..*self } } @@ -454,7 +404,7 @@ impl GameManager { }, castling_rights: self.castling_rights.clone(), en_passant_target: self.en_passant_target.clone(), - movetable: &MOVETABLE, + ..*self } } @@ -473,7 +423,7 @@ impl GameManager { }, castling_rights: self.castling_rights.clone(), en_passant_target: self.en_passant_target.clone(), - movetable: &MOVETABLE, + ..*self } } @@ -503,7 +453,7 @@ impl GameManager { }, castling_rights: self.castling_rights.clone(), en_passant_target: self.en_passant_target.clone(), - movetable: &MOVETABLE, + ..*self } } @@ -532,7 +482,7 @@ impl GameManager { }, castling_rights: self.castling_rights.clone(), en_passant_target: String::from(target_coord), - movetable: &MOVETABLE, + ..*self } } @@ -543,7 +493,7 @@ impl GameManager { }, castling_rights: self.castling_rights.clone(), en_passant_target: self.en_passant_target.clone(), - movetable: &MOVETABLE, + ..*self }, MoveType::Capture => { @@ -560,7 +510,7 @@ impl GameManager { }, castling_rights: self.castling_rights.clone(), en_passant_target: self.en_passant_target.clone(), - movetable: &MOVETABLE, + ..*self } } @@ -577,7 +527,7 @@ impl GameManager { }, castling_rights: self.castling_rights.clone(), en_passant_target: self.en_passant_target.clone(), - movetable: &MOVETABLE, + ..*self }, MoveType::Capture => { @@ -594,7 +544,7 @@ impl GameManager { }, castling_rights: self.castling_rights.clone(), en_passant_target: self.en_passant_target.clone(), - movetable: &MOVETABLE, + ..*self } } @@ -636,7 +586,7 @@ impl GameManager { }, castling_rights: self.castling_rights.clone(), en_passant_target: self.en_passant_target.clone(), - movetable: &MOVETABLE, + ..*self }, MoveType::Capture => { @@ -654,7 +604,7 @@ impl GameManager { }, castling_rights: self.castling_rights.clone(), en_passant_target: self.en_passant_target.clone(), - movetable: &MOVETABLE, + ..*self } } @@ -684,7 +634,7 @@ impl GameManager { }, castling_rights: new_castling_rights, en_passant_target: self.en_passant_target.clone(), - movetable: &MOVETABLE, + ..*self }, MoveType::Capture => { @@ -702,7 +652,7 @@ impl GameManager { }, castling_rights: new_castling_rights, en_passant_target: self.en_passant_target.clone(), - movetable: &MOVETABLE, + ..*self } } @@ -721,7 +671,7 @@ impl GameManager { }, castling_rights: self.castling_rights.clone(), en_passant_target: self.en_passant_target.clone(), - movetable: &MOVETABLE, + ..*self }, MoveType::QueenCastle => GameManager { @@ -733,7 +683,7 @@ impl GameManager { }, castling_rights: self.castling_rights.clone(), en_passant_target: self.en_passant_target.clone(), - movetable: &MOVETABLE, + ..*self }, MoveType::Capture => { @@ -750,7 +700,7 @@ impl GameManager { }, castling_rights: self.castling_rights.clone(), en_passant_target: self.en_passant_target.clone(), - movetable: &MOVETABLE, + ..*self } } @@ -761,7 +711,7 @@ impl GameManager { }, castling_rights: self.castling_rights.clone(), en_passant_target: self.en_passant_target.clone(), - movetable: &MOVETABLE, + ..*self }, _ => unreachable!("Kings will never make another type of move."), @@ -774,7 +724,7 @@ impl GameManager { }, castling_rights: self.castling_rights.clone(), en_passant_target: self.en_passant_target.clone(), - movetable: &MOVETABLE, + ..*self }, MoveType::Capture => { @@ -792,7 +742,7 @@ impl GameManager { }, castling_rights: self.castling_rights.clone(), en_passant_target: self.en_passant_target.clone(), - movetable: &MOVETABLE, + ..*self } } @@ -808,7 +758,7 @@ impl GameManager { }, castling_rights: self.castling_rights.clone(), en_passant_target: self.en_passant_target.clone(), - movetable: &MOVETABLE, + ..*self }, MoveType::RPromotion => GameManager { @@ -819,7 +769,7 @@ impl GameManager { }, castling_rights: self.castling_rights.clone(), en_passant_target: self.en_passant_target.clone(), - movetable: &MOVETABLE, + ..*self }, MoveType::NPromotion => GameManager { @@ -830,7 +780,7 @@ impl GameManager { }, castling_rights: self.castling_rights.clone(), en_passant_target: self.en_passant_target.clone(), - movetable: &MOVETABLE, + ..*self }, MoveType::QPromotion => GameManager { @@ -841,7 +791,7 @@ impl GameManager { }, castling_rights: self.castling_rights.clone(), en_passant_target: self.en_passant_target.clone(), - movetable: &MOVETABLE, + ..*self }, // On a promotion capture to X delete all enemy pieces @@ -861,7 +811,7 @@ impl GameManager { }, castling_rights: self.castling_rights.clone(), en_passant_target: self.en_passant_target.clone(), - movetable: &MOVETABLE, + ..*self } } @@ -880,7 +830,7 @@ impl GameManager { }, castling_rights: self.castling_rights.clone(), en_passant_target: self.en_passant_target.clone(), - movetable: &MOVETABLE, + ..*self } } @@ -899,7 +849,7 @@ impl GameManager { }, castling_rights: self.castling_rights.clone(), en_passant_target: self.en_passant_target.clone(), - movetable: &MOVETABLE, + ..*self } } @@ -918,7 +868,7 @@ impl GameManager { }, castling_rights: self.castling_rights.clone(), en_passant_target: self.en_passant_target.clone(), - movetable: &MOVETABLE, + ..*self } } @@ -948,7 +898,7 @@ impl GameManager { }, castling_rights: self.castling_rights.clone(), en_passant_target: self.en_passant_target.clone(), - movetable: &MOVETABLE, + ..*self } } @@ -977,7 +927,7 @@ impl GameManager { }, castling_rights: self.castling_rights.clone(), en_passant_target: String::from(target_coord), - movetable: &MOVETABLE, + ..*self } } @@ -988,7 +938,7 @@ impl GameManager { }, castling_rights: self.castling_rights.clone(), en_passant_target: self.en_passant_target.clone(), - movetable: &MOVETABLE, + ..*self }, MoveType::Capture => { @@ -1005,7 +955,7 @@ impl GameManager { }, castling_rights: self.castling_rights.clone(), en_passant_target: self.en_passant_target.clone(), - movetable: &MOVETABLE, + ..*self } } @@ -1022,7 +972,7 @@ impl GameManager { }, castling_rights: self.castling_rights.clone(), en_passant_target: self.en_passant_target.clone(), - movetable: &MOVETABLE, + ..*self }, MoveType::Capture => { @@ -1039,7 +989,7 @@ impl GameManager { }, castling_rights: self.castling_rights.clone(), en_passant_target: self.en_passant_target.clone(), - movetable: &MOVETABLE, + ..*self } } @@ -1058,7 +1008,7 @@ mod tests { #[test] fn test_en_passant() { let gm = GameManager::black_match_block( - &GameManager::from_fen_string("6k1/5p2/4p3/2p1P3/1pP2P2/1P6/8/6K1 b - c3 0 1"), + &GameManager::from_fen_str("6k1/5p2/4p3/2p1P3/1pP2P2/1P6/8/6K1 b - c3 0 1"), crate::types::PieceType::Pawn, crate::types::MoveType::EPCapture, crate::types::Square::B4, diff --git a/src/gamemanager/legal_moves/perft.rs b/src/gamemanager/legal_moves/perft.rs index d2e08b3..fe3f871 100644 --- a/src/gamemanager/legal_moves/perft.rs +++ b/src/gamemanager/legal_moves/perft.rs @@ -1,23 +1,13 @@ -use crate::types::Move; - -use super::GameManager; +use super::{GameManager, MoveTable, NoArc}; use rayon::prelude::*; -pub fn perft(depth: u16, maxdepth: u16, mv: Move, gm: GameManager) { - if depth > maxdepth { - return; - } - let mvlst = gm.legal_moves(); - let count = mvlst.iter().count(); +pub fn perft(depth: u16, maxdepth: u16, gm: GameManager, tbl: &NoArc) -> u64 { if depth == maxdepth { - //let s = format!("{}{}: ", mv.1.to_str(), mv.2.to_str()).to_ascii_lowercase(); - //println!("{}", s); - //eprintln!("MOVE AT DEPTH {depth}"); - //println!("{s}{}", mvlst.iter().count()); + 1 + } else { + gm.legal_moves(tbl) + .into_par_iter() + .map(|mv| perft(depth + 1, maxdepth, mv.4, tbl)) + .sum::() } - mvlst - .into_par_iter() - .for_each(|(pc, from, to, mvtp, modgm)| { - perft(depth + 1, maxdepth, (pc, from, to, mvtp.clone()), modgm) - }); } diff --git a/src/gamemanager/mod.rs b/src/gamemanager/mod.rs index f225248..61e7521 100644 --- a/src/gamemanager/mod.rs +++ b/src/gamemanager/mod.rs @@ -1,11 +1,7 @@ -#![allow(dead_code, unused_variables, unused_mut)] -use std::sync::LazyLock; - use crate::{ bitboard, - movetable::MoveTable, + movetable::{noarc::NoArc, MoveTable}, types::{CastlingRecord, Color}, - MOVETABLE, }; use bitboard::BitBoard; use pseudolegal_moves::pseudolegal_moves; @@ -33,7 +29,6 @@ pub struct GameManager { * fullmove number - number of completed turns (increment when black moves) */ pub bitboard: BitBoard, - pub movetable: &'static LazyLock, pub white_to_move: bool, pub castling_rights: CastlingRecord, pub en_passant_target: String, @@ -42,11 +37,10 @@ pub struct GameManager { } impl Default for GameManager { - /// Constructs a new `GameManager`, set to Chess's starting position + /// Constructs a new `GameManager` set to startpos. fn default() -> Self { GameManager { bitboard: BitBoard::default(), - movetable: &MOVETABLE, white_to_move: true, castling_rights: CastlingRecord::default(), en_passant_target: String::new(), @@ -60,13 +54,12 @@ impl GameManager { /// A utility method for generating a new `GameManager` from a FEN string\ /// * `fen` - a `&str` representing a game's state in FEN /// * `returns` - a `GameManager` as generated from the FEN - pub fn from_fen_string(fen: &str) -> Self { + pub fn from_fen_str(fen: &str) -> Self { if Self::is_valid_fen(fen) { let tokens: Vec = fen.split_whitespace().map(str::to_string).collect(); GameManager { //board space validation implemented at higher level (is_valid_fen()) bitboard: BitBoard::from_fen_string(&tokens[0]), - movetable: &MOVETABLE, white_to_move: tokens[1] == "w", castling_rights: CastlingRecord::try_from(tokens[2].as_str()) .expect("We expect FEN strings to be well-formed."), @@ -151,15 +144,15 @@ impl GameManager { } /// Returns a bitmask of all the pieces attacked by the given color on this GameManager's state. - pub fn attacked_by(&self, color: Color) -> u64 { + pub fn attacked_by(&self, tbl: &NoArc, color: Color) -> u64 { let moves = pseudolegal_moves( color, self.bitboard, - &MOVETABLE, self.castling_rights, &self.en_passant_target, self.halfmoves, self.fullmoves, + tbl, ); moves @@ -172,7 +165,11 @@ impl GameManager { #[cfg(test)] mod test { use super::GameManager; - use crate::{gamemanager::pseudolegal_moves::*, types::Color}; + use crate::{ + gamemanager::pseudolegal_moves::*, + movetable::{noarc::NoArc, MoveTable}, + types::Color, + }; #[test] fn check_psl_moves_1() { @@ -180,11 +177,11 @@ mod test { let moves = pseudolegal_moves( Color::Black, game_manager.bitboard, - &game_manager.movetable, game_manager.castling_rights, &game_manager.en_passant_target, game_manager.halfmoves, game_manager.fullmoves, + &NoArc::new(MoveTable::default()), ); assert_eq!( @@ -199,11 +196,11 @@ mod test { let moves = pseudolegal_moves( Color::White, game_manager.bitboard, - &game_manager.movetable, game_manager.castling_rights, &game_manager.en_passant_target, game_manager.halfmoves, game_manager.fullmoves, + &NoArc::new(MoveTable::default()), ); assert_eq!( diff --git a/src/gamemanager/pseudolegal_moves/bishops.rs b/src/gamemanager/pseudolegal_moves/bishops.rs index d614306..ac38478 100644 --- a/src/gamemanager/pseudolegal_moves/bishops.rs +++ b/src/gamemanager/pseudolegal_moves/bishops.rs @@ -1,4 +1,7 @@ -use crate::{movetable::MoveTable, types::*}; +use crate::{ + movetable::{noarc::NoArc, MoveTable}, + types::*, +}; /// Returns all pseudolegal moves the knights can make from their positions. /// ## Inputs @@ -41,10 +44,10 @@ use crate::{movetable::MoveTable, types::*}; /// ``` pub fn pseudolegal_bishop_moves( color: Color, - movetable: &MoveTable, bishop_locations: Vec, friendly_pieces: u64, enemy_pieces: u64, + movetable: &NoArc, ) -> Vec<(PieceType, Square, Square, MoveType)> { let mut bishop_pseudo_legal_moves = Vec::new(); @@ -88,17 +91,21 @@ pub fn pseudolegal_bishop_moves( #[cfg(test)] mod test { - use crate::{gamemanager::pseudolegal_moves::bishops, movetable::MoveTable, types::*}; + use crate::{ + gamemanager::pseudolegal_moves::bishops, + movetable::{noarc::NoArc, MoveTable}, + types::*, + }; use std::collections::HashSet; #[test] fn check_bishop_pslm() { let pslnm = bishops::pseudolegal_bishop_moves( Color::Black, - &MoveTable::default(), vec![0x20000000_00000000], 0xFFAF5000_00000000, 0xFFFF, + &NoArc::new(MoveTable::default()), ); let moves: HashSet = HashSet::from_iter( vec![ diff --git a/src/gamemanager/pseudolegal_moves/kings.rs b/src/gamemanager/pseudolegal_moves/kings.rs index da96346..31fb191 100644 --- a/src/gamemanager/pseudolegal_moves/kings.rs +++ b/src/gamemanager/pseudolegal_moves/kings.rs @@ -1,4 +1,7 @@ -use crate::{movetable::MoveTable, types::*}; +use crate::{ + movetable::{noarc::NoArc, MoveTable}, + types::*, +}; /// Returns all pseudolegal moves the kings can make from their positions. /// ## Inputs @@ -43,12 +46,12 @@ use crate::{movetable::MoveTable, types::*}; /// ``` pub fn pseudolegal_king_moves( color: Color, - movetable: &MoveTable, king_locations: Vec, friendly_pieces: u64, friendly_rooks: u64, enemy_pieces: u64, castling_rights: CastlingRecord, + movetable: &NoArc, ) -> Vec { let mut king_pseudo_legal_moves = Vec::new(); @@ -190,7 +193,11 @@ pub fn pseudolegal_king_moves( #[cfg(test)] mod tests { - use crate::{gamemanager::pseudolegal_moves::kings, movetable::MoveTable, types::*}; + use crate::{ + gamemanager::pseudolegal_moves::kings, + movetable::{noarc::NoArc, MoveTable}, + types::*, + }; use std::collections::HashSet; use Square::*; @@ -198,7 +205,6 @@ mod tests { fn check_king_pslm() { let pslnm = kings::pseudolegal_king_moves( Color::Black, - &MoveTable::default(), vec![B5.to_u64()], 0, 0, @@ -207,6 +213,7 @@ mod tests { black: CastlingRights::Neither, white: CastlingRights::Neither, }, + &NoArc::new(MoveTable::default()), ); let moves: HashSet = HashSet::from_iter( vec![ @@ -230,7 +237,6 @@ mod tests { fn check_black_king_pslm_castling() { let pslnm = kings::pseudolegal_king_moves( Color::Black, - &MoveTable::default(), vec![E8.to_u64()], 0, Square::A8.to_u64() | Square::H8.to_u64(), @@ -239,6 +245,7 @@ mod tests { black: CastlingRights::Both, white: CastlingRights::Neither, }, + &NoArc::new(MoveTable::default()), ); let moves: HashSet = HashSet::from_iter( vec![ @@ -262,7 +269,6 @@ mod tests { fn check_white_king_pslm_castling() { let pslnm = kings::pseudolegal_king_moves( Color::White, - &MoveTable::default(), vec![E1.to_u64()], 0, Square::A1.to_u64() | Square::H1.to_u64(), @@ -271,6 +277,7 @@ mod tests { black: CastlingRights::Neither, white: CastlingRights::Both, }, + &NoArc::new(MoveTable::default()), ); let moves: HashSet = HashSet::from_iter( vec![ diff --git a/src/gamemanager/pseudolegal_moves/knights.rs b/src/gamemanager/pseudolegal_moves/knights.rs index 02e8f76..f96dd30 100644 --- a/src/gamemanager/pseudolegal_moves/knights.rs +++ b/src/gamemanager/pseudolegal_moves/knights.rs @@ -1,4 +1,7 @@ -use crate::{movetable::MoveTable, types::*}; +use crate::{ + movetable::{noarc::NoArc, MoveTable}, + types::*, +}; /// Returns all pseudolegal moves the knights can make from their positions. /// ## Inputs @@ -29,10 +32,10 @@ use crate::{movetable::MoveTable, types::*}; /// ``` pub fn pseudolegal_knight_moves( color: Color, - movetable: &MoveTable, knight_locations: Vec, friendly_pieces: u64, enemy_pieces: u64, + movetable: &NoArc, ) -> Vec { let mut knight_pseudo_legal_moves = Vec::new(); @@ -73,6 +76,7 @@ pub fn pseudolegal_knight_moves( #[cfg(test)] mod tests { use crate::gamemanager::pseudolegal_moves::knights; + use crate::movetable::noarc::NoArc; use crate::{movetable::MoveTable, types::*}; use std::collections::HashSet; @@ -80,10 +84,10 @@ mod tests { fn check_knight_pslm() { let pslnm = knights::pseudolegal_knight_moves( Color::Black, - &MoveTable::default(), vec![0x40000000_00000000], 0xFFFF0000_00000000, 0xFFFF, + &NoArc::new(MoveTable::default()), ); let moves: HashSet = HashSet::from_iter( vec![0x00008000_00000000, 0x00002000_00000000] diff --git a/src/gamemanager/pseudolegal_moves/mod.rs b/src/gamemanager/pseudolegal_moves/mod.rs index 955725d..1119ed4 100644 --- a/src/gamemanager/pseudolegal_moves/mod.rs +++ b/src/gamemanager/pseudolegal_moves/mod.rs @@ -13,7 +13,7 @@ pub mod rooks; use crate::{ bitboard::BitBoard, gamemanager::GameManager, - movetable::MoveTable, + movetable::{noarc::NoArc, MoveTable}, types::{CastlingRecord, Color, Move}, }; @@ -23,11 +23,11 @@ use crate::{ pub fn pseudolegal_moves( color: Color, bitboard: BitBoard, - movetable: &MoveTable, castling_rights: CastlingRecord, en_passant_target: &str, halfmoves: u32, fullmoves: u32, + movetable: &NoArc, ) -> Vec { let mut pseudolegal_moves: Vec = Vec::new(); @@ -65,58 +65,58 @@ pub fn pseudolegal_moves( let mut pawn_pseudo_legal_moves = pawns::pseudolegal_pawn_moves( color, - movetable, pawns, friendly_pieces, enemy_pieces, en_passant_target, + &movetable, ); pseudolegal_moves.append(&mut pawn_pseudo_legal_moves); let mut knight_pseudo_legal_moves = knights::pseudolegal_knight_moves( color, - movetable, knights, friendly_pieces, enemy_pieces, + &movetable, ); pseudolegal_moves.append(&mut knight_pseudo_legal_moves); let mut bishop_pseudo_legal_moves = bishops::pseudolegal_bishop_moves( color, - movetable, bishops, friendly_pieces, enemy_pieces, + &movetable, ); pseudolegal_moves.append(&mut bishop_pseudo_legal_moves); let mut rook_pseudo_legal_moves = rooks::pseudolegal_rook_moves( color, - movetable, rooks, friendly_pieces, enemy_pieces, + &movetable, ); pseudolegal_moves.append(&mut rook_pseudo_legal_moves); let mut queen_pseudo_legal_moves = queens::pseudolegal_queen_moves( color, - movetable, queens, friendly_pieces, enemy_pieces, + &movetable, ); pseudolegal_moves.append(&mut queen_pseudo_legal_moves); let mut king_pseudo_legal_moves = kings::pseudolegal_king_moves( color, - movetable, kings, friendly_pieces, bitboard.rooks_black, enemy_pieces, castling_rights, + &movetable, ); pseudolegal_moves.append(&mut king_pseudo_legal_moves); } @@ -145,58 +145,58 @@ pub fn pseudolegal_moves( let mut pawn_pseudo_legal_moves = pawns::pseudolegal_pawn_moves( color, - movetable, pawns, friendly_pieces, enemy_pieces, en_passant_target, + &movetable, ); pseudolegal_moves.append(&mut pawn_pseudo_legal_moves); let mut knight_pseudo_legal_moves = knights::pseudolegal_knight_moves( color, - movetable, knights, friendly_pieces, enemy_pieces, + &movetable, ); pseudolegal_moves.append(&mut knight_pseudo_legal_moves); let mut bishop_pseudo_legal_moves = bishops::pseudolegal_bishop_moves( color, - movetable, bishops, friendly_pieces, enemy_pieces, + &movetable, ); pseudolegal_moves.append(&mut bishop_pseudo_legal_moves); let mut rook_pseudo_legal_moves = rooks::pseudolegal_rook_moves( color, - movetable, rooks, friendly_pieces, enemy_pieces, + &movetable, ); pseudolegal_moves.append(&mut rook_pseudo_legal_moves); let mut queen_pseudo_legal_moves = queens::pseudolegal_queen_moves( color, - movetable, queens, friendly_pieces, enemy_pieces, + &movetable, ); pseudolegal_moves.append(&mut queen_pseudo_legal_moves); let mut king_pseudo_legal_moves = kings::pseudolegal_king_moves( color, - movetable, kings, friendly_pieces, bitboard.rooks_white, enemy_pieces, castling_rights, + &movetable, ); pseudolegal_moves.append(&mut king_pseudo_legal_moves); } diff --git a/src/gamemanager/pseudolegal_moves/pawns.rs b/src/gamemanager/pseudolegal_moves/pawns.rs index f2bcdf7..814c286 100644 --- a/src/gamemanager/pseudolegal_moves/pawns.rs +++ b/src/gamemanager/pseudolegal_moves/pawns.rs @@ -1,4 +1,7 @@ -use crate::{movetable::MoveTable, types::*}; +use crate::{ + movetable::{noarc::NoArc, MoveTable}, + types::*, +}; /// A method returning a list of pseudo-legal pawn moves playable according to /// the information encoded in this instance of GameManager @@ -11,11 +14,11 @@ use crate::{movetable::MoveTable, types::*}; /// the target `Square`, and the `MoveType`) pub fn pseudolegal_pawn_moves( color: Color, - movetable: &MoveTable, pawn_locations: Vec, friendly_pieces: u64, enemy_pieces: u64, en_passant_target: &str, + movetable: &NoArc, ) -> Vec { let mut pawn_pseudo_legal_moves = Vec::new(); diff --git a/src/gamemanager/pseudolegal_moves/queens.rs b/src/gamemanager/pseudolegal_moves/queens.rs index 3a44f67..9026501 100644 --- a/src/gamemanager/pseudolegal_moves/queens.rs +++ b/src/gamemanager/pseudolegal_moves/queens.rs @@ -1,11 +1,14 @@ -use crate::{movetable::MoveTable, types::*}; +use crate::{ + movetable::{noarc::NoArc, MoveTable}, + types::*, +}; pub fn pseudolegal_queen_moves( color: Color, - movetable: &MoveTable, queen_locations: Vec, friendly_pieces: u64, enemy_pieces: u64, + movetable: &NoArc, ) -> Vec { let mut queen_pseudo_legal_moves = Vec::new(); diff --git a/src/gamemanager/pseudolegal_moves/rooks.rs b/src/gamemanager/pseudolegal_moves/rooks.rs index e02f377..15ba3c2 100644 --- a/src/gamemanager/pseudolegal_moves/rooks.rs +++ b/src/gamemanager/pseudolegal_moves/rooks.rs @@ -1,4 +1,7 @@ -use crate::{movetable::MoveTable, types::*}; +use crate::{ + movetable::{noarc::NoArc, MoveTable}, + types::*, +}; /// Returns all pseudolegal moves the rooks can make from their positions. /// ## Inputs @@ -13,10 +16,10 @@ use crate::{movetable::MoveTable, types::*}; /// which expands to `(PieceType, Square, Square, MoveType)`. pub fn pseudolegal_rook_moves( color: Color, - movetable: &MoveTable, rook_locations: Vec, friendly_pieces: u64, enemy_pieces: u64, + movetable: &NoArc, ) -> Vec { let mut rook_pseudo_legal_moves = Vec::new(); @@ -87,6 +90,7 @@ pub fn pseudolegal_rook_moves( #[cfg(test)] mod tests { use crate::gamemanager::pseudolegal_moves::rooks; + use crate::movetable::noarc::NoArc; use crate::{movetable::MoveTable, types::*}; use std::collections::HashSet; @@ -96,10 +100,10 @@ mod tests { let pslm = rooks::pseudolegal_rook_moves( Color::Black, - &MoveTable::default(), vec![B5.to_u64()], 0, 0, + &NoArc::new(MoveTable::default()), ); let moves: HashSet = HashSet::from_iter( vec![ diff --git a/src/main.rs b/src/main.rs index 94d6512..a263703 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,7 +1,6 @@ #![allow(dead_code)] -use std::sync::LazyLock; -use gamemanager::GameManager; +use gamemanager::{legal_moves::perft::perft, GameManager}; use movetable::{noarc, MoveTable}; mod bitboard; @@ -10,29 +9,11 @@ mod movetable; mod types; mod ucimanager; -pub static MOVETABLE: LazyLock = std::sync::LazyLock::new(MoveTable::default); - fn main() { - let movetable = noarc::NoArc::new(MoveTable::default()); + let tbl = noarc::NoArc::new(MoveTable::default()); - let gm = - GameManager::from_fen_string("rnbq1k1r/pp1Pbppp/2p5/8/2B5/8/PPP1NnPP/RNBQK2R w KQ - 1 8"); - let mvlst = gm.legal_moves(); - for mv in &mvlst { - let s = format!("{}{}: ", mv.1.to_str(), mv.2.to_str()).to_ascii_lowercase(); - println!("{}{}", s, mv.4.legal_moves().iter().count()); - // println!( - // "{}: 1", - // format!( - // "{s}{}", - // mv.4.legal_moves() - // .iter() - // .map(|newmv| format!("{}{}", newmv.1.to_str(), newmv.2.to_str())) - // .fold(String::new(), |acc, s| acc.to_owned() + " " + &s) - // .to_ascii_lowercase() - // ) - // ); - } + let gm = GameManager::default(); + println!("Searched {} nodes.", perft(0, 6, gm, &tbl)); } #[cfg(test)] @@ -68,7 +49,7 @@ mod test { ]; for fen in tests { - let game = GameManager::from_fen_string(fen); + let game = GameManager::from_fen_str(fen); let generated_fen = game.to_fen_string(); assert_eq!(fen, generated_fen); diff --git a/src/movetable/noarc.rs b/src/movetable/noarc.rs index f7a46b0..ee7d88d 100644 --- a/src/movetable/noarc.rs +++ b/src/movetable/noarc.rs @@ -1,6 +1,6 @@ use std::ops::Deref; -#[derive(Clone)] +#[derive(Copy, Clone)] pub struct NoArc { ptr: *mut T, }