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