Add basic UCI support
This commit is contained in:
97
src/uci.rs
Normal file
97
src/uci.rs
Normal file
@@ -0,0 +1,97 @@
|
||||
use std::str::SplitWhitespace;
|
||||
|
||||
use crate::{game::Game, r#move::Move, search::search};
|
||||
|
||||
pub enum Command {
|
||||
Uci,
|
||||
IsReady,
|
||||
UciNewGame,
|
||||
Position(String),
|
||||
Go,
|
||||
Stop,
|
||||
Quit,
|
||||
}
|
||||
|
||||
pub enum Response {
|
||||
Id(String),
|
||||
UciOk,
|
||||
ReadyOk,
|
||||
BestMove(String),
|
||||
Info(String),
|
||||
}
|
||||
|
||||
struct SearchParameters {
|
||||
movetime: Option<usize>,
|
||||
depth: Option<u8>,
|
||||
}
|
||||
|
||||
impl SearchParameters {
|
||||
const fn new() -> Self {
|
||||
Self {
|
||||
movetime: None,
|
||||
depth: None,
|
||||
}
|
||||
}
|
||||
|
||||
fn add_movetime(&mut self, movetime: usize) {
|
||||
self.movetime = Some(movetime);
|
||||
}
|
||||
|
||||
fn add_depth(&mut self, depth: u8) {
|
||||
self.depth = Some(depth);
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for SearchParameters {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn uci_position(mut position: SplitWhitespace) -> Result<Game, String> {
|
||||
let state = position.next().ok_or("Expected startpos or fen")?;
|
||||
let mut game = match state {
|
||||
"startpos" => Game::new(),
|
||||
"fen" => Game::new_from_fen(position.next().ok_or("Expected fen string")?)?,
|
||||
_ => return Err("Expected startpos or fen".to_string()),
|
||||
};
|
||||
|
||||
for mv_str in position {
|
||||
let mv = Move::parse_from_str(mv_str)?;
|
||||
game.board.make_move(mv, game.board.state.next_turn());
|
||||
}
|
||||
|
||||
Ok(game)
|
||||
}
|
||||
|
||||
const MAX_DEPTH: u8 = 5;
|
||||
|
||||
pub fn uci_go(mut go: SplitWhitespace, game: &mut Game) -> Response {
|
||||
let mut params = SearchParameters::new();
|
||||
while let Some(subcommand) = go.next() {
|
||||
match subcommand {
|
||||
"depth" => params.add_depth(go.next().unwrap().parse::<u8>().ok().unwrap()),
|
||||
"movetime" => params.add_movetime(go.next().unwrap().parse::<usize>().ok().unwrap()),
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
search(game, params.depth.unwrap_or(MAX_DEPTH));
|
||||
Response::BestMove(String::from("value"))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::fen::from_fen;
|
||||
|
||||
const FEN: [&str; 1] = ["r3k2r/2p1p1qp/2npb3/1p3p2/p3P1pP/P1PB1Q2/1P1PNPP1/R3K2R w KQkq - 0 1"];
|
||||
|
||||
#[test]
|
||||
fn test_uci_position() -> Result<(), String> {
|
||||
let mut _game = from_fen(FEN[0])?;
|
||||
|
||||
// check that the board state is as expected after using uci position and compare
|
||||
// with a separate fen that created the update instance by itself
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user