-
Notifications
You must be signed in to change notification settings - Fork 1
/
strategy.js
159 lines (152 loc) · 7.38 KB
/
strategy.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
'use strict';
var blackjack = require('./blackjack');
module.exports = {
BasicStrategy: function (options) {
var defaults = {
standAt: 17,
takeInsurance: false, // set to false for dealer play
split: true, // set to false for dealer play
doubleDown: true, // set to false for dealer play
isDealer: false, // set to true for dealer play
printEmoji: true, // set to false for non-emoji terminal output
};
var getOption = function (key) {
var option = options[key];
if (option === null || option === undefined) {
return defaults[key];
}
return options[key];
};
var Trick = function (dealer, cards) {
var cards = cards || new Array();
var value = function () {
var sum = 0;
var aces = 0;
// a hard hand is one with no aces or where aces are forced to be equal to 1.
// a soft hand is one with at least one ace which may still count as 11 or 1.
var hard = true;
for (var i = 0; i < cards.length; ++i) {
var value = cards[i].value;
if (value !== "ACE") {
sum += value;
} else {
++aces;
}
}
while (aces > 0) {
if (sum + 11 <= 21) {
hard = false;
sum = sum + 11;
} else {
sum = sum + 1;
}
--aces;
}
var hardness = hard ? "hard" : "soft";
return {hard: hard, sum: sum, toString: function() { return hardness + " " + sum;} };
};
var states = {
BUST: 0,
STAND: 1,
HIT: 2,
DOUBLE: 3,
};
var state = function () {
var dealerCard = dealer.getFirstCard();
var sum = value();
if (sum.sum > 21) {
return states.BUST;
}
if (getOption("isDealer")) {
if (sum.sum >= getOption("standAt") && sum.sum <= 21) {
return states.STAND;
} else {
return states.HIT;
}
}
if (sum.hard && sum.sum >= 17) {
return states.STAND;
}
if (!sum.hard && sum.sum >= 20) {
return states.STAND;
}
if (!sum.hard && sum.sum <= 12) {
return states.HIT; // TODO double check this
}
if (sum.sum <= 7) {
return states.HIT;
}
// encoding of basic strategy
var matrix = {
hard: {
8: [states.HIT, states.HIT, states.HIT, states.DOUBLE, states.DOUBLE, states.HIT, states.HIT, states.HIT, states.HIT, states.HIT],
9: [states.DOUBLE, states.DOUBLE, states.DOUBLE, states.DOUBLE, states.DOUBLE, states.HIT, states.HIT, states.HIT, states.HIT, states.HIT],
10: [states.DOUBLE, states.DOUBLE, states.DOUBLE, states.DOUBLE, states.DOUBLE, states.DOUBLE, states.DOUBLE, states.DOUBLE, states.HIT, states.HIT],
11: [states.DOUBLE, states.DOUBLE, states.DOUBLE, states.DOUBLE, states.DOUBLE, states.DOUBLE, states.DOUBLE, states.DOUBLE, states.DOUBLE, states.DOUBLE],
12: [states.HIT, states.HIT, states.STAND, states.STAND, states.STAND, states.HIT, states.HIT, states.HIT, states.HIT, states.HIT],
13: [states.STAND, states.STAND, states.STAND, states.STAND, states.STAND, states.HIT, states.HIT, states.HIT, states.HIT, states.HIT],
14: [states.STAND, states.STAND, states.STAND, states.STAND, states.STAND, states.HIT, states.HIT, states.HIT, states.HIT, states.HIT],
15: [states.STAND, states.STAND, states.STAND, states.STAND, states.STAND, states.HIT, states.HIT, states.HIT, states.HIT, states.HIT],
16: [states.STAND, states.STAND, states.STAND, states.STAND, states.STAND, states.HIT, states.HIT, states.HIT, states.HIT, states.HIT],
},
soft: {
13: [states.HIT, states.HIT, states.DOUBLE, states.DOUBLE, states.DOUBLE, states.HIT, states.HIT, states.HIT, states.HIT, states.HIT],
14: [states.HIT, states.HIT, states.DOUBLE, states.DOUBLE, states.DOUBLE, states.HIT, states.HIT, states.HIT, states.HIT, states.HIT],
15: [states.HIT, states.HIT, states.DOUBLE, states.DOUBLE, states.DOUBLE, states.HIT, states.HIT, states.HIT, states.HIT, states.HIT],
16: [states.HIT, states.HIT, states.DOUBLE, states.DOUBLE, states.DOUBLE, states.HIT, states.HIT, states.HIT, states.HIT, states.HIT],
17: [states.DOUBLE, states.DOUBLE, states.DOUBLE, states.DOUBLE, states.DOUBLE, states.HIT, states.HIT, states.HIT, states.HIT, states.HIT],
18: [states.STAND, states.DOUBLE, states.DOUBLE, states.DOUBLE, states.DOUBLE, states.STAND, states.STAND, states.HIT, states.HIT, states.STAND],
19: [states.STAND, states.STAND, states.STAND, states.STAND, states.DOUBLE, states.STAND, states.STAND, states.STAND, states.STAND, states.STAND],
},
};
var dealerIndex = dealerCard.value;
if (value === "ACE") {
dealerIndex = 11;
}
dealerIndex -= 2;
return matrix[sum.hard ? "hard" : "soft"][sum.sum][dealerIndex];
};
var stateAsTxt = function () {
var stateVal = state();
for (var i = 0; i < Object.keys(states).length; ++i) {
var val = states[i];
if (val === stateVal) {
return i;
}
}
return "UNKNOWN";
};
var doubled = false;
var doubleDown = function () {
doubled = true;
};
return {
cards: cards,
addCard: function (card) {
cards.push(card);
},
states: states,
value: value,
stateAsTxt: stateAsTxt,
state: state,
doubleDown: doubleDown,
doubled: doubled,
toString: function () {
var out = "";
for (var j = 0; j < cards.length; ++j) {
if (j !== 0) {
out += ",";
}
out += (getOption('printEmoji') ? cards[j].emojiName : cards[j].shortName);
}
out += " [" + value() + "]";
return out;
},
copy: function () { return new Trick(dealer, cards); },
};
};
return {
Trick: Trick,
};
},
};