最初の予備的な注意:チェスの専門用語では、転置テーブルという用語は「ハッシュテーブル」よりも一般的であり、Googleでより良い検索結果を提供します。
これを念頭に置いて、転置テーブルと汎用ハッシュテーブル(JavaMap
など)の間には重要な違いがあります。
マップは、新しい値が挿入されたときに既存のエントリが削除されないことを保証する連想配列です。通常、これはあなたが望むものですが、チェスエンジンを書くとき、古いエントリを削除または上書きしないと、すぐにメモリが不足します。
対照的に、転置テーブルはキャッシュであり、最新のエントリのみが含まれます。これは、現在の位置のハッシュ値によってアドレス指定される単純な固定サイズの配列として実装できます。キーを計算するためのよく知られた非常に効率的な方法は、Zobristハッシュです(質問ですでに言及しています)。このキーは、配列にインデックスを付けるために使用されます。新しいエントリが追加されると、既存のエントリが上書きされます。
アイデアを説明するためのいくつかの擬似コードを次に示します。
// the transposition table entry
class TTEntry {
long hashKey; // should be at least 64-bit to be safe
// other information, e.g.:
Move move;
int distance;
// ...
}
TTEntry[] ttable = ... // the more memory, the better
Entry getTTEntry(Board board) {
long hashKey = board.getHashKey();
int index = hashKey % ttable.length;
return ttable[index];
}
void store(Board board) {
Entry entry = getTTEntry(board);
entry.hashKey = board.getHashKey();
entry.move = ...;
entry.distance = ...;
}
void probe(Board board) {
Entry entry = getTTEntry(board);
if (entry.hashKey == hashKey) {
// entry found
// ... do something with entry.move and entry.distance
}
}
使用したとのことですArrayList
が、保存されている位置の数に応じてルックアップ時間が長くなりました。上記の例の手法を使用する場合、それは決して起こり得ません。検索された位置の数に依存しないだけでなく、HashMap
内部がはるかに複雑な、よりも高速になります。