Use increment from uci winc/binc in time management
This commit is contained in:
@@ -1,7 +1,6 @@
|
|||||||
use std::{
|
use std::{
|
||||||
io::{BufRead, Write},
|
io::{BufRead, Write},
|
||||||
str::SplitWhitespace,
|
str::SplitWhitespace,
|
||||||
time::Instant,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use anyhow::{anyhow, bail};
|
use anyhow::{anyhow, bail};
|
||||||
@@ -13,8 +12,8 @@ use crate::{
|
|||||||
},
|
},
|
||||||
movegen::r#move::Move,
|
movegen::r#move::Move,
|
||||||
search::{
|
search::{
|
||||||
iterative_deepening, transposition_table::TranspositionTable, MAX_DEPTH, MAX_TT_SIZE,
|
iterative_deepening, time::TimeInfo, transposition_table::TranspositionTable, INC,
|
||||||
REMAINING_TIME_DEFAULT,
|
MAX_DEPTH, MAX_TT_SIZE, TIME,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -70,28 +69,26 @@ impl fmt::Display for Response {
|
|||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct UciParameters {
|
struct UciParameters {
|
||||||
movetime: Option<usize>,
|
|
||||||
depth: Option<u8>,
|
depth: Option<u8>,
|
||||||
game: Option<Game>,
|
game: Option<Game>,
|
||||||
wtime: Option<u128>,
|
wtime: Option<u128>,
|
||||||
btime: Option<u128>,
|
btime: Option<u128>,
|
||||||
|
winc: Option<u128>,
|
||||||
|
binc: Option<u128>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl UciParameters {
|
impl UciParameters {
|
||||||
const fn new() -> Self {
|
const fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
movetime: None,
|
|
||||||
depth: None,
|
depth: None,
|
||||||
game: None,
|
game: None,
|
||||||
wtime: None,
|
wtime: None,
|
||||||
btime: None,
|
btime: None,
|
||||||
|
winc: None,
|
||||||
|
binc: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_movetime(&mut self, movetime: usize) {
|
|
||||||
self.movetime = Some(movetime);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn add_depth(&mut self, depth: u8) {
|
fn add_depth(&mut self, depth: u8) {
|
||||||
self.depth = Some(depth);
|
self.depth = Some(depth);
|
||||||
}
|
}
|
||||||
@@ -104,6 +101,14 @@ impl UciParameters {
|
|||||||
self.btime = Some(btime);
|
self.btime = Some(btime);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn add_winc(&mut self, winc: u128) {
|
||||||
|
self.winc = Some(winc);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn add_binc(&mut self, binc: u128) {
|
||||||
|
self.binc = Some(binc);
|
||||||
|
}
|
||||||
|
|
||||||
fn add_game(&mut self, game: Game) {
|
fn add_game(&mut self, game: Game) {
|
||||||
self.game = Some(game);
|
self.game = Some(game);
|
||||||
}
|
}
|
||||||
@@ -148,24 +153,24 @@ pub fn uci_go(go_iter: &mut SplitWhitespace, game: &mut Game) -> anyhow::Result<
|
|||||||
match subcommand {
|
match subcommand {
|
||||||
"wtime" => params.add_wtime(parse_next(go_iter, "wtime")?),
|
"wtime" => params.add_wtime(parse_next(go_iter, "wtime")?),
|
||||||
"btime" => params.add_btime(parse_next(go_iter, "btime")?),
|
"btime" => params.add_btime(parse_next(go_iter, "btime")?),
|
||||||
|
"winc" => params.add_winc(parse_next(go_iter, "winc")?),
|
||||||
|
"binc" => params.add_binc(parse_next(go_iter, "binc")?),
|
||||||
"depth" => params.add_depth(parse_next(go_iter, "depth")?),
|
"depth" => params.add_depth(parse_next(go_iter, "depth")?),
|
||||||
"movetime" => params.add_movetime(parse_next(go_iter, "movetime")?),
|
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let time = Instant::now();
|
let (time, inc) = match game.current_player() {
|
||||||
let remaining_time = match game.current_player() {
|
Color::White => (params.wtime.unwrap_or(TIME), params.winc.unwrap_or(INC)),
|
||||||
Color::White => params.wtime.unwrap_or(REMAINING_TIME_DEFAULT),
|
Color::Black => (params.btime.unwrap_or(TIME), params.binc.unwrap_or(INC)),
|
||||||
Color::Black => params.btime.unwrap_or(REMAINING_TIME_DEFAULT),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
iterative_deepening::iterative_deepening(game, MAX_DEPTH, remaining_time)?.ok_or_else(|| {
|
iterative_deepening::iterative_deepening(
|
||||||
anyhow!(
|
game,
|
||||||
"No stored best move found. Time: {}",
|
params.depth.unwrap_or(MAX_DEPTH),
|
||||||
remaining_time - time.elapsed().as_millis()
|
&TimeInfo::new(std::time::Instant::now(), time, inc),
|
||||||
)
|
)?
|
||||||
})
|
.ok_or_else(|| anyhow!("No stored best move found"))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_next<T: std::str::FromStr>(go_iter: &mut SplitWhitespace, val: &str) -> anyhow::Result<T> {
|
fn parse_next<T: std::str::FromStr>(go_iter: &mut SplitWhitespace, val: &str) -> anyhow::Result<T> {
|
||||||
@@ -295,7 +300,6 @@ mod tests {
|
|||||||
id author stefiosif\n\
|
id author stefiosif\n\
|
||||||
uciok\n\
|
uciok\n\
|
||||||
Clear cache\n\
|
Clear cache\n\
|
||||||
Initialized position\n\
|
|
||||||
bestmove e3f2\n";
|
bestmove e3f2\n";
|
||||||
let actual_response = String::from_utf8(output).expect("Invalid UTF-8 in output");
|
let actual_response = String::from_utf8(output).expect("Invalid UTF-8 in output");
|
||||||
|
|
||||||
@@ -303,30 +307,4 @@ mod tests {
|
|||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_cute_chess_bug() -> anyhow::Result<()> {
|
|
||||||
init_attacks();
|
|
||||||
let commands = "uci\n\
|
|
||||||
ucinewgame\n\
|
|
||||||
position startpos moves b1c3 g7g6 d2d4 f8g7 e2e4 f7f5 e4f5 e7e6 f5g6 h7g6 g1f3 b8c6 f1c4 d7d6 c1e3 e6e5 d4d5 c6e7 c3b5 c7c6 d5c6 b7c6 b5d6 d8d6 d1d6 c8d7 f3e5 d7e6 d6e6 g8f6 e5g6 f6g8 e6f7 e8d7 f7g7 g8f6 g7e7 d7c8 g6h8 c8b8 e7d8 b8b7 d8f6 b7c7 e3a7 a8a7 h8g6 c7b6 g6e5 a7c7 f6c6 b6a7
|
|
||||||
go\n\
|
|
||||||
quit";
|
|
||||||
let input = Cursor::new(commands);
|
|
||||||
let mut output: Vec<_> = vec![];
|
|
||||||
|
|
||||||
uci_loop(input, &mut output)?;
|
|
||||||
|
|
||||||
let expected_response = "id name zeal\n\
|
|
||||||
id author stefiosif\n\
|
|
||||||
uciok\n\
|
|
||||||
Clear cache\n\
|
|
||||||
Initialized position\n\
|
|
||||||
bestmove c6c7\n";
|
|
||||||
let actual_response = String::from_utf8(output).expect("Invalid UTF-8 in output");
|
|
||||||
|
|
||||||
assert_eq!(expected_response, actual_response);
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -59,9 +59,6 @@ impl fmt::Debug for Move {
|
|||||||
write!(f, "{promote_char}")?;
|
write!(f, "{promote_char}")?;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(debug_assertions)]
|
|
||||||
write!(f, ", debug_field: {:?}", self.move_type)?;
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,52 +9,38 @@ use crate::{
|
|||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
negamax,
|
negamax,
|
||||||
time::{soft_limit, TimeInfo},
|
time::{hard_limit, TimeInfo},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn iterative_deepening(
|
pub fn iterative_deepening(
|
||||||
game: &mut Game,
|
game: &mut Game,
|
||||||
max_depth: u8,
|
max_depth: u8,
|
||||||
remaining_time: u128,
|
time_info: &TimeInfo,
|
||||||
) -> anyhow::Result<Option<Move>> {
|
) -> anyhow::Result<Option<Move>> {
|
||||||
let (mut best_move, mut best_score) = (None, MIN_SCORE);
|
let mut best_move = None;
|
||||||
let time = std::time::Instant::now();
|
|
||||||
|
|
||||||
for depth in 1..=max_depth {
|
for depth in 1..=max_depth {
|
||||||
if soft_limit(&time, remaining_time, best_score) {
|
if hard_limit(time_info.instant, time_info.time, time_info.inc) {
|
||||||
return Ok(best_move);
|
return Ok(best_move);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut total_nodes_searched = 0;
|
let mut nodes = 0;
|
||||||
|
let score = negamax::negamax(game, MIN_SCORE, MAX_SCORE, depth, 0, time_info, &mut nodes);
|
||||||
let score = negamax::negamax(
|
|
||||||
game,
|
|
||||||
MIN_SCORE,
|
|
||||||
MAX_SCORE,
|
|
||||||
depth,
|
|
||||||
0,
|
|
||||||
&TimeInfo::new(time, remaining_time),
|
|
||||||
&mut total_nodes_searched,
|
|
||||||
);
|
|
||||||
|
|
||||||
if score.is_err() {
|
if score.is_err() {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
best_score = score?;
|
|
||||||
best_move = game.tt.lookup(game.hash).and_then(|entry| entry.mv);
|
best_move = game.tt.lookup(game.hash).and_then(|entry| entry.mv);
|
||||||
|
|
||||||
let nps = ((total_nodes_searched * 1_000_000) as u128).div_ceil(time.elapsed().as_micros())
|
|
||||||
as u64;
|
|
||||||
|
|
||||||
write_response(
|
write_response(
|
||||||
&mut io::stdout(),
|
&mut io::stdout(),
|
||||||
&search_info(
|
&log_depth_results(
|
||||||
depth,
|
depth,
|
||||||
time.elapsed().as_millis() as u64,
|
time_info.instant.elapsed().as_millis() as u64,
|
||||||
total_nodes_searched,
|
nodes,
|
||||||
nps,
|
time_info.nps(nodes),
|
||||||
best_score,
|
score?,
|
||||||
best_move,
|
best_move,
|
||||||
),
|
),
|
||||||
)?;
|
)?;
|
||||||
@@ -62,22 +48,22 @@ pub fn iterative_deepening(
|
|||||||
Ok(best_move)
|
Ok(best_move)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn search_info(
|
fn log_depth_results(
|
||||||
depth: u8,
|
depth: u8,
|
||||||
time: u64,
|
seconds: u64,
|
||||||
total_nodes_searched: u64,
|
nodes: u64,
|
||||||
nps: u64,
|
nps: u64,
|
||||||
best_score: i32,
|
best_score: i32,
|
||||||
best_move: Option<Move>,
|
best_move: Option<Move>,
|
||||||
) -> Response {
|
) -> Response {
|
||||||
Response::Info(format!(
|
Response::Info(format!(
|
||||||
"info depth {} time {} nodes {} nps {} eval {} pv {}",
|
"info depth {} seconds {} nodes {} nps {} eval {} bestmove {}",
|
||||||
depth,
|
depth,
|
||||||
time,
|
seconds,
|
||||||
total_nodes_searched,
|
nodes,
|
||||||
nps,
|
nps,
|
||||||
best_score,
|
best_score,
|
||||||
best_move.expect("msg: No best move found")
|
best_move.expect("No best move found")
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -86,7 +72,7 @@ mod tests {
|
|||||||
use crate::{
|
use crate::{
|
||||||
board::fen::from_fen,
|
board::fen::from_fen,
|
||||||
movegen::attack_generator::init_attacks,
|
movegen::attack_generator::init_attacks,
|
||||||
search::{iterative_deepening, MAX_DEPTH, REMAINING_TIME_DEFAULT},
|
search::{iterative_deepening, time::TimeInfo, INC, MAX_DEPTH, TIME},
|
||||||
};
|
};
|
||||||
|
|
||||||
const FEN: &str = "1r2k2r/2P1pq1p/2npb3/1p3ppP/p3P3/P2B1Q2/1P1PNPP1/R3K2R w KQk g6 0 1";
|
const FEN: &str = "1r2k2r/2P1pq1p/2npb3/1p3ppP/p3P3/P2B1Q2/1P1PNPP1/R3K2R w KQk g6 0 1";
|
||||||
@@ -95,11 +81,15 @@ mod tests {
|
|||||||
fn test_iterative_deepening() -> anyhow::Result<()> {
|
fn test_iterative_deepening() -> anyhow::Result<()> {
|
||||||
init_attacks();
|
init_attacks();
|
||||||
let mut game = from_fen(FEN).unwrap();
|
let mut game = from_fen(FEN).unwrap();
|
||||||
let time_now = std::time::Instant::now();
|
let instant = std::time::Instant::now();
|
||||||
|
|
||||||
iterative_deepening::iterative_deepening(&mut game, MAX_DEPTH, REMAINING_TIME_DEFAULT)?;
|
iterative_deepening::iterative_deepening(
|
||||||
|
&mut game,
|
||||||
|
MAX_DEPTH,
|
||||||
|
&TimeInfo::new(instant, TIME, INC),
|
||||||
|
)?;
|
||||||
|
|
||||||
dbg!(time_now.elapsed());
|
dbg!(instant.elapsed());
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,9 +6,9 @@ pub mod quiescence;
|
|||||||
pub mod time;
|
pub mod time;
|
||||||
pub mod transposition_table;
|
pub mod transposition_table;
|
||||||
|
|
||||||
pub const MAX_DEPTH: u8 = 7;
|
pub const MAX_DEPTH: u8 = 50;
|
||||||
pub const REMAINING_TIME_DEFAULT: u128 = 100000; // in ms
|
pub const TIME: u128 = 1000;
|
||||||
pub const HARD_LIMIT_DIVISION: u128 = 10; // % of the remaining time
|
pub const INC: u128 = 1000;
|
||||||
pub const SOFT_LIMIT_DIVISION: u128 = HARD_LIMIT_DIVISION / 2;
|
pub const HARD_LIMIT_DIVISION: u128 = 10;
|
||||||
pub const SOFT_EVAL_THRESHOLD: i32 = 500;
|
pub const SOFT_LIMIT_DIVISION: u128 = HARD_LIMIT_DIVISION * 2;
|
||||||
pub const MAX_TT_SIZE: u64 = 1000000;
|
pub const MAX_TT_SIZE: u64 = 1500000;
|
||||||
|
|||||||
@@ -19,9 +19,9 @@ pub fn negamax(
|
|||||||
depth: u8,
|
depth: u8,
|
||||||
plies: u8,
|
plies: u8,
|
||||||
time_info: &TimeInfo,
|
time_info: &TimeInfo,
|
||||||
total_nodes_searched: &mut u64,
|
nodes: &mut u64,
|
||||||
) -> Result<i32> {
|
) -> Result<i32> {
|
||||||
if hard_limit(&time_info.time, time_info.remaining_time_in_ms) {
|
if hard_limit(time_info.instant, time_info.time, time_info.inc) {
|
||||||
bail!("Time is up! In Negamax");
|
bail!("Time is up! In Negamax");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -30,8 +30,8 @@ pub fn negamax(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if depth == 0 {
|
if depth == 0 {
|
||||||
let q_score = quiescence(game, alpha, beta, time_info, total_nodes_searched)
|
let q_score =
|
||||||
.map_err(|e| anyhow!("{e}"))?;
|
quiescence(game, alpha, beta, time_info, nodes).map_err(|e| anyhow!("{e}"))?;
|
||||||
return Ok(q_score);
|
return Ok(q_score);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -52,18 +52,10 @@ pub fn negamax(
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
legal_moves += 1;
|
legal_moves += 1;
|
||||||
*total_nodes_searched += 1;
|
*nodes += 1;
|
||||||
|
|
||||||
let score = if legal_moves == 1 {
|
let score = if legal_moves == 1 {
|
||||||
-negamax(
|
-negamax(game, -beta, -alpha, depth - 1, plies + 1, time_info, nodes)?
|
||||||
game,
|
|
||||||
-beta,
|
|
||||||
-alpha,
|
|
||||||
depth - 1,
|
|
||||||
plies + 1,
|
|
||||||
time_info,
|
|
||||||
total_nodes_searched,
|
|
||||||
)?
|
|
||||||
} else {
|
} else {
|
||||||
let mut score = -negamax(
|
let mut score = -negamax(
|
||||||
game,
|
game,
|
||||||
@@ -72,18 +64,10 @@ pub fn negamax(
|
|||||||
depth - 1,
|
depth - 1,
|
||||||
plies + 1,
|
plies + 1,
|
||||||
time_info,
|
time_info,
|
||||||
total_nodes_searched,
|
nodes,
|
||||||
)?;
|
)?;
|
||||||
if score > alpha && score < beta {
|
if score > alpha && score < beta {
|
||||||
score = -negamax(
|
score = -negamax(game, -beta, -alpha, depth - 1, plies + 1, time_info, nodes)?;
|
||||||
game,
|
|
||||||
-beta,
|
|
||||||
-alpha,
|
|
||||||
depth - 1,
|
|
||||||
plies + 1,
|
|
||||||
time_info,
|
|
||||||
total_nodes_searched,
|
|
||||||
)?;
|
|
||||||
}
|
}
|
||||||
score
|
score
|
||||||
};
|
};
|
||||||
@@ -123,6 +107,7 @@ mod tests {
|
|||||||
use crate::movegen::r#move::Move;
|
use crate::movegen::r#move::Move;
|
||||||
use crate::search::negamax::negamax;
|
use crate::search::negamax::negamax;
|
||||||
use crate::search::time::TimeInfo;
|
use crate::search::time::TimeInfo;
|
||||||
|
use crate::search::{INC, TIME};
|
||||||
|
|
||||||
const FEN_MATE_IN_1: [&str; 2] = [
|
const FEN_MATE_IN_1: [&str; 2] = [
|
||||||
"8/8/8/8/8/4q1k1/8/5K2 b - - 0 1",
|
"8/8/8/8/8/4q1k1/8/5K2 b - - 0 1",
|
||||||
@@ -135,7 +120,7 @@ mod tests {
|
|||||||
let mut game = from_fen(FEN_MATE_IN_1[0]).unwrap();
|
let mut game = from_fen(FEN_MATE_IN_1[0]).unwrap();
|
||||||
|
|
||||||
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(), TIME, INC);
|
||||||
negamax(&mut game, MIN_SCORE, MAX_SCORE, 2, 0, &time_info, &mut 0)
|
negamax(&mut game, MIN_SCORE, MAX_SCORE, 2, 0, &time_info, &mut 0)
|
||||||
.expect("Expected a search result");
|
.expect("Expected a search result");
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ pub fn quiescence(
|
|||||||
time_info: &TimeInfo,
|
time_info: &TimeInfo,
|
||||||
total_nodes_searched: &mut u64,
|
total_nodes_searched: &mut u64,
|
||||||
) -> Result<i32> {
|
) -> Result<i32> {
|
||||||
if hard_limit(&time_info.time, time_info.remaining_time_in_ms) {
|
if hard_limit(time_info.instant, time_info.time, time_info.inc) {
|
||||||
bail!("Time is up! In Quiescence");
|
bail!("Time is up! In Quiescence");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,25 +1,23 @@
|
|||||||
use std::time::Instant;
|
use std::time::Instant;
|
||||||
|
|
||||||
use super::{HARD_LIMIT_DIVISION, SOFT_EVAL_THRESHOLD, SOFT_LIMIT_DIVISION};
|
use super::HARD_LIMIT_DIVISION;
|
||||||
|
|
||||||
pub struct TimeInfo {
|
pub struct TimeInfo {
|
||||||
pub time: Instant,
|
pub instant: Instant,
|
||||||
pub remaining_time_in_ms: u128,
|
pub time: u128,
|
||||||
|
pub inc: u128,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TimeInfo {
|
impl TimeInfo {
|
||||||
pub const fn new(time: Instant, remaining_time_in_ms: u128) -> Self {
|
pub const fn new(instant: Instant, time: u128, inc: u128) -> Self {
|
||||||
Self {
|
Self { instant, time, inc }
|
||||||
time,
|
}
|
||||||
remaining_time_in_ms,
|
|
||||||
}
|
pub fn nps(&self, nodes: u64) -> u64 {
|
||||||
|
((nodes * 1_000_000) as u128).div_ceil(self.instant.elapsed().as_micros()) as u64
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn hard_limit(time_now: &Instant, remaining_time: u128) -> bool {
|
pub fn hard_limit(time_now: Instant, time: u128, inc: u128) -> bool {
|
||||||
time_now.elapsed().as_millis() >= remaining_time / HARD_LIMIT_DIVISION
|
time_now.elapsed().as_millis() >= time / HARD_LIMIT_DIVISION + inc / 2
|
||||||
}
|
|
||||||
|
|
||||||
pub fn soft_limit(time: &Instant, remaining_time: u128, eval: i32) -> bool {
|
|
||||||
time.elapsed().as_millis() >= remaining_time / SOFT_LIMIT_DIVISION && eval > SOFT_EVAL_THRESHOLD
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -58,12 +58,12 @@ mod tests {
|
|||||||
fn test_transposition_table() -> anyhow::Result<()> {
|
fn test_transposition_table() -> anyhow::Result<()> {
|
||||||
init_attacks();
|
init_attacks();
|
||||||
let mut game = from_fen(FEN).unwrap();
|
let mut game = from_fen(FEN).unwrap();
|
||||||
let time_info = TimeInfo::new(std::time::Instant::now(), 30000);
|
let time_info = TimeInfo::new(std::time::Instant::now(), 30000, 100);
|
||||||
|
|
||||||
negamax(&mut game, MIN_SCORE, MAX_SCORE, 2, 0, &time_info, &mut 0)
|
negamax(&mut game, MIN_SCORE, MAX_SCORE, 2, 0, &time_info, &mut 0)
|
||||||
.expect("Expected a search result");
|
.expect("Expected a search result");
|
||||||
|
|
||||||
dbg!(time_info.time.elapsed());
|
dbg!(time_info.instant.elapsed());
|
||||||
|
|
||||||
let will_be_hash = from_fen(FEN_POSSIBLE).unwrap().hash;
|
let will_be_hash = from_fen(FEN_POSSIBLE).unwrap().hash;
|
||||||
let tt_entry = game.tt.lookup(will_be_hash);
|
let tt_entry = game.tt.lookup(will_be_hash);
|
||||||
|
|||||||
Reference in New Issue
Block a user