Skip to content

Commit 5cd9453

Browse files
committed
informed
1 parent f5dde69 commit 5cd9453

5 files changed

Lines changed: 181 additions & 233 deletions

File tree

players/35-informed/blackjack.conf

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
decks = 1
2-
enhc = false
2+
enhc = true
33
flat_bet = true
44
no_insurance = true
5-
shuffle_every_hand = true
5+
# shuffle_every_hand = true
66
# cards = 3 2 5
7-
cards = 2 3 5
7+
cards = TH 6 JD
88
player = informed

src/blackjack.cpp

Lines changed: 51 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,29 @@
3636
namespace lbj {
3737
Blackjack::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() {
155171
int 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

235251
void 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

src/conf.cpp

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,7 @@ std::string trim(const std::string& str) {
204204
if (first == std::string::npos) {
205205
return ""; // String is all whitespace
206206
}
207-
207+
208208
size_t last = str.find_last_not_of(" \t\n\r\f\v");
209209
return str.substr(first, (last - first + 1));
210210
}
@@ -229,10 +229,9 @@ std::string strip_inline_comment(const std::string& line) {
229229
}
230230

231231
int Configuration::readConfigFile(std::string file_path, bool mandatory) {
232-
233-
// std::ifstream is RAII, i.e. no need to call close
232+
234233
std::ifstream fileStream(file_path);
235-
234+
236235
if (fileStream.is_open()) {
237236
int line_num = 0;
238237
std::string line;
@@ -242,26 +241,26 @@ int Configuration::readConfigFile(std::string file_path, bool mandatory) {
242241
if (line[0] == '#' || line[0] == ';' || line.empty()) {
243242
continue;
244243
}
245-
244+
246245
std::size_t delimiter_pos = line.find("=");
247246
if (delimiter_pos != std::string::npos) {
248247
std::string name = trim(line.substr(0, delimiter_pos));
249248
std::string value = trim(line.substr(delimiter_pos + 1));
250249
if (!exists(name)) {
251250
conf[name] = value;
252251
used[name] = false;
253-
}
252+
}
254253
} else {
255254
std::cerr << "error: cannot find '=' in " << file_path << ":" << line_num << std::endl;
256255
return -1;
257-
}
256+
}
258257
}
259258
} else {
260259
return -1;
261260
}
262-
261+
263262
return 0;
264-
263+
265264
}
266265

267266
bool Configuration::set(bool *value, std::list<std::string> key) {

0 commit comments

Comments
 (0)