All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.fathzer.games.ai.transposition.OneLongEntryTranspositionTable Maven / Gradle / Ivy

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