pub struct TranspositionTable {
keys: Vec<u32>,
scores: Vec<i8>,
}
impl TranspositionTable {
pub fn new(capacity: usize) -> Self {
assert!(capacity % 2 == 1);
assert!(capacity * (2 ^ 32) > 2 ^ 49);
Self {
keys: vec![0; capacity],
scores: vec![0; capacity],
}
}
pub fn put(&mut self, board: u64, score: i8) {
let index = self.index(board);
self.keys[index] = Self::key(board);
self.scores[index] = score;
}
pub fn get(&self, board: u64) -> Option<i8> {
let index = self.index(board);
let found_key = self.keys[index];
if found_key == Self::key(board) {
Some(self.scores[index])
} else {
None
}
}
fn key(board: u64) -> u32 {
board as u32
}
fn index(&self, board: u64) -> usize {
(board % self.keys.len() as u64) as usize
}
}
#[cfg(test)]
mod tests {
use crate::ConnectFour;
use super::TranspositionTable;
#[test]
fn cache_hit() {
let position = ConnectFour::from_move_list("5655663642443");
let score = 15;
let mut cache = TranspositionTable::new(131101);
cache.put(position.encode(), score);
assert_eq!(cache.get(position.encode()), Some(score));
}
#[test]
fn cache_miss() {
let position = ConnectFour::from_move_list("5655663642443");
let other_position = ConnectFour::from_move_list("5655663642442");
let score = 15;
let mut cache = TranspositionTable::new(131101);
cache.put(position.encode(), score);
assert_eq!(cache.get(other_position.encode()), None);
}
}