Refactor project structure to use submodules
This commit is contained in:
@@ -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::*;
|
||||
|
||||
@@ -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<Game, FenError> {
|
||||
@@ -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,
|
||||
6
src/board/mod.rs
Normal file
6
src/board/mod.rs
Normal file
@@ -0,0 +1,6 @@
|
||||
pub mod bitboard;
|
||||
pub mod board;
|
||||
pub mod fen;
|
||||
pub mod game;
|
||||
pub mod square;
|
||||
pub mod state;
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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 {
|
||||
@@ -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] = [
|
||||
2
src/evaluation/mod.rs
Normal file
2
src/evaluation/mod.rs
Normal file
@@ -0,0 +1,2 @@
|
||||
pub mod evaluation;
|
||||
pub mod psqt;
|
||||
@@ -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]
|
||||
1
src/interface/mod.rs
Normal file
1
src/interface/mod.rs
Normal file
@@ -0,0 +1 @@
|
||||
pub mod uci;
|
||||
@@ -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<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))
|
||||
}
|
||||
@@ -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`
|
||||
```
|
||||
*/
|
||||
26
src/main.rs
26
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.."),
|
||||
};
|
||||
|
||||
@@ -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> {
|
||||
@@ -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<F1, F2>(
|
||||
fn find_magic_numbers<F1, F2>(
|
||||
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]
|
||||
4
src/movegen/mod.rs
Normal file
4
src/movegen/mod.rs
Normal file
@@ -0,0 +1,4 @@
|
||||
pub mod attack;
|
||||
pub mod magic;
|
||||
pub mod r#move;
|
||||
pub mod movegen;
|
||||
@@ -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",
|
||||
@@ -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";
|
||||
|
||||
3
src/search/mod.rs
Normal file
3
src/search/mod.rs
Normal file
@@ -0,0 +1,3 @@
|
||||
pub mod move_ordering;
|
||||
pub mod perft;
|
||||
pub mod search;
|
||||
@@ -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<u8, &str> = 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;
|
||||
|
||||
@@ -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(())
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user