From 84aea649bf8992a3b9aaa1168d55a74a1efb6d17 Mon Sep 17 00:00:00 2001 From: Patrick Heck <49785565+FitzOReilly@users.noreply.github.com> Date: Mon, 9 Mar 2026 18:29:13 +0100 Subject: [PATCH 1/4] Update dependencies --- engine/Cargo.toml | 2 +- eval/Cargo.toml | 2 +- fatalii/Cargo.toml | 2 +- movegen/Cargo.toml | 10 +++++----- search/Cargo.toml | 2 +- tuner/Cargo.toml | 12 ++++++------ uci/Cargo.toml | 2 +- 7 files changed, 16 insertions(+), 16 deletions(-) diff --git a/engine/Cargo.toml b/engine/Cargo.toml index 0ad410b3..c127d4aa 100644 --- a/engine/Cargo.toml +++ b/engine/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] crossbeam-channel = "0.5" -thiserror = "2.0.11" +thiserror = "2.0.18" movegen = { path = "../movegen" } search = { path = "../search" } diff --git a/eval/Cargo.toml b/eval/Cargo.toml index 73532440..f1ede637 100644 --- a/eval/Cargo.toml +++ b/eval/Cargo.toml @@ -11,4 +11,4 @@ movegen = { path = "../movegen" } trace = [] [dev-dependencies] -rand = "0.9.2" +rand = "0.10.0" diff --git a/fatalii/Cargo.toml b/fatalii/Cargo.toml index 4a3c289b..c7dc8119 100644 --- a/fatalii/Cargo.toml +++ b/fatalii/Cargo.toml @@ -11,4 +11,4 @@ uci = { path = "../uci" } [dev-dependencies] assert_matches = "1.5.0" -rexpect = "0.6.0" +rexpect = "0.6.3" diff --git a/movegen/Cargo.toml b/movegen/Cargo.toml index 1adaec5e..c27c08be 100644 --- a/movegen/Cargo.toml +++ b/movegen/Cargo.toml @@ -5,13 +5,13 @@ authors = ["Patrick Heck <49785565+FitzOReilly@users.noreply.github.com>"] edition = "2021" [dependencies] -bitflags = "2.8.0" -smallvec = "1.13.2" -thiserror = "2.0.11" +bitflags = "2.11.0" +smallvec = "1.15.1" +thiserror = "2.0.18" [dev-dependencies] -criterion = "0.5.1" -rand = "0.9" +criterion = "0.8.2" +rand = "0.10" [[bench]] name = "bench_movegen" diff --git a/search/Cargo.toml b/search/Cargo.toml index d42a6cdf..43ce1864 100644 --- a/search/Cargo.toml +++ b/search/Cargo.toml @@ -10,7 +10,7 @@ eval = { path = "../eval" } movegen = { path = "../movegen" } [dev-dependencies] -criterion = "0.5.1" +criterion = "0.8.2" [[bench]] name = "bench_search" diff --git a/tuner/Cargo.toml b/tuner/Cargo.toml index 31a220de..0811f21b 100644 --- a/tuner/Cargo.toml +++ b/tuner/Cargo.toml @@ -6,11 +6,11 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -clap = { version = "4.5.28", features = ["derive"] } -nalgebra = { version = "0.33.2", features = ["serde-serialize"] } -nalgebra-sparse = "0.10.0" -rand = "0.9.0" -serde = "1.0.217" -serde_json = "1.0.138" +clap = { version = "4.5.60", features = ["derive"] } +nalgebra = { version = "0.34.1", features = ["serde-serialize"] } +nalgebra-sparse = "0.11.0" +rand = "0.10.0" +serde = "1.0.228" +serde_json = "1.0.149" eval = { path = "../eval", features = ["trace"] } movegen = { path = "../movegen" } diff --git a/uci/Cargo.toml b/uci/Cargo.toml index c3d3ab7a..b79a0460 100644 --- a/uci/Cargo.toml +++ b/uci/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] regex = "1" -thiserror = "2.0.11" +thiserror = "2.0.18" engine = { path = "../engine" } eval = { path = "../eval" } movegen = { path = "../movegen" } From 17e6fd64c2358ef3ae2205294655418151e63341 Mon Sep 17 00:00:00 2001 From: Patrick Heck <49785565+FitzOReilly@users.noreply.github.com> Date: Mon, 9 Mar 2026 18:37:37 +0100 Subject: [PATCH 2/4] Update readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d063032c..d5c15eaa 100644 --- a/README.md +++ b/README.md @@ -53,7 +53,7 @@ Fatalii supports both standard chess and Chess960 (a.k.a. Fischer Random Chess). - Mobility - Bishop pair - Tempo - - King tropism + - Piece positions relative to both kings - Tapered evaluation for all parameters - Tuned with training positions from the [Zurichess dataset quiet-labeled.v7](https://bitbucket.org/zurichess/tuner/downloads/quiet-labeled.v7.epd.gz) From 404ec7a4e9811660c6fec7a0dc80b3e7b4bad930 Mon Sep 17 00:00:00 2001 From: Patrick Heck <49785565+FitzOReilly@users.noreply.github.com> Date: Mon, 9 Mar 2026 18:44:02 +0100 Subject: [PATCH 3/4] Update rust edition from 2021 to 2024 --- Cargo.toml | 2 +- engine/Cargo.toml | 2 +- engine/src/best_move_handler.rs | 63 +++--- engine/src/engine.rs | 4 +- engine/src/lib.rs | 2 +- engine/tests/engine.rs | 30 +-- eval/Cargo.toml | 2 +- eval/src/hand_crafted_eval.rs | 8 +- eval/src/hand_crafted_eval_coeffs.rs | 2 +- eval/src/lib.rs | 2 +- eval/src/material_mobility.rs | 2 +- eval/src/params.rs | 2 +- fatalii/Cargo.toml | 2 +- fatalii/src/lib.rs | 4 +- movegen/Cargo.toml | 2 +- movegen/benches/bench_movegen.rs | 2 +- movegen/src/fen.rs | 8 +- movegen/src/move_generator.rs | 4 +- .../move_generator/king_in_check_generator.rs | 2 +- .../move_generator/move_generator_template.rs | 6 +- movegen/src/performance_tester.rs | 2 +- movegen/src/position.rs | 4 +- movegen/src/position_history.rs | 2 +- movegen/src/transposition_table.rs | 2 +- movegen/src/zobrist.rs | 2 +- search/Cargo.toml | 2 +- search/benches/bench_search.rs | 6 +- search/src/alpha_beta.rs | 95 +++++----- search/src/alpha_beta_entry.rs | 2 +- search/src/aspiration_window.rs | 2 +- search/src/counter_table.rs | 2 +- search/src/history_table.rs | 2 +- search/src/move_selector.rs | 27 ++- search/src/search.rs | 4 +- search/src/search_data.rs | 20 +- search/src/searcher.rs | 70 +++---- search/src/static_exchange_eval.rs | 4 +- search/tests/search.rs | 8 +- tuner/Cargo.toml | 2 +- tuner/src/eval_params.rs | 4 +- tuner/src/file_reader.rs | 6 +- tuner/src/main.rs | 2 +- uci/Cargo.toml | 2 +- uci/src/uci_in/debug.rs | 2 +- uci/src/uci_in/go.rs | 6 +- uci/src/uci_in/is_ready.rs | 2 +- uci/src/uci_in/position.rs | 12 +- uci/src/uci_in/quit.rs | 2 +- uci/src/uci_in/set_option.rs | 4 +- uci/src/uci_in/stop.rs | 2 +- uci/src/uci_in/uci.rs | 2 +- uci/src/uci_in/ucinewgame.rs | 2 +- uci/src/uci_move.rs | 2 +- uci/src/uci_option.rs | 2 +- uci/src/uci_out.rs | 2 +- uci/tests/uci.rs | 179 ++++++++++-------- 56 files changed, 341 insertions(+), 301 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index ec7be4b0..aac771b1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,4 +12,4 @@ members = [ "tuner", "uci", ] -resolver = "2" +resolver = "3" diff --git a/engine/Cargo.toml b/engine/Cargo.toml index c127d4aa..bf012423 100644 --- a/engine/Cargo.toml +++ b/engine/Cargo.toml @@ -2,7 +2,7 @@ name = "engine" version = "0.1.0" authors = ["Patrick Heck <49785565+FitzOReilly@users.noreply.github.com>"] -edition = "2021" +edition = "2024" [dependencies] crossbeam-channel = "0.5" diff --git a/engine/src/best_move_handler.rs b/engine/src/best_move_handler.rs index 578d5ee0..9e6fa423 100644 --- a/engine/src/best_move_handler.rs +++ b/engine/src/best_move_handler.rs @@ -2,8 +2,8 @@ use crate::engine_out::EngineOut; use crossbeam_channel::Receiver; use movegen::r#move::Move; use movegen::side::Side; -use search::search::SearchResult; use search::SearchOptions; +use search::search::SearchResult; use std::sync::{Arc, Mutex}; use std::thread; @@ -20,40 +20,45 @@ impl BestMoveHandler { let mut side_to_move = None; let mut best_move = None; - let thread = thread::spawn(move || loop { - let message = receiver.recv().expect("Error receiving BestMoveCommand"); - match message { - BestMoveCommand::SetOptions(new_options) => match options.lock() { - Ok(mut opt) => *opt = *new_options, - Err(e) => panic!("{}", e), - }, - BestMoveCommand::SetSideToMove(s) => side_to_move = s, - BestMoveCommand::DepthFinished(res) => engine_out - .info_depth_finished(Self::search_result_to_relative(Some(res), side_to_move)) - .expect("Error writing search info"), - BestMoveCommand::Stop(StopReason::Command) => { - match options.lock() { - Ok(mut opt) => opt.infinite = false, + let thread = thread::spawn(move || { + loop { + let message = receiver.recv().expect("Error receiving BestMoveCommand"); + match message { + BestMoveCommand::SetOptions(new_options) => match options.lock() { + Ok(mut opt) => *opt = *new_options, Err(e) => panic!("{}", e), + }, + BestMoveCommand::SetSideToMove(s) => side_to_move = s, + BestMoveCommand::DepthFinished(res) => engine_out + .info_depth_finished(Self::search_result_to_relative( + Some(res), + side_to_move, + )) + .expect("Error writing search info"), + BestMoveCommand::Stop(StopReason::Command) => { + match options.lock() { + Ok(mut opt) => opt.infinite = false, + Err(e) => panic!("{}", e), + } + engine_out + .best_move(best_move.take()) + .expect("Error writing best move"); } - engine_out - .best_move(best_move.take()) - .expect("Error writing best move"); - } - BestMoveCommand::Stop(StopReason::Finished(new_best_move)) => { - best_move = Some(new_best_move); - match options.lock() { - Ok(opt) => { - if !opt.infinite { - engine_out - .best_move(best_move.take()) - .expect("Error writing best move"); + BestMoveCommand::Stop(StopReason::Finished(new_best_move)) => { + best_move = Some(new_best_move); + match options.lock() { + Ok(opt) => { + if !opt.infinite { + engine_out + .best_move(best_move.take()) + .expect("Error writing best move"); + } } + Err(e) => panic!("{}", e), } - Err(e) => panic!("{}", e), } + BestMoveCommand::Terminate => break, } - BestMoveCommand::Terminate => break, } }); diff --git a/engine/src/engine.rs b/engine/src/engine.rs index ac783a9d..dc53c5b9 100644 --- a/engine/src/engine.rs +++ b/engine/src/engine.rs @@ -1,14 +1,14 @@ use crate::best_move_handler::{BestMoveCommand, BestMoveHandler, StopReason}; use crate::engine_out::EngineOut; use crate::{EngineOptions, Variant}; -use crossbeam_channel::{unbounded, Sender}; +use crossbeam_channel::{Sender, unbounded}; use movegen::position::Position; use movegen::position_history::PositionHistory; use movegen::side::Side; +use search::SearchOptions; use search::search::{Search, SearchInfo}; use search::search_params::SearchParamsOptions; use search::searcher::Searcher; -use search::SearchOptions; use std::sync::{Arc, Mutex}; use std::time::Duration; diff --git a/engine/src/lib.rs b/engine/src/lib.rs index 9115911b..9fd64f78 100644 --- a/engine/src/lib.rs +++ b/engine/src/lib.rs @@ -1,6 +1,6 @@ pub use crate::engine::{Engine, EngineError}; pub use crate::engine_options::{ - EngineOptions, Variant, DEFAULT_HASH_BYTES, DEFAULT_HASH_MB, DEFAULT_MOVE_OVERHEAD_MILLIS, + DEFAULT_HASH_BYTES, DEFAULT_HASH_MB, DEFAULT_MOVE_OVERHEAD_MILLIS, EngineOptions, Variant, }; pub use crate::engine_out::EngineOut; diff --git a/engine/tests/engine.rs b/engine/tests/engine.rs index 865b7e55..a6e8bd5a 100644 --- a/engine/tests/engine.rs +++ b/engine/tests/engine.rs @@ -7,8 +7,8 @@ use mock_engine_out::MockEngineOut; use more_asserts::assert_le; use movegen::position::Position; use movegen::position_history::PositionHistory; -use search::alpha_beta::AlphaBeta; use search::SearchOptions; +use search::alpha_beta::AlphaBeta; use std::sync::{Arc, Mutex}; use std::thread; use std::time::Duration; @@ -38,12 +38,14 @@ fn search_timeout() { let tol = 80; let start = Instant::now(); - assert!(engine - .search(SearchOptions { - movetime: Some(movetime), - ..Default::default() - }) - .is_ok()); + assert!( + engine + .search(SearchOptions { + movetime: Some(movetime), + ..Default::default() + }) + .is_ok() + ); assert!(receiver.recv_timeout(waittime).is_ok()); let stop = Instant::now(); assert_le!( @@ -75,12 +77,14 @@ fn search_timeout_aborted() { let tol = 80; let start = Instant::now(); - assert!(engine - .search(SearchOptions { - movetime: Some(movetime), - ..Default::default() - }) - .is_ok()); + assert!( + engine + .search(SearchOptions { + movetime: Some(movetime), + ..Default::default() + }) + .is_ok() + ); thread::sleep(sleeptime); engine.stop(); assert!(receiver.recv_timeout(waittime).is_ok()); diff --git a/eval/Cargo.toml b/eval/Cargo.toml index f1ede637..b5d0e32f 100644 --- a/eval/Cargo.toml +++ b/eval/Cargo.toml @@ -2,7 +2,7 @@ name = "eval" version = "0.1.0" authors = ["Patrick Heck <49785565+FitzOReilly@users.noreply.github.com>"] -edition = "2021" +edition = "2024" [dependencies] movegen = { path = "../movegen" } diff --git a/eval/src/hand_crafted_eval.rs b/eval/src/hand_crafted_eval.rs index 2cecb890..3edde110 100644 --- a/eval/src/hand_crafted_eval.rs +++ b/eval/src/hand_crafted_eval.rs @@ -5,7 +5,7 @@ use crate::hand_crafted_eval_coeffs::{Coeff, HandCraftedEvalCoeffs}; use crate::params; use crate::piece_table_refs::PIECE_TABLE_REFS; use crate::score_pair::ScorePair; -use crate::{Eval, Score, EQ_POSITION}; +use crate::{EQ_POSITION, Eval, Score}; use movegen::bishop::Bishop; use movegen::bitboard::Bitboard; use movegen::file::File; @@ -557,12 +557,12 @@ impl HandCraftedEval { #[cfg(test)] mod tests { use movegen::{ - fen::Fen, move_generator::MoveGenerator, position::Position, - position_history::PositionHistory, r#move::MoveList, + fen::Fen, r#move::MoveList, move_generator::MoveGenerator, position::Position, + position_history::PositionHistory, }; use rand::seq::{IndexedMutRandom, SliceRandom}; - use crate::{Eval, EQ_POSITION}; + use crate::{EQ_POSITION, Eval}; use super::HandCraftedEval; diff --git a/eval/src/hand_crafted_eval_coeffs.rs b/eval/src/hand_crafted_eval_coeffs.rs index 5ea30583..cf1c49ec 100644 --- a/eval/src/hand_crafted_eval_coeffs.rs +++ b/eval/src/hand_crafted_eval_coeffs.rs @@ -11,7 +11,7 @@ use movegen::{ square::Square, }; -use crate::{params, Score}; +use crate::{Score, params}; #[derive(Debug, Clone, Copy, Default, PartialEq)] pub struct Coeff(pub i8); diff --git a/eval/src/lib.rs b/eval/src/lib.rs index b9d7cab5..da3ea1db 100644 --- a/eval/src/lib.rs +++ b/eval/src/lib.rs @@ -3,7 +3,7 @@ pub use crate::game_phase::GamePhase; pub use crate::hand_crafted_eval::HandCraftedEval; #[cfg(feature = "trace")] pub use crate::hand_crafted_eval_coeffs::HandCraftedEvalCoeffs; -pub use crate::score::{Score, ScoreVariant, BLACK_WIN, EQ_POSITION, NEG_INF, POS_INF, WHITE_WIN}; +pub use crate::score::{BLACK_WIN, EQ_POSITION, NEG_INF, POS_INF, Score, ScoreVariant, WHITE_WIN}; pub mod eval; pub mod hand_crafted_eval; diff --git a/eval/src/material_mobility.rs b/eval/src/material_mobility.rs index d7c30ce0..641ba893 100644 --- a/eval/src/material_mobility.rs +++ b/eval/src/material_mobility.rs @@ -134,8 +134,8 @@ impl MaterialMobility { #[cfg(test)] mod tests { use super::*; - use movegen::position_history::PositionHistory; use movegen::r#move::{Move, MoveType}; + use movegen::position_history::PositionHistory; use movegen::square::Square; #[test] diff --git a/eval/src/params.rs b/eval/src/params.rs index ff22cc2c..767dace9 100644 --- a/eval/src/params.rs +++ b/eval/src/params.rs @@ -1,6 +1,6 @@ use movegen::{file::File, rank::Rank, square::Square}; -use crate::{score_pair::ScorePair, Score}; +use crate::{Score, score_pair::ScorePair}; // Piece square tables: // We use symmetrical PSTs, so we only define values for half the board. Squares diff --git a/fatalii/Cargo.toml b/fatalii/Cargo.toml index c7dc8119..dcf4169c 100644 --- a/fatalii/Cargo.toml +++ b/fatalii/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "fatalii" version = "0.10.0-alpha" -edition = "2021" +edition = "2024" [dependencies] engine = { path = "../engine" } diff --git a/fatalii/src/lib.rs b/fatalii/src/lib.rs index 96c82f52..2aad457a 100644 --- a/fatalii/src/lib.rs +++ b/fatalii/src/lib.rs @@ -1,13 +1,13 @@ -use engine::{Engine, EngineOptions, DEFAULT_HASH_BYTES}; +use engine::{DEFAULT_HASH_BYTES, Engine, EngineOptions}; use eval::HandCraftedEval; use search::alpha_beta::AlphaBeta; use std::error::Error; use std::io; use std::sync::{Arc, Mutex}; +use uci::UciOut; use uci::uci_in::{ debug, go, is_ready, position, quit, set_option, stop, uci as cmd_uci, ucinewgame, }; -use uci::UciOut; use uci::{Parser, ParserMessage}; pub fn run() -> Result<(), Box> { diff --git a/movegen/Cargo.toml b/movegen/Cargo.toml index c27c08be..21c53667 100644 --- a/movegen/Cargo.toml +++ b/movegen/Cargo.toml @@ -2,7 +2,7 @@ name = "movegen" version = "0.1.0" authors = ["Patrick Heck <49785565+FitzOReilly@users.noreply.github.com>"] -edition = "2021" +edition = "2024" [dependencies] bitflags = "2.11.0" diff --git a/movegen/benches/bench_movegen.rs b/movegen/benches/bench_movegen.rs index 7d4ac423..2487de41 100644 --- a/movegen/benches/bench_movegen.rs +++ b/movegen/benches/bench_movegen.rs @@ -1,4 +1,4 @@ -use criterion::{criterion_group, criterion_main, BatchSize, BenchmarkId, Criterion, Throughput}; +use criterion::{BatchSize, BenchmarkId, Criterion, Throughput, criterion_group, criterion_main}; use movegen::fen::Fen; use movegen::performance_tester::PerformanceTester; use movegen::position::Position; diff --git a/movegen/src/fen.rs b/movegen/src/fen.rs index 7f38605f..3093989e 100644 --- a/movegen/src/fen.rs +++ b/movegen/src/fen.rs @@ -323,10 +323,10 @@ impl Fen { for cur in fen.bytes() { let cur_castling_right = match cur { b'K' | b'Q' | b'k' | b'q' if cur == prev => { - return Err(FenError::DuplicateCastlingRights) + return Err(FenError::DuplicateCastlingRights); } b'K' | b'Q' | b'k' | b'q' if cur < prev => { - return Err(FenError::WrongCastlingRightOrder) + return Err(FenError::WrongCastlingRightOrder); } b'K' => CastlingRights::WHITE_KINGSIDE, b'Q' => CastlingRights::WHITE_QUEENSIDE, @@ -386,7 +386,7 @@ impl Fen { match king_file.idx().cmp(&castling_file.idx()) { Ordering::Less => match kingside { Some(f) if f != castling_file => { - return Err(FenError::InvalidCastlingRights) + return Err(FenError::InvalidCastlingRights); } _ => { kingside = Some(castling_file); @@ -400,7 +400,7 @@ impl Fen { Ordering::Equal => return Err(FenError::InvalidCastlingRights), Ordering::Greater => match queenside { Some(f) if f != castling_file => { - return Err(FenError::InvalidCastlingRights) + return Err(FenError::InvalidCastlingRights); } _ => { queenside = Some(castling_file); diff --git a/movegen/src/move_generator.rs b/movegen/src/move_generator.rs index 107aab4c..5c21af8f 100644 --- a/movegen/src/move_generator.rs +++ b/movegen/src/move_generator.rs @@ -10,9 +10,9 @@ use crate::move_generator::move_generator_template::MoveGeneratorTemplate; use crate::attacks_to::AttacksTo; use crate::bitboard::Bitboard; +use crate::r#move::{Move, MoveList}; use crate::piece; use crate::position::Position; -use crate::r#move::{Move, MoveList}; use crate::square::Square; pub struct MoveGenerator; @@ -128,9 +128,9 @@ mod tests { use super::*; use crate::fen::Fen; + use crate::r#move::{Move, MoveType}; use crate::position::Position; use crate::position_history::PositionHistory; - use crate::r#move::{Move, MoveType}; use crate::square::Square; use rand::seq::IndexedMutRandom; diff --git a/movegen/src/move_generator/king_in_check_generator.rs b/movegen/src/move_generator/king_in_check_generator.rs index 31c13a7c..ffe81885 100644 --- a/movegen/src/move_generator/king_in_check_generator.rs +++ b/movegen/src/move_generator/king_in_check_generator.rs @@ -2,8 +2,8 @@ use crate::move_generator::move_generator_template::MoveGeneratorTemplate; use crate::attacks_to::AttacksTo; use crate::bitboard::Bitboard; -use crate::pawn::Pawn; use crate::r#move::MoveList; +use crate::pawn::Pawn; use crate::square::Square; // In check, the only legal moves are: diff --git a/movegen/src/move_generator/move_generator_template.rs b/movegen/src/move_generator/move_generator_template.rs index fe7fffd6..5123796b 100644 --- a/movegen/src/move_generator/move_generator_template.rs +++ b/movegen/src/move_generator/move_generator_template.rs @@ -3,12 +3,12 @@ use crate::bishop::Bishop; use crate::bitboard::Bitboard; use crate::king::King; use crate::knight::Knight; +use crate::r#move::{Move, MoveList, MoveType}; use crate::pawn::Pawn; use crate::piece; use crate::piece_targets::PieceTargets; use crate::position::CastlingRights; use crate::queen::Queen; -use crate::r#move::{Move, MoveList, MoveType}; use crate::rank::Rank; use crate::rook::Rook; use crate::side::Side; @@ -546,7 +546,7 @@ pub trait MoveGeneratorTemplate { piece::Type::Queen, ), ) - .into() + .into(); } } } @@ -566,7 +566,7 @@ pub trait MoveGeneratorTemplate { piece::Type::Queen, ), ) - .into() + .into(); } } } diff --git a/movegen/src/performance_tester.rs b/movegen/src/performance_tester.rs index 7223e805..6840e59a 100644 --- a/movegen/src/performance_tester.rs +++ b/movegen/src/performance_tester.rs @@ -1,8 +1,8 @@ use std::cmp; +use crate::r#move::MoveList; use crate::move_generator::MoveGenerator; use crate::position_history::PositionHistory; -use crate::r#move::MoveList; use crate::transposition_table::{TranspositionTable, TtEntry}; use crate::zobrist::Zobrist; diff --git a/movegen/src/position.rs b/movegen/src/position.rs index 13329d19..082a7e93 100644 --- a/movegen/src/position.rs +++ b/movegen/src/position.rs @@ -4,12 +4,12 @@ use crate::castling_squares::CastlingSquares; use crate::file::File; use crate::king::King; use crate::knight::Knight; +use crate::r#move::Move; +use crate::r#move::MoveType; use crate::pawn::Pawn; use crate::piece; use crate::piece::Piece; use crate::queen::Queen; -use crate::r#move::Move; -use crate::r#move::MoveType; use crate::rank::Rank; use crate::rook::Rook; use crate::side::Side; diff --git a/movegen/src/position_history.rs b/movegen/src/position_history.rs index c9753efc..5fccc214 100644 --- a/movegen/src/position_history.rs +++ b/movegen/src/position_history.rs @@ -1,10 +1,10 @@ use crate::bitboard::Bitboard; use crate::fen::Fen; +use crate::r#move::{Move, MoveType}; use crate::move_generator::MoveGenerator; use crate::pawn::Pawn; use crate::piece::{self, Piece}; use crate::position::{CastlingRights, Position}; -use crate::r#move::{Move, MoveType}; use crate::rank::Rank; use crate::repetition_tracker::RepetitionTracker; use crate::side::Side; diff --git a/movegen/src/transposition_table.rs b/movegen/src/transposition_table.rs index 62bdd4d2..270f6a08 100644 --- a/movegen/src/transposition_table.rs +++ b/movegen/src/transposition_table.rs @@ -176,9 +176,9 @@ where #[cfg(test)] mod tests { use super::*; + use crate::r#move::{Move, MoveType}; use crate::position::Position; use crate::position_history::PositionHistory; - use crate::r#move::{Move, MoveType}; use crate::square::Square; use crate::zobrist::Zobrist; diff --git a/movegen/src/zobrist.rs b/movegen/src/zobrist.rs index 7a0d9c57..7389e283 100644 --- a/movegen/src/zobrist.rs +++ b/movegen/src/zobrist.rs @@ -934,9 +934,9 @@ impl Zobrist { #[cfg(test)] mod tests { use super::*; + use crate::r#move::{Move, MoveList, MoveType}; use crate::move_generator::MoveGenerator; use crate::position_history::PositionHistory; - use crate::r#move::{Move, MoveList, MoveType}; #[test] fn hash_values_differ() { diff --git a/search/Cargo.toml b/search/Cargo.toml index 43ce1864..ea6282c1 100644 --- a/search/Cargo.toml +++ b/search/Cargo.toml @@ -2,7 +2,7 @@ name = "search" version = "0.1.0" authors = ["Patrick Heck <49785565+FitzOReilly@users.noreply.github.com>"] -edition = "2021" +edition = "2024" [dependencies] crossbeam-channel = "0.5" diff --git a/search/benches/bench_search.rs b/search/benches/bench_search.rs index ca8e1322..0c1110d8 100644 --- a/search/benches/bench_search.rs +++ b/search/benches/bench_search.rs @@ -1,14 +1,14 @@ -use criterion::{criterion_group, criterion_main, BatchSize, BenchmarkId, Criterion, Throughput}; -use crossbeam_channel::{unbounded, Receiver}; +use criterion::{BatchSize, BenchmarkId, Criterion, Throughput, criterion_group, criterion_main}; +use crossbeam_channel::{Receiver, unbounded}; use eval::Eval; use eval::HandCraftedEval; use movegen::fen::Fen; use movegen::position::Position; use movegen::position_history::PositionHistory; +use search::SearchOptions; use search::alpha_beta::AlphaBeta; use search::search::{Search, SearchInfo, SearchResult}; use search::searcher::Searcher; -use search::SearchOptions; use std::time::Duration; const TIMEOUT_PER_BENCH: Duration = Duration::from_millis(10000); diff --git a/search/src/alpha_beta.rs b/search/src/alpha_beta.rs index ae9e2c33..3b07f456 100644 --- a/search/src/alpha_beta.rs +++ b/search/src/alpha_beta.rs @@ -5,22 +5,22 @@ use crate::history_table::HistoryTable; use crate::lmr_table::LmrTable; use crate::move_selector::{MoveSelector, Stage}; use crate::search::{ - Search, SearchCommand, SearchInfo, SearchResult, MAX_SEARCH_DEPTH, - PLIES_WITHOUT_PAWN_MOVE_OR_CAPTURE_TO_DRAW, + MAX_SEARCH_DEPTH, PLIES_WITHOUT_PAWN_MOVE_OR_CAPTURE_TO_DRAW, Search, SearchCommand, + SearchInfo, SearchResult, }; use crate::search_data::SearchData; use crate::search_params::{ - SearchParams, SearchParamsOptions, DELTA_PRUNING_MARGIN_ALL_MOVES, DELTA_PRUNING_MARGIN_MOVE, - MIN_LATE_MOVE_REDUCTION_DEPTH, MIN_NULL_MOVE_PRUNE_DEPTH, MIN_PVS_DEPTH, + DELTA_PRUNING_MARGIN_ALL_MOVES, DELTA_PRUNING_MARGIN_MOVE, MIN_LATE_MOVE_REDUCTION_DEPTH, + MIN_NULL_MOVE_PRUNE_DEPTH, MIN_PVS_DEPTH, SearchParams, SearchParamsOptions, }; use crate::time_manager::TimeManager; -use crate::{static_exchange_eval as see, SearchOptions}; +use crate::{SearchOptions, static_exchange_eval as see}; use crossbeam_channel::{Receiver, Sender}; use eval::score::is_valid; -use eval::{Eval, Score, BLACK_WIN, EQ_POSITION, NEG_INF, POS_INF, WHITE_WIN}; +use eval::{BLACK_WIN, EQ_POSITION, Eval, NEG_INF, POS_INF, Score, WHITE_WIN}; +use movegen::r#move::{Move, MoveList}; use movegen::move_generator::MoveGenerator; use movegen::position_history::PositionHistory; -use movegen::r#move::{Move, MoveList}; use movegen::side::Side; use movegen::transposition_table::{TranspositionTable, TtEntry}; use movegen::zobrist::Zobrist; @@ -156,10 +156,10 @@ impl Search for AlphaBeta { if search_data.should_stop_search_immediately() { break; } - if let Some(limit) = soft_time_limit { - if search_data.start_time().elapsed() > limit { - break; - } + if let Some(limit) = soft_time_limit + && search_data.start_time().elapsed() > limit + { + break; } } @@ -206,14 +206,13 @@ impl Search for AlphaBeta { let score = abs_alpha_beta_res.score(); if eval::score::is_mating(score) && eval::score::mate_dist(score).unsigned_abs() as usize <= d + && let Some(ref mut limit) = soft_time_limit { - if let Some(ref mut limit) = soft_time_limit { - // A mate has been found. Don't abort the search immediately, because we - // might have pruned away a shorter mate. Instead lower the search time. - // This also makes sure that we continue searching if there is no time - // limit given. - *limit = *limit * 3 / 4; - } + // A mate has been found. Don't abort the search immediately, because we + // might have pruned away a shorter mate. Instead lower the search time. + // This also makes sure that we continue searching if there is no time + // limit given. + *limit = *limit * 3 / 4; } break; } @@ -261,10 +260,10 @@ impl AlphaBeta { } let is_pv_node = alpha + 1 != beta; - if search_data.ply() > 0 { - if let Some(entry) = Self::is_draw(search_data, is_pv_node) { - return Some(entry); - } + if search_data.ply() > 0 + && let Some(entry) = Self::is_draw(search_data, is_pv_node) + { + return Some(entry); } if let Some(entry) = self.usable_table_entry(search_data, alpha, beta) { @@ -611,11 +610,11 @@ impl AlphaBeta { return entry; } - if let Some(entry) = self.lookup_table_entry(search_data) { - if let Some(bounded) = entry.bound_soft(alpha, beta) { - search_data.increment_cache_hits(); - return bounded; - } + if let Some(entry) = self.lookup_table_entry(search_data) + && let Some(bounded) = entry.bound_soft(alpha, beta) + { + search_data.increment_cache_hits(); + return bounded; } if search_data.is_in_check() { @@ -825,28 +824,28 @@ impl AlphaBeta { alpha: Score, beta: Score, ) -> Option { - if let Some(entry) = self.lookup_table_entry(search_data) { - if let Some(bounded) = entry.bound_soft(alpha, beta) { - search_data.increment_cache_hits(); - match (bounded.score_type(), search_data.remaining_depth()) { - (ScoreType::Exact, 0) => return Some(bounded), - (ScoreType::Exact, 1) => { - search_data.update_pv_move_and_truncate(bounded.best_move()); - // Root move ordering: move the new best move to the front - if search_data.ply() == 0 { - search_data.move_to_front(bounded.best_move()); - } - return Some(bounded); - } - (ScoreType::Exact, _) => { - // For greater depths, we need to keep searching in order to obtain the PV - } - _ => { - // We're not in a PV node, but it might be in the previous search depth's PV. - // So we make sure to remove it. - search_data.end_prev_pv(); - return Some(bounded); + if let Some(entry) = self.lookup_table_entry(search_data) + && let Some(bounded) = entry.bound_soft(alpha, beta) + { + search_data.increment_cache_hits(); + match (bounded.score_type(), search_data.remaining_depth()) { + (ScoreType::Exact, 0) => return Some(bounded), + (ScoreType::Exact, 1) => { + search_data.update_pv_move_and_truncate(bounded.best_move()); + // Root move ordering: move the new best move to the front + if search_data.ply() == 0 { + search_data.move_to_front(bounded.best_move()); } + return Some(bounded); + } + (ScoreType::Exact, _) => { + // For greater depths, we need to keep searching in order to obtain the PV + } + _ => { + // We're not in a PV node, but it might be in the previous search depth's PV. + // So we make sure to remove it. + search_data.end_prev_pv(); + return Some(bounded); } } } diff --git a/search/src/alpha_beta_entry.rs b/search/src/alpha_beta_entry.rs index d7cc63c2..d1c96aa0 100644 --- a/search/src/alpha_beta_entry.rs +++ b/search/src/alpha_beta_entry.rs @@ -1,6 +1,6 @@ use crate::search::MAX_SEARCH_DEPTH; -use eval::score::{dec_mate_dist_by, inc_mate_dist_by}; use eval::Score; +use eval::score::{dec_mate_dist_by, inc_mate_dist_by}; use movegen::r#move::Move; use movegen::transposition_table::TtEntry; use movegen::zobrist::Zobrist; diff --git a/search/src/aspiration_window.rs b/search/src/aspiration_window.rs index 474d15ed..528db78f 100644 --- a/search/src/aspiration_window.rs +++ b/search/src/aspiration_window.rs @@ -1,5 +1,5 @@ use crate::search_params::SearchParams; -use eval::{Score, NEG_INF, POS_INF}; +use eval::{NEG_INF, POS_INF, Score}; #[derive(Debug)] pub struct AspirationWindow { diff --git a/search/src/counter_table.rs b/search/src/counter_table.rs index 1c566aad..92acd8d8 100644 --- a/search/src/counter_table.rs +++ b/search/src/counter_table.rs @@ -1,4 +1,4 @@ -use movegen::{piece::Piece, r#move::Move, square::Square}; +use movegen::{r#move::Move, piece::Piece, square::Square}; #[derive(Debug, Clone)] pub struct CounterTable { diff --git a/search/src/history_table.rs b/search/src/history_table.rs index 9211e307..ca3db87a 100644 --- a/search/src/history_table.rs +++ b/search/src/history_table.rs @@ -1,7 +1,7 @@ use movegen::{ + r#move::{Move, MoveList}, piece::Piece, position::Position, - r#move::{Move, MoveList}, square::Square, }; diff --git a/search/src/move_selector.rs b/search/src/move_selector.rs index f6fd3e78..63625f60 100644 --- a/search/src/move_selector.rs +++ b/search/src/move_selector.rs @@ -4,9 +4,9 @@ use crate::history_table::HistoryTable; use crate::search_data::SearchData; use crate::static_exchange_eval::static_exchange_eval; use eval::Score; +use movegen::r#move::{Move, MoveList}; use movegen::piece; use movegen::position::Position; -use movegen::r#move::{Move, MoveList}; #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)] #[repr(u8)] @@ -217,14 +217,13 @@ impl MoveSelector { search_data: &mut SearchData, transpos_table: &mut AlphaBetaTable, ) -> Option { - if let Some(entry) = transpos_table.get(&search_data.current_pos_hash()) { - if let Some(idx) = self + if let Some(entry) = transpos_table.get(&search_data.current_pos_hash()) + && let Some(idx) = self .moves .iter() .position(|x| x.r#move == entry.best_move()) - { - return Some(self.moves.swap_remove(idx).r#move); - } + { + return Some(self.moves.swap_remove(idx).r#move); } None } @@ -358,14 +357,14 @@ impl MoveSelector { search_data: &mut SearchData, counter_table: &CounterTable, ) -> Option { - if let Some(last_move) = search_data.pos_history().last_move() { - if let Some(last_moved_piece) = search_data.pos_history().last_moved_piece() { - let counter = counter_table.counter(last_moved_piece, last_move.target()); - if counter != Move::NULL { - if let Some(idx) = self.moves.iter().position(|x| x.r#move == counter) { - return Some(self.moves.swap_remove(idx).r#move); - } - } + if let Some(last_move) = search_data.pos_history().last_move() + && let Some(last_moved_piece) = search_data.pos_history().last_moved_piece() + { + let counter = counter_table.counter(last_moved_piece, last_move.target()); + if counter != Move::NULL + && let Some(idx) = self.moves.iter().position(|x| x.r#move == counter) + { + return Some(self.moves.swap_remove(idx).r#move); } } diff --git a/search/src/search.rs b/search/src/search.rs index 5649a6c1..5abac5a5 100644 --- a/search/src/search.rs +++ b/search/src/search.rs @@ -1,9 +1,9 @@ -use crate::search_params::SearchParamsOptions; use crate::SearchOptions; +use crate::search_params::SearchParamsOptions; use crossbeam_channel::{Receiver, Sender}; use eval::Score; -use movegen::position_history::PositionHistory; use movegen::r#move::{Move, MoveList}; +use movegen::position_history::PositionHistory; use std::fmt; use std::ops::Neg; diff --git a/search/src/search_data.rs b/search/src/search_data.rs index ea523f01..0a658958 100644 --- a/search/src/search_data.rs +++ b/search/src/search_data.rs @@ -3,12 +3,12 @@ use std::time::{Duration, Instant}; use crate::move_candidates::MoveCandidates; use crate::node_counter::NodeCounter; use crate::pv_table::PvTable; -use crate::search::{SearchCommand, SearchInfo, MAX_SEARCH_DEPTH}; +use crate::search::{MAX_SEARCH_DEPTH, SearchCommand, SearchInfo}; use crossbeam_channel::{Receiver, Sender, TryRecvError}; use eval::{Eval, Score}; +use movegen::r#move::{Move, MoveList}; use movegen::position::Position; use movegen::position_history::PositionHistory; -use movegen::r#move::{Move, MoveList}; use movegen::zobrist::Zobrist; pub type Killers = [Option; NUM_KILLERS]; @@ -356,15 +356,15 @@ impl<'a> SearchData<'a> { if let Ok(SearchCommand::Stop) = self.try_recv_cmd() { return true; } - if let Some(limit) = self.hard_time_limit() { - if self.start_time().elapsed() > limit { - return true; - } + if let Some(limit) = self.hard_time_limit() + && self.start_time().elapsed() > limit + { + return true; } - if let Some(max_nodes) = self.max_nodes() { - if self.searched_nodes() >= max_nodes { - return true; - } + if let Some(max_nodes) = self.max_nodes() + && self.searched_nodes() >= max_nodes + { + return true; } } false diff --git a/search/src/searcher.rs b/search/src/searcher.rs index bfb823d2..320b9745 100644 --- a/search/src/searcher.rs +++ b/search/src/searcher.rs @@ -1,9 +1,9 @@ use crate::{ + SearchOptions, search::{Search, SearchCommand, SearchInfo}, search_params::SearchParamsOptions, - SearchOptions, }; -use crossbeam_channel::{bounded, unbounded, Receiver, Sender}; +use crossbeam_channel::{Receiver, Sender, bounded, unbounded}; use movegen::position_history::PositionHistory; use std::thread; @@ -113,33 +113,35 @@ impl Worker { mut command_receiver: Receiver, mut info_sender: Sender, ) -> Self { - let thread = thread::spawn(move || loop { - let message = command_receiver - .recv() - .expect("Error receiving SearchCommand"); - - match message { - SearchCommand::SetHashSize(bytes, _sender) => { - Self::set_hash_size(&mut search_algo, bytes); - } - SearchCommand::ClearHashTable(_sender) => { - Self::clear_hash_table(&mut search_algo); + let thread = thread::spawn(move || { + loop { + let message = command_receiver + .recv() + .expect("Error receiving SearchCommand"); + + match message { + SearchCommand::SetHashSize(bytes, _sender) => { + Self::set_hash_size(&mut search_algo, bytes); + } + SearchCommand::ClearHashTable(_sender) => { + Self::clear_hash_table(&mut search_algo); + } + SearchCommand::SetSearchParams(search_params, _sender) => { + Self::set_search_params(&mut search_algo, search_params); + } + SearchCommand::Search(inner) => { + let (pos_hist, search_options) = *inner; + Self::search( + &mut search_algo, + pos_hist, + search_options, + &mut command_receiver, + &mut info_sender, + ); + } + SearchCommand::Stop => {} + SearchCommand::Terminate => break, } - SearchCommand::SetSearchParams(search_params, _sender) => { - Self::set_search_params(&mut search_algo, search_params); - } - SearchCommand::Search(inner) => { - let (pos_hist, search_options) = *inner; - Self::search( - &mut search_algo, - pos_hist, - search_options, - &mut command_receiver, - &mut info_sender, - ); - } - SearchCommand::Stop => {} - SearchCommand::Terminate => break, } }); Self { @@ -179,11 +181,13 @@ impl SearchInfoHandler { info_receiver: Receiver, mut info_callback: Box, ) -> Self { - let thread = thread::spawn(move || loop { - match info_receiver.recv() { - Ok(SearchInfo::Terminated) => break, - Ok(res) => info_callback(res), - Err(_) => break, + let thread = thread::spawn(move || { + loop { + match info_receiver.recv() { + Ok(SearchInfo::Terminated) => break, + Ok(res) => info_callback(res), + Err(_) => break, + } } }); Self { diff --git a/search/src/static_exchange_eval.rs b/search/src/static_exchange_eval.rs index 76631bd7..bed5142b 100644 --- a/search/src/static_exchange_eval.rs +++ b/search/src/static_exchange_eval.rs @@ -1,7 +1,7 @@ use eval::Score; use movegen::{ - bishop::Bishop, bitboard::Bitboard, king::King, knight::Knight, pawn::Pawn, piece, - position::Position, r#move::Move, rook::Rook, side::Side, square::Square, + bishop::Bishop, bitboard::Bitboard, king::King, knight::Knight, r#move::Move, pawn::Pawn, + piece, position::Position, rook::Rook, side::Side, square::Square, }; pub fn static_exchange_eval(pos: &Position, m: Move, threshold: Score) -> bool { diff --git a/search/tests/search.rs b/search/tests/search.rs index 4fb6b896..59f1fa2b 100644 --- a/search/tests/search.rs +++ b/search/tests/search.rs @@ -1,18 +1,18 @@ -use crossbeam_channel::{unbounded, Receiver}; +use crossbeam_channel::{Receiver, unbounded}; use eval::HandCraftedEval; -use eval::{Eval, ScoreVariant, BLACK_WIN, EQ_POSITION, NEG_INF, WHITE_WIN}; +use eval::{BLACK_WIN, EQ_POSITION, Eval, NEG_INF, ScoreVariant, WHITE_WIN}; use movegen::fen::Fen; +use movegen::r#move::{Move, MoveList, MoveType}; use movegen::move_generator::MoveGenerator; use movegen::piece; use movegen::position::Position; use movegen::position_history::PositionHistory; -use movegen::r#move::{Move, MoveList, MoveType}; use movegen::side::Side; use movegen::square::Square; +use search::SearchOptions; use search::alpha_beta::AlphaBeta; use search::search::{Search, SearchInfo, SearchResult}; use search::searcher::Searcher; -use search::SearchOptions; use std::cmp; use std::time::Duration; diff --git a/tuner/Cargo.toml b/tuner/Cargo.toml index 0811f21b..4634d54f 100644 --- a/tuner/Cargo.toml +++ b/tuner/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "tuner" version = "0.1.0" -edition = "2021" +edition = "2024" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/tuner/src/eval_params.rs b/tuner/src/eval_params.rs index c93a26c3..1e559154 100644 --- a/tuner/src/eval_params.rs +++ b/tuner/src/eval_params.rs @@ -1,15 +1,15 @@ use std::fmt::Display; use eval::{ + Score, params::{ BISHOP_MOB_LEN, KNIGHT_MOB_LEN, PASSED_PAWNS_RELATIVE_TO_KING_LEN, PIECE_RELATIVE_TO_KING_LEN, QUEEN_MOB_LEN, ROOK_MOB_LEN, }, score_pair::ScorePair, - Score, }; -use crate::feature_evaluator::{Weight, WeightVector, PST_SIZE}; +use crate::feature_evaluator::{PST_SIZE, Weight, WeightVector}; #[derive(Debug)] pub struct EvalParams { diff --git a/tuner/src/file_reader.rs b/tuner/src/file_reader.rs index ac1a9b1f..d2461076 100644 --- a/tuner/src/file_reader.rs +++ b/tuner/src/file_reader.rs @@ -4,7 +4,7 @@ use std::{ path::Path, }; -use eval::{eval::HasMatingMaterial, Eval, HandCraftedEval}; +use eval::{Eval, HandCraftedEval, eval::HasMatingMaterial}; use movegen::{fen::Fen, side::Side}; use crate::{ @@ -57,7 +57,9 @@ pub fn read_training_data( } let training_count = training_data.len(); let filtered_count = parsed_count - training_count; - println!("Positions: {parsed_count} parsed, {filtered_count} filtered out, will use {training_count} for training"); + println!( + "Positions: {parsed_count} parsed, {filtered_count} filtered out, will use {training_count} for training" + ); } training_data } diff --git a/tuner/src/main.rs b/tuner/src/main.rs index 606aca29..5824bd68 100644 --- a/tuner/src/main.rs +++ b/tuner/src/main.rs @@ -7,7 +7,7 @@ use clap::{Args, Parser, Subcommand}; use eval::HandCraftedEval; use tuner::{ eval_params::EvalParams, - feature_evaluator::{default_weights, engine_weights, FeatureEvaluator, WeightVector}, + feature_evaluator::{FeatureEvaluator, WeightVector, default_weights, engine_weights}, file_reader, optimizer::{self, AdamParams, Checkpoint}, }; diff --git a/uci/Cargo.toml b/uci/Cargo.toml index b79a0460..cf60de3a 100644 --- a/uci/Cargo.toml +++ b/uci/Cargo.toml @@ -2,7 +2,7 @@ name = "uci" version = "0.1.0" authors = ["Patrick Heck <49785565+FitzOReilly@users.noreply.github.com>"] -edition = "2021" +edition = "2024" [dependencies] regex = "1" diff --git a/uci/src/uci_in/debug.rs b/uci/src/uci_in/debug.rs index 42132022..ae562348 100644 --- a/uci/src/uci_in/debug.rs +++ b/uci/src/uci_in/debug.rs @@ -1,5 +1,5 @@ -use crate::parser::{ParserMessage, UciError}; use crate::UciOut; +use crate::parser::{ParserMessage, UciError}; use engine::{Engine, EngineOut}; use std::error::Error; diff --git a/uci/src/uci_in/go.rs b/uci/src/uci_in/go.rs index 9d1cd0cd..955ee3e8 100644 --- a/uci/src/uci_in/go.rs +++ b/uci/src/uci_in/go.rs @@ -1,6 +1,6 @@ -use crate::parser::{split_first_word, ParserMessage, UciError}; -use crate::uci_move::UciMove; use crate::UciOut; +use crate::parser::{ParserMessage, UciError, split_first_word}; +use crate::uci_move::UciMove; use engine::{Engine, EngineError}; use movegen::r#move::MoveList; use search::SearchOptions; @@ -54,7 +54,7 @@ fn parse_options( return Err(Box::new(UciError::InvalidArgument(format!( "go {}", go_args.trim_end() - )))) + )))); } } } diff --git a/uci/src/uci_in/is_ready.rs b/uci/src/uci_in/is_ready.rs index b96b2856..10998c50 100644 --- a/uci/src/uci_in/is_ready.rs +++ b/uci/src/uci_in/is_ready.rs @@ -1,5 +1,5 @@ -use crate::parser::{ParserMessage, UciError}; use crate::UciOut; +use crate::parser::{ParserMessage, UciError}; use engine::Engine; use std::error::Error; diff --git a/uci/src/uci_in/position.rs b/uci/src/uci_in/position.rs index b9cb1798..da0b634f 100644 --- a/uci/src/uci_in/position.rs +++ b/uci/src/uci_in/position.rs @@ -1,6 +1,6 @@ -use crate::parser::{split_first_word, ParserMessage, UciError}; -use crate::uci_move::UciMove; use crate::UciOut; +use crate::parser::{ParserMessage, UciError, split_first_word}; +use crate::uci_move::UciMove; use engine::{Engine, Variant}; use movegen::fen::Fen; use movegen::position::Position as Pos; @@ -19,7 +19,7 @@ pub fn run_command( return Err(Box::new(UciError::InvalidArgument(format!( "position {}", args.trim_end() - )))) + )))); } }; @@ -38,7 +38,7 @@ pub fn run_command( "Invalid move `{}` in command: position {}", move_str, args.trim_end() - )))) + )))); } } } @@ -57,7 +57,7 @@ pub fn run_command( "Invalid move `{}` in command: position {}", move_str, args.trim_end() - )))) + )))); } } } @@ -69,7 +69,7 @@ pub fn run_command( return Err(Box::new(UciError::InvalidArgument(format!( "position {}", args.trim_end() - )))) + )))); } }; diff --git a/uci/src/uci_in/quit.rs b/uci/src/uci_in/quit.rs index 51c5b251..9b34a356 100644 --- a/uci/src/uci_in/quit.rs +++ b/uci/src/uci_in/quit.rs @@ -1,5 +1,5 @@ -use crate::parser::{ParserMessage, UciError}; use crate::UciOut; +use crate::parser::{ParserMessage, UciError}; use engine::Engine; use std::error::Error; diff --git a/uci/src/uci_in/set_option.rs b/uci/src/uci_in/set_option.rs index ca935678..c581f244 100644 --- a/uci/src/uci_in/set_option.rs +++ b/uci/src/uci_in/set_option.rs @@ -1,6 +1,6 @@ -use crate::parser::{split_first_word, ParserMessage, UciError}; -use crate::uci_option::{OptionType, OPTIONS}; use crate::UciOut; +use crate::parser::{ParserMessage, UciError, split_first_word}; +use crate::uci_option::{OPTIONS, OptionType}; use engine::{Engine, EngineOut}; use std::error::Error; diff --git a/uci/src/uci_in/stop.rs b/uci/src/uci_in/stop.rs index 730261ba..0c654019 100644 --- a/uci/src/uci_in/stop.rs +++ b/uci/src/uci_in/stop.rs @@ -1,5 +1,5 @@ -use crate::parser::{ParserMessage, UciError}; use crate::UciOut; +use crate::parser::{ParserMessage, UciError}; use engine::Engine; use std::error::Error; diff --git a/uci/src/uci_in/uci.rs b/uci/src/uci_in/uci.rs index cd300bf3..a000998d 100644 --- a/uci/src/uci_in/uci.rs +++ b/uci/src/uci_in/uci.rs @@ -1,5 +1,5 @@ -use crate::parser::{ParserMessage, UciError}; use crate::UciOut; +use crate::parser::{ParserMessage, UciError}; use engine::Engine; use std::error::Error; diff --git a/uci/src/uci_in/ucinewgame.rs b/uci/src/uci_in/ucinewgame.rs index 06071d20..b5a98fe5 100644 --- a/uci/src/uci_in/ucinewgame.rs +++ b/uci/src/uci_in/ucinewgame.rs @@ -1,5 +1,5 @@ -use crate::parser::{ParserMessage, UciError}; use crate::UciOut; +use crate::parser::{ParserMessage, UciError}; use engine::Engine; use std::error::Error; diff --git a/uci/src/uci_move.rs b/uci/src/uci_move.rs index 685b0503..a16d713d 100644 --- a/uci/src/uci_move.rs +++ b/uci/src/uci_move.rs @@ -1,8 +1,8 @@ use movegen::file::File; +use movegen::r#move::{Move, MoveList, MoveType}; use movegen::move_generator::MoveGenerator; use movegen::piece; use movegen::position::Position; -use movegen::r#move::{Move, MoveList, MoveType}; use regex::Regex; use std::str; diff --git a/uci/src/uci_option.rs b/uci/src/uci_option.rs index 279cb2bf..e5cf6b60 100644 --- a/uci/src/uci_option.rs +++ b/uci/src/uci_option.rs @@ -1,4 +1,4 @@ -use engine::{Engine, Variant, DEFAULT_HASH_MB, DEFAULT_MOVE_OVERHEAD_MILLIS}; +use engine::{DEFAULT_HASH_MB, DEFAULT_MOVE_OVERHEAD_MILLIS, Engine, Variant}; use eval::Score; use movegen::file::File; use search::search_params::SearchParamsOptions; diff --git a/uci/src/uci_out.rs b/uci/src/uci_out.rs index da16d81b..010304bf 100644 --- a/uci/src/uci_out.rs +++ b/uci/src/uci_out.rs @@ -1,5 +1,5 @@ use crate::uci_move::UciMove; -use crate::uci_option::{OptionType, UciOption, OPTIONS}; +use crate::uci_option::{OPTIONS, OptionType, UciOption}; use crate::uci_score::UciScore; use engine::{EngineOptions, EngineOut, Variant}; use movegen::r#move::Move; diff --git a/uci/tests/uci.rs b/uci/tests/uci.rs index 88084452..88af6ea8 100644 --- a/uci/tests/uci.rs +++ b/uci/tests/uci.rs @@ -12,10 +12,10 @@ use search::search::Search; use std::str; use std::sync::{Arc, Mutex}; use std::time::Duration; +use uci::UciOut; use uci::uci_in::{ debug, go, is_ready, position, quit, set_option, stop, uci as cmd_uci, ucinewgame, }; -use uci::UciOut; use uci::{Parser, ParserMessage}; const EVALUATOR: MaterialMobility = MaterialMobility::new(); @@ -183,14 +183,16 @@ fn run_command_position() { assert!(p.run_command("position startpos\n", &mut engine).is_ok()); assert_eq!(Some(&Position::initial()), engine.position()); - assert!(p - .run_command(format!("position fen {FEN_STR}\n").as_str(), &mut engine) - .is_ok()); + assert!( + p.run_command(format!("position fen {FEN_STR}\n").as_str(), &mut engine) + .is_ok() + ); assert_eq!(Fen::str_to_pos(FEN_STR).ok().as_ref(), engine.position()); - assert!(p - .run_command("position startpos moves e2e4 c7c5 g1f3\n", &mut engine) - .is_ok()); + assert!( + p.run_command("position startpos moves e2e4 c7c5 g1f3\n", &mut engine) + .is_ok() + ); let fen = "rnbqkbnr/pp1ppppp/8/2p5/4P3/5N2/PPPP1PPP/RNBQKB1R b KQkq - 1 2"; assert_eq!(Fen::str_to_pos(fen).ok().as_ref(), engine.position()); } @@ -211,9 +213,10 @@ fn run_command_position_chess_960() { p.register_command(String::from("position"), Box::new(position::run_command)); p.register_command(String::from("setoption"), Box::new(set_option::run_command)); - assert!(p - .run_command("setoption name UCI_Chess960 value true\n", &mut engine) - .is_ok()); + assert!( + p.run_command("setoption name UCI_Chess960 value true\n", &mut engine) + .is_ok() + ); assert_matches!(engine.variant(), Variant::Chess960(_, _)); assert_eq!(None, engine.position()); @@ -230,20 +233,22 @@ fn run_command_position_chess_960() { assert!(p.run_command("position startpos\n", &mut engine).is_ok()); assert_eq!(Some(&Position::initial()), engine.position()); - assert!(p - .run_command( + assert!( + p.run_command( format!("position fen {FEN_STR_CHESS_960}\n").as_str(), &mut engine ) - .is_ok()); + .is_ok() + ); assert_eq!(Fen::str_to_pos(FEN_STR).ok().as_ref(), engine.position()); - assert!(p - .run_command( + assert!( + p.run_command( &format!("position fen {FEN_STR_CHESS_960} moves e1h1\n"), &mut engine ) - .is_ok()); + .is_ok() + ); let fen = "rnbq1k1r/pp1Pbppp/2p5/8/2B5/8/PPP1NnPP/RNBQ1RK1 b - - 2 8"; assert_eq!( Fen::str_to_pos_chess_960(fen).ok().as_ref(), @@ -385,9 +390,10 @@ fn run_command_go() { // Combine multiple options assert!(p.run_command("position startpos\n", &mut engine).is_ok()); - assert!(p - .run_command("go depth 2 movetime 100\n", &mut engine) - .is_ok()); + assert!( + p.run_command("go depth 2 movetime 100\n", &mut engine) + .is_ok() + ); std::thread::sleep(Duration::from_millis(400)); assert!(contains(test_writer.split_off(0), "bestmove")); assert!(p.run_command("stop\n", &mut engine).is_ok()); @@ -404,9 +410,10 @@ fn run_command_go() { std::thread::sleep(Duration::from_millis(20)); assert!(!contains(test_writer.split_off(0), "bestmove")); - assert!(p - .run_command("go movetime 100 infinite\n", &mut engine) - .is_ok()); + assert!( + p.run_command("go movetime 100 infinite\n", &mut engine) + .is_ok() + ); std::thread::sleep(Duration::from_millis(400)); assert!(!contains(test_writer.split_off(0), "bestmove")); assert!(p.run_command("stop\n", &mut engine).is_ok()); @@ -439,19 +446,22 @@ fn run_command_go_time() { assert!(p.run_command("go btime\n", &mut engine).is_err()); assert!(p.run_command("go winc\n", &mut engine).is_err()); assert!(p.run_command("go binc\n", &mut engine).is_err()); - assert!(p - .run_command("go wtime 500 btime 800 winc 100 binc 100\n", &mut engine) - .is_ok()); + assert!( + p.run_command("go wtime 500 btime 800 winc 100 binc 100\n", &mut engine) + .is_ok() + ); std::thread::sleep(Duration::from_millis(500)); assert!(contains(test_writer.split_off(0), "bestmove")); - assert!(p - .run_command("position startpos moves e2e4\n", &mut engine) - .is_ok()); + assert!( + p.run_command("position startpos moves e2e4\n", &mut engine) + .is_ok() + ); std::thread::sleep(Duration::from_millis(20)); - assert!(p - .run_command("go wtime 500 btime 800 winc 100 binc 100\n", &mut engine) - .is_ok()); + assert!( + p.run_command("go wtime 500 btime 800 winc 100 binc 100\n", &mut engine) + .is_ok() + ); std::thread::sleep(Duration::from_millis(800)); assert!(contains(test_writer.split_off(0), "bestmove")); } @@ -475,9 +485,10 @@ fn run_command_go_time_limit_exceeded() { p.register_command(String::from("position"), Box::new(position::run_command)); p.register_command(String::from("go"), Box::new(go::run_command)); - assert!(p - .run_command("setoption name Move Overhead value 100\n", &mut engine) - .is_ok()); + assert!( + p.run_command("setoption name Move Overhead value 100\n", &mut engine) + .is_ok() + ); assert!(p.run_command("position startpos\n", &mut engine).is_ok()); std::thread::sleep(Duration::from_millis(20)); @@ -485,9 +496,10 @@ fn run_command_go_time_limit_exceeded() { std::thread::sleep(Duration::from_millis(50)); assert!(contains(test_writer.split_off(0), "bestmove")); - assert!(p - .run_command("position startpos moves e2e4\n", &mut engine) - .is_ok()); + assert!( + p.run_command("position startpos moves e2e4\n", &mut engine) + .is_ok() + ); std::thread::sleep(Duration::from_millis(20)); assert!(p.run_command("go wtime 0 btime 0\n", &mut engine).is_ok()); std::thread::sleep(Duration::from_millis(50)); @@ -541,9 +553,10 @@ fn run_command_go_with_negative_value() { p.register_command(String::from("stop"), Box::new(stop::run_command)); assert!(p.run_command("position startpos\n", &mut engine).is_ok()); - assert!(p - .run_command("go wtime 100 btime -1\n", &mut engine) - .is_ok()); + assert!( + p.run_command("go wtime 100 btime -1\n", &mut engine) + .is_ok() + ); std::thread::sleep(Duration::from_millis(400)); assert!(contains(test_writer.split_off(0), "bestmove")); assert!(p.run_command("go wtime -1\n", &mut engine).is_ok()); @@ -605,15 +618,19 @@ fn run_command_quit() { let res = p.run_command("quit\n", &mut engine); assert!(res.is_ok()); assert_eq!(Some(ParserMessage::Quit), res.unwrap()); - assert!(String::from_utf8(test_writer.split_off(0)) - .unwrap() - .is_empty()); + assert!( + String::from_utf8(test_writer.split_off(0)) + .unwrap() + .is_empty() + ); let res = p.run_command("ignored quit\n", &mut engine); assert!(res.is_ok()); assert_eq!(Some(ParserMessage::Quit), res.unwrap()); - assert!(String::from_utf8(test_writer.split_off(0)) - .unwrap() - .is_empty()); + assert!( + String::from_utf8(test_writer.split_off(0)) + .unwrap() + .is_empty() + ); } #[test] @@ -635,12 +652,13 @@ fn info_score_equal_from_both_sides() { let re_info_score = Regex::new(r"score cp \d+").unwrap(); // Set up King's Gambit - assert!(p - .run_command( + assert!( + p.run_command( "position fen rnbqkbnr/pppp1ppp/8/4p3/4PP2/8/PPPP2PP/RNBQKBNR b KQkq - 0 2\n", &mut engine ) - .is_ok()); + .is_ok() + ); std::thread::sleep(Duration::from_millis(20)); assert!(p.run_command("go depth 1\n", &mut engine).is_ok()); std::thread::sleep(Duration::from_millis(400)); @@ -659,12 +677,13 @@ fn info_score_equal_from_both_sides() { .as_str(); // Set up mirrored position - assert!(p - .run_command( + assert!( + p.run_command( "position fen rnbqkbnr/pppp2pp/8/4pp2/4P3/8/PPPP1PPP/RNBQKBNR w KQkq - 0 2\n", &mut engine ) - .is_ok()); + .is_ok() + ); std::thread::sleep(Duration::from_millis(20)); assert!(p.run_command("go depth 1\n", &mut engine).is_ok()); std::thread::sleep(Duration::from_millis(400)); @@ -703,12 +722,13 @@ fn mate_in_one_white_to_move() { p.register_command(String::from("go"), Box::new(go::run_command)); // Set up mate in one - assert!(p - .run_command( + assert!( + p.run_command( "position fen 8/7k/7P/8/8/8/6Q1/6K1 w - - 0 1\n", &mut engine ) - .is_ok()); + .is_ok() + ); std::thread::sleep(Duration::from_millis(20)); assert!(p.run_command("go movetime 100\n", &mut engine).is_ok()); std::thread::sleep(Duration::from_millis(200)); @@ -735,12 +755,13 @@ fn mate_in_one_black_to_move() { p.register_command(String::from("go"), Box::new(go::run_command)); // Set up mate in one - assert!(p - .run_command( + assert!( + p.run_command( "position fen 6k1/6q1/8/8/8/7p/7K/8 b - - 0 1\n", &mut engine ) - .is_ok()); + .is_ok() + ); std::thread::sleep(Duration::from_millis(20)); assert!(p.run_command("go movetime 100\n", &mut engine).is_ok()); std::thread::sleep(Duration::from_millis(200)); @@ -771,8 +792,8 @@ fn threefold_repetition(search_algo: impl Search + Send + 'static) { p.register_command(String::from("go"), Box::new(go::run_command)); // Set up threefold repetition on next move - assert!(p - .run_command( + assert!( + p.run_command( "position startpos moves e2e3 b8c6 f1b5 g8f6 d1f3 c6b4 b1a3 e7e5 c2c3 e5e4 f3f5 b4c6 \ g1e2 d7d5 f5e5 c8e6 e2d4 f8d6 e5g5 f6d7 g5g7 d6e5 g7h6 c6d4 e3d4 d8f6 d2d3 f6h6 c1h6 \ c7c6 d4e5 c6b5 a3b5 e8e7 h6g5 f7f6 e5f6 d7f6 e1d2 a8g8 h2h4 e4d3 a1e1 h7h6 b5d4 h6g5 \ @@ -789,14 +810,16 @@ fn threefold_repetition(search_algo: impl Search + Send + 'static) { e3f5 a2a1 e5e6 a1b1 e6e7 b1a1 e7f7 a1b1 f5e3 b1a1 f7g7 a1b1 g7f7 b1a1 f7g7 a1b1\n", &mut engine ) - .is_ok()); + .is_ok() + ); std::thread::sleep(Duration::from_millis(20)); - assert!(p - .run_command( + assert!( + p.run_command( "go wtime 8955 btime 109427 winc 1000 binc 1000 movestogo 4\n", &mut engine ) - .is_ok()); + .is_ok() + ); std::thread::sleep(Duration::from_millis(400)); } @@ -838,13 +861,15 @@ fn search_stopped_after_depth_1_if_move_is_forced() { (fen_black_to_move, "btime 10000", false), ] { assert!(p.run_command("ucinewgame\n", &mut engine).is_ok()); - assert!(p - .run_command(&format!("position fen {fen}\n"), &mut engine) - .is_ok()); + assert!( + p.run_command(&format!("position fen {fen}\n"), &mut engine) + .is_ok() + ); std::thread::sleep(Duration::from_millis(20)); - assert!(p - .run_command(&format!("go {go_option}\n"), &mut engine) - .is_ok()); + assert!( + p.run_command(&format!("go {go_option}\n"), &mut engine) + .is_ok() + ); std::thread::sleep(Duration::from_millis(200)); assert!(p.run_command("stop\n", &mut engine).is_ok()); @@ -886,12 +911,13 @@ fn stress() { assert!(p.run_command("debug on\n", &mut engine).is_ok()); for hash_size in [1, 8, 64] { - assert!(p - .run_command( + assert!( + p.run_command( format!("setoption name Hash value {hash_size}\n").as_str(), &mut engine ) - .is_ok()); + .is_ok() + ); assert!(p.run_command("isready\n", &mut engine).is_ok()); for i in 0..10_000 { @@ -926,12 +952,13 @@ fn play_move_after_unclaimed_threefold_repetition() { // The given position and move history result in a threefold repetition. // The engine should do a normal search because the draw was not claimed. // It should not return a null move. - assert!(p - .run_command( + assert!( + p.run_command( "position startpos moves g1f3 g8f6 f3g1 f6g8 g1f3 g8f6 f3g1 f6g8\n", &mut engine ) - .is_ok()); + .is_ok() + ); std::thread::sleep(Duration::from_millis(20)); assert!(p.run_command("go depth 1\n", &mut engine).is_ok()); std::thread::sleep(Duration::from_millis(200)); From dd55753957a5c2fb6c5af97b34ecc866be363a61 Mon Sep 17 00:00:00 2001 From: Patrick Heck <49785565+FitzOReilly@users.noreply.github.com> Date: Mon, 9 Mar 2026 18:44:58 +0100 Subject: [PATCH 4/4] Bump version --- fatalii/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fatalii/Cargo.toml b/fatalii/Cargo.toml index dcf4169c..d9db9c9e 100644 --- a/fatalii/Cargo.toml +++ b/fatalii/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "fatalii" -version = "0.10.0-alpha" +version = "0.10.0" edition = "2024" [dependencies]