├── players.txt ├── Player.java ├── Deck.java ├── Card.java ├── BotPlayer.java ├── PokerSimulation.java ├── BotPlayer2.java ├── Scoreboard.java ├── README.md ├── Hand.java └── Game.java /players.txt: -------------------------------------------------------------------------------- 1 | BotPlayer 2 | BotPlayer 3 | BotPlayer 4 | BotPlayer2 -------------------------------------------------------------------------------- /Player.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | 3 | public interface Player { 4 | public abstract Double makeMove(List hand, List communityCards, Double pot, Double current_bet, Double chips, Double already_bet, Double[] playerChips, Double[] bets, int index, int dealer_index); 5 | } 6 | -------------------------------------------------------------------------------- /Deck.java: -------------------------------------------------------------------------------- 1 | import java.util.ArrayList; 2 | import java.util.Collections; 3 | import java.util.Random; 4 | 5 | public class Deck { 6 | private ArrayList cards = new ArrayList<>(); 7 | Random rng; 8 | public Deck() { 9 | rng = new Random(); 10 | String[] suits = {"Hearts", "Diamonds", "Clubs", "Spades"}; 11 | String[] ranks = {"2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A"}; 12 | 13 | for (String suit : suits) { 14 | for (String rank : ranks) { 15 | cards.add(new Card(rank, suit)); 16 | } 17 | } 18 | shuffle(); 19 | } 20 | 21 | public String toString() { 22 | String res = ""; 23 | for (Card c : cards) res = res + c.toString() + " "; 24 | return res; 25 | } 26 | 27 | public void shuffle() { 28 | Collections.shuffle(cards, rng); 29 | } 30 | 31 | public Card draw() { 32 | return cards.isEmpty() ? null : cards.remove(cards.size() - 1); 33 | } 34 | 35 | public int remainingCards() { 36 | return cards.size(); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Card.java: -------------------------------------------------------------------------------- 1 | public class Card { 2 | private String rank; 3 | private String suit; 4 | 5 | public Card(String rank, String suit) { 6 | this.rank = rank; 7 | this.suit = suit; 8 | } 9 | 10 | public String getRank() { 11 | return rank; 12 | } 13 | 14 | public String getSuit() { 15 | return suit; 16 | } 17 | public String toString() { 18 | return rank + " " + suit; 19 | } 20 | public int getRankValue() { 21 | switch (rank) { 22 | case "A": 23 | return 14; 24 | case "K": 25 | return 13; 26 | case "Q": 27 | return 12; 28 | case "J": 29 | return 11; 30 | case "10": 31 | return 10; 32 | case "9": 33 | return 9; 34 | case "8": 35 | return 8; 36 | case "7": 37 | return 7; 38 | case "6": 39 | return 6; 40 | case "5": 41 | return 5; 42 | case "4": 43 | return 4; 44 | case "3": 45 | return 3; 46 | case "2": 47 | return 2; 48 | default: 49 | return 0; // Invalid rank 50 | } 51 | } 52 | } -------------------------------------------------------------------------------- /BotPlayer.java: -------------------------------------------------------------------------------- 1 | import java.util.List; 2 | 3 | public class BotPlayer implements Player { 4 | /** 5 | * TODO: implement this function (replace the name of the class with your name in your new file) 6 | * 7 | * @param hand The player's current hand (list of cards). 8 | * @param communityCards The community cards available on the table. 9 | * @param pot The total amount of chips in the pot. 10 | * @param current_bet The highest current bet in the round. 11 | * @param chips The player's remaining chips. 12 | * @param already_bet The player's current bet. 13 | * @param playerChips An array representing the chips each player has. 14 | * @param bets An array representing the current bets of each player. 15 | * @param index The index of the player making the move. 16 | * @param dealer_index The index of the dealer 17 | * @return The amount to bet: 18 | * - Return `current_bet` to call. 19 | * - Return at least twice `current_bet` or all remaining `chips` to raise. 20 | * - Return any other value to fold. 21 | */ 22 | public Double makeMove(List hand, List communityCards, Double pot, Double current_bet, Double chips, Double already_bet, Double[] playerChips, Double[] bets, int index, int dealer_index) { 23 | return Math.min(current_bet, chips); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /PokerSimulation.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | import java.io.*; 3 | public class PokerSimulation { 4 | public static boolean PRINT_VERBOSE = true; 5 | 6 | public static final String PLAYER_FILENAME = "players.txt"; 7 | 8 | private static ArrayList playerNames = new ArrayList(); 9 | private static ArrayList playerClasses = new ArrayList(); 10 | 11 | public static int GAMES = 100; 12 | 13 | public static void main(String args[]) { 14 | int numGames = GAMES; 15 | try { 16 | loadPlayerData(); 17 | Scoreboard s = new Scoreboard(playerNames.toArray(new String[0])); 18 | for (int i = 0; i < numGames; i++) { 19 | Game g = new Game(s,playerClasses, i); 20 | int winner = g.play(); 21 | System.out.println("Game " + i + ": player " + winner + " (" + playerNames.get(winner) + ") wins!"); 22 | } 23 | System.out.println(s); 24 | } 25 | catch (Exception e) { 26 | e.printStackTrace(); 27 | } 28 | } 29 | 30 | private static void loadPlayerData() throws Exception { 31 | BufferedReader br = new BufferedReader(new FileReader(PLAYER_FILENAME)); 32 | String playerLine = br.readLine(); 33 | while (playerLine != null) { 34 | Scanner line = new Scanner(playerLine); 35 | String s = line.next(); 36 | playerNames.add(s); 37 | playerClasses.add(s); 38 | playerLine = br.readLine(); 39 | line.close(); 40 | } 41 | br.close(); 42 | } 43 | } -------------------------------------------------------------------------------- /BotPlayer2.java: -------------------------------------------------------------------------------- 1 | import java.util.List; 2 | import java.util.Random; 3 | 4 | public class BotPlayer2 implements Player { 5 | /** 6 | * TODO: implement this function (replace the name of the class with your name in your new file) 7 | * 8 | * @param hand The player's current hand (list of cards). 9 | * @param communityCards The community cards available on the table. 10 | * @param pot The total amount of chips in the pot. 11 | * @param current_bet The highest current bet in the round. 12 | * @param chips The player's remaining chips. 13 | * @param already_bet The player's current bet. 14 | * @param playerChips An array representing the chips each player has. 15 | * @param bets An array representing the current bets of each player. 16 | * @param index The index of the player making the move. 17 | * @param dealer_index The index of the dealer 18 | * @return The amount to bet: 19 | * - Return `current_bet` to call. 20 | * - Return at least twice `current_bet` or all remaining `chips` to raise. 21 | * - Return any other value to fold. 22 | */ 23 | public Double makeMove(List hand, List communityCards, Double pot, Double current_bet, Double chips, Double already_bet, Double[] playerChips, Double[] bets, int index, int dealer_index) { 24 | Random rng = new Random(); 25 | if (rng.nextInt() > (1<<28)) { 26 | return Math.min(chips, current_bet); //call 27 | } 28 | else if (rng.nextBoolean()) { 29 | return chips; //go all in 30 | } 31 | else { 32 | return 0.; //fold 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Scoreboard.java: -------------------------------------------------------------------------------- 1 | public class Scoreboard 2 | { 3 | private String playerList[]; 4 | private int scores[]; 5 | 6 | public Scoreboard(String playerList[]) { 7 | scores = new int[playerList.length]; 8 | for (int i = 0; i < playerList.length; i++) { 9 | scores[i] = 0; 10 | } 11 | this.playerList = playerList; 12 | } 13 | 14 | public void addToScore(int player, int points) { 15 | scores[player] += points; 16 | } 17 | 18 | public int getScore(int player) { 19 | return scores[player]; 20 | } 21 | 22 | public String toString() { 23 | String retval = ""; 24 | for (int i = 0; i < scores.length; i++) { 25 | retval += "Player #" + i + " (" + playerList[i] + "): " + scores[i] + " wins\n"; 26 | } 27 | return retval; 28 | } 29 | 30 | /** 31 | * Return the list of player names. 32 | */ 33 | public String[] getPlayerList() { 34 | return playerList; 35 | } 36 | 37 | /** 38 | * Return the number of players in the game. 39 | */ 40 | public int getNumPlayers() { 41 | return playerList.length; 42 | } 43 | 44 | /** 45 | * Return the zero-based number of the player who has won the game, 46 | * presuming someone has. (This method should only be called 47 | * once the end of the entire match has been detected by some other 48 | * means, and returns the number of the player with the highest score.) 49 | */ 50 | public int getWinner() { 51 | int winner = 0; 52 | int topScore = scores[0]; 53 | 54 | for (int i = 1; i < scores.length; i++) { 55 | if (scores[i] > topScore) { 56 | topScore = scores[i]; 57 | winner = i; 58 | } 59 | } 60 | return winner; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SBUPokerCompetition 2 | Template for the Stony Brook Computing Society's Poker Bot Tournament for Geek Games. 3 | 4 | Copy BotPlayer.java and rename it with your name, and implement the makeMove function (to call, return bet; to raise, return **at least twice current bet or your remaining chips**; and any other number to fold), list player names in players.txt to run games with them, and run PokerSimulation.java to simulate 100 rounds with those players. There are two bots, BotPlayer.java and BotPlayer2.java for you to test your code against- the current setup in players.txt has three BotPlayers playing against one BotPlayer2. 5 | 6 | You do NOT need to use all arguments for your bot, they are only there for convenience. 7 | 8 | Card interface: getRank() returns "2" to "10", "J", "Q", "K", or "A" (there is getRankValue() which returns the corresponding "value" from 2 to 14), getSuit() returns one of "Hearts", "Diamonds", "Clubs", "Spades" 9 | 10 | List hand is a list of the two cards you have. 11 | 12 | List communityCards is a list of the communityCards 13 | 14 | pot is the amount in the pot. 15 | 16 | current_bet is the amount that someone bet that you need to match/call/raise. 17 | 18 | chips is the amount of chips you have. 19 | 20 | already_bet is the amount that you have already bet (for example, binds or how much you raised but someone reraised you). 21 | 22 | playerChips is an array of the amount of chips all players have. 23 | 24 | bets is an array of all bets that have been made. 25 | 26 | index is your index in the two above arrays. 27 | 28 | dealer_index is the index of the dealer. 29 | 30 | Finally, learn Java here! https://www.w3schools.com/java/default.asp 31 | 32 | # Code Submissions 33 | 34 | When you are done coding your bot, submit your program **[here](https://docs.google.com/forms/d/e/1FAIpQLSeSl6_iEJTGXu3T41AW8iNbE_sYoXJYYY43_uzvx9CG8xtUKA/viewform?usp=dialog).** Your code will be run in a tournament with 4-6 people who submit at around the same time. 35 | 36 | Have fun! 37 | -------------------------------------------------------------------------------- /Hand.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | 3 | public class Hand { 4 | private ArrayList cards; 5 | private Player player; 6 | private String playerName; 7 | 8 | public Hand(String playerClassName, String playerName) { 9 | try { 10 | //System.out.println("Initializing " + playerName); 11 | player = (Player) Class.forName(playerClassName).newInstance(); 12 | } 13 | catch (Exception e) { 14 | System.out.println("Problem with " + playerClassName + "."); 15 | e.printStackTrace(); 16 | System.exit(1); 17 | } 18 | this.playerName = playerName; 19 | cards = new ArrayList(); 20 | } 21 | 22 | public void reset() { 23 | cards = new ArrayList(); 24 | } 25 | 26 | Double play(List communityCards, Double pot, Double current_bet, Double chips, Double already_bet, Double[] playerChips, Double[] bets, int index, int dealer_index) { 27 | ArrayList communityCardsCopy = new ArrayList(); 28 | for (Card c : communityCards) { 29 | communityCardsCopy.add(c); 30 | } 31 | ArrayList cardsCopy = new ArrayList(); 32 | for (Card c : cards) { 33 | cardsCopy.add(c); 34 | } 35 | return player.makeMove(cardsCopy, communityCardsCopy, pot, current_bet, chips, already_bet, playerChips, bets, index, dealer_index); 36 | } 37 | 38 | void addCard(Card c) { 39 | cards.add(c); 40 | } 41 | 42 | public List getCards() { 43 | return cards; 44 | } 45 | 46 | public String getPlayerName() { 47 | return playerName; 48 | } 49 | 50 | int straight_flush() { 51 | ArrayList flush_cards = new ArrayList<>(); 52 | for (int i = 0; i < 7; i++) { 53 | if (cards.get(i).getSuit()=="Hearts") { 54 | flush_cards.add(i); 55 | } 56 | } 57 | if (flush_cards.size() < 5) { 58 | flush_cards = new ArrayList<>(); 59 | for (int i = 0; i < 7; i++) { 60 | if (cards.get(i).getSuit()=="Diamonds") { 61 | flush_cards.add(i); 62 | } 63 | } 64 | } 65 | if (flush_cards.size() < 5) { 66 | flush_cards = new ArrayList<>(); 67 | for (int i = 0; i < 7; i++) { 68 | if (cards.get(i).getSuit()=="Clubs") { 69 | flush_cards.add(i); 70 | } 71 | } 72 | } 73 | if (flush_cards.size() < 5) { 74 | flush_cards = new ArrayList<>(); 75 | for (int i = 0; i < 7; i++) { 76 | if (cards.get(i).getSuit()=="Spades") { 77 | flush_cards.add(i); 78 | } 79 | } 80 | } 81 | for (int i = 4; i < flush_cards.size(); i++) { 82 | if (cards.get(flush_cards.get(i)).getRankValue() + 4 == cards.get(flush_cards.get(i-4)).getRankValue()) 83 | return 800000000 + cards.get(flush_cards.get(i-4)).getRankValue(); 84 | } 85 | return 0; 86 | } 87 | int four() { 88 | for (int i = 3; i < 7; i++) { 89 | if (cards.get(i).getRankValue() == cards.get(i-3).getRankValue()) { 90 | int ret = cards.get(0).getRankValue(); 91 | if (i==3) ret = cards.get(4).getRankValue(); 92 | ret += 700000000; 93 | return ret; 94 | } 95 | } 96 | return 0; 97 | } 98 | int house() { 99 | for (int i = 2; i < 7; i++) { 100 | if (cards.get(i).getRankValue() == cards.get(i-2).getRankValue()) { 101 | for (int j = 1; j < 7; j++) { 102 | if ((j > i+1 || j < i-2) && cards.get(i).getRankValue() == cards.get(i-1).getRankValue()) { 103 | return 600000000 + 100 * cards.get(i).getRankValue() + cards.get(j).getRankValue(); 104 | } 105 | } 106 | } 107 | } 108 | return 0; 109 | } 110 | int flush() { 111 | ArrayList flush_cards = new ArrayList<>(); 112 | for (int i = 0; i < 7; i++) { 113 | if (cards.get(i).getSuit()=="Hearts") { 114 | flush_cards.add(i); 115 | } 116 | } 117 | if (flush_cards.size() < 5) { 118 | flush_cards = new ArrayList<>(); 119 | for (int i = 0; i < 7; i++) { 120 | if (cards.get(i).getSuit()=="Diamonds") { 121 | flush_cards.add(i); 122 | } 123 | } 124 | } 125 | if (flush_cards.size() < 5) { 126 | flush_cards = new ArrayList<>(); 127 | for (int i = 0; i < 7; i++) { 128 | if (cards.get(i).getSuit()=="Clubs") { 129 | flush_cards.add(i); 130 | } 131 | } 132 | } 133 | if (flush_cards.size() < 5) { 134 | flush_cards = new ArrayList<>(); 135 | for (int i = 0; i < 7; i++) { 136 | if (cards.get(i).getSuit()=="Spades") { 137 | flush_cards.add(i); 138 | } 139 | } 140 | } 141 | if (flush_cards.size() >= 5) { 142 | return 500000000 + 15 * 15 * 15 * 15 * cards.get(flush_cards.get(0)).getRankValue() + 15 * 15 * 15 * cards.get(flush_cards.get(1)).getRankValue() + 15 * 15 * cards.get(flush_cards.get(2)).getRankValue() + 15 * cards.get(flush_cards.get(3)).getRankValue() + cards.get(flush_cards.get(4)).getRankValue(); 143 | } 144 | return 0; 145 | } 146 | int straight() { 147 | int[] has = new int[15]; 148 | for (Card c : cards) { 149 | has[c.getRankValue()] = 1; 150 | } 151 | for (int i = 14; i > 5; i--) { 152 | if (has[i]==1 && has[i-1]==1 && has[i-2]==1 && has[i-3]==1 && has[i-4]==1) { 153 | return 400000000 + i; 154 | } 155 | } 156 | return 0; 157 | } 158 | int three() { 159 | for (int i = 2; i < 7; i++) { 160 | if (cards.get(i).getRankValue() == cards.get(i-2).getRankValue()) { 161 | for (int j = 0; j < 7;) { 162 | if (j >= i-2 && j <= i) j++; 163 | int k = j+1; 164 | if (k==i-2) { 165 | k = i+1; 166 | } 167 | return 300000000 + 100 * cards.get(j).getRankValue() + cards.get(k).getRankValue(); 168 | } 169 | } 170 | } 171 | return 0; 172 | } 173 | int two_pair() { 174 | for (int i = 1; i < 7; i++) { 175 | if (cards.get(i).getRankValue() == cards.get(i-1).getRankValue()) { 176 | for (int j = i+2; j < 7; j++) { 177 | if (cards.get(j).getRankValue() == cards.get(j-1).getRankValue()) { 178 | int k = 0; 179 | while (k==i-1 || k==i || k==j || k==j-1) k++; 180 | return 200000000 + 10000 * cards.get(i).getRankValue() + 100 * cards.get(j).getRankValue() + cards.get(k).getRankValue(); 181 | } 182 | } 183 | } 184 | } 185 | return 0; 186 | } 187 | int pair() { 188 | for (int i = 1; i < 7; i++) { 189 | if (cards.get(i).getRankValue() == cards.get(i-1).getRankValue()) { 190 | int ret = 100000000 + 15 * 15 * 15 * cards.get(i).getRankValue(); 191 | for (int j = 0, cnt = 2; j < 7 && cnt >= 0; j++) { 192 | if (j==i-1 || j==i) continue; 193 | cnt--; 194 | ret += Math.pow(15, cnt) * cards.get(j).getRankValue(); 195 | } 196 | return ret; 197 | } 198 | } 199 | return 0; 200 | } 201 | int high_card_value() { 202 | int ret = 0; 203 | for (int i = 0; i < 5; i++) { 204 | ret += Math.pow(15, 4-i) * (cards.get(i).getRankValue()); 205 | } 206 | return ret; 207 | } 208 | int evaluate() { 209 | Collections.sort(cards, new Comparator() { 210 | @Override 211 | public int compare(Card card1, Card card2) { 212 | return card2.getRankValue() - card1.getRankValue(); 213 | } 214 | }); 215 | if (straight_flush()>0) 216 | return straight_flush(); 217 | else if (four()>0) { 218 | return four(); 219 | } 220 | else if (house()>0) { 221 | return house(); 222 | } 223 | else if (flush()>0) { 224 | return flush(); 225 | } 226 | else if (straight()>0) { 227 | return straight(); 228 | } 229 | else if (three()>0) { 230 | return three(); 231 | } 232 | else if (two_pair()>0) { 233 | return two_pair(); 234 | } 235 | else if (pair()>0) { 236 | return pair(); 237 | } 238 | return high_card_value(); 239 | } 240 | public String toString() { 241 | String res = ""; 242 | for (Card c : cards) { 243 | res += c.toString() + " "; 244 | } 245 | return res; 246 | } 247 | } -------------------------------------------------------------------------------- /Game.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | 3 | public class Game { 4 | static final boolean PRINT_VERBOSE = true; 5 | 6 | private Deck deck; 7 | private Hand playerHands[]; 8 | private List communityCards; 9 | private int dealer; 10 | private Scoreboard scoreboard; 11 | private Double playerChips[]; 12 | private final Double BIG_BIND = 20.; 13 | private final Double SMALL_BIND = 10.; 14 | private final Double STARTING_CHIPS = 1000.; 15 | private final Double eps = 1e-6; 16 | 17 | private boolean eq(Double a, Double b) { 18 | return (Math.abs(a-b) < eps); 19 | } 20 | 21 | public Game(Scoreboard scoreboard, ArrayList playerClassList, int start) { 22 | this.scoreboard = scoreboard; 23 | deck = new Deck(); 24 | playerHands = new Hand[scoreboard.getNumPlayers()]; 25 | playerChips = new Double[scoreboard.getNumPlayers()]; 26 | try { 27 | for (int i = 0; i < scoreboard.getNumPlayers(); i++) { 28 | playerHands[i] = new Hand(playerClassList.get(i), 29 | scoreboard.getPlayerList()[i]); 30 | for (int j = 0; j < 2; j++) { 31 | playerHands[i].addCard(deck.draw()); 32 | } 33 | playerChips[i] = STARTING_CHIPS; 34 | } 35 | } 36 | catch (Exception e) { 37 | System.out.println("Can't deal initial hands!"); 38 | System.exit(1); 39 | } 40 | dealer = start % scoreboard.getNumPlayers(); 41 | } 42 | public int getNextPlayer() { 43 | return (dealer + 1) % scoreboard.getNumPlayers(); 44 | } 45 | 46 | void nextRound() { 47 | dealer = getNextPlayer(); 48 | } 49 | 50 | void addCommunityCard() { 51 | try { 52 | communityCards.add(deck.draw()); 53 | } 54 | catch (Exception e) { 55 | println("DECK IS COOKED"); 56 | } 57 | } 58 | public int play() { 59 | try { 60 | while (true) { 61 | communityCards = new ArrayList(); 62 | //first time is (dealer+3)%n 63 | deck = new Deck(); 64 | Double pot = BIG_BIND + SMALL_BIND; 65 | Double bet = BIG_BIND; 66 | int n = scoreboard.getNumPlayers(); 67 | int cnt = 0; 68 | Double bets[] = new Double[n]; 69 | for (int i = 0; i < n; i++) bets[i] = 0.; 70 | boolean folded[] = new boolean[n]; 71 | for (int i = 0; i < n; i++) { 72 | playerHands[i].reset(); 73 | if (playerChips[i]>0.0001) { 74 | cnt++; 75 | playerHands[i].addCard(deck.draw()); 76 | playerHands[i].addCard(deck.draw()); 77 | } 78 | else folded[i] = true; 79 | } 80 | if (cnt<=1) { 81 | for (int i = 0; i < n; i++) { 82 | if (playerChips[i]>0.0001) { 83 | scoreboard.addToScore(i, 1); 84 | return i; 85 | } 86 | } 87 | return 0; 88 | } 89 | int remaining_count = n; 90 | while (folded[dealer]) {dealer = (dealer+1)%n;} 91 | int small_bind_player = (dealer+1)%n; 92 | while (folded[small_bind_player]) small_bind_player = (small_bind_player+1)%n; 93 | int big_bind_player = (small_bind_player+1)%n; 94 | while (folded[big_bind_player]) big_bind_player = (big_bind_player+1)%n; 95 | bets[small_bind_player] = Math.min(playerChips[small_bind_player], SMALL_BIND); 96 | playerChips[small_bind_player] -= bets[small_bind_player]; 97 | bets[big_bind_player] = Math.min(playerChips[big_bind_player], BIG_BIND); 98 | playerChips[big_bind_player] -= bets[big_bind_player]; 99 | int stop = (big_bind_player+1)%n; 100 | 101 | for (int player = (big_bind_player+1)%n, count = 0; ; player = (player+1)%n, count++) { 102 | if (count >= n && stop==player) break; 103 | if (remaining_count==0) break; 104 | if (folded[player]) continue; 105 | Double[] copy_playerChips = new Double[n]; 106 | Double[] copy_bets = new Double[n]; 107 | for (int i = 0; i < n; i++) { 108 | copy_playerChips[i] = playerChips[i]; 109 | copy_bets[i] = bets[i]; 110 | } 111 | Double move = Math.min(playerChips[player]+bets[player], playerHands[player].play(communityCards, pot, bet, playerChips[player], bets[player], copy_playerChips, copy_bets, player, dealer)); 112 | if (eq(move, playerChips[player]+bets[player])) { 113 | pot += move - bets[player]; 114 | playerChips[player] -= move - bets[player]; 115 | bet += move - bets[player]; 116 | bets[player] = Math.max(bets[player], move); 117 | remaining_count--; 118 | stop = player; 119 | } 120 | else if (move < playerChips[player] + bets[player] + eps && eq(move, bet)) { 121 | pot += move - bets[player]; 122 | playerChips[player] -= move - bets[player]; 123 | bets[player] = move; 124 | } 125 | else if (move < playerChips[player] + bets[player] + eps && move >= bet*2-eps) { 126 | pot += move - bets[player]; 127 | playerChips[player] -= move - bets[player]; 128 | bet += move - bets[player]; 129 | bets[player] = move; 130 | stop = player; 131 | } 132 | else { 133 | // System.out.printf("Folded: %.2f %.2f %.2f\n", bets[player], playerChips[player], move); 134 | folded[player] = true; 135 | remaining_count--; 136 | } 137 | } 138 | addCommunityCard(); 139 | addCommunityCard(); 140 | addCommunityCard(); 141 | bet = 0.; 142 | stop = (dealer+1)%n; 143 | double[] new_bets = new double[n]; 144 | for (int player = (dealer+1)%n, count = 0; ; player = (player+1)%n, count++) { 145 | if (count >= n && stop==player) break; 146 | if (remaining_count==0) break; 147 | if (folded[player]) continue; 148 | Double[] copy_playerChips = new Double[n]; 149 | Double[] copy_bets = new Double[n]; 150 | for (int i = 0; i < n; i++) { 151 | copy_playerChips[i] = playerChips[i]; 152 | copy_bets[i] = bets[i]; 153 | } 154 | Double move = Math.min(playerChips[player]+bets[player], playerHands[player].play(communityCards, pot, bet, playerChips[player], bets[player], playerChips, bets, player, dealer)); 155 | if (bet>eps && eq(move, 0.)) { 156 | folded[player] = true; 157 | remaining_count--; 158 | } 159 | else if (eq(move, playerChips[player])) { 160 | double change = move - new_bets[player]; 161 | pot += change; 162 | playerChips[player] -= change; 163 | new_bets[player] = move; 164 | bets[player] += move; 165 | remaining_count--; 166 | stop = player; 167 | bet = Math.max(bet, move); 168 | } 169 | else if (move < playerChips[player] + bets[player] + eps && eq(move, bet)) { 170 | double change = move - new_bets[player]; 171 | pot += change; 172 | playerChips[player] -= change; 173 | bets[player] += move; 174 | new_bets[player] = move; 175 | } 176 | else if (move < playerChips[player] + bets[player] + eps && move >= bet*2-eps) { 177 | double change = move - new_bets[player]; 178 | playerChips[player] -= change; 179 | bets[player] += move; 180 | new_bets[player] = move; 181 | bet = Math.max(bet, move); 182 | stop = player; 183 | } 184 | else { 185 | folded[player] = true; 186 | remaining_count--; 187 | } 188 | } 189 | 190 | addCommunityCard(); 191 | bet = 0.; 192 | stop = (dealer+1)%n; 193 | new_bets = new double[n]; 194 | for (int player = (dealer+1)%n, count = 0; ; player = (player+1)%n, count++) { 195 | if (count >= n && stop==player) break; 196 | if (remaining_count==0) break; 197 | if (folded[player]) continue; 198 | Double[] copy_playerChips = new Double[n]; 199 | Double[] copy_bets = new Double[n]; 200 | for (int i = 0; i < n; i++) { 201 | copy_playerChips[i] = playerChips[i]; 202 | copy_bets[i] = bets[i]; 203 | } 204 | Double move = Math.min(playerChips[player]+bets[player], playerHands[player].play(communityCards, pot, bet, playerChips[player], bets[player], playerChips, bets, player, dealer)); 205 | if (bet>eps && eq(move, 0.)) { 206 | folded[player] = true; 207 | remaining_count--; 208 | } 209 | else if (eq(move, playerChips[player])) { 210 | double change = move - new_bets[player]; 211 | pot += change; 212 | playerChips[player] -= change; 213 | new_bets[player] = move; 214 | bets[player] += move; 215 | remaining_count--; 216 | stop = player; 217 | bet = Math.max(bet, move); 218 | } 219 | else if (move < playerChips[player] + bets[player] + eps && eq(move, bet)) { 220 | double change = move - new_bets[player]; 221 | pot += change; 222 | playerChips[player] -= change; 223 | bets[player] += move; 224 | new_bets[player] = move; 225 | } 226 | else if (move < playerChips[player] + bets[player] + eps && move >= bet*2-eps) { 227 | double change = move - new_bets[player]; 228 | playerChips[player] -= change; 229 | bets[player] += move; 230 | new_bets[player] = move; 231 | bet = Math.max(bet, move); 232 | stop = player; 233 | } 234 | else { 235 | folded[player] = true; 236 | remaining_count--; 237 | } 238 | } 239 | 240 | addCommunityCard(); 241 | bet = 0.; 242 | stop = (dealer+1)%n; 243 | new_bets = new double[n]; 244 | for (int player = (dealer+1)%n, count = 0; ; player = (player+1)%n, count++) { 245 | if (count >= n && stop==player) break; 246 | if (remaining_count==0) break; 247 | if (folded[player]) continue; 248 | Double[] copy_playerChips = new Double[n]; 249 | Double[] copy_bets = new Double[n]; 250 | for (int i = 0; i < n; i++) { 251 | copy_playerChips[i] = playerChips[i]; 252 | copy_bets[i] = bets[i]; 253 | } 254 | Double move = Math.min(playerChips[player]+bets[player], playerHands[player].play(communityCards, pot, bet, playerChips[player], bets[player], playerChips, bets, player, dealer)); 255 | if (bet>eps && eq(move, 0.)) { 256 | folded[player] = true; 257 | remaining_count--; 258 | } 259 | else if (eq(move, playerChips[player])) { 260 | double change = move - new_bets[player]; 261 | pot += change; 262 | playerChips[player] -= change; 263 | new_bets[player] = move; 264 | bets[player] += move; 265 | remaining_count--; 266 | stop = player; 267 | bet = Math.max(bet, move); 268 | } 269 | else if (move < playerChips[player] + bets[player] + eps && eq(move, bet)) { 270 | double change = move - new_bets[player]; 271 | pot += change; 272 | playerChips[player] -= change; 273 | bets[player] += move; 274 | new_bets[player] = move; 275 | } 276 | else if (move < playerChips[player] + bets[player] + eps && move >= bet*2-eps) { 277 | double change = move - new_bets[player]; 278 | playerChips[player] -= change; 279 | bets[player] += move; 280 | new_bets[player] = move; 281 | bet = Math.max(bet, move); 282 | stop = player; 283 | } 284 | else { 285 | // System.out.printf("Folded: %.2f %.2f %.2f\n", bets[player], playerChips[player], move); 286 | folded[player] = true; 287 | remaining_count--; 288 | } 289 | } 290 | 291 | //calculate winnings 292 | int[] score = new int[n]; 293 | for (int i = 0; i < n; i++) { 294 | if (folded[i]) score[i] = 1; 295 | else { 296 | for (Card c : communityCards) 297 | playerHands[i].addCard(c); 298 | score[i] = playerHands[i].evaluate(); 299 | } 300 | } 301 | ArrayList ranks = new ArrayList<>(); 302 | for (int i = 0; i < n; i++) { 303 | ranks.add(i); 304 | } 305 | Collections.sort(ranks, new Comparator() { 306 | @Override 307 | public int compare(Integer i1, Integer i2) { 308 | return score[i2] - score[i1] + (score[i2] - score[i1] == 0 ? ((int) Math.round(1000 * (bets[i1] - bets[i2]))) : 0); 309 | } 310 | }); 311 | double[] add = new double[n]; 312 | for (int i = 0; i < n; i++) { 313 | if (score[ranks.get(i)]==1) break; 314 | int j = i+1; 315 | while (j < n && score[ranks.get(j)] == score[ranks.get(i)]) j++; 316 | Double gain = 0.; 317 | for (int k = i; k < n; k++) { 318 | gain += Math.min(bets[ranks.get(i)] / (j-i), bets[ranks.get(k)] / (j-i)); 319 | } 320 | for (int k = n-1; k >= i; k--) { 321 | bets[ranks.get(k)] -= Math.min(bets[ranks.get(k)], bets[ranks.get(i)]); 322 | } 323 | for (int k = i; k < j; k++) { 324 | add[ranks.get(k)] += gain; 325 | } 326 | } 327 | for (int i = 0; i < n; i++) playerChips[ranks.get(i)] += add[ranks.get(i)] + bets[ranks.get(i)]; 328 | nextRound(); 329 | } 330 | } 331 | catch (Exception e) { 332 | e.printStackTrace(); 333 | return 0; 334 | } 335 | } 336 | 337 | void print(String s) { 338 | if (PRINT_VERBOSE) { 339 | System.out.print(s); 340 | } 341 | } 342 | 343 | void println(String s) { 344 | if (PRINT_VERBOSE) { 345 | System.out.println(s); 346 | } 347 | } 348 | } --------------------------------------------------------------------------------