From ed711f905dfba3e7082949c92063badfa6068f84 Mon Sep 17 00:00:00 2001 From: stefiosif Date: Wed, 14 Aug 2024 21:58:20 +0300 Subject: [PATCH] Refactor project structure to use submodules --- src/{ => board}/bitboard.rs | 0 src/{ => board}/board.rs | 12 ++++++------ src/{ => board}/fen.rs | 6 +++--- src/{ => board}/game.rs | 4 +++- src/board/mod.rs | 6 ++++++ src/{ => board}/square.rs | 8 +------- src/{ => board}/state.rs | 2 +- src/{ => evaluation}/evaluation.rs | 12 ++++++------ src/evaluation/mod.rs | 2 ++ src/{ => evaluation}/psqt.rs | 8 ++++---- src/interface/mod.rs | 1 + src/{ => interface}/uci.rs | 25 +++++++++++++++++++++---- src/main.rs | 26 ++++++++------------------ src/{ => movegen}/attack.rs | 6 +++--- src/{ => movegen}/magic.rs | 20 ++++++++++---------- src/movegen/mod.rs | 4 ++++ src/{ => movegen}/move.rs | 12 +++--------- src/{ => movegen}/movegen.rs | 20 ++++++++++---------- src/search/mod.rs | 3 +++ src/{ => search}/perft.rs | 10 +++++----- src/{ => search}/search.rs | 23 +++++++++++++++++++++-- 21 files changed, 121 insertions(+), 89 deletions(-) rename src/{ => board}/bitboard.rs (100%) rename src/{ => board}/board.rs (97%) rename src/{ => board}/fen.rs (97%) rename src/{ => board}/game.rs (88%) create mode 100644 src/board/mod.rs rename src/{ => board}/square.rs (94%) rename src/{ => board}/state.rs (98%) rename src/{ => evaluation}/evaluation.rs (91%) create mode 100644 src/evaluation/mod.rs rename src/{ => evaluation}/psqt.rs (96%) create mode 100644 src/interface/mod.rs rename src/{ => interface}/uci.rs (89%) rename src/{ => movegen}/attack.rs (99%) rename src/{ => movegen}/magic.rs (93%) create mode 100644 src/movegen/mod.rs rename src/{ => movegen}/move.rs (98%) rename src/{ => movegen}/movegen.rs (98%) create mode 100644 src/search/mod.rs rename src/{ => search}/perft.rs (94%) rename src/{ => search}/search.rs (54%) diff --git a/src/bitboard.rs b/src/board/bitboard.rs similarity index 100% rename from src/bitboard.rs rename to src/board/bitboard.rs diff --git a/src/board.rs b/src/board/board.rs similarity index 97% rename from src/board.rs rename to src/board/board.rs index f5943e5..6ba5179 100644 --- a/src/board.rs +++ b/src/board/board.rs @@ -1,16 +1,16 @@ use u64 as Bitboard; -use crate::attack::{ +use crate::board::bitboard::{have_common_bit, lsb}; +use crate::board::state::State; +use crate::movegen::attack::{ fetch_bishop_attacks, fetch_king_attacks, fetch_knight_attacks, fetch_pawn_attacks, fetch_queen_attacks, fetch_rook_attacks, }; -use crate::bitboard::{have_common_bit, lsb}; -use crate::movegen::{ +use crate::movegen::movegen::{ bishop_pseudo_moves, king_pseudo_moves, knight_pseudo_moves, pawn_pseudo_moves, queen_pseudo_moves, rook_pseudo_moves, }; -use crate::r#move::Move; -use crate::state::State; +use crate::movegen::r#move::Move; #[derive(Debug, PartialEq, Eq, Clone)] pub struct Board { @@ -247,7 +247,7 @@ impl Color { #[cfg(test)] mod tests { - use crate::{attack::init_attacks, fen::from_fen}; + use crate::{board::fen::from_fen, movegen::attack::init_attacks}; use super::*; diff --git a/src/fen.rs b/src/board/fen.rs similarity index 97% rename from src/fen.rs rename to src/board/fen.rs index 1a51a8c..3d0b2be 100644 --- a/src/fen.rs +++ b/src/board/fen.rs @@ -1,6 +1,6 @@ -use crate::board::{Board, Color, Piece, PieceType}; -use crate::game::Game; -use crate::state::{Castle, State}; +use crate::board::board::{Board, Color, Piece, PieceType}; +use crate::board::game::Game; +use crate::board::state::{Castle, State}; use String as FenError; pub fn from_fen(fen: &str) -> Result { diff --git a/src/game.rs b/src/board/game.rs similarity index 88% rename from src/game.rs rename to src/board/game.rs index 638191e..08054c3 100644 --- a/src/game.rs +++ b/src/board/game.rs @@ -1,6 +1,8 @@ -use crate::{board::Board, fen::from_fen}; +use crate::board::fen::from_fen; use String as FenError; +use super::board::Board; + #[derive(Debug, PartialEq, Eq)] pub struct Game { pub board: Board, diff --git a/src/board/mod.rs b/src/board/mod.rs new file mode 100644 index 0000000..1d7dcc8 --- /dev/null +++ b/src/board/mod.rs @@ -0,0 +1,6 @@ +pub mod bitboard; +pub mod board; +pub mod fen; +pub mod game; +pub mod square; +pub mod state; diff --git a/src/square.rs b/src/board/square.rs similarity index 94% rename from src/square.rs rename to src/board/square.rs index 0cbe211..86b4416 100644 --- a/src/square.rs +++ b/src/board/square.rs @@ -1,6 +1,6 @@ use u64 as Bitboard; -use crate::bitboard::lsb; +use crate::board::bitboard::lsb; pub struct Square {} @@ -95,9 +95,3 @@ pub fn square_to_algebraic(square: usize) -> String { format!("{}{}", (file + b'a') as char, (rank + b'1') as char) } - -impl Square { - pub const fn to_bitboard(square: usize) -> Bitboard { - 1_u64 << square - } -} diff --git a/src/state.rs b/src/board/state.rs similarity index 98% rename from src/state.rs rename to src/board/state.rs index 35e5f7f..a00001c 100644 --- a/src/state.rs +++ b/src/board/state.rs @@ -1,4 +1,4 @@ -use crate::{board::Color, r#move::MoveType}; +use crate::{board::board::Color, movegen::r#move::MoveType}; #[derive(Debug, PartialEq, Eq, Clone, Copy)] pub struct State { diff --git a/src/evaluation.rs b/src/evaluation/evaluation.rs similarity index 91% rename from src/evaluation.rs rename to src/evaluation/evaluation.rs index ea283ef..cbe01cf 100644 --- a/src/evaluation.rs +++ b/src/evaluation/evaluation.rs @@ -1,9 +1,9 @@ use u64 as Bitboard; use crate::{ - bitboard::lsb, - board::{Board, Color, PieceType}, - psqt::{mirror_index, piece_square_score}, + board::bitboard::lsb, + board::board::{Board, Color, PieceType}, + evaluation::psqt::{mirror_index, piece_square_score}, }; const fn piece_score(piece_type: PieceType) -> i32 { @@ -56,9 +56,9 @@ pub fn evaluate_position(board: &Board, color: Color) -> i32 { #[cfg(test)] mod tests { use crate::{ - board::{Color, PieceType}, - evaluation::{evaluate_position, evaluate_side, piece_score}, - fen::from_fen, + board::board::{Color, PieceType}, + board::fen::from_fen, + evaluation::evaluation::{evaluate_position, evaluate_side, piece_score}, }; const FEN_QUIET: [&str; 2] = [ diff --git a/src/evaluation/mod.rs b/src/evaluation/mod.rs new file mode 100644 index 0000000..2d9779a --- /dev/null +++ b/src/evaluation/mod.rs @@ -0,0 +1,2 @@ +pub mod evaluation; +pub mod psqt; diff --git a/src/psqt.rs b/src/evaluation/psqt.rs similarity index 96% rename from src/psqt.rs rename to src/evaluation/psqt.rs index 1ba2534..4ffbcd5 100644 --- a/src/psqt.rs +++ b/src/evaluation/psqt.rs @@ -1,4 +1,4 @@ -use crate::board::PieceType; +use crate::board::board::PieceType; pub const fn piece_square_score(piece_type: PieceType, index: usize) -> i32 { match piece_type { @@ -113,9 +113,9 @@ const KING_ENDGAME_PSQT: [i32; 64] = [ #[cfg(test)] mod tests { use crate::{ - board::PieceType, - psqt::{mirror_index, piece_square_score}, - square::Square, + board::board::PieceType, + board::square::Square, + evaluation::psqt::{mirror_index, piece_square_score}, }; #[test] diff --git a/src/interface/mod.rs b/src/interface/mod.rs new file mode 100644 index 0000000..9e50542 --- /dev/null +++ b/src/interface/mod.rs @@ -0,0 +1 @@ +pub mod uci; diff --git a/src/uci.rs b/src/interface/uci.rs similarity index 89% rename from src/uci.rs rename to src/interface/uci.rs index 8c0b32b..8138ee3 100644 --- a/src/uci.rs +++ b/src/interface/uci.rs @@ -3,7 +3,7 @@ use std::{ str::SplitWhitespace, }; -use crate::{game::Game, r#move::Move, search::search, square::Square}; +use crate::{board::game::Game, board::square::Square, movegen::r#move::Move, search::search}; #[derive(PartialEq, Eq, Debug)] pub enum Command { @@ -128,7 +128,7 @@ pub fn uci_go(go: &mut SplitWhitespace, game: &mut Game) -> Result _ => (), } } - search(game, params.depth.unwrap_or(MAX_DEPTH)); + search::search(game, params.depth.unwrap_or(MAX_DEPTH)); Ok(Move::new(Square::B8, Square::C6)) } @@ -173,8 +173,8 @@ pub fn uci_loop() -> Result<(), String> { #[cfg(test)] mod tests { use crate::{ - fen::from_fen, - uci::{parse_command, Command}, + board::fen::from_fen, + interface::uci::{parse_command, Command}, }; use super::uci_position; @@ -217,3 +217,20 @@ mod tests { Ok(()) } } + +/* +``` +- CuteChess: `uci` +- Engine: `id name MyChessEngine` +- Engine: `id author John Doe` +- Engine: `option name Hash type spin default 32 min 1 max 512` +- Engine: `uciok` +- CuteChess: `setoption name Hash value 128` +- CuteChess: `ucinewgame` +- CuteChess: `position startpos moves e2e4 e7e5` +- CuteChess: `go wtime 600000 btime 600000 winc 0 binc 0` +- Engine: `info depth 1 score cp 20 nodes 15 nps 1500 time 10 pv e2e4` +- Engine: `bestmove e2e4` +- CuteChess: `quit` +``` +*/ diff --git a/src/main.rs b/src/main.rs index 9cf8484..984141a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,26 +1,16 @@ -pub mod attack; -pub mod bitboard; -pub mod board; -pub mod evaluation; -pub mod fen; -pub mod game; -pub mod magic; -pub mod r#move; -pub mod movegen; -pub mod perft; -pub mod psqt; -pub mod search; -pub mod square; -pub mod state; -pub mod uci; +mod board; +mod evaluation; +mod interface; +mod movegen; +mod search; fn main() { - attack::init_attacks(); + movegen::attack::init_attacks(); let command = std::env::args().nth(1).unwrap_or(String::from("quit")); match command.as_str() { - "perft" => perft::perftree_script(), - "uci" => uci::uci_loop().unwrap_or_else(|e| println!("{}", e)), + "perft" => search::perft::perftree_script(), + "uci" => interface::uci::uci_loop().unwrap_or_else(|e| println!("{}", e)), "quit" => println!("Exiting.."), _ => println!("Wrong command. Exiting.."), }; diff --git a/src/attack.rs b/src/movegen/attack.rs similarity index 99% rename from src/attack.rs rename to src/movegen/attack.rs index e65010a..04c86d9 100644 --- a/src/attack.rs +++ b/src/movegen/attack.rs @@ -1,4 +1,4 @@ -use crate::{ +use crate::board::{ bitboard::{ have_common_bit, lsb, square_to_bitboard, square_to_bitboard_wrapping, EMPTY, NOT_FILE_A, NOT_FILE_AB, NOT_FILE_GH, NOT_FILE_H, @@ -218,7 +218,7 @@ pub fn fetch_king_attacks(square: usize) -> Bitboard { unsafe { KING_ATTACKS[square] } } -use crate::magic::{BISHOP_MAGIC, ROOK_MAGIC}; +use crate::movegen::magic::{BISHOP_MAGIC, ROOK_MAGIC}; pub fn fetch_bishop_attacks(mut occupancy: Bitboard, square: usize) -> Bitboard { unsafe { @@ -316,7 +316,7 @@ pub fn init_attacks() { #[cfg(test)] mod tests { use super::*; - use crate::board::{Color, Piece, PieceType}; + use crate::board::board::{Color, Piece, PieceType}; #[test] fn test_pawn_attacks() -> Result<(), String> { diff --git a/src/magic.rs b/src/movegen/magic.rs similarity index 93% rename from src/magic.rs rename to src/movegen/magic.rs index c8f2304..f6ea00b 100644 --- a/src/magic.rs +++ b/src/movegen/magic.rs @@ -1,9 +1,9 @@ -use crate::attack::{ +use crate::board::bitboard::{bit_count, square_to_bitboard, EMPTY, RANK_8}; +use crate::board::square::Square; +use crate::movegen::attack::{ bishop_attacks_on_the_fly, mask_bishop_attacks, mask_rook_attacks, rook_attacks_on_the_fly, set_occupancy, BISHOP_RELEVANT_BITS, ROOK_RELEVANT_BITS, }; -use crate::bitboard::{bit_count, square_to_bitboard, EMPTY, RANK_8}; -use crate::square::Square; use rand::rngs::SmallRng; use rand::{RngCore, SeedableRng}; use u64 as Bitboard; @@ -51,7 +51,7 @@ pub const BISHOP_MAGIC: [u64; 64] = [ 0x4000000004208200, 0x804a10011602, 0x200a24c410041500, 0x8408080088061020, ]; -pub fn random_uint64(state: &mut SmallRng) -> u64 { +fn random_uint64(state: &mut SmallRng) -> u64 { let n1 = state.next_u32() as u64 & 0xffff; let n2 = state.next_u32() as u64 & 0xffff; let n3 = state.next_u32() as u64 & 0xffff; @@ -60,11 +60,11 @@ pub fn random_uint64(state: &mut SmallRng) -> u64 { n1 | (n2 << (16)) | (n3 << (32)) | (n4 << (48)) } -pub fn generate_magic_number_candidate(state: &mut SmallRng) -> u64 { +fn generate_magic_number_candidate(state: &mut SmallRng) -> u64 { random_uint64(state) & random_uint64(state) & random_uint64(state) } -pub fn init_magic_arrays() { +fn init_magic_arrays() { let mut state = SmallRng::seed_from_u64(1804289383); for square in Square::A1..=Square::H8 { @@ -93,7 +93,7 @@ pub fn init_magic_arrays() { } } -pub fn find_magic_numbers( +fn find_magic_numbers( relevant_bits: usize, bitboard: Bitboard, state: &mut SmallRng, @@ -125,7 +125,7 @@ where ) } -pub fn generate_magic_number( +fn generate_magic_number( relevant_bits: usize, state: &mut SmallRng, attack_mask: u64, @@ -165,8 +165,8 @@ pub fn generate_magic_number( mod tests { use super::init_magic_arrays; use crate::{ - magic::{BISHOP_MAGIC, BISHOP_MAGIC_INIT, ROOK_MAGIC, ROOK_MAGIC_INIT}, - square::Square, + board::square::Square, + movegen::magic::{BISHOP_MAGIC, BISHOP_MAGIC_INIT, ROOK_MAGIC, ROOK_MAGIC_INIT}, }; #[test] diff --git a/src/movegen/mod.rs b/src/movegen/mod.rs new file mode 100644 index 0000000..c6a70ac --- /dev/null +++ b/src/movegen/mod.rs @@ -0,0 +1,4 @@ +pub mod attack; +pub mod magic; +pub mod r#move; +pub mod movegen; diff --git a/src/move.rs b/src/movegen/move.rs similarity index 98% rename from src/move.rs rename to src/movegen/move.rs index eacc202..3e1bdf2 100644 --- a/src/move.rs +++ b/src/movegen/move.rs @@ -1,6 +1,6 @@ use core::fmt; -use crate::{ +use crate::board::{ bitboard::{have_common_bit, square_to_bitboard}, board::{Board, Color, Piece, PieceType}, square::{coords_to_square, square_to_algebraic, Square}, @@ -112,8 +112,6 @@ impl Board { self.update_board_state(mv, color); } - pub fn unmake_move(&mut self) {} - pub fn update_board_state(&mut self, mv: &Move, color: Color) { let (own_pieces, opponent_pieces, en_passant_square) = match color { Color::White => ( @@ -227,12 +225,8 @@ impl Board { #[cfg(test)] mod tests { - use crate::{ - board::Color, - fen::from_fen, - r#move::{Move, MoveType, Promote}, - square::Square, - }; + use crate::board::{board::Color, fen::from_fen, square::Square}; + use crate::movegen::r#move::{Move, MoveType, Promote}; const FEN_QUIET: [&str; 2] = [ "r3k2r/2p1p1qp/2npb3/1p3p2/p3P1pP/P1PB1Q2/1P1PNPP1/R3K2R w KQkq - 0 1", diff --git a/src/movegen.rs b/src/movegen/movegen.rs similarity index 98% rename from src/movegen.rs rename to src/movegen/movegen.rs index cc9dcf1..3dd4445 100644 --- a/src/movegen.rs +++ b/src/movegen/movegen.rs @@ -1,14 +1,14 @@ -use crate::attack::{ - fetch_bishop_attacks, fetch_king_attacks, fetch_knight_attacks, fetch_pawn_attacks, - fetch_queen_attacks, fetch_rook_attacks, -}; -use crate::bitboard::{ +use crate::board::bitboard::{ have_common_bit, lsb, square_to_bitboard, NOT_FILE_A, NOT_FILE_H, RANK_1, RANK_2, RANK_4, RANK_5, RANK_7, RANK_8, }; -use crate::board::{Board, Color}; -use crate::r#move::{Move, MoveType, Promote}; -use crate::state::Castle; +use crate::board::board::{Board, Color}; +use crate::board::state::Castle; +use crate::movegen::attack::{ + fetch_bishop_attacks, fetch_king_attacks, fetch_knight_attacks, fetch_pawn_attacks, + fetch_queen_attacks, fetch_rook_attacks, +}; +use crate::movegen::r#move::{Move, MoveType, Promote}; use u64 as Bitboard; pub fn pawn_pseudo_moves( @@ -399,10 +399,10 @@ fn king_and_adj_square_safety(board: &Board, color: Color) -> Castle { #[cfg(test)] mod tests { - use crate::{attack::init_attacks, fen::from_fen}; + use crate::{board::fen::from_fen, movegen::attack::init_attacks}; use super::*; - use crate::board::PieceType; + use crate::board::board::PieceType; const FEN_PAWN_MOVES: &str = "r1bqk2r/p4pbp/1pnp1np1/P3P1B1/3NNP2/8/1PP3PP/R2QKB1R w - - 0 1"; diff --git a/src/search/mod.rs b/src/search/mod.rs new file mode 100644 index 0000000..91e3c9c --- /dev/null +++ b/src/search/mod.rs @@ -0,0 +1,3 @@ +pub mod move_ordering; +pub mod perft; +pub mod search; diff --git a/src/perft.rs b/src/search/perft.rs similarity index 94% rename from src/perft.rs rename to src/search/perft.rs index f586ee0..9177c43 100644 --- a/src/perft.rs +++ b/src/search/perft.rs @@ -1,4 +1,4 @@ -use crate::game::Game; +use crate::board::game::Game; pub fn driver(game: &mut Game, nodes: &mut u64, depth: u8) { if depth == 0 { @@ -12,7 +12,7 @@ pub fn driver(game: &mut Game, nodes: &mut u64, depth: u8) { for mv in pseudo_moves { let original_board = game.board.clone(); game.board.make_move(&mv, color); - + if game.board.king_under_check(color) { game.board = original_board; continue; @@ -27,7 +27,7 @@ const MAX_DEPTH: u8 = 3; pub fn perftree_script() { let fen = "r3k2r/p1ppqpb1/bn2pnp1/3PN3/1p2P3/2N2Q1p/PPPBBPPP/R3K2R w KQkq - 0 1"; - let mut game = crate::fen::from_fen(fen).expect("Invalid FEN string"); + let mut game = crate::board::fen::from_fen(fen).expect("Invalid FEN string"); let (mut nodes, depth): (u64, u8) = (0, MAX_DEPTH); driver(&mut game, &mut nodes, depth); } @@ -35,7 +35,7 @@ pub fn perftree_script() { use std::collections::HashMap; #[rustfmt::skip] -pub fn square_to_notation(square: u8) -> &'static str { +pub fn _square_to_notation(square: u8) -> &'static str { let mut map: HashMap = HashMap::new(); map.insert(0, "a1"); map.insert(1, "b1"); map.insert(2, "c1"); map.insert(3, "d1"); map.insert(4, "e1"); map.insert(5, "f1"); map.insert(6, "g1"); map.insert(7, "h1"); @@ -58,7 +58,7 @@ pub fn square_to_notation(square: u8) -> &'static str { #[cfg(test)] mod tests { - use crate::{attack::init_attacks, fen::from_fen}; + use crate::{board::fen::from_fen, movegen::attack::init_attacks}; use super::driver; diff --git a/src/search.rs b/src/search/search.rs similarity index 54% rename from src/search.rs rename to src/search/search.rs index 53a97f4..fb2f286 100644 --- a/src/search.rs +++ b/src/search/search.rs @@ -1,4 +1,4 @@ -use crate::game::Game; +use crate::board::game::Game; pub fn search(game: &mut Game, depth: u8) { if depth == 0 { @@ -11,7 +11,7 @@ pub fn search(game: &mut Game, depth: u8) { for mv in pseudo_moves { let original_board = game.board.clone(); game.board.make_move(&mv, color); - + if game.board.king_under_check(color) { game.board = original_board; continue; @@ -21,3 +21,22 @@ pub fn search(game: &mut Game, depth: u8) { game.board = original_board; } } + +#[cfg(test)] +mod tests { + use crate::board::fen::from_fen; + + const FEN_QUIET: [&str; 2] = [ + "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1", + "rnbqkbnr/ppp2ppp/4p3/3pN3/3P4/8/PPP1PPPP/RNBQKB1R w KQkq - 0 1", + ]; + + #[test] + fn test_search() -> Result<(), String> { + let _game = from_fen(FEN_QUIET[0])?; + + //TODO: + + Ok(()) + } +}