// Filename: aces.cpp // Last updated: Nov 4, 2003 // Author: Barry Greenstein // Purpose: This program estimates the odds are of getting a pair of Aces in // the big blind if the everyone folds to you in a nine-handed game // When no one has entered the pot, pot-entry is classified as follows: // 0 indicates hand will be folded in all postions // 1 indicates hand is playable in early position: first and second to act // 2 indicates hand is playable in middle position: next two positions // 3 indicates hand is playable in late position: one or two to right of button // 4 indicates hand is playable on the button // 5 indicates hand is playable in the small blind // 169 hold'em hands: Entries above the diagonal are suited; below are offsuit // Think of the 169 hands as an ordered pair of ranks: when the first rank // is higher than the second, the combination is suited, otherwise unsuited. // This table represents typical basic strategy. It is not computer generated. // A K Q J 10 9 8 7 6 5 4 3 2 // A 1 1 1 1 1 1 1 1 1 1 1 1 1 // K 1 1 1 1 2 2 3 3 3 3 3 3 3 // Q 1 2 1 2 2 2 3 3 3 3 3 3 3 // J 1 2 2 1 2 2 3 4 4 4 4 4 4 // 10 2 2 2 2 1 2 3 3 4 5 5 5 5 // 9 3 3 3 2 2 1 3 3 4 5 0 0 0 // 8 3 4 4 4 3 3 1 3 4 4 0 0 0 // 7 3 4 5 4 4 4 4 1 4 5 0 0 0 // 6 3 4 5 0 5 4 4 4 2 5 5 0 0 // 5 3 4 5 0 0 0 5 5 5 2 5 0 0 // 4 3 4 5 0 0 0 0 0 0 0 2 5 0 // 3 3 4 5 0 0 0 0 0 0 0 0 2 0 // 2 3 4 5 0 0 0 0 0 0 0 0 0 2 #include // standard input/output; this allows us to output results #include // includes definition of the random() function #define TOTALHANDS 1000000L #define SEED 4 // random numbers stay the same if seed is unchanged for debugging purposes void main(){ int dealacard(int []); // this function will deal a random card from a depleted deck int tableentry, player, firstcard, secondcard, i; int cardstaken[52]; // this will store cards that have been dealt // fill in pot-entry array from table above (smallest card to largest here) int potentry[169]= { 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 4, 3, // Deuce 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 5, 4, 3, // Three 0, 5, 2, 0, 0, 0, 0, 0, 0, 0, 5, 4, 3, // Four 0, 0, 5, 2, 5, 5, 5, 0, 0, 0, 5, 4, 3, // Five 0, 0, 5, 5, 2, 4, 4, 4, 5, 0, 5, 4, 3, // Six 0, 0, 0, 5, 4, 1, 4, 4, 4, 4, 5, 4, 3, // Seven 0, 0, 0, 4, 4, 3, 1, 3, 3, 4, 4, 4, 3, // Eight 0, 0, 0, 5, 4, 3, 3, 1, 2, 2, 3, 3, 3, // Nine 5, 5, 5, 5, 4, 3, 3, 2, 1, 2, 2, 2, 2, // Ten 4, 4, 4, 4, 4, 4, 3, 2, 2, 1, 2, 2, 1, // Jack 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 1, 2, 1, // Queen 3, 3, 3, 3, 3, 3, 3, 2, 2, 1, 1, 1, 1, // King 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; // Ace // Instead of writing a Monte Carlo Simulation, I would have liked to go // through all possible deals of nine-handed hold'em and see how many times // someone with two Aces gets a walk in the big blind. // There are (52 choose 2)(50 choose 2) ... (36 choose 2) combinations. // That equals (1326)(1225)(1128)(1035)(946)(861)(780)(703)(630), which // equals 533,597,550,452,438,349,477,600,000 (a 27 digit number) // Computers are not fast enough to handle checking that many cases. // (I could cut it down to a 24 digit number of cases with some cleverness.) long walks = 0L; // keep track of times no one enters the pot long pairaces = 0L; // number of pairs of aces for all walks srand(SEED); // activate random number generator // We deal hands to eight players; then if no one has opened we will look // at all combinations of the remaining 36 cards left for the big blind. for (long handsdealt = 0L; handsdealt < TOTALHANDS; handsdealt++) { int opener = 0; // no one has entered the pot yet cardstaken[0] = -1; // start each deal with a fresh deck for (player = 1; (opener == 0) && (player <= 8); player++){ // one player at a time firstcard = dealacard(cardstaken); // first card of next player's hand secondcard = dealacard(cardstaken); // second card of next player's hand int firstrank = firstcard % 13; // rank of firstcard int secondrank = secondcard % 13; // rank of secondcard if (firstcard/13 == secondcard/13){ // are cards of the same suit? if (firstrank > secondrank) tableentry = firstrank * 13 + secondrank; // get to suited entry else // switch order in calculation to get suited entry tableentry = secondrank * 13 + firstrank; } else{ // cards are not the same suit if (firstrank > secondrank) tableentry = secondrank * 13 + firstrank; // get to unsuited entry else // switch order in calculation to get unsuited entry tableentry = firstrank * 13 + secondrank; } switch (potentry[tableentry]){ // case 0 is unplayable hand; we will keep going case 1: // hand is playable in all positions opener = 1; break; case 2: // hand is playable in middle position or later if (player > 2) opener = 1; break; case 3: // hand is playable in late postion if (player > 4) opener = 1; break; case 4: if (player > 6) // hand is playable on the button opener = 1; break; case 5: // hand is playable in the small blind if (player == 8) opener = 1; break; } } // end of "for" loop; hands were dealt to eight players if (opener == 0){ // none of the first eight players entered the pot int aces = 4; // tracks how many Aces are left in the deck for (i = 0; cardstaken[i] >= 0; i++) if ((cardstaken[i] % 13) == 12) // is this an Ace? aces--; // one less Ace is in the deck // We can calculate by hand how many times out of the (36 choose 2) // possible two card combinations, the big blind will get a pair of Aces // Note that (36 choose 2) is (36 * 35)/2, which equals 630 // If there is 0 or 1 Ace left, we can't get a pair of Aces in the big blind. // If 2 Aces are left, there is 1 way to get a pair of Aces out of 630. // If 3 Aces are left, there are 3 ways to get a pair of Aces out of 630. // If 4 Aces are left, there are 6 ways to get a pair of Aces out of 630. walks++; // we got a walk if (aces == 2) pairaces++; if (aces == 3) pairaces += 3L; if (aces == 4) pairaces += 6L; } } // end of "for" loop counting hands dealt printf("The number of hands dealt is %ld.\n", handsdealt); printf("The number of walks in the big blind is %ld.\n", walks); printf("There were %ld pairs of Aces out of %ld combinations.\n", pairaces, walks * 630L); if (pairaces != 0) { // when I was testing the program with TOTALHANDS // set at 1, pairaces might have been 0 float acesratio = (float)walks * 630.0/(float)pairaces; // chance of Aces printf("When getting a walk in the big blind, the odds of having Aces is %4.2f to 1.\n", acesratio - 1.0); float increase = (float)(pairaces - walks * 630.0/221.0)/ ((float)walks * 630.0/221.0); // normally we get a pair of Aces once in 221, since 1/13 x 1/17 = 1/221 printf("This is %4.2f percent more than normal.\n", increase * 100.0); } } // end of main program // dealacard() returns the value of a randomly dealt card from a deck that may // have some cards already dealt out of it, and stores the card in the array that // has been passed. int dealacard(int dealtcards[]){ int i, j; int taken = 0; // used to count how many cards are out of deck for (taken = 0; dealtcards[taken] >= 0; taken++); int cardnum = random(52 - taken); // randomly choose a card left in the deck // this is the relative location in the cards that have not been dealt for (i = 0; i < taken; i++){ // see which cards are lower than cardnum if (dealtcards[i] <= cardnum){ cardnum++; // card value needs to be one more for (j = 0; j < i; j++){ // backtrack and see if we passed a value // that should now be skipped if (dealtcards[j] == cardnum) cardnum++; // increase actual card value } } } dealtcards[taken] = cardnum; // this card is now taken dealtcards[taken + 1] = -1; // indicate new end of list return cardnum; // this is the next randomly dealt card }