CMPSCI 240

Programming Project #2: Calculating probabilities in poker

Due Monday, October 26, 2009

Correction in purple added 23 October 2009.

Overview

In this project, you'll compute the odds of each player winning a televised round of Texas hold'em. The cards have been dealt, and people watching this on TV get to see all the players' hands, as well as any face up cards on the table. To do this, you're going to need to know (a) how to play poker, including specifically (b) how to compare two poker hands, (c) how to enumerate all possible hands that can be formed using any possible set of known and unknown cards, and (d) how to use this to determine the odds of each player winning.

Televised Texas Hold'em

In Texas Hold'em each player gets two private cards, which form a seven-card hand when combined with five community cards. The winner of the hand is the player who has the highest hand among those players who do not drop out during the betting. The best seven-card hand is determined by the best five-card hand that can be obtained as a subset from those seven cards. There are separate rounds of betting with 0, 3, 4, and 5 of the community cards revealed to the players respectively.

When a Texas Hold'em game is shown on television, the audience is shown the private cards of each player still active, plus the community cards that are visible to the players. If not all of the community cards are visible, the audience is also shown the probability that each player has the highest hand among those active, based on the possible values of the remaining community cards. Your job is to write a Java method that will compute these probabilities, given all the other input available to the audience.

Poker hands

For the purposes of this assignment, here's how the game works. There are five cards on the table (the "community" cards). Of these community cards, 0, 3, 4, or 5 may be face up (revealed), and the rest of the five are face down (hidden). There are two cards in each player's hand (the "hole" cards). That's seven, from which a player will choose the optimal five-card hand. Each other player uses those same community cards plus the two cards they have in their own hand. Whoever can produce the best five-card hand wins.

Wikipedia's article on poker hands is a good place to learn about hands and their ranking. (Also useful: this summary and Wikipedia on Texas hold'em.)

Here's a brief description of how to compare two five-card poker hands:

Assignment

This assignment consists of roughly three parts: First, we need to define a FiveCardHand class for five-card poker hands, with a compareTo method to determine which of two hands ranks higher. Second, we need a SevenCardHand class with a similar method that allows us to find the best five-card subset of a seven-card hand. Finally, we need to enumerate the possible seven-card hands to compute the odds that each person has a winning hand.

Part 1: comparing five-card hands

You are provided a code base that knows a few things about poker. It knows what a card is (from a number 1-52), and its rank and suit. It knows that a seven-card hand contains a best five-card hand; it can check for flushes and straights and reason about them; and, it can do most of the work of extracting the best hand and comparing two five-card hands. But, it relies on a pre-processing step to make it easier to reason about the hands: computing what's called the "shape" of the hand.

You'll need to implement two methods before this code for five-card hands will work:

Take a look at the code. In addition to some additional hints in the comments, there are test cases coded up (in Deal.java) that will help you check your work. Don't assume they are exhaustive. You may want to add your own.

Part 2: comparing seven-card hands

Next we need a SevenCardHand class with a similar method for seven-card hands. The rank of a seven-card hand is equivalent to the rank of the best five-card subset, so in order to compute the best seven-card hand, we need to find the best five-card subset. Note that there are at least two possible ways to compute the best five-card subset of a seven-card hand:

  1. Simple: The simplest way is to cycle through all (7 choose 5) = 21 subsets, keeping the best one. You can use our Set class from project #1 to generate all the appropriate subsets.
  2. Better: Alternatively, we can use the fact that the rank structure of the seven-card hand implies the rank of the best five-card hand, unless there is a straight or a flush. To get you started, take a look at some of the logic for dealing with straights and flushes in FiveCardHand.compareTo.
    Extra credit if you implement this method!

You'll need to implement these methods before this works:

Note that the simple method will work fine later in part 3 when at least some of the community cards are face up, but in the worst case when all five community cards are face down and there are only 2 players, this can noticeably change the runtime. On my five-year old laptop, this is the difference between a runtime of 2 minutes and a runtime of a 20 minutes as we search through all (48 choose 5) = 1,712,304 possible combinations of community cards. Presumably, the TV viewers at home will want to see the probabilities sooner than that!

Part 3: computing the odds of winning

Finally, we need to compute the odds of each player winning. Given k active players, d folded players, and either 1, 2, or 5 unknown (face down) community cards, the number of possible values of the unknown cards is either (52-2k-2d choose 5), (49-2k-2d choose 2), or (48-2k-2d choose 1). [Correction added 23 October, this used to say "(51-2k-2d choose 1), (50-2k-2d choose 2), or (47-2k-2d choose 5)."] We can generate each of these values using the Set code from Project #1, count the cases in which each player has the best hand, and compute the k different probabilities.

You'll need to implement this method before this works:

You're provided with some code to make this easier. The method Deal.computeAvailableCards() returns the complement of the set of cards visible to the TV viewer. That is, if we've dealt out cards to 4 players, 3 community cards are revealed, and the discard pile contains 10 cards, then 52 - 4*2 - 3 - 10 = 31 cards are available. You can then use the Set.map methods to choose subsets of these remaining cards.

Finally, once you've written calculateOdds(), make any necessary changes to Deal.main() and run java Deal to test your code. In general, add any extra methods you find helpful, but be cautious about changing the existing code unless you're sure you know what you're doing.

Logistics

The java files needed for this assignment are in a directory called

/courses/cs200/cs240/cs240/proj2/skeleton/

See the edlab main page if you don't yet know how to access this directory.

Submit the completed java files to the cs240 folder of your own home directory by 11:59pm on Monday, October 26, 2009.

Last modified 23 October 2009