diff --git a/src/main.rs b/src/main.rs index 46824e5..e79da86 100644 --- a/src/main.rs +++ b/src/main.rs @@ -115,7 +115,7 @@ fn cmd_go(mut tokens: std::str::SplitWhitespace<'_>, state: &mut MainState) { // hard timeout let mut hard_ms = 15_000; // soft timeout - let mut soft_ms = 1_650; + let mut soft_ms = 1_200; macro_rules! set_time { () => { @@ -258,10 +258,11 @@ fn task_stdin_reader(tx_main: Sender) { /// The "Engine" thread that does all the computation. fn task_engine(tx_main: Sender, rx_engine: Receiver) { thread::spawn(move || { + let conf = SearchConfig::default(); let mut state = EngineState::new( - SearchConfig::default(), + conf, rx_engine, - TranspositionTable::new(0), + TranspositionTable::new(conf.transposition_size), TimeLimits::default(), ); diff --git a/src/search.rs b/src/search.rs index ffb0b42..6fd47d9 100644 --- a/src/search.rs +++ b/src/search.rs @@ -79,7 +79,7 @@ impl From for EvalInt { } } SearchEval::Centipawns(eval) => eval, - SearchEval::Stopped => 0, + SearchEval::Stopped => panic!("Attempted to evaluate a halted search"), } } } @@ -169,28 +169,30 @@ fn minmax( alpha: Option, beta: Option, ) -> (Vec, SearchEval) { - if false { - if state.node_count % 2048 == 1 { - // respect the hard stop if given - match state.rx_engine.try_recv() { - Ok(msg) => match msg { - MsgToEngine::Go(_) => panic!("received go while thinking"), - MsgToEngine::Stop => return (Vec::new(), SearchEval::Stopped), - MsgToEngine::NewGame => panic!("received newgame while thinking"), - }, - Err(e) => match e { - mpsc::TryRecvError::Empty => {} - mpsc::TryRecvError::Disconnected => panic!("thread Main stopped"), - }, - } - - if let Some(hard) = state.time_lims.hard { - if Instant::now() > hard { + // these operations are relatively expensive, so only run them occasionally + if state.node_count % ((1 << 31) - 1) == 0 { + // respect the hard stop if given + match state.rx_engine.try_recv() { + Ok(msg) => match msg { + MsgToEngine::Go(_) => panic!("received go while thinking"), + MsgToEngine::Stop => { return (Vec::new(), SearchEval::Stopped); } + MsgToEngine::NewGame => panic!("received newgame while thinking"), + }, + Err(e) => match e { + mpsc::TryRecvError::Empty => {} + mpsc::TryRecvError::Disconnected => panic!("thread Main stopped"), + }, + } + + if let Some(hard) = state.time_lims.hard { + if Instant::now() > hard { + return (Vec::new(), SearchEval::Stopped); } } } + state.node_count += 1; // default to worst, then gradually improve let mut alpha = alpha.unwrap_or(EVAL_WORST); @@ -278,8 +280,6 @@ fn minmax( } } - state.node_count += 1; - (best_continuation, abs_best) } @@ -297,39 +297,26 @@ pub type TranspositionTable = ZobristTable; /// Iteratively deepen search until it is stopped. fn iter_deep(board: &mut Board, state: &mut EngineState) -> (Vec, SearchEval) { - // keep two previous lines (in case current one is halted) - // 1 is the most recent - let (mut line1, mut eval1) = minmax(board, state, 1, None, None); - let (mut line2, mut eval2) = (line1.clone(), eval1); - - macro_rules! ret_best { - ($depth: expr) => { - if $depth & 1 == 1 && (EvalInt::from(eval1) - EvalInt::from(eval2) > 300) { - // be skeptical if we move last and we suddenly earn a lot of - // centipawns. this may be a sign of horizon problem - return (line2, eval2); - } else { - return (line1, eval1); - } - }; - } + let (mut prev_line, mut prev_eval) = minmax(board, state, 1, None, None); for depth in 2..=state.config.depth { let (line, eval) = minmax(board, state, depth, None, None); - if matches!(eval, SearchEval::Stopped) { - ret_best!(depth - 1) - } else { - (line2, eval2) = (line1, eval1); - (line1, eval1) = (line, eval); - } if let Some(soft_lim) = state.time_lims.soft { if Instant::now() > soft_lim { - ret_best!(depth) + if depth & 1 == 1 && (EvalInt::from(eval) - EvalInt::from(prev_eval) > 300) { + // be skeptical if we move last and we suddenly earn a lot of + // centipawns. this may be a sign of horizon problem + return (prev_line, prev_eval); + } else { + return (line, eval); + } } } + + (prev_line, prev_eval) = (line, eval); } - (line1, eval1) + (prev_line, prev_eval) } /// Deadlines for the engine to think of a move.