def newhand_handler(self, received_packet): self.my_hand = received_packet['hand'] self.my_seat = received_packet['seat'] self.list_of_stacksizes = received_packet['stack_size'] self.my_original_stacksize = self.list_of_stacksizes[self.my_seat - 1] self.hand_id = received_packet['handID'] self.num_active_players = received_packet['num_active_players'] if self.num_active_players == 2: self.handPosition = POSITION_TWO[self.my_seat] else: self.handPosition = POSITION_THREE[self.my_seat] ############################################################################################### # see if we STATS has been initialized if self.STATS == None: self.STATS = Statistician(self.my_name, self.opponent_1_name, self.opponent_2_name) self.STATS.getPrecomputedHashtables(self.equity_table_2, self.equity_table_3) for opponent_name in [self.opponent_1_name, self.opponent_2_name]: if self.hasPlayed[opponent_name]: self.STATS.loadDataFromHistoryStorage(self.history_storage, opponent_name) # self.STATS.loadDataFromHistoryStorage(self.history_storage) self.STATS.setBigBlind(self.bigBlind) # print "===> STORAGE: " + str (self.history_storage) self.STATS.getNumActivePlayers(self.num_active_players) ############################################################################################### self.list_of_active_players = received_packet['active_players'] # adjust iterations new_time_bank = float(received_packet['timeBank']) if new_time_bank < self.time_low_thres and self.already_set_new_time == False: self.time_per_hand = 0.8 * self.time_per_hand self.already_set_new_time = True delta_time = self.time_bank - new_time_bank if delta_time > self.time_per_hand: self.monte_carlo_iter = max(self.monte_carlo_iter - DELTA_ITER, DELTA_ITER) else: self.monte_carlo_iter = min(self.monte_carlo_iter + DELTA_ITER, MAX_ITER) self.time_bank = new_time_bank # print "ITER : " + str(self.monte_carlo_iter) # print "DELTA: " + str(delta_time) self.one_folded = False names = received_packet['player_names'] for i in range(len(names)): name = names[i] if name != self.my_name: self.opp_dict[name].playerType = self.STATS.getPlayerType(name) self.opp_dict[name].seat = i if self.num_active_players == 2: self.opp_dict[name].handPosition = POSITION_TWO[i+1] else: self.opp_dict[name].handPosition = POSITION_THREE[i+1] self.opp_dict[name].stack_size = self.list_of_stacksizes[i] self.opp_dict[name].original_stacksize = self.list_of_stacksizes[i] # update status if (self.opp_dict[name].stack_size == 0 and self.opp_dict[name].status != OUT): self.opp_dict[name].status = OUT ############################################################################################### # self.STATS.updateHandCount(name, self.hand_id - 1) ############################################################################################### else: self.opp_dict[name].status = ACTIVE winPercA = self.STATS.getPostFlopWinPct(self.opponent_1_name) winPercB = self.STATS.getPostFlopWinPct(self.opponent_2_name) self.opp1_skill = winPercA / (winPercA + winPercB) self.opp2_skill = 1 - self.opp1_skill
class Player: def __init__ (self): self.time_low_thres = 0.0 self.time_bank = 0.0 self.time_per_hand = 0.0 self.my_name = "" self.opponent_1_name = "" self.opponent_2_name = "" self.hasPlayed_opponent_1 = False self.hasPlayed_opponent_2 = False self.my_hand = "" self.my_stacksize = 0 self.list_of_stacksizes = [] self.hand_id = 0 self.num_active_players = 0 self.list_of_active_players = [] self.history_storage = {} self.minBet = 0 self.maxBet = 0 self.minRaise = 0 self.maxRaise = 0 self.my_original_stacksize = 0 self.alpha = 0.5 # how agressive we are self.fold_thres = 0 self.opp_fold_thres = 0 self.raise_thres = 0 self.highestRaiseAmtThisRnd = 0 self.call_amount = 0 self.inc_call_amount = 0 self.is_new_round = True self.last_action = None self.num_boardcards = -1 self.boardcards = [] self.foundFaceCard = False self.my_seat = 1 self.potsize = 0 self.opp_dict = {} self.STATS = None self.monte_carlo_iter = MONTE_CARLO_ITER self.one_folded = False self.guy_active = "" self.handPosition = None self.opp1_skill = 0.5 self.opp2_skill = 0.5 self.isPreflop = True self.bigBlind = 2 self.lastRaiser = None self.oppCheckedThisRound = False self.already_set_new_time = False self.hasPlayed = {} # boss-ass hands self.boss_class1 = ['AsAh', 'AsAd', 'AsAc', 'AhAs', 'AhAd', 'AhAc', 'AdAs', 'AdAh', 'AdAc', 'AcAs', 'AcAh', 'AcAd', 'KsKh', 'KsKd', 'KsKc', 'KhKs', 'KhKd', 'KhKc', 'KdKs', 'KdKh', 'KdKc', 'KcKs', 'KcKh', 'KcKd', 'QsQh', 'QsQd', 'QsQc', 'QhQs', 'QhQd', 'QhQc', 'QdQs', 'QdQh', 'QdQc', 'QcQs', 'QcQh', 'QcQd', 'JsJh', 'JsJd', 'JsJc', 'JhJs', 'JhJd', 'JhJc', 'JdJs', 'JdJh', 'JdJc', 'JcJs', 'JcJh', 'JcJd', 'TsTh', 'TsTd', 'TsTc', 'ThTs', 'ThTd', 'ThTc', 'TdTs', 'TdTh', 'TdTc', 'TcTs', 'TcTh', 'TcTd'] self.boss_class2 = ['AsKs', 'KsAs', 'AhKh', 'KhAh', 'AdKd', 'KdAd', 'AcKc', 'KcAc', 'AsQs', 'QsAs', 'AhQh', 'QhAh', 'AdQd', 'QdAd', 'AcQc', 'QcAc', 'AsJs', 'JsAs', 'AhJh', 'JhAh', 'AdJd', 'JdAd', 'AcJc', 'JcAc', 'KdJd', 'KsJs', 'KcJc', 'KhJh', 'JdKd', 'JsKs', 'JcKc', 'JhKh', 'KdQd', 'KsQs', 'KcQc', 'KhQh', 'QdKd', 'QsKs', 'QcKc', 'QhKh', 'QdJd', 'QsJs', 'QcJc', 'QhJh', 'JdQd', 'JsQs', 'JcQc', 'JhQh', '9s9h', '9s9d', '9s9c', '9h9s', '9h9d', '9h9c', '9d9s', '9d9h', '9d9c', '9c9s', '9c9h', '9c9d', '8s8h', '8s8d', '8s8c', '8h8s', '8h8d', '8h8c', '8d8s', '8d8h', '8d8c', '8c8s', '8c8h', '8c8d'] # precomputed equity tables for pre flop self.equity_table_2 = {} self.equity_table_3 = {} with open("precomputed2.txt") as f: for line in f: (key, val) = line.split() self.equity_table_2[key] = float(val) with open("precomputed3.txt") as f: for line in f: (key, val) = line.split() self.equity_table_3[key] = float(val) def makeBet(self, amount): return int(max(self.minBet, min(amount, self.maxBet))) def makeRaise(self, amount): return int(max(self.minRaise, min(amount, self.maxRaise))) def faceCardOnTable(self, boardcards): if len(boardcards) > 0: for card in boardcards: if card[0] in FACE_CARDS: self.foundFaceCard = True return self.foundFaceCard def keyval_handler(self, received_packet): self.history_storage[received_packet['key']] = eval(received_packet['value']) def newgame_handler(self, received_packet): self.opponent_1_name = received_packet['opponent_1_name'] self.opponent_2_name = received_packet['opponent_2_name'] self.my_name = received_packet['player_name'] self.bigBlind = received_packet['big_blind'] self.opp_dict[self.opponent_1_name] = Opponent(self.opponent_1_name) self.opp_dict[self.opponent_2_name] = Opponent(self.opponent_2_name) self.time_bank = float(received_packet['timeBank']) self.time_low_thres = 0.05 * self.time_bank self.time_per_hand = self.time_bank / received_packet['num_hands'] # If we have already played the opponent before, # we load their statistics from the previous encounter # for this game. NOTE that Historian is just an instance of the Statistician/Historian class # that is not yet created. self.hasPlayed = {self.opponent_1_name: False, self.opponent_2_name: False} for opponent_name in [self.opponent_1_name, self.opponent_2_name]: if opponent_name in self.history_storage: self.hasPlayed[opponent_name] = True def newhand_handler(self, received_packet): self.my_hand = received_packet['hand'] self.my_seat = received_packet['seat'] self.list_of_stacksizes = received_packet['stack_size'] self.my_original_stacksize = self.list_of_stacksizes[self.my_seat - 1] self.hand_id = received_packet['handID'] self.num_active_players = received_packet['num_active_players'] if self.num_active_players == 2: self.handPosition = POSITION_TWO[self.my_seat] else: self.handPosition = POSITION_THREE[self.my_seat] ############################################################################################### # see if we STATS has been initialized if self.STATS == None: self.STATS = Statistician(self.my_name, self.opponent_1_name, self.opponent_2_name) self.STATS.getPrecomputedHashtables(self.equity_table_2, self.equity_table_3) for opponent_name in [self.opponent_1_name, self.opponent_2_name]: if self.hasPlayed[opponent_name]: self.STATS.loadDataFromHistoryStorage(self.history_storage, opponent_name) # self.STATS.loadDataFromHistoryStorage(self.history_storage) self.STATS.setBigBlind(self.bigBlind) # print "===> STORAGE: " + str (self.history_storage) self.STATS.getNumActivePlayers(self.num_active_players) ############################################################################################### self.list_of_active_players = received_packet['active_players'] # adjust iterations new_time_bank = float(received_packet['timeBank']) if new_time_bank < self.time_low_thres and self.already_set_new_time == False: self.time_per_hand = 0.8 * self.time_per_hand self.already_set_new_time = True delta_time = self.time_bank - new_time_bank if delta_time > self.time_per_hand: self.monte_carlo_iter = max(self.monte_carlo_iter - DELTA_ITER, DELTA_ITER) else: self.monte_carlo_iter = min(self.monte_carlo_iter + DELTA_ITER, MAX_ITER) self.time_bank = new_time_bank # print "ITER : " + str(self.monte_carlo_iter) # print "DELTA: " + str(delta_time) self.one_folded = False names = received_packet['player_names'] for i in range(len(names)): name = names[i] if name != self.my_name: self.opp_dict[name].playerType = self.STATS.getPlayerType(name) self.opp_dict[name].seat = i if self.num_active_players == 2: self.opp_dict[name].handPosition = POSITION_TWO[i+1] else: self.opp_dict[name].handPosition = POSITION_THREE[i+1] self.opp_dict[name].stack_size = self.list_of_stacksizes[i] self.opp_dict[name].original_stacksize = self.list_of_stacksizes[i] # update status if (self.opp_dict[name].stack_size == 0 and self.opp_dict[name].status != OUT): self.opp_dict[name].status = OUT ############################################################################################### # self.STATS.updateHandCount(name, self.hand_id - 1) ############################################################################################### else: self.opp_dict[name].status = ACTIVE winPercA = self.STATS.getPostFlopWinPct(self.opponent_1_name) winPercB = self.STATS.getPostFlopWinPct(self.opponent_2_name) self.opp1_skill = winPercA / (winPercA + winPercB) self.opp2_skill = 1 - self.opp1_skill def bet_handler(self, winning_factor): a = random.random() bet_amount = 0 # slow play if self.num_boardcards == 0: winning_factor = min(1, winning_factor) elif self.num_boardcards == 3: winning_factor = min(0.5, 0.75*winning_factor) elif self.num_boardcards == 4: winning_factor = min(0.5, winning_factor) if self.alpha > a: # YOLO r = random.random() if winning_factor > r: bet_amount = self.my_stacksize else: # EBOLO bet_amount = self.my_stacksize * winning_factor amountBet = self.makeBet(bet_amount) self.highestRaiseAmtThisRnd = amountBet return amountBet # s.send(BET + ':' + str(self.makeBet(bet_amount)) + '\n') def raise_handler(self, winning_factor): a = random.random() raise_amount = 0 if self.alpha > a: # YOLO r = random.random() if winning_factor > r: raise_amount = self.my_stacksize else: # EBOLO raise_amount = self.my_stacksize * winning_factor amountRaise = self.makeRaise(raise_amount) self.highestRaiseAmtThisRnd = amountRaise return amountRaise # s.send(RAISE + ':' + str(self.makeRaise(raise_amount)) + '\n') def should_call_no_stats (self, equity): fold_ew = 0 call_win_ew = 0 call_lose_ew = 0 if self.call_amount < SLOW_PLAY_AMOUNT: return True # should call before the flop if self.num_boardcards == 0 and self.potsize <= 6: return True bitch_factor = 1 # check if one is out guy_active = "" guy_folded = "" if self.num_active_players == 2: #heads-up guy_active = self.guy_active other_guy_stacksize = self.opp_dict[guy_active].original_stacksize # if other_guy_stacksize <= 0.05*self.my_original_stacksize: # "$$$ THIS IS PROB NEVER TRUE" # return True # else: bitch_factor = TWO_IN_BITCH_FACTOR_TABLE[self.num_boardcards] fold_chips = self.my_stacksize call_lose_chips = self.my_stacksize - self.inc_call_amount call_win_chips = self.my_stacksize + self.potsize # print "FOLD CHIPS: " + str(fold_chips * bitch_factor) # print "EXP CHIPS : " + str(call_lose_chips*(1-equity) + call_win_chips*equity) lhs = fold_chips * bitch_factor rhs = call_lose_chips*(1-equity) + call_win_chips*equity return lhs < rhs else: # all three players have chips opp_names = self.opp_dict.keys() one_folded = False for name in self.opp_dict: if self.opp_dict[name].status == FOLDED: one_folded = True guy_folded = name else: guy_active = name if one_folded: # one person folded fold_ew = calc_icm(self.my_stacksize, self.opp_dict[guy_active].stack_size+self.potsize, self.opp_dict[guy_folded].stack_size)[0] call_win_ew = calc_icm(self.my_stacksize+self.potsize, self.opp_dict[guy_active].stack_size, self.opp_dict[guy_folded].stack_size)[0] call_lose_ew = calc_icm(self.my_stacksize-self.inc_call_amount, self.opp_dict[guy_active].stack_size+self.potsize+self.inc_call_amount, self.opp_dict[guy_folded].stack_size)[0] else: # all three are still in hand winPercA = self.STATS.getPostFlopWinPct(opp_names[0]) winPercB = self.STATS.getPostFlopWinPct(opp_names[1]) skill_a = winPercA / (winPercA + winPercB) skill_b = 1 - skill_a # if min(self.STATS.postFlopCount.values()) > 10 and not self.STATS.postFlopWinPct[opp_names[0]] == 0 and self.STATS.postFlopWinPct[opp_names[1]] == 0: # skill_a = self.STATS.postFlopWinPct[opp_names[0]] / (self.STATS.postFlopWinPct[opp_names[0]] + self.STATS.postFlopWinPct[opp_names[1]]) # skill_b = self.STATS.postFlopWinPct[opp_names[1]] / (self.STATS.postFlopWinPct[opp_names[0]] + self.STATS.postFlopWinPct[opp_names[1]]) fold_ew_a = calc_icm(self.my_stacksize, self.opp_dict[opp_names[0]].stack_size+self.potsize, self.opp_dict[opp_names[1]].stack_size)[0] fold_ew_b = calc_icm(self.my_stacksize, self.opp_dict[opp_names[0]].stack_size , self.opp_dict[opp_names[1]].stack_size+self.potsize)[0] fold_ew = skill_a*fold_ew_a + skill_b*fold_ew_b if self.opp_dict[opp_names[0]].stack_size == 0 and self.opp_dict[opp_names[1]].stack_size == 0: call_win_ew = FIRST_PRIZE else: call_win_ew = calc_icm(self.my_stacksize+self.potsize, self.opp_dict[opp_names[0]].stack_size, self.opp_dict[opp_names[1]].stack_size)[0] if self.my_stacksize == self.inc_call_amount: # we are all-in if self.opp_dict[opp_names[0]].stack_size == 0: if self.opp_dict[opp_names[1]].stack_size != 0: # only first opponent and us all-in if self.my_original_stacksize > self.opp_dict[opp_names[0]].original_stacksize: call_lose_ew_b = SECOND_PRIZE # all-in opponent loses (and us) elif self.my_original_stacksize < self.opp_dict[opp_names[0]].original_stacksize: call_lose_ew_b = THIRD_PRIZE # all-in opponent loses (and us) else: call_lose_ew_b = SECOND_PRIZE / 2 # all-in opponent loses (and us) call_lose_ew_a = 0 # all-in opponent wins and we lose else: # both opponents all-in if self.my_original_stacksize > self.opp_dict[opp_names[0]].original_stacksize: call_lose_ew_b = SECOND_PRIZE elif self.my_original_stacksize < self.opp_dict[opp_names[0]].original_stacksize: call_lose_ew_b = 0 elif self.my_original_stacksize == self.opp_dict[opp_names[0]].original_stacksize: call_lose_ew_b = SECOND_PRIZE / 2 if self.my_original_stacksize > self.opp_dict[opp_names[1]].original_stacksize: call_lose_ew_a = SECOND_PRIZE elif self.my_original_stacksize < self.opp_dict[opp_names[1]].original_stacksize: call_lose_ew_a = 0 elif self.my_original_stacksize == self.opp_dict[opp_names[1]].original_stacksize: call_lose_ew_a = SECOND_PRIZE / 2 elif self.opp_dict[opp_names[1]].stack_size == 0: # only second opponent and us all-in if self.my_original_stacksize > self.opp_dict[opp_names[1]].original_stacksize: call_lose_ew_a = SECOND_PRIZE elif self.my_original_stacksize < self.opp_dict[opp_names[1]].original_stacksize: call_lose_ew_a = 0 else: call_lose_ew_a = SECOND_PRIZE / 2 call_lose_ew_b = 0 # all-in opponent wins and we lose else: # only we are all-in call_lose_ew_a = 0 call_lose_ew_b = 0 else: # we are not all-in call_lose_ew_a = calc_icm(self.my_stacksize-self.inc_call_amount, self.opp_dict[opp_names[0]].stack_size+self.potsize+self.inc_call_amount, self.opp_dict[opp_names[1]].stack_size)[0] call_lose_ew_b = calc_icm(self.my_stacksize-self.inc_call_amount, self.opp_dict[opp_names[0]].stack_size, self.opp_dict[opp_names[1]].stack_size+self.potsize+self.inc_call_amount)[0] call_lose_ew = skill_a*call_lose_ew_a + skill_b*call_lose_ew_b # logic to determine call/fold if self.one_folded: bitch_factor = TWO_IN_BITCH_FACTOR_TABLE[self.num_boardcards] else: bitch_factor = THREE_IN_BITCH_FACTOR_TABLE[self.num_boardcards] lhs = fold_ew * bitch_factor rhs = equity*call_win_ew + (1-equity)*call_lose_ew # print 'HAND ID : ' + str(self.hand_id) # print 'MY HAND : ' + self.my_hand # print 'MY STACK: ' + str(self.my_stacksize) # print 'POT : ' + str(self.potsize) # print 'EQUITY : ' + str(equity) # print 'FOLD EW : ' + str(fold_ew) # print "CALL EW : " + str(rhs) # print 'BITCH F : ' + str(bitch_factor) if lhs < rhs: return True return False def should_call(self, equity): should = self.should_call_no_stats(equity) # minEquity = 0 # avgEquity = 0 # if self.num_active_players == 2 or self.one_folded: # guy_active = "" # for name in self.opp_dict: # if self.opp_dict[name].status == ACTIVE: # guy_active = name # # DEBUG # print "PLAYER_TYPE : " + self.opp_dict[name].playerType # minEquity = self.STATS.minEquityTwo[guy_active][self.num_boardcards] # avgEquity = self.STATS.averageEquityTwo[guy_active][self.num_boardcards] # else: # minEquity = max([i[self.num_boardcards] for i in self.STATS.minEquityThree.values()]) # avgEquity = max([i[self.num_boardcards] for i in self.STATS.averageEquityThree.values()]) if should: # print "$$$ SHOULD" # print "INC CALL: " + str(self.inc_call_amount) # print "POT SIZE: " + str(self.potsize) # if relatively smalll: if self.inc_call_amount <= 2 * self.bigBlind: return True # # aggressive raise # if self.inc_call_amount > 10 and self.inc_call_amount > 0.24 * self.potsize: # if self.opp_dict[self.lastRaiser].playerType in [TYPE_TA, TYPE_STA]: # print "FOLDED BECAUSE PLAYER TYPE: " + self.opp_dict[self.lastRaiser].playerType # return False # elif self.opp_dict[self.lastRaiser].playerType != TYPE_LA and equity < 1.15 * self.raise_thres: # print "FOLDED BECAUSE DID NOT MEET THRES: " + str(self.raise_thres * 1.15) # return False # elif equity < self.raise_thres: # print "FOLDED BECAUSE DID NOT MEET THRES" # return False # new aggressive raise logic if self.my_stacksize < SUFFICIENT_CHIPS / 2: return True if self.my_stacksize < SUFFICIENT_CHIPS and equity > self.raise_thres: return True raiseToMaxRaise = float(self.inc_call_amount) / (self.potsize - self.call_amount + self.highestRaiseAmtThisRnd + 0.01) # print "AGGRESSIVENESS : " + str(raiseToMaxRaise) if self.num_active_players == 2: return True if self.inc_call_amount >= 6 * self.bigBlind: if raiseToMaxRaise > 0.75: # very aggressive if self.opp_dict[self.lastRaiser].playerType in [TYPE_TA, TYPE_STA] and equity < 0.96: # print "FOLDED 1 BECAUSE PLAYER TYPE: " + self.opp_dict[self.lastRaiser].playerType return False elif self.opp_dict[self.lastRaiser].playerType != TYPE_LA and equity < 1.12 * self.raise_thres: # print "FOLDED 2 BECAUSE PLAYER TYPE: " + self.opp_dict[self.lastRaiser].playerType return False elif equity < self.raise_thres: return False elif raiseToMaxRaise > 0.5: # medium aggressive if self.opp_dict[self.lastRaiser].playerType in [TYPE_TA, TYPE_STA] and equity < 0.92: # print "FOLDED 3 BECAUSE PLAYER TYPE: " + self.opp_dict[self.lastRaiser].playerType return False elif self.opp_dict[self.lastRaiser].playerType != TYPE_LA and equity < 1.12 * self.raise_thres: # print "FOLDED 4 BECAUSE PLAYER TYPE: " + self.opp_dict[self.lastRaiser].playerType return False elif equity < self.raise_thres: return False elif raiseToMaxRaise > 0.35: # mildly aggressive if self.opp_dict[self.lastRaiser].playerType in [TYPE_TA, TYPE_STA]: if equity < 1.12 * self.raise_thres: # print "FOLDED 5 BECAUSE PLAYER TYPE: " + self.opp_dict[self.lastRaiser].playerType return False elif self.opp_dict[self.lastRaiser].playerType != TYPE_LA: if equity < self.raise_thres: return False return True # if self.num_boardcards != 0 and equity < avgEquity: # print "$$$ BUT NO" # return False # else: # return True return False # else: # print "$$$ SHOULD NOT" # if equity > avgEquity: # print "$$$ BUT YES" # return True # else: # return False def get_best_action(self, received_packet, avail_actions = []): equity = None # set thresholds # if not self.one_out: # self.fold_thres = THREE_FOLD_THRES_TABLE[self.num_boardcards] # self.raise_thres = THREE_RAISE_THRES_TABLE[self.num_boardcards] # self.opp_fold_thres = THREE_opp_fold_thres # else: # self.fold_thres = TWO_FOLD_THRES_TABLE[self.num_boardcards] # self.raise_thres = TWO_RAISE_THRES_TABLE[self.num_boardcards] # self.opp_fold_thres = TWO_opp_fold_thres # see if we could use precomputed equity if self.num_active_players == 2 or self.one_folded == True: self.fold_thres = TWO_FOLD_THRES_TABLE[self.num_boardcards] self.raise_thres = TWO_RAISE_THRES_TABLE[self.num_boardcards] self.opp_fold_thres = self.STATS.getFoldPercent(self.guy_active) if self.num_boardcards == 0: equity = self.equity_table_2[self.my_hand] else: equity = pbots_calc.calc(':'.join([self.my_hand, 'xx']), ''.join(received_packet['boardcards']), "", self.monte_carlo_iter) equity = equity.ev[0] else: self.fold_thres = THREE_FOLD_THRES_TABLE[self.num_boardcards] self.raise_thres = THREE_RAISE_THRES_TABLE[self.num_boardcards] self.opp_fold_thres = self.opp1_skill * self.STATS.getFoldPercent(self.opponent_1_name) + self.opp2_skill * self.STATS.getFoldPercent(self.opponent_2_name) if self.num_boardcards == 0: equity = self.equity_table_3[self.my_hand] else: equity = pbots_calc.calc(':'.join([self.my_hand, 'xx', 'xx']), ''.join(received_packet['boardcards']), "", self.monte_carlo_iter) equity = equity.ev[0] do_reraise = random.random() < self.opp_fold_thres # print 'FOLD T: ' + str(self.opp_fold_thres) # print 'EQUITY: ' + str(equity) own_a_lot_of_chips = self.my_stacksize > LOTS_OF_CHIPS winning_factor = ((equity - self.fold_thres) / (1 - self.fold_thres))**POWER # TODO: Raise a little if they checked last turn # if equity < self.fold_thres and ((own_a_lot_of_chips != True) or (self.num_boardcards != 0)): # # TODO: Implement bluffing / call here # if CHECK in avail_actions: # # bet a little bit if possible to exploit bots who fold to small raises: (but dont do this all the time) # # if BET in avail_actions and self.my_stacksize > BET_SMALL_LIKELIHOOD[self.num_boardcards]: # if False: # random_nig = random.random() # # foldPerc = 0.0 # # for name in self.opp_dict: # # if self.opp_dict[name].status == ACTIVE: # # foldPerc += self.STATS.foldPercentage[name] # # if not self.one_folded: # # foldPerc = foldPerc / 2 # if random_nig < self.opp_fold_thres: # print "MINBET: " + str(self.minBet) # return BET + ":" + str(self.minBet) # return CHECK # return FOLD # Subroutines we use to make our lives easier: ##################################################################################################### def do_call (): if self.should_call(equity): self.highestRaiseAmtThisRnd = self.call_amount return CALL + ":" + str(self.call_amount) else: return FOLD def do_raise_preflop (): if self.my_hand in self.boss_class1: if self.lastRaiser in [TYPE_STA] and self.my_stacksize > SUFFICIENT_CHIPS: return CALL + ":" + str(self.call_amount) # raise a lot self.highestRaiseAmtThisRnd = self.maxRaise return RAISE + ":" + str(self.maxRaise) elif self.my_hand in self.boss_class2: if self.num_active_players == 3 and self.one_folded == False: if (self.opp_dict[self.opponent_1_name].playerType not in [TYPE_STA, TYPE_TA, TYPE_LP]) and \ (self.opp_dict[self.opponent_2_name].playerType not in [TYPE_STA, TYPE_TA, TYPE_LP]): # raise a lot self.highestRaiseAmtThisRnd = self.maxRaise return RAISE + ":" + str(self.maxRaise) else: self.highestRaiseAmtThisRnd = self.maxRaise return RAISE + ":" + str(self.minRaise) elif self.opp_dict[self.guy_active].playerType not in [TYPE_STA, TYPE_TA, TYPE_LP]: # raise a lot self.highestRaiseAmtThisRnd = self.maxRaise return RAISE + ":" + str(self.maxRaise) else: self.highestRaiseAmtThisRnd = self.minRaise return RAISE + ":" + str(self.minRaise) # bet a little in general self.highestRaiseAmtThisRnd = self.minRaise return RAISE + ":" + str(self.minRaise) def do_call_preflop (): raiserType = self.opp_dict[self.lastRaiser].playerType if raiserType in [TYPE_STA, TYPE_TA, TYPE_LP]: if self.my_hand in self.boss_class1: return do_call() else: # do not engage return FOLD elif raiserType != TYPE_LA: if self.my_hand in self.boss_class1 or self.my_hand in self.boss_class2: return do_call() else: return FOLD else: return do_call() ##################################################################################################### if equity < self.fold_thres: if self.isPreflop: if self.handPosition == BUTTON: if self.opp_dict[self.opponent_1_name].playerType == TYPE_LA or self.opp_dict[self.opponent_2_name].playerType == TYPE_LA: if (self.fold_thres - equity) < TOLERANCE_FOR_LA: if CALL in avail_actions: if self.call_amount == self.bigBlind and RAISE in avail_actions: self.highestRaiseAmtThisRnd = self.minRaise return RAISE + ":" + str(self.minRaise) return FOLD if BET in avail_actions and self.minBet <= self.bigBlind: if self.oppCheckedThisRound: random_nig = random.random() if random_nig < self.opp_fold_thres: # print "MINBET: " + str(self.minBet) self.highestRaiseAmtThisRnd = self.minBet return BET + ":" + str(self.minBet) if CHECK in avail_actions: return CHECK if CALL in avail_actions: # if relatively smalll: if self.inc_call_amount <= self.bigBlind or \ (self.isPreflop == False and (self.inc_call_amount < 2 * self.bigBlind or self.inc_call_amount < 0.07 * self.potsize)): return do_call() return FOLD # elif equity > self.raise_thres and (self.is_new_round or do_reraise): elif equity > self.raise_thres: if self.isPreflop: # fun time! if self.handPosition == BUTTON: if self.opp_dict[self.opponent_1_name].playerType == TYPE_LA or self.opp_dict[self.opponent_2_name].playerType == TYPE_LA: if self.num_active_players == 2 or self.one_folded: if self.opp_dict[self.guy_active].playerType == TYPE_LA: # n***a will handle raising return do_call() else: # n****s will handle the raising for us return do_call() if CALL in avail_actions: if self.potsize > 5 * self.bigBlind: return do_call_preflop() else: if RAISE in avail_actions: return do_raise_preflop() else: return do_call_preflop() elif self.handPosition == BB: if CALL in avail_actions: # someone raised return do_call_preflop() elif RAISE in avail_actions and self.potsize < 7: return do_raise_preflop() return CHECK elif self.handPosition == SB: if CALL in avail_actions: if self.call_amount == self.bigBlind and RAISE in avail_actions: return do_raise_preflop() else: # someone raised return do_call_preflop() else: if BET in avail_actions: amount = self.bet_handler(winning_factor) return BET + ":" + str(amount) elif RAISE in avail_actions and do_reraise: # if they raise a little, either counter raise or call if self.should_call(equity): amount = self.raise_handler(winning_factor) return RAISE + ":" + str(amount) else: return FOLD # not in very good equity range if CHECK in avail_actions or BET in avail_actions: if self.oppCheckedThisRound: random_nig = random.random() if random_nig < self.opp_fold_thres: # print "MINBET: " + str(self.minBet * 4) self.highestRaiseAmtThisRnd = self.minBet * 4 return BET + ":" + str(self.minBet * 4) if CALL in avail_actions: # TODO: do preflop logic here if self.isPreflop: if self.handPosition == BUTTON or (self.handPosition == SB and self.num_active_players == 2): if self.opp_dict[self.guy_active].playerType == TYPE_LA: # n***a will handle raising return do_call() if self.potsize > 5 * self.bigBlind: return do_call_preflop() else: if RAISE in avail_actions: return do_raise_preflop() else: return do_call_preflop() elif self.handPosition == SB: if self.call_amount == self.bigBlind: return do_call() else: # someone raised return FOLD elif self.handPosition == BB: # someone raised if self.potsize <= 3 * self.bigBlind: return do_call_preflop() return FOLD else: return do_call () # return do_call() # if CHECK in avail_actions: # random_nig = random.random() # if random_nig < self.opp_fold_thres: # print "MINBET: " + str(self.minBet) # return BET + ":" + str(self.minBet) return CHECK def getaction_handler(self, received_packet): # for action in received_packet['last_action']: # split_action = action.split(":") self.list_of_stacksizes = received_packet['stack_size'] self.my_stacksize = self.list_of_stacksizes[self.my_seat - 1] self.potsize = received_packet['potsize'] self.num_active_players = received_packet['num_active_players'] self.boardcards = received_packet['boardcards'] self.foundFaceCard = self.faceCardOnTable(self.boardcards) # print "FACE CARD CHECK", self.foundFaceCard last_actions = received_packet['last_action'] ################################################################# self.STATS.recordActions(last_actions) ################################################################# self.lastRaiser = None self.oppCheckedThisRound = False for act in last_actions: sp = act.split(":") name = sp[-1] if sp[0] == DEAL: self.oppCheckedThisRound = False if name in self.opp_dict: self.opp_dict[name].last_action = sp[0] if sp[0] == FOLD: self.opp_dict[name].status = FOLDED self.one_folded = True if sp[0] == BET or sp[0] == RAISE: self.lastRaiser = name if sp[0] == CHECK: self.oppCheckedThisRound = True for name in self.opp_dict: self.opp_dict[name].stack_size = self.list_of_stacksizes[self.opp_dict[name].seat] if self.opp_dict[name].status == ACTIVE: self.guy_active = name # print '###################################' # for shit in self.opp_dict: # print shit # print self.opp_dict[shit].stack_size # print self.opp_dict[shit].status # print self.opp_dict[shit].last_action # print '###################################' # determine if we are still in the same betting round to prevent raising to infinity problem if received_packet['num_boardcards'] == self.num_boardcards: self.is_new_round = False else: self.is_new_round = True self.highestRaiseAmtThisRnd = 0 self.num_boardcards = received_packet['num_boardcards'] self.isPreflop = (self.num_boardcards == 0) for action in received_packet['legal_actions']: split_action = action.split(":") if split_action[0] == BET: self.minBet = int(split_action[1]) self.maxBet = int(split_action[2]) elif split_action[0] == RAISE: self.minRaise = int(split_action[1]) self.maxRaise = int(split_action[2]) elif split_action[0] == CALL: self.call_amount = int(split_action[1]) self.inc_call_amount = self.call_amount - self.highestRaiseAmtThisRnd avail_actions = [(e.split(":"))[0] for e in received_packet['legal_actions']] action = self.get_best_action (received_packet, avail_actions) ############################################################################################### # self.STATS.updateOpponentStatistics(received_packet, self.hand_id, action) ############################################################################################### s.send(action + "\n") def handover_handler(self, received_packet): ############################################################################################### self.foundFaceCard = False self.STATS.updateOpponentStatistics(received_packet, self.num_active_players, self.monte_carlo_iter / 5) ############################################################################################### def requestkeyvalue_handler(self, received_packet): # At the end, the engine will allow your bot save key/value pairs. # Send FINISH to indicate you're done. ############################################################################################### self.STATS.compileMatchStatistics(self.history_storage, s, int(received_packet['bytesLeft'])) ############################################################################################### s.send("FINISH\n") def run(self, input_socket): # Get a file-object for reading packets from the socket. # Using this ensures that you get exactly one packet per read. f_in = input_socket.makefile() while True: # Block until the engine sends us a packet. data = f_in.readline().strip() # If data is None, connection has closed. if not data: print "Gameover, engine disconnected." break # Here is where you should implement code to parse the packets from # the engine and act on it. We are just printing it instead. received_packet = packet_parse.parse_given_packet(data) # When appropriate, reply to the engine with a legal action. # The engine will ignore all spurious responses. # The engine will also check/fold for you if you return an # illegal action. # When sending responses, terminate each response with a newline # character (\n) or your bot will hang! # this print statement is so that the stupid piece of shit Batman won't run into an error print data if received_packet['packet_name'] == "KEYVALUE": self.keyval_handler(received_packet) elif received_packet['packet_name'] == "NEWGAME": self.newgame_handler(received_packet) elif received_packet['packet_name'] == "NEWHAND": self.newhand_handler(received_packet) elif received_packet['packet_name'] == "GETACTION": self.getaction_handler(received_packet) elif received_packet['packet_name'] == "HANDOVER": self.handover_handler(received_packet) elif received_packet['packet_name'] == "REQUESTKEYVALUES": self.requestkeyvalue_handler(received_packet) # Clean up the socket. s.close()