Add uci movetime, hash and initialize TT based on size in MBs

This commit is contained in:
stefiosif
2025-02-04 23:53:18 +02:00
parent 908a87bd26
commit b98100aa71
5 changed files with 75 additions and 23 deletions

View File

@@ -1,4 +1,5 @@
use std::{
collections::HashMap,
io::{BufRead, Write},
str::SplitWhitespace,
};
@@ -13,7 +14,7 @@ use crate::{
movegen::r#move::Move,
search::{
iterative_deepening, time::TimeInfo, transposition_table::TranspositionTable, INC,
MAX_DEPTH, MAX_TT_SIZE, TIME,
MAX_DEPTH, TIME,
},
};
@@ -26,6 +27,7 @@ pub enum Command {
Go,
Stop,
Quit,
SetOption,
}
fn parse_command(parts: &mut SplitWhitespace) -> anyhow::Result<Command> {
@@ -37,6 +39,7 @@ fn parse_command(parts: &mut SplitWhitespace) -> anyhow::Result<Command> {
Some("go") => Ok(Command::Go),
Some("stop") => Ok(Command::Stop),
Some("quit") => Ok(Command::Quit),
Some("setoption") => Ok(Command::SetOption),
_ => bail!("Unrecognised command"),
}
}
@@ -75,10 +78,11 @@ struct UciParameters {
btime: Option<u128>,
winc: Option<u128>,
binc: Option<u128>,
options: HashMap<String, String>,
}
impl UciParameters {
const fn new() -> Self {
fn new() -> Self {
Self {
depth: None,
game: None,
@@ -86,9 +90,15 @@ impl UciParameters {
btime: None,
winc: None,
binc: None,
options: HashMap::new(),
}
}
fn add_move_time(&mut self, movetime: u128) {
self.wtime = Some(movetime);
self.btime = Some(movetime);
}
fn add_depth(&mut self, depth: u8) {
self.depth = Some(depth);
}
@@ -112,6 +122,10 @@ impl UciParameters {
fn add_game(&mut self, game: Game) {
self.game = Some(game);
}
fn add_option(&mut self, name: String, value: String) {
self.options.insert(name, value);
}
}
impl Default for UciParameters {
@@ -156,6 +170,7 @@ pub fn uci_go(go_iter: &mut SplitWhitespace, game: &mut Game) -> anyhow::Result<
"winc" => params.add_winc(parse_next(go_iter, "winc")?),
"binc" => params.add_binc(parse_next(go_iter, "binc")?),
"depth" => params.add_depth(parse_next(go_iter, "depth")?),
"movetime" => params.add_move_time(parse_next(go_iter, "movetime")?),
_ => (),
}
}
@@ -173,9 +188,34 @@ pub fn uci_go(go_iter: &mut SplitWhitespace, game: &mut Game) -> anyhow::Result<
.ok_or_else(|| anyhow!("No stored best move found"))
}
fn parse_next<T: std::str::FromStr>(go_iter: &mut SplitWhitespace, val: &str) -> anyhow::Result<T> {
go_iter
.next()
fn uci_option(option_iter: &mut SplitWhitespace, game: &mut Game) -> anyhow::Result<()> {
let mut params = UciParameters::new();
//TODO: Implement the rest of the options and refactor
while let Some(subcommand) = option_iter.next() {
if subcommand == "name" {
let name: String = parse_next(option_iter, "name")?;
option_iter.next();
let value: String = parse_next(option_iter, "value")?;
params.add_option(name, value);
}
}
if let Some(name) = params.options.get("name") {
if name == "Hash" {
let value = params.options.get("value").expect("Expected key value");
let size = value
.parse::<usize>()
.map_err(|_| anyhow!("Invalid value for Hash"))?;
game.tt = TranspositionTable::new_with_mb_size(size);
}
}
Ok(())
}
fn parse_next<T: std::str::FromStr>(iter: &mut SplitWhitespace, val: &str) -> anyhow::Result<T> {
iter.next()
.ok_or_else(|| anyhow!("Expected {val}"))
.and_then(|v| v.parse::<T>().map_err(|_| anyhow!("Invalid {val}")))
}
@@ -192,18 +232,14 @@ pub fn uci_loop<R: BufRead, W: Write>(input: R, mut output: W) -> anyhow::Result
Command::IsReady => write_response(&mut output, &Response::ReadyOk)?,
Command::UciNewGame => {
if let Some(game) = params.game.as_mut() {
game.tt = TranspositionTable::new(MAX_TT_SIZE);
game.tt = TranspositionTable::new();
game.board = Board::startpos();
} else {
let game = Game::new();
params.add_game(game);
}
write_response(&mut output, &Response::Info("Clear cache".to_string()))?;
}
Command::Position => {
//TODO: doesnt have to create a new game every time, we can just update the game
params.add_game(uci_position(&mut parts)?);
}
Command::Position => params.add_game(uci_position(&mut parts)?),
Command::Go => {
if let Some(game) = params.game.as_mut() {
match uci_go(&mut parts, game) {
@@ -222,6 +258,14 @@ pub fn uci_loop<R: BufRead, W: Write>(input: R, mut output: W) -> anyhow::Result
}
Command::Stop => break,
Command::Quit => break,
Command::SetOption => {
if let Some(game) = params.game.as_mut() {
uci_option(&mut parts, game)?;
} else {
let game = Game::new();
params.add_game(game);
};
}
};
output.flush().map_err(|e| anyhow!(e))?
@@ -299,7 +343,6 @@ mod tests {
let expected_response = "id name zeal\n\
id author stefiosif\n\
uciok\n\
Clear cache\n\
bestmove e3f2\n";
let actual_response = String::from_utf8(output).expect("Invalid UTF-8 in output");