ttable.rs 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. use board::Board;
  2. use evaluate::PosValue;
  3. use static_assertions::const_assert_eq;
  4. use std::collections::{HashMap};
  5. use log::info;
  6. use zobrist;
  7. use crate::movegen::{SimpleMove};
  8. use crate::zobrist::Hash;
  9. #[derive(Clone, PartialEq)]
  10. pub enum EntryType {
  11. Value,
  12. LowerBound,
  13. UpperBound,
  14. NoBound
  15. }
  16. #[derive(Clone)]
  17. pub struct CacheEntry {
  18. pub entry_type: EntryType, // 1 byte
  19. pub halfmove_age: u8, // 1 byte
  20. pub mov: SimpleMove, // 2 bytes
  21. pub value_and_depth: i32, // 4 bytes
  22. }
  23. const_assert_eq!(std::mem::size_of::<CacheEntry>(), 8);
  24. impl CacheEntry {
  25. pub fn null() -> Self {
  26. CacheEntry { entry_type: EntryType::Value, halfmove_age: 0, mov: SimpleMove { from: 0, to: 0 }, value_and_depth: 0 }
  27. }
  28. pub fn new_value(depth: u8, halfmove_age: u8, mov: SimpleMove, value: PosValue) -> Self {
  29. CacheEntry {
  30. entry_type: EntryType::Value,
  31. halfmove_age,
  32. mov,
  33. value_and_depth: (value << 8) | (depth as i32),
  34. }
  35. }
  36. pub fn new_upper(depth: u8, halfmove_age: u8, mov: SimpleMove, value: PosValue) -> Self {
  37. CacheEntry {
  38. entry_type: EntryType::UpperBound,
  39. halfmove_age,
  40. mov,
  41. value_and_depth: (value << 8) | (depth as i32),
  42. }
  43. }
  44. pub fn new_lower(depth: u8, halfmove_age: u8, mov: SimpleMove, value: PosValue) -> Self {
  45. CacheEntry {
  46. entry_type: EntryType::LowerBound,
  47. halfmove_age,
  48. mov,
  49. value_and_depth: (value << 8) | (depth as i32),
  50. }
  51. }
  52. pub fn value(&self) -> PosValue {
  53. self.value_and_depth >> 8
  54. }
  55. pub fn depth(&self) -> u8 {
  56. (self.value_and_depth & 0xFF) as u8
  57. }
  58. }
  59. struct Bucket {
  60. hashes: [Hash; 4],
  61. entries: [CacheEntry; 4],
  62. }
  63. const_assert_eq!(std::mem::size_of::<Bucket>(), 64);
  64. pub struct Cache {
  65. table: Vec<Bucket>,
  66. }
  67. #[derive(Clone)]
  68. pub struct RepetitionTable {
  69. hashmap: HashMap<zobrist::Hash, i32>,
  70. }
  71. impl Cache {
  72. pub fn new_in_megabytes(mbytes: usize) -> Self {
  73. Self::new(mbytes * 1024 * 1024 / std::mem::size_of::<Bucket>())
  74. }
  75. pub fn new(length: usize) -> Self {
  76. let c = Cache {
  77. table: unsafe {
  78. let layout = std::alloc::Layout::array::<Bucket>(length).unwrap();
  79. let allayout = layout.align_to(64).unwrap();
  80. let ptr = std::alloc::alloc(allayout);
  81. Vec::from_raw_parts(ptr.cast(), length, length)
  82. },
  83. };
  84. c
  85. }
  86. fn get_index(&self, hash: zobrist::Hash) -> usize {
  87. (hash % (self.table.len() as u64)) as usize
  88. }
  89. pub fn lookup<'a>(&'a self, board: &Board) -> Option<&'a CacheEntry> {
  90. if board.zobrist.is_none() {
  91. info!("invalid zobrist");
  92. }
  93. let hash = board.zobrist.as_ref().unwrap().1;
  94. let index = self.get_index(hash);
  95. let bucket = &self.table[index];
  96. for i in 0..bucket.hashes.len() {
  97. if bucket.hashes[i] == hash {
  98. return Some(&bucket.entries[i]);
  99. }
  100. }
  101. return None;
  102. }
  103. fn should_replace(old_hash: Hash, old_ce: &CacheEntry, new_hash: Hash, new: &CacheEntry) -> bool {
  104. if old_hash == 0 {
  105. return true;
  106. }
  107. // different positions
  108. if old_hash != new_hash {
  109. if old_ce.halfmove_age < new.halfmove_age {
  110. return true;
  111. }
  112. if old_ce.entry_type == EntryType::Value {
  113. return false;
  114. }
  115. if old_ce.depth() <= new.depth() {
  116. return true;
  117. }
  118. }
  119. if new.depth() >= old_ce.depth() {
  120. return true;
  121. }
  122. return false;
  123. }
  124. pub fn cache(&mut self, game_pos: &Board, ce: CacheEntry) {
  125. if game_pos.zobrist.is_none() {
  126. info!("invalid zobrist");
  127. }
  128. let hash = game_pos.zobrist.as_ref().unwrap().1;
  129. let index = self.get_index(hash);
  130. let bucket = &mut self.table[index];
  131. for i in 0..bucket.hashes.len() {
  132. if bucket.hashes[i] == hash {
  133. if bucket.entries[i].depth() <= ce.depth() {
  134. bucket.entries[i] = ce;
  135. }
  136. return;
  137. }
  138. }
  139. for i in 0..bucket.hashes.len() {
  140. if Self::should_replace(bucket.hashes[i], &bucket.entries[i], hash, &ce) {
  141. bucket.hashes[i] = hash;
  142. bucket.entries[i] = ce;
  143. break;
  144. }
  145. }
  146. }
  147. pub fn fullness_permill(&self) -> usize {
  148. let mut permill = 0;
  149. for i in 0..25 {
  150. permill += 10 * self.table[i].hashes.iter().filter(|h| **h != 0).count();
  151. }
  152. permill
  153. }
  154. pub fn clear(&mut self) {
  155. for bucket in &mut self.table {
  156. bucket.hashes = [0; 4];
  157. }
  158. }
  159. }
  160. impl RepetitionTable {
  161. pub fn new() -> Self {
  162. RepetitionTable {
  163. hashmap: HashMap::with_capacity(64)
  164. }
  165. }
  166. pub fn clear(&mut self) {
  167. self.hashmap.clear();
  168. }
  169. pub fn lookup(&self, hash: zobrist::Hash) -> i32 {
  170. *self.hashmap.get(&hash).unwrap_or(&0)
  171. }
  172. pub fn increment(&mut self, hash: zobrist::Hash) -> i32 {
  173. if let Some(entry) = self.hashmap.get_mut(&hash) {
  174. *entry += 1;
  175. *entry
  176. }
  177. else {
  178. self.hashmap.insert(hash, 1);
  179. 1
  180. }
  181. }
  182. pub fn decrement(&mut self, hash: zobrist::Hash) {
  183. if let Some(entry) = self.hashmap.get_mut(&hash) {
  184. *entry -= 1;
  185. if *entry == 0 {
  186. self.hashmap.remove(&hash);
  187. }
  188. }
  189. }
  190. }