On this page

My methodology for video poker analysis

One question I get asked from time to time is how I got my video poker program to evaluate a pay table in under one minute. This page will attempt to answer that question.

My original program used a brute force method to loop through all 2,598,960 starting hands and then play all 32 possible ways to discard, including looping through all 1,533,939 replacements cards when discarding all five. This was about the year 1998. On my computer at the time, I determined it would take over a year to finish. Such a program today would only take about a month. However, with two shortcuts you can cut the time from about a month to about three seconds. Following is how to do it.

To cut down the running time to a few days you can avoid analyzing similar hands on the deal. For example if the starting hand were four aces and a king it would not make any difference what suit the king was. It would save some time to assign an arbitrary suit to the king and multiply the results by four. Using this same logic the number of different kinds of starting hands can be cut from 2,598,960 to 134,459. The following tables show the ways to arrange the suits, and associated weighting, for every class of hands by rank.

Five Singletons

 

Loop through all combin(13,5)=1,287 possible ways to pick 5 different ranks out of 13. For each combination of ranks, set the suits (numbered 1 to 4) and weightings as follows. For example, the first row sets each singleton rank with a suit of 1. There are four possible suits, so rather than do it four times, do it once and multiply the results by the weighting of 4.

 

Five Unique Ranks

Sing. 1 Sing. 2 Sing. 3 Sing. 4 Sing. 5 Weight
1 1 1 1 1 4
2 1 1 1 1 12
1 2 1 1 1 12
1 1 2 1 1 12
1 1 1 2 1 12
1 1 1 1 2 12
2 2 1 1 1 12
2 1 2 1 1 12
2 1 1 2 1 12
2 1 1 1 2 12
1 2 2 1 1 12
1 2 1 2 1 12
1 2 1 1 2 12
1 1 2 2 1 12
1 1 2 1 2 12
1 1 1 2 2 12
2 3 1 1 1 24
2 1 3 1 1 24
2 1 1 3 1 24
2 1 1 1 3 24
1 2 3 1 1 24
1 2 1 3 1 24
1 2 1 1 3 24
1 1 2 3 1 24
1 1 2 1 3 24
1 1 1 2 3 24
1 1 2 2 3 24
1 2 1 2 3 24
1 2 2 1 3 24
1 1 2 3 2 24
1 2 1 3 2 24
1 2 2 3 1 24
1 1 3 2 2 24
1 2 3 1 2 24
1 2 3 2 1 24
1 3 1 2 2 24
1 3 2 1 2 24
1 3 2 2 1 24
3 1 1 2 2 24
3 1 2 1 2 24
3 1 2 2 1 24
4 4 1 2 3 24
4 1 4 2 3 24
4 2 3 4 1 24
4 1 2 3 4 24
1 4 4 2 3 24
1 4 2 4 3 24
1 4 2 3 4 24
2 3 4 4 1 24
2 3 4 1 4 24
1 2 3 4 4 24

 

Pair

Loop through all 13×combin(12,3)=2,860 possible ways to pick a rank for the pair, and three ranks out of the 12 remaining for the three singletons. For each combination of ranks, set the suits (numbered 1 to 4) and weightings as follows. For example, the first row sets the suits of the pair to 1 and 2, and the suits of the singletons all to 1. There are combin(4,2)=6 ways to choose the suits of the pair, and 2 ways to picks a suit for the singletons equal to one of the pair suits, for a weighting of 6×2=12.

 

Pair

Pair 1 Pair 2 Sing. 1 Sing. 2 Sing. 3 Weight
1 2 1 1 1 12
1 2 1 1 2 12
1 2 1 2 1 12
1 2 2 1 1 12
1 2 1 1 3 24
1 2 1 3 1 24
1 2 3 1 1 24
1 2 1 3 3 24
1 2 3 1 3 24
1 2 3 3 1 24
1 2 3 3 3 12
1 2 1 2 3 24
1 2 1 3 2 24
1 2 3 1 2 24
1 2 3 4 4 12
1 2 4 3 4 12
1 2 4 4 3 12
1 2 1 3 4 24
1 2 3 1 4 24
1 2 3 4 1 24

 

Two Pair

Loop through all combin(13,2)×11=858 possible ways to pick two ranks out of 13 for the two pairs, and one rank out of the 11 left for the singleton. For each combination of ranks, set the suits (numbered 1 to 4) and weightings as follows. For example, the first row sets the suits of the first pair to 1 and 2, the suits of the second pair to 3 and 4, and the suit of the singleton to 1. There are combin(4,2)=6 ways to pick the suits for the first pair. The second pair has the other two suits, so there is only one 1 to choose those. The singleton can have either suit from the first pair, so there are two possibilities. Thus the weighting in the first row is 6×1×2=12.

 

