1 """Calculate the probability of various poker hands
4 from pbot.combinations import xunique_combinations
5 from pbot.deck import new_deck, SevenChooseFiveHand
9 """Calculate the odds of winning given the current game state.
11 >>> from pprint import pprint
12 >>> from pbot.deck import unpp_card
14 The only thing that can beat 4 aces is a straight flush. With
15 spaced out public cards, that is impossible, so we only get wins
16 in that case. The total number of opposing hands is
19 >>> o = Odds(hole=[unpp_card(c) for c in ['As', 'Ah']],
20 ... public=[unpp_card(c) for c in ['Ad', 'Ac', 'Ts', '7h', '4d']])
22 {'losses': 0, 'ties': 0, 'wins': 990}
24 However, with properly aligned public cards, the straight flush is
25 within reach, so we get losses whenever the opposing hole contains
26 `Tc`. This leaves `52-8=44` options for the other hole card.
28 >>> o.public = [unpp_card(c) for c in ['Ad', 'Ac', 'Kc', 'Qc', 'Jc']]
29 >>> pprint(o.calculate())
30 {'losses': 44, 'ties': 0, 'wins': 946}
32 The odds caclulator will cycle through unknown public cards, but
36 >>> pprint(o.calculate())
37 {'losses': 134, 'ties': 0, 'wins': 47476}
41 def __init__(self, hole, public=None):
46 self.results = self.calculate()
49 known = self.hole + self.public
50 hidden = [c for c in self.deck if c not in known]
51 remaining = 5 - len(self.public)
52 results = {'wins': 0, 'ties': 0, 'losses': 0}
53 for new_public in xunique_combinations(hidden, remaining):
54 p = self.public + new_public
55 h = [c for c in hidden if c not in p]
56 hand = SevenChooseFiveHand(self.hole + p)
57 for hole in xunique_combinations(hidden, 2):
58 other_hand = SevenChooseFiveHand(hole + p)
59 result = cmp(hand, other_hand)
65 results['losses'] += 1