implement go
This commit is contained in:
		
							parent
							
								
									a46ff43db4
								
							
						
					
					
						commit
						d68d7023e1
					
				| @ -6,10 +6,13 @@ pub mod uci_command; | ||||
| use log::{info, warn}; | ||||
| use std::io::*; | ||||
| use std::time::Duration; | ||||
| use std::result::Result; | ||||
| use crate::uci_command::*; | ||||
| 
 | ||||
| use chess::{Game, Board, ChessMove}; | ||||
| 
 | ||||
| const DEFAULT_TIME: (Option<Duration>, Option<Duration>) = (Some(Duration::from_secs(120 * 60)), None); | ||||
| 
 | ||||
| /// Structure used to manage a chess game with a uci engine.
 | ||||
| ///
 | ||||
| /// It needs a in / out communication channel to read / push line by line uci commands
 | ||||
| @ -40,9 +43,9 @@ pub struct UciEngine<Fi: Read, Fo: Write> { | ||||
|     initial: Board, | ||||
|     game: Game, | ||||
|     /// white (total, incr), black (total, incr)
 | ||||
|     time: ((Option<Duration>, Option<Duration>), (Option<Duration>, Option<Duration>)), | ||||
|     time: [(Option<Duration>, Option<Duration>); 2], | ||||
|     /// white, black
 | ||||
|     player: (Player, Player) | ||||
|     player: [Player; 2], | ||||
| } | ||||
| 
 | ||||