Two Pair

Pair 1
Card 1
Pair 1
Card 2
Pair 2
Card 1
Pair 2
Card 2
Sing. 1 Weight
1 2 3 4 1 12
1 2 3 4 3 12
1 2 1 3 1 24
1 2 1 3 2 24
1 2 1 3 3 24
1 2 1 3 4 24
1 2 1 2 1 12
1 2 1 2 3 12

 

Three of a Kind

Loop through all 13×combin(12,2)=858 possible ways to pick one rank out of 13 for the three of a kind and 66 ways to choose two singtons from the other 12 ranks. For each combination of ranks, set the suits (numbered 1 to 4) and weightings as follows. For example, the first row sets the suits of the three of a kind to 1, 2, and 3, and the suits of the two singletons equal to two of the three suits represented in the three of a kind. There are combin(4,3)=4 ways to choose 3 out of 4 suits for the three of a kind, 3 ways to pick a suit from those three for the first singleton, and 2 ways to pick a suit for the second singleton. Thus the weighting for the first row is 4×3×2=24.

 

Three of a Kind

3 Kind
Card 1
3 Kind
Card 2
3 Kind
Card 3
Sing. 1 Sing. 2 Weight
1 2 3 1 2 24
1 2 3 1 4 12
1 2 3 4 1 12
1 2 3 1 1 12
1 2 3 4 4 4

 

Full House

Loop through all 13×12=156 possible ways to choose one rank out of 13 for the three of a kind and 12 ways to choose a rank for the pair. For each combination of ranks, set the suits (numbered 1 to 4) and weightings as follows. For example, the first row sets the suits of the pair to 1 and 2, and the suits of the three of a kind equal to 1, 2, and 3. There are combin(4,2)=6 ways to pick the suits for the pair. The three of a kind uses both pair suits, and one of the other two. Thus the weighting for the first row is 6×2×2=12.

 

Full House

Pair
Card 1
Pair
Card 2
3 Kind
Card 1
3 Kind
Card 2
3 Kind
Card 3
Weight
1 2 1 2 3 12
1 4 1 2 3 12

 

Four of a Kind

Loop through all 13×12=156 possible ways to choose one rank out of 13 for the four of a kind and 12 ways to choose a rank for the singleton. For each combination of ranks, set the suits (numbered 1 to 4) and weightings as follows. For example, the first row sets the suits of the four of a kind to 1, 2, 3 and 4, and the suits of the singleton equal to 1. There is only one way to pick 4 suits out of 4 for the three of a kind, and 4 ways to pick out suit out of 4 for the singleton. Thus the weighting for the first row is 1×4×2=4.

 

Four of a Kind

4 Kind
Card 1
4 Kind
Card 2
4 Kind
Card 3
4 Kind
Card 4
Sing. 1 Weight
1 2 3 4 1 4

 

