From 6093b7973371e206885d0a389547dd19e3808e81 Mon Sep 17 00:00:00 2001 From: DkeRee Date: Tue, 3 May 2022 17:59:18 -0700 Subject: [PATCH] Fixed PV and move parsing for UCI display bugs. Reorganized some sections of code --- src/eval/eval_info.rs | 26 +++--- src/eval/evaluator.rs | 40 ++++----- src/movegen/movegen.rs | 17 ++++ src/search/search_master.rs | 171 +++++++++++++++++------------------ src/uci/castle_parse.rs | 60 +++++++++++++ src/uci/mod.rs | 3 +- src/uci/uci.rs | 173 ++++++++++++++++++------------------ 7 files changed, 285 insertions(+), 205 deletions(-) create mode 100644 src/uci/castle_parse.rs diff --git a/src/eval/eval_info.rs b/src/eval/eval_info.rs index dc1db4e..15ceb99 100644 --- a/src/eval/eval_info.rs +++ b/src/eval/eval_info.rs @@ -1,17 +1,23 @@ #![allow(dead_code)] #![allow(non_upper_case_globals)] -pub const square_display: [&str; 64] = [ - "a1", "b1", "c1", "d1", "e1", "f1", "g1", "h1", - "a2", "b2", "c2", "d2", "e2", "f2", "g2", "h2", - "a3", "b3", "c3", "d3", "e3", "f3", "g3", "h3", - "a4", "b4", "c4", "d4", "e4", "f4", "g4", "h4", - "a5", "b5", "c5", "d5", "e5", "f5", "g5", "h5", - "a6", "b6", "c6", "d6", "e6", "f6", "g6", "h6", - "a7", "b7", "c7", "d7", "e7", "f7", "g7", "h7", - "a8", "b8", "c8", "d8", "e8", "f8", "g8", "h8" -]; +//PIECE WEIGHTS +pub const pawn_normal: i32 = 126; +pub const pawn_endgame: i32 = 208; + +pub const knight_normal: i32 = 781; +pub const knight_endgame: i32 = 854; + +pub const bishop_normal: i32 = 825; +pub const bishop_endgame: i32 = 915; + +pub const rook_normal: i32 = 1276; +pub const rook_endgame: i32 = 1380; + +pub const queen_normal: i32 = 2538; +pub const queen_endgame: i32 = 2682; +//now replaced with see swap algorithm pub const MVV_LVA: [u32; 49] = [ 0, 0, 0, 0, 0, 0, 0, // victim K, attacker K, Q, R, B, N, P, None 50, 51, 52, 53, 54, 55, 0, // victim Q, attacker K, Q, R, B, N, P, None diff --git a/src/eval/evaluator.rs b/src/eval/evaluator.rs index 64e4e18..9e695a1 100644 --- a/src/eval/evaluator.rs +++ b/src/eval/evaluator.rs @@ -36,9 +36,9 @@ impl Evaluator { Piece::Pawn => { let mut weight = 0; if self.end_game { - weight = 208; + weight = pawn_endgame; } else { - weight = 126; + weight = pawn_normal; } piece_sum = weight; @@ -52,9 +52,9 @@ impl Evaluator { Piece::Knight => { let mut weight = 0; if self.end_game { - weight = 854; + weight = knight_endgame; } else { - weight = 781; + weight = knight_normal; } piece_sum = weight; @@ -68,9 +68,9 @@ impl Evaluator { Piece::Bishop => { let mut weight = 0; if self.end_game { - weight = 915; + weight = bishop_endgame; } else { - weight = 825; + weight = bishop_normal; } piece_sum = weight; @@ -84,9 +84,9 @@ impl Evaluator { Piece::Rook => { let mut weight = 0; if self.end_game { - weight = 1380; + weight = rook_endgame; } else { - weight = 1276; + weight = rook_normal; } piece_sum = weight; @@ -100,9 +100,9 @@ impl Evaluator { Piece::Queen => { let mut weight = 0; if self.end_game { - weight = 2682; + weight = queen_endgame; } else { - weight = 2538; + weight = queen_normal; } piece_sum = weight; @@ -143,9 +143,9 @@ impl Evaluator { Piece::Pawn => { let mut weight = 0; if self.end_game { - weight = 208; + weight = pawn_endgame; } else { - weight = 126; + weight = pawn_normal; } piece_sum = weight; @@ -159,9 +159,9 @@ impl Evaluator { Piece::Knight => { let mut weight = 0; if self.end_game { - weight = 854; + weight = knight_endgame; } else { - weight = 781; + weight = knight_normal; } piece_sum = weight; @@ -175,9 +175,9 @@ impl Evaluator { Piece::Bishop => { let mut weight = 0; if self.end_game { - weight = 915; + weight = bishop_endgame; } else { - weight = 825; + weight = bishop_normal; } piece_sum = weight; @@ -191,9 +191,9 @@ impl Evaluator { Piece::Rook => { let mut weight = 0; if self.end_game { - weight = 1380; + weight = rook_endgame; } else { - weight = 1276; + weight = rook_normal; } piece_sum = weight; @@ -207,9 +207,9 @@ impl Evaluator { Piece::Queen => { let mut weight = 0; if self.end_game { - weight = 2682; + weight = queen_endgame; } else { - weight = 2538; + weight = queen_normal; } piece_sum = weight; diff --git a/src/movegen/movegen.rs b/src/movegen/movegen.rs index 5803c8b..4f685e6 100644 --- a/src/movegen/movegen.rs +++ b/src/movegen/movegen.rs @@ -8,6 +8,13 @@ pub struct SortedMove { pub movetype: MoveType } +#[derive(Clone, Debug, PartialEq)] +pub struct Eval { + pub score: i32, + pub mate: bool, + pub mate_ply: usize +} + //mvv_lva MVV_LVA[(self.piece_index(moves.piece) * 7) + self.piece_index(piece)] impl SortedMove { @@ -20,6 +27,16 @@ impl SortedMove { } } +impl Eval { + pub fn new(score: i32, mate: bool, mate_ply: usize) -> Eval { + Eval { + score: score, + mate: mate, + mate_ply: mate_ply + } + } +} + pub struct MoveGen { sorter: MoveSorter } diff --git a/src/search/search_master.rs b/src/search/search_master.rs index 8bd357b..8d609f0 100644 --- a/src/search/search_master.rs +++ b/src/search/search_master.rs @@ -1,7 +1,3 @@ -#![allow(unused_variables)] -#![allow(unused_assignments)] -#![allow(unused_mut)] - use cozy_chess::*; use std::thread; @@ -12,13 +8,12 @@ use std::time::{Instant, Duration}; use crate::eval::evaluator::*; use crate::search::tt::*; use crate::movegen::movegen::*; +use crate::uci::castle_parse::*; pub struct Engine { pub board: Board, pub max_depth: i32, pub my_past_positions: Vec, - pub wtime: i64, - pub btime: i64, searching_depth: i32, nodes: u64, pv: [[Option; 100]; 100], @@ -33,8 +28,6 @@ impl Engine { board: Board::default(), max_depth: 0, my_past_positions: Vec::with_capacity(64), - wtime: 300000, - btime: 300000, searching_depth: 0, nodes: 0, pv: [[None; 100]; 100], @@ -44,30 +37,34 @@ impl Engine { } } - pub fn go(&mut self, max_depth: i32, wtime: i64, btime: i64, stop_abort: Arc) -> String { + pub fn go(&mut self, max_depth: i32, wtime: i64, btime: i64, winc: i64, binc: i64, movestogo: i64, stop_abort: Arc) -> String { let now = Instant::now(); let mut best_move = None; let mut time: f32; + let mut timeinc: f32; self.max_depth = max_depth; - self.wtime = wtime; - self.btime = btime; self.nodes = 0; - if self.board.side_to_move() == Color::White { - time = self.wtime as f32; - } else { - time = self.btime as f32; + //set time + match self.board.side_to_move() { + Color::White => { + time = wtime as f32; + timeinc = winc as f32; + }, + Color::Black => { + time = btime as f32; + timeinc = binc as f32; + } } for depth_index in 0..self.max_depth { let search_elapsed = now.elapsed().as_secs_f32() * 1000_f32; - if search_elapsed < time / 50_f32 { + if search_elapsed < ((time + timeinc) / f32::min(40_f32, movestogo as f32)) { self.searching_depth = depth_index + 1; - let search_time = Instant::now(); let board = &mut self.board.clone(); //set up pv table @@ -91,6 +88,7 @@ impl Engine { let elapsed = now.elapsed().as_secs_f32() * 1000_f32; + //get nps let mut nps: u64; if elapsed == 0_f32 { nps = self.nodes; @@ -98,15 +96,46 @@ impl Engine { nps = ((self.nodes as f32 * 1000_f32) / elapsed) as u64; } + //get pv let mut pv = String::new(); + let pv_board = &mut self.board.clone(); for i in 0..self.pv[0].len() { if self.pv[0][i] != None { - pv += &(self.parse_to_uci(self.pv[0][i]) + " "); + let pv_parsed = _960_to_regular_(self.pv[0][i], pv_board); + + pv += &(pv_parsed.clone() + " "); + + let mut uci_mv = String::new(); + let pv_mv = self.pv[0][i].unwrap(); + + let from = pv_mv.from.to_string(); + let to = pv_mv.to.to_string(); + + uci_mv += &from; + uci_mv += &to; + + if pv_mv.promotion != None { + uci_mv += &pv_mv.promotion.unwrap().to_string(); + } + + pv_board.play(uci_mv.parse().unwrap()); } } - println!("info depth {} nodes {} pv {} score cp {} nps {}", self.searching_depth, self.nodes, pv.trim(), eval, nps); + let mut score_str = if eval.mate { + let mut mate_score = if eval.score > 0 { + (eval.mate_ply - (eval.mate_ply / 2)) as i32 + } else { + (eval.mate_ply - (eval.mate_ply / 2)) as i32 * -1 + }; + + format!("mate {}", mate_score) + } else { + format!("cp {}", eval.score) + }; + + println!("info depth {} nodes {} pv {} score {} nps {}", self.searching_depth, self.nodes, pv.trim(), score_str, nps); } else { break; } @@ -144,41 +173,7 @@ impl Engine { self.evaluator.end_game = true; } - self.parse_to_uci(best_move) - } - - fn parse_to_uci(&self, mv: Option) -> String { - let mv_parsed = mv.unwrap(); - - let from = mv_parsed.from.to_string(); - let to = mv_parsed.to.to_string(); - - let square: Square = from.parse().unwrap(); - - if from == "e1" && (to == "a1" || to == "h1") && self.board.piece_on(square).unwrap() == Piece::King { - if to == "a1" { - return String::from("e1c1"); - } else { - return String::from("e1g1"); - } - } else if from == "e8" && (to == "a8" || to == "h8") && self.board.piece_on(square).unwrap() == Piece::King { - if to == "a8" { - return String::from("e8c8"); - } else { - return String::from("e8g8"); - } - } else { - let mut uci_mv = String::new(); - - uci_mv += &from; - uci_mv += &to; - - if mv_parsed.promotion != None { - uci_mv += &mv_parsed.promotion.unwrap().to_string(); - } - - return uci_mv; - } + _960_to_regular_(best_move, &self.board) } fn is_repetition(&self, board: &Board, past_positions: &mut Vec) -> bool { @@ -203,41 +198,42 @@ impl Engine { fn get_piece_amount(&self, piece_type: BitBoard) -> usize { let mut piece_amount = 0; - for piece in piece_type { + for _piece in piece_type { piece_amount += 1; } piece_amount } - fn qsearch(&mut self, abort: &AtomicBool, stop_abort: &AtomicBool, board: &Board, mut alpha: i32, beta: i32, mut ply: i32, past_positions: &mut Vec) -> Option<(Option, i32)> { + fn qsearch(&mut self, abort: &AtomicBool, stop_abort: &AtomicBool, board: &Board, mut alpha: i32, beta: i32, mut ply: i32, past_positions: &mut Vec) -> Option<(Option, Eval)> { //abort? if self.searching_depth > 1 && (abort.load(Ordering::Relaxed) || stop_abort.load(Ordering::Relaxed)) { return None; } self.nodes += 1; + self.pv[ply as usize] = [None; 100]; ply += 1; match board.status() { - GameStatus::Won => return Some((None, -30000 + ply)), - GameStatus::Drawn => return Some((None, 0)), + GameStatus::Won => return Some((None, Eval::new(-30000 + ply, true, ply as usize))), + GameStatus::Drawn => return Some((None, Eval::new(0, false, 0))), GameStatus::Ongoing => {} } //check for three move repetition if self.is_repetition(board, past_positions) { - return Some((None, 0)); + return Some((None, Eval::new(0, false, 0))); } - let stand_pat = self.evaluator.evaluate(board); + let stand_pat = Eval::new(self.evaluator.evaluate(board), false, 0); //beta cutoff - if stand_pat >= beta { - return Some((None, beta)); + if stand_pat.score >= beta { + return Some((None, Eval::new(beta, false, 0))); } - if alpha < stand_pat { - alpha = stand_pat; + if alpha < stand_pat.score { + alpha = stand_pat.score; } let move_list = self.movegen.qmove_gen(board); @@ -248,7 +244,7 @@ impl Engine { } let mut best_move = None; - let mut eval = i32::MIN; + let mut eval = Eval::new(i32::MIN, false, 0); for sm in move_list { let mv = sm.mv; @@ -261,35 +257,36 @@ impl Engine { past_positions.pop(); - child_eval *= -1; - if child_eval > eval { + child_eval.score *= -1; + if child_eval.score > eval.score { eval = child_eval; best_move = Some(mv); - if eval > alpha { + if eval.score > alpha { self.update_pv(best_move, ply as usize); - alpha = eval; + alpha = eval.score; if alpha >= beta { - return Some((None, beta)); + return Some((None, Eval::new(beta, false , 0))); } } } } - return Some((best_move, alpha)); + return Some((best_move, eval)); } - fn search(&mut self, abort: &AtomicBool, stop_abort: &AtomicBool, board: &Board, depth: i32, mut alpha: i32, beta: i32, past_positions: &mut Vec) -> Option<(Option, i32)> { + fn search(&mut self, abort: &AtomicBool, stop_abort: &AtomicBool, board: &Board, depth: i32, mut alpha: i32, beta: i32, past_positions: &mut Vec) -> Option<(Option, Eval)> { //abort? if self.searching_depth > 1 && (abort.load(Ordering::Relaxed) || stop_abort.load(Ordering::Relaxed)) { return None; } self.nodes += 1; + self.pv[(self.searching_depth - depth) as usize] = [None; 100]; let mut legal_moves: Vec; match board.status() { - GameStatus::Won => return Some((None, -30000 + (self.searching_depth - depth))), - GameStatus::Drawn => return Some((None, 0)), + GameStatus::Won => return Some((None, Eval::new(-30000 + (self.searching_depth - depth), true, (self.searching_depth - depth) as usize))), + GameStatus::Drawn => return Some((None, Eval::new(0, false, 0))), GameStatus::Ongoing => {} } @@ -300,16 +297,16 @@ impl Engine { if table_find.depth >= depth && alpha == beta - 1 { match table_find.node_kind { NodeKind::Exact => { - return Some((table_find.best_move, table_find.eval)); + return Some((table_find.best_move, Eval::new(table_find.eval, false, 0))); }, NodeKind::UpperBound => { if table_find.eval <= alpha { - return Some((table_find.best_move, table_find.eval)); + return Some((table_find.best_move, Eval::new(table_find.eval, false, 0))); } }, NodeKind::LowerBound => { if table_find.eval >= beta { - return Some((table_find.best_move, table_find.eval)); + return Some((table_find.best_move, Eval::new(table_find.eval, false, 0))); } }, NodeKind::Null => {} @@ -331,7 +328,7 @@ impl Engine { if depth <= Self::MAX_DEPTH_RFP && board.checkers() == BitBoard::EMPTY && alpha == beta - 1 { let eval = self.evaluator.evaluate(board); if eval - (Self::MULTIPLIER_RFP * depth) >= beta { - return Some((None, eval)); + return Some((None, Eval::new(eval, false, 0))); } } @@ -341,11 +338,11 @@ impl Engine { //check for three move repetition if self.is_repetition(board, past_positions) && self.searching_depth - depth > 0 { - return Some((None, 0)); + return Some((None, Eval::new(0, false, 0))); } let mut best_move = None; - let mut eval = i32::MIN; + let mut eval = Eval::new(i32::MIN, false, 0); for sm in legal_moves { let mv = sm.mv; let mut board_cache = board.clone(); @@ -357,21 +354,21 @@ impl Engine { past_positions.pop(); - child_eval *= -1; - if child_eval > eval { + child_eval.score *= -1; + if child_eval.score > eval.score { eval = child_eval; best_move = Some(mv); - if eval > alpha { + if eval.score > alpha { self.update_pv(best_move, (self.searching_depth - depth) as usize); - alpha = eval; + alpha = eval.score; if alpha >= beta { - self.tt.insert(best_move, eval, board.hash(), self.searching_depth, depth, NodeKind::LowerBound); + self.tt.insert(best_move, eval.score, board.hash(), self.searching_depth, depth, NodeKind::LowerBound); break; } else { - self.tt.insert(best_move, eval, board.hash(), self.searching_depth, depth, NodeKind::Exact); + self.tt.insert(best_move, eval.score, board.hash(), self.searching_depth, depth, NodeKind::Exact); } } else { - self.tt.insert(best_move, eval, board.hash(), self.searching_depth, depth, NodeKind::UpperBound); + self.tt.insert(best_move, eval.score, board.hash(), self.searching_depth, depth, NodeKind::UpperBound); } } } diff --git a/src/uci/castle_parse.rs b/src/uci/castle_parse.rs new file mode 100644 index 0000000..cdd0abe --- /dev/null +++ b/src/uci/castle_parse.rs @@ -0,0 +1,60 @@ +use cozy_chess::*; + +pub fn _regular_to_960_(mv_string: String, board: &Board) -> String { + let mv = &*mv_string; + + let from = mv.chars().nth(0).unwrap().to_string() + &mv.chars().nth(1).unwrap().to_string(); + let to = mv.chars().nth(2).unwrap().to_string() + &mv.chars().nth(3).unwrap().to_string(); + + let square: Square = from.parse().unwrap(); + + if from == "e1" && (to == "c1" || to == "g1") && board.piece_on(square).unwrap() == Piece::King { + if to == "c1" { + return String::from("e1a1"); + } else { + return String::from("e1h1"); + } + } else if from == "e8" && (to == "c8" || to == "g8") && board.piece_on(square).unwrap() == Piece::King { + if to == "c8" { + return String::from("e8a8"); + } else { + return String::from("e8h8"); + } + } else { + return mv_string; + } +} + +pub fn _960_to_regular_(mv: Option, board: &Board) -> String { + let mv_parsed = mv.unwrap(); + + let from = mv_parsed.from.to_string(); + let to = mv_parsed.to.to_string(); + + let square: Square = from.parse().unwrap(); + + if from == "e1" && (to == "a1" || to == "h1") && board.piece_on(square).unwrap() == Piece::King { + if to == "a1" { + return String::from("e1c1"); + } else { + return String::from("e1g1"); + } + } else if from == "e8" && (to == "a8" || to == "h8") && board.piece_on(square).unwrap() == Piece::King { + if to == "a8" { + return String::from("e8c8"); + } else { + return String::from("e8g8"); + } + } else { + let mut uci_mv = String::new(); + + uci_mv += &from; + uci_mv += &to; + + if mv_parsed.promotion != None { + uci_mv += &mv_parsed.promotion.unwrap().to_string(); + } + + return uci_mv; + } +} \ No newline at end of file diff --git a/src/uci/mod.rs b/src/uci/mod.rs index ad3d338..36ec580 100644 --- a/src/uci/mod.rs +++ b/src/uci/mod.rs @@ -1 +1,2 @@ -pub mod uci; \ No newline at end of file +pub mod uci; +pub mod castle_parse; \ No newline at end of file diff --git a/src/uci/uci.rs b/src/uci/uci.rs index c0dd18f..cf76150 100644 --- a/src/uci/uci.rs +++ b/src/uci/uci.rs @@ -7,12 +7,13 @@ use std::sync::mpsc::Receiver; use std::thread; use crate::search::search_master::*; +use crate::uci::castle_parse::*; enum UCICmd { Uci, UciNewGame, IsReady, - Go(i32, i64, i64, Arc), + Go(i32, i64, i64, i64, i64, i64, Arc), PositionFen(String), PositionPgn(Vec, bool), Quit @@ -27,7 +28,7 @@ fn get_channel() -> (Sender, Arc>>) { pub struct UCIMaster { pub playing: bool, engine_thread: Option>, - stop_abort: Option>, + stop_abort: Arc, channel: (Sender, Arc>>) } @@ -42,7 +43,7 @@ impl UCIMaster { UCIMaster { playing: true, engine_thread: None, - stop_abort: None, + stop_abort: Arc::new(AtomicBool::new(false)), channel: get_channel() } } @@ -55,78 +56,61 @@ impl UCIMaster { match cmd_vec[0] { "uci" => { - let thread_receiver = receiver.clone(); - - self.engine_thread = Some(thread::spawn(move || { - let mut engine = Engine::new(); - let mut playing = true; - - loop { - if playing { - match thread_receiver.lock().unwrap().recv().unwrap() { - UCICmd::Uci => { - println!("id name Trinket 1.0.0"); - println!("id author DkeRee"); - println!("uciok"); - }, - UCICmd::UciNewGame => { - engine = Engine::new(); - }, - UCICmd::IsReady => { - println!("readyok"); - }, - UCICmd::Go(depth, wtime, btime, stop_abort) => { - let best_move = engine.go(depth, wtime, btime, stop_abort); - println!("bestmove {}", best_move); - }, - UCICmd::PositionFen(fen) => { - engine.board = Board::from_fen(&*fen, false).unwrap(); - - engine.my_past_positions = Vec::with_capacity(64); - engine.my_past_positions.push(engine.board.hash()); - }, - UCICmd::PositionPgn(pgn_vec, default) => { - if default { - engine.board = Board::default(); - engine.my_past_positions = Vec::with_capacity(64); - } - for i in 0..pgn_vec.len() { - let mv = &*pgn_vec[i]; - - let from = mv.chars().nth(0).unwrap().to_string() + &mv.chars().nth(1).unwrap().to_string(); - let to = mv.chars().nth(2).unwrap().to_string() + &mv.chars().nth(3).unwrap().to_string(); - - let square: Square = from.parse().unwrap(); - - if from == "e1" && (to == "c1" || to == "g1") && engine.board.piece_on(square).unwrap() == Piece::King { - if to == "c1" { - engine.board.play("e1a1".parse().unwrap()); - } else { - engine.board.play("e1h1".parse().unwrap()); - } - } else if from == "e8" && (to == "c8" || to == "g8") && engine.board.piece_on(square).unwrap() == Piece::King { - if to == "c8" { - engine.board.play("e8a8".parse().unwrap()); - } else { - engine.board.play("e8h8".parse().unwrap()); - } - } else { - engine.board.play(mv.parse().unwrap()); - } + //init engine + if self.engine_thread.is_none() { + let thread_receiver = receiver.clone(); + + self.engine_thread = Some(thread::spawn(move || { + let mut engine = Engine::new(); + let mut playing = true; + + loop { + if playing { + match thread_receiver.lock().unwrap().recv().unwrap() { + UCICmd::Uci => { + println!("id name Trinket 1.0.0"); + println!("id author DkeRee"); + println!("uciok"); + }, + UCICmd::UciNewGame => { + engine = Engine::new(); + }, + UCICmd::IsReady => { + println!("readyok"); + }, + UCICmd::Go(depth, wtime, btime, winc, binc, movestogo, stop_abort) => { + let best_move = engine.go(depth, wtime, btime, winc, binc, movestogo, stop_abort); + println!("bestmove {}", best_move); + }, + UCICmd::PositionFen(fen) => { + engine.board = Board::from_fen(&*fen, false).unwrap(); + engine.my_past_positions = Vec::with_capacity(64); engine.my_past_positions.push(engine.board.hash()); + }, + UCICmd::PositionPgn(pgn_vec, default) => { + if default { + engine.board = Board::default(); + engine.my_past_positions = Vec::with_capacity(64); + } + + for i in 0..pgn_vec.len() { + engine.board.play_unchecked(_regular_to_960_(pgn_vec[i].clone(), &engine.board).parse().unwrap()); + engine.my_past_positions.push(engine.board.hash()); + } + }, + UCICmd::Quit => { + playing = false; } - }, - UCICmd::Quit => { - playing = false; } + } else { + break; } - } else { - break; } - } - })); + })); + } + sender.send(UCICmd::Uci).unwrap(); }, "ucinewgame" => { @@ -136,29 +120,44 @@ impl UCIMaster { sender.send(UCICmd::IsReady).unwrap(); }, "go" => { - self.stop_abort = Some(Arc::new(AtomicBool::new(false))); + self.stop_abort = Arc::new(AtomicBool::new(false)); let mut depth = i32::MAX; - let mut wtime: i64 = 300000; - let mut btime: i64 = 300000; - - if cmd_vec.len() > 1 { - if cmd_vec[1] == "wtime" { - //specified time - wtime = cmd_vec[2].parse::().unwrap(); - btime = cmd_vec[4].parse::().unwrap(); - } else if cmd_vec[1] == "depth" { - //specified depth without time - depth = cmd_vec[2].parse::().unwrap(); - } - - if cmd_vec.len() > 7 && cmd_vec[7] == "depth" { - //specified depth with time - depth = cmd_vec[8].parse::().unwrap(); + let mut wtime: i64 = i64::MAX; + let mut btime: i64 = i64::MAX; + let mut winc: i64 = 0; + let mut binc: i64 = 0; + let mut movestogo: i64 = i64::MAX; + + for i in 1..cmd_vec.len() { + match cmd_vec[i] { + "depth" => { + depth = cmd_vec[i + 1].parse::().unwrap(); + }, + "movetime" => { + wtime = cmd_vec[i + 1].parse::().unwrap(); + btime = cmd_vec[i + 1].parse::().unwrap(); + }, + "wtime" => { + wtime = cmd_vec[i + 1].parse::().unwrap(); + }, + "btime" => { + btime = cmd_vec[i + 1].parse::().unwrap(); + }, + "winc" => { + winc = cmd_vec[i + 1].parse::().unwrap(); + }, + "binc" => { + binc = cmd_vec[i + 1].parse::().unwrap(); + }, + "movestogo" => { + movestogo = cmd_vec[i + 1].parse::().unwrap(); + }, + _ => {} } } - sender.send(UCICmd::Go(depth, wtime, btime, self.stop_abort.clone().unwrap())).unwrap(); + sender.send(UCICmd::Go(depth, wtime, btime, winc, binc, movestogo, self.stop_abort.clone())).unwrap(); }, "position" => { if cmd_vec[1] == "startpos" { @@ -195,7 +194,7 @@ impl UCIMaster { } }, "stop" => { - self.stop_abort.as_ref().unwrap().store(true, Ordering::Relaxed); + self.stop_abort.as_ref().store(true, Ordering::Relaxed); }, "quit" => { sender.send(UCICmd::Quit).unwrap();