def get_actions(self, game_state, round_state, active): ''' Where the magic happens - your code should implement this function. Called any time the engine needs a triplet of actions from your bot. Arguments: game_state: the GameState object. round_state: the RoundState object. active: your player's index. Returns: Your actions. ''' 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, turn, or river respectively my_cards = round_state.hands[active] # your cards across all boards board_cards = [board_state.deck if isinstance(board_state, BoardState) else board_state.previous_state.deck for board_state in round_state.board_states] #the board cards my_pips = [board_state.pips[active] if isinstance(board_state, BoardState) else 0 for board_state in round_state.board_states] # the number of chips you have contributed to the pot on each board this round of betting opp_pips = [board_state.pips[1-active] if isinstance(board_state, BoardState) else 0 for board_state in round_state.board_states] # the number of chips your opponent has contributed to the pot on each board this round of betting continue_cost = [opp_pips[i] - my_pips[i] for i in range(NUM_BOARDS)] #the number of chips needed to stay in each board's pot 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 stacks = [my_stack, opp_stack] net_upper_raise_bound = round_state.raise_bounds()[1] # max raise across 3 boards net_cost = 0 # keep track of the net additional amount you are spending across boards this round my_actions = [None] * NUM_BOARDS for i in range(NUM_BOARDS): print("bot reached street", street) if AssignAction in legal_actions[i]: cards = self.board_allocations[i] my_actions[i] = AssignAction(cards) if street < 3: if CheckAction in legal_actions[i]: # check-call my_actions[i] = CheckAction() elif CallAction in legal_actions[i]: my_actions[i] = CallAction() else: #self.calculate_strength(self.board_allocations[i], board_cards, 100) if RaiseAction(stacks[0]/3) in legal_actions[i]: my_actions[i] = RaiseAction(stacks[0]/3) elif CallAction in legal_actions[i]: my_actions[i] = CallAction() elif RaiseAction(stacks[0]) in legal_actions[i]: my_actions[i] = RaiseActions(stack[0]) elif CheckAction in legal_actions[i]: my_actions[i] = CheckAction() else: my_actions[i] = FoldAction() return my_actions
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, turn, or river 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 if CheckAction in legal_actions: # check-call return CheckAction() return CallAction()
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 # STRATEGY: fold-to-win if possible, otherwise shove 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() if len(legal_actions) == 1: return legal_actions.pop()() # SHOVE 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()
def get_actions(self, game_state, round_state, active): ''' Where the magic happens - your code should implement this function. Called any time the engine needs a triplet of actions from your bot. Arguments: game_state: the GameState object. round_state: the RoundState object. active: your player's index. Returns: Your actions. ''' 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, turn, or river respectively my_cards = round_state.hands[active] # your cards across all boards board_cards = [board_state.deck if isinstance(board_state, BoardState) else board_state.previous_state.deck for board_state in round_state.board_states] #the board cards my_pips = [board_state.pips[active] if isinstance(board_state, BoardState) else 0 for board_state in round_state.board_states] # the number of chips you have contributed to the pot on each board this round of betting opp_pips = [board_state.pips[1-active] if isinstance(board_state, BoardState) else 0 for board_state in round_state.board_states] # the number of chips your opponent has contributed to the pot on each board this round of betting continue_cost = [opp_pips[i] - my_pips[i] for i in range(NUM_BOARDS)] #the number of chips needed to stay in each board's pot 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 stacks = [my_stack, opp_stack] net_upper_raise_bound = round_state.raise_bounds()[1] # max raise across 3 boards net_cost = 0 # keep track of the net additional amount you are spending across boards this round my_actions = [None] * NUM_BOARDS for i in range(NUM_BOARDS): if AssignAction in legal_actions[i]: cards = self.board_allocations[i] #assign our cards that we made earlier my_actions[i] = AssignAction(cards) #add to our actions elif isinstance(round_state.board_states[i], TerminalState): #make sure the game isn't over at this board my_actions[i] = CheckAction() #check if it is else: #do we add more resources? board_cont_cost = continue_cost[i] #we need to pay this to keep playing board_total = round_state.board_states[i].pot #amount before we started betting pot_total = my_pips[i] + opp_pips[i] + board_total #total money in the pot right now min_raise, max_raise = round_state.board_states[i].raise_bounds(active, round_state.stacks) strength = self.hole_strengths[i] if street < 3: #pre-flop raise_ammount = int(my_pips[i] + board_cont_cost + 0.4 * (pot_total + board_cont_cost)) #play a little conservatively pre-flop else: raise_ammount = int(my_pips[i] + board_cont_cost + 0.75 * (pot_total + board_cont_cost)) #raise the stakes deeper into the game raise_ammount = max([min_raise, raise_ammount]) #make sure we have a valid raise raise_ammount = min([max_raise, raise_ammount]) raise_cost = raise_ammount - my_pips[i] #how much it costs to make that raise if RaiseAction in legal_actions[i] and (raise_cost <= my_stack - net_cost): #raise if we can and if we can afford it commit_action = RaiseAction(raise_ammount) commit_cost = raise_cost elif CallAction in legal_actions[i] and (board_cont_cost <= my_stack - net_cost): #call if we can afford it! commit_action = CallAction() commit_cost = board_cont_cost #the cost to call is board_cont_cost elif CheckAction in legal_actions[i]: #try to check if we can commit_action = CheckAction() commit_cost = 0 else: #we have to fold commit_action = FoldAction() commit_cost = 0 if board_cont_cost > 0: #our opp raised!!! we must respond if board_cont_cost > 5: #<--- parameters to tweak. _INTIMIDATION = 0.15 strength = max([0, strength - _INTIMIDATION]) #if our opp raises a lot, be cautious! pot_odds = board_cont_cost / (pot_total + board_cont_cost) if strength >= pot_odds: #Positive Expected Value!! at least call!! if strength > 0.5 and random.random() < strength: #raise sometimes, more likely if our hand is strong my_actions[i] = commit_action net_cost += commit_cost else: # try to call if we don't raise if (board_cont_cost <= my_stack - net_cost): #we call because we can afford it and it's +EV my_actions[i] = CallAction() net_cost += board_cont_cost else: #we can't afford to call :( should have managed our stack better my_actions[i] = FoldAction() net_cost += 0 else: #Negative Expected Value!!! FOLD!!! my_actions[i] = FoldAction() net_cost += 0 else: #board_cont_cost == 0, we control the action if random.random() < strength: #raise sometimes, more likely if our hand is strong my_actions[i] = commit_action net_cost += commit_cost else: #just check otherwise my_actions[i] = CheckAction() net_cost += 0 return my_actions
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 pot_after_continue = my_contribution + opp_contribution + continue_cost 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 # if game_state.round_num == NUM_ROUNDS: # print(self.edges) if my_stack == 0: return CheckAction() # cards = my_cards # if street==0 and self.preflop == 0:#pre flop strategy # if cards[0][0]==cards[1][0]:#pairs # return RaiseAction(pot_after_continue/2) # if cards[0][0]==self.values[12] or cards[1][0]==self.values[12]: #rwhenever there is an Ace # return RaiseAction(pot_after_continue/2) # elif cards[0][1]!=cards[1][1]:#different suit absolutes # if self.values.index(cards[0][0])+self.values.index(cards[1][0])<10:#folding on low values # return CheckAction() if CheckAction in legal_actions else FoldAction() # elif self.values.index(cards[0][0])+self.values.index(cards[1][0])>16: # return RaiseAction(pot_after_continue/2) # elif cards[0][0]==self.values[8] and cards[1][0]==self.values[3]: # return CheckAction() if CheckAction in legal_actions else FoldAction() # elif cards[0][0]==self.values[3] and cards[1][0]==self.values[8]: # return CheckAction() if CheckAction in legal_actions else FoldAction() # elif cards[0][0]==self.values[8] and cards[1][0]==self.values[2]: # return RaiseAction(pot_after_continue/2) # elif cards[0][0]==self.values[2] and cards[1][0]==self.values[8]: # return RaiseAction(pot_after_continue/2) # elif cards[0][0]==self.values[7] and cards[1][0]==self.values[3]: # return RaiseAction(pot_after_continue/2) # elif cards[0][0]==self.values[3] and cards[1][0]==self.values[7]: # return RaiseAction(pot_after_continue/2) # elif cards[0][1]==cards[1][1]:#same suit absolutes # if cards[0][0]==self.values[0] or cards[1][0]==self.values[0]: # if self.values.index(cards[0][0])+self.values.index(cards[1][0]) < 9: #folding on low values # return CheckAction() if CheckAction in legal_actions else FoldAction() # elif self.values.index(cards[0][0])+self.values.index(cards[1][0])>11:#raising high # return RaiseAction(pot_after_continue/2) # elif cards[0][0]==self.values[1] or cards[1][0]==self.values[1]: # if self.values.index(cards[0][0])+self.values.index(cards[1][0])<11: # if self.values.index(cards[0][0])+self.values.index(cards[1][0])>4: # return CheckAction() if CheckAction in legal_actions else FoldAction() # elif cards[0][0]==self.values[6] and cards[1][0]==self.values[5]: # return RaiseAction(pot_after_continue/2) # elif cards[0][0]==self.values[5] and cards[1][0]==self.values[6]: # return RaiseAction(pot_after_continue/2) # elif cards[0][0]==self.values[5] and cards[1][0]==self.values[4]: # return RaiseAction(pot_after_continue/2) # elif cards[0][0]==self.values[4] and cards[1][0]==self.values[5]: # return RaiseAction(pot_after_continue/2) # elif active==True:#big blind # return CheckAction() if CheckAction in legal_actions else CallAction() # else:#small blind # return RaiseAction(pot_after_continue/2) #maybe call under 10 value # self.preflop += 1 # elif street == 0 and self.preflop > 0: # return CheckAction() if CheckAction in legal_actions else CallAction() # else: # #after flop # if street == 3: # if self.checkFlush(my_cards, board_cards) or self.check3ofKind(my_cards, board_cards) or self.check2Pair(my_cards, board_cards) or (self.checkPair(my_cards, board_cards) != False and self.values.index(self.checkPair(my_cards, board_cards)) >= 9): # return RaiseAction(max_raise) # if self.checkFlush(my_cards, board_cards) or self.check3ofKind(my_cards, board_cards): # return RaiseAction(pot_after_continue) # elif self.checkPair(my_cards, board_cards): # return RaiseAction(pot_after_continue/2) # elif self.values.index(self.highCard(my_cards, [])) >10: # return CallAction() if continue_cost < my_contribution else FoldAction() highCard = self.highCard(my_cards, []) lowCard = my_cards[0][0] if my_cards[0][0] != highCard else my_cards[1][0] suited = 's' if my_cards[0][1] == my_cards[1][1] else 'o' if my_stack == 0: return CheckAction() starting_amount=25
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 if street==0:#pre flop strategy if cards[0][0]==cards[1][0]:#pairs return RaiseAction() if cards[0][0]==self.values[12] or cards[1][0]==self.values[12]:#rwhenever there is an Ace return RaiseAction() elif cards[0][1]!=cards[1][1]:#different suit absolutes if self.values.index[cards[0][0]]+self.values.index[cards[1][0]]<10:#folding on low values return FoldAction() elif self.values.index[cards[0][0]]+self.values.index[cards[1][0]]>16: return RaiseAction() elif cards[0][0]==self.values[8] and cards[1][0]==self.values[3]: return FoldAction() elif cards[0][0]==self.values[3] and cards[1][0]==self.values[8]: return FoldAction() elif cards[0][0]==self.values[8] and cards[1][0]==self.values[2]: return RaiseAction() elif cards[0][0]==self.values[2] and cards[1][0]==self.values[8]: return RaiseAction() elif cards[0][0]==self.values[7] and cards[1][0]==self.values[3]: return RaiseAction() elif cards[0][0]==self.values[3] and cards[1][0]==self.values[7]: return RaiseAction() elif cards[0][1]==cards[1][1]:#same suit absolutes if cards[0][0]==self.values[0] or if cards[1][0]==self.values[0]: if self.values.index[cards[0][0]]+self.values.index[cards[1][0]]<9#folding on low values return FoldAction() elif self.values.index[cards[0][0]]+self.values.index[cards[1][0]]>11:#raising high return RaiseAction() elif cards[0][0]==self.values[1] or cards[1][0]==self.values[1]: if self.values.index[cards[0][0]]+self.values.index[cards[1][0]]<11: if self.values.index[cards[0][0]]+self.values.index[cards[1][0]]>4: return FoldAction() elif cards[0][0]==self.values[6] and cards[1][0]==self.values[5]: return RaiseAction() elif cards[0][0]==self.values[5] and cards[1][0]==self.values[6]: return RaiseAction() elif cards[0][0]==self.values[5] and cards[1][0]==self.values[4]: return RaiseAction() elif cards[0][0]==self.values[4] and cards[1][0]==self.values[5]: return RaiseAction() #code to be copied in small and big for kings w 2-8 w opposite elif active==True:#big blind return CallAction() else:#small blind return RaiseAction() #maybe call under 10 value #yellow=[jack opp 7-10, diff 13 and up, same 5 and 4] #red=[ rest of diff, same 2 and 3] #green=[rest of same] #if cards[0][0]==self.values[0] and cards[1][0]==self.values[10] and cards[0][1]==cards[1][1]: #small blind goes second #call=match check=next raise=big fold=quit #green raise #yellow small raie big call #light orange small call red call #dark orange small call red fold #red fold fold if CheckAction in legal_actions: # check-call return CheckAction() return CallAction()
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, turn, or river 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 we haven't computed EV yet on this street, do so. if street not in self._street_ev: self._street_ev[street] = self._pf.ComputeEvRandom( "".join(my_cards), "".join(board_cards), "", self._compute_ev_samples, self._compute_ev_iters) EV = self._street_ev[street] if self._pf.Nonzero() <= 0: print("Particle filter empty, checkfolding") return CheckAction if CheckAction in legal_actions else FoldAction( ) pot_size = my_contribution + opp_contribution 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 # CASE 1: Don't need to call. if CheckAction in legal_actions: if EV <= 0.5 or RaiseAction not in legal_actions: return CheckAction() elif EV <= 0.8: return RaiseAction(min(max(pot_size, min_raise), max_raise)) else: return RaiseAction(max_raise) # CASE 2: Must call to continue. else: pot_after_call = 2 * opp_contribution equity = EV * pot_after_call # If calling costs more than the expected payout after calling, fold. if equity < continue_cost: return FoldAction() else: # Do a pot raise. if EV >= 0.8: return RaiseAction( min(max(pot_after_call, min_raise), max_raise) ) if RaiseAction in legal_actions else CallAction() elif EV >= 0.9: return RaiseAction( min(max(2 * pot_after_call, min_raise), max_raise) ) if RaiseAction in legal_actions else CallAction() else: return CallAction()
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 if my_cards[0][0] == my_cards[1][0]: return RaiseAction(min_raise) elif BetAction in legal_actions: if my_cards[0][0] == my_cards[1][0]: return BetAction(my_contribution * 2) for i in range(street): if my_cards[0][0] == board_cards[i][0] or my_cards[1][ 0] == board_cards[i][0]: if RaiseAction in legal_actions: return RaiseAction(min_raise) elif BetAction in legal_actions: return BetAction(my_contribution * 2) if game_state.round_num > 100: card1_value = self.cards_won[my_cards[0][0]] / self.cards_played[ my_cards[0][0]] card2_value = self.cards_won[my_cards[1][0]] / self.cards_played[ my_cards[1][0]] if card1_value > .5 and card2_value > .5: if RaiseAction in legal_actions: return RaiseAction(min_raise) if card1_value < .5 and card2_value < .5: if FoldAction in legal_actions: return FoldAction() else: return CheckAction() if CheckAction in legal_actions: # check-call return CheckAction() return CallAction()
def check_fold(): if CheckAction in legal_actions: return CheckAction() return FoldAction()
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 # if game_state.round_num == NUM_ROUNDS: # print(self.edges) # if self.CHECK_CALL: # return CheckAction() if CheckAction in legal_actions else CallAction() if my_stack == 0: return CheckAction() ` if self.winOut: return CheckAction() if CheckAction in legal_actions else FoldAction() if ShakeOpponent()==True: if CallAction in legal_actions: return CallAction() elif ShakeOpponent()==False: if RaiseAction in legal_actions: return RaiseAction(max_raise-1) self.total_continue_cost+=continue_cost self.total_times+=1
def HeadsUpStrategyJay(self, game_state, round_state, active): 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 pot_after_continue = my_contribution + opp_contribution + continue_cost 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 if self.winOut: return CheckAction() if CheckAction in legal_actions else FoldAction() board_cards = previous_state.deck[:street] my_high = self.highCard(my_cards, []) board_high = self.highCard([], board_cards) my_pair = self.checkPair(my_cards, board_cards) my_2pair = self.check2Pair(my_cards, board_cards) my_3ofKind = self.check3ofKind(my_cards, board_cards) my_straight = self.checkStraight(my_cards, board_cards) my_flush = self.checkFlush(my_cards, board_cards) my_fullHouse = True if my_3ofKind != False and my_2pair != False else False my_4ofKind = False #TODO my_straightFlush = True if my_straight and my_flush else False my_besthand = None if my_straightFlush != False: my_besthand = 'sf' elif my_fullHouse != False: my_besthand = 'fh' elif my_flush != False: my_besthand = 'f' elif my_straight != False: my_besthand = 's' elif my_3ofKind != False: my_besthand = '3' elif my_2pair != False: my_besthand = '2' elif my_pair != False: my_besthand = '1' else: my_besthand = 'h' agressive = True highCard = self.highCard(my_cards, []) lowCard = my_cards[0][0] if my_cards[0][0] != highCard else my_cards[1][0] suited = 's' if my_cards[0][1] == my_cards[1][1] else 'o' my_rank = self.handRankingDict[(self.values.index(lowCard), self.values.index(highCard)), suited] if agressive: small_preflop = [10 + 5 * random.gauss(0,1), 40 + 10 * random.gauss(0,1), 100 + 10 * random.gauss(0,1)] big_preflop = [10 + 5 * random.gauss(0,1), 30 + 10 * random.gauss(0,1), 80 + 10 * random.gauss(0,1)] else: small_preflop = [10 + 5 * random.gauss(0,1), 30 + 10 * random.gauss(0,1), 60 + 10 * random.gauss(0,1)] big_preflop = [10 + 5 * random.gauss(0,1), 20 + 10 * random.gauss(0,1), 50 + 10 * random.gauss(0,1)] if street == 0: if my_pip == 1: #small blind goes first pre flop if my_rank < small_preflop[0]: return RaiseAction(min_raise) if my_rank < small_preflop[1]: return RaiseAction(5) elif my_rank < small_preflop[2]: return RaiseAction(min_raise) elif my_rank < 120: return CallAction() else: return FoldAction() elif my_pip == 2: #big blind goes second preflop if continue_cost == 0: #they limped if my_rank < big_preflop[0]: return CallAction() elif my_rank < big_preflop[1]: return RaiseAction(5) elif my_rank < big_preflop[2]: return CallAction() else: return FoldAction() else: if continue_cost <= 5: if my_rank < big_preflop[1]-10: return RaiseAction((continue_cost + 1) * 2) elif my_rank < big_preflop[2]-10: return CallAction() else: return FoldAction() elif continue_cost <= 25: if my_rank < big_preflop[1]-15: return RaiseAction(min_cost * 2) elif my_rank < big_preflop[2]-30: return CallAction() else: return FoldAction() elif continue_cost <= 100: if my_rank < big_preflop[1]-20: return RaiseAction(min_cost) elif my_rank < big_preflop[2]-50: return CallAction() else: return FoldAction() elif continue_cost <= max_cost: if my_rank <= 9: return CallAction() else: return FoldAction() else: #they 3-bet (small blind) or 4-bet (big blind) us if self.big_blind: if continue_cost <= 10: if my_rank < big_preflop[1]-15: return RaiseAction((continue_cost + 1) * 2) elif my_rank < big_preflop[2]-25: return CallAction() else: return FoldAction() elif continue_cost <= 25: if my_rank < big_preflop[1]-20: return RaiseAction(min_cost * 2) elif my_rank < big_preflop[2]-30: return CallAction() else: return FoldAction() elif continue_cost <= 100: if my_rank < big_preflop[1]-25: return RaiseAction(min_cost) elif my_rank < big_preflop[2]-60: return CallAction() else: return FoldAction() elif continue_cost <= max_cost: if my_rank <= 6: return CallAction() else: return FoldAction() else: if continue_cost <= 10: if my_rank < big_preflop[1]-15: return RaiseAction((continue_cost + 1) * 2) elif my_rank < big_preflop[2]-25: return CallAction() else: return FoldAction() elif continue_cost <= 25: if my_rank < big_preflop[1]-20: return RaiseAction(min_cost * 2) elif my_rank < big_preflop[2]-50: return CallAction() else: return FoldAction() elif continue_cost <= 100: if my_rank < big_preflop[1]-30: return RaiseAction(min_cost) elif my_rank < big_preflop[2]-80: return CallAction() else: return FoldAction() elif continue_cost <= max_cost: if my_rank <= 6: return CallAction() else: return FoldAction() else: pass
def get_actions(self, game_state, round_state, active): ''' Where the magic happens - your code should implement this function. Called any time the engine needs a triplet of actions from your bot. Arguments: game_state: the GameState object. round_state: the RoundState object. active: your player's index. Returns: Your actions. ''' 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, turn, or river respectively my_cards = round_state.hands[active] # your cards across all boards # board_cards = [board_state.deck if isinstance(board_state, BoardState) else board_state.previous_state.deck for board_state in round_state.board_states] #the board cards # my_pips = [board_state.pips[active] if isinstance(board_state, BoardState) else 0 for board_state in round_state.board_states] # the number of chips you have contributed to the pot on each board this round of betting # opp_pips = [board_state.pips[1-active] if isinstance(board_state, BoardState) else 0 for board_state in round_state.board_states] # the number of chips your opponent has contributed to the pot on each board this round of betting # continue_cost = [opp_pips[i] - my_pips[i] for i in range(NUM_BOARDS)] #the number of chips needed to stay in each board's pot # 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 # stacks = [my_stack, opp_stack] # net_upper_raise_bound = round_state.raise_bounds()[1] # max raise across 3 boards # net_cost = 0 # keep track of the net additional amount you are spending across boards this round my_actions = [None] * NUM_BOARDS high_cards = [] for card in my_cards: if (card[0] == 'A' or card[0] == 'J' or card[0] == 'Q' or card[0] == 'K'): high_cards.append(card) not_high_cards_set = set(my_cards) - set(high_cards) not_high_cards = list(not_high_cards_set) if len( high_cards ) == 2: # if we have a pair of high cards, then make sure they're both on the third board self.board_allocations[2] = high_cards[0:2] self.board_allocations[0] = not_high_cards[0:2] self.board_allocations[1] = not_high_cards[2:4] elif len( high_cards ) == 1: # if we have one high card, then make sure it's on the third board self.board_allocations[2] = [high_cards[0], []] self.board_allocations[0] = not_high_cards[0:2] self.board_allocations[1] = not_high_cards[2:4] self.board_allocations[2][1] = not_high_cards[4] elif len(high_cards) == 4: # big money self.board_allocations[2] = high_cards[0:2] self.board_allocations[1] = high_cards[2:4] self.board_allocations[0] = not_high_cards[0:2] else: self.board_allocations[2] = my_cards[0:2] self.board_allocations[0] = my_cards[2:4] self.board_allocations[1] = my_cards[4:6] for i in range(NUM_BOARDS): if AssignAction in legal_actions[i]: my_actions[i] = AssignAction(self.board_allocations[i]) elif CheckAction in legal_actions[i]: # check-call my_actions[i] = CheckAction() else: my_actions[i] = CallAction() print(my_cards) return my_actions
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 print(game_state.bankroll, NUM_ROUNDS, game_state.round_num) 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 my_hand_trans = [ ALL_RANKS[self.value_ranks[c[0]]] + c[1] for c in my_hand ] my_hand_trans_e7 = convert_e7(my_hand_trans) trans_board = [ALL_RANKS[self.value_ranks[c[0]]] + c[1] for c in board] board_trans_e7 = convert_e7(trans_board) print(my_hand, board) print(my_hand_trans, trans_board, '(translated)') # raise sizes # these are parameters to be tweaked (maybe by stats on opponent) if street == 0: RAISE_SIZE = 1 # raise (1x)pot else: RAISE_SIZE = 0.75 # bet 3/4 pot if street == 0: equity = get_preflop_equity(my_hand_trans_e7, self.opponent_range) print(f'Preflop equity {equity}') else: equity = eval7.py_hand_vs_range_monte_carlo( my_hand_trans_e7, get_v_range(self.opponent_range), board_trans_e7, self.N_MCMC) print(f'Postflop equity {equity}') if my_pip == 1 and street == 0: pot_odds = 0.4 raise_odds = 0.45 if opp_pip > my_pip: self.opponent_range *= 0.5 else: pot = 2 * my_contribution bet = opp_pip - my_pip pot_odds = bet / (pot + 2 * bet) raise_amt = int(RAISE_SIZE * pot) + opp_pip raise_odds = raise_amt / (pot + 2 * raise_amt) print('pot odds = ', pot_odds, 'raise odds = ', raise_odds) if equity > raise_odds and opp_contribution < STARTING_STACK: raise_size = min(int(opp_pip + RAISE_SIZE * 2 * opp_contribution), my_pip + my_stack) print('RAISE:', raise_size) return RaiseAction(raise_size) elif equity > pot_odds and opp_pip > my_pip: print('CALL') return CallAction() elif my_pip == opp_pip: print('CHECK') return CheckAction() else: return FoldAction()
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 pot_after_continue = my_contribution+opp_contribution+continue_cost 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 first_card_winrate = self.wins_dict[my_cards[0][0]] / self.showdowns_dict[my_cards[0][0]] second_card_winrate = self.wins_dict[my_cards[1][0]] / self.showdowns_dict[my_cards[1][0]] winrates = [first_card_winrate, second_card_winrate] #how often board cards match pocket cards agree_counts = [0,0] raise_amount = my_pip + continue_cost + int(0.77 * pot_after_continue) raise_amount = min(raise_amount, max_raise) raise_amount = max(raise_amount, min_raise) if len(self.proposal_perms) <= 5: royal_flush = 135004160 straight_flush = 134610944 low_pair = 16820320 high_pair = 34342912 highest_card = 829538 #print(eval7.evaluate([eval7.Card("Ad"), eval7.Card("7h"), eval7.Card("2c"), eval7.Card("Ah"),eval7.Card("Td"),eval7.Card("2h"),eval7.Card("5c")])) if round_state.street==5: #permute the hand and bet according to the scores running_score = 0 for perm in self.proposal_perms: hand = [perm[i] for i in board_cards] my_perm_cards = [perm[c] for c in my_cards] hand.extend(my_perm_cards) score = eval7.evaluate(hand) running_score+=score # if score==royal_flush or score>=straight_flush: # return RaiseAction(max_raise) running_score = running_score/len(self.proposal_perms) if running_score<low_pair: #random.randrange(highest_card,royal_flush): if FoldAction in legal_actions: return FoldAction() elif running_score>=high_pair: if RaiseAction in legal_actions: return RaiseAction(raise_amount) else: for card in board_cards: for i in range(2): if my_cards[i][0]==card[0]: agree_counts[i]+=1 #two pair or better if sum(agree_counts)>=2: #definitely raise return RaiseAction(raise_amount) #one pair in first card if agree_counts[0]==1: if random.random()<winrates[0]: return RaiseAction(raise_amount) #one pair in seond card if agree_counts[1]==1: if random.random()<winrates[1]: return RaiseAction(raise_amount) #high pocket pairs are extremely good if my_cards[0][0]==my_cards[1][0]: #pocket pair if random.random() < winrates[0]: return RaiseAction(raise_amount) if first_card_winrate > 0.5 and second_card_winrate > 0.5: return RaiseAction(raise_amount) if CheckAction in legal_actions: # check-call return CheckAction() return CallAction()
def get_actions(self, game_state, round_state, active): ''' Where the magic happens - your code should implement this function. Called any time the engine needs a triplet of actions from your bot. Arguments: game_state: the GameState object. round_state: the RoundState object. active: your player's index. Returns: Your actions. ''' 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, turn, or river respectively my_cards = round_state.hands[active] # your cards across all boards board_cards = [ board_state.deck if isinstance(board_state, BoardState) else board_state.previous_state.deck for board_state in round_state.board_states ] #the board cards my_pips = [ board_state.pips[active] if isinstance(board_state, BoardState) else 0 for board_state in round_state.board_states ] # the number of chips you have contributed to the pot on each board this round of betting opp_pips = [ board_state.pips[1 - active] if isinstance(board_state, BoardState) else 0 for board_state in round_state.board_states ] # the number of chips your opponent has contributed to the pot on each board this round of betting continue_cost = [ opp_pips[i] - my_pips[i] for i in range(NUM_BOARDS) ] #the number of chips needed to stay in each board's pot 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 stacks = [my_stack, opp_stack] net_upper_raise_bound = round_state.raise_bounds()[ 1] # max raise across 3 boards net_cost = 0 # keep track of the net additional amount you are spending across boards this round my_actions = [None] * NUM_BOARDS for i in range(NUM_BOARDS): if AssignAction in legal_actions[i]: cards = self.board_allocations[ i] #allocate our cards that we made earlier my_actions[i] = AssignAction(cards) #add to our actions elif (RaiseAction in legal_actions[i] and self.strong_hole): #only consider this if we're strong min_raise, max_raise = round_state.board_states[ i].raise_bounds( active, round_state.stacks ) #calulate the highest and lowest we can raise to max_cost = max_raise - my_pips[ i] #the cost to give the max raise if max_cost <= my_stack - net_cost: #make sure the max_cost is something we can afford! Must have at least this much left after our other costs my_actions[i] = RaiseAction(max_raise) #GO ALL IN!!! net_cost += max_cost elif CallAction in legal_actions[i]: # check-call my_actions[i] = CallAction() net_cost += continue_cost[i] else: my_actions[i] = CheckAction() elif CheckAction in legal_actions[i]: # check-call my_actions[i] = CheckAction() else: my_actions[i] = CallAction() net_cost += continue_cost[i] return my_actions
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() # Simple hardcoded / eval7 strategy. street = round_state.street my_hand = round_state.hands[active] board = round_state.deck[:street] # Pre-flop, raise pairs and suited for example PREFLOP_PAIR_SUITED_VALUE = 1.0 if street == 0: if my_hand[0][0] == my_hand[1][0] or my_hand[0][1] == my_hand[1][1]: mean_hand_val = PREFLOP_PAIR_SUITED_VALUE else: mean_hand_val = 0.0 # Post-flop, need to do some sims else: hand_ensemble = [] board_ensemble = [] for order in order_ensemble: hand_ensemble.append([ order[ALL_RANKS.index(card[0])] + card[1] for card in my_hand ]) board_ensemble.append([ order[ALL_RANKS.index(card[0])] + card[1] for card in board ]) # simply eval7 each translation TRIPS_UP_VALUE = 1.0 PAIR_UP_VALUE = 0.75 hand_vals = [] for hand, board in zip(hand_ensemble, board_ensemble): code = eval7.evaluate([eval7.Card(s) for s in hand + board]) handtype = code >> 24 if handtype >= 3: # we have something trips or higher hand_vals.append(TRIPS_UP_VALUE) elif handtype >= 1: # we have something pair or higher hand_vals.append(PAIR_UP_VALUE) else: hand_vals.append(0.0) mean_hand_val = np.mean(hand_vals) # bet our value (this is basically bogus) # value * (2*x + pot) = x # (1 - 2*value) x = value*pot # x = pot * value / (1-2*value). # Note: for value > 0.5, our bets go through infinty and negative. Instead, # run this all through a tanh function for stability (more bogus). my_stack = round_state.stacks[active] opp_stack = round_state.stacks[1 - active] pot = 2 * STARTING_STACK - my_stack - opp_stack bet = int(pot * mean_hand_val / (1 - np.tanh(mean_hand_val))) min_raise, max_raise = round_state.raise_bounds() my_pip = round_state.pips[active] opp_pip = round_state.pips[1 - active] call_cost = min_raise - my_pip if bet < min_raise: return check_fold() elif max_raise == 0: soft_assert(CheckAction in legal_actions) return CheckAction() elif RaiseAction in legal_actions: return RaiseAction(min(max_raise, bet + my_pip)) else: soft_assert(CallAction in legal_actions) return CallAction()
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 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. ''' ''' roundsleft = 1000-game_state.round_num necessarylead = 1.5*roundsleft if roundsleft % 2 == 1: if bool(active): necessarylead += 0.5 else: necessarylead -= 0.5 if(self.netgain > necessarylead): if CheckAction in round_state.legal_actions(): return CheckAction() return FoldAction() ''' legal_actions = round_state.legal_actions( ) # the actions you are allowed to take if legal_actions == {CheckAction}: return CheckAction() 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 pot_after_continue = my_contribution + opp_contribution + continue_cost pot_odds = continue_cost / pot_after_continue #namedtuple('_RoundState', ['button', 'street', 'pips', 'stacks', 'hands', 'deck', 'previous_state']) dict_values = np.array(round_state.previous_state) if dict_values.any() == None: dict_values = [0, 0, [0, 0], [0, 0], 0, 0, 0] dict_keys = [ 'button', 'street', 'pips', 'stacks', 'hands', 'deck', 'previous_state' ] previous_state = {} for i in range(len(dict_values)): previous_state[dict_keys[i]] = dict_values[i] last_round_opp_pip = previous_state['pips'][1 - active] last_round_pot_after_continue = (STARTING_STACK - previous_state['stacks'][active]) + \ (STARTING_STACK - previous_state['stacks'][1-active]) + \ previous_state['pips'][active] - previous_state['pips'][1-active] opp_reasonable_raise_amount = previous_state['pips'][active] + int( 0.75 * last_round_pot_after_continue) if opp_pip - last_round_opp_pip >= opp_reasonable_raise_amount * 2: self.big_raise_times += 1 allcard_winrate = self.compute_strength() #allcard_winrate = [self.wins_dict[x] / self.showdowns_dict[x] for x in self.VALUES] #[0.9,0.1,0.2,0.3] ind = list(np.argsort(allcard_winrate)) #[1,2,3,0] new_cards = [] for x in my_cards + board_cards: original_index = self.VALUES.index(x[0]) current_index = ind.index(original_index) y = self.VALUES[current_index] + x[1] #print(y) new_cards.append(y) my_cards = new_cards[:2] board_cards = new_cards[2:] first_card_strength = (self.VALUES.index(my_cards[0][0]) + 1) / len( self.VALUES) second_card_strength = (self.VALUES.index(my_cards[1][0]) + 1) / len( self.VALUES) card_strength = [first_card_strength, second_card_strength] agree_counts = [0, 0] for card in board_cards: # increase agree_counts each time values agree for i in range(2): if my_cards[i][0] == card[0]: agree_counts[i] += 1 FLUSH = False ABOUT_FLUSH = False OPP_FLUSH = False suit = [x[1] for x in board_cards] board_same_suits = max(suit.count('h'), suit.count('d'), suit.count('s'), suit.count('c')) suit.append(my_cards[0][1]) suit.append(my_cards[1][1]) hand_same_suits = max(suit.count('h'), suit.count('d'), suit.count('s'), suit.count('c')) if hand_same_suits >= 5 and board_same_suits <= 4: FLUSH == True if hand_same_suits >= 4 and street <= 3: ABOUT_FLUSH == True if hand_same_suits == board_same_suits and board_same_suits >= 3: OPP_FLUSH == True bluff_factor = 0 if self.big_raise_times / self.games_played >= 0.3: bluff_factor = self.big_raise_times / self.games_played / 2 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 raise_amount = my_pip + continue_cost + int( 0.75 * pot_after_continue) raise_amount = min(raise_amount, max_raise) raise_amount = max(raise_amount, min_raise) # FLUSH if FLUSH == True: return RaiseAction(raise_amount) # OPPO FLUSH if pot_odds >= 0.7 and bluff_factor < 0.05 and OPP_FLUSH == True: return FoldAction() # ABOUT FLUSH if ABOUT_FLUSH == True: if random.random() < 0.5: return RaiseAction(raise_amount) # THREE OF A KIND OR BETTER if agree_counts[0] >= 2 or agree_counts[1] >= 2: return RaiseAction(raise_amount) # TWO-PAIR if sum(agree_counts) >= 2: if first_card_strength > 0.5 or second_card_strength > 0.5: return RaiseAction(raise_amount) if pot_odds >= 0.7 and bluff_factor < 0.05: return FoldAction() else: # ONE PAIR IN FIRST CARD if agree_counts[0] == 1: if random.random() < first_card_strength: return RaiseAction(raise_amount) # ONE PAIR IN SECOND CARD if agree_counts[1] == 1: if random.random() < second_card_strength: return RaiseAction(raise_amount) # POCKET PAIR if my_cards[0][0] == my_cards[1][0]: if random.random() < first_card_strength: return RaiseAction(raise_amount) # PRE-FLOP HIGH CARD if street == 0 and (first_card_strength > 0.8 or second_card_strength > 0.8): return RaiseAction(raise_amount) if CheckAction in legal_actions: # check-call return CheckAction() if CallAction in legal_actions: # FLUSH if FLUSH == True: return CallAction() # OPPO FLUSH if pot_odds >= 0.7 and bluff_factor < 0.05 and OPP_FLUSH == True: return FoldAction() # ABOUT FLUSH if ABOUT_FLUSH == True and pot_odds < 0.4: return CallAction() # THREE OF A KIND OR BETTER if agree_counts[0] >= 2 or agree_counts[1] >= 2: return CallAction() # TWO-PAIR if sum(agree_counts) >= 2: return CallAction() if pot_odds >= 0.7 and bluff_factor < 0.05: return FoldAction() else: # ONE PAIR IN FIRST CARD if agree_counts[0] == 1: if bluff_factor < (first_card_strength * (1 + bluff_factor)): return CallAction() # ONE PAIR IN SECOND CARD if agree_counts[1] == 1: if random.random() < (second_card_strength * (1 + bluff_factor)): return CallAction() # POCKET PAIR if my_cards[0][0] == my_cards[1][0]: if random.random() < (first_card_strength * (1 + bluff_factor)): return CallAction() #HIGH CARD if street == 0 and ( first_card_strength > 0.9 or second_card_strength > 0.9) and bluff_factor > 0.05: return CallAction() if street == 0 and ( first_card_strength > 0.8 or second_card_strength > 0.8) and bluff_factor > 0.15: return CallAction() # SMALL BET if pot_odds < 0.2: return CallAction() return FoldAction()
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 if legal_actions == {CheckAction}: return CheckAction() street = round_state.street # 0, 3, 4, or 5 representing pre-flop, flop, turn, or river 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 pot_after_continue = my_contribution + opp_contribution + continue_cost 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 first_card_winrate = self.wins_dict[ my_cards[0][0]] / self.showdowns_dict[my_cards[0][0]] second_card_winrate = self.wins_dict[ my_cards[1][0]] / self.showdowns_dict[my_cards[1][0]] # for indexing winrates = [first_card_winrate, second_card_winrate] # count up how often our cards agree with the board cards agree_counts = [0, 0] for card in board_cards: # increase agree_counts each time values agree for i in range(2): if my_cards[i][0] == card[0]: agree_counts[i] += 1 raise_amount = my_pip + continue_cost + int( 0.75 * pot_after_continue) raise_amount = min(raise_amount, max_raise) raise_amount = max(raise_amount, min_raise) suit_counts = [0, 0] for card in board_cards: # increase suit_counts each time values agree for i in range(2): if my_cards[i][1] == card[1]: agree_counts[i] += 1 # FLUSH if suit_counts[0] > 4 or suit_counts[1] > 4: return RaiseAction(raise_amount) # TWO-PAIR OR BETTER if sum(agree_counts) >= 2: return RaiseAction(raise_amount) # ONE PAIR IN FIRST CARD if agree_counts[0] == 1: if random.random() < winrates[0]: return RaiseAction(raise_amount) # ONE PAIR IN SECOND CARD if agree_counts[1] == 1: if random.random() < winrates[1]: return RaiseAction(raise_amount) # POCKET PAIR if my_cards[0][0] == my_cards[1][0]: if random.random() < winrates[0]: return RaiseAction(raise_amount) if first_card_winrate > 0.5 and second_card_winrate > 0.5: return RaiseAction(min_raise) if CheckAction in legal_actions: # check-call return CheckAction() return CallAction()
class Player(Bot): ''' A pokerbot. ''' 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.nodes = ['2','3','4','5','6','7','8','9','T','J','Q','K','A'] self.edges = [] self.carddict = PreFlopStrat() # card_strength = {v:self.values.index(v) for v in self.values} #creates dictionary to see what cards win #create a directed graph with 13 nodes and if a certain card beats another add a node def handle_new_round(self, game_state, round_state, active): ''' Called when a new round starts. Called NUM_ROUNDS times. Arguments: game_state: the GameState object. round_state: the RoundState object. active: your player's index. Returns: Nothing. ''' my_bankroll = game_state.bankroll # the total number of chips you've gained or lost from the beginning of the game to the start of this round game_clock = game_state.game_clock # the total number of seconds your bot has left to play this game round_num = game_state.round_num # the round number from 1 to NUM_ROUNDS my_cards = round_state.hands[active] # your cards big_blind = bool(active) # True if you are the big blind self.preflop = 0 pass 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 self.updateCardStrength(my_delta, game_state, previous_state, street, my_cards, opp_cards) 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 pot_after_continue = my_contribution + opp_contribution + continue_cost 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 # if game_state.round_num == NUM_ROUNDS: # print(self.edges) if my_stack == 0: return CheckAction() # cards = my_cards # if street==0 and self.preflop == 0:#pre flop strategy # if cards[0][0]==cards[1][0]:#pairs # return RaiseAction(pot_after_continue/2) # if cards[0][0]==self.values[12] or cards[1][0]==self.values[12]: #rwhenever there is an Ace # return RaiseAction(pot_after_continue/2) # elif cards[0][1]!=cards[1][1]:#different suit absolutes # if self.values.index(cards[0][0])+self.values.index(cards[1][0])<10:#folding on low values # return CheckAction() if CheckAction in legal_actions else FoldAction() # elif self.values.index(cards[0][0])+self.values.index(cards[1][0])>16: # return RaiseAction(pot_after_continue/2) # elif cards[0][0]==self.values[8] and cards[1][0]==self.values[3]: # return CheckAction() if CheckAction in legal_actions else FoldAction() # elif cards[0][0]==self.values[3] and cards[1][0]==self.values[8]: # return CheckAction() if CheckAction in legal_actions else FoldAction() # elif cards[0][0]==self.values[8] and cards[1][0]==self.values[2]: # return RaiseAction(pot_after_continue/2) # elif cards[0][0]==self.values[2] and cards[1][0]==self.values[8]: # return RaiseAction(pot_after_continue/2) # elif cards[0][0]==self.values[7] and cards[1][0]==self.values[3]: # return RaiseAction(pot_after_continue/2) # elif cards[0][0]==self.values[3] and cards[1][0]==self.values[7]: # return RaiseAction(pot_after_continue/2) # elif cards[0][1]==cards[1][1]:#same suit absolutes # if cards[0][0]==self.values[0] or cards[1][0]==self.values[0]: # if self.values.index(cards[0][0])+self.values.index(cards[1][0]) < 9: #folding on low values # return CheckAction() if CheckAction in legal_actions else FoldAction() # elif self.values.index(cards[0][0])+self.values.index(cards[1][0])>11:#raising high # return RaiseAction(pot_after_continue/2) # elif cards[0][0]==self.values[1] or cards[1][0]==self.values[1]: # if self.values.index(cards[0][0])+self.values.index(cards[1][0])<11: # if self.values.index(cards[0][0])+self.values.index(cards[1][0])>4: # return CheckAction() if CheckAction in legal_actions else FoldAction() # elif cards[0][0]==self.values[6] and cards[1][0]==self.values[5]: # return RaiseAction(pot_after_continue/2) # elif cards[0][0]==self.values[5] and cards[1][0]==self.values[6]: # return RaiseAction(pot_after_continue/2) # elif cards[0][0]==self.values[5] and cards[1][0]==self.values[4]: # return RaiseAction(pot_after_continue/2) # elif cards[0][0]==self.values[4] and cards[1][0]==self.values[5]: # return RaiseAction(pot_after_continue/2) # elif active==True:#big blind # return CheckAction() if CheckAction in legal_actions else CallAction() # else:#small blind # return RaiseAction(pot_after_continue/2) #maybe call under 10 value # self.preflop += 1 # elif street == 0 and self.preflop > 0: # return CheckAction() if CheckAction in legal_actions else CallAction() # else: # #after flop # if street == 3: # if self.checkFlush(my_cards, board_cards) or self.check3ofKind(my_cards, board_cards) or self.check2Pair(my_cards, board_cards) or (self.checkPair(my_cards, board_cards) != False and self.values.index(self.checkPair(my_cards, board_cards)) >= 9): # return RaiseAction(max_raise) # if self.checkFlush(my_cards, board_cards) or self.check3ofKind(my_cards, board_cards): # return RaiseAction(pot_after_continue) # elif self.checkPair(my_cards, board_cards): # return RaiseAction(pot_after_continue/2) # elif self.values.index(self.highCard(my_cards, [])) >10: # return CallAction() if continue_cost < my_contribution else FoldAction() highCard = self.highCard(my_cards, []) lowCard = my_cards[0][0] if my_cards[0][0] != highCard else my_cards[1][0] suited = 's' if my_cards[0][1] == my_cards[1][1] else 'o' if my_stack == 0: return CheckAction() starting_amount=25 if active==True:#ur big blind if continue_cost==max_raise: #if they have a strong hand starting_amount+=10 elif continue_cost<(max_raise): #if they have a really good hand starting_amount+=10*(1-((max_raise-continue_cost)/max_raise)) if RaiseAction in legal_actions: if street != 0: if self.check3ofKind(my_cards, board_cards) or self.checkFlush(my_cards, board_cards): return RaiseAction(max_raise) elif self.check2Pair(my_cards, board_cards) and self.highCard(my_cards, []) in self.check2Pair(my_cards, board_cards): return RaiseAction(max_raise) elif self.checkPair(my_cards, board_cards) and self.highCard(my_cards, []) in self.checkPair(my_cards, board_cards): return RaiseAction(15) else: if self.carddict[(self.values.index(lowCard), self.values.index(highCard)), suited]>starting_amount: return RaiseAction() elif self.carddict[(self.values.index(lowCard), self.values.index(highCard)), suited] < starting_amount and continue_cost < 70: return RaiseAction() elif self.carddict[(self.values.index(lowCard), self.values.index(highCard)), suited] < starting_amount and continue_cost < 110: return CallAction() else: return FoldAction() elif CheckAction in legal_actions: # check-call return CheckAction() return FoldAction()
def get_actions(self, game_state: GameState, round_state: RoundState, active: int): ''' Where the magic happens - your code should implement this function. Called any time the engine needs a triplet of actions from your bot. Arguments: game_state: the GameState object. round_state: the RoundState object. active: your player's index. Returns: Your actions. ''' legal_actions = round_state.legal_actions() my_actions = [None] * NUM_BOARDS raise_bounds = list(round_state.raise_bounds()) print(raise_bounds) total_cost = sum([ (round_state.board_states[i].pips[1 - active] - round_state.board_states[i].pips[active]) if isinstance( round_state.board_states[i], BoardState) else 0 for i in range(NUM_BOARDS) ]) for i in range(NUM_BOARDS): board_state = round_state.board_states[i] board_actions = legal_actions[i] if isinstance(board_state, TerminalState) or board_state.settled: my_actions[i] = CheckAction() continue elif AssignAction in legal_actions[i]: my_actions[i] = AssignAction(self.card_allocation[i]) mc = monte_carlo_prob(self.card_allocation[i], [], all_cards_excluding(self.cards)) for hand_range in branches_from_dealer[0]: if mc <= float(hand_range): self.players[i].move_down(hand_range) print(f'Branching from dealer: {hand_range}') break elif round_state.street <= 3: print(f'-Board {i+1}-') pips = board_state.pips[active] opp_pips = board_state.pips[1 - active] pot = board_state.pot + opp_pips + pips continue_cost = opp_pips - pips count = 0 while not (self.players[i].is_owner() or self.players[i].at_terminal()): if count > 10: break if self.players[i].current_node().get_owner() == 'D': mc = self.win_probability(board_state, active) for hand_range in branches_from_dealer[1]: if mc <= float(hand_range): self.players[i].move_down(hand_range) print(f'Branching from dealer: {hand_range}') break else: prev = self.players[i].current_node().get_incoming() if continue_cost > 0: if round_state.street > 0 and prev == 'C': self.players[i].move_down('K2') print(f'Opp chose branch: K2') else: branches = [] for branch in self.players[i].get_branches(): if 'R' in branch: branches.append(branch) raise_boundaries = [ int((pot - continue_cost) * (2**(int(branch.replace('R', '')) - 2.5))) for branch in branches ] casted_amount = 0 for k in range(len(raise_boundaries)): if continue_cost <= raise_boundaries[k]: casted_amount = branches[k].replace( 'R', '') break if casted_amount == 0: casted_amount = branches[-1].replace( 'R', '') if 'R' in prev: self.players[i].move_down( f'RR{casted_amount}') print( f'Opp chose branch: RR{casted_amount}') else: self.players[i].move_down( f'R{casted_amount}') print( f'Opp chose branch: R{casted_amount}') else: if 'R' in prev: self.players[i].move_down('C') print('Opp chose branch: C') elif 'K1' == prev or 'C' == prev: self.players[i].move_down('K2') print('Opp chose branch: K2') elif '.' in prev: if 'K1' in self.players[i].get_branches(): self.players[i].move_down('K1') print('Opp chose branch: K1') elif 'C' in self.players[i].get_branches(): self.players[i].move_down('C') print('Opp chose branch: C') count += 1 if continue_cost > 2.25 * (pot - continue_cost): mc = self.win_probability(board_state, active) if (mc > .7 and round_state.street == 0) or (mc > .85 and round_state.street == 3): my_actions[i] = CallAction() self.players[i].move_down('C') print('Swerving branch: C') else: my_actions[i] = FoldAction() self.players[i].move_down('F') print('Swerving branch: F') continue elif not (self.players[i].is_owner() or self.players[i].at_terminal()): if CheckAction in board_actions: my_actions[i] = CheckAction() print('Timed out branch: K') else: my_actions[i] = CallAction() print('Timed out branch: C') continue branch = self.players[i].choose_branch() prev = self.players[i].current_node().get_incoming() if 'RR' in branch and CallAction in board_actions: my_actions[i] = CallAction() self.players[i].move_down('C') print('Choosing branch: C') elif 'R' in branch and 'RR' not in branch and RaiseAction in board_actions: raise_amount = max( BIG_BLIND, min(raise_bounds[1], int(pot * (2**(int(branch[1:]) - 3))))) raise_bounds[1] -= raise_amount my_actions[i] = RaiseAction(raise_amount + opp_pips) self.players[i].move_down(branch) print('Choosing branch:', branch) elif 'C' in branch and CallAction in board_actions: my_actions[i] = CallAction() self.players[i].move_down(branch) print('Choosing branch:', branch) elif 'K' in branch and CheckAction in board_actions: my_actions[i] = CheckAction() self.players[i].move_down(branch) print('Choosing branch:', branch) elif 'F' in branch and FoldAction in board_actions: my_actions[i] = FoldAction() self.players[i].move_down(branch) print('Choosing branch:', branch) elif CheckAction in board_actions: my_actions[i] = CheckAction() self.players[i].move_down('K') print('Defaulting branch: K') else: my_actions[i] = CallAction() self.players[i].move_down('C') print('Defaulting branch: C') else: pips = board_state.pips[active] opp_pips = board_state.pips[1 - active] continue_cost = opp_pips - pips pot = board_state.pot + opp_pips + pips pot_odds = float(continue_cost) / (pot + continue_cost) win_prob = self.win_probability(board_state, active) if continue_cost == 0: if win_prob >= .7 and RaiseAction in legal_actions[ i] and raise_bounds[1] >= BIG_BLIND: if win_prob > 0.96: increase = min(raise_bounds[1] - total_cost, int(pot)) elif win_prob >= 0.9: increase = min(raise_bounds[1] - total_cost, int(.75 * pot)) else: increase = min(raise_bounds[1] - total_cost, int(0.5 * pot)) amount = increase print(f'Bet/raise board {i + 1} to {amount}.') my_actions[i] = RaiseAction(amount) raise_bounds[1] -= amount else: print(f'Check {i + 1}.') my_actions[i] = CheckAction() else: if win_prob > .97 and RaiseAction in legal_actions[ i] and raise_bounds[1] >= BIG_BLIND: increase = min(raise_bounds[1] - total_cost, int(.5 * pot) + opp_pips) amount = increase + opp_pips print(f'Reraise board {i + 1} to {amount}.') my_actions[i] = RaiseAction(amount) raise_bounds[1] -= amount elif win_prob - .4 > pot_odds or win_prob > .95 - ( .05 * (5 - round_state.street)): print( f'Call board {i + 1} w/ {round(pot_odds, 2)} odds.' ) self.when_raised[i].append(round_state.street) my_actions[i] = CallAction() else: print(f'Fold board {i + 1}') my_actions[i] = FoldAction() print() return my_actions
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 if legal_actions == {CheckAction}: return CheckAction() 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 pot_after_continue = my_contribution + opp_contribution + continue_cost if FoldAction in legal_actions: if my_cards[0][0] == my_cards[1][0] and 0.5 > ( self.wins_dict[my_cards[0][0]] / self.showdowns_dict[my_cards[0][0]]): return FoldAction() 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 first_card_winrate = self.wins_dict[ my_cards[0][0]] / self.showdowns_dict[my_cards[0][0]] second_card_winrate = self.wins_dict[ my_cards[1][0]] / self.showdowns_dict[my_cards[1][0]] winrates = [first_card_winrate, second_card_winrate] #how often board cards match pocket cards agree_counts = [0, 0] raise_amount = my_pip + continue_cost + int( 0.77 * pot_after_continue) raise_amount = min(raise_amount, max_raise) raise_amount = max(raise_amount, min_raise) for card in board_cards: for i in range(2): if my_cards[i][0] == card[0]: agree_counts[i] += 1 #two pair or better if sum(agree_counts) >= 2: #definitely raise return RaiseAction(raise_amount) #one pair in first card if agree_counts[0] == 1: if random.random() < winrates[0]: return RaiseAction(raise_amount) #one pair in seond card if agree_counts[1] == 1: if random.random() < winrates[1]: return RaiseAction(raise_amount) #high pocket pairs are extremely good if my_cards[0][0] == my_cards[1][0]: #pocket pair if random.random() < winrates[0]: return RaiseAction(raise_amount) if first_card_winrate > 0.5 and second_card_winrate > 0.5: return RaiseAction(raise_amount) if CheckAction in legal_actions: # check-call return CheckAction() return CallAction()