Refactor project structure to use submodules

This commit is contained in:
stefiosif
2024-08-14 21:58:20 +03:00
parent 69cabd5b58
commit ed711f905d
21 changed files with 121 additions and 89 deletions

View File

@@ -1,16 +1,16 @@
use u64 as Bitboard; 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_bishop_attacks, fetch_king_attacks, fetch_knight_attacks, fetch_pawn_attacks,
fetch_queen_attacks, fetch_rook_attacks, fetch_queen_attacks, fetch_rook_attacks,
}; };
use crate::bitboard::{have_common_bit, lsb}; use crate::movegen::movegen::{
use crate::movegen::{
bishop_pseudo_moves, king_pseudo_moves, knight_pseudo_moves, pawn_pseudo_moves, bishop_pseudo_moves, king_pseudo_moves, knight_pseudo_moves, pawn_pseudo_moves,
queen_pseudo_moves, rook_pseudo_moves, queen_pseudo_moves, rook_pseudo_moves,
}; };
use crate::r#move::Move; use crate::movegen::r#move::Move;
use crate::state::State;
#[derive(Debug, PartialEq, Eq, Clone)] #[derive(Debug, PartialEq, Eq, Clone)]
pub struct Board { pub struct Board {
@@ -247,7 +247,7 @@ impl Color {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::{attack::init_attacks, fen::from_fen}; use crate::{board::fen::from_fen, movegen::attack::init_attacks};
use super::*; use super::*;

View File

@@ -1,6 +1,6 @@
use crate::board::{Board, Color, Piece, PieceType}; use crate::board::board::{Board, Color, Piece, PieceType};
use crate::game::Game; use crate::board::game::Game;
use crate::state::{Castle, State}; use crate::board::state::{Castle, State};
use String as FenError; use String as FenError;
pub fn from_fen(fen: &str) -> Result<Game, FenError> { pub fn from_fen(fen: &str) -> Result<Game, FenError> {

View File

@@ -1,6 +1,8 @@
use crate::{board::Board, fen::from_fen}; use crate::board::fen::from_fen;
use String as FenError; use String as FenError;
use super::board::Board;
#[derive(Debug, PartialEq, Eq)] #[derive(Debug, PartialEq, Eq)]
pub struct Game { pub struct Game {
pub board: Board, pub board: Board,

6
src/board/mod.rs Normal file
View File

@@ -0,0 +1,6 @@
pub mod bitboard;
pub mod board;
pub mod fen;
pub mod game;
pub mod square;
pub mod state;

View File

@@ -1,6 +1,6 @@
use u64 as Bitboard; use u64 as Bitboard;
use crate::bitboard::lsb; use crate::board::bitboard::lsb;
pub struct Square {} 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) format!("{}{}", (file + b'a') as char, (rank + b'1') as char)
} }
impl Square {
pub const fn to_bitboard(square: usize) -> Bitboard {
1_u64 << square
}
}

View File

@@ -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)] #[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub struct State { pub struct State {

View File

@@ -1,9 +1,9 @@
use u64 as Bitboard; use u64 as Bitboard;
use crate::{ use crate::{
bitboard::lsb, board::bitboard::lsb,
board::{Board, Color, PieceType}, board::board::{Board, Color, PieceType},
psqt::{mirror_index, piece_square_score}, evaluation::psqt::{mirror_index, piece_square_score},
}; };
const fn piece_score(piece_type: PieceType) -> i32 { const fn piece_score(piece_type: PieceType) -> i32 {
@@ -56,9 +56,9 @@ pub fn evaluate_position(board: &Board, color: Color) -> i32 {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::{ use crate::{
board::{Color, PieceType}, board::board::{Color, PieceType},
evaluation::{evaluate_position, evaluate_side, piece_score}, board::fen::from_fen,
fen::from_fen, evaluation::evaluation::{evaluate_position, evaluate_side, piece_score},
}; };
const FEN_QUIET: [&str; 2] = [ const FEN_QUIET: [&str; 2] = [

2
src/evaluation/mod.rs Normal file
View File

@@ -0,0 +1,2 @@
pub mod evaluation;
pub mod psqt;

View File

@@ -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 { pub const fn piece_square_score(piece_type: PieceType, index: usize) -> i32 {
match piece_type { match piece_type {
@@ -113,9 +113,9 @@ const KING_ENDGAME_PSQT: [i32; 64] = [
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::{ use crate::{
board::PieceType, board::board::PieceType,
psqt::{mirror_index, piece_square_score}, board::square::Square,
square::Square, evaluation::psqt::{mirror_index, piece_square_score},
}; };
#[test] #[test]

1
src/interface/mod.rs Normal file
View File

@@ -0,0 +1 @@
pub mod uci;

View File

@@ -3,7 +3,7 @@ use std::{
str::SplitWhitespace, 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)] #[derive(PartialEq, Eq, Debug)]
pub enum Command { pub enum Command {
@@ -128,7 +128,7 @@ pub fn uci_go(go: &mut SplitWhitespace, game: &mut Game) -> Result<Move, String>
_ => (), _ => (),
} }
} }
search(game, params.depth.unwrap_or(MAX_DEPTH)); search::search(game, params.depth.unwrap_or(MAX_DEPTH));
Ok(Move::new(Square::B8, Square::C6)) Ok(Move::new(Square::B8, Square::C6))
} }
@@ -173,8 +173,8 @@ pub fn uci_loop() -> Result<(), String> {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::{ use crate::{
fen::from_fen, board::fen::from_fen,
uci::{parse_command, Command}, interface::uci::{parse_command, Command},
}; };
use super::uci_position; use super::uci_position;
@@ -217,3 +217,20 @@ mod tests {
Ok(()) 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`
```
*/

View File

@@ -1,26 +1,16 @@
pub mod attack; mod board;
pub mod bitboard; mod evaluation;
pub mod board; mod interface;
pub mod evaluation; mod movegen;
pub mod fen; mod search;
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;
fn main() { fn main() {
attack::init_attacks(); movegen::attack::init_attacks();
let command = std::env::args().nth(1).unwrap_or(String::from("quit")); let command = std::env::args().nth(1).unwrap_or(String::from("quit"));
match command.as_str() { match command.as_str() {
"perft" => perft::perftree_script(), "perft" => search::perft::perftree_script(),
"uci" => uci::uci_loop().unwrap_or_else(|e| println!("{}", e)), "uci" => interface::uci::uci_loop().unwrap_or_else(|e| println!("{}", e)),
"quit" => println!("Exiting.."), "quit" => println!("Exiting.."),
_ => println!("Wrong command. Exiting.."), _ => println!("Wrong command. Exiting.."),
}; };

View File

@@ -1,4 +1,4 @@
use crate::{ use crate::board::{
bitboard::{ bitboard::{
have_common_bit, lsb, square_to_bitboard, square_to_bitboard_wrapping, EMPTY, NOT_FILE_A, have_common_bit, lsb, square_to_bitboard, square_to_bitboard_wrapping, EMPTY, NOT_FILE_A,
NOT_FILE_AB, NOT_FILE_GH, NOT_FILE_H, 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] } 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 { pub fn fetch_bishop_attacks(mut occupancy: Bitboard, square: usize) -> Bitboard {
unsafe { unsafe {
@@ -316,7 +316,7 @@ pub fn init_attacks() {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use crate::board::{Color, Piece, PieceType}; use crate::board::board::{Color, Piece, PieceType};
#[test] #[test]
fn test_pawn_attacks() -> Result<(), String> { fn test_pawn_attacks() -> Result<(), String> {

View File

@@ -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, bishop_attacks_on_the_fly, mask_bishop_attacks, mask_rook_attacks, rook_attacks_on_the_fly,
set_occupancy, BISHOP_RELEVANT_BITS, ROOK_RELEVANT_BITS, 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::rngs::SmallRng;
use rand::{RngCore, SeedableRng}; use rand::{RngCore, SeedableRng};
use u64 as Bitboard; use u64 as Bitboard;
@@ -51,7 +51,7 @@ pub const BISHOP_MAGIC: [u64; 64] = [
0x4000000004208200, 0x804a10011602, 0x200a24c410041500, 0x8408080088061020, 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 n1 = state.next_u32() as u64 & 0xffff;
let n2 = state.next_u32() as u64 & 0xffff; let n2 = state.next_u32() as u64 & 0xffff;
let n3 = 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)) 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) 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); let mut state = SmallRng::seed_from_u64(1804289383);
for square in Square::A1..=Square::H8 { for square in Square::A1..=Square::H8 {
@@ -93,7 +93,7 @@ pub fn init_magic_arrays() {
} }
} }
pub fn find_magic_numbers<F1, F2>( fn find_magic_numbers<F1, F2>(
relevant_bits: usize, relevant_bits: usize,
bitboard: Bitboard, bitboard: Bitboard,
state: &mut SmallRng, state: &mut SmallRng,
@@ -125,7 +125,7 @@ where
) )
} }
pub fn generate_magic_number( fn generate_magic_number(
relevant_bits: usize, relevant_bits: usize,
state: &mut SmallRng, state: &mut SmallRng,
attack_mask: u64, attack_mask: u64,
@@ -165,8 +165,8 @@ pub fn generate_magic_number(
mod tests { mod tests {
use super::init_magic_arrays; use super::init_magic_arrays;
use crate::{ use crate::{
magic::{BISHOP_MAGIC, BISHOP_MAGIC_INIT, ROOK_MAGIC, ROOK_MAGIC_INIT}, board::square::Square,
square::Square, movegen::magic::{BISHOP_MAGIC, BISHOP_MAGIC_INIT, ROOK_MAGIC, ROOK_MAGIC_INIT},
}; };
#[test] #[test]

4
src/movegen/mod.rs Normal file
View File

@@ -0,0 +1,4 @@
pub mod attack;
pub mod magic;
pub mod r#move;
pub mod movegen;

View File

@@ -1,6 +1,6 @@
use core::fmt; use core::fmt;
use crate::{ use crate::board::{
bitboard::{have_common_bit, square_to_bitboard}, bitboard::{have_common_bit, square_to_bitboard},
board::{Board, Color, Piece, PieceType}, board::{Board, Color, Piece, PieceType},
square::{coords_to_square, square_to_algebraic, Square}, square::{coords_to_square, square_to_algebraic, Square},
@@ -112,8 +112,6 @@ impl Board {
self.update_board_state(mv, color); self.update_board_state(mv, color);
} }
pub fn unmake_move(&mut self) {}
pub fn update_board_state(&mut self, mv: &Move, color: Color) { pub fn update_board_state(&mut self, mv: &Move, color: Color) {
let (own_pieces, opponent_pieces, en_passant_square) = match color { let (own_pieces, opponent_pieces, en_passant_square) = match color {
Color::White => ( Color::White => (
@@ -227,12 +225,8 @@ impl Board {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::{ use crate::board::{board::Color, fen::from_fen, square::Square};
board::Color, use crate::movegen::r#move::{Move, MoveType, Promote};
fen::from_fen,
r#move::{Move, MoveType, Promote},
square::Square,
};
const FEN_QUIET: [&str; 2] = [ const FEN_QUIET: [&str; 2] = [
"r3k2r/2p1p1qp/2npb3/1p3p2/p3P1pP/P1PB1Q2/1P1PNPP1/R3K2R w KQkq - 0 1", "r3k2r/2p1p1qp/2npb3/1p3p2/p3P1pP/P1PB1Q2/1P1PNPP1/R3K2R w KQkq - 0 1",

View File

@@ -1,14 +1,14 @@
use crate::attack::{ use crate::board::bitboard::{
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, square_to_bitboard, NOT_FILE_A, NOT_FILE_H, RANK_1, RANK_2, RANK_4, 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, RANK_5, RANK_7, RANK_8,
}; };
use crate::board::{Board, Color}; use crate::board::board::{Board, Color};
use crate::r#move::{Move, MoveType, Promote}; use crate::board::state::Castle;
use crate::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; use u64 as Bitboard;
pub fn pawn_pseudo_moves( pub fn pawn_pseudo_moves(
@@ -399,10 +399,10 @@ fn king_and_adj_square_safety(board: &Board, color: Color) -> Castle {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::{attack::init_attacks, fen::from_fen}; use crate::{board::fen::from_fen, movegen::attack::init_attacks};
use super::*; 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"; const FEN_PAWN_MOVES: &str = "r1bqk2r/p4pbp/1pnp1np1/P3P1B1/3NNP2/8/1PP3PP/R2QKB1R w - - 0 1";

3
src/search/mod.rs Normal file
View File

@@ -0,0 +1,3 @@
pub mod move_ordering;
pub mod perft;
pub mod search;

View File

@@ -1,4 +1,4 @@
use crate::game::Game; use crate::board::game::Game;
pub fn driver(game: &mut Game, nodes: &mut u64, depth: u8) { pub fn driver(game: &mut Game, nodes: &mut u64, depth: u8) {
if depth == 0 { if depth == 0 {
@@ -12,7 +12,7 @@ pub fn driver(game: &mut Game, nodes: &mut u64, depth: u8) {
for mv in pseudo_moves { for mv in pseudo_moves {
let original_board = game.board.clone(); let original_board = game.board.clone();
game.board.make_move(&mv, color); game.board.make_move(&mv, color);
if game.board.king_under_check(color) { if game.board.king_under_check(color) {
game.board = original_board; game.board = original_board;
continue; continue;
@@ -27,7 +27,7 @@ const MAX_DEPTH: u8 = 3;
pub fn perftree_script() { pub fn perftree_script() {
let fen = "r3k2r/p1ppqpb1/bn2pnp1/3PN3/1p2P3/2N2Q1p/PPPBBPPP/R3K2R w KQkq - 0 1"; 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); let (mut nodes, depth): (u64, u8) = (0, MAX_DEPTH);
driver(&mut game, &mut nodes, depth); driver(&mut game, &mut nodes, depth);
} }
@@ -35,7 +35,7 @@ pub fn perftree_script() {
use std::collections::HashMap; use std::collections::HashMap;
#[rustfmt::skip] #[rustfmt::skip]
pub fn square_to_notation(square: u8) -> &'static str { pub fn _square_to_notation(square: u8) -> &'static str {
let mut map: HashMap<u8, &str> = HashMap::new(); let mut map: HashMap<u8, &str> = HashMap::new();
map.insert(0, "a1"); map.insert(1, "b1"); map.insert(2, "c1"); map.insert(3, "d1"); 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"); 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)] #[cfg(test)]
mod tests { mod tests {
use crate::{attack::init_attacks, fen::from_fen}; use crate::{board::fen::from_fen, movegen::attack::init_attacks};
use super::driver; use super::driver;

View File

@@ -1,4 +1,4 @@
use crate::game::Game; use crate::board::game::Game;
pub fn search(game: &mut Game, depth: u8) { pub fn search(game: &mut Game, depth: u8) {
if depth == 0 { if depth == 0 {
@@ -11,7 +11,7 @@ pub fn search(game: &mut Game, depth: u8) {
for mv in pseudo_moves { for mv in pseudo_moves {
let original_board = game.board.clone(); let original_board = game.board.clone();
game.board.make_move(&mv, color); game.board.make_move(&mv, color);
if game.board.king_under_check(color) { if game.board.king_under_check(color) {
game.board = original_board; game.board = original_board;
continue; continue;
@@ -21,3 +21,22 @@ pub fn search(game: &mut Game, depth: u8) {
game.board = original_board; 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(())
}
}