private int GetBoardValueRecursive(OthelloBoard board, int ply, int notStuck, int alpha, int beta) { //MyTrace(ply, "left="+board.EmptySquares+" alpha="+alpha+" beta="+beta); /* If the game is over */ if (notStuck == 0 || board.EmptySquares == 0) { _finalEvaluations++; int squareDifference = board.PlayerSquares - board.OpponentSquares; if (squareDifference > 0) { return(squareDifference + 1000); } if (squareDifference < 0) { return(squareDifference - 1000); } // Tie return(0); } #if USE_TRANSPOSITION_TABLE int moveToTryFirst_X = -1, moveToTryFirst_Y = -1; bool needToTryFirstMove = false; int boardHashCode = board.GetHashCode(); int transpositionValue = _transpositionTable.LookupEntry(boardHashCode, ply, alpha, beta, ref moveToTryFirst_X, ref moveToTryFirst_Y); if (transpositionValue != AlphaBetaOthelloPlayer.INVALID_MOVE) { _transpositionHits++; return(transpositionValue); } if (moveToTryFirst_X >= 0) { needToTryFirstMove = true; } TranspositionTableElementType elementType = TranspositionTableElementType.Alpha; OthelloMoveWithData bestMove = null; #endif if (ply == 0) { _boardEvaluations++; int val = GetBoardValue(board); #if USE_TRANSPOSITION_TABLE _transpositionTable.AddEntry(boardHashCode, 0, val, TranspositionTableElementType.Exact, -1, -1); #endif return(val); } int count = 0; for (int y = 0; y < 8; y++) { for (int x = 0; x < 8; x++) { OthelloMoveWithData move; #if USE_TRANSPOSITION_TABLE if (needToTryFirstMove) { move = board.GetMoveInfoIfValid(moveToTryFirst_X, moveToTryFirst_Y); needToTryFirstMove = false; // Set x to -1 to make sure that (0,0) gets process next time around x = -1; // This could happen if we found an incorrect entry in the table if (move == null) { continue; } } else { // Skip this move if we've already tried it if (x == moveToTryFirst_X && y == moveToTryFirst_Y) { continue; } move = board.GetMoveInfoIfValid(x, y); if (move == null) { continue; } } #else move = board.GetMoveInfoIfValid(x, y); if (move == null) { continue; } #endif count++; /* perform the move */ board.PlayMove(move); //MyTrace(ply, move.X + "," + move.Y + " alpha="+alpha+" beta="+beta); int val = (-GetBoardValueRecursive(board, ply - 1, 2, -beta, -alpha)); //MyTrace(ply, move.X + "," + move.Y + " alpha="+alpha+" beta="+beta+" val="+val); board.UnplayMove(move); if (val >= beta) { #if USE_TRANSPOSITION_TABLE _transpositionTable.AddEntry(boardHashCode, ply, beta, TranspositionTableElementType.Beta, move.X, move.Y); #endif return(BEST_MOVE); } if (val > alpha) { alpha = val; #if USE_TRANSPOSITION_TABLE elementType = TranspositionTableElementType.Exact; bestMove = move; #endif } } } if (count == 0) { /* if no possible move */ board.SwitchPlayer(); int val = -GetBoardValueRecursive(board, ply, notStuck - 1, -beta, -alpha); board.SwitchPlayer(); return(val); } #if USE_TRANSPOSITION_TABLE if (bestMove != null) { _transpositionTable.AddEntry(boardHashCode, ply, alpha, elementType, bestMove.X, bestMove.Y); } else { _transpositionTable.AddEntry(boardHashCode, ply, alpha, elementType, -1, -1); } #endif return(alpha); }