Example #1
0
 private int alphaBeta(
     Board board, int depth, int alpha, int beta, int player, int move, boolean nullMove) {
   if (forceHalt || interupted) return 0;
   //		if (timeCheck == 0) {
   //			// Check if still time left.
   //			if (System.currentTimeMillis() >= endTime) {
   //				forceHalt = true;
   //				return 0;
   //			}
   //			timeCheck = TIME_CHECK_INT;
   //		}
   //		timeCheck--;
   nodes++;
   // For win/loss depth
   int inv_depth = maxDepth - depth, value = N_INF, bestValue = N_INF;
   int capsw, capsb, olda = alpha, oldb = beta;
   int plyBestMove = -1, hashPos = 0, color = (player == myPlayer) ? 1 : -1;
   boolean valuefound = false, collision = false;
   int[] currentMoves;
   //
   Transposition tp = null;
   if (transpositions) {
     hashPos = getHashPos(board.zobristHash);
     tp = tt[hashPos];
     // Check if present in transposition table
     if (tp != null) {
       tt_lookups++;
       // Position was evaluated previously
       // Check for a collision
       if (tp.hash != board.zobristHash) {
         collisions++;
         collision = true;
       } else if (depth <= tp.depth) {
         if (tp.flag == Transposition.REAL) return tp.value;
         if (tp.flag == Transposition.L_BOUND && tp.value > alpha) alpha = tp.value;
         else if (tp.flag == Transposition.U_BOUND && tp.value < beta) beta = tp.value;
         if (alpha >= beta) return tp.value;
       }
     }
   }
   // Check if position is terminal.
   if (move != -1) {
     int winstate = board.checkWin(board.board[move]);
     if (winstate != Board.NONE_WIN) {
       if (winstate == player) {
         // Prefer shallow wins!
         bestValue = (WIN_VAL - (D_DECR * inv_depth));
         valuefound = true;
       } else if (winstate == Board.DRAW) {
         return 0;
       } else {
         // Deeper losses are "less worse" :) than shallow losses
         bestValue = -(WIN_VAL - (D_DECR * inv_depth));
         return bestValue;
       }
     }
   }
   // Leaf-node, evaluate the node
   if (depth == 0 && !valuefound) {
     bestValue = color * evaluate(board, inv_depth);
     valuefound = true;
   } else if (!valuefound) {
     // Don't do null moves at the first move, it messes up the swap rule
     if (nullmoves && !nullMove && depth < maxDepth && depth > R && !board.firstMove) {
       board.pass();
       // Check for a null-move cut-off
       value = -alphaBeta(board, depth - 1 - R, -beta, -alpha, getOpponent(player), -1, true);
       board.undoPass();
       if (value >= beta) {
         return beta;
       }
     }
     //
     if (tp == null || collision) {
       currentMoves = board.getAvailableMoves(killermove[inv_depth]);
     } else {
       currentMoves =
           board.getAvailableMoves(
               killermove[inv_depth][0], killermove[inv_depth][1], tp.bestMove);
     }
     int startindex = board.startindex, currentmove;
     double maxHistVal = 1.;
     for (int i = 0; i < currentMoves.length; i++) {
       // Try the killer and transposition moves first, then try the hh moves
       if (i >= startindex && maxHistVal > 0. && historyHeuristic) {
         board.getNextMove(history[player - 1], bfboard[player - 1], currentMoves, i);
         // If the previous max history value was 0, we can just follow the indexed list
         maxHistVal = board.maxHistVal;
       }
       currentmove = currentMoves[i];
       if (board.doMove(currentmove, player)) {
         // Returns false if suicide
         if (board.capturePieces(currentmove)) {
           //
           capsw = board.playerCaps[0];
           capsb = board.playerCaps[1];
           // Keep track of the captured pieces.
           captures[0] += capsw;
           captures[1] += capsb;
           //
           value =
               -alphaBeta(
                   board, depth - 1, -beta, -alpha, getOpponent(player), currentmove, nullMove);
           //
           if (value > bestValue) {
             // for detemining the move to return
             if (depth == maxDepth && value > bestValue) {
               bestMove = currentmove;
             }
             //
             bestValue = value;
             plyBestMove = currentmove;
           }
           //
           alpha = Math.max(alpha, bestValue);
           // Substract the captures from this move
           captures[0] -= capsw;
           captures[1] -= capsb;
           board.undoMove();
           // Update the butterfly board for the relative history heuristic
           bfboard[player - 1][currentmove]++;
           if (alpha >= beta) {
             if (killermoves && currentmove != killermove[inv_depth][0]) {
               killermove[inv_depth][1] = killermove[inv_depth][0];
               killermove[inv_depth][0] = currentmove;
             }
             break;
           }
         }
       } else {
         System.err.println("error making move!");
       }
     }
   }
   // Update the history heuristics for move-ordering
   if (plyBestMove > -1) history[player - 1][plyBestMove]++;
   // Replace if deeper or doesn't exist
   if (transpositions && (tp == null || (collision && depth > tp.depth))) {
     tp = new Transposition();
     tt[hashPos] = tp;
     tp.bestMove = plyBestMove;
     tp.depth = depth;
     tp.hash = board.zobristHash;
     //
     if (bestValue <= olda) {
       tp.flag = Transposition.U_BOUND;
     } else if (bestValue >= oldb) {
       tp.flag = Transposition.L_BOUND;
     } else {
       tp.flag = Transposition.REAL;
     }
     tp.value = bestValue;
   }
   return bestValue;
 }