tune: make only three repetitions (not two) evaluate as draw

this commit might fix some positions being evaluated as zero
This commit is contained in:
dogeystamp 2024-12-25 20:08:32 -05:00
parent e06d614885
commit 093dc51eed
No known key found for this signature in database
3 changed files with 31 additions and 33 deletions

View File

@ -568,17 +568,6 @@ impl BoardHistory {
self.ptr_start += 1; self.ptr_start += 1;
} }
} }
/// Remove from end (pop) hash from history.
///
/// Adding and then removing a hash may erase old entries due to lack of space.
fn pop(&mut self) {
if self.ptr_end == self.ptr_start {
// history is empty already
} else {
self.ptr_end -= 1;
}
}
} }
/// Game state, describes a position. /// Game state, describes a position.
@ -810,7 +799,7 @@ mod tests {
use super::*; use super::*;
use fen::FromFen; use fen::FromFen;
use movegen::{FromUCIAlgebraic, Move}; use movegen::{FromUCIAlgebraic, Move, ToUCIAlgebraic};
#[test] #[test]
fn test_square_casts() { fn test_square_casts() {
@ -962,22 +951,6 @@ mod tests {
assert_eq!(history.count(board_empty.zobrist), 4); assert_eq!(history.count(board_empty.zobrist), 4);
assert_eq!(history.count(board.zobrist), HISTORY_SIZE - 5); assert_eq!(history.count(board.zobrist), HISTORY_SIZE - 5);
for _ in 0..3 {
history.pop();
}
assert_eq!(history.count(board_empty.zobrist), 1);
// after popping, the replaced entries no longer exist
assert_eq!(history.count(board.zobrist), HISTORY_SIZE - 5);
history.pop();
assert_eq!(history.count(board_empty.zobrist), 0);
assert_eq!(history.count(board.zobrist), HISTORY_SIZE - 5);
history.pop();
assert_eq!(history.count(board_empty.zobrist), 0);
assert_eq!(history.count(board.zobrist), HISTORY_SIZE - 6);
} }
#[test] #[test]
@ -992,6 +965,7 @@ mod tests {
for _ in 0..2 { for _ in 0..2 {
for mv in &mvs { for mv in &mvs {
board.push_history();
let _ = mv.make(&mut board); let _ = mv.make(&mut board);
} }
} }
@ -1015,10 +989,17 @@ mod tests {
let expected_bestmv = Move::from_uci_algebraic("a2a1").unwrap(); let expected_bestmv = Move::from_uci_algebraic("a2a1").unwrap();
let mut cnt = 0;
for mv in &mvs { for mv in &mvs {
board.push_history();
cnt += 1;
let _ = mv.make(&mut board); let _ = mv.make(&mut board);
} }
eprintln!("board is: '{}'", board.to_fen());
eprintln!("added {} history entries", cnt);
let (_tx, rx) = std::sync::mpsc::channel(); let (_tx, rx) = std::sync::mpsc::channel();
let cache = TranspositionTable::new(1); let cache = TranspositionTable::new(1);
@ -1037,7 +1018,20 @@ mod tests {
let (line, eval) = best_line(&mut board, &mut engine_state); let (line, eval) = best_line(&mut board, &mut engine_state);
let best_mv = line.last().unwrap(); let best_mv = line.last().unwrap();
assert_eq!(*best_mv, expected_bestmv); expected_bestmv.make(&mut board);
eprintln!(
"after expected mv, board repeated {} times",
board.history.count(board.zobrist)
);
assert_eq!(
*best_mv,
expected_bestmv,
"got {} (eval {:?}) instead of {}",
best_mv.to_uci_algebraic(),
eval,
expected_bestmv.to_uci_algebraic()
);
assert!(EvalInt::from(eval) == 0); assert!(EvalInt::from(eval) == 0);
// now ensure that it's completely one-sided without the repetition opportunity // now ensure that it's completely one-sided without the repetition opportunity

View File

@ -63,8 +63,8 @@ fn cmd_position_moves(mut tokens: std::str::SplitWhitespace<'_>, mut board: Boar
"moves" => { "moves" => {
for mv in tokens.by_ref() { for mv in tokens.by_ref() {
let mv = Move::from_uci_algebraic(mv).unwrap(); let mv = Move::from_uci_algebraic(mv).unwrap();
let _ = mv.make(&mut board);
board.push_history(); board.push_history();
let _ = mv.make(&mut board);
} }
} }
_ => ignore!(), _ => ignore!(),

View File

@ -208,14 +208,18 @@ fn minmax(board: &mut Board, state: &mut EngineState, mm: MinmaxState) -> (Vec<M
} }
} }
let is_drawn = !mm.quiesce && board.history.count(board.zobrist) >= 1; let is_repetition_draw = board.history.count(board.zobrist) >= 2;
// quiescence stand-pat score (only calculated if needed). // quiescence stand-pat score (only calculated if needed).
// this is where static eval goes. // this is where static eval goes.
let mut board_eval: Option<EvalInt> = None; let mut board_eval: Option<EvalInt> = None;
if mm.quiesce { if mm.quiesce {
board_eval = Some(board.eval() * EvalInt::from(board.turn.sign())); board_eval = Some(if is_repetition_draw {
0
} else {
board.eval() * EvalInt::from(board.turn.sign())
});
} }
if mm.depth == 0 { if mm.depth == 0 {
@ -343,7 +347,7 @@ fn minmax(board: &mut Board, state: &mut EngineState, mm: MinmaxState) -> (Vec<M
} }
} }
if is_drawn { if is_repetition_draw {
abs_best = SearchEval::Exact(0); abs_best = SearchEval::Exact(0);
} }