iterative deepening
This commit is contained in:
parent
0c1055d7aa
commit
ecf1de6c6a
5 changed files with 77 additions and 9 deletions
Binary file not shown.
|
|
@ -29,7 +29,7 @@ fn main() {
|
||||||
let mut engine = Engine::new("Yakari".to_string(), "EiSiMo".to_string());
|
let mut engine = Engine::new("Yakari".to_string(), "EiSiMo".to_string());
|
||||||
|
|
||||||
// Set the time limit to 1 second
|
// Set the time limit to 1 second
|
||||||
let time_limit = Duration::from_secs(1);
|
let time_limit = Duration::from_millis(500);
|
||||||
|
|
||||||
for test in &sts {
|
for test in &sts {
|
||||||
let fen = &test[0];
|
let fen = &test[0];
|
||||||
|
|
@ -40,7 +40,7 @@ fn main() {
|
||||||
// Record start time
|
// Record start time
|
||||||
let start_time = Instant::now();
|
let start_time = Instant::now();
|
||||||
|
|
||||||
let result = engine.search(5);
|
let result = engine.search(490_u64);
|
||||||
|
|
||||||
// Calculate duration
|
// Calculate duration
|
||||||
let duration = start_time.elapsed();
|
let duration = start_time.elapsed();
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
// ... (your use statements)
|
|
||||||
use crate::board::Board;
|
use crate::board::Board;
|
||||||
use crate::r#move::Move;
|
use crate::r#move::Move;
|
||||||
use crate::search::alpha_beta::alpha_beta;
|
use crate::search::alpha_beta::alpha_beta;
|
||||||
|
use std::time::{Instant, Duration};
|
||||||
|
|
||||||
pub struct Engine {
|
pub struct Engine {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
|
|
@ -32,8 +32,51 @@ impl Engine {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn search(&mut self, depth: u8) -> String {
|
pub fn search(&mut self, time_limit_ms: u64) -> String {
|
||||||
let (opt_move, _score) = alpha_beta(&mut self.board, depth, 0, -i32::MAX, i32::MAX);
|
let start_time = Instant::now();
|
||||||
|
let time_limit = Duration::from_millis(time_limit_ms);
|
||||||
|
|
||||||
|
// We track nodes to limit how often we check the clock inside alpha_beta
|
||||||
|
let mut nodes = 0;
|
||||||
|
|
||||||
|
// Initial search at depth 1
|
||||||
|
let (mut opt_move, mut _score) = alpha_beta(
|
||||||
|
&mut self.board,
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
-i32::MAX,
|
||||||
|
i32::MAX,
|
||||||
|
start_time,
|
||||||
|
time_limit,
|
||||||
|
&mut nodes
|
||||||
|
);
|
||||||
|
|
||||||
|
let mut depth = 2;
|
||||||
|
|
||||||
|
// Iterative Deepening
|
||||||
|
while start_time.elapsed() < time_limit {
|
||||||
|
let (new_move, new_score) = alpha_beta(
|
||||||
|
&mut self.board,
|
||||||
|
depth,
|
||||||
|
0,
|
||||||
|
-i32::MAX,
|
||||||
|
i32::MAX,
|
||||||
|
start_time,
|
||||||
|
time_limit,
|
||||||
|
&mut nodes
|
||||||
|
);
|
||||||
|
|
||||||
|
// If time ran out during the search, alpha_beta returns garbage (None, 0).
|
||||||
|
// We must verify we still have time before accepting the new result.
|
||||||
|
if start_time.elapsed() > time_limit {
|
||||||
|
break; // Discard new_move, keep the one from the previous depth
|
||||||
|
}
|
||||||
|
|
||||||
|
opt_move = new_move;
|
||||||
|
_score = new_score;
|
||||||
|
|
||||||
|
depth += 1;
|
||||||
|
}
|
||||||
|
|
||||||
if let Some(mv) = opt_move {
|
if let Some(mv) = opt_move {
|
||||||
mv.to_algebraic()
|
mv.to_algebraic()
|
||||||
|
|
@ -42,4 +85,4 @@ impl Engine {
|
||||||
"null".to_string()
|
"null".to_string()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,9 @@
|
||||||
use crate::board::{Board, Color}; // <-- Assuming you have a Color enum (e.g., Color::White, Color::Black)
|
use crate::board::{Board, Color};
|
||||||
use crate::eval::basic::evaluate_board;
|
use crate::eval::basic::evaluate_board;
|
||||||
use crate::movegen::generate_pseudo_legal_moves;
|
use crate::movegen::generate_pseudo_legal_moves;
|
||||||
use crate::movegen::legal_check::*;
|
use crate::movegen::legal_check::*;
|
||||||
use crate::r#move::{Move, MoveList};
|
use crate::r#move::{Move, MoveList};
|
||||||
|
use std::time::{Instant, Duration};
|
||||||
|
|
||||||
// A score high enough to be > any material eval, but low enough to not overflow when adding ply
|
// A score high enough to be > any material eval, but low enough to not overflow when adding ply
|
||||||
const MATE_SCORE: i32 = 1_000_000;
|
const MATE_SCORE: i32 = 1_000_000;
|
||||||
|
|
@ -21,7 +22,20 @@ pub fn alpha_beta(
|
||||||
ply: u8,
|
ply: u8,
|
||||||
mut alpha: i32,
|
mut alpha: i32,
|
||||||
beta: i32,
|
beta: i32,
|
||||||
|
start_time: Instant,
|
||||||
|
time_limit: Duration,
|
||||||
|
nodes: &mut u64,
|
||||||
) -> (Option<Move>, i32) {
|
) -> (Option<Move>, i32) {
|
||||||
|
// Check for time usage every 4096 nodes to reduce system call overhead
|
||||||
|
if *nodes % 4096 == 0 {
|
||||||
|
if start_time.elapsed() > time_limit {
|
||||||
|
// Return immediately. The return value here effectively signals an abort,
|
||||||
|
// but the engine must discard this result.
|
||||||
|
return (None, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*nodes += 1;
|
||||||
|
|
||||||
if depth == 0 {
|
if depth == 0 {
|
||||||
return (None, evaluate_board_relative(board));
|
return (None, evaluate_board_relative(board));
|
||||||
}
|
}
|
||||||
|
|
@ -42,7 +56,18 @@ pub fn alpha_beta(
|
||||||
legal_moves_found = true;
|
legal_moves_found = true;
|
||||||
|
|
||||||
// Recursive call with negated and swapped alpha/beta
|
// Recursive call with negated and swapped alpha/beta
|
||||||
let (_, score) = alpha_beta(board, depth - 1, ply + 1, -beta, -alpha);
|
// Pass time parameters and node counter down
|
||||||
|
let (_, score) = alpha_beta(board, depth - 1, ply + 1, -beta, -alpha, start_time, time_limit, nodes);
|
||||||
|
|
||||||
|
// If we aborted deeper in the tree (returned 0 due to timeout),
|
||||||
|
// we should technically propagate that up, but checking elapsed()
|
||||||
|
// at the loop start (via recursion) handles it eventually.
|
||||||
|
// For a strict abort, we check here too:
|
||||||
|
if *nodes % 4096 == 0 && start_time.elapsed() > time_limit {
|
||||||
|
board.undo_move(undo_mv);
|
||||||
|
return (None, 0);
|
||||||
|
}
|
||||||
|
|
||||||
let current_score = -score;
|
let current_score = -score;
|
||||||
|
|
||||||
if current_score > best_score {
|
if current_score > best_score {
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,7 @@ pub fn uci_mainloop(engine: &mut Engine) {
|
||||||
}
|
}
|
||||||
"go" => {
|
"go" => {
|
||||||
// TODO add a lot functionality
|
// TODO add a lot functionality
|
||||||
println!("bestmove {}", engine.search(6));
|
println!("bestmove {}", engine.search(1000_u64));
|
||||||
}
|
}
|
||||||
"stop" => {
|
"stop" => {
|
||||||
// TODO stop search as soon as possible
|
// TODO stop search as soon as possible
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue