/
blackjack.py
221 lines (206 loc) · 9.36 KB
/
blackjack.py
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
import random
import sys
import GeneticAlgorithm
import math
# genetic algorithm individual
GA = None
# creates deck of cards for blackjack as a list of integers (16 10s instead of 10s and face cards)
def create_blackjack_deck():
deck = []
for i in range(1,14):
for j in range(4):
deck.append(min(i,10))
return deck
# calculates sum of hand with Aces as 11
def high_sum(hand):
sum = 0
ace_made_11 = False
for i in hand:
if i == 1 and not ace_made_11:
sum += 11
ace_made_11 = True
else:
sum += i
return sum
# calculates sum of hand with Aces as 1
def low_sum(hand):
sum = 0
for i in hand:
sum += i
return sum
# calculates highest sum that doesn't bust or lowest sum
def hand_sum(hand):
if low_sum(hand) > 21: return low_sum(hand)
if high_sum(hand) < 22:
return high_sum(hand)
else:
return low_sum(hand)
# calculates state of hand
# returns None if less than 21, False if busted (>21), and True if 21
def hand_state(hand):
if hand_sum(hand) > 21:
return False
elif hand_sum(hand) < 21:
return None
else:
return True
## CHOOSERS ##
# randomly returns hit or stand
def random_chooser():
if random.randint(0,1) == 1:
return 'h'
else:
return 's'
# uses dealer strategy of hitting if sum is under 17
def dealer_strategy(hand):
if high_sum(hand) < 17 or (low_sum(hand) < 17 and high_sum(hand) > 21):
return 'h'
else:
return 's'
# use genetic algorithm chromosome to choose
def genetic_algorithm(hand, dealer, ga_player):
#print(GA)
#print('hand',hand,'dealer',dealer)
# pairs & soft hands
if len(hand) == 2:
# pairs
if hand[0] == hand[1]:
#print('pair')
return ga_player.chromosome.pairs[hand[0]][dealer]
# soft hand
elif 1 in hand:
#print('soft')
if not hand[0] == 1:
return ga_player.chromosome.soft_hands[hand[0]][dealer]
else:
return ga_player.chromosome.soft_hands[hand[1]][dealer]
# hard hands
#print('hard')
return ga_player.chromosome.hard_hands[hand_sum(hand)][dealer]
# chooser that uses ga filled with data from online strategy
# double downs were replaced with holds and pairs copy hard hands
def optimal(hand, dealer):
optimalGA = GeneticAlgorithm.Individual(GeneticAlgorithm.Chromosome())
optimalGA.chromosome.hard_hands = {
5: {2: 'h', 3: 'h', 4: 'h', 5: 'h', 6: 'h', 7: 'h', 8: 'h', 9: 'h', 10: 'h', 1: 'h'},
6: {2: 'h', 3: 'h', 4: 'h', 5: 'h', 6: 'h', 7: 'h', 8: 'h', 9: 'h', 10: 'h', 1: 'h'},
7: {2: 'h', 3: 'h', 4: 'h', 5: 'h', 6: 'h', 7: 'h', 8: 'h', 9: 'h', 10: 'h', 1: 'h'},
8: {2: 'h', 3: 'h', 4: 'h', 5: 'h', 6: 'h', 7: 'h', 8: 'h', 9: 'h', 10: 'h', 1: 'h'},
9: {2: 'h', 3: 'h', 4: 'h', 5: 'h', 6: 'h', 7: 'h', 8: 'h', 9: 'h', 10: 'h', 1: 'h'},
10: {2: 'h', 3: 'h', 4: 'h', 5: 'h', 6: 'h', 7: 'h', 8: 'h', 9: 'h', 10: 'h', 1: 'h'},
11: {2: 'h', 3: 'h', 4: 'h', 5: 'h', 6: 'h', 7: 'h', 8: 'h', 9: 'h', 10: 'h', 1: 'h'},
12: {2: 'h', 3: 'h', 4: 's', 5: 's', 6: 's', 7: 'h', 8: 'h', 9: 'h', 10: 'h', 1: 'h'},
13: {2: 's', 3: 's', 4: 's', 5: 's', 6: 's', 7: 'h', 8: 'h', 9: 'h', 10: 'h', 1: 'h'},
14: {2: 's', 3: 's', 4: 's', 5: 's', 6: 's', 7: 'h', 8: 'h', 9: 'h', 10: 'h', 1: 'h'},
15: {2: 's', 3: 's', 4: 's', 5: 's', 6: 's', 7: 'h', 8: 'h', 9: 'h', 10: 'h', 1: 'h'},
16: {2: 's', 3: 's', 4: 's', 5: 's', 6: 's', 7: 'h', 8: 'h', 9: 'h', 10: 'h', 1: 'h'},
17: {2: 's', 3: 's', 4: 's', 5: 's', 6: 's', 7: 's', 8: 's', 9: 's', 10: 's', 1: 's'},
18: {2: 's', 3: 's', 4: 's', 5: 's', 6: 's', 7: 's', 8: 's', 9: 's', 10: 's', 1: 's'},
19: {2: 's', 3: 's', 4: 's', 5: 's', 6: 's', 7: 's', 8: 's', 9: 's', 10: 's', 1: 's'},
20: {2: 's', 3: 's', 4: 's', 5: 's', 6: 's', 7: 's', 8: 's', 9: 's', 10: 's', 1: 's'}}
optimalGA.chromosome.soft_hands = {
2: {2: 'h', 3: 'h', 4: 'h', 5: 'h', 6: 'h', 7: 'h', 8: 'h', 9: 'h', 10: 'h', 1: 'h'},
3: {2: 'h', 3: 'h', 4: 'h', 5: 'h', 6: 'h', 7: 'h', 8: 'h', 9: 'h', 10: 'h', 1: 'h'},
4: {2: 'h', 3: 'h', 4: 'h', 5: 'h', 6: 'h', 7: 'h', 8: 'h', 9: 'h', 10: 'h', 1: 'h'},
5: {2: 'h', 3: 'h', 4: 'h', 5: 'h', 6: 'h', 7: 'h', 8: 'h', 9: 'h', 10: 'h', 1: 'h'},
6: {2: 'h', 3: 'h', 4: 'h', 5: 'h', 6: 'h', 7: 'h', 8: 'h', 9: 'h', 10: 'h', 1: 'h'},
7: {2: 'h', 3: 'h', 4: 'h', 5: 'h', 6: 'h', 7: 's', 8: 's', 9: 'h', 10: 'h', 1: 'h'},
8: {2: 's', 3: 's', 4: 's', 5: 's', 6: 's', 7: 's', 8: 's', 9: 's', 10: 's', 1: 's'},
9: {2: 's', 3: 's', 4: 's', 5: 's', 6: 's', 7: 's', 8: 's', 9: 's', 10: 's', 1: 's'}}
optimalGA.chromosome.pairs = {
2: {2: 'h', 3: 'h', 4: 'h', 5: 'h', 6: 'h', 7: 'h', 8: 'h', 9: 'h', 10: 'h', 1: 'h'},
3: {2: 'h', 3: 'h', 4: 'h', 5: 'h', 6: 'h', 7: 'h', 8: 'h', 9: 'h', 10: 'h', 1: 'h'},
4: {2: 'h', 3: 'h', 4: 'h', 5: 'h', 6: 'h', 7: 'h', 8: 'h', 9: 'h', 10: 'h', 1: 'h'},
5: {2: 'h', 3: 'h', 4: 'h', 5: 'h', 6: 'h', 7: 'h', 8: 'h', 9: 'h', 10: 'h', 1: 'h'},
6: {2: 'h', 3: 'h', 4: 's', 5: 's', 6: 's', 7: 'h', 8: 'h', 9: 'h', 10: 'h', 1: 'h'},
7: {2: 's', 3: 's', 4: 's', 5: 's', 6: 's', 7: 'h', 8: 'h', 9: 'h', 10: 'h', 1: 'h'},
8: {2: 's', 3: 's', 4: 's', 5: 's', 6: 's', 7: 'h', 8: 'h', 9: 'h', 10: 'h', 1: 'h'},
9: {2: 's', 3: 's', 4: 's', 5: 's', 6: 's', 7: 's', 8: 's', 9: 's', 10: 's', 1: 's'},
10: {2: 's', 3: 's', 4: 's', 5: 's', 6: 's', 7: 's', 8: 's', 9: 's', 10: 's', 1: 's'},
1: {2: 's', 3: 's', 4: 's', 5: 's', 6: 's', 7: 's', 8: 's', 9: 's', 10: 's', 1: 's'}}
return genetic_algorithm(hand, dealer, optimalGA)
# main blackjack game (1 hand)
# return 1 if player wins, 0 if ties, -1 if they lose
def play_blackjack_hand(player,ga_player=None,card1=None,card2=None,dealer_card=None):
deck = create_blackjack_deck()
random.shuffle(deck)
player_hand = [deck.pop(deck.index(card1)),deck.pop(deck.index(card2))] if not (card1==None or card2==None) else [deck.pop(0),deck.pop(0)]
dealer_hand = [deck.pop(deck.index(dealer_card)),deck.pop(0)] if not dealer_card == None else [deck.pop(0),deck.pop(0)]
#print("player",player_hand,"dealer",dealer_hand)
if player == 'human': print("dealer's card: ",dealer_hand[0])
choice = None
if hand_state(player_hand):
if player == 'human': print('you have blackjack!')
if hand_state(dealer_hand): # check for dealer blackjack
if player == 'human': print('dealer also has blackjack')
return 0
else:
return 1
while not choice == 's':
if player == 'human': print("your hand:",player_hand)
# choice
if player == 'human':
choice = input("enter s for stand or h for hit: ")
if player == 'random':
choice = random_chooser()
if player == 'dealer':
choice = dealer_strategy(player_hand)
if player == 'ga':
choice = genetic_algorithm(player_hand,dealer_hand[0],ga_player)
#print(choice)
if player == 'optimal':
choice = optimal(player_hand,dealer_hand[0])
# hit
if choice == 'h':
player_hand.append(deck.pop(0))
if player == 'human': print("new card:",player_hand[len(player_hand)-1])
# check game state
if hand_state(player_hand):
break # if 21
elif hand_state(player_hand) == False:
if player == 'human': print('you busted :(')
return -1
if hand_state(dealer_hand): # check for dealer blackjack
if player == 'human': print('dealer has blackjack :(')
#print("player",player_hand,"dealer",dealer_hand)
return -1
# dealer plays
while high_sum(dealer_hand) < 17 or (low_sum(dealer_hand) < 17 and high_sum(dealer_hand) > 21):
dealer_hand.append(deck.pop(0))
# compare hands
if hand_state(dealer_hand) == False:
if player == 'human': print('the dealer busted!')
#print("player",player_hand,"dealer",dealer_hand)
return 1
elif hand_sum(dealer_hand) > hand_sum(player_hand):
if player == 'human': print('you lose :(')
#print("player",player_hand,"dealer",dealer_hand)
return -1
elif hand_sum(dealer_hand) < hand_sum(player_hand):
if player == 'human': print('you win!')
#print("player",player_hand,"dealer",dealer_hand)
return 1
else:
if player == 'human': print("it's a tie")
return 0
def blackjack_tournament(player,num_games=1000):
score = 0
for j in range(30):
for i in range(num_games):
score += play_blackjack_hand(player)
print(score / (j + 1))
return score / 30
if __name__ == "__main__":
if 'human' in sys.argv:
print(play_blackjack_hand('human'))
if 'tournament' in sys.argv:
print(blackjack_tournament(sys.argv[sys.argv.index('tournament') + 1],int(sys.argv[sys.argv.index('tournament') + 2])))
if 'ga' in sys.argv:
print(play_blackjack_hand('ga'))
if 'optimal' in sys.argv:
print(blackjack_tournament('optimal'))
if 'dealer' in sys.argv:
print(blackjack_tournament('dealer'))
else:
x = input('enter player: ')
print(play_blackjack_hand(x))