use game::Game; use evaluate::PosValue; use std::collections::{HashMap}; use log::info; use zobrist; #[derive(Clone)] pub enum EntryType { Value, LowerBound, UpperBound, } #[derive(Clone)] pub struct CacheEntry { pub entry_type: EntryType, pub depth: i32, pub value: PosValue, } impl CacheEntry { pub fn new_value(depth: i32, value: PosValue) -> Self { CacheEntry { entry_type: EntryType::Value, depth, value, } } pub fn new_upper(depth: i32, beta: PosValue) -> Self { CacheEntry { entry_type: EntryType::UpperBound, depth, value: beta, } } pub fn new_lower(depth: i32, alpha: PosValue) -> Self { CacheEntry { entry_type: EntryType::LowerBound, depth, value: alpha, } } } pub struct Cache { hashmap: HashMap, max_capacity: usize } #[derive(Clone)] pub struct RepetitionTable { hashmap: HashMap, } impl Cache { pub fn new() -> Self { Cache { hashmap: HashMap::new(), max_capacity: 40000000 } } pub fn lookup(&self, game_pos: &Game) -> Option { self.hashmap.get(&game_pos.zobrist.as_ref().unwrap().1).map(|x| x.clone()) } pub fn cache(&mut self, game_pos: &Game, ce: CacheEntry) { if let Some(c) = self.lookup(game_pos) { if c.depth > ce.depth { return; } } if self.hashmap.len() > self.max_capacity { //let first_key = self.hashmap.keys().next().unwrap().clone(); //self.hashmap.remove(&first_key); self.hashmap.clear(); } let key = game_pos.zobrist.as_ref().unwrap().1; self.hashmap.insert(key, ce); if self.hashmap.len() % (1024 * 32) == 0 { info!("hash contains {} items", self.hashmap.len()); } } } impl RepetitionTable { pub fn new() -> Self { RepetitionTable { hashmap: HashMap::with_capacity(256) } } pub fn clear(&mut self) { self.hashmap.clear(); } pub fn increment(&mut self, hash: zobrist::Hash) -> i32 { if let Some(entry) = self.hashmap.get_mut(&hash) { *entry += 1; *entry } else { self.hashmap.insert(hash, 1); 1 } } pub fn decrement(&mut self, hash: zobrist::Hash) { if let Some(entry) = self.hashmap.get_mut(&hash) { *entry -= 1; if *entry == 0 { self.hashmap.remove(&hash); } } } }