def play_the_board(cards, board_cards): hand = [eval7.Card(s) for s in (cards[:2], cards[2:])] board = [ eval7.Card(s) for s in [board_cards[i:i + 2] for i in range(0, len(board_cards), 2)] ] hand_type = eval7.hand_type(eval7.evaluate(hand + board)) board_type = eval7.hand_type(eval7.evaluate(board)) if hand_type != board_type: return False # cannot have a higher pair/trips elif hand_type in ['High Card', 'Pair', 'Trips']: return True # can have a higher two pair, if evaluation is highly different elif hand_type in ['Two Pair']: # do something numbers = [ 'A', 'K', 'Q', 'J', 'T', '9', '8', '7', '6', '5', '4', '3', '2' ] return [2 if (cards+board_cards)[::2].count(i) == 2 else 0 for i in numbers] == \ [2 if board_cards[::2].count(i) == 2 else 0 for i in numbers] # five card hands will evaluate to the same else: return eval7.evaluate(hand + board) == eval7.evaluate(board)
def calculate(self, hand_range_string, board_card_strings): """Calculate the probabilities of each hand type.""" for key in hand_types + draw_types + pair_types: self[key] = 0.0 board = map(eval7.Card, board_card_strings) hr = hand_range.HandRange(hand_range_string) hr.exclude_cards(board) if len(board) < 3: raise ValueError("Not enough cards in board!") for hand, prob in hr.iteritems(): if not prob == 0.0: cards = board + list(hand) result = eval7.evaluate(cards) hand_type = eval7.hand_type(result) self[hand_type] += prob if len(cards) < 7 and hand_types.index(hand_type) < 5: # No flush or better, so there may be draws. if self.check_flush_draw(cards): self["Flush Draw"] += prob if hand_type != 'Straight': straight_draw_type = self.check_straight_draw(cards) if straight_draw_type is not None: self[straight_draw_type] += prob if hand_type == "Pair": # Break down pairs by type. self[self.pair_type(hand, board)] += prob
def canbe_straight(cards): count = 0 for c in [eval7.Card(x + "d") for x in eval7.ranks]: if not c.rank in [x.rank for x in cards]: hand_type = eval7.hand_type(eval7.evaluate(cards + [c])) if hand_type in ["Straight", "Straight Flush"]: count += 1 return count
def evaluate(data): if data["game"]["board"] is not None: cards = data["self"]["cards"] + data["game"]["board"] else: cards = data["self"]["cards"] hand = [eval7.Card(x.capitalize()) for x in cards] score = eval7.evaluate(hand) type = eval7.hand_type(score) suitcount = maxsuitcount(hand) straight = canbe_straight(hand) return (hand, score, type, suitcount, straight)
def showdown(self): ''' Compares the players' hands and computes payoffs. ''' global STRAIGHTS score0 = eval7.evaluate(list(self.deck.peek(5) + self.hands[0])) score1 = eval7.evaluate(list(self.deck.peek(5) + self.hands[1])) if score0 > score1: delta = STARTING_STACK - self.stacks[1] if eval7.hand_type(score0) == 'Straight': STRAIGHTS[0] += 1 elif score0 < score1: delta = self.stacks[0] - STARTING_STACK if eval7.hand_type(score1) == 'Straight': STRAIGHTS[1] += 1 else: # split the pot delta = (self.stacks[0] - self.stacks[1]) // 2 return TerminalState([delta, -delta], self)
def test_evaluate(self): cases = ( (['2c', '3d', '4h', '5s', '7s', '8d', '9c'], 484658, 'High Card'), (['2c', '3d', '4h', '4s', '7s', '8d', '9c'], 16938576, 'Pair'), (['2c', '3d', '4h', '4s', '7s', '7d', '9c'], 33892096, 'Two Pair'), (['2c', '3d', '4h', '7s', '7c', '7d', '9c'], 50688512, 'Trips'), (['2c', '3d', '4h', '5s', '7c', '7d', '6c'], 67436544, 'Straight'), (['Ac', '3h', '4h', '5s', '2h', 'Jh', 'Kd'], 67305472, 'Straight'), (['Ac', '3h', 'Th', '5s', 'Qh', 'Jh', 'Kd'], 67895296, 'Straight'), (['2c', '3h', '4h', '5s', 'Jh', '7h', '6h'], 84497441, 'Flush'), (['Ac', '3h', 'Th', 'Ts', 'Ks', 'Kh', 'Kd'], 101416960, 'Full House'), (['Ac', '3h', 'Th', 'Ks', 'Kh', 'Kd', 'Kc'], 118210560, 'Quads'), (['3c', '2c', '5c', 'Ac', '4c', 'Kd', 'Kc'], 134414336, 'Straight Flush'), ) for card_strs, expected_val, expected_type in cases: cards = tuple(map(eval7.Card, card_strs)) value = eval7.evaluate(cards) hand_type = eval7.hand_type(value) self.assertEqual(value, expected_val) self.assertEqual(hand_type, expected_type)
def river_action_wrapped(cards, board_cards, opponents, bet, pot, raised=False, first_bet=False, pot_type=2): hand = [eval7.Card(s) for s in (cards[:2], cards[2:])] board = [ eval7.Card(s) for s in [board_cards[i:i + 2] for i in range(0, len(board_cards), 2)] ] current_hand = eval7.hand_type(eval7.evaluate(hand + board)) # if you have nuts, raise or jam RFI = "22+, 32s, 53s+, 63s+, 74s+, 84s+, 95s+, T6s+, J6s+, " \ "Q4s+, K2s+, A2s+, A2o+, K8o+, Q8o+, J8o+, T8o+, 98o+" TBet = "ATo+, KJo+, QJo+, 44+, 65s, 76s, 87s, 97s+, T8s+, J9s+, Q9s+, K9s+, A2s+" FBet = "TT+, AJs+, KQs, AQo+" villain_ranges = {2: RFI, 3: TBet, 4: FBet} villain = eval7.HandRange(villain_ranges[pot_type]) equity = eval7.py_hand_vs_range_monte_carlo(hand, villain, board, 1000) if raised: if equity > 0.99: return "Raise " + str(2.5 * bet) elif equity > 0.95: return "Call" else: return "Fold" if equity > 0.97: if bet > 0: return "Raise " + str(2.5 * bet) else: return "Bet " + str(0.8 * pot) # else, look into non-raising methods # multi-way pot if opponents > 1: # someone bet, only call if top pair or better (< 2 rounds of bets) if bet > 0: if first_bet: if current_hand != 'High Card' and not play_the_board( cards, board_cards): if current_hand == 'Pair': if not tpttk(cards, board_cards): return "Fold" return "Call" if play_the_board(cards, board_cards): return "Fold" if current_hand == 'High Card' or current_hand == 'Pair': return "Fold" elif current_hand == 'Two Pair': if paired_card(board_cards) and max(list( board_cards[::2])) >= highest_two_pair( cards, board_cards): return "Fold" return "Call" else: return "Call" # no one bet, bet if you have trips or better if current_hand not in ['High Card', 'Pair', 'Two Pair' ] and not play_the_board(cards, board_cards): return "Bet " + str(pot * 0.8) else: return "Check" # heads up else: # someone bet, only call if enough equity, above 80% if bet > 0: if first_bet: if equity > bet / (bet + pot): return "Call" else: return "Fold" elif equity > 0.80: return "Call" else: return "Fold" else: if equity > 0.80: return "Bet " + str(pot * 0.8) else: return "Check"
def betting_round_2_wrapped(cards, board_cards, opponents, bet, pot, preflop_agg=False, position=False, raised=False, pot_type=2): hand = [eval7.Card(s) for s in (cards[:2], cards[2:])] board = [ eval7.Card(s) for s in [board_cards[i:i + 2] for i in range(0, len(board_cards), 2)] ] current_hand = eval7.hand_type(eval7.evaluate(hand + board)) if raised: if current_hand in ['High Card', 'Pair', 'Two Pair'] or play_the_board( cards, board_cards): return "Fold" else: return "Call" # multi-way pot, bluff less if opponents > 1: # someone bet again, only call if have top pair (if bet < pot) or better if bet > 0: if play_the_board(cards, board_cards): return "Fold" if current_hand == 'High Card': return "Fold" elif current_hand == 'Pair': if not tpttk(cards, board_cards): return "Fold" else: return "Call" elif current_hand == 'Two Pair': if paired_card(board_cards): return "Fold" return "Call" else: return "Call" # no one bet, bet if you are pre-flop aggressor IP if (preflop_agg or position) and current_hand not in ['High Card', 'Pair'] and \ not play_the_board(cards, board_cards): return "Bet " + str(pot * 0.70) else: return "Check" # heads up else: # since not playing limp pot, pots are either RFI, 3-bet, 4-bet+ RFI = "22+, 32s, 53s+, 63s+, 74s+, 84s+, 95s+, T6s+, J6s+, " \ "Q4s+, K2s+, A2s+, A2o+, K8o+, Q8o+, J8o+, T8o+, 98o+" TBet = "ATo+, KJo+, QJo+, 44+, 65s, 76s, 87s, 97s+, T8s+, J9s+, Q9s+, K9s+, A2s+" FBet = "TT+, AJs+, KQs, AQo+" villain_ranges = {2: RFI, 3: TBet, 4: FBet} villain = eval7.HandRange(villain_ranges[pot_type]) equity = eval7.py_hand_vs_range_monte_carlo(hand, villain, board, 1000) # someone bet, only call if above 75% equity, since second bullet if bet > 0: if equity > 0.75: return "Call" else: return "Fold" # no one bet, bet if you are pre-flop aggressor and have > 50% equity against range if (preflop_agg or position) and equity > 0.5: return "Bet " + str(pot * 0.7) else: return "Check"
def betting_round_1_wrapped(cards, board_cards, opponents, bet, pot, preflop_agg=False, position=False, raised=False, pot_type=2): hand = [eval7.Card(s) for s in (cards[:2], cards[2:])] board = [ eval7.Card(s) for s in [board_cards[i:i + 2] for i in range(0, len(board_cards), 2)] ] current_hand = eval7.hand_type(eval7.evaluate(hand + board)) if raised: if current_hand in ['High Card', 'Pair'] or play_the_board( cards, board_cards): return "Fold" elif current_hand == 'Two Pair': if paired_card(board_cards) and paired_card( board_cards) >= highest_two_pair(cards, board_cards): return "Fold" return "Call" else: return "Call" # multi-way pot, bluff less if opponents > 1: # someone bet, only call if have pair, oesd, fd if bet > 0: if play_the_board(cards, board_cards): return "Fold" if current_hand == 'High Card': # want a good flush draw, or an oesd w/ hole cards if bet < pot and (good_flush_draw(cards, board_cards) or (oesd(cards, board_cards) and not oesd("", board_cards))): return "Call" return "Fold" elif current_hand == 'Pair' and bet > 0.5 * pot: return "Fold" else: return "Call" # no one bet, bet if you are pre-flop aggressor IP if (preflop_agg or position ) and current_hand != 'High Card' and not play_the_board( cards, board_cards): return "Bet " + str(pot / 3) else: return "Check" # heads up else: # since not playing limp pot, pots are either RFI, 3-bet, 4-bet+ RFI = "22+, 32s, 53s+, 63s+, 74s+, 84s+, 95s+, T6s+, J6s+, " \ "Q4s+, K2s+, A2s+, A2o+, K8o+, Q8o+, J8o+, T8o+, 98o+" TBet = "ATo+, KJo+, QJo+, 44+, 65s, 76s, 87s, 97s+, T8s+, J9s+, Q9s+, K9s+, A2s+" FBet = "TT+, AJs+, KQs, AQo+" villain_ranges = {2: RFI, 3: TBet, 4: FBet} villain = eval7.HandRange(villain_ranges[pot_type]) equity = eval7.py_hand_vs_range_monte_carlo(hand, villain, board, 1000) # someone bet, only call if enough equity if bet > 0: if equity > bet / (bet + pot): return "Call" else: return "Fold" # no one bet, bet if you are pre-flop aggressor and have > 50% equity against range if (preflop_agg or position) and equity > 0.5: return "Bet " + str(pot / 3) else: return "Check"