diff --git a/src/search/pvs.rs b/src/search/pvs.rs index d258f338..c9bccb13 100644 --- a/src/search/pvs.rs +++ b/src/search/pvs.rs @@ -165,17 +165,28 @@ fn pvs( history: &mut BranchHistory, ply: Depth, ) -> (ValueScore, usize) { + // Max depth reached; search for quiet position + if depth == 0 { + return quiesce(position, alpha, beta, constraint, ply); + } + + // Time limit reached + if constraint.should_stop_search() { + return (alpha, 1); + } + + // Detect history-related draws let repeated_times = history.repeated(position); let twofold_repetition = repeated_times >= 2; let threefold_repetition = repeated_times >= 3; - - // Detect history-related draws if position.halfmove_clock >= 100 || threefold_repetition { return (0, 1); } - // Get known score from transposition table - if !twofold_repetition { + // Get known score from transposition table. + // We disable this in the root node, as we want to explore all moves nevertheless. + // Also, in case of a twofold repetition, this score may not hold due to possible threefold repetitions. + if !ROOT && !twofold_repetition { if let Some((score, score_type)) = table.get_table_score(position, depth, ply) { match score_type { ScoreType::Exact => return (score, 1), @@ -190,16 +201,6 @@ fn pvs( } } - // Time limit reached - if constraint.should_stop_search() { - return (alpha, 1); - } - - // Max depth reached; search for quiet position - if depth == 0 { - return quiesce(position, alpha, beta, constraint, ply); - } - // We count each move on the board as 1 node. let mut count = 1; @@ -371,47 +372,47 @@ pub fn pvs_aspiration( ); all_count += count; - if !constraint.should_stop_search() { - // Search failed low; increase lower bound and try again - if score <= lower_bound { - lower_bound = std::cmp::max( - ValueScore::MIN + 1, - lower_bound.saturating_sub(WINDOW_SIZE.saturating_mul(cof)), - ); - continue; - } + // Searched failed as result of outside order: this is not valid. + if constraint.should_stop_search() { + return None; + } - // Search failed high; increase upper bound and try again - if score >= upper_bound { - upper_bound = upper_bound.saturating_add(WINDOW_SIZE.saturating_mul(cof)); - continue; - } + // Search failed low; increase lower bound and try again + if score <= lower_bound { + lower_bound = std::cmp::max( + ValueScore::MIN + 1, + lower_bound.saturating_sub(WINDOW_SIZE.saturating_mul(cof)), + ); + continue; + } - // Our score is valid, so other threads can stop gracefully. - if MAIN_THREAD { - constraint.signal_root_finished(); - } + // Search failed high; increase upper bound and try again + if score >= upper_bound { + upper_bound = upper_bound.saturating_add(WINDOW_SIZE.saturating_mul(cof)); + continue; + } - return Some(if Score::is_mate(score) { - let plys_to_mate = (MATE_SCORE.abs() - score.abs()) as u8; - ( - Score::Mate( - if score > 0 { - position.side_to_move - } else { - position.side_to_move.opposite() - }, - (plys_to_mate + 1) / 2, - ), - all_count, - ) - } else { - (Score::Value(score), all_count) - }); + // Our score is valid, so other threads can stop gracefully. + if MAIN_THREAD { + constraint.signal_root_finished(); } - // Search stopped as an outside order, so this is not a valid result. - return None; + return Some(if Score::is_mate(score) { + let plys_to_mate = (MATE_SCORE.abs() - score.abs()) as u8; + ( + Score::Mate( + if score > 0 { + position.side_to_move + } else { + position.side_to_move.opposite() + }, + (plys_to_mate + 1) / 2, + ), + all_count, + ) + } else { + (Score::Value(score), all_count) + }); } unreachable!() diff --git a/src/search/table.rs b/src/search/table.rs index f5d9929e..199202dd 100644 --- a/src/search/table.rs +++ b/src/search/table.rs @@ -20,8 +20,6 @@ pub const DEFAULT_TABLE_SIZE_MB: usize = 64; const NULL_KILLER: u16 = u16::MAX; const NULL_TT_ENTRY: u64 = u64::MAX; -const AGE_INCREASE_FREQUENCY: usize = 5; - #[derive(Clone, Copy, Debug, PartialEq)] pub enum ScoreType { Exact = 0, @@ -93,17 +91,12 @@ impl TableEntry { struct TranspositionTable { data: Vec, age: bool, - search_counter: usize, } impl TranspositionTable { pub fn new(size_mb: usize) -> Self { let data_len = Self::calculate_data_len(size_mb); - Self { - data: (0..data_len).map(|_| AtomicU64::new(NULL_TT_ENTRY)).collect(), - age: false, - search_counter: 0, - } + Self { data: (0..data_len).map(|_| AtomicU64::new(NULL_TT_ENTRY)).collect(), age: false } } fn calculate_data_len(size_mb: usize) -> usize { @@ -177,10 +170,7 @@ impl SearchTable { pub fn prepare_for_new_search(&self) { let mut tt = self.transposition.write().unwrap(); - tt.search_counter += 1; - if tt.search_counter % AGE_INCREASE_FREQUENCY == 0 { - tt.age = !tt.age; - } + tt.age = !tt.age; } pub fn set_size(&self, size_mb: usize) {