aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoreug-vs <eugene@eug-vs.xyz>2024-01-22 01:30:47 +0100
committereug-vs <eugene@eug-vs.xyz>2024-01-22 02:01:34 +0100
commit299c6d6dee96a50f9366955192f922d449d11f20 (patch)
treedb03f75fc611fcc409af9981c25c8373ed6d7b95
parentf266b20fd559b624fc265905af4e7d971491915a (diff)
downloadchessnost-299c6d6dee96a50f9366955192f922d449d11f20.tar.gz
feat: store PV in a separate table
-rw-r--r--src/grossmeister/search.rs40
-rw-r--r--src/grossmeister/ttable.rs24
2 files changed, 44 insertions, 20 deletions
diff --git a/src/grossmeister/search.rs b/src/grossmeister/search.rs
index c81c586..372fecc 100644
--- a/src/grossmeister/search.rs
+++ b/src/grossmeister/search.rs
@@ -47,6 +47,12 @@ impl Grossmeister {
return 0.0
}
+ // Mate distance pruning
+ let mating_score = Grossmeister::MDP(&mut alpha, &mut beta, root_distance);
+ if mating_score != 0.0 {
+ return mating_score
+ }
+
if let Some(transposition) = self.transposition() {
if transposition.depth >= depth_left {
match transposition.node_type {
@@ -77,12 +83,6 @@ impl Grossmeister {
node_type: NodeType::All,
};
- // Mate distance pruning
- let mating_score = Grossmeister::MDP(&mut alpha, &mut beta, root_distance);
- if mating_score != 0.0 {
- return mating_score
- }
-
if depth_left == 0 {
return self.quiscence(alpha, beta, root_distance)
}
@@ -167,6 +167,12 @@ impl Grossmeister {
return 0.0
}
+ // Mate distance pruning
+ let mating_score = Grossmeister::MDP(&mut alpha, &mut beta, root_distance);
+ if mating_score != 0.0 {
+ return mating_score
+ }
+
if let Some(transposition) = self.transposition() {
match transposition.node_type {
NodeType::PV => {
@@ -195,14 +201,6 @@ impl Grossmeister {
node_type: NodeType::All,
};
- // Mate distance pruning
- let mating_score = Grossmeister::MDP(&mut alpha, &mut beta, root_distance);
- if mating_score != 0.0 {
- transposition.score = mating_score;
- return mating_score
- }
-
-
let mut tactical_only = false;
if !self.board.is_king_in_check(color) {
// If we are not in check, we can evaluate stand pat
@@ -263,17 +261,17 @@ impl Grossmeister {
alpha
}
- fn reconstruct_pv(&mut self, depth: u8) -> Vec<Move> {
+ fn collect_pv(&mut self, depth: u8) -> Vec<Move> {
let mut pv = Vec::with_capacity(depth as usize);
if depth > 0 {
- if let Some(transposition) = self.transposition().cloned() {
+ if let Some(transposition) = self.pv().cloned() {
if let Some(mov) = transposition.mov {
if transposition.depth < depth {
- println!("info string found lower-depth {:?}-node ({}) than expected ({}). Probably bad", transposition.node_type, transposition.depth, depth);
+ println!("info string found lower-depth {:?} node ({}) than expected ({}). Probably bad", transposition.node_type, transposition.depth, depth);
}
if transposition.depth > depth {
- println!("info string found higher-depth {:?}-node ({}) than expected ({}). Good for us?", transposition.node_type, transposition.depth, depth);
+ println!("info string found higher-depth {:?} node ({}) than expected ({}). Good for us?", transposition.node_type, transposition.depth, depth);
}
let ep_target_before = self.board.ep_target;
let castling_rights_before = self.board.castling_rights;
@@ -281,12 +279,14 @@ impl Grossmeister {
let captured = self.board.make_move(mov);
pv.push(mov);
- let mut subtree_pv = self.reconstruct_pv(transposition.depth - 1);
+ let mut subtree_pv = self.collect_pv(depth - 1);
pv.append(&mut subtree_pv);
self.board.unmake_move(mov, captured, ep_target_before, castling_rights_before, hash_before);
}
+ } else {
+ println!("No PV node found for hash {}", self.board.hash);
}
}
@@ -336,7 +336,7 @@ impl Grossmeister {
}
best_score = score;
- pv = self.reconstruct_pv(depth);
+ pv = self.collect_pv(depth);
// Print UCI info
print!("info depth {} score ", depth);
diff --git a/src/grossmeister/ttable.rs b/src/grossmeister/ttable.rs
index b1eeec3..b40bac1 100644
--- a/src/grossmeister/ttable.rs
+++ b/src/grossmeister/ttable.rs
@@ -62,8 +62,12 @@ impl TranspositionTable {
#[derive(Debug, Default, Clone)]
pub struct MasterTable {
+ /// Always contains the most recent transposition
always_replace: TranspositionTable,
+ /// Stores highest-depth entries
depth_preferred: TranspositionTable,
+ /// Used to collect Principal Variation. Not used in search
+ pv: TranspositionTable,
}
impl Grossmeister {
@@ -81,6 +85,26 @@ impl Grossmeister {
} {
self.transposition_table.depth_preferred.set(self.board.hash, transposition)
}
+
+ // Store PV/Cut nodes in PV table
+ // Note: Cut nodes are probably only relevant in close-to-mate situations
+ if match transposition.node_type {
+ NodeType::PV => true, // Always replace PV nodes
+ NodeType::Cut => {
+ match self.transposition_table.pv.get(self.board.hash) {
+ Some(existing_transposition) => existing_transposition.node_type != NodeType::PV,
+ None => true,
+ }
+ }
+ _ => false,
+ } {
+ self.transposition_table.pv.set(self.board.hash, transposition)
+ }
+ }
+
+ /// Extract current node information from PV table
+ pub fn pv(&self) -> Option<&TranspositionTableItem> {
+ self.transposition_table.pv.get(self.board.hash)
}
pub fn table_full(&self) -> u64 {