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 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 load_all_hands(): try: array_path = os.path.dirname(os.path.abspath(__file__)) + "/array_storage" all_possible_hands = [[eval7.Card(each[0]), eval7.Card(each[1])] for each in numpy.load(array_path + "/sorted_starting_hands.npy")] except: array_path = os.path.dirname(os.path.abspath(__file__)) + "/../array_storage" all_possible_hands = [[eval7.Card(each[0]), eval7.Card(each[1])] for each in numpy.load(array_path + "/sorted_starting_hands.npy")] return [[each, 1] for each in all_possible_hands]
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 __init__(self): suits = ['c', 'd', 'h', 's'] values = ['2', '3', '4', '5', '6', '7', '8', '9', 'T', 'J', 'Q', 'K', 'A'] perm = [values[i] for i in self.permute_values()] # create global permutation dictionary global PERM PERM = {eval7.Card(values[i % 13] + suits[i // 13]) : eval7.Card(perm[i % 13] + suits[i // 13]) for i in range(52)} self.log = ['6.176 MIT Pokerbots - ' + PLAYER_1_NAME + ' vs ' + PLAYER_2_NAME, '---------------------------', ' ' + ' '.join(values) + ' ', '[' + ' '.join(perm) + ']', '---------------------------',] self.player_messages = [[], []]
def query_board(self, board_state, clause, game_log, button, stacks): ''' Parses one action from the pokerbot for a specific board. ''' legal_actions = board_state.legal_actions( button, stacks) if isinstance(board_state, BoardState) else {CheckAction} action = DECODE[clause[1]] if action in legal_actions: if clause[1] == 'R': amount = int(clause[2:]) min_raise, max_raise = board_state.raise_bounds(button, stacks) # print(amount) # print(min_raise <= amount <= max_raise) # print("MIN RAISE:", min_raise, "MAX RAISE:", max_raise) if min_raise <= amount <= max_raise: return action(amount) elif clause[1] == 'A': cards_strings = clause[2:].split(',') cards = [eval7.Card(s) for s in cards_strings] return action(cards) else: return action() game_log.append(self.name + ' attempted illegal ' + action.__name__) return CheckAction() if CheckAction in legal_actions else FoldAction()
def test_pickle(self): for i, rank in enumerate(eval7.ranks): for suit in eval7.suits: card = eval7.Card(rank + suit) pickled = pickle.dumps(card) card2 = pickle.loads(pickled) self.assertEqual(card, card2)
def __init__(self): ''' Called when a new game starts. Called exactly once. Arguments: Nothing. Returns: Nothing. ''' self.VALUES = [ '2', '3', '4', '5', '6', '7', '8', '9', 'T', 'J', 'Q', 'K', 'A' ] self.wins_dict = {v: 1 for v in self.VALUES} self.showdowns_dict = {v: 2 for v in self.VALUES} values = list('23456789TJQKA') suits = list('cdhs') self.proposal_perms = [] for j in range(1000): # proposal_perm is a list with entries from 0 to 12 proposal_perm = self.permute_values() perm_dict = {} for i, v in enumerate(values): for s in suits: card = v + s permuted_i = proposal_perm[i] permuted_v = values[permuted_i] permuted_card = eval7.Card(permuted_v + s) perm_dict[card] = permuted_card # we've gone through the whole deck self.proposal_perms.append(perm_dict)
def __init__(self): ''' Called when a new game starts. Called exactly once. Arguments: Nothing. Returns: Nothing. ''' #nothing in here counts towards 30 seconds self.VALUES = ['2', '3', '4', '5', '6', '7', '8', '9', 'T', 'J', 'Q', 'K', 'A'] self.SUITS = list('cdhs') self.wins_dict = {v : 1 for v in self.VALUES} self.showdowns_dict = {v : 2 for v in self.VALUES} self.proposal_perms = [] for j in range(1000): #play around wiht number proposal_perm = self.permute_values() #list with entries [0,12] perm_dict = {} for i, v in enumerate(self.VALUES): for s in self.SUITS: card = v+s permuted_i = proposal_perm[i] permuted_v = self.VALUES[permuted_i] permuted_card = eval7.Card(permuted_v+s) perm_dict[card] = permuted_card self.proposal_perms.append(perm_dict) perm_mistakes = {} #narrow down to best perms; instead of weeding further, track the nums that they get wrong
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 move(self, hero_hand=None): if hero_hand is None: raise Exception("Give hero hand for move") hh = [eval7.Card(c) for c in hero_hand] self.hero_hand = hh return self.strategy.move(self)
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 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 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 pdict(perm): ''' Generates a permutation dictionary given a permutation. ''' perm_dict = {} for i, v in enumerate(ranks): for s in suits: card = v + s permuted_i = perm[i] permuted_v = ranks[permuted_i] permuted_card = eval7.Card(permuted_v + s) perm_dict[card] = permuted_card return perm_dict
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 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 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 adjust_ranges(self): if not self.adjusted[0]: # Initial reset - Button, Blinds, How many players self.button = self.game_state_history[0][1] self.players = self.game_state_history[1] self.player_bets = [0 for _ in range(0, len(self.players))] self.small_blind = self.game_state_history[2][3] self.player_bets[self.game_state_history[2][0]] = self.small_blind self.big_blind = self.game_state_history[3][3] self.player_bets[self.game_state_history[3][0]] = self.big_blind # First 5 lines are adjusted: Button, Players, preflop self.adjusted[0:4] = [True for _ in range(0, 4)] self.player_ranges.sort([], self.players) for i, action in enumerate(self.game_state_history[4:]): if not self.adjusted[i+4]: if action[0] == "board": self.betting_round += 1 self.board = [eval7.Card(c) for c in action[1]] # Board is the next line after stage indicator self.player_ranges.filter(self.board) self.player_ranges.sort(self.board, self.players) self.pot += sum(self.player_bets) # collecting the pot - money/ not weed self.player_bets = [0 for _ in range(0, len(self.players))] # resetting bets to 0 - everything went to pot self.adjusted[i + 4] = True continue print(action) player, player_name, move, bet_size = tuple(action) if "fold" in move: self.players[player] = 0 self.adjusted[i + 4] = True continue self.strategy.adjust_range(self) self.player_bets[player] = bet_size self.adjusted[i+4] = True
def __init__(self): ''' Called when a new game starts. Called exactly once. Arguments: Nothing. Returns: Nothing. ''' self.t = 1 self.islists = False self.lists = [] self.cards = [ '2', '3', '4', '5', '6', '7', '8', '9', 'T', 'J', 'Q', 'K', 'A' ] values = list('23456789TJQKA') suits = list('cdhs') self.proposal_perms = [] for j in range(20000): # proposal_perm is a list with entries from 0 to 12 proposal_perm = self.permute_values() perm_dict = {} for i, v in enumerate(values): for s in suits: card = v + s permuted_i = proposal_perm[i] permuted_v = values[permuted_i] permuted_card = eval7.Card(permuted_v + s) perm_dict[card] = permuted_card # we've gone through the whole deck self.proposal_perms.append(perm_dict) self.values = [ '2', '3', '4', '5', '6', '7', '8', '9', 'T', 'J', 'Q', 'K', 'A' ] self.nodes = [ '2', '3', '4', '5', '6', '7', '8', '9', 'T', 'J', 'Q', 'K', 'A' ] self.edges = [] self.carddict = PreFlopStrat()
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 sort(self, board=[], has_cards=None): if len(board) > 0: if isinstance(board[0], str): hands_2_score_dict = self.hands_2_scores(board=[eval7.Card(c) for c in board], has_cards=has_cards) else: hands_2_score_dict = self.hands_2_scores(board=board, has_cards=has_cards) else: hands_2_score_dict = self.hands_2_scores(board=[], has_cards=has_cards) def key_lookup(x): try: return hands_2_score_dict[tuple(x[0])] except: return hands_2_score_dict[tuple([x[0][1], x[0][0]])] for i in range(0, len(self.card_ranges)): self.card_ranges[i] = sorted(self.card_ranges[i], key=key_lookup, reverse=True)
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
def query_board(self, board_state, clause, game_log, active, stacks): ''' Parses one action from the pokerbot for a specific board. ''' legal_actions = board_state.legal_actions( active, stacks) if isinstance(board_state, BoardState) else {CheckAction} action = DECODE[clause[1]] if action in legal_actions: if clause[1] == 'R': amount = int(clause[2:]) max_raise = board_state.raise_bounds(active, stacks)[1] if board_state.pips[1 - active] < amount <= max_raise: return action(amount) elif board_state.pips[1 - active] == amount: return CallAction() elif clause[1] == 'A': cards_strings = clause[2:].split(',') cards = [eval7.Card(s) for s in cards_strings] return action(cards) else: return action() game_log.append(self.name + ' attempted illegal ' + action.__name__) return CheckAction() if CheckAction in legal_actions else FoldAction()
def translate_card(perm, card): i = ranks_rev[card[0]] permuted_i = perm[i] permuted_v = ranks[permuted_i] return eval7.Card(permuted_v + card[1])
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 __init__(self, existing_deck): self.cards = [eval7.Card(str(card)) for card in existing_deck.cards]
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"