Slowhand-VI

TUT: blackjack.fos

Jan 19th, 2016
141
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 30.07 KB | None
  1. /**<
  2.  *  Main logic for the Blackjack module.
  3.  */
  4.  
  5.  
  6. #include "blackjack_h.fos"
  7. #include "blackjack_shoe.fos"
  8. #include "ITEMPID.H"
  9. #include "_math.fos"
  10.  
  11.  
  12. class CBlackjack
  13. {
  14.     private uint playerId;
  15.     private uint dealerId;
  16.  
  17.     private int playerSkill;
  18.     private int dealerSkill;
  19.     private int skillDifference;
  20.  
  21.     private CShoe shoe;
  22.     private BlackjackProgress progress;
  23.     private bool doubleDown;
  24.     private bool insurance;
  25.  
  26.     private int sidebetType;
  27.     private int sidebetValue;
  28.     private int betValue;
  29.  
  30.     private bool showDealerCards;
  31.  
  32.     private string lastAction;
  33.     private string result;
  34.     private string sidebetResult;
  35.  
  36.     private array<CCard@> playerHand;
  37.     private array<CCard@> dealerHand;
  38.  
  39.     /**< Getters */
  40.     uint GetPlayerId()
  41.     {
  42.         return playerId;
  43.     }
  44.     uint GetDealerId()
  45.     {
  46.         return dealerId;
  47.     }
  48.     string GetLastAction()
  49.     {
  50.         return lastAction;
  51.     }
  52.     string GetPlayerHand()
  53.     {
  54.         string hand;
  55.         if (playerHand.length() > 0)
  56.         {
  57.             hand = playerHand[0].GetCardNotation();
  58.         }
  59.         for (uint i = 1; i < playerHand.length(); i++)
  60.         {
  61.             hand += ", " + playerHand[i].GetCardNotation();
  62.         }
  63.         if (IsPlayerBlackjack())
  64.         {
  65.             hand += " = Blackjack.";
  66.         }
  67.         else
  68.         {
  69.             hand += " = " + GetHandSoftValue(playerHand) + ".";
  70.         }
  71.         return hand;
  72.     }
  73.     string GetDealerHand()
  74.     {
  75.         string hand;
  76.         if (showDealerCards)
  77.         {
  78.             if (dealerHand.length() > 0)
  79.             {
  80.                 hand += dealerHand[0].GetCardNotation();
  81.             }
  82.             for (uint i = 1; i < dealerHand.length(); i++)
  83.             {
  84.                 hand += ", " + dealerHand[i].GetCardNotation();
  85.             }
  86.             if (IsDealerBlackjack())
  87.             {
  88.                 hand += " = Blackjack. ";
  89.             }
  90.             else
  91.             {
  92.                 hand += " = " + GetHandSoftValue(dealerHand) + ". ";
  93.             }
  94.         }
  95.         else
  96.         {
  97.             if (dealerHand.length() > 0)
  98.             {
  99.                 hand += dealerHand[0].GetCardNotation() + ", ?.";
  100.             }
  101.         }
  102.         return hand;
  103.     }
  104.     string GetResult()
  105.     {
  106.         return result;
  107.     }
  108.  
  109.     /**< Constructor - Well, only a simple function to call after declaring variable. */
  110.     CBlackjack(uint playerId, uint dealerId, int decksInShoe)
  111.     {
  112.         this.playerId = playerId;
  113.         this.dealerId = dealerId;
  114.         shoe = CShoe(decksInShoe);
  115.         Init();
  116.     }
  117.  
  118.     /**< Initialize variables for a clean session, generate a new shoe and shuffle it. */
  119.     void Init()
  120.     {
  121.         progress = Init;
  122.         shoe.Shuffle();
  123.         SetGamblingSkills();
  124.         ResetVariables();
  125.         progress = Bet;
  126.         //  Insert test cases here.
  127.         //InsertTestCasesForPlayerBlackjack();
  128.         //InsertTestCasesForDoubleDown();
  129.         //InsertTestCasesForLuckyLadies();
  130.         //InsertTestCasesForPerfectPair();
  131.         //InsertTestCasesForRoyalMatch();
  132.     }
  133.     void SetGamblingSkills()
  134.     {
  135.         Critter@ dealer = GetCritter(dealerId);
  136.         Critter@ player = GetCritter(playerId);
  137.         if (valid(player) && valid(dealer))
  138.         {
  139.             playerSkill = player.Skill[SK_GAMBLING];
  140.             dealerSkill = dealer.Skill[SK_GAMBLING];
  141.             skillDifference = playerSkill - dealerSkill;
  142.         }
  143.         else
  144.         {
  145.             playerSkill = 0;
  146.             dealerSkill = 0;
  147.             skillDifference = 0;
  148.         }
  149.     }
  150.     bool IsSeeShoeSize()
  151.     {
  152.         if (playerSkill >= BLACKJACK_SKILL_TO_SEE_SHOE_SIZE)
  153.             return true;
  154.         else
  155.             return false;
  156.     }
  157.     void ResetVariables()
  158.     {
  159.         sidebetType = BLACKJACK_SIDE_NONE;
  160.         sidebetValue = 0;
  161.         playerHand = array<CCard@>(0);
  162.         dealerHand = array<CCard@>(0);
  163.         result = "Round is not finished yet!";
  164.         sidebetResult = "No side bet set.";
  165.         doubleDown = false;
  166.         insurance = false;
  167.         if (IsSeeDealerCards())
  168.         {
  169.             Log("Show dealers card.");
  170.             showDealerCards = true;
  171.         }
  172.         else
  173.         {
  174.             showDealerCards = false;
  175.         }
  176.         if (IsShuffleNeeded())
  177.         {
  178.             shoe.Shuffle();
  179.             if (IsSeeReshuffling())
  180.             {
  181.                 lastAction = "Dealer reshuffles the shoe. A fresh round starts!";
  182.             }
  183.         }
  184.         if (progress == Init)
  185.         {
  186.             if (IsSeeShoeSize())
  187.             {
  188.                 lastAction += "Shoe size is " + shoe.GetNumberOfDecks() + " decks. First round!";
  189.             }
  190.             else
  191.             {
  192.                 lastAction = "First round! ";
  193.             }
  194.         }
  195.         else
  196.         {
  197.             lastAction = "A fresh round! ";
  198.         }
  199.         progress = Bet;
  200.     }
  201.  
  202.     /**< Gambling skill related stuff. */
  203.     bool IsSeeDealerCards()
  204.     {
  205.         int chance = CLAMP(skillDifference - BLACKJACK_SKILL_DIFF_TO_SEE_HOLE_CARD, 0, 95);
  206.         if (chance >= Random(1, 100))
  207.         {
  208.             return true;
  209.         }
  210.         else
  211.         {
  212.             return false;
  213.         }
  214.     }
  215.     bool IsShuffleNeeded()
  216.     {
  217.         int cardsLeftInPercent = (shoe.GetTotalCards() - shoe.GetCurrentCardIndex()) * 100 / shoe.GetTotalCards();
  218.         if (skillDifference <= 0)
  219.         {
  220.             if (cardsLeftInPercent <= BLACKJACK_SHUFFLE_THRESHOLD_MAX)
  221.             {
  222.                 return true;
  223.             }
  224.             else
  225.             {
  226.                 return false;
  227.             }
  228.         }
  229.         else
  230.         {
  231.             float min = BLACKJACK_SHUFFLE_THRESHOLD_MIN;
  232.             float max = BLACKJACK_SHUFFLE_THRESHOLD_MAX;
  233.             float threshold = BLACKJACK_SHUFFLE_SKILL_THRESHOLD;
  234.             float factor = CLAMP(threshold - skillDifference, 0, threshold) / threshold;
  235.             Log("factor = " + factor);
  236.             int shuffleThreshold = min + ((max - min) * factor);
  237.             if (cardsLeftInPercent <= shuffleThreshold)
  238.             {
  239.                 return true;
  240.             }
  241.             else
  242.             {
  243.                 Log("Cards: Left = " + cardsLeftInPercent + "%, threshold = " + shuffleThreshold + "%. ");
  244.                 return false;
  245.             }
  246.         }
  247.     }
  248.     bool IsSeeReshuffling()
  249.     {
  250.         if (playerSkill >= BLACKJACK_SKILL_TO_SEE_SHUFFLING)
  251.         {
  252.             return true;
  253.         }
  254.         else
  255.         {
  256.             return false;
  257.         }
  258.     }
  259.     /**<
  260.      *  Side bet related.
  261.      */
  262.     bool IsSidebetAvailable()
  263.     {
  264.         if (progress == Bet)
  265.         {
  266.             return true;
  267.         }
  268.         else
  269.         {
  270.             return false;
  271.         }
  272.     }
  273.  
  274.     void SetSidebetType(int type)
  275.     {
  276.         switch (type)
  277.         {
  278.             case BLACKJACK_SIDE_LUCKY_LADIES:
  279.             case BLACKJACK_SIDE_PERFECT_PAIR:
  280.             case BLAKCJACK_SIDE_ROYAL_MATCH:
  281.                 sidebetType = type;
  282.                 break;
  283.             default:
  284.                 sidebetType = BLACKJACK_SIDE_NONE;
  285.         }
  286.     }
  287.  
  288.     string GetSidebetType()
  289.     {
  290.         switch (sidebetType)
  291.         {
  292.             case BLACKJACK_SIDE_LUCKY_LADIES:
  293.                 return "Lucky Ladies";
  294.             case BLACKJACK_SIDE_PERFECT_PAIR:
  295.                 return "Perfect Pair";
  296.             case BLAKCJACK_SIDE_ROYAL_MATCH:
  297.                 return "Royal Match";
  298.         }
  299.         return "no side bet";
  300.     }
  301.  
  302.     void SetSidebetValue(int value)
  303.     {
  304.         sidebetValue = value;
  305.         ProgressToSidebetDone();
  306.         lastAction = "Set " + GetSidebetType() + " side bet for " + sidebetValue + " caps. ";
  307.         sidebetResult = "Side bet set on " + GetSidebetType() + " for " + sidebetValue + " caps. ";
  308.     }
  309.  
  310.     void ProgressToSidebetDone()
  311.     {
  312.         progress = SidebetDone;
  313.     }
  314.  
  315.     string GetSidebetResult()
  316.     {
  317.         return sidebetResult;
  318.     }
  319.     /**<  */
  320.  
  321.     /**<
  322.      *  Bet related.
  323.      */
  324.     void SetBetValue(int value)
  325.     {
  326.         betValue = value;
  327.         ProgressToFirst();
  328.         lastAction = "You placed bet for " + value + " caps. ";
  329.     }
  330.     /**<  */
  331.  
  332.     /**<
  333.      *  Hit related.
  334.      */
  335.     bool IsHitAvailable()
  336.     {
  337.         if ((progress == First || progress == Rest)
  338.             && GetHandSoftValue(playerHand) < 21)
  339.         {
  340.             return true;
  341.         }
  342.         else
  343.         {
  344.             return false;
  345.         }
  346.     }
  347.     void Hit()
  348.     {
  349.         giveCardToPlayer();
  350.         if (IsPlayerBust())
  351.         {
  352.             lastAction += " and you busted. ";
  353.             ProgressToPlayerBust();
  354.         }
  355.         else if (DidPlayerReachBlackjackValue())
  356.         {
  357.             lastAction += " and you got 21! ";
  358.             ProgressToPlayerBlackjack();
  359.         }
  360.         else
  361.         {
  362.             lastAction += ". ";
  363.             ProgressToRest();
  364.         }
  365.     }
  366.  
  367.     /**<
  368.      *  Stand related.
  369.      */
  370.     bool IsStandAvailable()
  371.     {
  372.         //  player can always stand, except if bust, but then different mechanic is in effect anyways.
  373.         return !IsPlayerBust();
  374.     }
  375.     void Stand()
  376.     {
  377.         //  Basically do nothing, wait for dealer's turn (part of result)
  378.         lastAction = "You stand. ";
  379.         ProgressToDealersTurn();
  380.     }
  381.     bool IsEvenMoneyAvailable()
  382.     {
  383.         if (progress == First
  384.             && IsPlayerBlackjack()
  385.             && IsDealerFirstCardAce())
  386.             return true;
  387.         else
  388.             return false;
  389.     }
  390.     bool IsDealerFirstCardAce()
  391.     {
  392.         if (dealerHand.length() > 0)
  393.         {
  394.             if (dealerHand[0].Type() == CARD_TYPE_ACE)
  395.                 return true;
  396.         }
  397.         return false;
  398.     }
  399.     void EvenMoney()
  400.     {
  401.         int amountWon = betValue * 2;
  402.         result = "You chose even money on your Blackjack and won " + amountWon + " caps. ";
  403.         GivePlayerMoney(amountWon);
  404.         ProgressToResult();
  405.     }
  406.  
  407.     /**<
  408.      *  Double down related.
  409.      *  Double down is available anytime as long as the player is not busted or does not have 21 already.
  410.      *  The player will receive exactly one card after doubling the bet and finishes his turn.
  411.      */
  412.     bool IsDoubleDownAvailable()
  413.     {
  414.         if (GetHandSoftValue(playerHand) < 21
  415.             && (progress == First || progress == Rest)
  416.             && doubleDown == false
  417.             && IsPlayerHaveMoney(betValue))
  418.         {
  419.             return true;
  420.         }
  421.         else
  422.         {
  423.             return false;
  424.         }
  425.     }
  426.     void DoubleDown()
  427.     {
  428.         doubleDown = true;
  429.         lastAction = "You double down";
  430.         TakePlayerMoney(betValue);
  431.         betValue = betValue * 2;
  432.         giveCardToPlayer();
  433.         if (IsPlayerBust())
  434.         {
  435.             lastAction += " and bust. ";
  436.             ProgressToPlayerBust();
  437.         }
  438.         else
  439.         {
  440.             lastAction += ".";
  441.         }
  442.     }
  443.     bool IsPlayerHaveMoney(uint value)
  444.     {
  445.         Critter@ player = GetCritter(playerId);
  446.         if (valid(player) && player.CountItem(PID_BOTTLE_CAPS) >= value)
  447.             return true;
  448.         else
  449.             return false;
  450.     }
  451.     /**< Surrender related, available only at starting hand. (Early surrender, bc easier to implement and easier for player also.) */
  452.     bool IsSurrenderAvailable()
  453.     {
  454.         if (progress == First &&  !IsPlayerBlackjack())
  455.             return true;
  456.         else
  457.             return false;
  458.     }
  459.     void Surrender()
  460.     {
  461.         result = "You surrender and get half of your bet back.";
  462.         GivePlayerMoney(betValue / 2);
  463.         ProgressToResult();
  464.     }
  465.     /**< Insurance related - Only available when Dealer has an Ace revealed and only wins if host has a Blackjack. */
  466.     bool IsInsuranceAvailable()
  467.     {
  468.         if (dealerHand.length() > 0
  469.             && dealerHand[0].Type() == CARD_TYPE_ACE
  470.             && IsPlayerHaveMoney(betValue)
  471.             && !IsPlayerBlackjack()
  472.             && !IsPlayerBust()
  473.             && insurance == false)
  474.             return true;
  475.         else
  476.             return false;
  477.     }
  478.     void Insurance()
  479.     {
  480.         TakePlayerMoney(betValue);
  481.         lastAction = "You put an insurance bet versus dealer Blackjack. ";
  482.         insurance = true;
  483.     }
  484.     /**<
  485.      *  Game mechanic
  486.      */
  487.     void dealFirst()
  488.     {
  489.         CCard@ firstCard = shoe.TakeNextCard();
  490.         playerHand.insertLast(firstCard);
  491.         CCard@ secondCard = shoe.TakeNextCard();
  492.         playerHand.insertLast(secondCard);
  493.         CCard@ thirdCard = shoe.TakeNextCard();
  494.         dealerHand.insertLast(thirdCard);
  495.         CCard@ fourthCard = shoe.TakeNextCard();
  496.         dealerHand.insertLast(fourthCard);
  497.         lastAction = "You got a " + firstCard.GetCardNotation() + " and a " + secondCard.GetCardNotation()
  498.                     + ". The dealer got a " + thirdCard.GetCardNotation() + ". ";
  499.     }
  500.  
  501.     void giveCardToPlayer()
  502.     {
  503.         if (!shoe.IsEmpty())
  504.         {
  505.             CCard@ nextCard = shoe.TakeNextCard();
  506.             playerHand.insertLast(nextCard);
  507.             lastAction = "You got a " + nextCard.GetCardNotation() + " ";
  508.         }
  509.         else
  510.         {
  511.             Log("Blackjack error: shoe got empty and cards were to be taken. This may not happen.");
  512.         }
  513.     }
  514.  
  515.     void showDealersHoleCard()
  516.     {
  517.         lastAction = "Dealers hole card is a " + GetDealersHoleCard().GetCardNotation() + ". ";
  518.         showDealerCards = true;
  519.     }
  520.  
  521.     CCard@ GetDealersHoleCard()
  522.     {
  523.         return dealerHand[1];
  524.     }
  525.  
  526.     int GetHandSoftValue(array<CCard@> hand)
  527.     {
  528.         int nrOfAces = 0;
  529.         int total = 0;
  530.         for (uint i = 0; i < hand.length(); i++)
  531.         {
  532.             if (hand[i].Type() == CARD_TYPE_ACE)
  533.                 nrOfAces++;
  534.             total += hand[i].Value();
  535.         }
  536.         if (total <= 21)
  537.         {
  538.             return total;
  539.         }
  540.         else
  541.         {
  542.             for (int i = 0; i < nrOfAces; i++)
  543.             {
  544.                 total -= 10;
  545.                 if (total <= 21)
  546.                     return total;
  547.             }
  548.         }
  549.         return total;
  550.     }
  551.  
  552.     /**< Needed for the "Hit hard 17" rule, but only for the dealer. */
  553.     int GetDealerHandHardValue()
  554.     {
  555.         int nrOfAces = 0;
  556.         int total = 0;
  557.         for (uint i = 0; i < dealerHand.length(); i++)
  558.         {
  559.             if (dealerHand[i].Type() == CARD_TYPE_ACE)
  560.                 nrOfAces++;
  561.             total += dealerHand[i].Value();
  562.         }
  563.         total -= 10 * nrOfAces;
  564.         return total;
  565.     }
  566.  
  567.     bool IsPlayerBust()
  568.     {
  569.         if (GetHandSoftValue(playerHand) > 21)
  570.             return true;
  571.         else
  572.             return false;
  573.     }
  574.  
  575.     bool IsPlayerBlackjack()
  576.     {
  577.         if (GetHandSoftValue(playerHand) == 21
  578.             && playerHand.length() == 2)
  579.         {
  580.             return true;
  581.         }
  582.         else
  583.         {
  584.             return false;
  585.         }
  586.     }
  587.  
  588.     bool DidPlayerReachBlackjackValue()
  589.     {
  590.         if (GetHandSoftValue(playerHand) == 21)
  591.             return true;
  592.         else
  593.             return false;
  594.     }
  595.  
  596.     /**< Side bet result check */
  597.     void ProcessSidebet()
  598.     {
  599.         switch (sidebetType)
  600.         {
  601.             case BLACKJACK_SIDE_LUCKY_LADIES:
  602.                 ProcessSidebetLuckyLadies();
  603.                 break;
  604.             case BLACKJACK_SIDE_PERFECT_PAIR:
  605.                 ProcessSidebetPerfectPair();
  606.                 break;
  607.             case BLAKCJACK_SIDE_ROYAL_MATCH:
  608.                 ProcessSidebetRoyalMatch();
  609.                 break;
  610.             case BLACKJACK_SIDE_NONE:
  611.                 ProcessSidebetNone();
  612.         }
  613.     }
  614.     void ProcessSidebetLuckyLadies()
  615.     {
  616.         uint winAmount = 0;
  617.         if (IsPlayerHaveTwenty())
  618.         {
  619.             if (IsPlayerHaveQueenOfHearts())
  620.             {
  621.                 if (IsDealerBlackjack())
  622.                 {
  623.                     winAmount = sidebetValue * BLACKJACK_SIDE_FACTOR_LL_QOHP_BJ;
  624.                     sidebetResult = "You won " + winAmount + " on Lucky Ladies because you got Queen of hearts pair and dealer had Blackjack. ";
  625.                     GivePlayerMoney(winAmount);
  626.                 }
  627.                 else
  628.                 {
  629.                     winAmount = sidebetValue * BLACKJACK_SIDE_FACTOR_LL_QOHP;
  630.                     sidebetResult = "You won " + winAmount + " on Lucky Ladies because you got Queen of hearts pair. ";
  631.                     GivePlayerMoney(winAmount);
  632.                 }
  633.             }
  634.             else
  635.             {
  636.                 if (IsPlayerHaveSuit())
  637.                 {
  638.                     if (IsPlayerHavePair())
  639.                     {
  640.                         winAmount = sidebetValue * BLACKJACK_SIDE_FACTOR_LL_MATCHED;
  641.                         sidebetResult = "You won " + winAmount + " on Lucky Ladies because you got matched pair. ";
  642.                         GivePlayerMoney(winAmount);
  643.                     }
  644.                     else
  645.                     {
  646.                         winAmount = sidebetValue * BLACKJACK_SIDE_FACTOR_LL_SUITED;
  647.                         sidebetResult = "You won " + winAmount + " on Lucky Ladies because you got suited 20. ";
  648.                         GivePlayerMoney(winAmount);
  649.                     }
  650.                 }
  651.                 else
  652.                 {
  653.                     winAmount = sidebetValue * BLACKJACK_SIDE_FACTOR_LL_UNSUITED;
  654.                     sidebetResult = "You won " + winAmount + " on Lucky Ladies because you got unsuited 20. ";
  655.                     GivePlayerMoney(winAmount);
  656.                 }
  657.             }
  658.         }
  659.         else
  660.         {
  661.             sidebetResult = "Your side bet on Lucky Ladies failed. ";
  662.         }
  663.     }
  664.     void ProcessSidebetPerfectPair()
  665.     {
  666.         uint winAmount = 0;
  667.         if (IsPlayerHavePair())
  668.         {
  669.             if (IsPlayerHaveSuit())
  670.             {
  671.                 winAmount = sidebetValue * BLACKJACK_SIDE_FACTOR_PP_PERFECTPAIR;
  672.                 sidebetResult = "You won " + winAmount + " on Perfect Pair because you got a perfect pair. ";
  673.                 GivePlayerMoney(winAmount);
  674.             }
  675.             else
  676.             {
  677.                 if (IsPlayerHaveColor())
  678.                 {
  679.                     winAmount = sidebetValue * BLACKJACK_SIDE_FACTOR_PP_COLOREDPAIR;
  680.                     sidebetResult = "You won " + winAmount + " on Perfect Pair because you got a colored pair. ";
  681.                     GivePlayerMoney(winAmount);
  682.                 }
  683.                 else
  684.                 {
  685.                     winAmount = sidebetValue * BLACKJACK_SIDE_FACTOR_PP_MIXEDPAIR;
  686.                     sidebetResult = "You won " + winAmount + " on Perfect Pair because you got a mixed pair. ";
  687.                     GivePlayerMoney(winAmount);
  688.                 }
  689.             }
  690.         }
  691.         else
  692.         {
  693.             sidebetResult = "Your side bet on Perfect Pair failed. ";
  694.         }
  695.     }
  696.     void ProcessSidebetRoyalMatch()
  697.     {
  698.         uint winAmount = 0;
  699.         if (IsPlayerHaveSuit())
  700.         {
  701.             if (IsPlayerHaveRoyalPair())
  702.             {
  703.                 winAmount = sidebetValue * BALCKJACK_SIDE_FACTOR_RM_ROYAL_MATCH;
  704.                 sidebetResult = "You won " + winAmount + " on Royal Match because you got a King and Queen of the same suit. ";
  705.                 GivePlayerMoney(winAmount);
  706.             }
  707.             else
  708.             {
  709.                 winAmount = sidebetValue * BLACKJACK_SIDE_FACTOR_RM_SUITED;
  710.                 sidebetResult = "You won " + winAmount + " on Royal Match because you got a start hand with same suit. ";
  711.                 GivePlayerMoney(winAmount);
  712.             }
  713.         }
  714.         else
  715.         {
  716.             sidebetResult = "Your side bet on Royal Match failed. ";
  717.         }
  718.     }
  719.     void ProcessSidebetNone()
  720.     {
  721.         sidebetResult = "";
  722.     }
  723.     bool IsPlayerHaveTwenty()
  724.     {
  725.         if (playerHand.length() >= 2
  726.             && playerHand[0].Value() + playerHand[1].Value() == 20)
  727.             return true;
  728.         else
  729.             return false;
  730.     }
  731.     bool IsPlayerHaveQueenOfHearts()
  732.     {
  733.         if (playerHand.length() >= 2
  734.             && playerHand[0].Type() == CARD_TYPE_QUEEN && playerHand[0].Suit() == CARD_SUIT_HEARTS
  735.             && playerHand[1].Type() == CARD_TYPE_QUEEN && playerHand[1].Suit() == CARD_SUIT_HEARTS)
  736.             return true;
  737.         else
  738.             return false;
  739.     }
  740.     bool IsPlayerHaveSuit()
  741.     {
  742.         if (playerHand.length() >= 2
  743.             && playerHand[0].Suit() == playerHand[1].Suit())
  744.             return true;
  745.         else
  746.             return false;
  747.     }
  748.     bool IsPlayerHavePair()
  749.     {
  750.         if (playerHand.length() >= 2
  751.             && playerHand[0].Type() == playerHand[1].Type())
  752.             return true;
  753.         else
  754.             return false;
  755.     }
  756.     bool IsPlayerHaveColor()
  757.     {
  758.         if (playerHand.length() >= 2
  759.             && playerHand[0].Color() == playerHand[1].Color())
  760.             return true;
  761.         else
  762.             return false;
  763.     }
  764.     bool IsPlayerHaveRoyalPair()
  765.     {
  766.         if (playerHand.length() >= 2
  767.             && ( (playerHand[0].Type() == CARD_TYPE_KING && playerHand[1].Type() == CARD_TYPE_QUEEN)
  768.                  || (playerHand[0].Type() == CARD_TYPE_QUEEN && playerHand[1].Type() == CARD_TYPE_KING)))
  769.             return true;
  770.         else
  771.             return false;
  772.     }
  773.     /**<
  774.      *  Progress calls - Most of these are in separate function for readability.
  775.      */
  776.     void ProgressToFirst()
  777.     {
  778.         progress = First;
  779.         dealFirst();
  780.     }
  781.     void ProgressToPlayerBust()
  782.     {
  783.         ProcessSidebet();
  784.         progress = PlayerBust;
  785.     }
  786.     void ProgressToResult()
  787.     {
  788.         progress = Result;
  789.         ProcessSidebet();
  790.     }
  791.     void ProgressToPlayerBlackjack()
  792.     {
  793.         progress = PlayerBlackjack;
  794.     }
  795.     void ProgressToRest()
  796.     {
  797.         progress = Rest;
  798.     }
  799.     void ProgressToDealersTurn()
  800.     {
  801.         progress = DealersTurn;
  802.         showDealersHoleCard();
  803.         if (IsPlayerBlackjack())
  804.         {
  805.             ProgressToResult();
  806.         }
  807.         if (canDealerStand())
  808.         {
  809.             lastAction += "Dealer stands. ";
  810.             ProgressToResult();
  811.         }
  812.     }
  813.     bool IsDealerDone()
  814.     {
  815.         if (progress == DealersTurn
  816.             && !IsPlayerBlackjack())
  817.         {
  818.             return false;
  819.         }
  820.         else
  821.         {
  822.             return true;
  823.         }
  824.     }
  825.     bool canDealerStand()
  826.     {
  827.         if (GetHandSoftValue(dealerHand) >= 17
  828.             && GetHandSoftValue(dealerHand) <= 21)
  829.             return true;
  830.         else
  831.             return false;
  832.     }
  833.     bool isDealerBust()
  834.     {
  835.         if (GetHandSoftValue(dealerHand) > 21)
  836.             return true;
  837.         else
  838.             return false;
  839.     }
  840.     bool IsDealerBlackjack()
  841.     {
  842.         if (GetHandSoftValue(dealerHand) == 21
  843.             &&  dealerHand.length() == 2)
  844.             return true;
  845.         else
  846.             return false;
  847.     }
  848.     void DealerTakesCard()
  849.     {
  850.         if (!shoe.IsEmpty())
  851.         {
  852.             CCard@ nextCard = shoe.TakeNextCard();
  853.             dealerHand.insertLast(nextCard);
  854.             lastAction = "Dealer takes a " + nextCard.GetCardNotation() + ". ";
  855.             if (canDealerStand())
  856.             {
  857.                 lastAction = "Dealer takes a " + nextCard.GetCardNotation() + " and stands. ";
  858.                 ProgressToResult();
  859.             }
  860.             else if (isDealerBust())
  861.             {
  862.                 lastAction = "Dealer takes a " + nextCard.GetCardNotation() + " and is busted. ";
  863.                 ProgressToResult();
  864.             }
  865.         }
  866.         else
  867.         {
  868.             Log("Blackjack error: shoe got empty and cards were to be taken. This may not happen.");
  869.         }
  870.     }
  871.     void DealerFinishedTurn()
  872.     {
  873.         int amountWon = 0;
  874.         if (!IsPlayerBust())
  875.         {
  876.             if (isDealerBust())
  877.             {
  878.                 if (IsPlayerBlackjack())
  879.                 {
  880.                     amountWon = betValue * 2.5;
  881.                     result = "You won " + amountWon + " caps with Blackjack! ";
  882.                     GivePlayerMoney(amountWon);
  883.                 }
  884.                 else
  885.                 {
  886.                     amountWon = betValue * 2;
  887.                     result = "You won " + amountWon + " caps. ";
  888.                     GivePlayerMoney(amountWon);
  889.                 }
  890.             }
  891.             else
  892.             {
  893.                 if (IsDealerBlackjack())
  894.                 {
  895.                     if (IsPlayerBlackjack())
  896.                     {
  897.                         amountWon = betValue;
  898.                         result = "You both have Blackjack. It's a push. You get your bet back. ";
  899.                         GivePlayerMoney(amountWon);
  900.                     }
  901.                     else
  902.                     {
  903.                         result = "You lost, because dealer had Blackjack and you didn't. ";
  904.                     }
  905.                 }
  906.                 else
  907.                 {
  908.                     if (IsPlayerBlackjack())
  909.                     {
  910.                         amountWon = betValue * 2.5;
  911.                         result = "You won " + amountWon + " caps with Blackjack! ";
  912.                         GivePlayerMoney(amountWon);
  913.                     }
  914.                     else
  915.                     {
  916.                         if (GetHandSoftValue(playerHand) > GetHandSoftValue(dealerHand))
  917.                         {
  918.                             amountWon = betValue * 2;
  919.                             result = "You won " + amountWon + " caps. ";
  920.                             GivePlayerMoney(amountWon);
  921.                         }
  922.                         else
  923.                         {
  924.                             if (GetHandSoftValue(playerHand) == GetHandSoftValue(dealerHand))
  925.                             {
  926.                                 amountWon = betValue;
  927.                                 result = "It's a push. You get your bet back. ";
  928.                                 GivePlayerMoney(amountWon);
  929.                             }
  930.                             else
  931.                             {
  932.                                 result = "You lost. ";
  933.                             }
  934.                         }
  935.                     }
  936.                 }
  937.             }
  938.         }
  939.         else
  940.         {
  941.             Log("Blakcjack bug: Player was busted, yet we reached the part where dealer finished his turn (draw his cards?).");
  942.         }
  943.     }
  944.     void GivePlayerMoney(int amount)
  945.     {
  946.         Critter@ player = GetCritter(playerId);
  947.         if (valid(player))
  948.         {
  949.             player.AddItem(PID_BOTTLE_CAPS, amount);
  950.         }
  951.         else
  952.         {
  953.             Log("Blackjack Error: Player to give money to not found.");
  954.         }
  955.     }
  956.     void TakePlayerMoney(int amount)
  957.     {
  958.         Critter@ player = GetCritter(playerId);
  959.         if (valid(player))
  960.         {
  961.             player.DeleteItem(PID_BOTTLE_CAPS, amount);
  962.         }
  963.         else
  964.         {
  965.             Log("Blackjack Error: Player to take money from not found.");
  966.         }
  967.     }
  968.  
  969.     /**<
  970.      *  Test cases - Function names speak for themselves, they should cover all possibilities, use the correct one for your tests.
  971.      */
  972.     void InsertTestCasesForPlayerBlackjack()
  973.     {
  974.         //  Fourth case: Even money is offered, dealer looses on stand.
  975.         shoe.InsertTestValuesForPlayerBlackjackAndDealerStandOn17();
  976.         //  Third case: Even money is offered, dealer looses on stand.
  977.         shoe.InsertTestValuesForPlayerBlackjackAndDealerIs21();
  978.         //  Second case: Even money may not appear, it's a push.
  979.         shoe.InsertTestValuesForPlayerBlackjackAndDealerNotAce();
  980.         //  First case: Even money is offered, it's a push on stand.
  981.         shoe.InsertTestValuesForPlayerBlackjackAndDealerBlackjack();
  982.     }
  983.  
  984.     void InsertTestCasesForDoubleDown()
  985.     {
  986.         //  Fifth case: Double down and bust.
  987.         shoe.InsertTestValuesForPlayerDoubleDownAndBustAndDealer18();
  988.         //  Fourth case: Double down shall be available and win after second card in hand.
  989.         shoe.InsertTestValuesForPlayerDoubleDown20AndDealer18();
  990.         //  Third case: Double down shall be available and loose after second card in hand.
  991.         shoe.InsertTestValuesForPlayerDoubleDown20AndDealer21();
  992.         //  Second case: Double down shall be available and loose after second card in hand.
  993.         shoe.InsertTestValuesForPlayerDoubleDown20AndDealerBlackjack();
  994.         //  First case: Double down shall be available after taking the 2nd and 3rd card in hand. Player doubles down after 3rd and wins.
  995.         shoe.InsertTestValuesForPlayerDoubleDownAfterThirdCard20AndDealer18();
  996.     }
  997.  
  998.     void InsertTestCasesForLuckyLadies()
  999.     {
  1000.         //  Fifth case: Unsuited total of 20 in start hand.
  1001.         shoe.InsertTestValuesForLuckyLadiesUnSuited();
  1002.         //  Fourth case: Suited total of 20 in start hand.
  1003.         shoe.InsertTestValuesForLuckyLadiesSuited();
  1004.         //  Third case: Matched
  1005.         shoe.InsertTestValuesForLuckyLadiesMatch();
  1006.         //  Second case: Queen of hearts pair and player not blackjack.
  1007.         shoe.InsertTestValuesForLuckyLadiesQohpAndDealer20();
  1008.         //  First case: Queen of hearts pair and player blackjack.
  1009.         shoe.InsertTestValuesForLuckyLadiesQohpAndDealerBlackjack();
  1010.     }
  1011.  
  1012.     void InsertTestCasesForPerfectPair()
  1013.     {
  1014.         //  Third case: Mixed Pair.
  1015.         shoe.InsertTestValuesForPerfectPairPlayerMixedPair();
  1016.         //  Second case: Colored Pair
  1017.         shoe.InsertTestValuesForPerfectPairPlayerColoredPair();
  1018.         //  First case: Perfect pair.
  1019.         shoe.InsertTestValuesForPerfectPairPlayerPerfectPair();
  1020.     }
  1021.  
  1022.     void InsertTestCasesForRoyalMatch()
  1023.     {
  1024.         //  Seconds case: Suited.
  1025.         shoe.InsertTestValuesForRoyalMatchPlayerSuited();
  1026.         //  First case: Royal Match.
  1027.         shoe.InsertTestValuesForRoyalMatchPlayerRoyalMatch();
  1028.     }
  1029. };
RAW Paste Data Copied