diff --git a/src/board/game.rs b/src/board/game.rs index e28f091..3b19e2a 100644 --- a/src/board/game.rs +++ b/src/board/game.rs @@ -29,7 +29,7 @@ pub struct Game { pub hash: ZobristHash, pub tt: TranspositionTable, pub killer: [Option; MAX_DEPTH as usize], - pub history_heuristic: [[[i16; 64]; 64]; 2], + pub history_heuristic: [[[i32; 64]; 64]; 2], } impl Game { diff --git a/src/interface/uci.rs b/src/interface/uci.rs index 621f479..714c535 100644 --- a/src/interface/uci.rs +++ b/src/interface/uci.rs @@ -6,7 +6,7 @@ use std::{ thread, }; -use anyhow::{anyhow, bail}; +use anyhow::{anyhow, bail, Context}; use crate::{ board::{ @@ -58,7 +58,12 @@ use std::fmt; impl fmt::Display for Response { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { - Self::UciOk => write!(f, "id name zeal\nid author stefiosif\nuciok"), + Self::UciOk => { + let name = "id name zeal 1.0"; + let author = "id author stefiosif"; + let hash = "option name Hash type spin default 64 min 1 max 1024"; + write!(f, "{name}\n{author}\n{hash}\nuciok") + } Self::ReadyOk => write!(f, "readyok"), Self::BestMove(best_move) => write!(f, "bestmove {best_move}"), Self::Info(info) => write!(f, "{info}"), @@ -179,7 +184,7 @@ pub fn uci_go(go_iter: &mut SplitWhitespace, game: &mut Game) -> anyhow::Result< iterative_deepening::iterative_deepening( game, params.depth.unwrap_or(MAX_DEPTH), - &TimeInfo::new(std::time::Instant::now(), time, inc), + &TimeInfo::new(time, inc), )? .ok_or_else(|| anyhow!("No stored best move found")) } @@ -199,11 +204,18 @@ fn uci_option(option_iter: &mut SplitWhitespace, game: &mut Game) -> anyhow::Res if let Some(name) = params.options.get("name") { if name == "Hash" { - let value = params.options.get("value").expect("Expected key value"); - let size = value + let value = params + .options + .get("value") + .expect("Expected key value") .parse::() - .map_err(|_| anyhow!("Invalid value for Hash"))?; - game.tt = TranspositionTable::with_capacity(size); + .with_context(|| "Not a number".to_string())?; + + if !(1..=1024).contains(&value) { + bail!("Size must be between 1 and 1024; got {value}"); + } + + game.tt = TranspositionTable::with_capacity(value); } } diff --git a/src/search/iterative_deepening.rs b/src/search/iterative_deepening.rs index 6f443b6..ffcd96a 100644 --- a/src/search/iterative_deepening.rs +++ b/src/search/iterative_deepening.rs @@ -92,15 +92,8 @@ mod tests { fn test_iterative_deepening() -> anyhow::Result<()> { init_attacks(); let mut game = from_fen(FEN).unwrap(); - let instant = std::time::Instant::now(); - iterative_deepening::iterative_deepening( - &mut game, - MAX_DEPTH, - &TimeInfo::new(instant, TIME, INC), - )?; - - dbg!(instant.elapsed()); + iterative_deepening::iterative_deepening(&mut game, MAX_DEPTH, &TimeInfo::new(TIME, INC))?; Ok(()) } diff --git a/src/search/mod.rs b/src/search/mod.rs index 00f1ef8..733d106 100644 --- a/src/search/mod.rs +++ b/src/search/mod.rs @@ -6,9 +6,9 @@ pub mod quiescence; pub mod time; pub mod transposition_table; -pub const MAX_DEPTH: u8 = 50; -pub const TIME: u128 = 8000; -pub const INC: u128 = 80; +pub const MAX_DEPTH: u8 = 100; +pub const TIME: u128 = 100000; +pub const INC: u128 = 1000; pub const HARD_LIMIT_DIVISION: u128 = 3; pub const SOFT_LIMIT_DIVISION: u128 = 20; pub const TT_SIZE_IN_MB: usize = 64; @@ -23,5 +23,5 @@ pub const LMR_DIVISION: f32 = 2.0; pub const NMP_REDUCTION: u8 = 2; pub const NMP_DEPTH_THRESHOLD: u8 = 2; pub const RFP_DEPTH_LIMIT: u8 = 6; -pub const RFP_MARGIN: u8 = 75; +pub const RFP_MARGIN: i16 = 75; pub const CHECK_EXTENSION: u8 = 1; diff --git a/src/search/move_ordering.rs b/src/search/move_ordering.rs index 9eb7daa..c1beab8 100644 --- a/src/search/move_ordering.rs +++ b/src/search/move_ordering.rs @@ -21,7 +21,7 @@ pub fn score_move( if mv.is_capture() { let aggressor = mailbox.piece_at(mv.src()).unwrap(); if let Some(victim) = mailbox.piece_at(mv.dst()) { - return aggressor.0.idx() as i16 - 8 * victim.0.idx() as i16; + return aggressor.0.idx() as i32 - 8 * victim.0.idx() as i32; } return 0; //en passant } diff --git a/src/search/negamax.rs b/src/search/negamax.rs index 477b866..632ceff 100644 --- a/src/search/negamax.rs +++ b/src/search/negamax.rs @@ -3,6 +3,7 @@ use anyhow::{bail, Result}; use crate::{ board::game::Game, evaluation::{pesto::pesto, MATE_SCORE, MIN_SCORE}, + movegen::r#move::Move, }; use super::{ @@ -24,7 +25,7 @@ pub fn negamax( nodes: &mut u64, do_nmp: bool, ) -> Result { - if time.exceed_hard_limit() { + if *nodes & 1024 == 0 && time.exceed_hard_limit() { bail!("Hard limit exceeded in negamax"); } @@ -64,7 +65,7 @@ pub fn negamax( && alpha == beta - 1 && depth < RFP_DEPTH_LIMIT && eval > beta - && eval - (RFP_MARGIN * depth) as i16 > beta + && eval - RFP_MARGIN * depth as i16 > beta { return Ok(eval); } @@ -218,9 +219,15 @@ mod tests { let mut game = from_fen(FEN_MATE_IN_1[0]).unwrap(); let e3f2 = Move::new(Square::E3, Square::F2); - let time_info = TimeInfo::new(std::time::Instant::now(), TIME, INC); negamax( - &mut game, MIN_SCORE, MAX_SCORE, 5, 0, &time_info, &mut 0, true, + &mut game, + MIN_SCORE, + MAX_SCORE, + 5, + 0, + &TimeInfo::new(TIME, INC), + &mut 0, + true, ) .expect("Expected a search result"); @@ -230,7 +237,14 @@ mod tests { let e3f2 = Move::new(Square::E3, Square::F2); negamax( - &mut game, MIN_SCORE, MAX_SCORE, 5, 0, &time_info, &mut 0, true, + &mut game, + MIN_SCORE, + MAX_SCORE, + 5, + 0, + &TimeInfo::new(TIME, INC), + &mut 0, + true, ) .expect("Expected a search result"); diff --git a/src/search/time.rs b/src/search/time.rs index c5c3389..46f2e4f 100644 --- a/src/search/time.rs +++ b/src/search/time.rs @@ -9,8 +9,12 @@ pub struct TimeInfo { } impl TimeInfo { - pub const fn new(instant: Instant, time: u128, inc: u128) -> Self { - Self { instant, time, inc } + pub fn new(time: u128, inc: u128) -> Self { + Self { + instant: std::time::Instant::now(), + time, + inc, + } } pub fn nps(&self, nodes: u64) -> u64 { diff --git a/src/search/transposition_table.rs b/src/search/transposition_table.rs index ca04381..dec0f20 100644 --- a/src/search/transposition_table.rs +++ b/src/search/transposition_table.rs @@ -94,15 +94,19 @@ mod tests { fn test_transposition_table() -> anyhow::Result<()> { init_attacks(); let mut game = from_fen(FEN).unwrap(); - let time_info = TimeInfo::new(std::time::Instant::now(), TIME, INC); negamax( - &mut game, MIN_SCORE, MAX_SCORE, 3, 0, &time_info, &mut 0, true, + &mut game, + MIN_SCORE, + MAX_SCORE, + 3, + 0, + &TimeInfo::new(TIME, INC), + &mut 0, + true, ) .expect("Expected a search result"); - dbg!(time_info.instant.elapsed()); - let will_be_hash = from_fen(FEN_POSSIBLE).unwrap().hash; let entry = game.tt.lookup(will_be_hash);