Package org.gnubridge.presentation.gui

Source Code of org.gnubridge.presentation.gui.DealController$SearchController

package org.gnubridge.presentation.gui;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

import org.gnubridge.core.Card;
import org.gnubridge.core.Deal;
import org.gnubridge.core.Direction;
import org.gnubridge.core.North;
import org.gnubridge.core.South;
import org.gnubridge.core.bidding.Bid;
import org.gnubridge.search.DoubleDummySolver;
import org.gnubridge.search.ProductionSettings;
import org.jdesktop.swingworker.SwingWorker;

public class DealController implements CardPlayedListener {
  private static final int COMPUTER_PLAYER_IS_THINKING = 0;
  public static int MAX_SECONDS_TO_MOVE = 15;
  long start = -1;
  private static final int MILISECONDS_PER_SECOND = 1000;
  private static final long RIDICULOUSLY_LONG_WAIT_TIME = 100000000;
  private final long TIME_ALLOTED_PER_MOVE = MAX_SECONDS_TO_MOVE * MILISECONDS_PER_SECOND;

  public class Clock extends Thread {
    @Override
    public void run() {
      while (start >= COMPUTER_PLAYER_IS_THINKING) {
        view
            .displayTimeRemaining((int) (0.001 * (TIME_ALLOTED_PER_MOVE - (System.currentTimeMillis() - start))));
        try {
          Thread.sleep(1000);
        } catch (InterruptedException e) {
          e.printStackTrace();
          throw new RuntimeException(e);
        }
      }
      view.displayTimeRemaining(-1);
    }
  }

  public class SearchController extends SwingWorker<Void, String> {
    private static final int COMPUTER_PLAYER_FINISHED_THINKING = -1;
    Card bestMove;

    @Override
    protected Void doInBackground() throws Exception {
      start = System.currentTimeMillis();
      bestMove = findBestMoveAtDepth(1, RIDICULOUSLY_LONG_WAIT_TIME);
      for (int tricksSearchDepth = 2; tricksSearchDepth <= ProductionSettings.getSearchDepthRecommendation(game); tricksSearchDepth++) {
        long timePassedSinceStart = System.currentTimeMillis() - start;
        long timeRemaining = TIME_ALLOTED_PER_MOVE - timePassedSinceStart;
        if (!haveEnoughTimeToAttemptNextSearch(timeRemaining)) {
          System.out.println("// not enough time to attempt next search");
          break;
        }
        System.out.println("// now searching depth: " + tricksSearchDepth);
        try {
          bestMove = findBestMoveAtDepth(tricksSearchDepth, timeRemaining);
        } catch (TimeoutException e) {
          System.out.println("// could not complete full search of depth " + tricksSearchDepth
              + ", current best: " + bestMove);
          break;
        }
      }
      start = COMPUTER_PLAYER_FINISHED_THINKING;
      return null;
    }

    private boolean haveEnoughTimeToAttemptNextSearch(long timeRemaining) {
      return timeRemaining > TIME_ALLOTED_PER_MOVE * 2 / 3;
    }

    private Card findBestMoveAtDepth(int tricksSearchDepth, long timeoutMs) throws InterruptedException,
        ExecutionException, TimeoutException {
      SearchWorker searchWorker = new SearchWorker(tricksSearchDepth);
      searchWorker.execute();
      return searchWorker.get(timeoutMs, TimeUnit.MILLISECONDS);
    }

    @Override
    public void done() {
      playCard(bestMove);
    }
  }

  public class SearchWorker extends SwingWorker<Card, String> {
    DoubleDummySolver search;
    private final int maxTricksSearchDepth;

    public SearchWorker(int maxTricksSearchDepth) {
      this.maxTricksSearchDepth = maxTricksSearchDepth;

    }

    @Override
    protected Card doInBackground() throws Exception {
      search = new DoubleDummySolver(game);
      search.setMaxTricks(maxTricksSearchDepth);
      search.search();
      return search.getBestMoves().get(0);
    }
  }

  public class PreviousTrickDisplayWorker extends SwingWorker<Void, String> {

    @Override
    protected Void doInBackground() throws Exception {
      view.displayPreviousTrick();
      return null;
    }

    @Override
    public void done() {
      try {
        Thread.sleep(ProductionSettings.getMilisecondsToDisplayLastTrick());
      } catch (InterruptedException e) {
        throw new RuntimeException(e);
      }
      if (!game.isDone()) {
        view.displayCurrentTrick();
      }

    }
  }

  private final MainController parent;
  private final Deal game;
  private final Direction human;

  private final DealView view;
  private final ScoringTracker scoringTracker;
  private final Bid highBid;
  private SearchController searchThread;
  private Clock clockThread;

  public DealController(MainController controller, Bid highBid, Deal g, Direction humanDir, DealView playView,
      ScoringTracker tracker) {
    parent = controller;
    this.highBid = highBid;
    game = g;
    this.scoringTracker = tracker;
    game.printHandsDebug();
    human = humanDir;
    view = playView;
    view.setListener(this);
    view.setGame(game, human);
    view.setContract(highBid);
    doAutomatedPlay();
    view.displayStartingScore(scoringTracker);
  }

  public Deal getGame() {
    return game;
  }

  public Direction getHuman() {
    return human;
  }

  public boolean humanHasMove() {
    Direction nextToMove = game.getNextToPlay().getDirection2();
    if (human.equals(nextToMove) || (human.equals(South.i()) && nextToMove.equals(North.i()))) {
      return true;
    } else {
      return false;
    }
  }

  public synchronized void playCard(Card c) {
    System.out.println("game.play(" + c.toDebugString() + ");");
    game.play(c);
    if (game.getCurrentTrick().getCards().size() == 0 && game.getPreviousTrick() != null) {
      displayPreviousTrick();
    } else {
      view.displayCurrentTrick();
    }
    if (game.isDone()) {
      scoringTracker.processFinishedGame(human.getValue(), highBid, game.getDeclarerTricksTaken());
      view.displayFinalScore(scoringTracker);
    } else {
      doAutomatedPlay();
    }
  }

  public void displayPreviousTrick() {
    PreviousTrickDisplayWorker tdw = new PreviousTrickDisplayWorker();
    tdw.execute();
    while (!tdw.isDone()) {
      try {
        Thread.sleep(200);
      } catch (InterruptedException e) {
        throw new RuntimeException(e);
      }
    }

  }

  public void doAutomatedPlay() {
    if (humanHasMove()) {
      return;
    }
    searchThread = new SearchController();
    searchThread.execute();
    start = COMPUTER_PLAYER_IS_THINKING;
    clockThread = new Clock();
    clockThread.start();

  }

  public void newGame() {
    view.hide();
    parent.newGame();
  }

  public synchronized void forceMove() {
    if (searchThread == null || searchThread.isDone()) {
      return;
    }
    while (searchThread.bestMove == null) {
      try {
        Thread.sleep(500);
      } catch (InterruptedException e) {
        e.printStackTrace();
        throw new RuntimeException(e);
      }
    }
    searchThread.cancel(true);
    view.displayTimeRemaining(-1);
    start = COMPUTER_PLAYER_IS_THINKING;

  }
}
TOP

Related Classes of org.gnubridge.presentation.gui.DealController$SearchController

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.