Fix overflow bug, clean up code

This commit is contained in:
stefiosif
2025-03-28 23:38:00 +02:00
parent 6211e5be89
commit d1bdc140a5
8 changed files with 59 additions and 32 deletions

View File

@@ -29,7 +29,7 @@ pub struct Game {
pub hash: ZobristHash, pub hash: ZobristHash,
pub tt: TranspositionTable, pub tt: TranspositionTable,
pub killer: [Option<Move>; MAX_DEPTH as usize], pub killer: [Option<Move>; MAX_DEPTH as usize],
pub history_heuristic: [[[i16; 64]; 64]; 2], pub history_heuristic: [[[i32; 64]; 64]; 2],
} }
impl Game { impl Game {

View File

@@ -6,7 +6,7 @@ use std::{
thread, thread,
}; };
use anyhow::{anyhow, bail}; use anyhow::{anyhow, bail, Context};
use crate::{ use crate::{
board::{ board::{
@@ -58,7 +58,12 @@ use std::fmt;
impl fmt::Display for Response { impl fmt::Display for Response {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self { match self {
Self::UciOk => write!(f, "id name zeal\nid author stefiosif\nuciok"), Self::UciOk => {
let name = "id name zeal 1.0";
let author = "id author stefiosif";
let hash = "option name Hash type spin default 64 min 1 max 1024";
write!(f, "{name}\n{author}\n{hash}\nuciok")
}
Self::ReadyOk => write!(f, "readyok"), Self::ReadyOk => write!(f, "readyok"),
Self::BestMove(best_move) => write!(f, "bestmove {best_move}"), Self::BestMove(best_move) => write!(f, "bestmove {best_move}"),
Self::Info(info) => write!(f, "{info}"), Self::Info(info) => write!(f, "{info}"),
@@ -179,7 +184,7 @@ pub fn uci_go(go_iter: &mut SplitWhitespace, game: &mut Game) -> anyhow::Result<
iterative_deepening::iterative_deepening( iterative_deepening::iterative_deepening(
game, game,
params.depth.unwrap_or(MAX_DEPTH), params.depth.unwrap_or(MAX_DEPTH),
&TimeInfo::new(std::time::Instant::now(), time, inc), &TimeInfo::new(time, inc),
)? )?
.ok_or_else(|| anyhow!("No stored best move found")) .ok_or_else(|| anyhow!("No stored best move found"))
} }
@@ -199,11 +204,18 @@ fn uci_option(option_iter: &mut SplitWhitespace, game: &mut Game) -> anyhow::Res
if let Some(name) = params.options.get("name") { if let Some(name) = params.options.get("name") {
if name == "Hash" { if name == "Hash" {
let value = params.options.get("value").expect("Expected key value"); let value = params
let size = value .options
.get("value")
.expect("Expected key value")
.parse::<usize>() .parse::<usize>()
.map_err(|_| anyhow!("Invalid value for Hash"))?; .with_context(|| "Not a number".to_string())?;
game.tt = TranspositionTable::with_capacity(size);
if !(1..=1024).contains(&value) {
bail!("Size must be between 1 and 1024; got {value}");
}
game.tt = TranspositionTable::with_capacity(value);
} }
} }

View File

@@ -92,15 +92,8 @@ 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 instant = std::time::Instant::now();
iterative_deepening::iterative_deepening( iterative_deepening::iterative_deepening(&mut game, MAX_DEPTH, &TimeInfo::new(TIME, INC))?;
&mut game,
MAX_DEPTH,
&TimeInfo::new(instant, TIME, INC),
)?;
dbg!(instant.elapsed());
Ok(()) Ok(())
} }

View File

@@ -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 = 50; pub const MAX_DEPTH: u8 = 100;
pub const TIME: u128 = 8000; pub const TIME: u128 = 100000;
pub const INC: u128 = 80; pub const INC: u128 = 1000;
pub const HARD_LIMIT_DIVISION: u128 = 3; 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;
@@ -23,5 +23,5 @@ pub const LMR_DIVISION: f32 = 2.0;
pub const NMP_REDUCTION: u8 = 2; pub const NMP_REDUCTION: u8 = 2;
pub const NMP_DEPTH_THRESHOLD: u8 = 2; pub const NMP_DEPTH_THRESHOLD: u8 = 2;
pub const RFP_DEPTH_LIMIT: u8 = 6; pub const RFP_DEPTH_LIMIT: u8 = 6;
pub const RFP_MARGIN: u8 = 75; pub const RFP_MARGIN: i16 = 75;
pub const CHECK_EXTENSION: u8 = 1; pub const CHECK_EXTENSION: u8 = 1;

View File

@@ -21,7 +21,7 @@ pub fn score_move(
if mv.is_capture() { if mv.is_capture() {
let aggressor = mailbox.piece_at(mv.src()).unwrap(); let aggressor = mailbox.piece_at(mv.src()).unwrap();
if let Some(victim) = mailbox.piece_at(mv.dst()) { if let Some(victim) = mailbox.piece_at(mv.dst()) {
return aggressor.0.idx() as i16 - 8 * victim.0.idx() as i16; return aggressor.0.idx() as i32 - 8 * victim.0.idx() as i32;
} }
return 0; //en passant return 0; //en passant
} }

View File

@@ -3,6 +3,7 @@ use anyhow::{bail, Result};
use crate::{ use crate::{
board::game::Game, board::game::Game,
evaluation::{pesto::pesto, MATE_SCORE, MIN_SCORE}, evaluation::{pesto::pesto, MATE_SCORE, MIN_SCORE},
movegen::r#move::Move,
}; };
use super::{ use super::{
@@ -24,7 +25,7 @@ pub fn negamax(
nodes: &mut u64, nodes: &mut u64,
do_nmp: bool, do_nmp: bool,
) -> Result<i16> { ) -> Result<i16> {
if time.exceed_hard_limit() { if *nodes & 1024 == 0 && time.exceed_hard_limit() {
bail!("Hard limit exceeded in negamax"); bail!("Hard limit exceeded in negamax");
} }
@@ -64,7 +65,7 @@ pub fn negamax(
&& alpha == beta - 1 && alpha == beta - 1
&& depth < RFP_DEPTH_LIMIT && depth < RFP_DEPTH_LIMIT
&& eval > beta && eval > beta
&& eval - (RFP_MARGIN * depth) as i16 > beta && eval - RFP_MARGIN * depth as i16 > beta
{ {
return Ok(eval); return Ok(eval);
} }
@@ -218,9 +219,15 @@ 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(), TIME, INC);
negamax( negamax(
&mut game, MIN_SCORE, MAX_SCORE, 5, 0, &time_info, &mut 0, true, &mut game,
MIN_SCORE,
MAX_SCORE,
5,
0,
&TimeInfo::new(TIME, INC),
&mut 0,
true,
) )
.expect("Expected a search result"); .expect("Expected a search result");
@@ -230,7 +237,14 @@ mod tests {
let e3f2 = Move::new(Square::E3, Square::F2); let e3f2 = Move::new(Square::E3, Square::F2);
negamax( negamax(
&mut game, MIN_SCORE, MAX_SCORE, 5, 0, &time_info, &mut 0, true, &mut game,
MIN_SCORE,
MAX_SCORE,
5,
0,
&TimeInfo::new(TIME, INC),
&mut 0,
true,
) )
.expect("Expected a search result"); .expect("Expected a search result");

View File

@@ -9,8 +9,12 @@ pub struct TimeInfo {
} }
impl TimeInfo { impl TimeInfo {
pub const fn new(instant: Instant, time: u128, inc: u128) -> Self { pub fn new(time: u128, inc: u128) -> Self {
Self { instant, time, inc } Self {
instant: std::time::Instant::now(),
time,
inc,
}
} }
pub fn nps(&self, nodes: u64) -> u64 { pub fn nps(&self, nodes: u64) -> u64 {

View File

@@ -94,15 +94,19 @@ 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(), TIME, INC);
negamax( negamax(
&mut game, MIN_SCORE, MAX_SCORE, 3, 0, &time_info, &mut 0, true, &mut game,
MIN_SCORE,
MAX_SCORE,
3,
0,
&TimeInfo::new(TIME, INC),
&mut 0,
true,
) )
.expect("Expected a search result"); .expect("Expected a search result");
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 entry = game.tt.lookup(will_be_hash); let entry = game.tt.lookup(will_be_hash);