| pub enum UciOption { | ||||
| @ -74,26 +77,26 @@ impl<Fi: Read, Fo:  Write> UciEngine<Fi, Fo> { | ||||
|             uciok: false, | ||||
|             initial: Board::default(), | ||||
|             game: Game::new(), | ||||
|             time: ((None, None), (None, None)), | ||||
|             player: (Player::Human{elo: None}, Player::Human{elo: None}), | ||||
|             time: [DEFAULT_TIME; 2], | ||||
|             player: [Player::Human{elo: None}; 2], | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     pub fn game_option(&mut self, option: GameOption) -> GameOption { | ||||
|         let old_value: GameOption; | ||||
|         match option { | ||||
|             GameOption::WhiteTotalTime{value} => {old_value = GameOption::WhiteTotalTime { value: self.time.0.0 }; | ||||
|                                                   self.time.0.0 = value}, | ||||
|             GameOption::BlackTotalTime{value} => {old_value = GameOption::BlackTotalTime { value: self.time.1.0 }; | ||||
|                                                   self.time.1.0 = value}, | ||||
|             GameOption::WhiteIncrement{value} => {old_value = GameOption::WhiteIncrement { value: self.time.0.1 }; | ||||
|                                                   self.time.0.1 = value}, | ||||
|             GameOption::BlackIncrement{value} => {old_value = GameOption::BlackIncrement { value: self.time.1.1 }; | ||||
|                                                   self.time.1.1 = value}, | ||||
|             GameOption::WhitePlayer{value} => {old_value = GameOption::WhitePlayer { value: self.player.0 }; | ||||
|                                                self.player.0 = value}, | ||||
|             GameOption::BlackPlayer{value} => {old_value = GameOption::WhitePlayer { value: self.player.1 }; | ||||
|                                                self.player.1 = value}, | ||||
|             GameOption::WhiteTotalTime{value} => {old_value = GameOption::WhiteTotalTime { value: self.time[Color::White.to_index()].0 }; | ||||
|                                                   self.time[Color::White.to_index()].0 = value}, | ||||
|             GameOption::BlackTotalTime{value} => {old_value = GameOption::BlackTotalTime { value: self.time[Color::Black.to_index()].0 }; | ||||
|                                                   self.time[Color::Black.to_index()].0 = value}, | ||||
|             GameOption::WhiteIncrement{value} => {old_value = GameOption::WhiteIncrement { value: self.time[Color::White.to_index()].1 }; | ||||
|                                                   self.time[Color::White.to_index()].1 = value}, | ||||
|             GameOption::BlackIncrement{value} => {old_value = GameOption::BlackIncrement { value: self.time[Color::Black.to_index()].1 }; | ||||
|                                                   self.time[Color::Black.to_index()].1 = value}, | ||||
|             GameOption::WhitePlayer{value} => {old_value = GameOption::WhitePlayer { value: self.player[Color::White.to_index()] }; | ||||
|                                                self.player[Color::White.to_index()] = value}, | ||||
|             GameOption::BlackPlayer{value} => {old_value = GameOption::WhitePlayer { value: self.player[Color::Black.to_index()] }; | ||||
|                                                self.player[Color::Black.to_index()] = value}, | ||||
|         } | ||||
| 
 | ||||
|         old_value | ||||
| @ -172,20 +175,11 @@ impl<Fi: Read, Fo:  Write> UciEngine<Fi, Fo> { | ||||
|         self.id.update_from_str(name, author); | ||||
|     } | ||||
| 
 | ||||
|     fn uciok(&mut self){ | ||||
|         self.uciok = true; | ||||
|     } | ||||
| 
 | ||||
|     /// Tell whether the uci engine has initialized
 | ||||
|     pub fn is_uciok(&self) -> bool { | ||||
|         self.uciok | ||||
|     } | ||||
| 
 | ||||
|     /// Execute a uci command
 | ||||
|     ///
 | ||||
|     /// if `EngineCommand::Id`: update name or authorship of the engine
 | ||||
|     /// if `EngineCommand::UciOk`: end engine initialization phase
 | ||||
|     pub fn exec(&mut self, command: &str) -> std::result::Result<EngineCommand, &'static str> { | ||||
|     pub fn exec(&mut self, command: &str) -> Result<EngineCommand, &'static str> { | ||||
|         let uci_command = parse (&mut command.to_string()); | ||||
|         match  uci_command.clone() { | ||||
|             Ok(EngineCommand::Id{id}) => self.update(&id), | ||||
| @ -259,6 +253,52 @@ impl<Fi: Read, Fo:  Write> UciEngine<Fi, Fo> { | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl<Fi: Read, Fo:  Write> UciEngine<Fi, Fo> { | ||||
|     fn uciok(&mut self){ | ||||
|         self.uciok = true; | ||||
|     } | ||||
| 
 | ||||
|     /// Tell whether the uci engine has initialized
 | ||||
|     pub fn is_uciok(&self) -> bool { | ||||
|         self.uciok | ||||
|     } | ||||
| 
 | ||||
|     pub fn human_play(&mut self, chess_move: ChessMove) -> Result<ChessMove, &'static str> { | ||||
|         match self.player[self.side_to_move().to_index()] { | ||||
|             Player::Human{..} => { | ||||
|                 if self.make_move(chess_move) { | ||||
|                     Ok(chess_move) | ||||
|                 } else { | ||||
|                     Err("Invalid move for human player") | ||||
|                 } | ||||
|             }, | ||||
|             Player::Machine {..} => Err("Not a human to play for current color.") | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     pub fn go(&mut self) -> Result<(), &'static str> { | ||||
|         match self.player[self.side_to_move().to_index()] { | ||||
|             Player::Human{..} => Err("Not a machine to play for current color."), | ||||
|             Player::Machine {elo} => 
 | ||||
|             { | ||||
|                 if self.is_uciok() { | ||||
|                     if let Some(elo) = elo { | ||||
|                         self.push(GuiCommand::SetOption {option: Opt::UCILimitStrength{value: true}}); | ||||
|                         self.push(GuiCommand::SetOption {option: Opt::UCIElo{value: elo}}); | ||||
|                     } | ||||
|                     let (wtime, wincr) = self.time[Color::White.to_index()]; | ||||
|                     let (btime, bincr) = self.time[Color::Black.to_index()]; | ||||
|                     self.push(GuiCommand::Go{wtime, wincr, btime, bincr}); | ||||
| 
 | ||||
|                     Ok(()) | ||||
|                 } else { | ||||
|                     Err("UCI engine not ready")                    
 | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| use chess::{Square, Piece, Color}; | ||||
| impl<Fi: Read, Fo:  Write> UciEngine<Fi, Fo> { | ||||
|     pub fn piece_on(&self, square: Square) -> Option<Piece> { | ||||
| @ -271,5 +311,9 @@ impl<Fi: Read, Fo:  Write> UciEngine<Fi, Fo> { | ||||
|     pub fn current_position(&self) -> Board { | ||||
|         self.game.current_position() | ||||
|     } | ||||
| 
 | ||||
|     pub fn side_to_move(&self) -> Color { | ||||
|         self.game.side_to_move() | ||||
|     } | ||||
| } | ||||
| //  LocalWords:  uci
 | ||||
|  | ||||
| @ -34,7 +34,10 @@ impl Id { | ||||
| #[derive(Debug, Clone)] | ||||
| pub struct Info {} | ||||
| #[derive(Debug, Clone)] | ||||
| pub struct Opt{} | ||||
| pub enum Opt{ | ||||
|     UCILimitStrength{value: bool}, | ||||
|     UCIElo{value: u32}, | ||||
| } | ||||
| 
 | ||||
| #[derive(Clone)] | ||||
| pub enum EngineCommand { | ||||
| @ -58,7 +61,8 @@ pub enum GuiCommand { | ||||
|     Register, // unimplemented
 | ||||
|     UciNewGame, | ||||
|     Position{position: Option<Board>, moves: Vec<Action>}, | ||||
|     Go, | ||||
|     Go{wtime: Option<Duration>, wincr: Option<Duration>, | ||||
|        btime: Option<Duration>, bincr: Option<Duration>}, | ||||
|     SearchMoves{moves: Vec<ChessMove>}, | ||||
|     Ponder, | ||||
|     WTime{time: Duration}, | ||||
| @ -117,6 +121,20 @@ impl fmt::Display for GuiCommand { | ||||
|                                       {chessmove.to_string()} else {"".to_string()}), "") | ||||
|                 ) | ||||
|             } | ||||
|             GuiCommand::SetOption { option } => { | ||||
|                 match option { | ||||
|                     Opt::UCILimitStrength { value } => write!(f, "setoption name UCI_LimitStrength value {value}"), | ||||
|                     Opt::UCIElo { value } => write!(f,"setoption name UCI_Elo value {value}"), | ||||
|                 } | ||||
|             } | ||||
|             GuiCommand::Go { wtime, wincr, btime, bincr } => {    
 | ||||
|                 let wtime = if let Some(wtime) = wtime {format!(" wtime {}", wtime.as_millis())} else {"".to_string()}; | ||||
|                 let btime = if let Some(btime) = btime {format!(" btime {}", btime.as_millis())} else {"".to_string()}; | ||||
|                 let wincr = if let Some(wincr) = wincr {format!(" wincr {}", wincr.as_millis())} else {"".to_string()}; | ||||
|                 let bincr = if let Some(bincr) = bincr {format!(" bincr {}", bincr.as_millis())} else {"".to_string()}; | ||||
|                 write!(f, "go{}{}{}{}", wtime, btime, wincr, bincr) | ||||
|             } | ||||
|             
 | ||||
|             a => unimplemented!("{:?}", a), | ||||
|         } | ||||
| 
 | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Baptiste Fouques
						Baptiste Fouques