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:
parent
e06d614885
commit
093dc51eed
52
src/lib.rs
52
src/lib.rs
@ -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
|
||||||
|
@ -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!(),
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user