advance on execution
This commit is contained in:
		
							parent
							
								
									745817d47a
								
							
						
					
					
						commit
						74cd37666e
					
				@ -1,5 +1,5 @@
 | 
				
			|||||||
[package]
 | 
					[package]
 | 
				
			||||||
name = "chess-uci"
 | 
					name = "chess_uci"
 | 
				
			||||||
version = "0.1.0"
 | 
					version = "0.1.0"
 | 
				
			||||||
edition = "2021"
 | 
					edition = "2021"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -8,3 +8,4 @@ edition = "2021"
 | 
				
			|||||||
[dependencies]
 | 
					[dependencies]
 | 
				
			||||||
chess = "3.2.0"
 | 
					chess = "3.2.0"
 | 
				
			||||||
itertools = "0.10.5"
 | 
					itertools = "0.10.5"
 | 
				
			||||||
 | 
					log = "0.4.17"
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										195
									
								
								src/lib.rs
									
									
									
									
									
								
							
							
						
						
									
										195
									
								
								src/lib.rs
									
									
									
									
									
								
							@ -1,80 +1,51 @@
 | 
				
			|||||||
#![allow(dead_code)]
 | 
					#![allow(dead_code)]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Manage UCI messages and link into chess component
 | 
					/// Manage UCI messages and link into chess component
 | 
				
			||||||
pub mod uci_engine {
 | 
					mod uci_command;
 | 
				
			||||||
    use itertools::join;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    mod chess_move {
 | 
					use log::warn;
 | 
				
			||||||
        pub struct Move {}
 | 
					use std::io::*;
 | 
				
			||||||
    }
 | 
					use crate::uci_command::*;
 | 
				
			||||||
    mod chess_info{
 | 
					
 | 
				
			||||||
        pub struct Info {}
 | 
					pub struct UciEngine<Fi: Read, Fo: Write> {
 | 
				
			||||||
    }
 | 
					    source: Fi,
 | 
				
			||||||
    mod chess_option{
 | 
					    destination: Fo,
 | 
				
			||||||
        pub struct Opt{}
 | 
					    uciok: bool,
 | 
				
