-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcounter.py
More file actions
224 lines (192 loc) · 6.48 KB
/
Copy pathcounter.py
File metadata and controls
224 lines (192 loc) · 6.48 KB
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
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
'''
counter.py
Defines the Counter class for a blackjack counter
'''
import json
import shoe
from math import floor
from player import Player
from rules import CARDS_PER_DECK, \
CARD_VALUES, \
hand_value, \
CARD_INDEXES
class Counter(Player):
'''
The Player is a card counter
'''
def __init__(self, json_file_path: str):
with open(json_file_path, 'r') as fobj:
self._tables = json.load(fobj)
self._true_count = 0.0
self._count = 0.0
self._decks_in_shoe = 0.0
self._number_cards_seen = 0.0
self._minimum_bet = 0.0 # table minimum
self._maximum_bet = 0.0 # table maximum
self._bankrole = self._tables['bankrole']
self._unit = self._tables['unit']
self._true_adjust = self._tables['true_adjust']
self._counts = self._tables['counts']
self._hard_stand = self._tables['hard_stand']
self._soft_stand = self._tables['soft_stand']
self._double = self._tables['double']
self._split = self._tables['split']
self._surrender = self._tables['surrender']
self._insurance = self._tables['insurance']
self._upcard_index = self._tables['upcard_index']
def place_insurance_bet(self, bet:float) -> None:
'remove the insurance bet from the player bankrole'
self._bankrole -= bet
def set_minimum_bet(self, bet:float) -> None:
'sets the table minimum bet'
self._minimum_bet = bet
def set_maximum_bet(self, bet:float) -> None:
'sets maximum table bet'
self._maximum_bet = bet
def receive_payoff(self, amount : float) -> None:
'''
Implements the Player interface function.
The player has won the wager. This is the
return of the win along with the original wager
'''
self._bankrole += amount
def get_bet_amount(self) -> float:
'''
Implements the Player interface function.
Get the desire bet amount. Do not take
any money from the bankrole, that is
done with make_bet
'''
scale = self._true_count + self._true_adjust
wager = self._unit * floor(scale + 0.5)
if wager < self._minimum_bet:
wager = self._minimum_bet
elif wager > self._maximum_bet:
wager = self._maximum_bet
if wager < self._unit:
wager = self._unit
return wager
def make_bet(self, wager:float) -> None:
'''
Required by the Player interface
'''
self._bankrole -= wager
return wager
def _accepts(self, cards:str, upcard:str, table) -> bool:
assert len(cards) == 2
try:
hand = self._handsort(cards)
updex = self._upcard_index[upcard]
decision = table[hand][updex]
return self._true_count >= decision
except KeyError:
return False
def accepts_insurance(self, cards : str, upcard : str) -> bool:
'''
Implements the Player interface function.
The player is asked by the dealer if the hand should be
insured. If then the dealer will place a side bet of
one half of the current bet on the hand
'''
assert upcard == 'A'
assert len(cards) == 2
try:
hand = self._handsort(cards)
return self._true_count >= self._insurance[hand]
except KeyError:
return False
def accepts_surrender(self, cards:str, upcard:str) -> bool:
'Required by the Player interface'
return self._accepts(cards, upcard, self._surrender)
def accepts_split(self, cards:str, upcard:str) -> bool:
'Required by the Player interface'
return self._accepts(cards, upcard, self._split)
def accepts_double(self, cards:str, upcard:str) -> bool:
'Required by the Player interface'
return self._accepts(cards, upcard, self._double)
def accepts_stand(self, cards:str, upcard:str) -> bool:
'Required by the Player interface'
value, soft = hand_value(cards)
if soft:
table = self._soft_stand
else:
table = self._hard_stand
try:
updex = self._upcard_index[upcard]
decision = table[str(value)][updex]
return self._true_count >= decision
except KeyError:
return False
def show_card(self, card : str) -> None:
'The player sees a card that has been dealt to the table'
print('counter sees', card)
assert len(card) == 1
self._number_cards_seen += 1.0
self._count += self._counts[card]
self._set_true_count()
def show_decks_in_shoe(self, decks_in_shoe:int) -> None:
'''
Tells the counter the number of decks in the shoe.
This is needed for calculating the true count.
'''
self._decks_in_shoe = float(decks_in_shoe)
def _set_true_count(self) -> None:
'set self.value to the current value'
number_cards = CARDS_PER_DECK * self._decks_in_shoe
number_cards_unseen = number_cards - self._number_cards_seen
number_decks_unseen = number_cards_unseen / CARDS_PER_DECK
self._true_count = self._count / number_decks_unseen
def _handsort(self, cards:str) -> str:
'''
sort a hand so that the low cards come first
Normally there are two cards.
'''
hand = list(cards)
def keyfun(card):
return CARD_INDEXES[card]
hand.sort(key=keyfun)
return ''.join(hand)
def test0() -> None:
'Just at test'
# Set everything done
counter = Counter('strategy1.json')
counter.show_decks_in_shoe(6)
counter.set_minimum_bet(100.0)
counter.set_maximum_bet(3000.0)
print('counter-bankrole:', counter._bankrole)
#play a round
# deal the cards
counter.show_card('A') # up-card
counter.show_card('X') # player card
counter.show_card('X') # player card
# what is the true?
print("true-count: {0:.1f}".format(counter._true_count))
bet = counter.get_bet_amount()
counter.make_bet(bet)
print("counter-bet:", bet)
print("couter-bankrole:", counter._bankrole)
# the player gets two tens
cards = 'XX'
# the dealer has an up-card
up_card = 'A'
# a hand is a values sorted string of cards
hand = counter._handsort(cards)
# print the original string of cards and then the sorted cards of the hand
print('counter-hand:', hand)
print('up-card:', up_card)
if counter.accepts_insurance(cards, up_card):
print("counter accepts insurance")
else:
print("counter declines insurance")
if counter.accepts_split(cards, up_card):
print("counter accepts split")
else:
print("counter declines split")
if counter.accepts_double(cards, up_card):
print("player accepts double")
else:
print("player declines double")
if counter.accepts_stand(cards, up_card):
print("player accepts stand")
else:
print("player declines stand")