public static double estimateFlopOddsByMonteCarlo(
      ArrayList<Card> mine, ArrayList<Card> table, ArrayList<ArrayList<Card>> opponents) {
    double winCount = 0;

    ArrayList<Card> baseAlreadyOut = new ArrayList<Card>();
    baseAlreadyOut.addAll(mine);
    baseAlreadyOut.addAll(table);
    for (ArrayList<Card> opp : opponents) {
      baseAlreadyOut.addAll(opp);
    }

    for (int i = 0; i < 500; i++) {
      ArrayList<Card> newOut = new ArrayList<Card>();
      newOut.addAll(baseAlreadyOut);

      ArrayList<Card> newTable = new ArrayList<Card>();
      newTable.addAll(table);
      while (newTable.size() < 5) {
        Card c = RandomCardGenerator.randomCard(newOut);
        newTable.add(c);
        newOut.add(c);
      }

      ArrayList<Card> newMine = new ArrayList<Card>();
      newMine.addAll(mine);

      while (newMine.size() < 2) {
        Card c = RandomCardGenerator.randomCard(newOut);
        newMine.add(c);
        newOut.add(c);
      }
      newMine.addAll(newTable);

      ArrayList<ArrayList<Card>> newOpps = new ArrayList<ArrayList<Card>>();
      for (ArrayList<Card> opp : opponents) {
        ArrayList<Card> newOpp = new ArrayList<Card>();
        newOpp.addAll(opp);

        while (newOpp.size() < 2) {
          Card c = RandomCardGenerator.randomCard(newOut);
          newOpp.add(c);
          newOut.add(c);
        }
        newOpp.addAll(newTable);
        newOpps.add(newOpp);
      }
      newMine.addAll(newTable);
      if (HandEvaluator.compare(newMine, newOpps, newTable)) {
        winCount += 1;
      }
    }
    return winCount / 500;
  }
  private double boardWetnessPostRiver() {
    Card[] opponentHand = new Card[2];

    // iterate through all possible opponent hands
    // note that two card opponent hand is an approximation
    for (int i = 0; i < cardCount; i += skip) {
      if (usedCards[i]) continue;

      opponentHand[0] = cardByID[i];

      for (int j = i + 1; j < cardCount; j += skip) {
        if (usedCards[j]) continue;

        opponentHand[1] = cardByID[j];

        totalHands++;
        totalValue += HandEvaluator.getHandRank(board, opponentHand).val;
      }
    }

    return getEquity();
  }
  public void Auto(Table tab) {

    for (int i = 0; i < tab.countPlayers(); i++) {
      System.out.println("player: " + i + "status: " + tab.getSystemPlayer(i).getPlayerStatus());
    }

    if (tab.countNonQuitPlayers() > 0) {
      nextState = tab.NewTurnState;
      if (tab.countNonQuitPlayers() == 1) {
        nextState = tab.stopGameState;
      }

      winners = new LinkedList<Boolean>();
      // initWinnersFalse(tab);
      cardRanks = new LinkedList<Integer>();
      Pots = new LinkedList<Integer>();
      PotsPerGamer = new LinkedList<Integer>();

      // wyłoń zwycięzców (sfoldowani i squitowani automatycznie przegrali)
      evaluator = new HandEvaluator();
      PlayerStatus status;
      for (int i = 0; i < tab.countPlayers(); i++) {
        status = tab.getSystemPlayer(i).getPlayerStatus();
        if ((status == PlayerStatus.folded) || (status == PlayerStatus.quit)) {
          cardRanks.add(80000);
        } else {
          evaluator
              .initWithTableCards(tab.getTabofTableCards())
              .initWithHoleCards(tab.getTabofPlayerCards(i));
          cardRanks.add(evaluator.eval());
        }
      }
      // wysw ranki
      for (int i = 0; i < cardRanks.size(); i++) {
        System.out.println(cardRanks.get(i));
      }

      // tworzy pule boczne
      IntsComp comp = new IntsComp();
      LinkedList<Integer> SortedBets = tab.getPlayersBets();
      Collections.sort(SortedBets, comp);
      Integer no = SortedBets.size();
      Pots.add(SortedBets.get(0) * no);
      PotsPerGamer.add(SortedBets.get(0));
      for (int i = 1; i < SortedBets.size(); i++) {
        int diff = SortedBets.get(i) - SortedBets.get(i - 1);
        // System.out.println("Diff: "+diff);
        if (diff > 0) {
          // System.out.println("Diff is greter. Add: "+diff*(no-i));
          Pots.add(diff * (no - i));
          PotsPerGamer.add(diff);
        }
      }

      for (int i = 0; i < tab.countPlayers(); i++) {
        System.out.println("BETS:" + tab.getSystemPlayer(i).getPlayerBet());
      }

      // wysw pule
      for (int i = 0; i < Pots.size(); i++) {
        System.out.println("POTS:" + Pots.get(i));
      }
      for (int i = 0; i < PotsPerGamer.size(); i++) {
        System.out.println("PGamer:" + PotsPerGamer.get(i));
      }

      // podziel bank między graczy (update kredytów)
      for (int i = 0; i < Pots.size(); i++) {
        prize = 0;
        findWinners(i, tab);
        if (winnersCount != 0) {
          prize = Pots.get(i) / winnersCount;
        }
        for (int j = 0; j < winners.size(); j++) {
          if (winners.get(j) == true) {
            tab.getSystemPlayer(j).incrPlayerCredits(prize);
            System.out.println("Winner: " + j + "Pot: " + i + " +PRIZE: " + prize);
          }
        }
      }
      /*
      winnersCount=0;
      bestRank=0;
      for(int i=0;i<cardRanks.size();i++){
      	if(cardRanks.get(i)>bestRank){
      		bestRank=cardRanks.get(i);
      	}
      }

      for(int i=0;i<tab.countPlayers();i++){
      	if(cardRanks.get(i)==bestRank){
      		winnersCount+=1;
      		winners.set(i,true);
      	}
      }
      */
      // zabierz karty graczom oraz ze stołu
      tab.cleanCards();

      // wykasuj bank
      tab.setBank(0);

      // wykasuj bety graczom
      tab.cleanBets();

      // przywróć wszystkich graczy  fo stanu init (poza squitowanymi);
      tab.initializePlayers();

      //
    } else {
      nextState = tab.stopGameState;
      if (tab.countNonQuitPlayers() > 0) {
        try {
          tab.getSystemPlayer(tab.nextNonQuitPlayer(0))
              .notify("W grze pozostał jeden gracz. Koniec gry.");
        } catch (RunOutOfPlayersException e) {

        }
      }
    }

    tab.setState(nextState);
    // tab.Auto();
  }
 private int calculateHandType(Hand newHand) {
   HandEvaluator evaluator = new HandEvaluator(newHand);
   int handType = evaluator.getType().getValue();
   return handType;
 }
 /**
  * Returns the potential value as a double in one situation
  *
  * <p>This method should be used to calculate the potential value.
  *
  * @return the potential value in one situation
  */
 private double calculateHandValue(Hand newHand) {
   HandEvaluator evaluator = new HandEvaluator(newHand);
   int cardValue = evaluator.getValue();
   return cardValue;
 }