seriously reworked my poker hand program to simulate preflop heads up equity
seems to work OK, although it takes a little longer than i would like for it to run
going to set this aside for now and focus more on the course materials
thanks to everyone for the advice
Code:
from operator import itemgetter
import random
VALUES = map(str, range(2, 10)) + ['T', 'J', 'Q', 'K', 'A']
SUITS = ['c', 'd', 'h', 's']
FULL_DECK = [v + s for s in SUITS for v in VALUES]
VALUES_DICT = dict(zip(VALUES, range(13)))
HAND_RANK = {
(1,1,1,1,1,'s','f'): ('Straight flush', 9), (4,1): ('Four of a kind', 8),
(3,2): ('Full house', 7), (1,1,1,1,1,'f'): ('Flush', 6),
(1,1,1,1,1,'s'): ('Straight', 5), (3,1,1): ('Three of a kind', 4),
(2,2,1): ('Two pair', 3), (2,1,1,1): ('One pair', 2),
(1,1,1,1,1): ('High card', 1)
}
class Card(object):
def __init__(self, name):
"""name is a string with value and suit, e.g. 'As', '8c', or 'Td'"""
self.n = name
self.r = name[0]
self.v = VALUES_DICT[name[0]]
self.s = name[1]
def rank(self):
return self.r
def value(self):
return self.v
def suit(self):
return self.s
def __str__(self):
return self.n
class Hand(list):
def __init__(self, cards):
"""cards is a list of card objects"""
list.__init__(self, cards)
name = '<'
for c in cards:
name += str(c) + ','
self.n = name[0:-1] + '>'
def ranks(self):
return [c.rank() for c in self]
def values(self):
return [c.value() for c in self]
def suits(self):
return [c.suit() for c in self]
def sorted_values(self):
self.sv = list(self.values())
self.sv.sort()
return self.sv
def counts(self):
i, j, counts, sv = 0, 0, [], list(self.sorted_values())
while i < len(sv):
counts.append(sv.count(sv[i]))
i += counts[j]
j += 1
return counts
def sorted_counts(self):
self.sc = list(self.counts())
self.sc.sort()
return self.sc
def __str__(self):
return self.n
class PokerHand(Hand):
def __init__(self, cards):
"""cards is a list of 5 card objects"""
Hand.__init__(self, cards)
def flush(self):
return len(set(self.suits())) == 1
def straight(self):
sv = self.sorted_values()
if max(self.counts()) != 1:
return False
return ((sv[4] - sv[0] == 4) or sv == [0, 1, 2, 3, 12])
def rank(self):
rank = list(self.sorted_counts())
rank.sort(reverse=True)
if self.straight():
rank.append('s')
if self.flush():
rank.append('f')
return HAND_RANK[tuple(rank)]
def index(self):
c = list(self.counts())
counts_x = [c[i] for i in range(len(c)) for j in range(c[i])]
counts_vals = zip(self.sorted_values(), counts_x)
index, x =zip(*sorted(counts_vals, key=itemgetter(1,0), reverse=True))
index = list(index)
if index == [12, 3, 2, 1, 0]:
index = [3, 2, 1, 0, -1]
index.insert(0, self.rank()[1])
return index
def hands_in_long_hand(long_hand):
"""Assumes long_hand is a Hand object containing seven Card objects
Returns list of all five card combinations"""
two_cards = [(x, y) for x in range(0, 7) for y in range(0,7) if x < y]
all_hands = []
for x, y in two_cards:
long_hand_copy = list(long_hand)
del long_hand_copy[x]
del long_hand_copy[y - 1]
all_hands.append(PokerHand(long_hand_copy))
return all_hands
def best_poker_hand(long_hand):
"""Assumes long_hand is a Hand object containing seven Card objects
Returns the highest ranking Poker Hand"""
all_hands = hands_in_long_hand(long_hand)
indexes = []
for hand in all_hands:
indexes.append(hand.index())
best_position = indexes.index(max(indexes))
best_hand = all_hands[best_position]
return best_hand
def deal(deck):
return deck.pop(random.randint(0, len(deck) - 1))
def heads_up(hole_cards1, hole_cards2):
hole_cards = hole_cards1 + hole_cards2
deck = list(FULL_DECK)
board = []
for c in hole_cards:
deck.remove(str(c))
deck = [Card(c) for c in deck]
for i in range(5):
board.append(deal(deck))
hand1 = hole_cards1 + board
hand2 = hole_cards2 + board
return Hand(hand1), Hand(hand2)
def equity(hole_cards1, hole_cards2, num_trials):
"""Assumes hole_cards1 and hole_cards2 are two card hands and
num_trials is an int > 0
Calculates simulated preflop equity of hole_cards 1 and hole_cards2"""
equity1 = 0.0
for i in range(num_trials):
hand1, hand2 = heads_up(hole_cards1, hole_cards2)
poker_hand1 = best_poker_hand(hand1)
poker_hand2 = best_poker_hand(hand2)
if poker_hand1.index() > poker_hand2.index():
equity1 += 1
elif poker_hand1.index() == poker_hand2.index():
equity1 += 0.5
avg_eq1 = 100*(equity1/num_trials)
avg_eq2 = 100 - avg_eq1
print 'Preflop equity of', hole_cards1, 'vs.', hole_cards2
print ' is', str(round(avg_eq1, 2)), 'vs.', str(round(avg_eq2, 2))
y1 = Card('Ks')
y2 = Card('Ad')
y3 = Card('Qh')
y4 = Card('Qs')
equity(Hand([y1, y2]), Hand([y3, y4]), 10000)