void doAddWord(Participant p, ArrayList<IndexPosition> currentWord) {
   String word = "";
   HashMap<IndexPosition, Token> tokenIndexByPosition = getTokenIndexByPosition();
   for (IndexPosition l : currentWord) {
     final BoardToken token = (BoardToken) tokenIndexByPosition.get(l);
     word += token.letter;
   }
   currentPath.put(p.getId(), currentWord);
   currentWords.get(p.getId()).add(word);
 }
 int getScore(final Participant p) {
   int thisScore = 0;
   for (final String s : getWordList(p.getId())) {
     thisScore += getWordScore(s);
   }
   return thisScore;
 }
  @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;
  }
 WordHuntGame doEnterWord(Participant p, final String currentWord) throws GameException {
   final ArrayList<String> wordList = getWordList(p.getId());
   final ArrayList<IndexPosition> wordPath = getPath(p.getId());
   if (wordList.contains(currentWord)) {
     WordHuntGame.this.doAddMessage("Already Entered: " + currentWord).setTo(p.getId());
     WordHuntGame.this.doSaveState();
   } else if (WordHuntGame.this.verifyWord(currentWord)) {
     WordHuntGame.this.doAddMessage(
         String.format(
             "%s spelled %s (%d points)",
             getDisplayName(p), currentWord, getWordScore(currentWord)));
     doAddWord(p, wordPath);
     doExplodeWord(p, wordPath);
   } else {
     WordHuntGame.this.doAddMessage("Rejected: " + currentWord).setTo(p.getId());
   }
   doClearCurrentWord(p.getId());
   doMaybeComplete();
   WordHuntGame.this.doSaveState();
   return this;
 }
 WordHuntGame doRollForLoot(Participant p) throws GameException {
   Account account = ((Player) p).getAccount();
   WordHuntLoot resource = account.getResource(WordHuntLoot.class);
   if (null == resource) {
     resource = new WordHuntLoot();
   }
   PromotionConfig promoConfig = resource.getLoot();
   if (null != promoConfig) {
     Promotion awardPromotion = account.doAwardPromotion(promoConfig);
     doAddMessage(awardPromotion.getMessage()).setTo(p.getId());
   }
   account.setResource(WordHuntLoot.class, resource);
   return this;
 }
  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 ArrayList<GameCommand> getMoves(final Participant access) throws GameException {
    final ArrayList<GameCommand> arrayList = new ArrayList<GameCommand>();
    if (_currentState == GameState.Lobby) {
      arrayList.addAll(_mplayerManager.getMoves(this, access));
    } else if (_currentState == GameState.Playing) {
      arrayList.add(
          new GameCommand() {

            @Override
            public CommandResult doCommand(Participant p, String commandText) throws GameException {
              ArrayList<ArrayList<IndexPosition>> paths = getFindWord(p, commandText);
              if (null == paths) return null;
              currentPath.put(p.getId(), paths.get(0));
              doEnterWord(p, commandText);
              return new CommandResult<WordHuntGame>(WordHuntGame.this);
            }

            @Override
            public String getCommandText() {
              return ""; // Filter everything
            }

            @Override
            public String getHelpText() {
              return "";
            }
          });

      final HashMap<IndexPosition, Token> tokenIndexByPosition = getTokenIndexByPosition();
      final ArrayList<IndexPosition> path = getPath(access.getId());
      final IndexPosition prevPosition = (0 == path.size()) ? null : path.get(path.size() - 1);
      for (int i = 0; i < NUM_ROWS; i++) {
        for (int j = 0; j < NUM_COLS; j++) {
          final String cmd = String.format("Select (%d, %d)", i, j);
          final IndexPosition position = new IndexPosition(i, j);
          if (tokenIndexByPosition.containsKey(position)) {
            final BoardToken token = (BoardToken) tokenIndexByPosition.get(position);
            arrayList.add(
                new GameCommand() {

                  @Override
                  public CommandResult doCommand(Participant p, String commandText)
                      throws GameException {
                    Player user = (Player) p;
                    if ((null != prevPosition) && !isAdjacent(position, prevPosition)) {
                      WordHuntGame.this
                          .doAddMessage("Non-adjacent letter selected: " + token.letter)
                          .setTo(user.getUserId());
                      doClearCurrentWord(user.getUserId());

                      getPath(user.getUserId()).add(position);
                      token.selectedFor.add(user.getUserId());
                      setSpellingBuffer(user.getUserId(), token.letter);

                      WordHuntGame.this.doSaveState();
                    } else {
                      final String tSpellingBuffer = getSpellingBuffer(user.getUserId());
                      final String currentWord = tSpellingBuffer + token.letter;

                      getPath(user.getUserId()).add(position);
                      token.selectedFor.add(user.getUserId());
                      setSpellingBuffer(user.getUserId(), currentWord);

                      doMaybeComplete();
                      WordHuntGame.this.doSaveState();
                    }
                    return new CommandResult<WordHuntGame>(WordHuntGame.this);
                  }

                  @Override
                  public String getCommandText() {
                    return cmd;
                  }

                  @Override
                  public String getHelpText() {
                    return "Submit the currently selected word";
                  }
                });
          }
        }
      }
      arrayList.add(
          new GameCommand() {
            public CommandResult doCommand(Participant p, String commandText) throws GameException {
              Player user = (Player) p;
              GameSession game = WordHuntGame.this.getSession();
              final String currentWord = getSpellingBuffer(user.getUserId());
              doEnterWord(user, currentWord);
              return new CommandResult<WordHuntGame>(WordHuntGame.this);
            }

            public String getCommandText() {
              return "Enter Word";
            }

            public String getHelpText() {
              return "Submit the currently selected word";
            }
          });
      arrayList.add(
          new GameCommand() {
            public CommandResult doCommand(Participant p, String commandText) throws GameException {
              Player user = (Player) p;
              GameSession game = WordHuntGame.this.getSession();
              doClearCurrentWord(user.getUserId());
              WordHuntGame.this.doSaveState();
              return new CommandResult<WordHuntGame>(WordHuntGame.this);
            }

            public String getCommandText() {
              return "Clear";
            }

            public String getHelpText() {
              return "Clear selected letters";
            }
          });
      arrayList.add(
          new GameCommand() {
            public CommandResult doCommand(Participant p, String commandText) throws GameException {
              Player user = (Player) p;
              GameSession game = WordHuntGame.this.getSession();
              playerStatus.put(user.getUserId(), PlayerState.Complete);
              doMaybeComplete();
              WordHuntGame.this.doSaveState();
              return new CommandResult<WordHuntGame>(WordHuntGame.this);
            }

            public String getCommandText() {
              return "Finish";
            }

            public String getHelpText() {
              return "Finish the game; no more words are found";
            }
          });
    }
    return arrayList;
  }