Пример #1
0
 /** 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;
 }
Пример #2
0
 public McRunnable(Player player, CopiableStructure stuff) {
   LgrfTable table = null;
   try {
     table = stuff.get(LgrfTable.class);
   } catch (final IllegalArgumentException e) {
     // If we get here, we're not using LGRF
   }
   final CopiableStructure copy = stuff.copy();
   board = copy.get(Board.class);
   coords = board.getCoordinateSystem();
   suggesters = copy.get(Suggester[].class);
   weights = copy.get(int[].class);
   this.player = player;
   random = new MersenneTwisterFast();
   mover = copy.get(Mover.class);
   if (table != null) {
     final LgrfSuggester lgrf = copy.get(LgrfSuggester.class);
     lgrf.setTable(table);
   }
   scorer = copy.get(ChinesePlayoutScorer.class);
   mercyObserver = copy.get(StoneCountObserver.class);
   historyObserver = copy.get(HistoryObserver.class);
   filter = copy.get(Predicate.class);
   fancyHashes = new long[coords.getMaxMovesPerGame() + 1];
   playedPoints = new ShortSet(coords.getFirstPointBeyondBoard());
 }
Пример #3
0
 /**
  * Plays moves to the end of the game and returns the winner: BLACK, WHITE, or (in rare event of a
  * tie or a playout canceled because it hits the maximum number of moves) VACANT.
  *
  * @param mercy True if we should abandon the playout when one color has many more stones than the
  *     other.
  */
 public Color playout(boolean mercy) {
   do {
     if (board.getTurn() >= coords.getMaxMovesPerGame()) {
       // Playout ran out of moves, probably due to superko
       return VACANT;
     }
     if (board.getPasses() < 2) {
       selectAndPlayOneMove();
     }
     if (board.getPasses() >= 2) {
       // Game ended
       return scorer.winner();
     }
     final Color mercyWinner = mercyObserver.mercyWinner();
     if (mercy && mercyWinner != null) {
       // One player has far more stones on the board
       return mercyWinner;
     }
   } while (true);
 }
Пример #4
0
 public Color performMcRun(boolean mercy, Board originalBoard) {
   player.descend(this);
   Color winner;
   if (originalBoard.getPasses() == 2) {
     winner = scorer.winner();
   } else {
     winner = playout(mercy);
   }
   player.updateTree(winner, this);
   playoutsCompleted++;
   return winner;
 }
Пример #5
0
 @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;
 }
Пример #6
0
 /** Some nodes may have their biases updated. */
 @Override
 public void descend(McRunnable runnable) {
   SearchNode node = getRoot();
   assert node != null : "Fancy hash code: " + board.getFancyHash();
   while (runnable.getBoard().getPasses() < 2) {
     selectAndPlayMove(node, runnable);
     final SearchNode child = table.findIfPresent(runnable.getBoard().getFancyHash());
     if (child == null) {
       return; // No child
     }
     if (child.getTotalRuns() > biasDelay && !child.biasUpdated()) {
       child.updateBias(runnable);
     }
     node = child;
   }
 }
Пример #7
0
 @Override
 public void fakeDescend(McRunnable runnable, short... moves) {
   runnable.copyDataFrom(board);
   final SearchNode node = getRoot();
   assert node != null : "Fancy hash code: " + board.getFancyHash();
   for (final short move : moves) {
     System.out.println("Passing " + move + " to runnable");
     runnable.acceptMove(move);
     final SearchNode child = table.findIfPresent(runnable.getBoard().getFancyHash());
     if (child == null) {
       return; // No child
     }
     if (child.getTotalRuns() > biasDelay && !child.biasUpdated()) {
       child.updateBias(runnable);
     }
   }
 }
Пример #8
0
 /** Returns the root node (creating it if necessary). */
 SearchNode getRoot() {
   return table.findOrAllocate(board.getFancyHash());
 }
Пример #9
0
 /** Returns the current turn number on this runnable's board. */
 public int getTurn() {
   return board.getTurn();
 }
Пример #10
0
 /** Copies data from that (the player's real board) to the local board. */
 public void copyDataFrom(Board that) {
   board.copyDataFrom(that);
   fancyHashes[board.getTurn()] = board.getFancyHash();
 }
Пример #11
0
 /**
  * Accepts (plays on on this McRunnable's own board) the given move.
  *
  * @see edu.lclark.orego.core.Board#play(short)
  */
 public void acceptMove(short p) {
   final Legality legality = board.play(p);
   assert legality == OK
       : "Legality " + legality + " for move " + coords.toString(p) + "\n" + board;
   fancyHashes[board.getTurn()] = board.getFancyHash();
 }