
com.fathzer.games.ai.transposition.OneLongEntryTranspositionTable Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of games-core Show documentation
Show all versions of games-core Show documentation
A core library to help implement two players games.
The newest version!
package com.fathzer.games.ai.transposition;
import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.concurrent.atomic.AtomicLongArray;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.function.Predicate;
import com.fathzer.games.MoveGenerator;
/**
* A transposition table that associates a key to an entry represented by a long.
*
Here are its limitations:
* - score should be a short (16 bits)
* - depth is limited to 127 (8 bits), of course, it should be >= 0
* - move can be represented as a integer (32 bits)
*
* @param The type of moves
* @param The type of move generator
*/
public abstract class OneLongEntryTranspositionTable> implements TranspositionTable {
private static final int SLOTS = 2; // The number of long per record
private final AtomicLongArray table; // Used for transposition table
private final ReadWriteLock lock;
private final int size; // The number of slots the table will have
private int entryCount; // The number of currently occupied slots.
private TranspositionTablePolicy policy;
/** Constructor.
* @param size The table size
* @param unit The unit used to pass the size
*/
protected OneLongEntryTranspositionTable(int size, SizeUnit unit) {
this.size = (int) ((long)size*unit.getSize()) / 8 / SLOTS;
table = new AtomicLongArray(this.size * SLOTS);
this.lock = new ReentrantReadWriteLock();
policy = new BasicPolicy<>();
}
@Override
public TranspositionTableEntry get(long key) {
final int index = getKeyIndex(key);
final OneLongEntry entry = new OneLongEntry<>(this::toMove);
lock.readLock().lock();
try {
return entry.set(key, table.get(index)==key ? table.get(index+1) : 0);
} finally {
lock.readLock().unlock();
}
}
private int getKeyIndex(long key) {
return Math.abs((int) (key % size) * SLOTS);
}
@Override
public boolean store(long key, EntryType type, int depth, int value, M move, Predicate> validator) {
final int index = getKeyIndex(key);
final OneLongEntry entry = new OneLongEntry<>(this::toMove);
lock.writeLock().lock();
try {
entry.set(table.get(index), table.get(index+1));
final boolean written = validator.test(entry);
if (written) {
if (!entry.isValid()) {
entryCount++;
}
table.set(index, key);
table.set(index+1, OneLongEntry.toLong(type, (byte)depth, (short) value, toInt(move)));
}
return written;
} finally {
lock.writeLock().unlock();
}
}
@Override
public TranspositionTablePolicy getPolicy() {
return policy;
}
@Override
public void setPolicy(TranspositionTablePolicy policy) {
this.policy = policy;
}
/** Converts a move to an int.
* @param move The move to convert
* @return The converted move
*/
protected abstract int toInt(M move);
/** Converts an int to a move.
* @param value The value to convert
* @return The converted move
*/
protected abstract M toMove(int value);
/**
* {@inheritDoc}
* In this implementation, the whole table is cleared.
*/
@Override
public void newGame() {
// Clears the table
for (int i=0; i> getEntries() {
return new TTIterator();
}
private class TTIterator implements Iterator> {
private final int max;
private int index = 0;
private OneLongEntry entry = new OneLongEntry<>(OneLongEntryTranspositionTable.this::toMove);
private TTIterator() {
index = 0;
max = size*SLOTS;
entry = new OneLongEntry<>(OneLongEntryTranspositionTable.this::toMove);
prepareNext();
}
private void prepareNext() {
while (index=max) {
entry=null;
}
}
@Override
public boolean hasNext() {
return entry!=null;
}
@Override
public TranspositionTableEntry next() {
if (entry==null) {
throw new NoSuchElementException();
}
final TranspositionTableEntry result = entry;
index += SLOTS;
prepareNext();
return result;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy