Use TT to store best move after each ID iteration

This commit is contained in:
stefiosif
2025-01-18 17:44:27 +02:00
parent 824f8a37b5
commit 1c7100f510
4 changed files with 19 additions and 51 deletions

View File

@@ -22,7 +22,7 @@ pub fn iterative_deepening(
return Ok(best_move); return Ok(best_move);
} }
let search_result = negamax::negamax( let score = negamax::negamax(
game, game,
MIN_SCORE, MIN_SCORE,
MAX_SCORE, MAX_SCORE,
@@ -31,22 +31,13 @@ pub fn iterative_deepening(
&TimeInfo::new(time, remaining_time), &TimeInfo::new(time, remaining_time),
); );
if let Ok(search_result) = search_result { if score.is_err() {
if search_result.best_move.is_some() { break;
best_move = search_result.best_move;
}
best_score = search_result.best_score;
} else {
return Ok(best_move);
} }
best_score = score?;
best_move = game.tt.lookup(game.hash).and_then(|entry| entry.mv);
} }
// tt.lookup(game.hash).map(|entry| {
// if entry.mv.is_some() {
// best_move = entry.mv;
// }
// });
Ok(best_move) Ok(best_move)
} }

View File

@@ -1,5 +1,3 @@
use crate::movegen::r#move::Move;
pub mod iterative_deepening; pub mod iterative_deepening;
pub mod move_ordering; pub mod move_ordering;
pub mod negamax; pub mod negamax;
@@ -14,17 +12,3 @@ pub const HARD_LIMIT_DIVISION: u128 = 10; // % of the remaining time
pub const SOFT_LIMIT_DIVISION: u128 = HARD_LIMIT_DIVISION / 2; pub const SOFT_LIMIT_DIVISION: u128 = HARD_LIMIT_DIVISION / 2;
pub const SOFT_EVAL_THRESHOLD: i32 = 500; pub const SOFT_EVAL_THRESHOLD: i32 = 500;
pub const MAX_TT_SIZE: u64 = 1000000; pub const MAX_TT_SIZE: u64 = 1000000;
pub struct SearchResult {
pub best_move: Option<Move>,
pub best_score: i32,
}
impl SearchResult {
pub const fn new(best_move: Option<Move>, best_score: i32) -> Self {
Self {
best_move,
best_score,
}
}
}

View File

@@ -10,7 +10,6 @@ use super::{
quiescence::quiescence, quiescence::quiescence,
time::{hard_limit, TimeInfo}, time::{hard_limit, TimeInfo},
transposition_table::TTEntry, transposition_table::TTEntry,
SearchResult,
}; };
pub fn negamax( pub fn negamax(
@@ -20,14 +19,14 @@ pub fn negamax(
depth: u8, depth: u8,
plies: u8, plies: u8,
time_info: &TimeInfo, time_info: &TimeInfo,
) -> Result<SearchResult> { ) -> Result<i32> {
if hard_limit(&time_info.time, time_info.remaining_time_in_ms) { if hard_limit(&time_info.time, time_info.remaining_time_in_ms) {
bail!("Time is up! In Negamax"); bail!("Time is up! In Negamax");
} }
if depth == 0 { if depth == 0 {
let q_score = quiescence(game, alpha, beta, time_info).map_err(|e| anyhow!("{e}"))?; let q_score = quiescence(game, alpha, beta, time_info).map_err(|e| anyhow!("{e}"))?;
return Ok(SearchResult::new(None, q_score)); return Ok(q_score);
} }
let color = game.current_player(); let color = game.current_player();
@@ -49,7 +48,7 @@ pub fn negamax(
} }
legal_moves += 1; legal_moves += 1;
let score = -negamax(game, -beta, -alpha, depth - 1, plies + 1, time_info)?.best_score; let score = -negamax(game, -beta, -alpha, depth - 1, plies + 1, time_info)?;
game.unmake_move(); game.unmake_move();
if score > best_score { if score > best_score {
@@ -70,13 +69,13 @@ pub fn negamax(
if legal_moves == 0 { if legal_moves == 0 {
if game.board.king_under_check(color) { if game.board.king_under_check(color) {
return Ok(SearchResult::new(None, mate_score)); return Ok(mate_score);
} }
return Ok(SearchResult::new(None, 0)); return Ok(0);
} }
game.tt.insert(TTEntry::new(game.hash, best_move)); game.tt.insert(TTEntry::new(game.hash, best_move));
Ok(SearchResult::new(best_move, best_score)) Ok(best_score)
} }
#[cfg(test)] #[cfg(test)]
@@ -100,22 +99,18 @@ mod tests {
let e3f2 = Move::new(Square::E3, Square::F2); let e3f2 = Move::new(Square::E3, Square::F2);
let time_info = TimeInfo::new(std::time::Instant::now(), 1000); let time_info = TimeInfo::new(std::time::Instant::now(), 1000);
let anointed_move = negamax(&mut game, MIN_SCORE, MAX_SCORE, 2, 0, &time_info) negamax(&mut game, MIN_SCORE, MAX_SCORE, 2, 0, &time_info)
.expect("Expected a search result") .expect("Expected a search result");
.best_move
.expect("Expected a move");
assert_eq!(e3f2, anointed_move); assert_eq!(e3f2, game.tt.lookup(game.hash).unwrap().mv.unwrap());
let mut game = from_fen(FEN_MATE_IN_1[1]).unwrap(); let mut game = from_fen(FEN_MATE_IN_1[1]).unwrap();
let e3f2 = Move::new(Square::E3, Square::F2); let e3f2 = Move::new(Square::E3, Square::F2);
let anointed_move = negamax(&mut game, MIN_SCORE, MAX_SCORE, 2, 0, &time_info) negamax(&mut game, MIN_SCORE, MAX_SCORE, 2, 0, &time_info)
.expect("Expected a search result") .expect("Expected a search result");
.best_move
.expect("Expected a move");
assert_eq!(e3f2, anointed_move); assert_eq!(e3f2, game.tt.lookup(game.hash).unwrap().mv.unwrap());
Ok(()) Ok(())
} }

View File

@@ -61,9 +61,7 @@ mod tests {
let time_info = TimeInfo::new(std::time::Instant::now(), 30000); let time_info = TimeInfo::new(std::time::Instant::now(), 30000);
negamax(&mut game, MIN_SCORE, MAX_SCORE, 2, 0, &time_info) negamax(&mut game, MIN_SCORE, MAX_SCORE, 2, 0, &time_info)
.expect("Expected a search result") .expect("Expected a search result");
.best_move
.expect("Expected a move");
dbg!(time_info.time.elapsed()); dbg!(time_info.time.elapsed());