3636namespace lbj {
3737Blackjack::Blackjack (Configuration &conf) : Dealer(conf), rng(dev_random()), fiftyTwoCards(1 , 52 ) {
3838
39+ // /conf+hands+usage `hands = ` $n$
40+ // /conf+hands+details Sets the number of hands to play before quiting.
41+ // /conf+hands+details If $n$ is zero, the program keeps playing until it receives the command `quit`.
42+ // /conf+hands+details Otherwise it plays $n$ hands and quits.
43+ // /conf+hands+details This parameter can be set on the command line with the option `-n`$n$ or `--hands=`$n$.
44+ // /conf+hands+default $0$
45+ // /conf+hands+example hands = 1
46+ // /conf+hands+example hands = 1000000
47+ // /conf+hands+example hands = 1e6
3948 conf.set (&n_hands, {" n_hands" , " hands" });
49+
50+ // /conf+decks+usage `decks = ` $n$
51+ // /conf+decks+details Sets the number of decks used in the game.
52+ // /conf+decks+details If $n$ is zero, the program draws cards from an infinte set.
53+ // /conf+decks+details For a finite $n$, the cards are drawn from a shoe.
54+ // /conf+decks+default $0$
55+ // /conf+decks+example decks = 1
56+ // /conf+decks+example decks = 2
57+ // /conf+decks+example decks = 8
4058 conf.set (&n_decks, {" decks" , " n_decks" });
4159
4260 conf.set (&max_bet, {" maximum_bet" , " max_bet" , " maxbet" });
43-
44-
61+
4562 // rules are base, particular options take precedence
4663 if (conf.exists (" rules" )) {
4764 std::istringstream iss (conf.getString (" rules" ));
@@ -75,25 +92,24 @@ Blackjack::Blackjack(Configuration &conf) : Dealer(conf), rng(dev_random()), fif
7592 }
7693 conf.markUsed (" rules" );
7794 }
78-
95+
7996 conf.set (&h17, {" h17" , " hit_soft_17" });
8097 conf.set (&das, {" das" , " double_after_split" });
8198 conf.set (&doa, {" doa" , " double_on_any" });
8299 conf.set (&rsa, {" rsa" , " resplit_aces" });
83100 conf.set (&enhc, {" enhc" , " european_no_hole_card" });
84101 conf.set (&blackjack_pays, {" blackjack_pays" });
85-
102+
86103 conf.set (&playerStats.bankroll , {" bankroll" , " initial_bankroll" });
87-
104+
88105 // parent class_
89106 conf.set (&number_of_burnt_cards, {" number_of_burnt_cards" , " n_burnt_cards" , " burnt_cards" });
90107 conf.set (&penetration, {" penetration" });
91108 conf.set (&penetration_sigma, {" penetration_sigma" , " penetration_dispersion" });
92109 conf.set (&shuffle_every_hand, {" shuffle" , " shuffle_every_hand" });
93110 conf.set (&quit_when_arranged_cards_run_out, {" quit_when_arranged_cards_run_out" });
94111 conf.set (&new_hand_reset_cards, {" new_hand_reset_cards" });
95-
96-
112+
97113 // read arranged cards
98114 if (conf.exists (" cards" )) {
99115 if (conf.exists (" cards_file" )) {
@@ -106,35 +122,35 @@ Blackjack::Blackjack(Configuration &conf) : Dealer(conf), rng(dev_random()), fif
106122 }
107123 conf.markUsed (" cards" );
108124 }
109-
125+
110126 if (conf.exists (" cards_file" )) {
111127 if (conf.exists (" cards" )) {
112128 std::cerr << " error: cannot have both cards and cards_file" << std::endl;
113129 exit (1 );
114130 }
115-
131+
116132 std::ifstream file (conf.getString (" cards_file" ));
117133 if (!file.is_open ()) {
118134 std::cerr << " error: opening file " << conf.getString (" cards_file" ) << std::endl;
119135 exit (1 );
120136 }
121137 std::string file_content ((std::istreambuf_iterator<char >(file)), std::istreambuf_iterator<char >());
122138 file.close ();
123-
139+
124140 std::istringstream iss (file_content);
125141 if (read_arranged_cards (std::move (iss)) != 0 ) {
126142 exit (1 );
127143 }
128144 conf.markUsed (" cards_file" );
129145 }
130-
146+
131147 n_arranged_cards = arranged_cards.size ();
132-
148+
133149 bool explicit_seed = conf.set (&rng_seed, {" rng_seed" , " seed" });
134150 if (explicit_seed) {
135151 rng = std::mt19937 (rng_seed);
136152 }
137-
153+
138154 // initialize shoe and perform initial shuffle
139155 if (n_decks > 0 ) {
140156 shoe.reserve (52 *n_decks);
@@ -155,13 +171,13 @@ Blackjack::~Blackjack() {
155171int Blackjack::read_arranged_cards (std::istringstream iss) {
156172 std::string token;
157173 while (iss >> token) {
158-
174+
159175 // TODO: move to cards.cpp
160176 bool number = true ;
161177 for (char c : token) {
162178 number &= std::isdigit (c);
163179 }
164-
180+
165181 int n = 0 ;
166182 if (number) {
167183 n = std::stoi (token);
@@ -190,7 +206,7 @@ int Blackjack::read_arranged_cards(std::istringstream iss) {
190206 std::cerr << " error: invalid ASCII card rank " << token << std::endl;
191207 return 1 ;
192208 }
193-
209+
194210 if (suit != ' \0 ' ) {
195211 if (suit == ' C' ) {
196212 n += static_cast <int >(lbj::Suit::Clubs) * 13 ;
@@ -206,11 +222,11 @@ int Blackjack::read_arranged_cards(std::istringstream iss) {
206222 }
207223 }
208224 }
209-
225+
210226 if (n == 0 ) {
211227 std::cerr << " error: invalid card " << token << std::endl;
212228 }
213-
229+
214230 arranged_cards.push_back (n);
215231 }
216232 return 0 ;
@@ -226,28 +242,28 @@ void Blackjack::can_double_split(void) {
226242 int value = playerStats.currentHand ->value ();
227243 player->canDouble &= (value == 9 || value == 10 || value == 11 );
228244 }
229-
245+
230246 player->canSplit = n_cards == 2 && (card[*(playerStats.currentHand ->cards .begin ())].value == card[*(++playerStats.currentHand ->cards .begin ())].value );
231247 return ;
232- }
248+ }
233249
234250
235251void Blackjack::deal (void ) {
236-
252+
237253 bool player_blackjack = false ;
238254 // let's start by assuming the player does not need to do anything
239255 player->actionRequired = lbj::PlayerActionRequired::None;
240-
256+
241257 switch (nextAction) {
242258 // -------------------------------------------------------------------------
243259 case lbj::DealerAction::StartNewHand:
244-
260+
245261 // check if we are done
246262 if (n_hands > 0 && n_hand >= n_hands) {
247263 finished (true );
248264 return ;
249265 }
250-
266+
251267 if (n_hand != 0 ) {
252268 updateMeanAndVariance ();
253269 }
@@ -257,7 +273,7 @@ void Blackjack::deal(void) {
257273 }
258274 playerStats.currentOutcome = 0 ;
259275 n_hand++;
260-
276+
261277 // clear dealer's hand
262278 hand.cards .clear ();
263279
@@ -268,16 +284,16 @@ void Blackjack::deal(void) {
268284 playerStats.hands .clear ();
269285 playerStats.hands .push_back (std::move (PlayerHand ()));
270286 playerStats.currentHand = playerStats.hands .begin ();
271-
287+
272288 // state that the player did not win anything nor split nor doubled down
273289 playerStats.splits = 0 ;
274-
290+
275291 if (last_pass || shuffle_every_hand) {
276292 info (lbj::Info::Shuffle);
277-
293+
278294 // shuffle the shoe
279- shuffle ();
280-
295+ shuffle ();
296+
281297 // burn as many cards as asked
282298 pos += number_of_burnt_cards;
283299 last_pass = false ;
@@ -287,9 +303,9 @@ void Blackjack::deal(void) {
287303#ifdef BJDEBUG
288304 std::cout << " new hand #" << n_hand << std::endl;
289305#endif
290-
306+
291307 if (player->flat_bet ) {
292-
308+
293309 // TODO: check bankroll
294310 playerStats.currentHand ->bet = player->flat_bet ;
295311 // take player's money
@@ -298,12 +314,12 @@ void Blackjack::deal(void) {
298314 playerStats.worstBankroll = playerStats.bankroll ;
299315 }
300316 playerStats.totalMoneyWaged += playerStats.currentHand ->bet ;
301-
317+
302318 player->actionRequired = lbj::PlayerActionRequired::None;
303319 nextAction = lbj::DealerAction::DealPlayerFirstCard;
304-
320+
305321 } else {
306-
322+
307323 player->actionRequired = lbj::PlayerActionRequired::Bet;
308324 nextAction = lbj::DealerAction::None;
309325
0 commit comments