Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion arche-core/src/board.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2339,7 +2339,7 @@ impl Board {
if piece == Piece::Pawn {
self.pawn_key ^= piece_key;
}
self.eval.count::<SET>(row, piece, color);
self.eval.count::<SET>(row, piece);

let board = &mut self.pieces[piece as usize];
if SET {
Expand Down
68 changes: 49 additions & 19 deletions arche-core/src/engine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ use crate::play::Play;
use crate::recorder::{Sampler, Window};
use crate::reduction;
use crate::residual::{Sample, Shortcut};
use crate::transposition::{DEFAULT_TABLE_BYTES, Probe, SignatureCounters, TranspositionTable};
use crate::transposition::{
DEFAULT_TABLE_BYTES, NO_EVAL, Probe, SignatureCounters, TranspositionTable,
};
use crate::value::{
MateDistanceWindow, Taint, Value, below_the_mate_window, is_mate, mate_distance_window,
};
Expand Down Expand Up @@ -1862,7 +1864,7 @@ impl AlphaBeta {
if score > alpha {
if score >= beta {
let value = taint.stamp(score);
self.store_cutoff(m, value, 0);
self.store_cutoff(m, value, 0, standing.unwrap_or(NO_EVAL));
return Ok(value);
}
alpha = score;
Expand All @@ -1876,7 +1878,13 @@ impl AlphaBeta {

let value = taint.stamp(best);
if let Some(play) = best_move {
self.store_answer(play, value, 0, alpha != old_alpha);
self.store_answer(
play,
value,
0,
alpha != old_alpha,
standing.unwrap_or(NO_EVAL),
);
}
Ok(value)
}
Expand Down Expand Up @@ -1906,7 +1914,9 @@ impl AlphaBeta {
/// leaves whatever it read in the node's taint.
///
/// `eval_memo` is filled wherever the gates passed and an evaluation
/// was read, fired or not, so the move loop does not evaluate twice.
/// was read, fired or not, so the move loop does not evaluate twice. It
/// arrives filled where the node's table entry held the evaluation, and
/// is then read rather than computed.
/// Alpha is read only for the open window and by the sampler.
// two arguments past clippy's limit: the root bounds and the evaluation
// handed back to the loop.
Expand Down Expand Up @@ -1939,7 +1949,10 @@ impl AlphaBeta {
{
return Ok(None);
}
let eval = self.eval();
let eval = match *eval_memo {
Some(eval) => eval,
None => self.eval(),
};
*eval_memo = Some(eval);

// the margin proves `eval - margin` as a lower bound, and fail soft
Expand Down Expand Up @@ -2121,10 +2134,11 @@ impl AlphaBeta {
taint: Taint,
score: Score,
depth: u8,
static_eval: Score,
) -> Value {
self.remember_cutoff(m, tried, depth);
let value = taint.stamp(score);
self.store_cutoff(m, value, depth);
self.store_cutoff(m, value, depth, static_eval);
value
}

Expand All @@ -2133,7 +2147,12 @@ impl AlphaBeta {
/// sort at all, and the tree searched is unchanged. A cutoff answers
/// the node. Otherwise the node absorbs what the move scored, or
/// nothing when the move was not legal here.
fn search_table_move(&mut self, tt: Play, node: &mut Node) -> Result<Option<Value>, Aborted> {
fn search_table_move(
&mut self,
tt: Play,
node: &mut Node,
static_eval: Score,
) -> Result<Option<Value>, Aborted> {
let Some(value) = self.search_child(
&tt,
node.alpha,
Expand All @@ -2160,6 +2179,7 @@ impl AlphaBeta {
node.taint,
value.score,
node.depth,
static_eval,
)))
}

Expand Down Expand Up @@ -2318,11 +2338,11 @@ impl AlphaBeta {
}

/// A cutoff's value to the table, when the taint policy allows.
fn store_cutoff(&mut self, m: &Play, value: Value, depth: u8) {
fn store_cutoff(&mut self, m: &Play, value: Value, depth: u8, static_eval: Score) {
if self.keeps(value) {
let landed = self
.transpositions
.record_cutoff(&self.board, *m, value, depth);
let landed =
self.transpositions
.record_cutoff(&self.board, *m, value, depth, static_eval);
self.ghi.count_store(landed, value);
}
}
Expand All @@ -2331,14 +2351,21 @@ impl AlphaBeta {
/// best move with its score where a move raised alpha, and as a
/// ceiling where none did, the move beside it then being only the one
/// that came closest.
fn store_answer(&mut self, play: Play, value: Value, depth: u8, raised_alpha: bool) {
fn store_answer(
&mut self,
play: Play,
value: Value,
depth: u8,
raised_alpha: bool,
static_eval: Score,
) {
if self.keeps(value) {
let landed = if raised_alpha {
self.transpositions
.record_best(&self.board, play, value, depth)
.record_best(&self.board, play, value, depth, static_eval)
} else {
self.transpositions
.record_ceiling(&self.board, play, value, depth)
.record_ceiling(&self.board, play, value, depth, static_eval)
};
self.ghi.count_store(landed, value);
}
Expand Down Expand Up @@ -2434,8 +2461,9 @@ impl AlphaBeta {
};
let mut taint = Taint::default();
// the node's static evaluation, filled by the shortcuts and read by
// the late move decision
let mut eval: Option<Score> = None;
// the late move decision, or found in the table's entry
let table_eval = self.transpositions.probed_eval(self.board.key);
let mut eval: Option<Score> = (table_eval != NO_EVAL).then_some(table_eval);
if let Some(value) = self.shortcuts(
alpha,
beta,
Expand All @@ -2448,6 +2476,8 @@ impl AlphaBeta {
)? {
return Ok(value);
}
// what the node's stores carry into the table
let static_eval = eval.unwrap_or(NO_EVAL);

let table_move = pv_play.filter(|tt| self.board.is_pseudo_legal(tt));
let mut node = Node::open(
Expand All @@ -2462,7 +2492,7 @@ impl AlphaBeta {
taint,
);
if let Some(tt) = table_move {
if let Some(value) = self.search_table_move(tt, &mut node)? {
if let Some(value) = self.search_table_move(tt, &mut node, static_eval)? {
return Ok(value);
}
}
Expand Down Expand Up @@ -2532,7 +2562,7 @@ impl AlphaBeta {
.enumerate()
.filter(|(place, _)| made.holds(*place))
.map(|(_, tried)| tried);
return Ok(self.cutoff(m, tried, node.taint, value.score, depth));
return Ok(self.cutoff(m, tried, node.taint, value.score, depth, static_eval));
}
Reached::Alpha => {
// the dropped moves stay dropped only while alpha is
Expand Down Expand Up @@ -2570,7 +2600,7 @@ impl AlphaBeta {
.best_move
.expect("a legal move was found, so one of them is best");
let value = node.taint.stamp(node.best);
self.store_answer(play, value, depth, node.raised_alpha());
self.store_answer(play, value, depth, node.raised_alpha(), static_eval);
Ok(value)
}

Expand Down
Loading
Loading