# Poker Example

Poker is a family of card games, where effective betting strategies require knowledge of the probabilities of being dealt various hands.

## Problem Description

Here, we use Hava to estimate these probabilities via a simulation approach. In our example, we use a standard card deck of 52 cards, and each hand has five cards. We consider various hand types, for example, full house, straight, two of a kind.

A simulation approach follows these steps:

• Generate a (large) sample, `N`, of random hands (draws of five cards) from a card deck.
• Count the number of hands in the sample, `Ct`, that have hand type t.
• Use the ratio `Ct/N` to estimate the probability of being dealt hand type t.

## Hava Preliminaries

To represent this problem in Hava, we begin by defining tokens and lists to represent the card deck:

```token JACK, QUEEN, KING, ACE; FACES = (2, 3, 4, 5, 6, 7, 8, 9, 10, JACK, QUEEN, KING, ACE); token CLUB, DIAMOND, HEART, SPADE; SUITS = (CLUB, DIAMOND, HEART, SPADE); ```
Next, we use a Hava structure to define a card in the deck:
```struct Card(face, suit); ```

## Dealing a Hand

A hand consists of five cards drawn sequentially from the deck. In lieu of simulating an actual deal of the cards, we adopt the following (easier to code) two-step approach.
• Generate five separate random draws of the deck. Using the Hava built-in function `random`, this step is easy:
```function randomCard = Card(random(FACES), random(SUITS)); function randomHand = collect(i=1 to handSize) {randomCard}; handSize = 5; ```

• Check to see if the random hand has any duplicate cards; if so, ignore it for purposes of sampling. Recall that a hand consists of an ordered list of five cards. Starting with the second card in this ordered list, each card is sequentially compared to each previous card to see if there is a match. The first match found is:
```first(i=2 to handSize, j=1 to i-1 | hand[i]==hand[j]) {(i,j)} ```

But we don't actually care what the match is; just finding one is enough to indicate an error. The following, simpler expression will evaluate to ERROR if the hand contains a match:
```first(i=2 to handSize, j=1 to i-1 | hand[i]==hand[j]) {ERROR} ```

(If the hand is valid, then no match is found, and `first` returns `IGNORE`).

## Poker Hand Types

A useful function counts the number of times a face appears in a hand.

```faceCountInHand(face, hand) = sum(card in hand) {card.face==face}; ```
The following function sums the face counts of each card in the hand:
```key(hand) = sum(card in hand) {faceCountInHand(card.face, hand)}; ```
For example, in the hand
```twoPair = collect(Card(6, SPADE), Card(2, SPADE), Card(6, CLUB), Card(8, DIAMOND), Card(8, HEART)); ```
the expression `key(twoPair)` evaluates to 9. Many poker hands can be uniquely identified from this key. For example, any hand whose key equals 9 must be a two-pair hand.

Sample statistics are calculated using the iterator `sum`. For example:
```N = 10000; stats = sum(i=1 to N, hand=randomHand | isValidHand(hand)) {(isFullHouse(hand), isStraight(hand), isFlush(hand))}; spFullHouse = stats/N; spStraight = stats/N; spFlush = stats/N; ```