-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathPokerModel.py
314 lines (247 loc) · 7.68 KB
/
PokerModel.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
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
import operator
import random
import pygame
class Card:
def __init__(self, rank, suit):
self.rank = 0
self.suit = ''
self.image_path = ('img/'+str(rank) + str(suit) + '.png')
self.selected = False
#convert the rank to an integer so it's easier to compute the winner of a hand
if rank == 'A':
self.rank = 14
elif rank == 'K':
self.rank = 13
elif rank == 'Q':
self.rank = 12
elif rank == 'J':
self.rank = 11
elif rank == 'T':
self.rank = 10
else:
self.rank = int(rank)
self.suit = suit
def __str__(self):
out = ""
#convert rank back to a word so it's easier to read
if self.rank == 14:
out += "Ace"
elif self.rank == 13:
out += "King"
elif self.rank == 12:
out += "Queen"
elif self.rank == 11:
out += "Jack"
else:
out += str(self.rank)
out += ' of '
#convert the suit to a word so it's easier to read
if self.suit == 'H':
out += 'Hearts'
elif self.suit == 'S':
out += 'Spades'
elif self.suit == 'C':
out += 'Clubs'
else:
out += 'Diamonds'
return out
#only exists for the __str__ function
class Hand:
def __init__(self, hand):
self.hand = hand
def __str__(self):
out = ""
for card in self.hand:
out += str(card) + ", "
return out
def __getitem__(self, index):
return self.hand[index]
def __len__(self):
return len(self.hand)
class Deck:
def __init__(self):
self.deck = []
for suit in ['H','S','C','D']:
for rank in range(2,15):
self.deck.append(Card(rank, suit))
def __str__(self):
out = ""
for card in self.deck:
out += str(card) + "\n"
return out
def __getitem__(self, index):
return self.deck[index]
#return a list a cards taken from the deck
def deal(self, amount):
cards = []
#cap out the cards dealt
if amount > len(self.deck):
print("There are not enough cards! I can only deal " + str(len(self.deck)) + " cards.")
amount = len(self.deck)
#create and then return a list of cards taken randomly from the deck
for i in range(amount):
card = random.choice(self.deck)
self.deck.remove(card)
cards.append(card)
return cards
class Poker:
def __init__(self):
self.deck = Deck()
self.scores = [0,0,0,0]
self.playerHand = Hand(self.deck.deal(5))
self.comp1Hand = Hand(self.deck.deal(5))
self.comp2Hand = Hand(self.deck.deal(5))
self.comp3Hand = Hand(self.deck.deal(5))
def __init__(self, scores):
self.deck = Deck()
self.scores = scores
self.playerHand = Hand(self.deck.deal(5))
self.comp1Hand = Hand(self.deck.deal(5))
self.comp2Hand = Hand(self.deck.deal(5))
self.comp3Hand = Hand(self.deck.deal(5))
#make each computer take a turn
def computerReplace(self):
self.AI_replace(self.comp1Hand)
self.AI_replace(self.comp2Hand)
self.AI_replace(self.comp3Hand)
def get_most_suit(self, hand):
suits = {'H':0, 'C':0, 'S':0, 'D':0}
for card in hand:
suits[card.suit] += 1
return max(suits.items(), key=operator.itemgetter(1))[0]
def get_most_rank(self, hand):
ranks = {1:0, 2:0, 3:0, 4:0, 5:0, 6:0, 7:0, 8:0, 9:0, 10:0, 11:0, 12:0, 13:0, 14:0}
for card in hand:
ranks[card.rank] += 1
return max(ranks.items(), key=operator.itemgetter(1))[0]
def replace_suit(self, hand):
suit = self.get_most_suit(hand)
for card in hand:
if card.suit != suit:
card.selected = True
self.replace(hand)
def replace_rank(self, hand):
rank = self.get_most_rank(hand)
for card in hand:
if card.rank != rank:
card.selected = True
self.replace(hand)
def AI_replace(self, hand):
score = self.get_score(hand)
#decide which cards not to toss away so as to keep the same score
if str(score)[0] == '1': #High card, try for flush
self.replace_suit(hand)
elif str(score)[0] == '2': #One pair, switch out cards not paired
self.replace_rank(hand)
elif str(score)[0] == '3': #Two pair, switch out card not paired
self.replace_rank(hand)
elif str(score)[0] == '4': #Three of a kind, switch out cards not paired
self.replace_rank(hand)
elif str(score)[0] == '8': #Four of a kind, switch out the not paired not
self.replace_rank(hand)
#all other cases are a pass
#repalces the selected cards in the hand with the top cards on the deck
def replace(self, hand):
count = 0
for i in range(3):
for card in hand:
if card.selected:
hand.hand.remove(card)
count += 1
hand.hand.extend(self.deck.deal(count))
#plays a round of poker with 4 hands
#winner is displayed and scores for each hand as well
#the number of the winner is returned by the function
def play_round(self):
score1 = self.get_score(self.playerHand)
score2 = self.get_score(self.comp1Hand)
score3 = self.get_score(self.comp2Hand)
score4 = self.get_score(self.comp3Hand)
winner = max(score1, max(score2, max(score3, score4)))
if winner == score1:
self.scores[0] += 1
elif winner == score2:
self.scores[1] += 1
elif winner == score3:
self.scores[2] += 1
elif winner == score4:
self.scores[3] += 1
return [score1, score2, score3, score4]
#returns an integer that represents a score given to the hand. The first digits represents the type of hand and the rest represent the cards in the hands
def get_score(self, hand):
#make a dictionary containing the count of each each
cardCount = {2:0, 3:0, 4:0, 5:0, 6:0, 7:0, 8:0, 9:0, 10:0, 11:0, 12:0, 13:0, 14:0}
for card in hand.hand:
cardCount[card.rank] += 1
#count number of unique cards
uniqueCount = 0
for rankCount in cardCount.values():
if rankCount > 0:
uniqueCount += 1
straight = self.is_straight(hand)
flush = self.is_flush(hand)
points = 0
if straight and flush:
points = max(points, 9) #straight flush
elif flush and not straight:
points = max(points, 6) #flush
elif not flush and straight:
points = max(points, 5) #straight
elif uniqueCount == 2:
if max(cardCount.values()) == 4:
points = 8 #four of a kind (2 uniques and 4 are the same)
elif max(cardCount.values()) == 3:
points = 7 #full house (2 unique and 3 are the same)
elif uniqueCount == 3:
if max(cardCount.values()) == 3:
points = 4 #three of a kind (3 unique and 3 are the same)
elif max(cardCount.values()) == 2:
points = 3 #two pair (3 uniques and 2 are the same)
elif uniqueCount == 4:
if max(cardCount.values()) == 2:
points = 2 #one pair (4 uniques and 2 are the same)
elif uniqueCount == 5:
points = 1 #high card
#print out the values of the cards in order from greatest to least with 2 digits for each card in order to generate a point value
sorted_cardCount = sorted(cardCount.items(), key=operator.itemgetter(1,0), reverse=True)
for keyval in sorted_cardCount:
if keyval[1] != 0:
points = int(str(points) + (keyval[1] * str(keyval[0]).zfill(2)))
return points
#given an integer score, returns the poker term equivalent
def convert_score(self, score):
if str(score)[0] == '1':
return "High Card"
elif str(score)[0] == '2':
return "One Pair"
elif str(score)[0] == '3':
return "Two Pair"
elif str(score)[0] == '4':
return "Three of a Kind"
elif str(score)[0] == '5':
return "Straight"
elif str(score)[0] == '6':
return "Flush"
elif str(score)[0] == '7':
return "Full House"
elif str(score)[0] == '8':
return "Four of a Kind"
elif str(score)[0] == '9':
return "Straight Flush"
#a hand is a straight if, when sorted, the current card's rank + 1 is the same as the next card
def is_straight(self,hand):
values = []
for card in hand.hand:
values.append(card.rank)
values.sort()
for i in range(0,4):
if values[i] + 1 != values[i + 1]:
return False
return True
#a hand is a flush if all the cards are of the same suit
def is_flush(self,hand):
suit = hand.hand[0].suit
for card in hand.hand:
if card.suit != suit:
return False
return True