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

0001 // bjgc_playertableutil.cpp                                           -*-C++-*-
0002 #include <bjgc_playertableutil.h>
0003 
0004 #include <bjgb_dealercount.h>
0005 #include <bjgb_types.h> // 'Double'
0006 
0007 #include <cassert>
0008 #include <iostream> // TBD TEMPORARY
0009 
0010 // The player's hand is all about expected value, not just Probability.
0011 //
0012 // The question is: For a specified set of rules, shoe, and dealer up card,
0013 // what is the expected value of any given hand (assuming you play perfectly)
0014 // and what is the optimal strategy.
0015 //
0016 // The structure of the Player's table is the same as that of the Dealer's
0017 // table except that the numbers in the columns represent expected values for
0018 // each dealer up card assuming a strategy.
0019 //
0020 // We need a table for stand (pstab), hit at least once (phtab), and hit once
0021 // only (p1tab), which we will use when we double the bet.
0022 //
0023 // In the end, we will need a table that has the best way to play.
0024 //
0025 // Split applies only to certain even counts: S2, 4-20.  We will get one card
0026 // to a split Ace unless we there is rule allowing multiple cards.  In the end,
0027 // we will have to incorporate the probability of getting two of the same card:
0028 // P(1) * P(1), P(2) * P(2), ... P(10) * P(10).  In the case of Aces, we will
0029 // typically use the 1-hit table without considering splits.  In all other
0030 // cases, we'll need a table that considers the possibility of getting a pair
0031 // and doubling the resulting expected value of that single card.  As a result,
0032 // the dealer table holds soft counts at the beginning and the has notion of
0033 // single cards, even for non-TEN cards, so that we can use the hit/one-hit
0034 // depending on whether it is a pair of Aces or otherwise.
0035 //
0036 // Surrender is defined precisely in terms of whether the expected value of
0037 // -0.5 is better or worse than playing normally.
0038 
0039 namespace bjgc {
0040 
0041 // ----------------------
0042 // struct PlayerTableUtil
0043 // ----------------------
0044 
0045 // CLASS METHODS
0046 void PlayerTableUtil::copyPlayerRow(PlayerTable *pta, int hia, const PlayerTable& ptb, int hib)
0047 {
0048     assert(pta);
0049     assert(0 <= hia);
0050     assert(hia < bjgb::State::k_NUM_STATES);
0051     assert(0 <= hib);
0052     assert(hib < bjgb::State::k_NUM_STATES);
0053 
0054     for (int i = 1; i <= 10; ++i) {
0055         pta->exp(hia, i) = ptb.exp(hib, i);
0056     }
0057 }
0058 
0059 bjgb::Types::Double PlayerTableUtil::eDouble(const PlayerTable& p1t, int uc, int hv, bool sf)
0060 {
0061     std::cout << "##### eDouble: " << std::flush;
0062     std::cout << " uc = " << uc;
0063     std::cout << " hv = " << hv;
0064     std::cout << " sf = " << sf;
0065     std::cout << std::endl;
0066 
0067     assert(1 <= uc);
0068     assert(uc <= 10);
0069     assert(2 <= hv);
0070     assert(hv <= 21);
0071     assert(hv >= 4 || sf);
0072     assert(hv <= 11 || !sf);
0073 
0074     // The expected value is simply twice the corresponding value in the
0075     // hard/soft hand.
0076 
0077     int hi = sf ? bjgb::State::soft(hv) : bjgb::State::hard(hv); // hand index
0078 
0079     bjgb::Types::Double temp = p1t.exp(hi, uc);
0080     assert(bjgb::Types::isValid(temp));
0081 
0082     bjgb::Types::Double expectedValue = 2 * temp;
0083     assert(bjgb::Types::isValid(expectedValue));
0084 
0085     return expectedValue;
0086 }
0087 
0088 bjgb::Types::Double PlayerTableUtil::eHit1(const PlayerTable& pst, int uc, int hv, bool sf, const bjgb::Shoe& shoe)
0089 {
0090     // Implementation note: Column values are deliberately summed in a
0091     // canonical order for numerical consistency: A, 2, ..., 9, T.
0092 
0093     assert(1 <= uc);
0094     assert(uc <= 10);
0095     assert(1 <= hv);
0096     assert(hv <= 21);
0097     assert(hv > 1 || sf);
0098     assert(hv <= 11 || !sf);
0099 
0100     bjgb::Types::Double sum = 0; // Accumulated expected value for each
0101                                  // possible hand.
0102 
0103     for (int cd = 1; cd <= 10; ++cd) { // for each possible card dealt, 'cd'
0104         int soft = 1 == cd || sf; // if we get an A it is automatically soft
0105         int value = hv + cd; // hit hand with 'cd'
0106 
0107         if (soft && value + 10 <= 21) {
0108             value += 10; // make soft count a hard count
0109         }
0110 
0111         // Hand 'value' is hard from here on.
0112 
0113         if (value <= 16) {
0114             assert(bjgb::Types::isValid(pst.exp(bjgb::State::hard(16), uc)));
0115 
0116             sum += shoe.prob(cd) * pst.exp(bjgb::State::hard(16), uc);
0117         } else if (value >= 22) {
0118             assert(-1 == pst.exp(bjgb::State::e_HOV, uc));
0119 
0120             sum += shoe.prob(cd) * pst.exp(bjgb::State::e_HOV, uc);
0121         } else {
0122             assert(17 <= value);
0123             assert(value <= 21);
0124             assert(bjgb::Types::isValid(pst.exp(bjgb::State::hard(value), uc)));
0125 
0126             sum += shoe.prob(cd) * pst.exp(bjgb::State::hard(value), uc);
0127         }
0128     }
0129 
0130     return sum;
0131 }
0132 
0133 bjgb::Types::Double
0134 PlayerTableUtil::eHitN(const PlayerTable& pht, const PlayerTable& pst, int uc, int hv, bool sf, const bjgb::Shoe& shoe)
0135 {
0136     // Implementation note: 'eHitN' is similar to 'eHit1' except that, for
0137     // each card, we choose to hit again or stand as appropriate.  Since this
0138     // table depends on itself, we need to do things in order, which means hard
0139     // counts down to 11 first, then soft counts from 11 to 1, followed by hard
0140     // counts from 10 to 2.  If we access an expected value that is not in the
0141     // valid range of -2 to 2, it is invalid and should be asserted as such.
0142     // Note that column values are deliberately summed in a canonical order for
0143     // numerical consistency: A, 2, ..., 9, T.
0144 
0145     assert(1 <= uc);
0146     assert(uc <= 10);
0147     assert(1 <= hv);
0148     assert(hv <= 21);
0149     assert(hv > 1 || sf);
0150     assert(hv <= 11 || !sf);
0151 
0152     bjgb::Types::Double sum = 0; // Accumulated expected value for each
0153                                  // possible hand.
0154 
0155     for (int cd = 1; cd <= 10; ++cd) { // for each possible card dealt, 'cd'
0156         int minValue = hv + cd; // lowest possible cards value
0157 
0158         bjgb::Types::Double expVal = -9999.99;
0159         bjgb::Types::Double shi = -999;
0160         bjgb::Types::Double hhi = -999;
0161         bjgb::Types::Double maxValue = -999999.9999;
0162 
0163         bool stillSoftFlag; // unset!
0164 
0165         // If minimum value is over, the expected value is exactly that of
0166         // standing with an OVER.
0167 
0168         if (minValue > 21) {
0169             expVal = pst.exp(bjgb::State::e_HOV, uc);
0170             assert(-1.0 == expVal);
0171         } else {
0172             stillSoftFlag = (1 == cd || sf) && minValue <= 11;
0173             maxValue = minValue + stillSoftFlag * 10;
0174 
0175             shi = bjgb::State::hard(maxValue);
0176             hhi = (stillSoftFlag ? bjgb::State::soft : bjgb::State::hard)(minValue);
0177             bjgb::Types::Double stand = pst.exp(shi, uc);
0178             assert(bjgb::Types::isValid(stand));
0179 
0180             bjgb::Types::Double hitIt = pht.exp(hhi, uc);
0181             assert(bjgb::Types::isValid(hitIt));
0182 
0183             expVal = std::max<bjgb::Types::Double>(stand, hitIt);
0184             assert(bjgb::Types::isValid(expVal));
0185         }
0186 
0187         sum += shoe.prob(cd) * expVal;
0188         assert(bjgb::Types::isValid(sum));
0189 
0190         // what follows is just double checking :)
0191 
0192         if (minValue > 21) {
0193             assert(-1.0 == expVal);
0194         } else if (minValue <= 11 && stillSoftFlag) {
0195             assert(maxValue == minValue + 10);
0196             assert(maxValue <= 21);
0197             assert(bjgb::State::hard(maxValue) == shi);
0198             assert(bjgb::State::soft(minValue) == hhi);
0199         } else { // they are both hard counts and not over 21.
0200             assert(maxValue == minValue);
0201             assert(maxValue == minValue);
0202             assert(maxValue <= 21);
0203             assert(bjgb::State::hard(maxValue) == shi);
0204             assert(bjgb::State::hard(minValue) == hhi);
0205         }
0206     }
0207 
0208     return sum;
0209 }
0210 
0211 bjgb::Types::Double PlayerTableUtil::eSplit(const PlayerTable& pdt,
0212                                             const PlayerTable& pht,
0213                                             const PlayerTable& p1t,
0214                                             const PlayerTable& pst,
0215                                             int uc,
0216                                             int hv,
0217                                             int n,
0218                                             const bjgb::Shoe& shoe,
0219                                             const bjgb::Rules& rules)
0220 // TBD: rules: can you double after a split Ace?
0221 // TBD: rules: can you re-split after a split Ace?
0222 {
0223     std::cout << "[eSplit: n = " << n << "]" << std::flush;
0224     assert(1 <= uc);
0225     assert(uc <= 10);
0226     assert(2 <= hv);
0227     assert(hv <= 20);
0228     assert(0 == hv % 2); // only even hands can be split
0229     assert(n >= 0);
0230 
0231     // The value to be returned is 2 * the expected value of every drawn card
0232     // other than the split card.  Suppose the split card is 8: the expected
0233     // value of splitting two eights is twice the max of hitting or doubling
0234     // A..7, 9, and 10.  But, for an eight, it is recursive, and there is
0235     // P(8) * the expected value of splitting again with decremented 'n':
0236     //
0237     // Split(8s, 10, 3) = 2 * shoe.prob( 1) * maxDHS(soft( 9))  // maybe can't
0238     //                                                          // double?
0239     //                  + 2 * shoe.prob( 2) * maxDHS(hard(10))
0240     //                  + 2 * shoe.prob( 3) * maxDHS(hard(11))
0241     //                  + ...
0242     //                  + 2 * shoe.prob( 7) * maxDHS(hard(15))
0243     //                  + 2 * shoe.prob( 8) * Split(8s, 10, 2)
0244     //                  + 2 * shoe.prob( 9) * maxDHS(hard(17))
0245     //                  + 2 * shoe.prob(10) * maxDHS(hard(18))
0246     //
0247     // Split(As, 6, 1)  = 2 * shoe.prob( 1) * maxDHS(soft(2))  // maybe can't
0248     //                                                         // double?
0249     //                  + 2 * shoe.prob( 2) * maxDHS(soft(3))
0250     //                  + 2 * shoe.prob( 3) * maxDHS(hard(11))
0251     //                  + ...
0252     //                  + 2 * shoe.prob( 7) * maxDHS(hard(15))
0253     //                  + 2 * shoe.prob( 9) * maxDHS(hard(17))
0254     //                  + 2 * shoe.prob(10) * maxDHS(hard(18))
0255     //
0256 
0257     if (0 == n) { // Splitting is not an option.
0258         std::cout << "[n = 0]" << std::flush;
0259         // We have recursed, and splitting is no longer an option.  We need to
0260         // return the best value between hitting or standing, and possibly
0261         // doubling.
0262 
0263         int hi = 2 == hv ? bjgb::State::soft(2) : bjgb::State::hard(hv);
0264         int ui = uc; // It would be nice if both
0265                      // 'hi' and 'ui' were type-safe.
0266 
0267         // TBD: the block below should be factored out as a separate function.
0268 
0269         bjgb::Types::Double hVal = pht.exp(hi, ui);
0270         bjgb::Types::Double sVal = pst.exp(hi, ui);
0271 
0272         bjgb::Types::Double expVal = std::max<bjgb::Types::Double>(hVal, sVal);
0273 
0274         if (rules.playerMayDoubleOnTheseTwoCards(hv, 2 == hv)) {
0275             std::cout << "[can double]" << std::flush;
0276             bjgb::Types::Double dVal = pdt.exp(hi, ui);
0277             expVal = std::max<bjgb::Types::Double>(expVal, dVal);
0278         }
0279 
0280         std::cout << "[***EARLY RETURN***]" << std::flush;
0281 
0282         return expVal; // there expected value isn't doubled here
0283     }
0284 
0285     // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
0286     // If we get to here, splitting is a viable option and the bet will be
0287     // doubled; we'll make the assumption that splitting is to be repeated
0288     // while possible.
0289 
0290     bjgb::Types::Double expectedValue = 0.0; // Accumulate expected value over
0291                                              // 10 cards.
0292     int ui = uc;
0293     const int playerCard = hv / 2;
0294 
0295     // Address splitting Aces as a special case.  Note that re-splitting Aces
0296     // is handled from outside the function by passing num-splits as 1.  There
0297     // is therefore no need to query 'playerMayResplitAces'.
0298 
0299     if (1 == playerCard && rules.playerGetsOneCardOnlyToSplitAce()) {
0300         std::cout << "[card=A]" << std::flush;
0301         bool resplitAces = n >= 2; // set by checking rules from outside
0302         std::cout << "[A]" << std::flush;
0303 
0304         if (resplitAces) { // Note that we do 'prob(1)' first! always.
0305             std::cout << "[C]" << std::flush;
0306             // TBD look into removing possibility of 'n == 0'
0307             expectedValue += shoe.prob(1) * eSplit(pdt, pht, p1t, pst, uc, hv, n - 1, shoe, rules);
0308         }
0309 
0310         for (int i = 2 - !resplitAces; i <= 10; ++i) {
0311             std::cout << "[B]" << std::flush;
0312             int softHand = 1 + i;
0313             expectedValue += shoe.prob(i) * pst.exp(bjgb::State::soft(softHand), ui);
0314         }
0315     } else { // treat Aces just like any other card (split based on 'n')
0316         std::cout << "[C]" << std::flush;
0317         for (int i = 1; i <= 10; ++i) { // for each possible drawn card
0318             std::cout << "[E]" << std::flush;
0319             if (playerCard == i && n >= 2) { // this is where we recurse
0320                 std::cout << "[F]" << std::flush;
0321                 // 0 would mean we recursed internally
0322                 // 1 would mean no further splits are allowed
0323                 // TBD consider removing the duplication of '0 == n'
0324 
0325                 expectedValue += shoe.prob(playerCard) * eSplit(pdt, pht, p1t, pst, uc, hv, n - 1, shoe, rules);
0326             } else { // no more splitting
0327                 std::cout << "[G]" << std::flush;
0328                 bool sf = 1 == i || 1 == playerCard;
0329                 int hand = playerCard + i;
0330                 int hi = sf ? bjgb::State::soft(hand) : bjgb::State::hard(hand);
0331 
0332                 bjgb::Types::Double hVal = pht.exp(hi, ui);
0333                 bjgb::Types::Double sVal = pst.exp(hi, ui);
0334 
0335                 bjgb::Types::Double expVal = std::max<bjgb::Types::Double>(hVal, sVal);
0336 
0337                 if (rules.playerMayDoubleOnTheseTwoCards(hv, 2 == hv)) {
0338                     std::cout << "[H]" << std::flush;
0339                     bjgb::Types::Double dVal = pdt.exp(hi, ui);
0340                     expVal = std::max<bjgb::Types::Double>(expVal, dVal);
0341                 }
0342 
0343                 expectedValue += shoe.prob(i) * expVal;
0344                 std::cout << "\n[" << i << ": " << expectedValue << "]" << std::flush;
0345             }
0346         }
0347     }
0348 
0349     std::cout << "[RETURN 2*EXP]" << std::flush;
0350 
0351     return 2 * expectedValue;
0352 }
0353 
0354 bjgb::Types::Double PlayerTableUtil::eStand(const DealerTable& t, int uc, int hv)
0355 {
0356     // Implementation note: Values are deliberately added in a canonical order
0357     // for numerical consistency: OVER first, then lower cards, then higher
0358     // cards.
0359 
0360     assert(1 <= uc);
0361     assert(uc <= 10);
0362     assert(4 <= hv);
0363     assert(hv <= 21);
0364 
0365     const int ci = hv < 17 ? -1 : hv - 17; // count index
0366                                            // e.g., if hv = 17, ci = 0; if hv = 21, ci = 4; bj = 5
0367 
0368     bjgb::Types::Double sum = t.prob(bjgb::State::unus(uc), bjgb::DealerCount::e_COV);
0369     // you win if you stand and dealer busts
0370 
0371     for (int i = 0; i < ci; ++i) { // counts that are lower than 'hv'
0372         sum += t.prob(bjgb::State::unus(uc), i);
0373     }
0374 
0375     const int k_FINAL = bjgb::DealerCount::k_NUM_FINAL_COUNTS - 1;
0376     // Don't count OVER again.
0377 
0378     for (int i = ci + 1; i < k_FINAL; ++i) {
0379         sum -= t.prob(bjgb::State::unus(uc), i);
0380     }
0381 
0382     return sum;
0383 }
0384 
0385 bjgb::Types::Double PlayerTableUtil::evalShoeImp(const bjgb::Shoe& shoe,
0386                                                  const PlayerTable& pt,
0387                                                  const PlayerTable& pat,
0388                                                  const bjgb::Rules& rules)
0389 {
0390     // The idea is that we're going to calculate the probability of every
0391     // dealer card.  Note that we need to pass in the adjusted player table
0392     // if we cannot lose double our bet, otherwise we need to pass in the
0393     // unadjusted table.
0394 
0395     // We need to make a pass for surrender if available before we check for
0396     // blackjack.  TBD
0397 
0398     bjgb::Types::Double expectedValue = 0.0;
0399 
0400     for (int i = 1; i <= 10; ++i) { // for each dealer card
0401         bjgb::Types::Double pi = shoe.prob(i);
0402         bjgb::Types::Double pdbj = 1 == i ? shoe.prob(10) : 10 == i ? shoe.prob(1) : 0.0;
0403 
0404         for (int j = 1; j <= 10; ++j) { // for each dealer card
0405             bjgb::Types::Double pj = shoe.prob(j);
0406             bjgb::Types::Double pij = pi * pj;
0407 
0408             for (int k = 1; k <= 10; ++k) { // for each dealer card
0409                 bjgb::Types::Double pk = shoe.prob(k);
0410                 bjgb::Types::Double pijk = pij * pk;
0411 
0412                 bool softFlag = j == 1 || k == 1;
0413                 bool splitFlag = j == k;
0414                 int v = j + k;
0415 
0416                 const PlayerTable& pTab = rules.playerCanLoseDouble() ? pt : pat;
0417 
0418                 bjgb::Types::Double best = pTab.exp(softFlag ? bjgb::State::soft(v) : bjgb::State::hard(v), i);
0419 
0420                 if (splitFlag) {
0421                     best = std::max<bjgb::Types::Double>(best, pTab.exp(bjgb::State::pair(j), i));
0422                 }
0423 
0424                 // We need to handle BJ separately because of payouts and
0425                 // such.  We might build them directly into the expected
0426                 // values for the tables, but let's just calculate them here
0427                 // separately anyway:
0428                 //
0429                 // if player has blackjack (assume player always stands)
0430                 //     if dealer has blackjack
0431                 //         eVal = 0
0432                 //     else
0433                 //         eVal = rules.playerBlackjackPayout();
0434                 // else
0435                 //     if dealer has blackjack
0436                 //         eVal = -1.0
0437                 //     else
0438                 //         eVal = best (based on appropriate player table)
0439 
0440                 bool bjFlag = 11 == v && softFlag;
0441 
0442                 bjgb::Types::Double eVal = -99e99; // "unset" value
0443 
0444                 if (bjFlag) {
0445                     eVal = pdbj * 0.0 + (1.0 - pdbj) * rules.playerBlackjackPayout();
0446                 } else {
0447                     eVal = pdbj * -1.0 + (1.0 - pdbj) * best;
0448                 }
0449 
0450                 if (rules.playerMaySurrender()) {
0451                     // If surrender is possible, we cannot do worse than -0.5.
0452                     // So if at the end of the exercise we would have a value
0453                     // for this combination of less than -0.5, we simply
0454                     // surrender and max out at -0.5.
0455 
0456                     eVal = std::max<bjgb::Types::Double>(eVal, -0.5);
0457                 }
0458 
0459                 expectedValue += pijk * eVal;
0460 
0461             } // end for k
0462         } // end for j
0463     } // end for i
0464 
0465     return expectedValue;
0466 }
0467 
0468 bool PlayerTableUtil::isSamePlayerRow(const PlayerTable& pta, int hia, const PlayerTable& ptb, int hib)
0469 {
0470     assert(0 <= hia);
0471     assert(hia < bjgb::State::k_NUM_STATES);
0472     assert(0 <= hib);
0473     assert(hib < bjgb::State::k_NUM_STATES);
0474 
0475     for (int i = 1; i <= 10; ++i) {
0476         if (pta.exp(hia, i) != ptb.exp(hib, i)) {
0477             std::cout << "[FALSE: i = " << i << "]" << std::flush;
0478 
0479             return false; // RETURN
0480         }
0481     }
0482 
0483     return true;
0484 }
0485 
0486 bjgb::Types::Double PlayerTableUtil::mx(int hi, int cd, const PlayerTable& t, const PlayerTable& q)
0487 {
0488     assert(0 <= hi);
0489     assert(hi < bjgb::State::k_NUM_STATES);
0490     assert(1 <= cd);
0491     assert(cd <= 10);
0492 
0493     assert((bjgb::State::e_HOV == hi) != bjgb::Types::isValid(t.exp(hi, cd)));
0494     // either it is OVER in which case the entry is invalid or vice versa
0495     assert(bjgb::Types::isValid(q.exp(hi, cd)));
0496 
0497     return bjgb::State::e_HOV == hi ? q.exp(hi, cd) : std::max<bjgb::Types::Double>(t.exp(hi, cd), q.exp(hi, cd));
0498 }
0499 
0500 bjgb::Types::Double
0501 PlayerTableUtil::mx3(int hi, int cd, const PlayerTable& x, const PlayerTable& y, const PlayerTable& z)
0502 {
0503     assert(0 <= hi);
0504     assert(hi < bjgb::State::k_NUM_STATES);
0505     assert(1 <= cd);
0506     assert(cd <= 10);
0507     assert(bjgb::Types::isValid(x.exp(hi, cd)));
0508     assert(bjgb::Types::isValid(y.exp(hi, cd)));
0509     assert(bjgb::Types::isValid(z.exp(hi, cd)));
0510 
0511     const bjgb::Types::Double temp = std::max<bjgb::Types::Double>(x.exp(hi, cd), y.exp(hi, cd));
0512 
0513     return std::max<bjgb::Types::Double>(temp, z.exp(hi, cd));
0514 }
0515 
0516 void PlayerTableUtil::populatePlayerTable(
0517     PlayerTable *pt, const PlayerTable& pxt, const PlayerTable& pht, const PlayerTable& pst, const bjgb::Rules& rules)
0518 {
0519     // TBD this doc is not clear
0520     // The player table assumes that these are the first two cards (TBD
0521     // meaning what??).  Copy the maximum from the Splits, Hits, and Stands
0522     // tables.  Then transfer the split values.  This table alone is sufficient
0523     // to determine the odds of the game but we will still need separate
0524     // functions for strategy.
0525     //
0526     // Note that if the dealer peeks for BJ, we need to separate out the case
0527     // where the dealer gets blackjack and the adjusted shoe where he or she
0528     // doesn't.
0529 
0530     assert(pt);
0531 
0532     // Just copy the split values.
0533 
0534     for (int i = 1; i <= 10; ++i) {
0535         copyPlayerRow(pt, bjgb::State::pair(i), pxt, bjgb::State::pair(i));
0536     }
0537 
0538     // hard counts
0539 
0540     for (int i = 4; i <= 20; ++i) {
0541         copyPlayerRow(pt, bjgb::State::hard(i), pst, bjgb::State::hard(i));
0542         // copy the hard stand values
0543 
0544         for (int j = 1; j <= 10; ++j) {
0545             pt->exp(bjgb::State::hard(i), j) =
0546                 std::max<bjgb::Types::Double>(pt->exp(bjgb::State::hard(i), j), pht.exp(bjgb::State::hard(i), j));
0547 
0548             if (rules.playerMayDoubleOnTheseTwoCards(i, false)) {
0549                 std::cout << "[D: HARD i=" << i << ", j=" << j << "]\n";
0550                 pt->exp(bjgb::State::hard(i), j) =
0551                     std::max<bjgb::Types::Double>(pt->exp(bjgb::State::hard(i), j), pxt.exp(bjgb::State::hard(i), j));
0552             }
0553         }
0554     }
0555 
0556     // soft counts
0557 
0558     for (int i = 2; i <= 10; ++i) {
0559         copyPlayerRow(pt, bjgb::State::soft(i), pst, bjgb::State::soft(i));
0560         // copy the soft stand values
0561 
0562         for (int j = 1; j <= 10; ++j) {
0563             pt->exp(bjgb::State::soft(i), j) =
0564                 std::max<bjgb::Types::Double>(pt->exp(bjgb::State::soft(i), j), pht.exp(bjgb::State::soft(i), j));
0565 
0566             if (rules.playerMayDoubleOnTheseTwoCards(i, true)) {
0567                 std::cout << "[D: SOFT i=" << i << ", j=" << j << "]\n";
0568                 pt->exp(bjgb::State::soft(i), j) =
0569                     std::max<bjgb::Types::Double>(pt->exp(bjgb::State::soft(i), j), pxt.exp(bjgb::State::soft(i), j));
0570             }
0571         }
0572     }
0573 
0574     // blackjack
0575 
0576     copyPlayerRow(pt, bjgb::State::e_SBJ, pst, bjgb::State::e_SBJ);
0577     // copy the BJ values
0578 
0579     for (int j = 1; j <= 10; ++j) {
0580         pt->exp(bjgb::State::e_SBJ, j) =
0581             std::max<bjgb::Types::Double>(pt->exp(bjgb::State::e_SBJ, j), pht.exp(bjgb::State::e_SBJ, j));
0582 
0583         if (rules.playerMayDoubleOnTheseTwoCards(11, true)) {
0584             std::cout << "[D: BJ j=" << j << "]\n";
0585             pt->exp(bjgb::State::e_SBJ, j) =
0586                 std::max<bjgb::Types::Double>(pt->exp(bjgb::State::e_SBJ, j), pxt.exp(bjgb::State::e_SBJ, j));
0587         }
0588     }
0589 }
0590 
0591 void PlayerTableUtil::populateP1tab(PlayerTable *p1,
0592                                     const PlayerTable& ps,
0593                                     const bjgb::Shoe& shoe,
0594                                     const bjgb::Rules& rules)
0595 {
0596     assert(p1);
0597 
0598 // 53 pair(10)
0599 // 52 pair( 9)
0600 // 51 pair( 8)
0601 // 50 pair( 7)
0602 // 49 pair( 6)
0603 // 48 pair( 5)
0604 // 47 pair( 4)
0605 // 46 pair( 3)
0606 // 45 pair( 2)
0607 // 44 pair( 1)
0608 #if 0
0609     for (int j = 10; j >= 1; --j) {
0610         for (int i = 1; i <= 10; ++i) {
0611             p->exp(bjgb::State::pair(j), i) =
0612                                              eStand(q, i, j == 1 ? 12 : 2 * j);
0613 
0614             assert(p->exp(bjgb::State::pair(j), i) ==
0615                                  j >= 6 ? p->exp(bjgb::State::hard(2 * j), i)
0616                                         : p->exp(bjgb::State::hard(   16), i));
0617         }
0618     }
0619 #endif
0620 
0621     for (int j = 10; j >= 1; --j) { // card value for each split hand
0622         for (int i = 1; i <= 10; ++i) {
0623             p1->exp(bjgb::State::pair(j), i) = eHit1(ps, i, 2 * j, j == 1, shoe);
0624         }
0625     }
0626     // Checked below.
0627 
0628     // ---------
0629     // 43 e_HOV  // cannot hit a hand that is OVer
0630     // N.A.
0631 
0632     // 42 hard(21)
0633     // 41 hard(20)
0634     // 40 hard(19)
0635     // 39 hard(18)
0636     // 38 hard(17)
0637     // 37 hard(16)
0638     // 36 hard(15)
0639     // 35 hard(14)
0640     // 34 hard(13)
0641     // 33 hard(12)
0642     // 32 hard(11)
0643     // 31 hard(10)
0644     // 30 hard( 9)
0645     // 29 hard( 8)
0646     // 28 hard( 7)
0647     // 27 hard( 6)
0648     // 26 hard( 5)
0649     // 25 hard( 4)
0650     // 24 hard( 3)  // this has to be a single 3 after a split
0651     // 23 hard( 2)  // this has to be a single 2 after a split
0652 
0653     for (int j = 21; j >= 2; --j) {
0654         for (int i = 1; i <= 10; ++i) {
0655             p1->exp(bjgb::State::hard(j), i) = eHit1(ps, i, j, false, shoe);
0656         }
0657     }
0658 
0659     // --------
0660     // 22 unus(10)
0661     // 21 unus( 9)
0662     // 20 unus( 8)
0663     // 19 unus( 7)
0664     // 18 unus( 6)
0665     // 17 unus( 5)
0666     // 16 unus( 4)
0667     // 15 unus( 3)
0668     // 14 unus( 2)
0669     // 13 unus( 1)  // this is the first card of two and it is an Ace.
0670 
0671     for (int j = 10; j >= 1; --j) {
0672         for (int i = 1; i <= 10; ++i) {
0673             p1->exp(bjgb::State::unus(j), i) = eHit1(ps, i, j, 1 == j, shoe);
0674         }
0675 
0676         std::cout << "[Z j = " << j << "]" << std::flush;
0677 
0678         assert(isSamePlayerRow(*p1, bjgb::State::unus(j), *p1, 1 == j ? bjgb::State::unus(j) : bjgb::State::hard(j)));
0679         // check 1 case below
0680     }
0681 
0682     // 12 e_HZR  // cannot hit one card only on no cards
0683     // N.A.
0684 
0685     // --------
0686     // 11 e_SBJ  // so treat this as an S11  (STUPID IS AS STUPID DOES)
0687 
0688     for (int i = 1; i <= 10; ++i) {
0689         p1->exp(bjgb::State::e_SBJ, i) = eHit1(ps, i, 11, true, shoe);
0690     }
0691 
0692     // 10 soft(11)
0693     //  9 soft(10)
0694     //  8 soft( 9)
0695     //  7 soft( 8)
0696     //  6 soft( 7)
0697     //  5 soft( 6)
0698     //  4 soft( 5)
0699     //  3 soft( 4)
0700     //  2 soft( 3)
0701     //  1 soft( 2)
0702     //  0 soft( 1)  // this is after a split Ace, which you *must* hit, no BJ
0703 
0704     for (int j = 11; j >= 1; --j) {
0705         for (int i = 1; i <= 10; ++i) {
0706             p1->exp(bjgb::State::soft(j), i) = eHit1(ps, i, j, true, shoe);
0707         }
0708     }
0709 
0710     assert(isSamePlayerRow(*p1, bjgb::State::e_SBJ, *p1, bjgb::State::soft(11)));
0711 
0712     for (int j = 10; j >= 2; --j) { // card this is split (TBD meaning??)
0713         assert(isSamePlayerRow(*p1, bjgb::State::pair(j), *p1, bjgb::State::hard(2 * j)));
0714     }
0715 
0716     assert(isSamePlayerRow(*p1, bjgb::State::pair(1), *p1, bjgb::State::soft(2)));
0717 
0718     assert(isSamePlayerRow(*p1, bjgb::State::unus(1), *p1, bjgb::State::soft(1)));
0719 }
0720 
0721 void PlayerTableUtil::populatePdtab(PlayerTable *pd, const PlayerTable& p1)
0722 {
0723     assert(pd);
0724     assert(bjgb::Types::isValid(p1.exp(bjgb::State::hard(20), 1)));
0725     assert(bjgb::Types::isValid(p1.exp(bjgb::State::hard(4), 9)));
0726     assert(bjgb::Types::isValid(p1.exp(bjgb::State::hard(11), 2)));
0727     assert(bjgb::Types::isValid(p1.exp(bjgb::State::hard(2), 10)));
0728 
0729     // 53 pair(10)
0730     // 52 pair( 9)
0731     // 51 pair( 8)
0732     // 50 pair( 7)
0733     // 49 pair( 6)
0734     // 48 pair( 5)
0735     // 47 pair( 4)
0736     // 46 pair( 3)
0737     // 45 pair( 2)
0738     // 44 pair( 1)
0739     // N.A.
0740 
0741     // ---------
0742     // 43 e_HOV
0743     // N.A.
0744 
0745     // 42 hard(21) // 3+ cards, not appropriate for a double
0746     // N.A.
0747 
0748     // 41 hard(20)
0749     // 40 hard(19)
0750     // 39 hard(18)
0751     // 38 hard(17)
0752     // 37 hard(16)
0753     // 36 hard(15)
0754     // 35 hard(14)
0755     // 34 hard(13)
0756     // 33 hard(12)
0757     // 32 hard(11)
0758     // 31 hard(10)
0759     // 30 hard( 9)
0760     // 29 hard( 8)
0761     // 28 hard( 7)
0762     // 27 hard( 6)
0763     // 26 hard( 5)
0764     // 25 hard( 4)
0765 
0766     for (int j = 20; j >= 4; --j) {
0767         std::cout << "j=" << j << std::flush;
0768         for (int i = 1; i <= 10; ++i) {
0769             pd->exp(bjgb::State::hard(j), i) = eDouble(p1, i, j, false);
0770         }
0771     }
0772 
0773     // 24 hard(3)  // this has to be a single 3 after a split
0774     // 23 hard(2)  // this has to be a single 2 after a split
0775     // N.A.
0776 
0777     // --------
0778     // 22 unus(10)
0779     // 21 unus( 9)
0780     // 20 unus( 8)
0781     // 19 unus( 7)
0782     // 18 unus( 6)
0783     // 17 unus( 5)
0784     // 16 unus( 4)
0785     // 15 unus( 3)
0786     // 14 unus( 2)
0787     // 13 unus( 1)  // This is the first card of two and it is an Ace.
0788     // N.A.
0789 
0790     // 12 e_HZR  // cannot hit one card only on no cards
0791     // N.A.
0792 
0793     // --------
0794     // 11 e_SBJ  // so treat this as an S11  (STUPID IS AS STUPID DOES)
0795 
0796     for (int i = 1; i <= 10; ++i) {
0797         pd->exp(bjgb::State::e_SBJ, i) = eDouble(p1, i, 11, true);
0798     }
0799 
0800     // 10 soft(11)
0801     //  9 soft(10)
0802     //  8 soft( 9)
0803     //  7 soft( 8)
0804     //  6 soft( 7)
0805     //  5 soft( 6)
0806     //  4 soft( 5)
0807     //  3 soft( 4)
0808     //  2 soft( 3)
0809     //  1 soft( 2)
0810 
0811     for (int j = 11; j >= 2; --j) {
0812         std::cout << "J=" << j << std::flush;
0813         for (int i = 1; i <= 10; ++i) {
0814             pd->exp(bjgb::State::soft(j), i) = eDouble(p1, i, j, true);
0815         }
0816     }
0817 
0818     assert(isSamePlayerRow(*pd, bjgb::State::e_SBJ, *pd, bjgb::State::soft(11)));
0819 
0820     //  0 soft(1)  // this is after a split Ace, which you *must* hit, no BJ
0821     // N.A.
0822 }
0823 
0824 void PlayerTableUtil::populatePhtab(PlayerTable *ph,
0825                                     const PlayerTable& ps,
0826                                     const bjgb::Shoe& shoe,
0827                                     const bjgb::Rules& rules)
0828 {
0829     assert(ph);
0830 
0831     // 53 pair(10)
0832     // 52 pair( 9)
0833     // 51 pair( 8)
0834     // 50 pair( 7)
0835     // 49 pair( 6)
0836     // 48 pair( 5)
0837     // 47 pair( 4)
0838     // 46 pair( 3)
0839     // 45 pair( 2)
0840     // 44 pair( 1)
0841     // N.A.
0842 
0843     // ---------
0844     // 43 e_HOV
0845     // N.A.
0846 
0847     // 42 hard(21)
0848     // 41 hard(20)
0849     // 40 hard(19)
0850     // 39 hard(18)
0851     // 38 hard(17)
0852     // 37 hard(16)
0853     // 36 hard(15)
0854     // 35 hard(14)
0855     // 34 hard(13)
0856     // 33 hard(12)
0857     // 32 hard(11)
0858 
0859     for (int j = 21; j >= 11; --j) {
0860         for (int i = 1; i <= 10; ++i) {
0861             ph->exp(bjgb::State::hard(j), i) = eHitN(*ph, ps, i, j, false, shoe);
0862         }
0863     }
0864 
0865     // 10 soft(11)
0866     //  9 soft(10)
0867     //  8 soft( 9)
0868     //  7 soft( 8)
0869     //  6 soft( 7)
0870     //  5 soft( 6)
0871     //  4 soft( 5)
0872     //  3 soft( 4)
0873     //  2 soft( 3)
0874     //  1 soft( 2)
0875     //  0 soft( 1)  // this is after a split Ace, which you *must* hit, no BJ
0876 
0877     for (int j = 11; j >= 1; --j) {
0878         for (int i = 1; i <= 10; ++i) {
0879             ph->exp(bjgb::State::soft(j), i) = eHitN(*ph, ps, i, j, true, shoe);
0880         }
0881     }
0882 
0883     // 31 hard(10)
0884     // 30 hard( 9)
0885     // 29 hard( 8)
0886     // 28 hard( 7)
0887     // 27 hard( 6)
0888     // 26 hard( 5)
0889     // 25 hard( 4)
0890     // 24 hard( 3)  // this has to be a single 3 after a split
0891     // 23 hard( 2)  // this has to be a single 2 after a split
0892 
0893     for (int j = 10; j >= 2; --j) {
0894         for (int i = 1; i <= 10; ++i) {
0895             ph->exp(bjgb::State::hard(j), i) = eHitN(*ph, ps, i, j, false, shoe);
0896         }
0897     }
0898 
0899     // --------
0900     // 22 unus(10)
0901     // 21 unus( 9)
0902     // 20 unus( 8)
0903     // 19 unus( 7)
0904     // 18 unus( 6)
0905     // 17 unus( 5)
0906     // 16 unus( 4)
0907     // 15 unus( 3)
0908     // 14 unus( 2)
0909     // 13 unus( 1)  // This is the first card of two and it is an Ace.
0910 
0911     for (int j = 10; j >= 1; --j) {
0912         for (int i = 1; i <= 10; ++i) {
0913             ph->exp(bjgb::State::unus(j), i) = eHitN(*ph, ps, i, j, 1 == j, shoe);
0914         }
0915 
0916         assert(isSamePlayerRow(*ph, bjgb::State::unus(j), *ph, 1 == j ? bjgb::State::soft(j) : bjgb::State::hard(j)));
0917     }
0918 
0919     // 12 e_HZR  // cannot hit one card only on no cards
0920     // N.A.
0921 
0922     // --------
0923     // 11 e_SBJ  // so treat this as an S11  (STUPID IS AS STUPID DOES)
0924 
0925     for (int i = 1; i <= 10; ++i) {
0926         ph->exp(bjgb::State::e_SBJ, i) = eHitN(*ph, ps, i, 11, true, shoe);
0927     }
0928 
0929     assert(isSamePlayerRow(*ph, bjgb::State::e_SBJ, *ph, bjgb::State::soft(11)));
0930 
0931     // 53 pair(10)
0932     // 52 pair( 9)
0933     // 51 pair( 8)
0934     // 50 pair( 7)
0935     // 49 pair( 6)
0936     // 48 pair( 5)
0937     // 47 pair( 4)
0938     // 46 pair( 3)
0939     // 45 pair( 2)
0940     // 44 pair( 1)
0941 
0942     for (int j = 10; j >= 1; --j) { // card value for each split hand
0943         for (int i = 1; i <= 10; ++i) {
0944             ph->exp(bjgb::State::pair(j), i) = eHitN(*ph, ps, i, 2 * j, 1 == j, shoe);
0945         }
0946     }
0947 
0948     for (int j = 10; j >= 2; --j) { // card this is split (TBD meaning??)
0949         assert(isSamePlayerRow(*ph, bjgb::State::pair(j), *ph, bjgb::State::hard(2 * j)));
0950     }
0951 
0952     assert(isSamePlayerRow(*ph, bjgb::State::pair(1), *ph, bjgb::State::soft(2)));
0953 }
0954 
0955 void PlayerTableUtil::populatePstab(PlayerTable *ps,
0956                                     const DealerTable& dt,
0957                                     const bjgb::Shoe& shoe,
0958                                     const bjgb::Rules& rules)
0959 {
0960     assert(ps);
0961 
0962     // 53 pair(10)
0963     // 52 pair( 9)
0964     // 51 pair( 8)
0965     // 50 pair( 7)
0966     // 49 pair( 6)
0967     // 48 pair( 5)
0968     // 47 pair( 4)
0969     // 46 pair( 3)
0970     // 45 pair( 2)
0971     // 44 pair( 1)
0972 
0973     for (int j = 10; j >= 1; --j) {
0974         for (int i = 1; i <= 10; ++i) {
0975             ps->exp(bjgb::State::pair(j), i) = eStand(dt, i, 1 == j ? 12 : 2 * j);
0976 
0977             assert(ps->exp(bjgb::State::pair(j), i) == j >= 6 ? ps->exp(bjgb::State::hard(2 * j), i)
0978                                                               : ps->exp(bjgb::State::hard(16), i));
0979         }
0980     }
0981 
0982     // ---------
0983     // 43 e_HOV
0984 
0985     ps->setRow(bjgb::State::e_HOV, -1.0); // set all entries to simple loss
0986 
0987     // 42 hard(21)
0988     // 41 hard(20)
0989     // 40 hard(19)
0990     // 39 hard(18)
0991     // 38 hard(17)
0992     // 37 hard(16)
0993     // 36 hard(15)
0994     // 35 hard(14)
0995     // 34 hard(13)
0996     // 33 hard(12)
0997     // 32 hard(11)
0998     // 31 hard(10)
0999     // 30 hard( 9)
1000     // 29 hard( 8)
1001     // 28 hard( 7)
1002     // 27 hard( 6)
1003     // 26 hard( 5)
1004     // 25 hard( 4)
1005 
1006     for (int j = 21; j >= 4; --j) {
1007         for (int i = 1; i <= 10; ++i) {
1008             ps->exp(bjgb::State::hard(j), i) = eStand(dt, i, j);
1009         }
1010     }
1011 
1012     // 24 hard(3)  // this has to be a 3 card after a split
1013     // 23 hard(2)  // this has to be a 2 card after a split
1014     // N.A.
1015 
1016     // --------
1017     // 22 unus(10)
1018     // 21 unus( 9)
1019     // 20 unus( 8)
1020     // 19 unus( 7)
1021     // 18 unus( 6)
1022     // 17 unus( 5)
1023     // 16 unus( 4)
1024     // 15 unus( 3)
1025     // 14 unus( 2)
1026     // 13 unus( 1)  // This is the first card of two and it is an Ace.
1027     // N.A.
1028 
1029     // 12 e_HZR  // cannot stand on no cards
1030 
1031     // --------
1032     // 11 e_SBJ
1033 
1034     ps->setRow(bjgb::State::e_SBJ, rules.playerBlackjackPayout());
1035     // set all entries blackjack
1036 
1037     ps->exp(bjgb::State::e_SBJ, 1) -= shoe.prob(10) * rules.playerBlackjackPayout();
1038     ps->exp(bjgb::State::e_SBJ, 10) -= shoe.prob(1) * rules.playerBlackjackPayout();
1039 
1040     // 10 soft(11)
1041     //  9 soft(10)
1042     //  8 soft( 9)
1043     //  7 soft( 8)
1044     //  6 soft( 7)
1045     //  5 soft( 6)
1046     //  4 soft( 5)
1047     //  3 soft( 4)
1048     //  2 soft( 3)
1049     //  1 soft( 2)
1050 
1051     for (int j = 11; j >= 2; --j) {
1052         for (int i = 1; i <= 10; ++i) {
1053             ps->exp(bjgb::State::soft(j), i) = eStand(dt, i, j + 10);
1054         }
1055     }
1056 
1057     //  0 soft(1)  // this is after a split Ace, which you *must* hit, no BJ
1058     // N.A.
1059 }
1060 
1061 void PlayerTableUtil::populatePxtab(PlayerTable *pxt,
1062                                     const PlayerTable& pdt,
1063                                     const PlayerTable& pht,
1064                                     const PlayerTable& p1t,
1065                                     const PlayerTable& pst,
1066                                     const bjgb::Shoe& shoe,
1067                                     const bjgb::Rules& rules)
1068 {
1069     assert(pxt);
1070 
1071     // Copy over the values from the double table.
1072 
1073     for (int i = 4; i <= 20; ++i) { // there is no hard 2-card 21
1074         copyPlayerRow(pxt, bjgb::State::hard(i), pdt, bjgb::State::hard(i));
1075     }
1076 
1077     for (int i = 2; i <= 11; ++i) { // A+A, A+2, ... A+T (after a split Ace)
1078         copyPlayerRow(pxt, bjgb::State::soft(i), pdt, bjgb::State::soft(i));
1079     }
1080 
1081     copyPlayerRow(pxt, bjgb::State::e_SBJ, pdt, bjgb::State::e_SBJ);
1082     // This is a natural A + 10.
1083 
1084     for (int i = 2; i <= 20; i += 2) {
1085         int splitCard = i / 2;
1086         int maxSplits = rules.playerMaxNumHands() - 1; // typically 3
1087 
1088         for (int j = 1; j <= 10; ++j) {
1089             pxt->exp(bjgb::State::pair(splitCard), j) = eSplit(pdt, pht, p1t, pst, j, i, maxSplits, shoe, rules);
1090         }
1091     }
1092 }
1093 
1094 } // namespace bjgc