Use labels to break from outer loop, group tunable constants
This commit is contained in:
@@ -5,7 +5,10 @@ use crate::{
|
|||||||
movegen::r#move::Move,
|
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(
|
pub fn iterative_deepening(
|
||||||
game: &mut Game,
|
game: &mut Game,
|
||||||
@@ -15,51 +18,44 @@ pub fn iterative_deepening(
|
|||||||
let mut best_move = None;
|
let mut best_move = None;
|
||||||
let mut best_score = MIN_SCORE;
|
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() {
|
if time.exceed_soft_limit() {
|
||||||
println!("Soft limit exceeded in negamax");
|
println!("Soft limit exceeded in negamax");
|
||||||
return Ok(best_move);
|
return Ok(best_move);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut nodes = 0;
|
let mut nodes = 0;
|
||||||
|
|
||||||
let mut score;
|
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);
|
score = negamax::negamax(game, MIN_SCORE, MAX_SCORE, depth, 0, time, &mut nodes, true);
|
||||||
} else {
|
} 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 alpha = (best_score - window_size).max(MIN_SCORE);
|
||||||
let mut beta = (best_score + window_size).min(MAX_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);
|
score = negamax::negamax(game, alpha, beta, depth, 0, time, &mut nodes, true);
|
||||||
|
|
||||||
let score = match score {
|
let score = match score {
|
||||||
Ok(score) => score,
|
Ok(score) => score,
|
||||||
Err(ref e) => {
|
Err(ref e) => {
|
||||||
println!("Error: {}", Response::Info(e.to_string()));
|
println!("Error: {}", Response::Info(e.to_string()));
|
||||||
break_from_aw = false;
|
break 'iterative_deepening;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if score >= beta {
|
if score >= beta {
|
||||||
beta = MAX_SCORE.min(beta.saturating_add(window_size));
|
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 {
|
} else if score <= alpha {
|
||||||
alpha = MIN_SCORE.max(alpha.saturating_sub(window_size));
|
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 {
|
} else {
|
||||||
best_score = score;
|
best_score = score;
|
||||||
break;
|
break 'aspiration_windows;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !break_from_aw {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Err(e) = score {
|
if let Err(e) = score {
|
||||||
|
|||||||
@@ -13,3 +13,14 @@ pub const HARD_LIMIT_DIVISION: u128 = 3;
|
|||||||
pub const SOFT_LIMIT_DIVISION: u128 = 20;
|
pub const SOFT_LIMIT_DIVISION: u128 = 20;
|
||||||
pub const TT_SIZE_IN_MB: usize = 64;
|
pub const TT_SIZE_IN_MB: usize = 64;
|
||||||
pub const MAX_HISTORY: i16 = 8192;
|
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;
|
||||||
|
|||||||
@@ -10,7 +10,8 @@ use super::{
|
|||||||
quiescence::quiescence,
|
quiescence::quiescence,
|
||||||
time::TimeInfo,
|
time::TimeInfo,
|
||||||
transposition_table::{NodeType, TTEntry},
|
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(
|
pub fn negamax(
|
||||||
@@ -35,7 +36,7 @@ pub fn negamax(
|
|||||||
let in_check = game.board.king_under_check(color);
|
let in_check = game.board.king_under_check(color);
|
||||||
|
|
||||||
if in_check {
|
if in_check {
|
||||||
depth += 1;
|
depth += CHECK_EXTENSION;
|
||||||
}
|
}
|
||||||
|
|
||||||
if depth == 0 {
|
if depth == 0 {
|
||||||
@@ -55,15 +56,13 @@ pub fn negamax(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const RFP_DEPTH: u8 = 5;
|
|
||||||
const RFP_MARGIN: u8 = 75;
|
|
||||||
let eval = entry
|
let eval = entry
|
||||||
.map(|entry| entry.score)
|
.map(|entry| entry.score)
|
||||||
.unwrap_or_else(|| pesto().eval(game));
|
.unwrap_or_else(|| pesto().eval(game));
|
||||||
|
|
||||||
if !in_check
|
if !in_check
|
||||||
&& alpha == beta - 1
|
&& alpha == beta - 1
|
||||||
&& depth <= RFP_DEPTH
|
&& depth < RFP_DEPTH_LIMIT
|
||||||
&& eval > beta
|
&& eval > beta
|
||||||
&& eval - (RFP_MARGIN * depth) as i16 > beta
|
&& eval - (RFP_MARGIN * depth) as i16 > beta
|
||||||
{
|
{
|
||||||
@@ -73,7 +72,7 @@ pub fn negamax(
|
|||||||
if alpha == beta - 1
|
if alpha == beta - 1
|
||||||
&& plies != 0
|
&& plies != 0
|
||||||
&& !in_check
|
&& !in_check
|
||||||
&& depth >= 3
|
&& depth > NMP_DEPTH_THRESHOLD
|
||||||
&& do_nmp
|
&& do_nmp
|
||||||
&& game.board.non_pawn_materials() > 0
|
&& game.board.non_pawn_materials() > 0
|
||||||
{
|
{
|
||||||
@@ -82,7 +81,7 @@ pub fn negamax(
|
|||||||
game,
|
game,
|
||||||
-beta,
|
-beta,
|
||||||
-beta + 1,
|
-beta + 1,
|
||||||
depth - 3,
|
depth - 1 - NMP_REDUCTION,
|
||||||
plies + 1,
|
plies + 1,
|
||||||
time,
|
time,
|
||||||
nodes,
|
nodes,
|
||||||
@@ -124,10 +123,11 @@ pub fn negamax(
|
|||||||
let score = if legal_moves == 1 {
|
let score = if legal_moves == 1 {
|
||||||
-negamax(game, -beta, -alpha, depth - 1, plies + 1, time, nodes, true)?
|
-negamax(game, -beta, -alpha, depth - 1, plies + 1, time, nodes, true)?
|
||||||
} else {
|
} else {
|
||||||
let mut lmr_reduction = 0;
|
#[rustfmt::skip]
|
||||||
if !in_check && !mv.is_capture() && depth > 2 && legal_moves > 3 {
|
let lmr_reduction = if !in_check
|
||||||
lmr_reduction = 2;
|
&& !mv.is_capture()
|
||||||
}
|
&& depth > LMR_DEPTH_THRESHOLD
|
||||||
|
&& legal_moves > LMR_MOVE_COUNT_THRESHOLD { LMR_REDUCTION } else { 0 };
|
||||||
|
|
||||||
let mut score = -negamax(
|
let mut score = -negamax(
|
||||||
game,
|
game,
|
||||||
|
|||||||
Reference in New Issue
Block a user