Преглед изворни кода

fiddling with replacement strategy

Nicolas Winkler пре 2 година
родитељ
комит
e6a772724e
3 измењених фајлова са 29 додато и 11 уклоњено
  1. 4 0
      src/engine.rs
  2. 9 5
      src/search.rs
  3. 16 6
      src/ttable.rs

+ 4 - 0
src/engine.rs

@@ -99,8 +99,10 @@ impl Engine {
         panic::set_hook(Box::new(|panic_info| {
             if let Some(s) = panic_info.payload().downcast_ref::<&str>() {
                 info!("panic occurred: {s:?}");
+                println!("panic occurred: {s:?}");
             } else {
                 info!("panic occurred");
+                println!("panic occurred");
             }
         }));
         while let Some(msg) = self.dequeue_message() {
@@ -240,6 +242,8 @@ impl Engine {
         let mut best_move = Move::default();
         let mut best_val: PosValue;
 
+        sc.halfmove_age = (self.game.turn_number * 2 + if self.game.turn == BLACK { 1 } else { 0 }) as _;
+
         if si.perft {
             if let Some(dep) = si.depth {
                 depth = dep;

+ 9 - 5
src/search.rs

@@ -19,6 +19,9 @@ pub struct SearchControl<'a> {
     pub pv: Vec<Move>,
     pub killer_moves: Vec<[Move; 2]>,
 
+    /// current halfmove clock for discarding old hash entries
+    pub halfmove_age: u16,
+
     /// function to check if the search should be exited
     pub check: &'a mut dyn FnMut() -> bool,
     pub stopping: bool,
@@ -40,6 +43,7 @@ impl<'a> SearchControl<'a> {
             nodes: 0,
             pv: Vec::with_capacity(depth as usize),
             killer_moves: vec![[Move::Nullmove; 2]; depth as usize],
+            halfmove_age: 0,
             check,
             stopping: false,
             move_history,
@@ -127,7 +131,7 @@ pub fn search(game: &mut Game, sc: &mut SearchControl, hash: &mut Cache, mut alp
             return SearchResult::Cancelled(Some((chosen_mov.0, -chosen_mov.1)));
         }
         else {
-            hash.cache(game, CacheEntry::new_value(depth, chosen_mov.0, chosen_mov.1));
+            hash.cache(game, CacheEntry::new_value(depth as _, sc.halfmove_age, chosen_mov.0, chosen_mov.1));
             sc.pv[0] = chosen_mov.0;
             return SearchResult::Finished(chosen_mov.0, -chosen_mov.1);
         }
@@ -142,7 +146,7 @@ pub fn negamax(game: &mut Game, sc: &mut SearchControl, hash: &mut Cache, mut al
     let cache_entry = hash.lookup(game);
 
     if let Some(e) = &cache_entry {
-        if e.depth >= depth {
+        if e.depth as i32 >= depth {
             //println!("TABLE HIT!");
             match e.entry_type {
                 EntryType::Value => { return e.value; },
@@ -237,7 +241,7 @@ pub fn negamax(game: &mut Game, sc: &mut SearchControl, hash: &mut Cache, mut al
         }
 
         if val >= beta {
-            hash.cache(game, CacheEntry::new_lower(depth, mov, val));
+            hash.cache(game, CacheEntry::new_lower(depth as _, sc.halfmove_age, mov, val));
             if !mov.is_capture() {
                 sc.insert_killer(ply_depth, mov);
             }
@@ -252,12 +256,12 @@ pub fn negamax(game: &mut Game, sc: &mut SearchControl, hash: &mut Cache, mut al
 
 
     if alpha_is_exact {
-        hash.cache(game, CacheEntry::new_value(depth, best_move, alpha));
+        hash.cache(game, CacheEntry::new_value(depth as _, sc.halfmove_age, best_move, alpha));
         let cur_depth = (sc.initial_depth - depth) as usize;
         sc.pv[cur_depth] = best_move;
     }
     else {
-        hash.cache(game, CacheEntry::new_upper(depth, Move::Nullmove, alpha));
+        hash.cache(game, CacheEntry::new_upper(depth as _, sc.halfmove_age, Move::Nullmove, alpha));
     }
     //info!("best alpha {}", alpha);
     return alpha;

+ 16 - 6
src/ttable.rs

@@ -16,37 +16,41 @@ pub enum EntryType {
 #[derive(Clone)]
 pub struct CacheEntry {
     pub entry_type: EntryType,
+    pub halfmove_age: u16,
     pub mov: Move,
-    pub depth: i32,
+    pub depth: i16,
     pub value: PosValue,
 }
 
 impl CacheEntry {
     pub fn null() -> Self {
-        CacheEntry { entry_type: EntryType::Value, mov: Move::Nullmove, depth: 0, value: 0 }
+        CacheEntry { entry_type: EntryType::Value, halfmove_age: 0, mov: Move::Nullmove, depth: 0, value: 0 }
     }
 
-    pub fn new_value(depth: i32, mov: Move, value: PosValue) -> Self {
+    pub fn new_value(depth: i16, halfmove_age: u16, mov: Move, value: PosValue) -> Self {
         CacheEntry {
             entry_type: EntryType::Value,
+            halfmove_age,
             mov,
             depth,
             value,
         }
     }
 
-    pub fn new_upper(depth: i32, mov: Move, value: PosValue) -> Self {
+    pub fn new_upper(depth: i16, halfmove_age: u16, mov: Move, value: PosValue) -> Self {
         CacheEntry {
             entry_type: EntryType::UpperBound,
+            halfmove_age,
             mov,
             depth,
             value,
         }
     }
 
-    pub fn new_lower(depth: i32, mov: Move, value: PosValue) -> Self {
+    pub fn new_lower(depth: i16, halfmove_age: u16, mov: Move, value: PosValue) -> Self {
         CacheEntry {
             entry_type: EntryType::LowerBound,
+            halfmove_age,
             mov,
             depth,
             value,
@@ -69,7 +73,7 @@ impl Cache {
         let mut c = Cache {
             table: Vec::new(),
         };
-        c.table.resize(4096 * 4096, (0, CacheEntry::null()));
+        c.table.resize(4096 * 512, (0, CacheEntry::null()));
         c
     }
 
@@ -102,9 +106,15 @@ impl Cache {
 
         // different positions
         if *old_hash != new_hash {
+            if old_ce.halfmove_age < new.halfmove_age {
+                return true;
+            }
             if old_ce.entry_type == EntryType::Value {
                 return false;
             }
+            if old_ce.depth <= new.depth {
+                return true;
+            }
         }
 
         if new.depth >= old_ce.depth {