158 lines
4.9 KiB
Rust
158 lines
4.9 KiB
Rust
|
#![allow(dead_code)]
|
||
|
|
||
|
/// Manage UCI messages and link into chess component
|
||
|
pub mod uci_engine {
|
||
|
use itertools::join;
|
||
|
|
||
|
mod chess_move {
|
||
|
pub struct Move {}
|
||
|
}
|
||
|
mod chess_info{
|
||
|
pub struct Info {}
|
||
|
}
|
||
|
mod chess_option{
|
||
|
pub struct Opt{}
|
||
|
}
|
||
|
|
||
|
pub struct UciEngine {
|
||
|
name: String,
|
||
|
author: String,
|
||
|
}
|
||
|
|
||
|
impl UciEngine {
|
||
|
pub fn new(name: &str, author: &str) -> UciEngine {
|
||
|
UciEngine{name: name.to_string(), author: author.to_string()}
|
||
|
}
|
||
|
|
||
|
pub fn name(&self) -> String {
|
||
|
self.name.clone()
|
||
|
}
|
||
|
|
||
|
pub fn author(&self) -> String {
|
||
|
self.author.clone()
|
||
|
}
|
||
|
|
||
|
pub fn update(&mut self, id: &Id){
|
||
|
match &id.name {
|
||
|
Some(name) => self.name = name.clone(),
|
||
|
None => {}
|
||
|
}
|
||
|
|
||
|
match &id.author {
|
||
|
Some(author) => self.author = author.clone(),
|
||
|
None => {}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
pub struct Id {name: Option<String>, author: Option<String>}
|
||
|
impl Id {
|
||
|
pub fn new(name: Option<&str>, author: Option<&str>) -> Id {
|
||
|
Id{
|
||
|
name: if let Some(name) = name {Some(name.to_string())} else {None},
|
||
|
author: if let Some(author) = author {Some(author.to_string())} else {None}
|
||
|
}
|
||
|
}
|
||
|
pub fn update(&mut self, name: Option<&str>, author: Option<&str>){
|
||
|
match &name {
|
||
|
Some(name) => self.name = Some(name.to_string()),
|
||
|
None => {}
|
||
|
}
|
||
|
|
||
|
match &author {
|
||
|
Some(author) => self.author = Some(author.to_string()),
|
||
|
None => {}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
pub enum UciCommand {
|
||
|
Id{id: Id},
|
||
|
UciOk,
|
||
|
ReadyOk,
|
||
|
BestMove{best_move: chess_move::Move, ponder: chess_move::Move},
|
||
|
CopyProtection, // unimplemented
|
||
|
Registration, // unimplemented
|
||
|
Info{infos: Vec<chess_info::Info>},
|
||
|
Opt{options: Vec<chess_option::Opt>},
|
||
|
}
|
||
|
|
||
|
/// Parse UCI commands
|
||
|
///
|
||
|
/// * id
|
||
|
/// * name *x*
|
||
|
///
|
||
|
/// this must be sent after receiving the "uci" command to identify the engine,
|
||
|
/// e.g. "id name Shredder X.Y\n"
|
||
|
/// * author *x*
|
||
|
///
|
||
|
/// this must be sent after receiving the "uci" command to identify the engine,
|
||
|
/// e.g. "id author Stefan MK\n"
|
||
|
///
|
||
|
/// ```rust
|
||
|
/// use chess_uci::uci_engine::{parse, UciCommand, Id, UciEngine};
|
||
|
/// let mut engine = UciEngine::new("Test", "Bat");
|
||
|
///
|
||
|
/// engine.exec(&parse(&mut "id name Baptiste".to_string()).expect("simple id name command"));
|
||
|
/// assert_eq!(engine.name(), "Baptiste");
|
||
|
///
|
||
|
/// engine.exec(&parse(&mut "id author Monique Jouve".to_string()).expect("simple id author command"));
|
||
|
/// assert_eq!(engine.author(), "Monique Jouve");
|
||
|
///
|
||
|
/// ```
|
||
|
pub fn parse(message: &mut String) -> Result<UciCommand,&'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(UciCommand::Id{id: Id::new(Some(&join(tail, " ")), None)}),
|
||
|
["author", tail @ ..] => Ok(UciCommand::Id{id: Id::new(None, Some(&join(tail, " ")))}),
|
||
|
_ => Err("Invalid id subcommand")
|
||
|
},
|
||
|
Some("uciok") => unimplemented!(),
|
||
|
Some("readyok") => unimplemented!(),
|
||
|
Some("bestmove") => unimplemented!(),
|
||
|
Some("copyprotection") => unimplemented!(),
|
||
|
Some("registration") => unimplemented!(),
|
||
|
Some("info") => unimplemented!(),
|
||
|
Some("option") => unimplemented!(),
|
||
|
Some(_) => Err("Unknown command provided"),
|
||
|
}
|
||
|
}
|
||
|
|
||
|
impl UciEngine {
|
||
|
pub fn exec(&mut self, command: &UciCommand){
|
||
|
match command {
|
||
|
UciCommand::Id{id} => self.update(&id),
|
||
|
_ => unimplemented!(),
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#[cfg(test)]
|
||
|
mod tests {
|
||
|
use super::uci_engine::*;
|
||
|
|
||
|
#[test]
|
||
|
fn new_uci() {
|
||
|
let mut engine = UciEngine::new("Test", "Bat");
|
||
|
assert_eq!(engine.name(), "Test");
|
||
|
assert_eq!(engine.author(), "Bat");
|
||
|
let new_id = Id::new(Some("Test 1"), None);
|
||
|
engine.update(&new_id);
|
||
|
assert_eq!(engine.name(), "Test 1");
|
||
|
assert_eq!(engine.author(), "Bat");
|
||
|
let new_id = Id::new(Some("Test 2"), Some("Bat 1"));
|
||
|
engine.update(&new_id);
|
||
|
assert_eq!(engine.name(), "Test 2");
|
||
|
assert_eq!(engine.author(), "Bat 1");
|
||
|
}
|
||
|
}
|