/**
  * Chooses a solution for a new game.
  *
  * @return A Suggestion to be used as a solution.
  */
 private Suggestion chooseSolution() {
   List<Suggestion> suggestions = Suggestion.getSuggestions();
   Collections.shuffle(suggestions, random);
   return suggestions.get(0);
 }
  /**
   * Runs a single game.
   *
   * @throws IOException
   * @throws ProtocolViolation
   * @throws DuplicateSuggestion
   * @throws InvalidDisprove
   */
  public void run() throws IOException, ProtocolViolation, DuplicateSuggestion, InvalidDisprove {
    int playerCount = players.size();

    Suggestion solution = chooseSolution();
    System.out.format("Chosen Solution: %s\n", solution);

    List<List<Card>> hands = buildHands(solution);
    for (int i = 0; i < playerCount; ++i) {
      players.get(i).reset(playerCount, i, hands.get(i));
    }

    int active = 0;
    int stillPlaying = playerCount;
    while (stillPlaying > 1) {
      Player current = players.get(active);
      Suggestion suggestion = current.suggest();
      System.out.format("%s suggests %s\n", current, suggestion);

      Card shown = null;
      int disprover;
      for (disprover = getNextPlayerIndex(active);
          disprover != active;
          disprover = getNextPlayerIndex(disprover)) {
        Player next = players.get(disprover);
        if (next.canDisprove(suggestion)) {
          System.out.format("%s can disprove.\n", next);
          shown = next.disprove(active, suggestion);
          System.out.format("%s shows %s.\n", next, shown);
          break;
        }

        System.out.format("%s cannot disprove...\n", next);
      }

      for (int i = 0; i < playerCount; ++i) {
        players.get(i).suggestion(active, suggestion, shown == null ? null : disprover, shown);
      }

      Suggestion accusation = current.accuse();
      if (accusation != null) {
        boolean correct = accusation.equals(solution);

        System.out.format(
            "%s makes the accusation %s... it is %s\n",
            current, accusation, (correct ? "right!" : "wrong."));

        if (correct) {
          stillPlaying = 0;
        } else {
          current.lose();
          --stillPlaying;
        }

        for (int i = 0; i < playerCount; ++i) {
          players.get(i).accusation(active, accusation, correct);
        }
      } else {
        System.out.format("%s makes no accusation\n", current);
      }

      if (stillPlaying > 0) {
        do {
          active = getNextPlayerIndex(active);
        } while (players.get(active).isEliminated());
      }
    }

    if (stillPlaying == 1) {
      System.out.format("%s wins by default.\n", players.get(active));
    }
  }
 /**
  * Gets the deck of Cards to deal to the Players.
  *
  * @param solution The Cards that have been removed from the deck.
  * @return A List of the Cards that remain to deal to Players.
  */
 private List<Card> getDeck(Suggestion solution) {
   List<Card> deck = Card.getCards();
   deck.removeAll(solution.getCards());
   return deck;
 }