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 getScore(c1, c2, iters=10000): score = 0 for i in range(iters): deck = eval7.Deck() deck.shuffle() myHand = [c1, c2] d = deck.deal(52) d.remove(c1) d.remove(c2) oppHand = [] for i in range(2): oppHand.append(d.pop(0)) street = [] for i in range(5): street.append(d.pop(0)) myHand = myHand + street oppHand = oppHand + street if eval7.evaluate(myHand) > eval7.evaluate(oppHand): score += 1 return score / iters
def calc_win_prob_by_sampling_eval7(sim_num, hole_cards, board_cards, data): """ Calculate the probability to win current players by sampling unknown cards Compute the probability to win one player first And then take the power of virtual player count """ o_hole_cards = [] o_board_cards = [] deck = eval7.Deck() # remove hole cards and board cards from deck for card in hole_cards: card = eval7.Card(card) o_hole_cards.append(card) deck.cards.remove(card) board_cards_to_draw = 5 for card in board_cards: board_cards_to_draw -= 1 card = eval7.Card(card) o_board_cards.append(card) deck.cards.remove(card) vpc_weighted = 1 rivals_count = get_rivals_count(data) win = 0 succeeded_sample = 0 start = time.time() if board_cards_to_draw: for _ in range(sim_num // rivals_count): simulate_cards = deck.sample(board_cards_to_draw + 2 * rivals_count) o_board_sample = o_board_cards + simulate_cards[:board_cards_to_draw] my_rank = eval7.evaluate(o_board_sample + o_hole_cards) won = True for i in range(board_cards_to_draw, board_cards_to_draw + 2 * rivals_count, 2): if my_rank < eval7.evaluate(o_board_sample + simulate_cards[i:i + 2]): won = False break if won: win += 1 succeeded_sample += 1 else: my_rank = eval7.evaluate(o_board_cards + o_hole_cards) n = sim_num * 1.1 for _ in range(n // rivals_count): won = True simulate_cards = deck.sample(2 * rivals_count) for i in range(0, 2 * rivals_count, 2): if my_rank < eval7.evaluate(o_board_cards + simulate_cards[i:i + 2]): won = False break if won: win += 1 succeeded_sample += 1 print("==== sampling result ==== win : %d, total : %d, takes: %f seconds" % (win, succeeded_sample, time.time() - start)) win_one_prob = win * vpc_weighted / succeeded_sample # win_all_prob = win_one_prob ** virtual_player_count(data) print("==== Win probability ==== " + str(win_one_prob)) return win_one_prob
def showdown(self): ''' Compares the players' hands and computes payoffs. ''' score0 = eval7.evaluate(self.deck.peek(5) + self.hands[0]) score1 = eval7.evaluate(self.deck.peek(5) + self.hands[1]) if score0 > score1: winnings = [self.pot, 0] elif score0 < score1: winnings = [0, self.pot] else: # split the pot winnings = [self.pot // 2, self.pot // 2] return TerminalState(winnings, self)
def showdown(self): ''' Compares the players' hands and computes payoffs. ''' score0 = eval7.evaluate(list(map(PERM.get, self.deck.peek(5) + self.hands[0]))) score1 = eval7.evaluate(list(map(PERM.get, self.deck.peek(5) + self.hands[1]))) if score0 > score1: delta = cfg.STARTING_STACK - self.stacks[1] elif score0 < score1: delta = self.stacks[0] - cfg.STARTING_STACK else: # split the pot delta = (self.stacks[0] - self.stacks[1]) // 2 return TerminalState([delta, -delta], self)
def calculate_strength(self, hole, board_cards, iters): ''' A Monte Carlo method meant to estimate the win probability of a pair of hole cards. Simlulates 'iters' games and determines the win rates of our cards Arguments: hole: a list of our two hole cards iters: a integer that determines how many Monte Carlo samples to take ''' deck = eval7.Deck() #eval7 object! hole_cards = [eval7.Card(card) for card in hole] #card objects, used to evaliate hands board_cards = [eval7.Card(card) for card in board_cards if card] for card in board_cards: deck.cards.remove(card) for card in hole_cards: deck.cards.remove(card) score = 0 for _ in range(iters): #take 'iters' samples deck.shuffle() #make sure our samples are random _COMM = 5 - len(board_cards) #the number of cards we need to draw _OPP = 2 draw = deck.peek(_COMM + _OPP) opp_hole = draw[:_OPP] community = draw[_OPP:] our_hand = hole_cards + community + board_cards #the two showdown hands opp_hand = opp_hole + community + board_cards our_hand_value = eval7.evaluate( our_hand ) #the ranks of our hands (only useful for comparisons) opp_hand_value = eval7.evaluate(opp_hand) if our_hand_value > opp_hand_value: #we win! score += 2 elif our_hand_value == opp_hand_value: #we tie. score += 1 else: #we lost.... score += 0 hand_strength = score / (2 * iters) #this is our win probability! return hand_strength
def projectEulerProblemFiftyFour(myList): total = 0 for x in myList: a = x[0:5] b = x[5:] oneHand = [] for card in a: oneHand.append(eval7.Card(card[0]+card[1].lower())) twoHand = [] for card in b: twoHand.append(eval7.Card(card[0]+card[1].lower())) if(eval7.evaluate(oneHand)>eval7.evaluate(twoHand)): total+=1 return total
def play_game(network_1, network_2, blinds, hands): for _ in range(hands): # Draw and distribute cards cards = deck.sample(9) p1_hole_cards = cards[0:2] p2_hole_cards = cards[2:4] board = cards[4:9] p1_cards = p1_hole_cards + board p2_cards = p2_hole_cards + board # Create the input to p1: a 52 value array filled with zeroes and two indices # where the value is 1. These two indices corresponds to p1_hole_cards. p1_input = np.zeros(52) card_id_1 = p1_hole_cards[0].rank + p1_hole_cards[0].suit * 13 card_id_2 = p1_hole_cards[1].rank + p1_hole_cards[1].suit * 13 p1_input[card_id_1] = 1 p1_input[card_id_2] = 1 p1_answer = get_answer(network_1["weights"], p1_input) if p1_answer != 0: p2_input = np.zeros(52) card_id_1 = p2_hole_cards[0].rank + p2_hole_cards[0].suit * 13 card_id_2 = p2_hole_cards[1].rank + p2_hole_cards[1].suit * 13 p2_input[card_id_1] = 1 p2_input[card_id_2] = 1 p2_answer = get_answer(network_2["weights"], p2_input) if p2_answer != 0: p1_eval = eval7.evaluate(p1_cards) p2_eval = eval7.evaluate(p2_cards) if p1_eval > p2_eval: network_1["performance"] += blinds network_2["performance"] -= blinds elif p1_eval < p2_eval: network_1["performance"] -= blinds network_2["performance"] += blinds else: # Player 2 folded network_1["performance"] += 1 network_2["performance"] -= 1 else: # Player 1 folded network_1["performance"] -= 0.5 network_2["performance"] += 0.5
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 rank_hand_py(self, player): print('Player ' + player.name + ' hand: ' + player.hole_cards_str()) cards = [eval7.Card(s) for s in (str(player.hole_cards[0]), str(player.hole_cards[1]), str(self.community[1][0]), str(self.community[1][1]), str(self.community[1][2]), str(self.community[2][0]), str(self.community[3][0]))] rank = eval7.evaluate(cards) handtype = eval7.handtype(rank) print(player.name + ' hand rank: ' + str(rank) + ', hand type: ' + handtype) return rank
def calc_num_outs(curr_hand): # no outs pre flop if len(curr_hand) == 2: return 0 # calculate outs after flop and turn deck = eval7.Deck() remaining_cards = list(set(deck.cards) - set(curr_hand)) num_outs = 0 curr_strength = eval7.evaluate(curr_hand) curr_rank = eval7.handtype(curr_strength) for card in remaining_cards: hand = curr_hand + [card] hand_strength = eval7.evaluate(hand) hand_rank = eval7.handtype(hand_strength) if hand_strength > curr_strength and hand_rank != curr_rank: num_outs += 1 return num_outs
def is_consistent_with_result(self, p, result): board_and_winner_true = [ eval7.Card(c) for c in p.map_str(result.board_cards + result.winner_hole_cards) ] board_and_loser_true = [ eval7.Card(c) for c in p.map_str(result.board_cards + result.loser_hole_cards) ] score_winner = eval7.evaluate(board_and_winner_true) score_loser = eval7.evaluate(board_and_loser_true) # If the losing hand has a higher score than the winning score, then the permutation is # inconsistent with observations. if score_winner <= score_loser: return False else: return True
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 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 handle_round_over(self, game_state, terminal_state, active): ''' Called when a round ends. Called NUM_ROUNDS times. Arguments: game_state: the GameState object. terminal_state: the TerminalState object. active: your player's index. Returns: Nothing. ''' my_delta = terminal_state.deltas[ active] # your bankroll change from this round previous_state = terminal_state.previous_state # RoundState before payoffs street = previous_state.street # 0, 3, 4, or 5 representing when this round ended my_cards = previous_state.hands[active] # your cards opp_cards = previous_state.hands[ 1 - active] # opponent's cards or [] if not revealed board_cards = previous_state.deck[:street] if opp_cards != []: # we have a showdown new_perms = [] for proposal_perm in self.proposal_perms: # check if valid my_perm_cards = [proposal_perm[c] for c in my_cards] opp_perm_cards = [proposal_perm[c] for c in opp_cards] board_perm_cards = [proposal_perm[c] for c in board_cards] my_cards_available = my_perm_cards + board_perm_cards opp_cards_available = opp_perm_cards + board_perm_cards my_strength = eval7.evaluate(my_cards_available) opp_strength = eval7.evaluate(opp_cards_available) # consistent with my win if my_strength > opp_strength and my_delta > 0: new_perms.append(proposal_perm) # consistent with opp win if my_strength < opp_strength and my_delta < 0: new_perms.append(proposal_perm) # consistent with a tie if my_strength == opp_strength and my_delta == 0: new_perms.append(proposal_perm) if len(new_perms) >= 10: self.proposal_perms = new_perms if game_state.round_num == NUM_ROUNDS: print(game_state.game_clock)
def showdown(p, board_state): ''' Computes a showdown between two players, assessed using p as the desired permutation. OUTPUTS: 1: a > b 0: a = b -1: a > b ''' #proposed_dict = pdict(p) #pa = [perm_dict[x] for x in a] #pb = [perm_dict[x] for x in b] #pboard = [perm_dict[x] for x in board] a, b, board = board_state pa = [translate_card(p, x) for x in a] pb = [translate_card(p, x) for x in b] pboard = [translate_card(p, x) for x in board] a_val = eval7.evaluate(pa + pboard) b_val = eval7.evaluate(pb + pboard) if a_val > b_val: #print(a) #print("beats") #print(b) if a_val == 4: return 2 return 1 elif a_val < b_val: #print(b) #print("beats") #print(a) if b_val == 4: return -2 return -1 else: #print(a) #print("ties") #print(b) return 0
def get_action(self, game_state, round_state, active): ''' Where the magic happens - your code should implement this function. Called any time the engine needs an action from your bot. Arguments: game_state: the GameState object. round_state: the RoundState object. active: your player's index. Returns: Your action. ''' legal_actions = round_state.legal_actions() # the actions you are allowed to take #street = round_state.street # 0, 3, 4, or 5 representing pre-flop, flop, river, or turn respectively #my_cards = round_state.hands[active] # your cards #board_cards = round_state.deck[:street] # the board cards #my_pip = round_state.pips[active] # the number of chips you have contributed to the pot this round of betting #opp_pip = round_state.pips[1-active] # the number of chips your opponent has contributed to the pot this round of betting #my_stack = round_state.stacks[active] # the number of chips you have remaining #opp_stack = round_state.stacks[1-active] # the number of chips your opponent has remaining #continue_cost = opp_pip - my_pip # the number of chips needed to stay in the pot #my_contribution = STARTING_STACK - my_stack # the number of chips you have contributed to the pot #opp_contribution = STARTING_STACK - opp_stack # the number of chips your opponent has contributed to the pot #if RaiseAction in legal_actions: # min_raise, max_raise = round_state.raise_bounds() # the smallest and largest numbers of chips for a legal bet/raise # min_cost = min_raise - my_pip # the cost of a minimum bet/raise # max_cost = max_raise - my_pip # the cost of a maximum bet/raise def check_fold(): if CheckAction in legal_actions: return CheckAction() return FoldAction() # STRATEGY: fold-to-win if possible, shove if pair, otherwise check-fold if game_state.bankroll > ceil((NUM_ROUNDS-game_state.round_num) * (SMALL_BLIND + BIG_BLIND)/2): return check_fold() if len(legal_actions) == 1: return legal_actions.pop()() ev = eval7.evaluate([eval7.Card(s) for s in round_state.hands[active]]) handtype = ev >> 24 if handtype >= 1: # pair or higher if RaiseAction in legal_actions: return RaiseAction(STARTING_STACK) elif CallAction in legal_actions: return CallAction() else: soft_assert(CheckAction in legal_actions) return CheckAction() else: return check_fold()
def __init__(self, *items): cards = [] for item in items: if isinstance(item, str): cards += [Card(item[x:x+2]) for x in range(0, len(item), 2)] elif hasattr(item, 'cards'): cards += item.cards else: cards += [item] self.cards = list(reversed(sorted(set(cards)))) self.name = ''.join([c.name for c in self.cards]) self.mask = eval7.evaluate(self.cards) super().__init__()
def monte_carlo_prob(hole_cards: list, shared_cards: list, remaining_cards: list = [], iters: int = 50) -> float: if remaining_cards == []: remaining_cards = all_cards_excluding(hole_cards + shared_cards) # print(f"Monte Carlo can see {len(shared_cards)} community cards") above = 0 # hands that beat ours below = 0 # hands that ours beats equiv = 0 # hands that are equivalent to ours for _ in range(iters): drawn_cards = draw_random_cards(remaining_cards, 7 - len(shared_cards)) # future_shared is the possible future_shared = shared_cards + drawn_cards[2:] pool = future_shared + hole_cards opp_pool = future_shared + drawn_cards[:2] hand = eval7.evaluate([eval7.Card(card) for card in pool]) opp_hand = eval7.evaluate([eval7.Card(card) for card in opp_pool]) if hand > opp_hand: above += 1 elif hand < opp_hand: below += 1 else: equiv += 1 wins = float(above + (equiv / 2.0)) assert (above + below + equiv == iters) total = float(above + below + equiv) return wins / total
def create_opp_hand_from_rank_distribution(opp_hand_rank_probas, public_cards, my_hand): deck = Deck() potential_hands = [] remaining_cards = list(set(deck.cards) - set(public_cards + my_hand)) selected_hand_rank = random.choices(['High Card', 'Pair', 'Two Pair', 'Trips', 'Straight', 'Flush', 'Nuts'], weights=opp_hand_rank_probas[0]) for hand in itertools.combinations(remaining_cards, 2): hand_strength = eval7.evaluate(public_cards + list(hand)) hand_rank = eval7.handtype(hand_strength) # print(selected_hand_rank) if hand_rank in selected_hand_rank: potential_hands.append(hand) elif selected_hand_rank == 'Nuts' and hand_rank in ['Quads', 'Full House', 'Straight Flush']: potential_hands.append(hand) return (remaining_cards[0], remaining_cards[1]) if len(potential_hands) == 0 else random.choice(potential_hands)
def handTypes(cards, board): hand = [eval7.Card(c) for c in cards + board] madeHand = eval7.handtype(eval7.evaluate(hand)) handRanks, handSuits = zip(*(cards + board)) handRanks = set(handRanks) suitCounts = Counter(handSuits) isOESD, isGSSD, isBDSD = straightDraws(handRanks) isFD, isBDFD = flushDraws(suitCounts) isOvercards = overcards(cards, board) draws = set() comboDraws = set() if isOvercards: draws.add('overcards') # if made hand is worse than a flush if madeHandTypes.index(madeHand) > madeHandTypes.index('Flush'): if isFD: draws.add('flush draw') if madeHand == 'Pair': comboDraws.add('FD+Pair') if isOESD: comboDraws.add('FD+OESD') elif isGSSD: comboDraws.add('FD+gutshot') elif isBDFD: if isBDSD: comboDraws.add('BDFD+BDSD') # if made hand is worse than a straight if madeHandTypes.index(madeHand) > madeHandTypes.index('Straight'): if isOESD: draws.add('OESD') if madeHand == 'Pair': comboDraws.add('OESD+Pair') elif isGSSD: draws.add('gutshot') if madeHand == 'Pair': comboDraws.add('gutshot+Pair') elif isBDSD: draws.add('BDSD') return madeHand, draws, comboDraws
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', 'Th', 'Ts', 'Ks', 'Kh', 'Kd'], 101416960, 'Full House'), (['Ac', '3h', 'Th', 'Ks', 'Kh', 'Kd', 'Kc'], 118210560, 'Quads'), (['3c', '2c', '5c', 'Ac', '4c', 'Kc'], 134414336, 'Straight Flush'), ) for card_strs, expected_val, expected_type in cases: cards = tuple(map(eval7.Card, card_strs)) value = eval7.evaluate(cards) handtype = eval7.handtype(value) self.assertEqual(value, expected_val) self.assertEqual(handtype, expected_type)
def find_winning_hand(self, winners_hand, deck): ''' returns the hand with highest evaluation score ''' max_score = 0 max_hand = [] hand = [eval7.Card(winners_hand[0]), eval7.Card(winners_hand[1])] for card1 in deck: hand.append(eval7.Card(card1)) for card2 in deck: if card2!=card1: hand.append(eval7.Card(card2)) for card3 in deck: if card3!=card1 and card3!=card2: hand.append(eval7.Card(card3)) score = eval7.evaluate(hand) if score>max_score: max_score = score max_hand = hand hand.remove(eval7.Card(card3)) hand.remove(eval7.Card(card2)) hand.remove(eval7.Card(card1)) final_hand = [] suit_dict = {0:"c", 1: "d", 2:"h", 3: "s"} for card in max_hand: c = str(card.rank+2)+suit_dict[card.suit] if c not in winners_hand: if card.rank>=8: if str(card.rank)=="8": c = "T"+suit_dict[card.suit] elif str(card.rank)=="9": c = "J"+suit_dict[card.suit] elif str(card.rank)=="10": c = "Q"+suit_dict[card.suit] elif str(card.rank)=="11": c = "K"+suit_dict[card.suit] elif str(card.rank)=="12": c = "A"+suit_dict[card.suit] final_hand.append(c) return final_hand
def decide_showdown(table_cards: Iterable[TexasCard], assist=True): """ If table cards have duplicates, the eval7 implementation might go wrong! so check for it @param table_cards: five to seven cards @return: """ if len(set(table_cards)) < len(tuple(table_cards)): raise ValueError('Duplicated cards') table_cards: List[TexasCard] = TexasCard.sort_desc(table_cards) hand = [eval7.Card(c.to_eval7_str()) for c in table_cards] int_type = eval7.evaluate(hand) str_type = eval7.handtype(int_type) best_type = STR_MAP[str_type] if assist and best_type == StraightFlush: # check with my implementation best = detect.decide_showdown(table_cards) assert isinstance(best, StraightFlush) or isinstance(best, RoyalFlush) if best.__class__ == RoyalFlush: best_type = RoyalFlush return best_type
import eval7
def get_action(self, game_state, round_state, active): ''' Where the magic happens - your code should implement this function. Called any time the engine needs an action from your bot. Arguments: game_state: the GameState object. round_state: the RoundState object. active: your player's index. Returns: Your action. ''' legal_actions = round_state.legal_actions( ) # the actions you are allowed to take #street = round_state.street # 0, 3, 4, or 5 representing pre-flop, flop, river, or turn respectively #my_cards = round_state.hands[active] # your cards #board_cards = round_state.deck[:street] # the board cards my_pip = round_state.pips[ active] # the number of chips you have contributed to the pot this round of betting opp_pip = round_state.pips[ 1 - active] # the number of chips your opponent has contributed to the pot this round of betting my_stack = round_state.stacks[ active] # the number of chips you have remaining opp_stack = round_state.stacks[ 1 - active] # the number of chips your opponent has remaining #continue_cost = opp_pip - my_pip # the number of chips needed to stay in the pot my_contribution = STARTING_STACK - my_stack # the number of chips you have contributed to the pot opp_contribution = STARTING_STACK - opp_stack # the number of chips your opponent has contributed to the pot #if RaiseAction in legal_actions: # min_raise, max_raise = round_state.raise_bounds() # the smallest and largest numbers of chips for a legal bet/raise # min_cost = min_raise - my_pip # the cost of a minimum bet/raise # max_cost = max_raise - my_pip # the cost of a maximum bet/raise # "check" down if already all-in if len(legal_actions) == 1: return CheckAction() # x/f to victory if we can if game_state.bankroll > ceil((NUM_ROUNDS - game_state.round_num) * (SMALL_BLIND + BIG_BLIND) / 2): return CheckAction( ) if CheckAction in legal_actions else FoldAction() # Simple hardcoded / eval7 strategy. street = round_state.street my_hand = round_state.hands[active] board = round_state.deck[:street] # reorder cards for consistent key in dict my_hand = my_hand[::-1] if CARDS.index(my_hand[0]) < CARDS.index( my_hand[1]) else my_hand # raise fraction / sizes # these are parameters to be tweaked (maybe by stats on opponent) if street == 0: RAISE_FRACTION = 0.33 # continue with 1/3 of our defends as 3bets RAISE_SIZE = 1 # raise (1x)pot MDF_FACTOR = 1.05 # slightly looser pre else: RAISE_FRACTION = 0.15 RAISE_SIZE = 0.75 # bet 3/4 pot MDF_FACTOR = 0.6 # slightly tighter post if my_pip == 1 and street == 0: # open 85% of our button preflop raise_range = mdf = bluff_range = 0.85 else: # calculate defend frequency and raise frequency if my_pip == 0 and opp_pip == 0: raise_range = RAISE_FRACTION mdf = RAISE_FRACTION else: mdf = MDF_FACTOR * 2 * my_contribution / ( (opp_pip - my_pip) + 2 * my_contribution) raise_range = mdf * RAISE_FRACTION bluff_range = mdf * (1 + (RAISE_SIZE) / (1 + 2 * RAISE_SIZE) * RAISE_FRACTION) bluff_range = mdf ### TEMP: other bots don't seem to fold too much so let's just not bluff for now. let's try changing this later # re-sort range based on board texture if street > 0 and street != self.sorted_street: hand_values = {} trans_board = [ ALL_RANKS[self.value_ranks[c[0]]] + c[1] for c in board ] new_range = [] for hand in self.range: if not hand[0] in board and not hand[1] in board: trans_hand = [ ALL_RANKS[self.value_ranks[c[0]]] + c[1] for c in hand ] value = eval7.evaluate( [eval7.Card(s) for s in trans_hand + trans_board]) # don't value straights at all if (value >> 24) == 4: # remove single cards so we only have pair/2p/trips ranking left counts = np.unique( [x[0] for x in trans_hand + trans_board], return_counts=True) duplicates = [ counts[0][i] for i in range(len(counts[0])) if counts[1][i] > 1 ] # new value based on just duplicate cards value = eval7.evaluate([ eval7.Card(s) for s in trans_hand + trans_board if s[0] in duplicates ]) hand_values[hand] = value new_range += [hand] self.range = sorted(new_range, key=lambda l: hand_values[l], reverse=True) self.sorted_street = street print('====================') print('Ranks:', self.value_ranks) print(my_hand, board) print([ALL_RANKS[self.value_ranks[c[0]]] + c[1] for c in my_hand], [ALL_RANKS[self.value_ranks[c[0]]] + c[1] for c in board], '(translated)') # print('Top 20 hands in range:', [(h, hand_values[h]) for h in self.range[:20]]) # print('Range: ', self.range) # rank current hand in our range N = len(self.range) hand_position = self.range.index(tuple(my_hand)) / N print('Hand %:', hand_position, my_hand, [ALL_RANKS[self.value_ranks[c[0]]] + c[1] for c in my_hand], self.value_ranks) print(raise_range, '(raise)', mdf, '(defend)', bluff_range, '(bluff)') # determine whether hand is a raise/call/bluff-raise/check/fold # currently commented out range updates; to be "unexploitable" our ranges should be # restricted at each decision (otherwise can be overbluffed if we show weakness), but # that results in us overvaluing weak hands. # e.g. if we check flop, we eliminate all ~pair+ holdings # then on turn if we bet the top 33% of our range, we'll have to start value-betting high card hands # to do it properly we need some "slowplay" range to protect our delayed value hands if (hand_position < raise_range or mdf < hand_position < bluff_range ) and opp_contribution < STARTING_STACK: raise_size = min(int(opp_pip + RAISE_SIZE * 2 * opp_contribution), my_pip + my_stack) if street == 0: self.range = self.range[:ceil(N * raise_range)] + self.range[ int(N * mdf):int(ceil(N * bluff_range))] print('RAISE:', raise_size) return RaiseAction(raise_size) elif hand_position < mdf and opp_pip > my_pip: if street == 0: self.range = ( self.range[:int(N * raise_range)] if opp_pip == my_pip + my_stack else []) + self.range[int(N * raise_range):int(ceil(N * mdf))] print('CALL') return CallAction() elif my_pip == opp_pip: if street == 0: self.range = self.range[int(N * raise_range):int(ceil( N * mdf))] + self.range[int(N * bluff_range):] print('CHECK') return CheckAction() else: return FoldAction()
def calc_win_prob_by_sampling_eval7(self, hole_cards, board_cards, data, sim_num): """ Calculate the probability to win current players by sampling unknown cards Compute the probability to win one player first And then take the power of virtual player count """ o_hole_cards = [] o_board_cards = [] deck = eval7.Deck() # remove hole cards and board cards from deck for card in hole_cards: card = eval7.Card(card) o_hole_cards.append(card) deck.cards.remove(card) board_cards_to_draw = 5 for card in board_cards: board_cards_to_draw -= 1 card = eval7.Card(card) o_board_cards.append(card) deck.cards.remove(card) # vpc_weighted = virtual_player_count_weighted() rivals_count = 1 # self.get_rivals_count(data) win = 0 succeeded_sample = 0 start = time.time() # TODO: Remove small rivals if board_cards_to_draw: n = sim_num index = 10 for iteration in range(n // rivals_count): simulate_cards, _ = self.exclude_impossible_rivals_lookup(deck, board_cards_to_draw, rivals_count) o_board_sample = o_board_cards + simulate_cards[:board_cards_to_draw] my_rank = eval7.evaluate(o_board_sample + o_hole_cards) won = True for i in range(board_cards_to_draw, board_cards_to_draw + 2 * rivals_count, 2): if my_rank < eval7.evaluate(o_board_sample + simulate_cards[i:i + 2]): won = False break if won: win += 1 succeeded_sample += 1 if iteration == index: print("==== sampling result ==== win : %d, total : %d, probability : %f, takes: %f seconds" % (win, succeeded_sample, win / succeeded_sample, time.time() - start)) index *= 10 else: my_rank = eval7.evaluate(o_board_cards + o_hole_cards) n = sim_num index = 10 for iteration in range(n // rivals_count): won = True simulate_cards, _ = self.exclude_impossible_rivals_lookup(deck, 0, rivals_count) # simulate_cards = deck.sample(2 * rivals_count) for i in range(0, 2 * rivals_count, 2): if my_rank < eval7.evaluate(o_board_cards + simulate_cards[i:i + 2]): won = False break if won: win += 1 succeeded_sample += 1 if iteration == index: print("==== sampling result ==== win : %d, total : %d, probability : %f, takes: %f seconds" % (win, succeeded_sample, win / succeeded_sample, time.time() - start)) index *= 10 print("==== sampling result ==== win : %d, total : %d, probability : %f, takes: %f seconds" % (win, succeeded_sample, win / succeeded_sample, time.time() - start)) return win / succeeded_sample
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"