From 478ed3511a098f649371b7ff6280b302f5f74e21 Mon Sep 17 00:00:00 2001 From: stefiosif Date: Sun, 2 Mar 2025 01:11:29 +0200 Subject: [PATCH] Use labels to break from outer loop, group tunable constants --- src/search/iterative_deepening.rs | 28 ++++++++++++---------------- src/search/mod.rs | 11 +++++++++++ src/search/negamax.rs | 22 +++++++++++----------- 3 files changed, 34 insertions(+), 27 deletions(-) diff --git a/src/search/iterative_deepening.rs b/src/search/iterative_deepening.rs index 4c90205..6f443b6 100644 --- a/src/search/iterative_deepening.rs +++ b/src/search/iterative_deepening.rs @@ -5,7 +5,10 @@ use crate::{ movegen::r#move::Move, }; -use super::{negamax, time::TimeInfo}; +use super::{ + negamax, time::TimeInfo, ASPIRATION_WINDOW_DEPTH_THRESHOLD, ASPIRATION_WINDOW_EXPANSION, + ASPIRATION_WINDOW_INITIAL, +}; pub fn iterative_deepening( game: &mut Game, @@ -15,51 +18,44 @@ pub fn iterative_deepening( let mut best_move = None; let mut best_score = MIN_SCORE; - for depth in 1..=max_depth { + 'iterative_deepening: for depth in 1..=max_depth { if time.exceed_soft_limit() { println!("Soft limit exceeded in negamax"); return Ok(best_move); } let mut nodes = 0; - let mut score; - if depth < 4 { + if depth < ASPIRATION_WINDOW_DEPTH_THRESHOLD { score = negamax::negamax(game, MIN_SCORE, MAX_SCORE, depth, 0, time, &mut nodes, true); } else { - let mut window_size = 20; + let mut window_size = ASPIRATION_WINDOW_INITIAL; let mut alpha = (best_score - window_size).max(MIN_SCORE); let mut beta = (best_score + window_size).min(MAX_SCORE); - let mut break_from_aw = true; - loop { + 'aspiration_windows: loop { score = negamax::negamax(game, alpha, beta, depth, 0, time, &mut nodes, true); let score = match score { Ok(score) => score, Err(ref e) => { println!("Error: {}", Response::Info(e.to_string())); - break_from_aw = false; - break; + break 'iterative_deepening; } }; if score >= beta { beta = MAX_SCORE.min(beta.saturating_add(window_size)); - window_size = window_size.saturating_mul(2); + window_size = window_size.saturating_mul(ASPIRATION_WINDOW_EXPANSION); } else if score <= alpha { alpha = MIN_SCORE.max(alpha.saturating_sub(window_size)); - window_size = window_size.saturating_mul(2); + window_size = window_size.saturating_mul(ASPIRATION_WINDOW_EXPANSION); } else { best_score = score; - break; + break 'aspiration_windows; } } - - if !break_from_aw { - break; - } } if let Err(e) = score { diff --git a/src/search/mod.rs b/src/search/mod.rs index 81a96a4..55114fb 100644 --- a/src/search/mod.rs +++ b/src/search/mod.rs @@ -13,3 +13,14 @@ pub const HARD_LIMIT_DIVISION: u128 = 3; pub const SOFT_LIMIT_DIVISION: u128 = 20; pub const TT_SIZE_IN_MB: usize = 64; pub const MAX_HISTORY: i16 = 8192; +pub const ASPIRATION_WINDOW_INITIAL: i16 = 20; +pub const ASPIRATION_WINDOW_DEPTH_THRESHOLD: u8 = 4; +pub const ASPIRATION_WINDOW_EXPANSION: i16 = 2; +pub const LMR_DEPTH_THRESHOLD: u8 = 2; +pub const LMR_MOVE_COUNT_THRESHOLD: u8 = 3; +pub const LMR_REDUCTION: u8 = 2; +pub const NMP_REDUCTION: u8 = 2; +pub const NMP_DEPTH_THRESHOLD: u8 = 2; +pub const RFP_DEPTH_LIMIT: u8 = 6; +pub const RFP_MARGIN: u8 = 75; +pub const CHECK_EXTENSION: u8 = 1; diff --git a/src/search/negamax.rs b/src/search/negamax.rs index 9db3450..b3e1343 100644 --- a/src/search/negamax.rs +++ b/src/search/negamax.rs @@ -10,7 +10,8 @@ use super::{ quiescence::quiescence, time::TimeInfo, transposition_table::{NodeType, TTEntry}, - MAX_HISTORY, + CHECK_EXTENSION, LMR_DEPTH_THRESHOLD, LMR_MOVE_COUNT_THRESHOLD, LMR_REDUCTION, MAX_HISTORY, + NMP_DEPTH_THRESHOLD, NMP_REDUCTION, RFP_DEPTH_LIMIT, RFP_MARGIN, }; pub fn negamax( @@ -35,7 +36,7 @@ pub fn negamax( let in_check = game.board.king_under_check(color); if in_check { - depth += 1; + depth += CHECK_EXTENSION; } if depth == 0 { @@ -55,15 +56,13 @@ pub fn negamax( } } - const RFP_DEPTH: u8 = 5; - const RFP_MARGIN: u8 = 75; let eval = entry .map(|entry| entry.score) .unwrap_or_else(|| pesto().eval(game)); if !in_check && alpha == beta - 1 - && depth <= RFP_DEPTH + && depth < RFP_DEPTH_LIMIT && eval > beta && eval - (RFP_MARGIN * depth) as i16 > beta { @@ -73,7 +72,7 @@ pub fn negamax( if alpha == beta - 1 && plies != 0 && !in_check - && depth >= 3 + && depth > NMP_DEPTH_THRESHOLD && do_nmp && game.board.non_pawn_materials() > 0 { @@ -82,7 +81,7 @@ pub fn negamax( game, -beta, -beta + 1, - depth - 3, + depth - 1 - NMP_REDUCTION, plies + 1, time, nodes, @@ -124,10 +123,11 @@ pub fn negamax( let score = if legal_moves == 1 { -negamax(game, -beta, -alpha, depth - 1, plies + 1, time, nodes, true)? } else { - let mut lmr_reduction = 0; - if !in_check && !mv.is_capture() && depth > 2 && legal_moves > 3 { - lmr_reduction = 2; - } + #[rustfmt::skip] + let lmr_reduction = if !in_check + && !mv.is_capture() + && depth > LMR_DEPTH_THRESHOLD + && legal_moves > LMR_MOVE_COUNT_THRESHOLD { LMR_REDUCTION } else { 0 }; let mut score = -negamax( game,