124 lines
3.8 KiB
Rust
124 lines
3.8 KiB
Rust
use itertools::join;
|
|
use std::time::Duration;
|
|
use std::fmt;
|
|
|
|
use chess::{ChessMove, Board, Action};
|
|
|
|
mod uci_command{}
|
|
|
|
pub struct Id {name: Option<String>, author: Option<String>}
|
|
impl Id {
|
|
pub fn new() -> Id {
|
|
Id{name: None, author: None}
|
|
}
|
|
|
|
pub fn update(&mut self, id: &Id){
|
|
if let Some(name) = &id.name {self.name = Some(name.clone());}
|
|
if let Some(author) = &id.author {self.author = Some(author.clone());}
|
|
}
|
|
|
|
pub fn update_from_str(&mut self, name: Option<&str>, author: Option<&str>){
|
|
if let Some(name) = name {self.name = Some(name.to_string());}
|
|
if let Some(author) = author {self.author = Some(author.to_string());}
|
|
}
|
|
|
|
pub fn name(&self) -> Option<String> {
|
|
self.name.clone()
|
|
}
|
|
|
|
pub fn author(&self) -> Option<String> {
|
|
self.author.clone()
|
|
}
|
|
}
|
|
#[derive(Debug)]
|
|
pub struct Info {}
|
|
#[derive(Debug)]
|
|
pub struct Opt{}
|
|
|
|
pub enum EngineCommand {
|
|
Id{id: Id},
|
|
UciOk,
|
|
ReadyOk,
|
|
BestMove{best_move: ChessMove, ponder: Option<ChessMove>},
|
|
CopyProtection, // unimplemented
|
|
Registration, // unimplemented
|
|
Info{infos: Vec<Info>},
|
|
Opt{options: Vec<Opt>},
|
|
}
|
|
|
|
|
|
#[derive(Debug)]
|
|
pub enum GuiCommand {
|
|
Uci,
|
|
Debug{mode: bool},
|
|
IsReady,
|
|
SetOption{option: Opt},
|
|
Register, // unimplemented
|
|
UciNewGame,
|
|
Position{position: Option<Board>, moves: Vec<Action>},
|
|
Go,
|
|
SearchMoves{moves: Vec<ChessMove>},
|
|
Ponder,
|
|
WTime{time: Duration},
|
|
BTime{time: Duration},
|
|
WInc{increment: Duration},
|
|
BInc{increment: Duration},
|
|
MovesToGo{number: u16},
|
|
Depth{number: u16},
|
|
Nodes{number: u16},
|
|
Mate{number: u16},
|
|
MoveTime{time: Duration},
|
|
Infinite,
|
|
Stop,
|
|
PonderHit,
|
|
Quit,
|
|
}
|
|
|
|
pub fn parse(message: &mut String) -> Result<EngineCommand,&'static str> {
|
|
let mut message_iter = message.split_whitespace();
|
|
|
|
match message_iter.next() {
|
|
None => Err("No command provided"),
|
|
|
|
Some("id") =>
|
|
match message_iter.collect::<Vec<&str>>().as_slice() {
|
|
[] => Err("Empty id command"),
|
|
["name"] => Err("Empty id name command"),
|
|
["author"] => Err("Empty id author command"),
|
|
["name", tail @ ..] => Ok(EngineCommand::Id{id: { let mut id = Id::new(); id.update_from_str(Some(&join(tail, " ")), None); id}}),
|
|
["author", tail @ ..] => Ok(EngineCommand::Id{id: { let mut id = Id::new(); id.update_from_str(None, Some(&join(tail, " "))); id}}),
|
|
_ => Err("Invalid id subcommand")
|
|
},
|
|
Some("uciok") => Ok(EngineCommand::UciOk),
|
|
Some("readyok") => unimplemented!(),
|
|
Some("bestmove") => unimplemented!(),
|
|
Some("copyprotection") => unimplemented!(),
|
|
Some("registration") => unimplemented!(),
|
|
Some("info") => unimplemented!(),
|
|
Some("option") => Ok(EngineCommand::Opt { options: Vec::new() }), // todo!("Parse options lines")
|
|
Some(_) => Err("Unknown command provided"),
|
|
}
|
|
}
|
|
|
|
impl fmt::Display for GuiCommand {
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result{
|
|
match self {
|
|
GuiCommand::Uci => write!(f, "uci\n"),
|
|
GuiCommand::UciNewGame => write!(f, "ucinewgame\n"),
|
|
GuiCommand::Position { position, moves } => {
|
|
write!(f, "position {} moves {}\n",
|
|
match position { None => "startpos".to_string(),
|
|
Some(board) if *board == Board::default() => "startpos".to_string(),
|
|
Some(board) =>"fen ".to_string() + &board.to_string()},
|
|
join(moves.into_iter().map(|x| if let Action::MakeMove(chessmove) = x
|
|
{chessmove.to_string()} else {"".to_string()}), "")
|
|
)
|
|
}
|
|
a => unimplemented!("{:?}", a),
|
|
}
|
|
|
|
}
|
|
}
|
|
|