@@ -202,7 +202,7 @@ Blackjack::Blackjack(Configuration &conf) : Dealer(conf), rng(dev_random()), fif
202202// /conf+quit_when_arranged_cards_run_out+example quit_when_arranged_cards_run_out = false
203203// /conf+quit_when_arranged_cards_run_out+example quit_when_arranged_cards_run_out = true
204204 conf.set (&quit_when_arranged_cards_run_out, {" quit_when_arranged_cards_run_out" });
205-
205+
206206// /conf+new_hand_reset_cards+usage `new_hand_reset_cards_out = ` $b$
207207// /conf+new_hand_reset_cards+details If the are arranged cards (either with `cards` or `cards_file`) and $b$ is `true`
208208// /conf+new_hand_reset_cards+details then when a hand is finished, the next hand starts with the arranged cards from the very beginning.
@@ -226,6 +226,19 @@ Blackjack::Blackjack(Configuration &conf) : Dealer(conf), rng(dev_random()), fif
226226// /conf+new_hand_reset_cards+example new_hand_reset_cards = true
227227 conf.set (&new_hand_reset_cards, {" new_hand_reset_cards" });
228228
229+ // /conf+dealer_draws_even_if_player_busted+usage `dealer_draws_even_if_player_busted = ` $b$
230+ // /conf+dealer_draws_even_if_player_busted+details The usual rule in casinos is that if all player busted all hands (including split hands),
231+ // /conf+dealer_draws_even_if_player_busted+details the dealer does not have to draw until sixteen (or soft seventeen) but the hand is finihsed
232+ // /conf+dealer_draws_even_if_player_busted+details and the next card in the shoe (or shuffler) is the player's first card of the next hand.
233+ // /conf+dealer_draws_even_if_player_busted+details Yet, this rule may distort some statistics such as dealer's bust rate because for sure
234+ // /conf+dealer_draws_even_if_player_busted+details he will not bust that hand.
235+ // /conf+dealer_draws_even_if_player_busted+details This flag can modify the dealer's behavior and, if true, the dealer will draw cards
236+ // /conf+dealer_draws_even_if_player_busted+details as normal even if the player had busted all her hands.
237+ // /conf+dealer_draws_even_if_player_busted+default `false`
238+ // /conf+dealer_draws_even_if_player_busted+example dealer_draws_even_if_player_busted = false
239+ // /conf+dealer_draws_even_if_player_busted+example dealer_draws_even_if_player_busted = true
240+ conf.set (&dealer_draws_even_if_player_busted, {" dealer_draws_even_if_player_busted" });
241+
229242 // read arranged cards
230243// /conf+cards+usage `cards = ` $\text{list of cards}$
231244// /conf+cards+details If this option is given, the dealer draws the cards specified on the list.
@@ -249,10 +262,14 @@ Blackjack::Blackjack(Configuration &conf) : Dealer(conf), rng(dev_random()), fif
249262// /conf+cards+details ii. a set of infinite cards , if `decks` is zero.
250263// /conf+cards+details b. the hand is over and `new_hand_reset_cards` is `true`, or
251264// /conf+cards+details c. `quit_when_arranged_cards_run_out` is true, in which case the program exits.
265+ // /conf+cards+details @
266+ // /conf+cards+details A zero or `XX` means a placeholder for an actual random card. So for example `JS XX AC` will give
267+ // /conf+cards+details the Jack of Spades, a random card and te Ace of Clubs.
268+ // /conf+cards+details @
252269// /conf+cards+default Empty list
253270// /conf+cards+example cards = TH JD 6C
254- // /conf+cards+example cards = 2S 5D QS AC
255- // /conf+cards+example cards = 8D QH TC 2C KD 7S 8S TD AH 5C
271+ // /conf+cards+example cards = 2S XX QS AC
272+ // /conf+cards+example cards = 8D QH XX 2C KD 7S XX TD AH 5C
256273 if (conf.exists (" cards" )) {
257274 if (conf.exists (" cards_file" )) {
258275 std::cerr << " error: cannot have both cards and cards_file" << std::endl;
@@ -373,25 +390,27 @@ int Blackjack::read_arranged_cards(std::istringstream iss) {
373390 if (rank == ' X' ) { // placeholder for random
374391 n = 0 ;
375392 } else if (rank == ' A' ) {
376- n = 1 ;
393+ n = 1 ;
377394 } else if (rank == ' T' ) {
378- n = 10 ;
395+ n = 10 ;
379396 } else if (rank == ' J' ) {
380- n = 11 ;
397+ n = 11 ;
381398 } else if (rank == ' Q' ) {
382- n = 12 ;
399+ n = 12 ;
383400 } else if (rank == ' K' ) {
384- n = 13 ;
401+ n = 13 ;
385402 } else {
386403 n = rank - ' 0' ;
387404 }
388- if (n < 1 || n > 13 ) {
405+ if (n < 0 || n > 13 ) {
389406 std::cerr << " error: invalid ASCII card rank " << token << std::endl;
390407 return 1 ;
391408 }
392409
393410 if (suit != ' \0 ' ) {
394- if (suit == ' C' ) {
411+ if (suit == ' X' ) {
412+ n += 0 ;
413+ } else if (suit == ' C' ) {
395414 n += static_cast <int >(lbj::Suit::Clubs) * 13 ;
396415 } else if (suit == ' D' ) {
397416 n += static_cast <int >(lbj::Suit::Diamonds) * 13 ;
@@ -699,38 +718,42 @@ void Blackjack::deal(void) {
699718 } else {
700719 // assume the player busted in all the hands
701720 bool player_busted_all_hands = true ;
702- for (auto playerHand = playerStats.hands . begin (); playerHand != playerStats. hands . end (); playerHand++ ) {
721+ for (const auto &player_hand : playerStats.hands ) {
703722 // if he (she) did not bust, set to false
704- if (playerHand-> busted () == false ) {
723+ if (player_hand. busted () == false ) {
705724 player_busted_all_hands = false ;
706725 break ;
707726 }
708727 }
709728
710729 if (player_busted_all_hands) {
711- if (enhc == false ) {
730+ if (enhc == false ) {
712731 info (lbj::Info::CardDealerRevealsHole, dealer_hole_card);
713732#ifdef BJDEBUG
714733 std::cout << " hole " << card[dealer_hole_card].utf8 () << std::endl;
715734#endif
716735 }
717- // } else {
718- playerStats.bustsPlayerAllHands ++;
719- // }
720-
721- player->actionRequired = lbj::PlayerActionRequired::None;
722- nextAction = lbj::DealerAction::StartNewHand;
723- return ;
736+ playerStats.bustsPlayerAllHands ++;
737+
738+ if (dealer_draws_even_if_player_busted) {
739+ player->actionRequired = lbj::PlayerActionRequired::None;
740+ nextAction = lbj::DealerAction::HitDealerHand;
741+ return ;
742+ } else {
743+ player->actionRequired = lbj::PlayerActionRequired::None;
744+ nextAction = lbj::DealerAction::StartNewHand;
745+ return ;
746+ }
724747 } else {
725748 player->actionRequired = lbj::PlayerActionRequired::None;
726749 nextAction = lbj::DealerAction::HitDealerHand;
727750 return ;
728751 }
729- }
752+ }
730753 break ;
731-
754+
732755 case lbj::DealerAction::HitDealerHand:
733-
756+
734757 if (enhc == false ) {
735758 info (lbj::Info::CardDealerRevealsHole, dealer_hole_card);
736759#ifdef BJDEBUG
@@ -740,11 +763,12 @@ void Blackjack::deal(void) {
740763
741764 // hit while count is less than 17 (or equal to soft 17 if hit_soft_17 is true)
742765 player->value_dealer = hand.value ();
743- while ((std::abs (player->value_dealer ) < 17 || (h17 && player->value_dealer == -17 )) && hand.busted () == 0 ) {
744- unsigned int dealerCard = draw (&hand);
745- info (lbj::Info::CardDealer, dealerCard);
766+ // while ((std::abs(dealer_value) < 17 || (h17 && dealer_value == -17)) && hand.busted() == false) {
767+ while (std::abs (player->value_dealer ) < 17 || (h17 && player->value_dealer == -17 )) {
768+ unsigned int dealer_card = draw (&hand);
769+ info (lbj::Info::CardDealer, dealer_card);
746770#ifdef BJDEBUG
747- std::cout << " dealer " << card[dealerCard ].utf8 () << std::endl;
771+ std::cout << " dealer " << card[dealer_card ].utf8 () << std::endl;
748772#endif
749773 player->value_dealer = hand.value ();
750774 }
@@ -780,7 +804,7 @@ void Blackjack::deal(void) {
780804 if (hand.busted ()) {
781805 info (lbj::Info::DealerBusts, player->value_dealer );
782806 playerStats.bustsDealer ++;
783- for (auto playerHand : playerStats.hands ) {
807+ for (const auto & playerHand : playerStats.hands ) {
784808 if (playerHand.busted () == false ) {
785809 // pay him (her)
786810 playerStats.bankroll += 2 * playerHand.bet ;
0 commit comments