
com.fathzer.games.perft.PerfT 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.perft;
import static com.fathzer.games.MoveGenerator.MoveConfidence.*;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.atomic.AtomicBoolean;
import com.fathzer.games.MoveGenerator;
import com.fathzer.games.MoveGenerator.MoveConfidence;
import com.fathzer.games.util.UncheckedException;
/** A Perft test.
* @param The type of moves
* @see PerfTBuilder
*/
public class PerfT {
final boolean playLeaves;
final MoveConfidence moveType;
final MoveGenerator board;
private final AtomicBoolean started = new AtomicBoolean();
final int depth;
final PerfTResult result;
PerfT(MoveGenerator board, int depth, boolean playLeaves, MoveConfidence moveType) {
if (depth <= 0) {
throw new IllegalArgumentException("Search depth MUST be > 0");
}
if (board==null) {
throw new IllegalArgumentException("Board cannot be null");
}
this.board = board;
this.playLeaves = playLeaves;
this.moveType = moveType;
this.depth = depth;
this.result = new PerfTResult<>();
}
/** Gets the result of the PerfT.
* @return The result of the PerfT
* @throws IllegalStateException if this method has already been called
* @throws UncheckedException if an execution error occurs
*/
public PerfTResult get() {
if (!started.compareAndSet(false, true)) {
throw new IllegalStateException("This PerfT has already been started");
}
try {
final List moves = getMoves(board);
result.addMovesFound(moves.size());
compute(moves);
return this.result;
} catch (UncheckedException e) {
throw e;
} catch (Exception e) {
throw new UncheckedException(e);
}
}
void compute(List moves) {
for (M move : moves) {
final Divide divide = getRootPerfT(board, move, depth - 1);
if (divide!=null) {
result.add(divide);
}
}
}
List getMoves(MoveGenerator moveGenerator) {
return LEGAL==moveType ? moveGenerator.getLegalMoves() : moveGenerator.getMoves();
}
Divide getRootPerfT(MoveGenerator moveGenerator, M move, int depth) {
final long leaves;
if (depth==0 && !playLeaves) {
leaves = 1;
} else {
if (moveGenerator.makeMove(move, moveType)) {
result.addMoveMade();
leaves = new PerfTTask(moveGenerator, depth).call();
moveGenerator.unmakeMove();
} else {
return null;
}
}
return new Divide<>(move, leaves);
}
class PerfTTask implements Callable {
private final MoveGenerator generator;
private int depth;
public PerfTTask(MoveGenerator generator, int depth) {
this.generator = generator;
this.depth = depth;
}
@Override
public Long call() {
if (isInterrupted()) {
result.setInterrupted(true);
return 1L;
}
if (depth==0) {
return 1L;
}
final List moves = getMoves(generator);
result.addMovesFound(moves.size());
if (depth==1 && !playLeaves) {
return (long)moves.size();
}
return process(moves);
}
protected Long process(List moves) {
long count = 0;
for (M move : moves) {
if (generator.makeMove(move, moveType)) {
result.addMoveMade();
count += goDeeper();
generator.unmakeMove();
}
}
return count;
}
protected Long goDeeper() {
depth--;
long nbLeaves = call();
depth++;
return nbLeaves;
}
}
/** Checks if this PerfT has been interrupted.
* @return true if this PerfT has been interrupted
*/
public boolean isInterrupted() {
if (result.isInterrupted()) {
return true;
}
if (Thread.interrupted()) {
Thread.currentThread().interrupt();
result.setInterrupted(true);
}
return result.isInterrupted();
}
/** Interrupts this PerfT.
*
If the {@link PerfT#get()} method is currently running, it will quickly stopped and will returned a {@link PerfTResult#isInterrupted()} tagged as interrupted.
*/
public void interrupt() {
result.setInterrupted(true);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy