/** Returns the best move to make from here during a playout. */ short bestSearchMove(SearchNode node, McRunnable runnable) { final Board runnableBoard = runnable.getBoard(); final MersenneTwisterFast random = runnable.getRandom(); short result = node.getWinningMove(); if (result != NO_POINT && runnableBoard.isLegal(result)) { // The isLegal() check is necessary to avoid superko violations return result; } float bestSearchValue = searchValue(node, PASS); result = PASS; final ShortSet vacantPoints = runnableBoard.getVacantPoints(); int start; start = random.nextInt(vacantPoints.size()); int i = start; final int skip = PRIMES[random.nextInt(PRIMES.length)]; do { final short move = vacantPoints.get(i); final float searchValue = searchValue(node, move); if (searchValue > bestSearchValue) { if (runnable.isFeasible(move) && runnableBoard.isLegal(move)) { bestSearchValue = searchValue; result = move; } else { node.exclude(move); } } // Advancing by a random prime skips through the array // in a manner analogous to double hashing. i = (i + skip) % vacantPoints.size(); } while (i != start); return result; }
@Override public short bestPlayMove() { double mostWins = 1; short result = PASS; final ShortSet vacantPoints = board.getVacantPoints(); final SearchNode root = getRoot(); do { mostWins = root.getWins(PASS); // If the move chosen on the previous pass through this loop was // illegal (e.g., because it was never actually tried in a playout), // throw it out if (result != PASS) { log("Rejected " + board.getCoordinateSystem().toString(result) + " as illegal"); root.exclude(result); result = PASS; } for (int i = 0; i < vacantPoints.size(); i++) { final short move = vacantPoints.get(i); if (root.getWins(move) > mostWins) { mostWins = root.getWins(move); result = move; } } } while (result != PASS && !board.isLegal(result)); // Consider resigning if (root.getWinRate(result) < RESIGN_PARAMETER) { return RESIGN; } log( "Selected " + board.getCoordinateSystem().toString(result) + " with " + root.getWins(result) + " wins in " + root.getRuns(result) + " runs"); return result; }