# Blackjack infinite deck calculations

a guest
Dec 13th, 2014
271
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
1. ////////////////////////////////////////////////////////////////////
2. // STRATEGY.CPP
3. //
4. // Calculates basic strategy with exact expected values for various styles
5. // of casino blackjack, using an infinite deck approximation.
6.
7. #include <stdio.h>
8. #include <conio.h>
9.
10. #define TRUE            1
11. #define FALSE           0
12. #define max(x,y)        (((x)>(y))?(x):(y))
13.
14. ////////////////////////////////////////////////////////////////////
15. // User-configurable game options.
16.
17. int HIT_SOFT_17,                // TRUE if dealer hits on soft 17
18.     PEEK_10,                    // TRUE if dealer peeks when showing a 10
19.     DOUBLE_ANY_2,               // TRUE if doubling down is allowed on any 2
20.                 // cards
21.     DOUBLE_AFTER_SPLIT,         // TRUE if doubling down after splitting
22.                 // pairs is allowed
23.     RESPLIT,                    // TRUE if re-splitting pairs is allowed
24.     RESPLIT_ACES;       // TRUE if re-splitting aces is allowed
25.
26. ////////////////////////////////////////////////////////////////////
27. // Dealer and player hands.
28.
29. class Hand {
30. public:
31.   int count,                            // point total for the hand
32.       num_aces,                         // number of aces in the hand
33.       soft;                             // TRUE if the hand is "soft"
34.
35. // New() gets rid of all cards in the hand.
36.
37.   void New() {
38.     count = num_aces = soft = 0;
39.   }
40.
41. // Deal() "deals" the given card into the hand.
42.
43.   void Deal(int card) {
44.     count += card;                      // add to point total
45.     if (card == 1) {            // aces are special
46.       num_aces++;
47.       if (count < 12) {         // count as 11 if possible
48.     count += 10;            // (a "soft" hand)
49.     soft = TRUE;
50.       }
51.     }
52.     if (count > 21 && soft) {           // if count is too high to count ace
53.       count -= 10;          // as 11, count it as 1
54.       soft = FALSE;
55.     }
56.   }
57.
58. // Undeal() removes the given card from the hand.
59.
60.   void Undeal(int card) {
61.     count -= card;                      // decrease point total
62.     if (card == 1) {                    // if removing an ace
63.       num_aces--;
64.       if (!num_aces && soft) {          // and the soft hand now has no
65.     count -= 10;                    // aces, make the hand "hard"
66.     soft = FALSE;
67.       }
68.     }
69.     if (count < 12 && num_aces &&       // if ace can now count as 11, make
70.     !soft) {            // hand soft
71.       count += 10;
72.       soft = TRUE;
73.     }
74.   }
75. };
76.
77. Hand dealer; int dealer_up_card;        // dealer's hand, PLUS up card
78. Hand player;                            // player's hand
79.
80. ////////////////////////////////////////////////////////////////////
81. // Chance_Card() returns the probability of drawing the given card from the
82. // deck (constant for infinite deck).
83.
84. long double Chance_Card(int card) {
85.   if (card == 10)
86.     return((long double)4/13);          // 4 of every 13 is a 10
87.   else
88.     return((long double)1/13);          // all others are 1 in 13
89. }
90.
91. ////////////////////////////////////////////////////////////////////
92. // Probability of every possible dealer hand for every possible up card. For
93. // example, chance_dealer_count[6][21] is the probability of the dealer
94. // standing on a count of 21 with 6 as an up card.
95.
96. long double chance_dealer_bust[11],
97.         chance_dealer_count[11][22],
98.         chance_dealer_blackjack[11];
99.
100. ////////////////////////////////////////////////////////////////////
101. // Dealer() is called by Compute_Dealer() to recursively compute the
102. // probability of every possible dealer hand.
103.
104. void Dealer(long double chance) {
105.   int card;
106.
107.   if (dealer.count < 17 ||                      // if dealer should hit
108.      (dealer.count == 17 && HIT_SOFT_17 &&      // (maybe on a soft 17)
109.     dealer.soft))
110.     for (card = 1; card <= 10; card++) {        // deal every possible card
111.       dealer.Deal(card);
112.       Dealer(chance*Chance_Card(card));         // with a given probability
113.       dealer.Undeal(card);
114.     }
115.   else if (dealer.count > 21)                   // dealer busts
116.     chance_dealer_bust[dealer_up_card] += chance;
117.
118. // Dealer stands; note that blackjacks are handled by Compute_Dealer().
119.
120.   else
121.     chance_dealer_count[dealer_up_card][dealer.count] += chance;
122. }
123.
124. ////////////////////////////////////////////////////////////////////
125. // Compute_Dealer() calls Dealer() to compute dealer probabilities for the
126. // up card specified by dealer_up_card.
127.
128. void Compute_Dealer() {
129.   int card;
130.
131. // Reset all dealer probabilities.
132.
133.   chance_dealer_bust[dealer_up_card] =
134.     chance_dealer_blackjack[dealer_up_card] = 0;
135.   for (dealer.count = 17; dealer.count <= 21; dealer.count++)
136.     chance_dealer_count[dealer_up_card][dealer.count] = 0;
137.   dealer.New(); dealer.Deal(dealer_up_card);    // deal JUST the up card
138.   switch (dealer_up_card) {
139.
140. // Dealer ALWAYS checks for blackjack when showing an ace, so assume the hole
141. // card is NEVER a 10.
142.
143.     case 1  : for (card = 1; card < 10;         // deal every card but a 10
144.             card++) {
145.         dealer.Deal(card);
146.         Dealer(Chance_Card(card)/       // chance of that card, GIVEN
147.             ((long double)1 -       // that it's not a 10
148.             Chance_Card(10)));
149.         dealer.Undeal(card);
150.           }
151.           break;
152.
153. // If the dealer checks for blackjack when showing a 10, assume the hole card
154. // is NOT an ace, as above.
155.
156.     case 10 : if (PEEK_10)
157.         for (card = 2; card <= 10; card++) {
158.           dealer.Deal(card);
159.           Dealer(Chance_Card(card)/
160.             ((long double)1 - Chance_Card(1)));
161.           dealer.Undeal(card);
162.         }
163.
164. // If the dealer does NOT peek when showing a 10, the hole card could be an
165. // ace, but handle it here.
166.
167.           else {
168.         for (card = 2; card <= 10; card++) {
169.           dealer.Deal(card);
170.           Dealer(Chance_Card(card));
171.           dealer.Undeal(card);
172.         }
173.         chance_dealer_blackjack[dealer_up_card] =
174.             Chance_Card(1);         // chance of blackjack =
175.           }                                 // chance hole card is an ace
176.           break;
177.
178. // All other up cards are no problem.
179.
180.     default : Dealer(1);
181.   }
182. }
183.
184. ////////////////////////////////////////////////////////////////////
185. // Expected value of every possible player action for every possible
186. // combination of player hand and dealer up card. For example:
187.
188. // stand[7][16] is the expected value of standing on a 16 against a dealer's
189. // 7. Note that these values are the same for "hard" and "soft" hands.
190.
191. long double stand[11][22],
192.
193. // hit[6][0][12] is the expected value of hitting a HARD (that's the 0) 12
194. // against a dealer's 6.
195.
196.         hit[11][2][22],
197.
198. // double_down[6][1][18] is the expected value of doubling down on a SOFT
199. // (that's the 1) 18 (i.e. A-7) against a dealer's 6.
200.
201.         double_down[11][2][22],
202.
203. // split[7][9] is the expected value of splitting a pair of 9's against a
204. // dealer's 7, BUT NOT SPLITTING ANY ADDITIONAL 9's YOU MAY DRAW.
205.
206.         split[11][11],
207.
208. // resplit[7][9] is the expected value of splitting a pair of 9's against a
209. // dealer's 7, AND RE-SPLITTING ANY ADDITIONAL 9's YOU MAY DRAW.
210.
211.         resplit[11][11];
212.
213. ////////////////////////////////////////////////////////////////////
214. // Compute_Gain() computes the expected value of standing, hitting, and
215. // doubling down on the player's hand (given in the player instance of Hand)
216. // against the dealer's up card (in dealer_up_card).
217.
218. void Compute_Gain() {
219.   int card;
220.   long double gain;
221.
222. // Calculate expected value of standing.
223.
224.   stand[dealer_up_card][player.count] =
225.     chance_dealer_bust[dealer_up_card] -    // win if dealer busts
226.     chance_dealer_blackjack[dealer_up_card]; // lose if dealer has BJ
227.   for (dealer.count = 17; dealer.count <= 21;   // if dealer stands
228.     dealer.count++)
229.     if (player.count > dealer.count)            // win if player's count
230.       stand[dealer_up_card][player.count] +=    // beats dealer's count
231.     chance_dealer_count[dealer_up_card][dealer.count];
232.     else if (player.count < dealer.count)       // lose if dealer's count
233.       stand[dealer_up_card][player.count] -=    // beats player's count
234.     chance_dealer_count[dealer_up_card][dealer.count];
235.
236. // Calculate expected value of hitting.
237.
238.   hit[dealer_up_card][player.soft]              // reset expected value
239.     [player.count] = 0;
240.   for (card = 1; card <= 10; card++) {          // for all possible hit cards
241.     player.Deal(card);                          // deal the card
242.
243. ////////////////////////////////////////////////////////////////////
244. // This is the heart of the algorithm. If the player didn't bust after
245. // hitting, we need to know the expected value of the player's NEW hand. We
246. // WILL know this, as long as we have made each of the calls to
247. // Compute_Gain() (one for each possible player hand) IN THE RIGHT ORDER.
248.
249.     if (player.count <= 21)                     // if player didn't bust
250.       gain = max(                               // get BEST expected value of
251.     stand[dealer_up_card][player.count],    // the NEW hand (player can
252.     hit[dealer_up_card][player.soft]        // either stand or hit)
253.         [player.count]);
254.     else                                        // player always loses on a
255.       gain = -1;                                // bust
256.     player.Undeal(card);
257.     hit[dealer_up_card][player.soft]            // weight value of new hand
258.     [player.count] +=                       // with chance of drawing
259.     gain*Chance_Card(card);                 // that card
260.   }
261.
262. // Calculate expected value of doubling down. Note the expected value is
263. // reset with the probability of the dealer having blackjack, and not 0. This
264. // is because IF the dealer has blackjack, the player only loses his original
265. // bet, and not his additional double down bet. Subsequent calculations don't
266. // take this into account, so we make the correction at the outset.
267.
268.   double_down[dealer_up_card][player.soft][player.count] =
269.     chance_dealer_blackjack[dealer_up_card];
270.   for (card = 1; card <= 10; card++) {          // for all possible hit cards
271.     player.Deal(card);                          // deal the card
272.     if (player.count <= 21)                     // if player didn't bust
273.       gain = stand[dealer_up_card][player.count]*2; // player HAS to stand
274.     else
275.       gain = -2;                                // lose it all if hand busts
276.     player.Undeal(card);
277.     double_down[dealer_up_card][player.soft]    // weight value with chance
278.     [player.count] +=                       // of drawing that card
279.     gain*Chance_Card(card);
280.   }
281. }
282.
283. ////////////////////////////////////////////////////////////////////
284. // Compute_Split() computes the expected value of splitting the given pair of
285. // cards against the dealer's up card (in dealer_up_card).
286.
287. void Compute_Split(int pair_card) {
288.   int card;
289.   long double gain;
290.
291.   split[dealer_up_card][pair_card] =            // reset expected values
292.     resplit[dealer_up_card][pair_card] = 0;
293.
294. // We can assume the pair has already been split, and compute the expected
295. // value of ONE of the two NEW hands. For an INFINITE deck, the expected
296. // value of the split will simply be twice this value.
297.
298.   player.New(); player.Deal(pair_card);         // deal the split card
299.   for (card = 1; card <= 10; card++) {          // for all possible second
300.     player.Deal(card);                          // cards, deal that card
301.     gain = stand[dealer_up_card][player.count]; // get EV of standing
302.     if (pair_card != 1) {                       // can't hit split aces!
303.       gain = max(gain,                          // otherwise, maybe hitting
304.     hit[dealer_up_card][player.soft][player.count]); // is better
305.       if (DOUBLE_AFTER_SPLIT &&
306.     (DOUBLE_ANY_2 || player.count == 10 || player.count == 11 ||
307.     (player.count == 20 && player.soft) ||
308.     (player.count == 21 && player.soft)))   // or (if allowed) doubling
309.     gain = max(gain,                        // down
310.         double_down[dealer_up_card][player.soft][player.count]);
311.     }
312.     player.Undeal(card);
313.     split[dealer_up_card][pair_card] +=         // weight EV with chance of
314.     gain*Chance_Card(card);                 // drawing that card
315.
316. // If the hit card makes ANOTHER pair, and re-splitting IS ALLOWED, then the
317. // EV of the new hand is exactly the value we are trying to calculate (this
318. // is similar to the problem of integrating e^x sin x by parts)! So we "put
319. // off" this calculation and "solve" for the EV when we're finished.
320.
321.     if (card != pair_card)
322.       resplit[dealer_up_card][pair_card] += gain*Chance_Card(card);
323.   }
324.
325. // The expected value of the split is twice the value of one split hand;
326. // however, as when doubling down, the player only loses his original bet if
327. // the dealer has blackjack, so the same correction must be made.
328.
329.   split[dealer_up_card][pair_card] *= 2;
330.   split[dealer_up_card][pair_card] +=
331.     chance_dealer_blackjack[dealer_up_card];
332.
333. // The expected value of splitting AND RE-SPLITTING is almost the same, mod a
334. // "normalization" as a result of "solving" for the EV.
335.
336.   resplit[dealer_up_card][pair_card] *= 2;
337.   resplit[dealer_up_card][pair_card] +=
338.     chance_dealer_blackjack[dealer_up_card];
339.   resplit[dealer_up_card][pair_card] /=
340.       (long double)1 - Chance_Card(pair_card)*2;
341. }
342.
343. ////////////////////////////////////////////////////////////////////
344. // Strategy() and Strategy_Split() return the character abbreviation for the
345. // best action for the given player's hand and dealer's up card. Uppercase
346. // means favorable for the player, lowercase means favorable for the house.
347.
348. char Strategy() {
349.   char strategy;
350.   long double s = stand[dealer_up_card][player.count],
351.           h = hit[dealer_up_card][player.soft][player.count],
352.           d = double_down[dealer_up_card][player.soft][player.count];
353.
354.   if (!DOUBLE_ANY_2 && player.count != 10 && player.count != 11 &&
355.     !(player.count == 20 && player.soft) &&
356.     !(player.count == 21 && player.soft))
357.     d = -2;
358.   if (s > h && s > d)
359.     if (s < 0) strategy = 's'; else strategy = 'S';
360.   else if (h > d)
361.     if (h < 0) strategy = 'h'; else strategy = 'H';
362.   else
363.     if (d < 0) strategy = 'd'; else strategy = 'D';
364.   return(strategy);
365. }
366.
367. char Strategy_Split(int card) {
368.   char strategy;
369.   long double s = stand[dealer_up_card][player.count],
370.           h = hit[dealer_up_card][player.soft][player.count],
371.           d = double_down[dealer_up_card][player.soft][player.count],
372.           t = split[dealer_up_card][card],
373.           p = resplit[dealer_up_card][card];
374.
375.   if (!DOUBLE_ANY_2 && player.count != 10) d = -2;
376.   if (!RESPLIT || (!RESPLIT_ACES && card == 1)) p = -2;
377.   if (s > h && s > d && s > t && s > p)
378.     if (s < 0) strategy = 's'; else strategy = 'S';
379.   else if (h > d && h > t && h > p)
380.     if (h < 0) strategy = 'h'; else strategy = 'H';
381.   else if (d > t && d > p)
382.     if (d < 0) strategy = 'd'; else strategy = 'D';
383.   else if (t > p)
384.     if (RESPLIT)
385.       if (t < 0) strategy = 'p'; else strategy = 'P';
386.     else
387.       if (t < 0) strategy = 't'; else strategy = 'T';
388.   else
389.     if (p < 0) strategy = 't'; else strategy = 'T';
390.   return(strategy);
391. }
392.
393. ////////////////////////////////////////////////////////////////////
394. // Expected_Return() returns the expected gain against the dealer's up card.
395.
396. long double Expected_Return() {
397.   long double gain,total = 0;
398.   int card1,card2;
399.
400.   for (card1 = 1; card1 <= 10; card1++)
401.     for (card2 = 1; card2 <= 10; card2++) {
402.       player.New(); player.Deal(card1); player.Deal(card2);
403.       gain = max(stand[dealer_up_card][player.count],
404.     hit[dealer_up_card][player.soft][player.count]);
405.       if (DOUBLE_ANY_2 || player.count == 10 || player.count == 11)
406.     gain = max(gain,
407.         double_down[dealer_up_card][player.soft][player.count]);
408.       if (card1 == card2) {
409.     gain = max(gain,split[dealer_up_card][card1]);
410.     if (RESPLIT && (RESPLIT_ACES || card1 != 1))
411.       gain = max(gain,resplit[dealer_up_card][card1]);
412.       }
413.       if (dealer_up_card == 1)
414.     gain = gain*((long double)1 - Chance_Card(10)) -
415.           Chance_Card(10);
416.       if (dealer_up_card == 10 && PEEK_10)
417.     gain = gain*((long double)1 - Chance_Card(1)) -
418.           Chance_Card(1);
419.       if (player.count == 21) {
420.     gain = (long double)3/2;
421.     if (dealer_up_card == 1)
422.       gain *= (long double)1 - Chance_Card(10);
423.     else if (dealer_up_card == 10)
424.       gain *= (long double)1 - Chance_Card(1);
425.       }
426.       total += gain*Chance_Card(card1)*Chance_Card(card2);
427.   }
428.   return(total);
429. }
430.
431. ////////////////////////////////////////////////////////////////////
432. // Main program.
433.
434. void main() {
435.   char key;
436.   int card;
437.
438.   printf("\n\nBlackjack strategy calculator\n\n");
439.
440. // Set user-configurable game options.
441.
442.   printf("Press 'H' if dealer hits on soft 17, 'Enter' otherwise: ");
443.   while ((key = getch()) != 'H' && key != 'h' && key != '\r');
444.   printf("%c\n",key);
445.   HIT_SOFT_17 = (key == 'H' || key == 'h');
446.
447.   printf("Press 'P' if dealer peeks when showing a 10, 'Enter' otherwise: ");
448.   while ((key = getch()) != 'P' && key != 'p' && key != '\r');
449.   printf("%c\n",key);
450.   PEEK_10 = (key == 'P' || key == 'p');
451.
452.   printf("Press 'D' if doubling down is allowed on any two cards, ");
453.   printf("'Enter' otherwise: ");
454.   while ((key = getch()) != 'D' && key != 'd' && key != '\r');
455.   printf("%c\n",key);
456.   DOUBLE_ANY_2 = (key == 'D' || key == 'd');
457.
458.   printf("Press 'D' if doubling down after splitting is allowed, ");
459.   printf("'Enter' otherwise: ");
460.   while ((key = getch()) != 'D' && key != 'd' && key != '\r');
461.   printf("%c\n",key);
462.   DOUBLE_AFTER_SPLIT = (key == 'D' || key == 'd');
463.
464.   printf("Press 'R' if re-splitting pairs is allowed, 'Enter' otherwise: ");
465.   while ((key = getch()) != 'R' && key != 'r' && key != '\r');
466.   printf("%c\n",key);
467.   RESPLIT = (key == 'R' || key == 'r');
468.
469.   RESPLIT_ACES = FALSE;
470.   if (RESPLIT) {
471.     printf("Press 'A' if re-splitting aces is allowed, 'Enter' otherwise: ");
472.     while ((key = getch()) != 'A' && key != 'a' && key != '\r');
473.     printf("%c\n",key);
474.     RESPLIT_ACES = (key == 'A' || key == 'a');
475.   }
476.   printf("\n");
477.
478. // Compute basic strategy for every possible dealer up card.
479.
480.   for (dealer_up_card = 1; dealer_up_card <= 10; dealer_up_card++) {
481.
482. // Compute probabilities of all possible dealer hands with the given up card.
483.
484.     Compute_Dealer();
485.     player.New();
486.
487. // Compute expected value of HARD hands first, in DECREASING order. We have
488. // to stop at 11, because we could hit a 10 with an ace and have a SOFT 21.
489.
490.     for (player.count = 21; player.count >= 11; player.count--)
491.       Compute_Gain();
492.
493. // Now compute expected value of all SOFT hands, also in DECREASING order.
494.
495.     player.num_aces = player.soft = 1;
496.     for (player.count = 21; player.count >= 12; player.count--)
497.       Compute_Gain();
498.     player.New();
499.
500. // Finish up the hard hands.
501.
502.     for (player.count = 10; player.count >= 4; player.count--)
503.       Compute_Gain();
504.
505. // Now compute expected value of splitting all pairs.
506.
507.     for (card = 1; card <= 10; card++)
508.       Compute_Split(card);
509.   }
510.
511. ////////////////////////////////////////////////////////////////////
512. // Display results to output file.
513.
514.   char filename[80];
515.   FILE *file;
516.
517.   printf("Enter output filename: ");
518.   scanf("%s",filename);
519.   file = fopen(filename,"w");
520.
521. // Display strategy table for hard hands.
522.
523.   fprintf(file,"                Basic Strategy Table\n\n");
524.   fprintf(file,"                         Dealer's up card\n");
525.   fprintf(file,"Hard hands |   2   3   4   5   6   7   8   9  10   A\n");
526.   fprintf(file,"-----------|----------------------------------------\n");
527.   player.New();
528.   for (player.count = 4; player.count <= 21; player.count++) {
529.     fprintf(file,"%6d     |",player.count);
530.     for (dealer_up_card = 2; dealer_up_card <= 10; dealer_up_card++)
531.       fprintf(file,"   %c",Strategy());
532.     dealer_up_card = 1; fprintf(file,"   %c\n",Strategy());
533.   }
534.
535. // Display strategy table for soft hands.
536.
537.   fprintf(file,"\n                         Dealer's up card\n");
538.   fprintf(file,"Soft hands |   2   3   4   5   6   7   8   9  10   A\n");
539.   fprintf(file,"-----------|----------------------------------------\n");
540.   player.New(); player.soft = TRUE;
541.   player.count = 12; fprintf(file,"    A- A   |");
542.   for (dealer_up_card = 2; dealer_up_card <= 10; dealer_up_card++)
543.     fprintf(file,"   %c",Strategy());
544.   dealer_up_card = 1; fprintf(file,"   %c\n",Strategy());
545.   for (player.count = 13; player.count <= 21; player.count++) {
546.     fprintf(file,"    A-%2d   |",player.count - 11);
547.     for (dealer_up_card = 2; dealer_up_card <= 10; dealer_up_card++)
548.       fprintf(file,"   %c",Strategy());
549.     dealer_up_card = 1; fprintf(file,"   %c\n",Strategy());
550.   }
551.
552. // Display strategy table for pairs.
553.
554.   fprintf(file,"\n                         Dealer's up card\n");
555.   fprintf(file,"   Pairs   |   2   3   4   5   6   7   8   9  10   A\n");
556.   fprintf(file,"-----------|----------------------------------------\n");
557.   player.New(); player.Deal(1); player.Deal(1);
558.   fprintf(file,"    A- A   |");
559.   for (dealer_up_card = 2; dealer_up_card <= 10; dealer_up_card++)
560.     fprintf(file,"   %c",Strategy_Split(1));
561.   dealer_up_card = 1; fprintf(file,"   %c\n",Strategy_Split(1));
562.   for (card = 2; card <= 10; card++) {
563.     player.New(); player.Deal(card); player.Deal(card);
564.     fprintf(file,"%5d-%2d   |",card,card);
565.     for (dealer_up_card = 2; dealer_up_card <= 10; dealer_up_card++)
566.       fprintf(file,"   %c",Strategy_Split(card));
567.     dealer_up_card = 1; fprintf(file,"   %c\n",Strategy_Split(card));
568.   }
569.
570. // Display legend.
571.
572.   fprintf(file,"----------------------------------------------------\n");
573.   fprintf(file,"S  Stand\n");
574.   fprintf(file,"H  Hit\n");
575.   fprintf(file,"D  Double down\n");
576.   if (RESPLIT) {
577.     fprintf(file,"T  Split (and re-split)\n");
578.     fprintf(file,"P  Split (only once)\n\n");
579.   }
580.   else
581.     fprintf(file,"T  Split\n\n");
582.   fprintf(file,"Uppercase indicates action is favorable for player\n");
583.   fprintf(file,"Lowercase indicates action is favorable for house\n");
584.
585. // Display expected return.
586.
587.   long double gain,overall = 0;
588.   fprintf(file,"\n     Player's Expected Return\n\n");
589.   fprintf(file,"Dealer's up card | Expected Return\n");
590.   fprintf(file,"-----------------|----------------\n");
591.   for (dealer_up_card = 2; dealer_up_card <= 10; dealer_up_card++) {
592.     gain = Expected_Return();
593.     fprintf(file,"%10d       |%13Lf\n",dealer_up_card,gain);
594.     overall += gain*Chance_Card(dealer_up_card);
595.   }
596.   dealer_up_card = 1;
597.   gain = Expected_Return();
598.   fprintf(file,"         A       |%13Lf\n",gain);
599.   overall += gain*Chance_Card(1);
600.   fprintf(file,"-----------------|----------------\n");
601.   fprintf(file,"     Overall     |%13Lf\n",overall);
602.
603. // Display chance of all possible dealer hands.
604.
605.   fprintf(file,"\n                         Probability of dealer's hand\n\n");
606.   fprintf(file,"Up card |   Bust  |    17   |    18   |    19   |    20   |    21   | Blackjack\n");
607.   fprintf(file,"--------|---------|---------|---------|---------|---------|---------|----------\n");
608.   chance_dealer_bust[0] = chance_dealer_blackjack[0] = 0;
609.   for (dealer.count = 17; dealer.count <= 21; dealer.count++)
610.     chance_dealer_count[0][dealer.count] = 0;
611.   for (dealer_up_card = 2; dealer_up_card < 10; dealer_up_card++) {
612.     fprintf(file,"%5d   |%8.5Lf",dealer_up_card,
613.     chance_dealer_bust[dealer_up_card]);
614.     chance_dealer_bust[0] += chance_dealer_bust[dealer_up_card]*
615.     Chance_Card(dealer_up_card);
616.     for (dealer.count = 17; dealer.count <= 21; dealer.count++) {
617.       fprintf(file," |%8.5Lf",
618.     chance_dealer_count[dealer_up_card][dealer.count]);
619.       chance_dealer_count[0][dealer.count] +=
620.     chance_dealer_count[dealer_up_card][dealer.count]*
621.     Chance_Card(dealer_up_card);
622.     }
623.     fprintf(file," |%8.5Lf\n",chance_dealer_blackjack[dealer_up_card]);
624.   }
625.   if (!PEEK_10) {
626.     fprintf(file,"   10   |%8.5Lf",chance_dealer_bust[10]);
627.     chance_dealer_bust[0] += chance_dealer_bust[10]*Chance_Card(10);
628.     for (dealer.count = 17; dealer.count <= 21; dealer.count++) {
629.       fprintf(file," |%8.5Lf",chance_dealer_count[10][dealer.count]);
630.       chance_dealer_count[0][dealer.count] +=
631.       chance_dealer_count[10][dealer.count]*Chance_Card(10);
632.     }
633.     fprintf(file," |%8.5Lf\n",Chance_Card(1));
634.     chance_dealer_blackjack[0] += Chance_Card(1)*Chance_Card(10);
635.   }
636.   else {
637.     fprintf(file,"   10   |%8.5Lf",chance_dealer_bust[10]*
638.       ((long double)1 - Chance_Card(1)));
639.     chance_dealer_bust[0] += chance_dealer_bust[10]*((long double)1 -
640.       Chance_Card(1))*Chance_Card(10);
641.     for (dealer.count = 17; dealer.count <= 21; dealer.count++) {
642.       fprintf(file," |%8.5Lf",chance_dealer_count[10][dealer.count]*
643.       ((long double)1 - Chance_Card(1)));
644.       chance_dealer_count[0][dealer.count] +=
645.       chance_dealer_count[10][dealer.count]*((long double)1 -
646.           Chance_Card(1))*Chance_Card(10);
647.     }
648.     fprintf(file," |%8.5Lf\n",Chance_Card(1));
649.     chance_dealer_blackjack[0] += Chance_Card(1)*Chance_Card(10);
650.   }
651.   fprintf(file,"    A   |%8.5Lf",chance_dealer_bust[1]*
652.     ((long double)1 - Chance_Card(10)));
653.   chance_dealer_bust[0] += chance_dealer_bust[1]*((long double)1 -
654.     Chance_Card(10))*Chance_Card(1);
655.   for (dealer.count = 17; dealer.count <= 21; dealer.count++) {
656.     fprintf(file," |%8.5Lf",chance_dealer_count[1][dealer.count]*
657.     ((long double)1 - Chance_Card(10)));
658.     chance_dealer_count[0][dealer.count] +=
659.     chance_dealer_count[1][dealer.count]*((long double)1 -
660.         Chance_Card(10))*Chance_Card(1);
661.   }
662.   fprintf(file," |%8.5Lf\n",Chance_Card(10));
663.   chance_dealer_blackjack[0] += Chance_Card(10)*Chance_Card(1);
664.   fprintf(file,"--------|---------|---------|---------|---------|---------|---------|----------\n");
665.   fprintf(file,"Overall |%8.5Lf",chance_dealer_bust[0]);
666.   for (dealer.count = 17; dealer.count <= 21; dealer.count++)
667.     fprintf(file," |%8.5Lf",chance_dealer_count[0][dealer.count]);
668.   fprintf(file," |%8.5Lf\n",chance_dealer_blackjack[0]);
669.
670. ////////////////////////////////////////////////////////////////////
671. // Display expected values for hard hands.
672.
673.   fprintf(file,"\n\t2\t3\t4\t5\t6\t7\t8\t9\t10\tA\n");
674.   player.New();
675.   for (player.count = 4; player.count <= 21; player.count++) {
676.     fprintf(file,"%d",player.count);
677.     for (dealer_up_card = 2; dealer_up_card <= 10; dealer_up_card++)
678.       fprintf(file,"\t%.9Lf",stand[dealer_up_card][player.count]);
679.     fprintf(file,"\t%.9Lf\n",stand[1][player.count]);
680.     fprintf(file,"Hit");
681.     for (dealer_up_card = 2; dealer_up_card <= 10; dealer_up_card++)
682.       fprintf(file,"\t%.9Lf",hit[dealer_up_card][0][player.count]);
683.     fprintf(file,"\t%.9Lf\n",hit[1][0][player.count]);
684.     fprintf(file,"Double");
685.     for (dealer_up_card = 2; dealer_up_card <= 10; dealer_up_card++)
686.       fprintf(file,"\t%.9Lf",double_down[dealer_up_card][0][player.count]);
687.     fprintf(file,"\t%.9Lf\n",double_down[1][0][player.count]);
688.   }
689.
690. // Display expected values for soft hands.
691.
692.   fprintf(file,"\t2\t3\t4\t5\t6\t7\t8\t9\t10\tA\n");
693.   player.num_aces = player.soft = 1;
694.   for (player.count = 12; player.count <= 21; player.count++) {
695.     fprintf(file,"Soft %d",player.count);
696.     for (dealer_up_card = 2; dealer_up_card <= 10; dealer_up_card++)
697.       fprintf(file,"\t%.9Lf",stand[dealer_up_card][player.count]);
698.     fprintf(file,"\t%.9Lf\n",stand[1][player.count]);
699.     fprintf(file,"Hit");
700.     for (dealer_up_card = 2; dealer_up_card <= 10; dealer_up_card++)
701.       fprintf(file,"\t%.9Lf",hit[dealer_up_card][1][player.count]);
702.     fprintf(file,"\t%.9Lf\n",hit[1][1][player.count]);
703.     fprintf(file,"Double");
704.     for (dealer_up_card = 2; dealer_up_card <= 10; dealer_up_card++)
705.       fprintf(file,"\t%.9Lf",double_down[dealer_up_card][1][player.count]);
706.     fprintf(file,"\t%.9Lf\n",double_down[1][1][player.count]);
707.   }
708.
709. // Display expected values for splitting pairs.
710.
711.   fprintf(file,"\t2\t3\t4\t5\t6\t7\t8\t9\t10\tA\n");
712.   player.New(); player.Deal(1); player.Deal(1);
713.   fprintf(file,"A-A");
714.   for (dealer_up_card = 2; dealer_up_card <= 10; dealer_up_card++)
715.     fprintf(file,"\t%.9Lf",stand[dealer_up_card][player.count]);
716.   fprintf(file,"\t%.9Lf\n",stand[1][player.count]);
717.   fprintf(file,"Hit");
718.   for (dealer_up_card = 2; dealer_up_card <= 10; dealer_up_card++)
719.     fprintf(file,"\t%.9Lf",hit[dealer_up_card][player.soft][player.count]);
720.   fprintf(file,"\t%.9Lf\n",hit[1][player.soft][player.count]);
721.   fprintf(file,"Double");
722.   for (dealer_up_card = 2; dealer_up_card <= 10; dealer_up_card++)
723.     fprintf(file,"\t%.9Lf",double_down[dealer_up_card][player.soft][player.count]);
724.   fprintf(file,"\t%.9Lf\n",double_down[1][player.soft][player.count]);
725.   fprintf(file,"Split");
726.   for (dealer_up_card = 2; dealer_up_card <= 10; dealer_up_card++)
727.     fprintf(file,"\t%.9Lf",split[dealer_up_card][1]);
728.   fprintf(file,"\t%.9Lf\n",split[1][1]);
729.   fprintf(file,"Resplit");
730.   for (dealer_up_card = 2; dealer_up_card <= 10; dealer_up_card++)
731.     fprintf(file,"\t%.9Lf",resplit[dealer_up_card][1]);
732.   fprintf(file,"\t%.9Lf\n",resplit[1][1]);
733.   for (card = 2; card <= 10; card++) {
734.     player.New(); player.Deal(card); player.Deal(card);
735.     fprintf(file,"%d-%d",card,card);
736.     for (dealer_up_card = 2; dealer_up_card <= 10; dealer_up_card++)
737.       fprintf(file,"\t%.9Lf",stand[dealer_up_card][player.count]);
738.     fprintf(file,"\t%.9Lf\n",stand[1][player.count]);
739.     fprintf(file,"Hit");
740.     for (dealer_up_card = 2; dealer_up_card <= 10; dealer_up_card++)
741.       fprintf(file,"\t%.9Lf",hit[dealer_up_card][player.soft][player.count]);
742.     fprintf(file,"\t%.9Lf\n",hit[1][player.soft][player.count]);
743.     fprintf(file,"Double");
744.     for (dealer_up_card = 2; dealer_up_card <= 10; dealer_up_card++)
745.       fprintf(file,"\t%.9Lf",double_down[dealer_up_card][player.soft][player.count]);
746.     fprintf(file,"\t%.9Lf\n",double_down[1][player.soft][player.count]);
747.     fprintf(file,"Split");
748.     for (dealer_up_card = 2; dealer_up_card <= 10; dealer_up_card++)
749.       fprintf(file,"\t%.9Lf",split[dealer_up_card][card]);
750.     fprintf(file,"\t%.9Lf\n",split[1][card]);
751.     fprintf(file,"Resplit");
752.     for (dealer_up_card = 2; dealer_up_card <= 10; dealer_up_card++)
753.       fprintf(file,"\t%.9Lf",resplit[dealer_up_card][card]);
754.     fprintf(file,"\t%.9Lf\n",resplit[1][card]);
755.   }
756.
757.   fclose(file);
758. }