# Cribbage: Calculating Hand Value

The last few months, we've been building a complex shell script
to play elements of the game of *Cribbage*, demonstrating a variety of
concepts and techniques as we proceed. That's all good, and last month,
the script expanded to include a "shuffle" capability and
the ability to deal out six cards, a typical two-player starting hand.

*Cribbage* tip: in a three-player game, each player gets
five cards, and
the extra is dealt directly into the "crib"—the extra hand
counted after play by the dealer.

The challenge we're going to tackle this month is figuring out the best
four cards to keep of those initial six, based on potential point values
of the different hands. Ultimately, a fifth, "cut card",
is turned up that everyone shares (somewhat akin to the shared cards in
*Texas Hold 'em*), but smart
*Cribbage* players seek to maximize the four
they hold and celebrate when the fifth adds to the point value of the
hand, rather than count on that cut card to make the hand.

So what's valuable in a *Cribbage* hand? Sequential runs of three or more
cards, pairs or better of the same rank, having all the cards in your hand
match suit (and possibly the cut card), combinations of card ranks that
add up to 15, and having the jack of the same suit as is on the cut card.

Cards of the same rank—pairs or better—are tricky to count because the game works on combinations. So 5H, 5D is worth two points "for the pair", but 5H, 5D, 5S is worth six points, because it combines to three pairs: 5H+5D, 5H+5S and 5D+5S. Four of a kind? A sweet 12 points and a very rare combination indeed.

Critical to know: aces always are worth 1 when counting up fifteens, and all face cards are worth 10 points. So A+4+K is a fifteen, just as 9+6 is, though for pairs, it's the same rank, not just pairs of face cards. In other words, J+K is not a pair.

Where counting gets tricky is those combinations of fifteens. A great hand, for example, is 6S, 7H, 8D, 8S, which offers two points for 7H+8D, two points for 7H+8S, three points for 6S+7H+8D, another three points for 6S+7H+8S and a final two points for the pair 8D+8S—very nice. If the cut card is another 7 or, even better, another 8, you can see where there are a lot of points in that potential hand!

The challenge, of course, is doing all of this programmatically. When we left off the program last month, it could deal six cards to us and sort them in increasing rank order, which is helpful, particularly in recognizing runs.

### Calculating All Four-Card Combinations

The first problem we have is actually earlier than anything to do with card values. It's to calculate all possible four-card combinations out of a six-card hand. It's combinatorics—something I really enjoyed back when I took that class in college for my CS degree.

What we're looking at is actually factorial math. So "six choose four" is really 6! minus 2!, which is generally written as shown in Figure 1, where n is the total number of cards, and m is the subset we want to choose. In this case, it's 6! / 4!(6! - 4!).

Figure 1. Equation for "Six Choose Four"

A factorial number is
calculated as the multiple of all decreasing numbers, so 4! = 4 x 3 x
2 x 1, and 6! = 6 x 5 x 4 x 3 x 2 x 1. Of course, the "x 1"
part is pointless, so we can skip it. 4! = 24 and 6! = 720, which means
that we have 15 card combinations to check for points. (If we had
only five cards dealt because it was a three- or four-person
*Cribbage* game, we'd have only five combinations to
evaluate instead.)

The question is, how do we figure out all 15 of those combinations easily? I mean, I could hard-code all 15 of them—it's only four digits per subset, after all—but that seems less interesting than trying to solve the more-general mathematical equation. And yes, I can see myself getting sidetracked as I proceed, but that's part of the fun of programming when you're not on a deadline, right?

Um, never mind. Let's just take as a given that for six-choose-four, there are these specific combinations and no more: {1,2,3,4}, {1,2,3,5}, {1,2,3,6}, {1,2,4,5}, {1,2,4,6}, {1,2,5,6}, {1,3,4,5}, {1,3,4,6}, {1,3,5,6}, {1,4,5,6}, {2,3,4,5}, {2,3,4,6}, {2,3,5,6}, {2,4,5,6} and {3,4,5,6}.

If we're working with five-choose-four, the combinations are {a,b,c,d}, {a,b,c,e}, {a,b,d,e}, {a,c,d,e} and {b,c,d,e}.

The easy way to code this is as an array of arrays. Let's do it this way:

```
# six choose four
sixfour[0]="0 1 2 3"; sixfour[1]="0 1 2 4"
sixfour[2]="0 1 2 5"; sixfour[3]="0 1 3 4"
sixfour[4]="0 1 3 5"; sixfour[5]="0 1 4 5"
sixfour[6]="0 2 3 4"; sixfour[7]="0 2 3 5"
sixfour[8]="0 2 4 5"; sixfour[9]="0 3 4 5"
sixfour[10]="1 2 3 4"; sixfour[11]="1 2 3 5"
sixfour[12]="1 2 4 5"; sixfour[13]="1 3 4 5"
sixfour[14]="2 3 4 5"
```

If you're paying close attention to the script we've been creating, you know that our hand is indexed starting at 0, so the card values are 0–5 instead. That's easily fixed by shifting every value down one in the predefined arrays.

Now it's just a matter of interpreting the different
`sixfour`

array values
as a set of four cards to select, and here's how I do it:

```
for subhand in {0..14}
do
/bin/echo -n "Subhand ${subhand}:"
for thecard in ${sixfour[$subhand]}
do
showcard ${hand[$thecard]}
/bin/echo -n " $showcardvalue"
done
echo ""
done
```

The echo statements (remember `-n`

prevents a carriage return being appended
to the output) aren't important to the final code, but for this interim
solution, you'll see how it works by me just tucking it into the end of
the program, just after the code that deals, sorts and shows the full
six-card hand:

```
Hand: AS, 5C, 7H, 8H, 9D, JS.
Subhand 0: AS 5C 7H 8H
Subhand 1: AS 5C 7H 9D
Subhand 2: AS 5C 7H JS
Subhand 3: AS 5C 8H 9D
Subhand 4: AS 5C 8H JS
Subhand 5: AS 5C 9D JS
Subhand 6: AS 7H 8H 9D
Subhand 7: AS 7H 8H JS
Subhand 8: AS 7H 9D JS
Subhand 9: AS 8H 9D JS
Subhand 10: 5C 7H 8H 9D
Subhand 11: 5C 7H 8H JS
Subhand 12: 5C 7H 9D JS
Subhand 13: 5C 8H 9D JS
Subhand 14: 7H 8H 9D JS
```

That's a lot of four-card hands, but at least we've got them. Next month, we'll actually start writing the code to evaluate hand values. Stay tuned!

### Limited Time Offer

Take *Linux Journal* for a test drive. Download our September issue for FREE.