File indexing completed on 2025-10-12 04:59:55

0001 // bjgb_rules.cpp                                                     -*-C++-*-
0002 #include <bjgb_rules.h>
0003 
0004 #include <algorithm> // 'fill_n', 'swap'
0005 #include <ostream>
0006 
0007 namespace bjgb {
0008 
0009 // -----------
0010 // class Rules
0011 // -----------
0012 
0013 // CREATORS
0014 Rules::Rules():
0015     d_dealerStandsOnSoft17(true),
0016     d_playerMaySurrender(false) // TBD late surrender is allowed; why 'false'?
0017     ,
0018     d_oneCardToSplitAce(true),
0019     d_playerMayResplitAces(false),
0020     d_playerCanLoseDouble(false),
0021     d_playerMayDoubleAny2Cards(true),
0022     d_playerMaxNumHands(4),
0023     d_playerBjPayout(1.5)
0024 {
0025     std::fill_n(d_doubleableHand, sizeof d_doubleableHand, true);
0026 }
0027 
0028 // MANIPULATORS
0029 void Rules::reset()
0030 {
0031     Rules temp;
0032 
0033     using std::swap;
0034     swap(temp, *this);
0035 }
0036 
0037 // Player Rules
0038 
0039 void Rules::setPlayerMayDoubleOnTheseTwoCards(const bool *doubleableHand)
0040 {
0041     assert(doubleableHand);
0042 
0043     std::copy_n(doubleableHand, sizeof d_doubleableHand, d_doubleableHand);
0044 }
0045 
0046 // ACCESSORS
0047 
0048 // Player Rules
0049 
0050 bool Rules::playerMayDoubleOnTheseTwoCards(int handValue, bool isSoftCount) const
0051 {
0052     assert(2 <= handValue);
0053     assert(handValue <= 20);
0054     assert(handValue >= 4 || isSoftCount);
0055     assert(handValue <= 11 || !isSoftCount);
0056 
0057     const int handIndex = isSoftCount ? State::soft(handValue) : State::hard(handValue);
0058 
0059     return playerMayDoubleOnAnyTwoCards() || d_doubleableHand[handIndex];
0060 }
0061 
0062 } // namespace bjgb
0063 
0064 // FREE OPERATORS
0065 bool bjgb::operator==(const Rules& lhs, const Rules& rhs)
0066 {
0067     if (lhs.dealerStandsOnSoft17() != rhs.dealerStandsOnSoft17() || lhs.playerMaySurrender() != rhs.playerMaySurrender()
0068         || lhs.playerGetsOneCardOnlyToSplitAce() != rhs.playerGetsOneCardOnlyToSplitAce()
0069         || lhs.playerMayResplitAces() != rhs.playerMayResplitAces()
0070         || lhs.playerCanLoseDouble() != rhs.playerCanLoseDouble()
0071         || lhs.playerMayDoubleOnAnyTwoCards() != rhs.playerMayDoubleOnAnyTwoCards()
0072         || lhs.playerMaxNumHands() != rhs.playerMaxNumHands()
0073         || lhs.playerBlackjackPayout() != rhs.playerBlackjackPayout()) {
0074         return false; // RETURN
0075     }
0076 
0077     for (int i = 0; i <= State::k_NUM_STATES; ++i) {
0078         if (lhs.d_doubleableHand[i] != rhs.d_doubleableHand[i]) {
0079             return false; // RETURN
0080         }
0081     }
0082 
0083     return true;
0084 }
0085 
0086 std::ostream& bjgb::operator<<(std::ostream& stream, const Rules& rules)
0087 {
0088     stream << "================ Blackjack Rules ================\n";
0089 
0090     stream << "Dealer must stand on soft 17:           " << rules.dealerStandsOnSoft17() << '\n';
0091 
0092     stream << "Player may surrender:                   " << rules.playerMaySurrender() << '\n';
0093 
0094     stream << "Player may resplit Aces:                " << rules.playerMayResplitAces() << '\n';
0095 
0096     stream << "Player gets 1 card only to a split Ace: " << rules.playerGetsOneCardOnlyToSplitAce() << '\n';
0097 
0098     stream << "Player may double on any 2 cards:       " << rules.playerMayDoubleOnAnyTwoCards() << '\n';
0099 
0100     if (!rules.playerMayDoubleOnAnyTwoCards()) {
0101         // TBD print out array of doubleable hands
0102     }
0103 
0104     stream << "Player can lose double:                 " << rules.playerCanLoseDouble() << '\n';
0105 
0106     stream << "Player max number of hands:             " << rules.playerMaxNumHands() << '\n';
0107 
0108     stream << "Player blackjack payout:                " << rules.playerBlackjackPayout() << '\n';
0109 
0110     stream << "=================================================\n";
0111 
0112     return stream;
0113 }