File indexing completed on 2025-02-23 05:14:54

0001 // bjgc_dealertableutil.cpp                                           -*-C++-*-
0002 #include <bjgc_dealertableutil.h>
0003 
0004 #include <bjgc_dealertable.h>
0005 
0006 #include <bjgb_dealercount.h>
0007 #include <bjgb_shoe.h>
0008 #include <bjgb_types.h> // 'Double'
0009 
0010 #include <cstring> // 'memcpy()'
0011 #include <iostream> // TBD TEMPORARY
0012 
0013 // STATIC HELPER FUNCTIONS
0014 static void f_h11_h16(bjgc::DealerTable *table, const bjgb::Shoe& shoe, bool dealerStandsOnSoft17Flag)
0015 // Load, into the specified 'table' for rows hard(16) to hard(11), the
0016 // probability of the dealer's getting the corresponding final (column)
0017 // count given the (row) initial state:
0018 //
0019 // P(17, 16) is the probability of getting a hard(17) given a hard(16),
0020 // which is exactly shoe.prob(1) * P(17, 17).
0021 // P(18, 16) is the probability of getting a hard(18) given a hard(16),
0022 // which is exactly shoe.prob(1) * P(18, 17) + shoe.prob(2) * P(18, 18).
0023 // ...
0024 // P(21, 16) is the probability of getting a hard(21) given a hard(16),
0025 // which is exactly shoe.prob(1) * P(21, 17) + shoe.prob(2) * P(21, 18)
0026 //                + shoe.prob(3) * P(21, 19) + shoe.prob(4) * P(21, 20)
0027 //                + shoe.prob(5) * P(21, 21).
0028 // P(BJ, 16) is the probability of getting a blackjack given a hard(16),
0029 // which is exactly 0.0.
0030 // P(OV, 16) is the probability of getting >= 22 given a hard(16),
0031 // which is exactly 1.0 - the sum of the rest (17-21) above.
0032 //
0033 // P(17, 15) is the probability of getting a hard(17) given a hard(15),
0034 // which is exactly shoe.prob(1) * P(17, 16) + shoe.prob(2) * P(17, 17).
0035 // ...
0036 // P(17, 12) is the probability of getting a hard(17) given a hard(12),
0037 // which is exactly shoe.prob(1) * P(17, 13) + shoe.prob(2) * P(17, 14)
0038 //                + shoe.prob(3) * P(17, 15) + shoe.prob(4) * P(17, 16)
0039 //                + shoe.prob(5) * P(17, 17).
0040 // ...
0041 // P(21, 12) is the probability of getting a hard(21) given a hard(12),
0042 // which is exactly shoe.prob(1) * P(21, 13) + shoe.prob(2) * P(21, 14)
0043 //                + shoe.prob(3) * P(21, 15) + shoe.prob(4) * P(21, 16)
0044 //                + shoe.prob(5) * P(21, 17) + shoe.prob(6) * P(21, 18)
0045 //                + shoe.prob(7) * P(21, 19) + shoe.prob(8) * P(21, 20)
0046 //                + shoe.prob(9) * P(21, 21).
0047 // P(BJ, 12) is the probability of getting a blackjack given a hard(12),
0048 // which is exactly 0.0.
0049 // P(OV, 12) is the probability of getting >= 22 given a hard(12),
0050 // which is exactly 1.0 - the sum of the rest (17-21) above.
0051 //
0052 // P(17, 11) is the probability of getting a hard(17) given a hard(11),
0053 // which is exactly shoe.prob(1) * P(17, 12) + shoe.prob(2) * P(17, 13)
0054 //                + shoe.prob(3) * P(17, 14) + shoe.prob(4) * P(17, 15)
0055 //                + shoe.prob(5) * P(17, 16) + shoe.prob(6) * P(17, 17).
0056 // ...
0057 // P(21, 11) is the probability of getting a hard(21) given a hard(11),
0058 // which is exactly shoe.prob(1) * P(21, 12) + shoe.prob(2) * P(21, 13)
0059 //                + shoe.prob(3) * P(21, 14) + shoe.prob(4) * P(21, 15)
0060 //                + shoe.prob(5) * P(21, 16) + shoe.prob(6) * P(21, 17)
0061 //                + shoe.prob(7) * P(21, 18) + shoe.prob(8) * P(21, 19)
0062 //                + shoe.prob(9) * P(21, 20) + shoe.prob(T) * P(21, 21)
0063 //
0064 // P(BJ, 11) is the probability of getting a blackjack given a hard(11),
0065 // which is exactly 0.0.
0066 // P(OV, 11) is the probability of getting >= 22 given a hard(11),
0067 // which is exactly 1.0 - the sum of the rest (17-21) above.
0068 //
0069 // We need to accumulate the probability of winding up with each final
0070 // value for the specified row in the dealer table.  We start with a
0071 // count, 'j', of 16 and reduce it each time until we reach 11, where an
0072 // Ace involves a soft count.
0073 {
0074     for (int j = 16; j >= 11; --j) { // 'hard(j)' is the row we are filling.
0075 
0076         table->clearRow(bjgb::State::hard(j)); // Set all entries in row to 0
0077                                                // (including 'e_CBJ').
0078 
0079         for (int k = 17; k <= 21; ++k) { // for each kolumn 17-21
0080             // For each next card, up to but not including a busting card, add
0081             // each dealt card multiplied by its probability.
0082 
0083             for (int i = 1; i + j <= 21; ++i) { // for each final count <= 21
0084                                                 // in column 'k'
0085 
0086                 table->prob(bjgb::State::hard(j), bjgb::DealerCount::fini(k)) +=
0087                     shoe.prob(i) * table->prob(bjgb::State::hard(j + i), bjgb::DealerCount::fini(k));
0088             }
0089         }
0090 
0091         // Address column 'e_COV' separately.  'total' is used to calculate
0092         // "over" probability.  It could be done independently without
0093         // cumulative error, but that isn't significant.
0094 
0095         bjgb::Types::Double total = 0.0;
0096 
0097         for (int k = 17; k <= 21; ++k) { // for each kolumn 17-21
0098             total += table->prob(bjgb::State::hard(j), // accumulate the row
0099                                  bjgb::DealerCount::fini(k));
0100         }
0101 
0102         table->prob(bjgb::State::hard(j), // "over" is everything else.
0103                     bjgb::DealerCount::e_COV) = 1 - total;
0104     }
0105 }
0106 
0107 static void f_s1_s11(bjgc::DealerTable *table, const bjgb::Shoe& shoe, bool dealerStandsOnSoft17Flag)
0108 // Load, into the specified 'table' for rows soft(1) to soft(11), the
0109 // probability of the dealer's getting the corresponding final (column)
0110 // count given the (row) initial state.
0111 //
0112 // Note that this calculation depends on whether the dealer hits on a soft
0113 // 17, soft(7), for values soft(7) - soft(1).
0114 //
0115 // Dealer cannot hit a soft 21 [soft(11)]:
0116 // P(17, S11) is the probability of getting a hard(17) given a soft(11),
0117 // which is exactly 0.0.
0118 // P(18, S11) is the probability of getting a hard(18) given a soft(11),
0119 // which is exactly 0.0.
0120 // P(19, S11) is the probability of getting a hard(19) given a soft(11),
0121 // which is exactly 0.0.
0122 // P(20, S11) is the probability of getting a hard(20) given a soft(11),
0123 // which is exactly 0.0.
0124 // P(21, S11) is the probability of getting a hard(21) given a soft(11),
0125 // which is exactly 1.0.
0126 //
0127 // ...
0128 //
0129 // Dealer cannot hit a soft 18 [soft(8)]:
0130 // P(17, S08) is the probability of getting a hard(17) given a soft(8),
0131 // which is exactly 0.0.
0132 // P(18, S08) is the probability of getting a hard(18) given a soft(8),
0133 // which is exactly 1.0.
0134 // P(19, S08) is the probability of getting a hard(19) given a soft(8),
0135 // which is exactly 0.0.
0136 // P(20, S08) is the probability of getting a hard(20) given a soft(8),
0137 // which is exactly 0.0.
0138 // P(21, S08) is the probability of getting a hard(21) given a soft(8),
0139 // which is exactly 0.0.
0140 //
0141 // If dealer stands on soft 17:
0142 // P(17, S07) is the probability of getting a hard(17) given a soft(7),
0143 // which is exactly 1.0.
0144 // P(18, S07) is the probability of getting a hard(18) given a soft(7),
0145 // which is exactly 0.0.
0146 // P(19, S07) is the probability of getting a hard(19) given a soft(7),
0147 // which is exactly 0.0.
0148 // P(20, S07) is the probability of getting a hard(20) given a soft(7),
0149 // which is exactly 0.0.
0150 // P(21, S07) is the probability of getting a hard(21) given a soft(7),
0151 // which is exactly 0.0.
0152 //
0153 // If dealer hits on soft 17:
0154 // P(17, S07) is the probability of getting a hard(17) given a soft(7),
0155 // which is exactly shoe.prob( 5) * P(17, 12) + shoe.prob( 6) * P(17, 13)
0156 //                + shoe.prob( 7) * P(17, 14) + shoe.prob( 8) * P(17, 15)
0157 //                + shoe.prob( 9) * P(17, 16) + shoe.prob(10) * P(17, 17)
0158 //                + shoe.prob( 1) * P(17,S08) + shoe.prob( 2) * P(17,S09)
0159 //                + shoe.prob( 3) * P(17,S10) + shoe.prob( 4) * P(17,S11).
0160 //
0161 // P(18, S07) is the probability of getting a hard(18) given a soft(7),
0162 // which is exactly shoe.prob( 5) * P(18, 12) + shoe.prob( 6) * P(18, 13)
0163 //                + shoe.prob( 7) * P(18, 14) + shoe.prob( 8) * P(18, 15)
0164 //                + shoe.prob( 9) * P(18, 16) + shoe.prob(10) * P(18, 17)
0165 //                + shoe.prob( 1) * P(18,S08) + shoe.prob( 2) * P(18,S09)
0166 //                + shoe.prob( 3) * P(18,S10) + shoe.prob( 4) * P(18,S11).
0167 //
0168 // ...
0169 //
0170 // P(21, S07) is the probability of getting a hard(21) given a soft(7),
0171 // which is exactly shoe.prob( 5) * P(21, 12) + shoe.prob( 6) * P(21, 13)
0172 //                + shoe.prob( 7) * P(21, 14) + shoe.prob( 8) * P(21, 15)
0173 //                + shoe.prob( 9) * P(21, 16) + shoe.prob(10) * P(21, 17)
0174 //                + shoe.prob( 1) * P(21,S08) + shoe.prob( 2) * P(21,S09)
0175 //                + shoe.prob( 3) * P(21,S10) + shoe.prob( 4) * P(21,S11).
0176 //
0177 //                         ---------
0178 //
0179 // P(17, S06) is the probability of getting a hard(17) given a soft(6),
0180 // which is exactly shoe.prob( 6) * P(17, 12) + shoe.prob( 7) * P(17, 13)
0181 //                + shoe.prob( 8) * P(17, 14) + shoe.prob( 9) * P(17, 15)
0182 //                + shoe.prob(10) * P(17, 16) + shoe.prob( 1) * P(17,S07)
0183 //                + shoe.prob( 2) * P(17,S08) + shoe.prob( 3) * P(17,S09)
0184 //                + shoe.prob( 4) * P(17,S10) + shoe.prob( 5) * P(17,S11).
0185 //
0186 // P(18, S06) is the probability of getting a hard(18) given a soft(6),
0187 // which is exactly shoe.prob( 6) * P(18, 12) + shoe.prob( 7) * P(18, 13)
0188 //                + shoe.prob( 8) * P(18, 14) + shoe.prob( 9) * P(18, 15)
0189 //                + shoe.prob(10) * P(18, 16) + shoe.prob( 1) * P(18,S07)
0190 //                + shoe.prob( 2) * P(18,S08) + shoe.prob( 3) * P(18,S09)
0191 //                + shoe.prob( 4) * P(18,S10) + shoe.prob( 5) * P(18,S11).
0192 //
0193 // ...
0194 //
0195 // P(21, S06) is the probability of getting a hard(21) given a soft(6),
0196 // which is exactly shoe.prob( 6) * P(21, 12) + shoe.prob( 7) * P(21, 13)
0197 //                + shoe.prob( 8) * P(21, 14) + shoe.prob( 9) * P(21, 15)
0198 //                + shoe.prob(10) * P(21, 16) + shoe.prob( 1) * P(21,S07)
0199 //                + shoe.prob( 2) * P(21,S08) + shoe.prob( 3) * P(21,S09)
0200 //                + shoe.prob( 4) * P(21,S10) + shoe.prob( 5) * P(21,S11).
0201 //
0202 // P(17, S05) is the probability of getting a hard(17) given a soft(5),
0203 // which is exactly shoe.prob( 7) * P(17, 12) + shoe.prob( 8) * P(17, 13)
0204 //                + shoe.prob( 9) * P(17, 14) + shoe.prob(10) * P(17, 15)
0205 //                + shoe.prob( 1) * P(17,S06) + shoe.prob( 2) * P(17,S07)
0206 //                + shoe.prob( 3) * P(17,S08) + shoe.prob( 4) * P(17,S09)
0207 //                + shoe.prob( 5) * P(17,S10) + shoe.prob( 6) * P(17,S11).
0208 //
0209 // P(18, S05) is the probability of getting a hard(18) given a soft(5),
0210 // which is exactly shoe.prob( 7) * P(18, 12) + shoe.prob( 8) * P(18, 13)
0211 //                + shoe.prob( 9) * P(18, 14) + shoe.prob(10) * P(18, 15)
0212 //                + shoe.prob( 1) * P(18,S06) + shoe.prob( 2) * P(18,S07)
0213 //                + shoe.prob( 3) * P(18,S08) + shoe.prob( 4) * P(18,S09)
0214 //                + shoe.prob( 5) * P(18,S10) + shoe.prob( 6) * P(18,S11).
0215 //
0216 // ...
0217 //
0218 // P(21, S05) is the probability of getting a hard(21) given a soft(5),
0219 // which is exactly shoe.prob( 7) * P(21, 12) + shoe.prob( 8) * P(21, 13)
0220 //                + shoe.prob( 9) * P(21, 14) + shoe.prob(10) * P(21, 15)
0221 //                + shoe.prob( 1) * P(21,S06) + shoe.prob( 2) * P(21,S07)
0222 //                + shoe.prob( 3) * P(21,S08) + shoe.prob( 4) * P(21,S09)
0223 //                + shoe.prob( 5) * P(21,S10) + shoe.prob( 6) * P(21,S11).
0224 //
0225 // ...
0226 //
0227 // P(17, S02) is the probability of getting a hard(17) given a soft(2),
0228 // which is exactly shoe.prob(10) * P(17, 12) + shoe.prob( 1) * P(17,S03)
0229 //                + shoe.prob( 2) * P(17,S04) + shoe.prob( 3) * P(17,S05)
0230 //                + shoe.prob( 4) * P(17,S06) + shoe.prob( 5) * P(17,S07)
0231 //                + shoe.prob( 6) * P(17,S08) + shoe.prob( 7) * P(17,S09)
0232 //                + shoe.prob( 8) * P(17,S10) + shoe.prob( 9) * P(17,S11).
0233 //
0234 // P(18, S02) is the probability of getting a hard(18) given a soft(2),
0235 // which is exactly shoe.prob(10) * P(18, 12) + shoe.prob( 1) * P(18,S03)
0236 //                + shoe.prob( 2) * P(18,S04) + shoe.prob( 3) * P(18,S05)
0237 //                + shoe.prob( 4) * P(18,S06) + shoe.prob( 5) * P(18,S07)
0238 //                + shoe.prob( 6) * P(18,S08) + shoe.prob( 7) * P(18,S09)
0239 //                + shoe.prob( 8) * P(18,S10) + shoe.prob( 9) * P(18,S11).
0240 //
0241 // ...
0242 //
0243 // P(21, S02) is the probability of getting a hard(21) given a soft(2),
0244 // which is exactly shoe.prob(10) * P(21, 12) + shoe.prob( 1) * P(21,S03)
0245 //                + shoe.prob( 2) * P(21,S04) + shoe.prob( 3) * P(21,S05)
0246 //                + shoe.prob( 4) * P(21,S06) + shoe.prob( 5) * P(21,S07)
0247 //                + shoe.prob( 6) * P(21,S08) + shoe.prob( 7) * P(21,S09)
0248 //                + shoe.prob( 8) * P(21,S10) + shoe.prob( 9) * P(21,S11).
0249 //
0250 // P(17, S01) is the probability of getting a hard(17) given a soft(1),
0251 // which is exactly shoe.prob( 1) * P(17,S02) + shoe.prob( 2) * P(17,S03)
0252 //                + shoe.prob( 3) * P(17,S04) + shoe.prob( 4) * P(17,S05)
0253 //                + shoe.prob( 5) * P(17,S06) + shoe.prob( 6) * P(17,S07)
0254 //                + shoe.prob( 7) * P(17,S08) + shoe.prob( 8) * P(17,S09)
0255 //                + shoe.prob( 9) * P(17,S10) + shoe.prob(10) * P(17,S11).
0256 //
0257 // P(18, S01) is the probability of getting a hard(18) given a soft(1),
0258 // which is exactly shoe.prob( 1) * P(18, 12) + shoe.prob( 2) * P(18,S03)
0259 //                + shoe.prob( 3) * P(18,S04) + shoe.prob( 4) * P(18,S05)
0260 //                + shoe.prob( 5) * P(18,S06) + shoe.prob( 6) * P(18,S07)
0261 //                + shoe.prob( 7) * P(18,S08) + shoe.prob( 8) * P(18,S09)
0262 //                + shoe.prob( 9) * P(18,S10) + shoe.prob(10) * P(18,S11).
0263 //
0264 // ...
0265 //
0266 // P(21, S01) is the probability of getting a hard(21) given a soft(1),
0267 // which is exactly shoe.prob( 1) * P(21,S02) + shoe.prob( 2) * P(21,S03)
0268 //                + shoe.prob( 3) * P(21,S04) + shoe.prob( 4) * P(21,S05)
0269 //                + shoe.prob( 5) * P(21,S06) + shoe.prob( 6) * P(21,S07)
0270 //                + shoe.prob( 7) * P(21,S08) + shoe.prob( 8) * P(21,S09)
0271 //                + shoe.prob( 9) * P(21,S10) + shoe.prob(10) * P(21,S11).
0272 //
0273 // P(BJ, S01) is the probability of getting blackjack given a soft(1),
0274 // which is exactly shoe.prob(10) * P(BJ, BJ);
0275 {
0276     // rows S11-S08 -- dealer cannot hit on any of these soft counts
0277 
0278     for (int j = 11; j >= 8; --j) { // 'soft(j)' is the row we are filling.
0279         table->clearRow(bjgb::State::soft(j)); // Set all entries in row to 0
0280                                                // (including 'e_CBJ').
0281 
0282         table->prob(bjgb::State::soft(j), bjgb::DealerCount::fini(j + 10)) = 1.0;
0283     }
0284 
0285     // row S07 -- depends on rules: Whether dealer must stand on soft 17.
0286 
0287     table->clearRow(bjgb::State::soft(7)); // Set all entries in row to 0
0288                                            // (including 'e_CBJ').
0289 
0290     if (dealerStandsOnSoft17Flag) {
0291         table->prob(bjgb::State::soft(7), bjgb::DealerCount::fini(17)) = 1.0;
0292     } else {
0293         // P(17, S07) is the probability of getting a hard(17) given a soft(7),
0294         // which is exactly:
0295         //               shoe.prob( 5) * P(17, 12) + shoe.prob( 6) * P(17, 13)
0296         //             + shoe.prob( 7) * P(17, 14) + shoe.prob( 8) * P(17, 15)
0297         //             + shoe.prob( 9) * P(17, 16) + shoe.prob(10) * P(17, 17)
0298         //             + shoe.prob( 1) * P(17,S08) + shoe.prob( 2) * P(17,S09)
0299         //             + shoe.prob( 3) * P(17,S10) + shoe.prob( 4) * P(17,S11)
0300         //
0301         // P(18, S07) is the probability of getting a hard(18) given a soft(7),
0302         // which is exactly:
0303         //               shoe.prob( 5) * P(18, 12) + shoe.prob( 6) * P(18, 13)
0304         //             + shoe.prob( 7) * P(18, 14) + shoe.prob( 8) * P(18, 15)
0305         //             + shoe.prob( 9) * P(18, 16) + shoe.prob(10) * P(18, 17)
0306         //             + shoe.prob( 1) * P(18,S08) + shoe.prob( 2) * P(18,S09)
0307         //             + shoe.prob( 3) * P(18,S10) + shoe.prob( 4) * P(18,S11)
0308         //
0309         // ...
0310         //
0311         // P(21, S07) is the probability of getting a hard(21) given a soft(7),
0312         // which is exactly:
0313         //               shoe.prob( 5) * P(21, 12) + shoe.prob( 6) * P(21, 13)
0314         //             + shoe.prob( 7) * P(21, 14) + shoe.prob( 8) * P(21, 15)
0315         //             + shoe.prob( 9) * P(21, 16) + shoe.prob(10) * P(21, 17)
0316         //             + shoe.prob( 1) * P(21,S08) + shoe.prob( 2) * P(21,S09)
0317         //             + shoe.prob( 3) * P(21,S10) + shoe.prob( 4) * P(21,S11)
0318 
0319         for (int k = 17; k <= 21; ++k) { // for each kolumn 17-21
0320             for (int i = 0; i < 10; ++i) { // index of the expression to add
0321                 int base = 4; // starting offset from 1 (ace)
0322                 int offset = base + i; // current     "     "  "   "
0323                 bool softFlag = offset >= 10;
0324 
0325                 int card = 1 + offset % 10; // 5, 6, 7, 8, 9, T, A, 2, 3, 4
0326 
0327                 int hand = 7 + card;
0328                 // 12, 13, 14, 15, 16, 17, S08, S09, S10, S11
0329 
0330                 int hi = softFlag ? bjgb::State::soft(hand) : bjgb::State::hard(hand); // hand index
0331 
0332                 assert(1 <= card);
0333                 assert(card <= 10);
0334 
0335                 table->prob(bjgb::State::soft(7), bjgb::DealerCount::fini(k)) +=
0336                     shoe.prob(card) * table->prob(hi, bjgb::DealerCount::fini(k));
0337             }
0338         }
0339     }
0340 
0341     // rows S06-S02
0342 
0343     for (int j = 6; j >= 2; --j) { // for each soft count S06 to S02
0344         table->clearRow(bjgb::State::soft(j)); // Set all entries in row to 0
0345                                                // (including 'e_CBJ').
0346 
0347         for (int k = 17; k <= 21; ++k) { // for each kolumn 17-21
0348             for (int i = 0; i < 10; ++i) { // index of the expression to add
0349                 int base = 11 - j; // starting offset from 1 (ace)
0350                 int offset = base + i; // current     "     "  "   "
0351                 bool softFlag = offset >= 10;
0352 
0353                 int card = 1 + offset % 10; // 6, 7, 8, 9, T, A, 2, 3, 4, 5
0354                                             // ...
0355                                             // T, A, 2, 3, 4, 5, 6, 7, 8, 9
0356 
0357                 int hand = j + card;
0358                 // 12,  13,  14,  15,  16, S07, S08, S09, S10, S11
0359                 // ...
0360                 // 12, S03, S04, S05, S06, S07, S08, S09, S10, S11
0361 
0362                 int hi = softFlag ? bjgb::State::soft(hand) : bjgb::State::hard(hand); // hand index
0363 
0364                 assert(1 <= card);
0365                 assert(card <= 10);
0366 
0367                 table->prob(bjgb::State::soft(j), bjgb::DealerCount::fini(k)) +=
0368                     shoe.prob(card) * table->prob(hi, bjgb::DealerCount::fini(k));
0369             }
0370         }
0371     }
0372 
0373     // row S01
0374 
0375     table->clearRow(bjgb::State::soft(1)); // Set all entries in row to 0
0376                                            // (including 'e_CBJ').
0377 
0378     for (int k = 17; k <= 21; ++k) { // for each kolumn 17-21
0379         //                  v------- Note that we don't include (TEN).
0380         for (int i = 0; i < 9; ++i) { // index of the expression to add
0381             int base = 10; // starting offset from 1 (ace)
0382             int offset = base + i; // current     "     "  "   "
0383             bool softFlag = offset >= 10;
0384 
0385             assert(softFlag);
0386 
0387             int card = 1 + offset % 10; //  A,  2,  3,  4,  5,  6, 8, 9, (T)
0388 
0389             int hand = 1 + card;
0390             // S02, S03, S04, S05, S06, S07, S08, S09, S10, (S11)
0391 
0392             int hi = bjgb::State::soft(hand); // hand index, always soft
0393 
0394             assert(1 <= card);
0395             assert(card <= 10);
0396 
0397             table->prob(bjgb::State::soft(1), bjgb::DealerCount::fini(k)) +=
0398                 shoe.prob(card) * table->prob(hi, bjgb::DealerCount::fini(k));
0399         }
0400     }
0401 
0402     table->prob(bjgb::State::soft(1), bjgb::DealerCount::e_CBJ) +=
0403         shoe.prob(10) * table->prob(bjgb::State::e_SBJ, bjgb::DealerCount::e_CBJ);
0404 }
0405 
0406 static void f_h2_h10_T_0(bjgc::DealerTable *table, const bjgb::Shoe& shoe, bool dealerStandsOnSoft17Flag)
0407 // Calculate the remaining rows: hard(10) to hard(2), TEN, ZERO
0408 //
0409 // E.g.,
0410 // P(17, 10) = shoe.prob(1) * P(17,S11) + shoe.prob(2) * P(17, 12)
0411 //           + shoe.prob(3) * P(17, 13) + shoe.prob(4) * P(17, 14)
0412 //           + shoe.prob(5) * P(17, 15) + shoe.prob(6) * P(17, 16)
0413 //           + shoe.prob(7) * P(17, 17) + shoe.prob(8) * P(17, 18)
0414 //           + shoe.prob(9) * P(17, 19) + shoe.prob(T) * P(17, 20)
0415 //
0416 // P(18, 10) = shoe.prob(1) * P(18,S11) + shoe.prob(2) * P(18, 12)
0417 //           + shoe.prob(3) * P(18, 13) + shoe.prob(4) * P(18, 14)
0418 //           + shoe.prob(5) * P(18, 15) + shoe.prob(6) * P(18, 16)
0419 //           + shoe.prob(7) * P(18, 17) + shoe.prob(8) * P(18, 18)
0420 //           + shoe.prob(9) * P(18, 19) + shoe.prob(T) * P(18, 20)
0421 // ...
0422 // P(21, 10) = shoe.prob(1) * P(21,S11) + shoe.prob(2) * P(21, 12)
0423 //           + shoe.prob(3) * P(21, 13) + shoe.prob(4) * P(21, 14)
0424 //           + shoe.prob(5) * P(21, 15) + shoe.prob(6) * P(21, 16)
0425 //           + shoe.prob(7) * P(21, 17) + shoe.prob(8) * P(21, 18)
0426 //           + shoe.prob(9) * P(21, 19) + shoe.prob(T) * P(21, 20)
0427 //
0428 // P(17,  9) = shoe.prob(1) * P(17,S10) + shoe.prob(2) * P(17, 11)
0429 //           + shoe.prob(3) * P(17, 12) + shoe.prob(4) * P(17, 13)
0430 //           + shoe.prob(5) * P(17, 14) + shoe.prob(6) * P(17, 15)
0431 //           + shoe.prob(7) * P(17, 16) + shoe.prob(8) * P(17, 17)
0432 //           + shoe.prob(9) * P(17, 18) + shoe.prob(T) * P(17, 19)
0433 //
0434 // P(18,  9) = shoe.prob(1) * P(18,S10) + shoe.prob(2) * P(18, 11)
0435 //           + shoe.prob(3) * P(18, 12) + shoe.prob(4) * P(18, 13)
0436 //           + shoe.prob(5) * P(18, 14) + shoe.prob(6) * P(18, 15)
0437 //           + shoe.prob(7) * P(18, 16) + shoe.prob(8) * P(18, 17)
0438 //           + shoe.prob(9) * P(18, 18) + shoe.prob(T) * P(18, 19)
0439 // ...
0440 // P(21,  9) = shoe.prob(1) * P(21,S10) + shoe.prob(2) * P(21, 11)
0441 //           + shoe.prob(3) * P(21, 12) + shoe.prob(4) * P(21, 13)
0442 //           + shoe.prob(5) * P(21, 14) + shoe.prob(6) * P(21, 15)
0443 //           + shoe.prob(7) * P(21, 16) + shoe.prob(8) * P(21, 17)
0444 //           + shoe.prob(9) * P(21, 18) + shoe.prob(T) * P(21, 19)
0445 //
0446 // :
0447 //
0448 // P(17,  2) = shoe.prob(1) * P(17, S03) + shoe.prob(2) * P(17,  4)
0449 //           + shoe.prob(3) * P(17,  5) + shoe.prob(4) * P(17,  6)
0450 //           + shoe.prob(5) * P(17,  7) + shoe.prob(6) * P(17,  8)
0451 //           + shoe.prob(7) * P(17,  9) + shoe.prob(8) * P(17, 10)
0452 //           + shoe.prob(9) * P(17, 11) + shoe.prob(T) * P(17, 12)
0453 //
0454 // P(18,  2) = shoe.prob(1) * P(18, S03) + shoe.prob(2) * P(18,  4)
0455 //           + shoe.prob(3) * P(18,  5) + shoe.prob(4) * P(18,  6)
0456 //           + shoe.prob(5) * P(18,  7) + shoe.prob(6) * P(18,  8)
0457 //           + shoe.prob(7) * P(18,  9) + shoe.prob(8) * P(18, 10)
0458 //           + shoe.prob(9) * P(18, 11) + shoe.prob(T) * P(18, 12)
0459 // ...
0460 // P(21,  2) = shoe.prob(1) * P(21, S03) + shoe.prob(2) * P(21,  4)
0461 //           + shoe.prob(3) * P(21,  5) + shoe.prob(4) * P(21,  6)
0462 //           + shoe.prob(5) * P(21,  7) + shoe.prob(6) * P(21,  8)
0463 //           + shoe.prob(7) * P(21,  9) + shoe.prob(8) * P(21, 10)
0464 //           + shoe.prob(9) * P(21, 11) + shoe.prob(T) * P(21, 12)
0465 {
0466     for (int j = 10; j >= 2; --j) { // 'hard(j)' is the row we are filling.
0467         table->clearRow(bjgb::State::hard(j)); // Set all entries in row to 0
0468                                                // (including 'e_CBJ').
0469 
0470         for (int k = 17; k <= 21; ++k) { // for each kolumn 17-21
0471             for (int card = 1; card <= 10; ++card) { // for each card value
0472                 bool softFlag = 1 == card; // an Ace?
0473                 int hand = j + card;
0474                 int hi = softFlag ? bjgb::State::soft(hand) : bjgb::State::hard(hand);
0475                 // hand index
0476 
0477                 table->prob(bjgb::State::hard(j), bjgb::DealerCount::fini(k)) +=
0478                     shoe.prob(card) * table->prob(hi, bjgb::DealerCount::fini(k));
0479             }
0480         }
0481     }
0482 
0483     // TEN
0484 
0485     table->clearRow(bjgb::State::e_H_T); // Set all entries in row to 0
0486                                          // (including 'e_CBJ').
0487 
0488     for (int k = 17; k <= 21; ++k) { // for each kolumn 17-21
0489         for (int card = 2; card <= 10; ++card) { // for each card value except
0490                                                  // A
0491             int hand = 10 + card;
0492             int hi = bjgb::State::hard(hand); // hand index, always hard
0493 
0494             table->prob(bjgb::State::e_H_T, bjgb::DealerCount::fini(k)) +=
0495                 shoe.prob(card) * table->prob(hi, bjgb::DealerCount::fini(k));
0496         }
0497     }
0498 
0499     table->prob(bjgb::State::e_H_T, bjgb::DealerCount::e_CBJ) =
0500         shoe.prob(1) * table->prob(bjgb::State::e_SBJ, bjgb::DealerCount::e_CBJ);
0501 
0502     // ZERO
0503 
0504     table->clearRow(bjgb::State::e_HZR); // Set all entries in row to 0
0505                                          // (including 'e_CBJ').
0506 
0507     for (int k = 17; k <= 21; ++k) { // for each kolumn 17-21
0508         for (int card = 1; card <= 9; ++card) { // for each card value except T
0509             bool softFlag = 1 == card; // an Ace?
0510             int hand = 0 + card;
0511             int hi = softFlag ? bjgb::State::soft(hand) : bjgb::State::hard(hand); // hand index
0512 
0513             table->prob(bjgb::State::e_HZR, bjgb::DealerCount::fini(k)) +=
0514                 shoe.prob(card) * table->prob(hi, bjgb::DealerCount::fini(k));
0515         }
0516 
0517         table->prob(bjgb::State::e_HZR, bjgb::DealerCount::fini(k)) +=
0518             shoe.prob(10) * table->prob(bjgb::State::e_H_T, bjgb::DealerCount::fini(k));
0519     }
0520 
0521     for (int card = 1; card <= 9; ++card) { // for each card value except T
0522         bool softFlag = 1 == card; // an Ace?
0523         int hand = 0 + card;
0524         int hi = softFlag ? bjgb::State::soft(hand) : bjgb::State::hard(hand); // hand index
0525 
0526         table->prob(bjgb::State::e_HZR, bjgb::DealerCount::e_CBJ) +=
0527             shoe.prob(card) * table->prob(hi, bjgb::DealerCount::e_CBJ);
0528     }
0529 
0530     table->prob(bjgb::State::e_HZR, bjgb::DealerCount::e_CBJ) +=
0531         shoe.prob(10) * table->prob(bjgb::State::e_H_T, bjgb::DealerCount::e_CBJ);
0532 
0533     // NOTE: 220118: I think we need to check this thoroughly.
0534     std::cout << "*** CHECK ME! ***" << std::endl;
0535     std::cout << "*** CHECK ME! ***" << std::endl;
0536     std::cout << "*** CHECK ME! ***" << std::endl;
0537 }
0538 
0539 static void calculateOverColumn(bjgc::DealerTable *table)
0540 // For each row in the specified dealer 'table', add up each entry except
0541 // the last, then subtract the total from 1.0 to get the final column
0542 // ('e_COV').
0543 {
0544     const int k_LAST = bjgb::DealerCount::k_NUM_FINAL_COUNTS - 1;
0545 
0546     assert(k_LAST == bjgb::DealerCount::e_COV);
0547 
0548     for (int st = 0; st < bjgb::State::k_NUM_STATES; ++st) { // for each state
0549         // 'total' is used to calculate "over" probability.  It could be done
0550         // independently without cumulative error, but that's not significant.
0551 
0552         bjgb::Types::Double total = 0.0;
0553 
0554         for (int k = 0; k < k_LAST; ++k) { // for each kolumn but the last
0555             total += table->prob(st, k);
0556         }
0557 
0558         table->prob(st, k_LAST) = 1.0 - total; // "over" is everything else.
0559     }
0560 }
0561 
0562 static void copyRowsS01H09toZ(bjgc::DealerTable *table)
0563 // Copy the contents of the 'e_S01' and 'e_H02 .. e_H09' rows in the
0564 // specified dealer 'table' to the corresponding 'e_S_A .. e_H_9' rows.
0565 // Note that row 'e_H_T' is filled by 'f_0_T_2_10' (above).
0566 {
0567     for (int k = 0; k < bjgb::DealerCount::k_NUM_FINAL_COUNTS; ++k) {
0568         // for each kolumn
0569         // Populate row 'e_S_A' from row 'e_S01'.
0570 
0571         table->prob(bjgb::State::unus(1), k) = table->prob(bjgb::State::soft(1), k);
0572 
0573         // Populate rows 'e_H_2 .. e_H_9' from rows 'e_H02 .. e_H09'.
0574 
0575         for (int i = 2; i <= 9; ++i) {
0576             table->prob(bjgb::State::unus(i), k) = table->prob(bjgb::State::hard(i), k);
0577         }
0578     }
0579 }
0580 
0581 namespace bjgc {
0582 
0583 // ----------------------
0584 // struct DealerTableUtil
0585 // ----------------------
0586 
0587 // CLASS METHODS
0588 void DealerTableUtil::adjustForBj(DealerTable *dst, const DealerTable& src)
0589 // NOTE: WAIT! IS THIS CORRECT? I THINK IT IS! TRIPLE CHECK :)
0590 // The idea is that IF a blackjack happens then there is no opportunity
0591 // for strategy.  However, it does affect the expected value of the game.
0592 // Specifically, that BJ pushes BJ.  Note that this is important only when
0593 // adding more money (splitting/doubling) is involved as scaling doesn't
0594 // change the relative values otherwise.
0595 {
0596     assert(dst);
0597 
0598     memcpy(dst, &src, sizeof src);
0599 
0600     // apply to each column: 17-21, BJ, OVER
0601 
0602     for (int j : {1, 10}) { // for each single card, 'unus(j)'
0603         std::cout << "adjustForBj: j = " << j << std::endl;
0604 
0605         const bjgb::Types::Double probabilityNotBj = 1.0 - src.prob(bjgb::State::unus(j), bjgb::DealerCount::e_CBJ);
0606 
0607         for (int i = 0; i < bjgb::DealerCount::k_NUM_FINAL_COUNTS; ++i) {
0608             dst->prob(bjgb::State::unus(j), i) /= probabilityNotBj;
0609         }
0610 
0611         dst->prob(bjgb::State::unus(j), bjgb::DealerCount::e_CBJ) = 0.0;
0612         // Overwrite BJ to be 0!
0613     }
0614 }
0615 
0616 void DealerTableUtil::populate(DealerTable *table, const bjgb::Shoe& shoe, bool dealerStandsOnSoft17)
0617 {
0618     assert(table);
0619 
0620     table->reset();
0621 
0622     // rows hard 17-21 ('e_H17 .. e_H21'), BJ, and OVer
0623 
0624     for (int i = 17; i <= 21; ++i) {
0625         table->clearRow(bjgb::State::hard(i));
0626         table->prob(bjgb::State::hard(i), bjgb::DealerCount::fini(i)) = 1.0;
0627     }
0628 
0629     table->clearRow(bjgb::State::e_SBJ);
0630     table->prob(bjgb::State::e_SBJ, bjgb::DealerCount::e_CBJ) = 1.0;
0631 
0632     table->clearRow(bjgb::State::e_HOV);
0633     table->prob(bjgb::State::e_HOV, bjgb::DealerCount::e_COV) = 1.0;
0634 
0635     // rows hard 11-16 ('e_H11 .. e_H16')
0636 
0637     f_h11_h16(table, shoe, dealerStandsOnSoft17);
0638 
0639     // rows soft 1-11 ('e_S01 .. e_S11')
0640 
0641     f_s1_s11(table, shoe, dealerStandsOnSoft17);
0642 
0643     // rows hard 2-10 ('e_H02 .. e_H10'), single TEN ('e_H_T'), and 'e_HZR'
0644 
0645     f_h2_h10_T_0(table, shoe, dealerStandsOnSoft17);
0646 
0647     // Calculate the final column ('e_COV') of each row as 1 minus the rest.
0648 
0649     calculateOverColumn(table);
0650 
0651     // Transfer the 'e_S01' and 'e_H02 .. e_H09' rows to 'e_S_A .. e_H_9'.
0652 
0653     copyRowsS01H09toZ(table);
0654 
0655     // Note that rows 'e_YAA .. e_YTT' are not populated in dealer tables as
0656     // they are relevant to players only.
0657 }
0658 
0659 } // namespace bjgc