As you people might have noticed, I've been working on my chess engine.
It'll become the original POS in a deep (multithreaded) brute force way.
First step is implementing a brute-force thingy, then bolting on the evaluator of the original pos. That last step won't be too difficult, but this brute force alpha/beta code; something is wrong with it.
I googled a little and it seems all implementations are different. Not just naming of variables and such, but how they work too. For example the implementation on wikipedia (english) seems to totally wrong.
So maybe you people could take a look at my code and tell me what is wrong?
Code: Select all
int alphaBeta(final Scene scene, final PlayerColor side, final PlayerColor rootSide, final double finishBefore, int depth, final int maxExtension, final IO io, int alpha, int beta) throws IOException {
// keep track of the number of processed nodes
nodeCount.addAndGet(1);
final PlayerColor otherSide = Statics.opponentColor(side);
if (depth <= 0) {
// if the bottom of the tree is check, search a little deeper
if (depth > maxExtension && scene.isKingUnderAttack(side, otherSide) && !scene.isCheckMate(side)) {
// if check then extend the searchdepth
// by entering this if, the 'depth--' is not invoked and also the next 'depth == 0' is not triggered
//io.progressCallback("Search depth extension due to check " + depth);
long now = System.currentTimeMillis();
if (now - prev.get() > 5000) { // emit output after 5s
double took = Statics.getTimestamp() - startTs;
io.progressCallbackDepthReached(maxDepth - depth);
prev.set(now);
}
}
else {
return getShannonValue(scene, side); // score
}
}
depth--;
final List<Move> moves = scene.getMoveList(side);
int movesListSize = moves.size();
totalNMoves.addAndGet(movesListSize);
totalNodes.addAndGet(1);
for(int index=0; index<movesListSize; index++) {
// "do a move", 'afterMove' is the "situation" after 'currentMove' was executed
Scene afterMove = null;
final Move currentMove = moves.get(index);
try {
afterMove = currentMove.getScene();
if (afterMove == null)
afterMove = scene.Move(currentMove);
else
currentMove.setScene(null); // help GC, link is not required
afterMove.validateMoves(otherSide);
}
catch(Exception e) {
System.out.println(" side: " + side + " alpha " + alpha + " beta " + beta);
System.out.println(" " + (depth + 1) + " " + currentMove);
Statics.displayBoard(afterMove.getBoard());
System.out.println("" + e);
e.printStackTrace();
System.exit(1);
}
final int score = alphaBeta(afterMove, otherSide, rootSide, finishBefore, depth, maxExtension, io, alpha, beta);
if (score == -Integer.MAX_VALUE || score == Integer.MAX_VALUE)
continue;
afterMove.shrink();
if (side == rootSide) { // MAX
if (score >= beta)
return beta;
if (score > alpha)
alpha = score;
}
else { // opposite side: MIN
if (score <= alpha)
return alpha;
if (score < beta)
beta = score;
}
double nowTs = Statics.getTimestamp();
if (finishBefore > 0 && finishBefore <= nowTs) {
io.progressCallback("Abort search due to time limit");
break;
}
}
if (side == rootSide)
return alpha;
return beta;
}