			||||||
 | 
					    id: Id,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl<Fi: Read, Fo:  Write> UciEngine<Fi, Fo> {
 | 
				
			||||||
 | 
					    pub fn new(source: Fi, destination: Fo) -> UciEngine<Fi, Fo> {
 | 
				
			||||||
 | 
					        UciEngine::<Fi, Fo>{
 | 
				
			||||||
 | 
					            source, destination,
 | 
				
			||||||
 | 
					            id: Id::new(), 
 | 
				
			||||||
 | 
					            uciok: false}
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pub struct UciEngine {
 | 
					    pub fn name(&self) -> Option<String> {
 | 
				
			||||||
        name: String,
 | 
					        self.id.name()
 | 
				
			||||||
        author: String,
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    impl UciEngine {
 | 
					    pub fn author(&self) -> Option<String> {
 | 
				
			||||||
        pub fn new(name: &str, author: &str) -> UciEngine {
 | 
					        self.id.author()
 | 
				
			||||||
            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>}
 | 
					    pub fn update(&mut self, id: &Id){
 | 
				
			||||||
    impl Id {
 | 
					        if self.is_uciok() {warn!("Engine info should not be updated now (uciok)");}
 | 
				
			||||||
        pub fn new(name: Option<&str>, author: Option<&str>) -> Id {
 | 
					        self.id.update(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_from_str(&mut self, name: Option<&str>, author: Option<&str>){
 | 
				
			||||||
            }
 | 
					        if self.is_uciok() {warn!("Engine info should not be updated now (uciok)");}
 | 
				
			||||||
        }
 | 
					        self.id.update_from_str(name, author);
 | 
				
			||||||
        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 {
 | 
					    pub fn uciok(&mut self){
 | 
				
			||||||
        Id{id: Id},
 | 
					        self.uciok = true;
 | 
				
			||||||
        UciOk,
 | 
					    }
 | 
				
			||||||
        ReadyOk,
 | 
					
 | 
				
			||||||
        BestMove{best_move: chess_move::Move, ponder: chess_move::Move},
 | 
					    pub fn is_uciok(&self) -> bool {
 | 
				
			||||||
        CopyProtection, // unimplemented
 | 
					        self.uciok
 | 
				
			||||||
        Registration, // unimplemented
 | 
					 | 
				
			||||||
        Info{infos: Vec<chess_info::Info>},
 | 
					 | 
				
			||||||
        Opt{options: Vec<chess_option::Opt>},
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Parse UCI commands
 | 
					    /// Parse UCI commands
 | 
				
			||||||
@ -90,68 +61,50 @@ pub mod uci_engine {
 | 
				
			|||||||
    ///     e.g. "id author Stefan MK\n"
 | 
					    ///     e.g. "id author Stefan MK\n"
 | 
				
			||||||
    ///
 | 
					    ///
 | 
				
			||||||
    /// ```rust
 | 
					    /// ```rust
 | 
				
			||||||
    /// use chess_uci::uci_engine::{parse, UciCommand, Id, UciEngine};
 | 
					    /// use chess_uci::*;
 | 
				
			||||||
    /// let mut engine = UciEngine::new("Test", "Bat");
 | 
					    /// use std::io;
 | 
				
			||||||
 | 
					    /// let mut engine = UciEngine::new(io::empty(), io::sink());
 | 
				
			||||||
    ///
 | 
					    ///
 | 
				
			||||||
    /// engine.exec(&parse(&mut "id name Baptiste".to_string()).expect("simple id name command"));
 | 
					    /// engine.exec("id name Baptiste");
 | 
				
			||||||
    /// assert_eq!(engine.name(), "Baptiste");
 | 
					    /// assert_eq!(engine.name().expect(""), "Baptiste");
 | 
				
			||||||
    ///
 | 
					    ///
 | 
				
			||||||
    /// engine.exec(&parse(&mut "id author   Monique       Jouve".to_string()).expect("simple id author command"));
 | 
					    /// engine.exec("id author   Monique       Jouve");
 | 
				
			||||||
    /// assert_eq!(engine.author(), "Monique Jouve");
 | 
					    /// assert_eq!(engine.author().expect(""), "Monique Jouve");
 | 
				
			||||||
    ///
 | 
					    ///
 | 
				
			||||||
    /// ```
 | 
					    /// ```
 | 
				
			||||||
    pub fn parse(message: &mut String) -> Result<UciCommand,&'static str> {
 | 
					    ///
 | 
				
			||||||
        let mut message_iter = message.split_whitespace();
 | 
					    /// * uciok
 | 
				
			||||||
 | 
					    ///
 | 
				
			||||||
        match message_iter.next() {
 | 
					    ///    Must be sent after the id and optional options to tell the GUI that the engine
 | 
				
			||||||
            None => Err("No command provided"),
 | 
					    ///    has sent all infos and is ready in uci mode.
 | 
				
			||||||
 | 
					    ///
 | 
				
			||||||
            Some("id") =>
 | 
					    /// ```rust
 | 
				
			||||||
                match message_iter.collect::<Vec<&str>>().as_slice() {
 | 
					    /// use chess_uci::*;
 | 
				
			||||||
                    [] => Err("Empty id command"),
 | 
					    /// use std::io;
 | 
				
			||||||
                    ["name"] => Err("Empty id name command"),
 | 
					    /// let mut engine = UciEngine::new(io::empty(), io::sink());
 | 
				
			||||||
                    ["author"] => Err("Empty id author command"),
 | 
					    /// assert_eq!(engine.is_uciok(), false);
 | 
				
			||||||
                    ["name", tail @ ..] => Ok(UciCommand::Id{id: Id::new(Some(&join(tail, " ")), None)}),
 | 
					    ///
 | 
				
			||||||
                    ["author", tail @ ..] => Ok(UciCommand::Id{id: Id::new(None, Some(&join(tail, " ")))}),
 | 
					    /// engine.exec("id name Baptiste");
 | 
				
			||||||
                    _ => Err("Invalid id subcommand")
 | 
					    /// assert_eq!(engine.name().expect(""), "Baptiste");
 | 
				
			||||||
                },
 | 
					    /// assert_eq!(engine.is_uciok(), false);
 | 
				
			||||||
            Some("uciok") => unimplemented!(),
 | 
					    ///
 | 
				
			||||||
            Some("readyok") => unimplemented!(),
 | 
					    /// engine.exec("id author   Monique       Jouve");
 | 
				
			||||||
            Some("bestmove") => unimplemented!(),
 | 
					    /// assert_eq!(engine.author().expect(""), "Monique Jouve");
 | 
				
			||||||
            Some("copyprotection") => unimplemented!(),
 | 
					    /// assert_eq!(engine.is_uciok(), false);
 | 
				
			||||||
            Some("registration") => unimplemented!(),
 | 
					    ///
 | 
				
			||||||
            Some("info") => unimplemented!(),
 | 
					    /// engine.exec("   uciok");
 | 
				
			||||||
            Some("option") => unimplemented!(),
 | 
					    /// assert_eq!(engine.is_uciok(), true);
 | 
				
			||||||
            Some(_) => Err("Unknown command provided"),
 | 
					    /// ```
 | 
				
			||||||
 | 
					    pub fn exec(&mut self, command: &str){
 | 
				
			||||||
 | 
					        match parse (&mut command.to_string()) {
 | 
				
			||||||
 | 
					            Ok(EngineCommand::Id{id}) => self.update(&id),
 | 
				
			||||||
 | 
					            Ok(EngineCommand::UciOk) => self.uciok(),
 | 
				
			||||||
 | 
					            Ok(_) => {unimplemented!("command not implemented")},
 | 
				
			||||||
 | 
					            Err(_) => warn!("Not a command"),
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    impl UciEngine {
 | 
					    pub fn next(&mut self) {
 | 
				
			||||||
        pub fn exec(&mut self, command: &UciCommand){
 | 
					        exec(self.source.read_line());
 | 
				
			||||||
            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");
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										97
									
								
								src/uci_command.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										97
									
								
								src/uci_command.rs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,97 @@
 | 
				
			|||||||
 | 
					use itertools::join;
 | 
				
			||||||
 | 
					use std::time::Duration;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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()
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					pub struct Move {}
 | 
				
			||||||
 | 
					pub struct Info {}
 | 
				
			||||||
 | 
					pub struct Opt{}
 | 
				
			||||||
 | 
					pub struct Position{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub enum EngineCommand {
 | 
				
			||||||
 | 
					    Id{id: Id},
 | 
				
			||||||
 | 
					    UciOk,
 | 
				
			||||||
 | 
					    ReadyOk,
 | 
				
			||||||
 | 
					    BestMove{best_move: Move, ponder: Move},
 | 
				
			||||||
 | 
					    CopyProtection, // unimplemented
 | 
				
			||||||
 | 
					    Registration, // unimplemented
 | 
				
			||||||
 | 
					    Info{infos: Vec<Info>},
 | 
				
			||||||
 | 
					    Opt{options: Vec<Opt>},
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub enum GuiCommand {
 | 
				
			||||||
 | 
					    Uci,
 | 
				
			||||||
 | 
					    Debug{mode: bool},
 | 
				
			||||||
 | 
					    IsReady,
 | 
				
			||||||
 | 
					    SetOption{option: Opt},
 | 
				
			||||||
 | 
					    Register, // unimplemented
 | 
				
			||||||
 | 
					    UciNewGame,
 | 
				
			||||||
 | 
					    Position{position: Option<Position>, moves: Vec<Move>},
 | 
				
			||||||
 | 
					    Go,
 | 
				
			||||||
 | 
					    SearchMoves{moves: Vec<Move>},
 | 
				
			||||||
 | 
					    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") => unimplemented!(),
 | 
				
			||||||
 | 
					        Some(_) => Err("Unknown command provided"),
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user