The above step will cut down the computation time by 95%, but it will still take several hours if you loop through the 1,533,939 possible combinations of replacement cards. The secret to a three-second program is to not loop at the draw step. Here is how to do it:

  1. Initialize the following arrays:
    • Array 1: size 2,598,960
    • Array 2: size 270,725 by 16
    • Array 3: size 22100 by 16
    • Array 4: size 1326 by 16
    • Array 5: size 52 by 16
    • Array 6: size 16
    The 16 is for the maximum number of kinds of paying hands on the draw. Adjust this as you see fit. I have never seen a video poker game with more than 16 elements in the pay table.
  2. Loop through all 2,598,960 combinations of 5 cards out of 52. Do NOT use the 134,459 hand shortcut at this point. For each hand on the deal do the following:
    • Score it according to its poker value.
    • Put the score in array0. Put the first hand in element 0 of the array, and increment by 1 for each hand.
    • For each of the 5 ways to choose 4 out of 5 cards on the deal, translate the four cards into an index number from 0 to 270,724 (I'll explain how to do that later), and increment element [index number][hand score] of array1 by 1.
    • For each of the 10 ways to choose 3 out of 5 cards on the deal, translate the three cards into an index number from 0 to 22,099, and increment element [index number][hand score] of array2 by 1.
    • For each of the 10 ways to choose 2 out of 5 cards on the deal, translate the two cards into an index number from 0 to 1,325, and increment element [index number][hand score] of array3 by 1.
    • For each of the 5 ways to choose 1 out of 5 cards on the deal, translate the card into an index number from 0 to 51, and increment element [index number][hand score] of array4 by 1.
    • Increment element [hand score] of array5 by 1.
    At this point you will have arrays showing the possible outcomes of holding any set of cards on the deal, without considering penalty cards (cards you discarded). Array0 will have the outcome of discarding zero cards, array1 for discarding 1 card, and so on.
  3. Next, loop through the 134,459 classes of hands explained above.
  4. To determine the value of holding all five cards, translate the five cards to an index number, and look up the poker value lin array0.
  5. To determine the value of holding any four cards, translate the four cards to an index number, and look up the possible outcomes on the draw in the corresponding element of array1. This, however, will include getting the card you discarded on the deal. So you should subtract one from the element in the array associated with the poker value of holding all five cards. For example, if you hold J♣, Q♣, K♣, A♣ and discard 2♥ there will be 1 way to get a royal, 8 ways to get a flush, 3 ways to get a straight, 12 ways to get a pair of jacks or better, and 23 ways to get a losing hand. However, array1 will say there are 24 ways to get a losing hand, including getting the 2♥ on the draw. So you need to subtract the outcome of holding everything from the possible outcomes of the 5 ways of holding 4 cards.
  6. Make sure you understand the logic of the step above, because we take it to the next level in this step. For the 10 ways of holding any 3 cards you will look up the possible outcomes in array2. Then subtract the possible outcomes from array1 for the 3 cards you are holding, and each of the cards you are discarding. For example, for the value of keeping 2♣2♥ 2♠ and discarding 4♥ and J♠ start with the values in array2 for 2♣ 2♥ 2&spades, and then subtract out the values for 2♣ 2♥ 2♠ 4♥and 2♣ 2♥ 2♠ J♠. However, this will double-subtract holding all five cards. So you need to add back in what you get by holding all 5.
  7. By the same logic, for holding any 2 cards start with the values in array3, subtract out the appropriate sets of cards from array2, add back in the appropriate sets of cards from array1, and subtract back out the element for holding everything fron array0.
  8. For holding 1 card, start with the associated values from array4, subtract out the appropriate values from array3, add back in the appropriate values from array2, subtract back out the appropriate values from array1, and add back in the appropriate value from array0.
  9. For discarding everything start with the values in array5, then subtract out the appropriate values from array4, add back in the appropriate values from array3, subtract back out the appropriate values from array2, add back in the appropriate values from array1, and subtract out the appropriate value from array0.
  10. You should now have the number of combinations of all possible outcomes for all 32 ways to play the hand. Determine the expected value of each. For the play resulting in the greatest expected value, add to an array for the overall possible outcomes of the game the possible outcomes of that play. Remember to multiply by the associated weighting for the hand on the deal.
  11. After looping through all 134,459 kinds of starting hands you should have the number of ways you can get each hand on the draw. Use that array to determine the overall return of the game.

 

Following are four subroutines for translating 2 to 5 cards (numbered 0 to 51) and returning an index value.

 

int HandIndex2(int c1, int c2){    int r;    r=combin_array[52][2]-combin_array[52-c1][2];    r+=combin_array[51-c1][1]-combin_array[52-c2][1];    return r;}int HandIndex3(int c1, int c2, int c3){    int r;    r=combin_array[52][3]-combin_array[52-c1][3];    r+=combin_array[51-c1][2]-combin_array[52-c2][2];    r+=combin_array[51-c2][1]-combin_array[52-c3][1];    return r;}int HandIndex4(int c1, int c2, int c3, int c4){    int r;    r=combin_array[52][4]-combin_array[52-c1][4];    r+=combin_array[51-c1][3]-combin_array[52-c2][3];    r+=combin_array[51-c2][2]-combin_array[52-c3][2];    r+=combin_array[51-c3][1]-combin_array[52-c4][1];    return r;}int HandIndex5(int CardIndex[]){    int r;    r=combin_array[52][5]-combin_array[52-CardIndex[0]][5];    r+=combin_array[51-CardIndex[0]][4]-combin_array[52-CardIndex[1]][4];    r+=combin_array[51-CardIndex[1]][3]-combin_array[52-CardIndex[2]][3];    r+=combin_array[51-CardIndex[2]][2]-combin_array[52-CardIndex[3]][2];    r+=combin_array[51-CardIndex[3]][1]-combin_array[52-CardIndex[4]][1];    return r;}

 

Links

This site explains how the author speeded up his video poker analzyer from a year to seven seconds.

VP Genius has an outstanding page on programming video poker.