@Override
  public WordHuntGame doStart() throws GameException {
    final GameSession session = getSession();
    session.doUnitWager();
    for (final Participant p : _mplayerManager.getPlayerManager().getPlayers()) {
      if (p instanceof Agent<?>) {
        session.doWithdraw(-session.getUnitWager(), null, "Agent Ante Up");
      }
    }

    playerStatus.clear();
    currentWords.clear();
    currentPath.clear();
    _currentState = GameState.Playing;
    _roundEndTime = new Date(new Date().getTime() + (1000 * 60 * 5));

    doClearTokens();
    tokenArray = new TokenArray(NUM_ROWS, NUM_COLS);

    final ArrayList<ArrayPosition> pos = getRandomPositions(tokenArray);
    for (final ArrayPosition p : pos) {
      final BoardToken token = getGenerateToken(chainSize, getMarkovChain(), tokenArray, p);
      doAddToken(token);
    }
    return this;
  }
  @Override
  public Collection<GameLabel> getLabels(final Player access) throws GameException {
    final ArrayList<GameLabel> arrayList = new ArrayList<GameLabel>();
    if (_currentState == GameState.Lobby) {
      arrayList.addAll(_mplayerManager.getLobbyLabels(this, access));
    } else if (_currentState == GameState.Playing) {
      int idx = 0;
      GameLabel cmdButton =
          new GameLabel("SubmitWord", new IndexPosition(CURVE_CMDS, idx++), "Submit Word");
      cmdButton.setCommand("Enter Word");
      cmdButton.setWidth(150);
      arrayList.add(cmdButton);

      cmdButton = new GameLabel("Finish", new IndexPosition(CURVE_CMDS, idx++), "Finish");
      cmdButton.setCommand("Finish");
      cmdButton.setWidth(150);
      arrayList.add(cmdButton);

      cmdButton = new GameLabel("Clear", new IndexPosition(CURVE_CMDS, idx++), "Clear");
      cmdButton.setCommand("Clear");
      cmdButton.setWidth(150);
      arrayList.add(cmdButton);

      final long ctime = new Date().getTime();
      final long etime = _roundEndTime.getTime();
      final double timeLeft = (etime - ctime) / 1000.0;
      arrayList.add(
          new GameLabel(
              "TimeLeft",
              new IndexPosition(CURVE_CMDS, idx++),
              "<TIMER>" + Integer.toString((int) Math.ceil(timeLeft)) + "</TIMER> sec left"));

      final String txt =
          String.format(
              "My Score: %d (%d)", getScore(access), getWordList(access.getUserId()).size());
      arrayList.add(new GameLabel("WordCount", new IndexPosition(CURVE_CMDS, idx++), txt));

      for (final Participant p : _mplayerManager.getPlayerManager().getPlayers()) {
        if (p.equals(access)) {
          continue;
        }
        final String txt2 =
            String.format(
                "%s: %d (%d)", getDisplayName(p), getScore(access), getWordList(p.getId()).size());
        arrayList.add(new GameLabel("WordCount", new IndexPosition(CURVE_CMDS, idx++), txt2));
      }
    } else if (_currentState == GameState.Complete) {
      int idx = 0;
      final GameLabel cmdButton =
          new GameLabel("SubmitWord", new IndexPosition(CURVE_CMDS, idx++), "Deal Again");
      cmdButton.setCommand("Deal");
      cmdButton.setWidth(150);
      arrayList.add(cmdButton);
    }
    return arrayList;
  }
  public WordHuntGame doMaybeComplete() throws GameException {
    boolean isEveryoneDone = true;
    for (final Participant p : _mplayerManager.getPlayerManager().getPlayers()) {
      if (getPlayerStatus(p.getId()) == PlayerState.Playing) {
        isEveryoneDone = false;
        break;
      }
    }
    final boolean isTimeUp = _roundEndTime.before(new Date());
    if (!isEveryoneDone && !isTimeUp) return this;
    if (isEveryoneDone) {
      doAddMessage("Everyone is done!");
    }
    if (isTimeUp) {
      doAddMessage("Time is up!");
    }
    int winningScore = -1;
    Participant winner = null;
    for (final Participant p : _mplayerManager.getPlayerManager().getPlayers()) {
      final int thisScore = getScore(p);
      if (thisScore > winningScore) {
        winningScore = thisScore;
        winner = p;
      }
      doAddMessage("%s's score: %d", getDisplayName(p), thisScore);
    }
    if (isEveryoneDone || isTimeUp) {
      _currentState = GameState.Complete;
      doAddMessage("<strong>%s won</strong>", getDisplayName(winner));
      final GameSession session = getSession();
      final ArrayList<Player> collection = new ArrayList<Player>();
      if (winner instanceof Player) {
        doRollForLoot(winner);

        String type = "Win/WordHunt";
        String event = String.format("I won a game of WordHunt!");
        ((Player) winner).doLogActivity(new ActivityEvent(type, event));
        collection.add((Player) winner);
      }
      session.doSplitWagerPool(collection);
    }
    return this;
  }
 @Override
 public com.sawdust.engine.view.game.GameFrame getView(Player access) throws GameException {
   final com.sawdust.engine.view.game.GameFrame returnValue = super.getView(access);
   if (!_mplayerManager.getPlayerManager().isMember(access)) {
     Notification notification = new Notification();
     notification.notifyText = "You are currently observing this game.";
     notification.add("Join Table", "Join Game");
     returnValue.setNotification(notification);
   } else if (!isInPlay()) {
     Notification notification = new Notification();
     notification.notifyText = "No game is currently in progress";
     notification.add("Leave Table", "Leave Game");
     returnValue.setNotification(notification);
   }
   return returnValue;
 }
 @Override
 public Participant getCurrentPlayer() {
   return _mplayerManager.getPlayerManager().getCurrentPlayer();
 }