diff --git a/src/interface/uci.rs b/src/interface/uci.rs index 8138ee3..082f4f8 100644 --- a/src/interface/uci.rs +++ b/src/interface/uci.rs @@ -1,5 +1,5 @@ use std::{ - io::{self, BufRead, Write}, + io::{BufRead, Write}, str::SplitWhitespace, }; @@ -133,38 +133,34 @@ pub fn uci_go(go: &mut SplitWhitespace, game: &mut Game) -> Result Ok(Move::new(Square::B8, Square::C6)) } -pub fn uci_loop() -> Result<(), String> { - let stdin = io::stdin(); - let stdout = io::stdout(); - let handle_in = stdin.lock(); - let mut handle_out = stdout.lock(); +pub fn uci_loop(input: R, mut output: W) -> Result<(), String> { let mut params = UciParameters::new(); - for line in handle_in.lines() { + for line in input.lines() { let line_str = line.unwrap_or_else(|_| "quit".to_string()); let mut parts = line_str.split_whitespace(); let command = parse_command(&mut parts)?; let response = match command { Command::Uci => Response::UciOk, Command::IsReady => Response::ReadyOk, - Command::UciNewGame => Response::Info("Clear cached game.".to_string()), + Command::UciNewGame => Response::Info("Clear cache".to_string()), Command::Position => { params.add_game(uci_position(&mut parts)?); - Response::Info("Initialized position.".to_string()) + Response::Info("Initialized position".to_string()) } Command::Go => { if let Some(ref mut game) = params.game { let best_move = uci_go(&mut parts, game)?; Response::BestMove(best_move.parse_into_str()) } else { - Response::Info("Going!".to_string()) + Response::Info("Going?".to_string()) } } Command::Quit => break, }; - write_response(&mut handle_out, response)?; - handle_out.flush().map_err(|e| e.to_string())?; + write_response(&mut output, response)?; + output.flush().map_err(|e| e.to_string())?; } Ok(()) @@ -172,11 +168,16 @@ pub fn uci_loop() -> Result<(), String> { #[cfg(test)] mod tests { + use std::io::Cursor; + use crate::{ - board::fen::from_fen, + board::{fen::from_fen, game::Game, square::Square}, interface::uci::{parse_command, Command}, + movegen::r#move::Move, }; + use super::uci_go; + use super::uci_loop; use super::uci_position; const FEN: [&str; 2] = [ @@ -205,32 +206,37 @@ mod tests { #[test] fn test_uci_go() -> Result<(), String> { - let mut _game = from_fen(FEN[0])?; + let mut game = Game::new(); + let command_go = "go depth 4"; + let mut parts = command_go.split_whitespace(); + let response = uci_go(&mut parts, &mut game)?; + assert_eq!(Move::new(Square::B8, Square::C6), response); Ok(()) } #[test] fn test_uci_loop() -> Result<(), String> { - let mut _game = from_fen(FEN[0])?; + let commands = b"uci\n\ + ucinewgame\n\ + position startpos moves e2e4 e7e5\n\ + go\n\ + quit"; + let input = Cursor::new(commands); + let mut output: Vec<_> = vec![]; + + uci_loop(input, &mut output)?; + + let expected_response = "id name ippos\n\ + id author stefiosif\n\ + uciok\n\ + Clear cache\n\ + Initialized position\n\ + bestmove b8c6\n"; + let actual_response = String::from_utf8(output).expect("Invalid UTF-8 in output"); + + assert_eq!(expected_response, actual_response); 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` -``` -*/ diff --git a/src/main.rs b/src/main.rs index 984141a..78846f7 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,16 +1,24 @@ +use std::io; + mod board; mod evaluation; mod interface; mod movegen; mod search; +use interface::uci; + fn main() { movegen::attack::init_attacks(); let command = std::env::args().nth(1).unwrap_or(String::from("quit")); match command.as_str() { "perft" => search::perft::perftree_script(), - "uci" => interface::uci::uci_loop().unwrap_or_else(|e| println!("{}", e)), + "uci" => { + let input = io::stdin().lock(); + let output = io::stdout().lock(); + uci::uci_loop(input, output).unwrap_or_else(|e| println!("{}", e)); + } "quit" => println!("Exiting.."), _ => println!("Wrong command. Exiting.."), };