Fix overflow bug, clean up code
This commit is contained in:
@@ -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 {
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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");
|
||||||
|
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user