def add_bet(state, total): # amount: 本局需要下的总注 amount = total - state.player[state.currpos].totalbet assert (amount > state.player[state.currpos].bet) # Obey the rule of last_raised minamount = state.last_raised + state.minbet real_amount = max(amount, minamount) # money_needed = real_amount - state.player[state.currpos].bet decision = Decision() decision.raisebet = 1 decision.amount = real_amount return decision
def make_decision(self, state): # record run time for making one decision if self.record_time: start_time = time.time() shared_cards = state.sharedcards.copy() my_id = state.currpos # see which round we are at, based on length of shared cards if len(shared_cards) == 0: round = 0 elif len(shared_cards) == 3: round = 1 elif len(shared_cards) == 4: round = 2 else: round = 3 my_cards = state.player[my_id].cards remain_card = list(range(0, 52)) for x in shared_cards: remain_card.pop(remain_card.index(x)) for x in my_cards: remain_card.pop(remain_card.index(x)) # check how many players are still alive # check how many players are making bold bet (larger than big blind) alive_players_num = 0 bold_better_list = [] for player_id in range(len(state.player)): if state.player[player_id].active & (player_id != my_id): player = state.player[player_id] alive_players_num += 1 total_bet = player.totalbet + player.bet if total_bet > 40: wealth = player.money + total_bet bold_better_list.append( bold_better(player=player, total_bet=total_bet, wealth=wealth)) def simulate_win_rate(in_hand_cards, bold_better_list=[], iterate=self.win_rate_sim_iterate): win_count = 0 _remain_card = list(range(0, 52)) for x in shared_cards: _remain_card.pop(_remain_card.index(x)) for x in in_hand_cards: _remain_card.pop(_remain_card.index(x)) # iterate, simulate unguessed players' cards, shared cards for i in range(iterate): _remain_card_sim = _remain_card.copy() other_players_cards_sim = [] random.shuffle(_remain_card_sim) for _bold_better in bold_better_list: player_cards = random.choice(_bold_better.card_guess) other_players_cards_sim.append(player_cards) for x in player_cards: if x in _remain_card_sim: _remain_card_sim.pop(_remain_card_sim.index(x)) for player in range(alive_players_num - len(bold_better_list)): player_cards = [] player_cards.append(_remain_card_sim.pop()) player_cards.append(_remain_card_sim.pop()) # player_hand = Hand(player_cards) other_players_cards_sim.append(player_cards) shared_cards_sim = shared_cards.copy() my_cards_sim = in_hand_cards.copy() random.shuffle(_remain_card_sim) while len(shared_cards_sim) < 5: shared_cards_sim.append(_remain_card_sim.pop()) my_cards_shared_cards_sim = my_cards_sim + shared_cards_sim # my_hand = Hand(my_cards_sim) win = 0 even = 0 assert (alive_players_num == len(other_players_cards_sim)) survive = True for other_player_cards_sim in other_players_cards_sim: compare = judge_two( other_player_cards_sim + shared_cards_sim, my_cards_shared_cards_sim) if compare == 0: even += 1 if compare == -1: survive = False if compare == 1: win += 1 if win == alive_players_num: win_count += 1 # if even, counted as elif survive == True: win_count += 1 / (even + 1) win_rate = win_count / iterate return win_rate # simulate possible in-hand cards set for bold better, calculate win rate def remove_known_card(card, card_set): card_set_ = [x for x in card_set if card not in x.cards] return card_set_ _shared_cards = shared_cards.copy() def rank_with_shared_card(hand_cards1, hand_cards2): result = judge_two( list(hand_cards1) + _shared_cards, list(hand_cards2) + _shared_cards) return result if len(bold_better_list) != 0: if round == 0: guess_card_list_full = pickle.load( open( '/Users/Simon-CWG/Documents/quantresearch/Texaspoker/modules/texaspoker/AI/research/pair_score_sorted', 'rb')) for x in shared_cards: guess_card_list_full = remove_known_card( x, guess_card_list_full) for x in my_cards: guess_card_list_full = remove_known_card( x, guess_card_list_full) else: guess_card_list_full = [] remain_card_comb = list(combinations(remain_card, 2)) remain_card_comb = sorted( remain_card_comb, key=functools.cmp_to_key(rank_with_shared_card)) hand_level = 10 pair = remain_card_comb[0] hand = Hand(list(pair) + shared_cards) hand_level = hand.level while hand_level >= 3: guess_card_list_full.append( guess_cards(cards=list(remain_card_comb.pop(0)))) if len(remain_card_comb) == 0: break pair = remain_card_comb[0] hand = Hand(list(pair) + shared_cards) hand_level = hand.level guess_card_list_full = list(reversed(guess_card_list_full)) if len(remain_card_comb) > 0: print('number of simulations: ', len(remain_card_comb)) remain_card_comb = map((lambda x: guess_cards( cards=list(x), shared_cards=shared_cards)), remain_card_comb) pool = multiprocessing.Pool() # guess_card_list_full = pool.map(lambda x: pickable_simulate_win_rate(x, shared_cards=shared_cards), card_only) guess_card_list_rest = pool.map(pickable_simulate_win_rate, remain_card_comb) pool.close() guess_card_list_rest = sorted(guess_card_list_rest, key=(lambda x: x.win_rate)) guess_card_list_full = guess_card_list_rest + guess_card_list_full # assess bold better's confidence based on their betting, bayesian style for _bold_better in bold_better_list: _invest_base = min(_bold_better.wealth, self.bold_better_invest_base_upper) _invest_base = max(_invest_base, self.bold_better_invest_base_lower) confidence = (_bold_better.total_bet / _invest_base)**(1 / self.bold_better_risk_averse) # set confidence upper bound for different round confidence = min(confidence, self.confidence_upper_bound[round]) # take upper subset of guess cards based on confidence guess_card_list_part = guess_card_list_full[ int(confidence * len(guess_card_list_full)):] guess_card_list = [i.cards for i in guess_card_list_part] _bold_better.card_guess = guess_card_list # finally, simulate my win rate given bold betters' cards guessed my_win_rate = simulate_win_rate(in_hand_cards=my_cards, bold_better_list=bold_better_list) if self.record_time: print("simulate guess book finish --- %s seconds ---" % (time.time() - start_time)) # print('estimated win rate: ', my_win_rate) # make decision decision = Decision() delta = state.minbet - state.player[state.currpos].bet me = state.player[my_id] wealth = me.money + me.totalbet + me.bet def add_bet(state, total): # amount: 本局需要下的总注 amount = total - state.player[state.currpos].totalbet assert (amount > state.player[state.currpos].bet) if amount > me.money: decision.allin = 1 return decision # Obey the rule of last_raised min_amount = state.last_raised + state.minbet real_amount = max(amount, min_amount) # money_needed = real_amount - state.player[state.currpos].bet decision.raisebet = 1 decision.amount = int(real_amount) return decision # set target total bet # if win rate smaller than average win rate ( 1 / number of players), fold if my_win_rate < 1 / (alive_players_num + 1): target = 0 # if high win rate, bet based on current wealth elif my_win_rate > 0.75: base = max(state.player[state.currpos].money, self.invest_base_lower) base = min(base, self.invest_base_upper) target = my_win_rate**self.risk_averse * base + 15 # if modest win rate, bet based on $2000 else: base = 2000 target = my_win_rate**self.risk_averse * base + 15 target = min(target, wealth * 0.6) # if nearly broke and good win rate, all in if (wealth <= 300) & (my_win_rate > 0.6): decision.allin = 1 return decision at_stake = me.totalbet + me.bet # make action based on target # if target less than minimum bet if (state.minbet + state.player[state.currpos].totalbet) >= target: # call if free to if delta == 0: decision.callbet = 1 # compare expected loss of fold and expected loss of call, choose smaller loss else: er_giveup = -at_stake er_call = -(1 - my_win_rate) * ( at_stake + delta) + my_win_rate * (state.moneypot) if er_giveup >= er_call: decision.giveup = 1 else: decision.callbet = 1 # if target grater than minimum bet, raise bet else: decision = add_bet(state, target) if self.log: log_text = 'estimated win rate, ' + str( my_win_rate) + ', ' + 'target, ' + str(target) print(log_text) state.logger.info(log_text) if self.record_time: print("FINISH--- %s seconds ---" % (time.time() - start_time)) return decision
def ai(id, state): shared_cards = state.sharedcards.copy() my_cards = state.player[id].cards remain_card = list(range(0, 52)) for x in shared_cards: remain_card.pop(remain_card.index(x)) for x in my_cards: remain_card.pop(remain_card.index(x)) # guess other player's card strength based on their betting alive_players = [] for player_id in range(len(state.player)): if state.player[id].active & player_id != id: alive_players.append(state.player[id]) for player in alive_players: guess_card_list = [] for i in range(1000): guess_card = [] heap = remain_card[:] random.shuffle(heap) guess_card.append(heap.pop()) guess_card.append(heap.pop()) for i in range(100): pass # 模拟发牌1000次 def simulate_win_rate(inhand_cards, other_player_cards = []): win_count = 0 _remain_card = list(range(0, 52)) for x in shared_cards: _remain_card.pop(remain_card.index(x)) for x in inhand_cards: _remain_card.pop(remain_card.index(x)) for i in range(1000): score = 0 for player in range(len(alive_players)): player_cards = [] if len(other_player_cards) == 0: player_cards.append(heap.pop()) player_cards.append(heap.pop()) player_cards = player_cards # player_hand = Hand(player_cards) other_player_cards.append(player_cards) else: pass # player_hand = other_player_cards[player]. shared_cards_sim = shared_cards my_cards_sim = inhand_cards heap = remain_card[:] random.shuffle(heap) while len(shared_cards_sim) < 5: shared_cards_sim.append(heap.pop()) my_cards_sim = my_cards_sim + shared_cards # my_hand = Hand(my_cards_sim) # other_player = [] score += judge_two(my_cards_sim, player_cards) if score == -len(alive_players): win_count += 1 win_rate = win_count / 1000 return win_rate my_win_rate = simulate_win_rate(inhand_cards = my_cards) decision = Decision() def add_bet(state, total): # amount: 本局需要下的总注 amount = total - state.player[state.currpos].totalbet assert (amount > state.player[state.currpos].bet) # Obey the rule of last_raised minamount = state.last_raised + state.minbet real_amount = max(amount, minamount) # money_needed = real_amount - state.player[state.currpos].bet decision.raisebet = 1 decision.amount = int(real_amount) return decision delta = state.minbet - state.player[state.currpos].bet target = my_win_rate**5 * state.player[state.currpos].money if (state.player[state.currpos].bet + state.player[state.currpos].totalbet) >= target: if delta == 0: decision.callbet = 1 else: decision.giveup = 1 else: decision = add_bet(state, target) return decision
def ai(id, state, risk_averse=2, log=True): start_time = time.time() shared_cards = state.sharedcards.copy() if len(shared_cards) == 0: round = 0 elif len(shared_cards) == 3: round = 1 elif len(shared_cards) == 4: round = 2 else: round = 3 my_cards = state.player[id].cards remain_card = list(range(0, 52)) for x in shared_cards: remain_card.pop(remain_card.index(x)) for x in my_cards: remain_card.pop(remain_card.index(x)) # guess other player's card strength based on their betting alive_players = [] for player_id in range(len(state.player)): if state.player[player_id].active & (player_id != id): alive_players.append(state.player[player_id]) bold_better = [] for alive_player in alive_players: total = alive_player.totalbet + alive_player.bet if total > 40: bold_better.append(alive_player) def simulate_win_rate(inhand_cards, other_player_cards=[], iterate=1000): win_count = 0 _remain_card = list(range(0, 52)) for x in shared_cards: _remain_card.pop(_remain_card.index(x)) for x in inhand_cards: _remain_card.pop(_remain_card.index(x)) for i in range(iterate): heap = _remain_card.copy() other_player_cards_sim = [] random.shuffle(heap) for player in range(len(other_player_cards)): player_cards = random.choice(other_player_cards[player]) other_player_cards_sim.append(player_cards) for x in player_cards: if x in heap: heap.pop(heap.index(x)) for player in range(len(alive_players) - len(other_player_cards)): player_cards = [] player_cards.append(heap.pop()) player_cards.append(heap.pop()) # player_hand = Hand(player_cards) other_player_cards_sim.append(player_cards) shared_cards_sim = shared_cards.copy() my_cards_sim = inhand_cards.copy() random.shuffle(heap) while len(shared_cards_sim) < 5: shared_cards_sim.append(heap.pop()) my_cards_sim = my_cards_sim + shared_cards_sim # my_hand = Hand(my_cards_sim) # other_player = [] score = 0 even = 0 assert (len(alive_players) == len(other_player_cards_sim)) for player in range(len(alive_players)): compare = judge_two( my_cards_sim, other_player_cards_sim[player] + shared_cards_sim) if compare == 0: even += 1 score += compare if score == -len(alive_players): win_count += 1 if even == alive_players: win_count += 0.5 win_rate = win_count / iterate return win_rate guess_book = [] guess_card_list_full = [] if len(bold_better) != 0: for i in range(100): guess_card = [] heap = remain_card[:] random.shuffle(heap) guess_card.append(heap.pop()) guess_card.append(heap.pop()) guess_card_win_rate = simulate_win_rate(inhand_cards=guess_card, iterate=50) guess_card_list_full.append([guess_card, guess_card_win_rate]) guess_card_list_full = sorted(guess_card_list_full, key=lambda x: x[1]) print("--- %s seconds ---" % (time.time() - start_time)) for player_id in range(len(bold_better)): cache_wealth = alive_players[player_id].money + alive_players[ player_id].bet + alive_players[player_id].totalbet cache_invest_base = min(cache_wealth, 4000) cache_invest_base = max(cache_invest_base, 1000) confidence = (alive_players[player_id].bet / cache_invest_base)**(1 / 2) if round == 0: confidence = min(confidence, 0.8) elif round == 1: confidence = min(confidence, 0.9) elif round == 2: confidence = min(confidence, 0.95) elif round == 3: confidence = min(confidence, 0.98) guess_card_list_part = guess_card_list_full[ int(confidence * len(guess_card_list_full)):] guess_card_list = [i[0] for i in guess_card_list_part] guess_book.append(guess_card_list) my_win_rate = simulate_win_rate(inhand_cards=my_cards, other_player_cards=guess_book) print("--- %s seconds ---" % (time.time() - start_time)) # print('estimated win rate: ', my_win_rate) decision = Decision() delta = state.minbet - state.player[state.currpos].bet me = state.player[id] wealth = me.money + me.totalbet + me.bet def add_bet(state, total): # amount: 本局需要下的总注 amount = total - state.player[state.currpos].totalbet assert (amount > state.player[state.currpos].bet) if amount > me.money: decision.allin = 1 return decision # Obey the rule of last_raised minamount = state.last_raised + state.minbet real_amount = max(amount, minamount) # money_needed = real_amount - state.player[state.currpos].bet decision.raisebet = 1 decision.amount = int(real_amount) return decision if my_win_rate < 1 / (len(alive_players) + 1): target = 0 elif my_win_rate > 0.75: base = max(state.player[state.currpos].money, 2000) base = min(base, 4000) target = my_win_rate**risk_averse * base + 15 else: base = 2000 target = my_win_rate**risk_averse * base + 15 target = 0.6 * min(target, wealth * 0.6) if (wealth <= 300) & (my_win_rate > 0.6): decision.allin = 1 return decision at_stake = state.player[id].totalbet + state.player[id].bet if (state.minbet + state.player[state.currpos].totalbet) >= target: if delta == 0: decision.callbet = 1 else: er_giveup = -at_stake er_call = -(1 - my_win_rate) * (at_stake + delta) + my_win_rate * ( state.moneypot) if er_giveup >= er_call: decision.giveup = 1 else: decision.callbet = 1 else: decision = add_bet(state, target) if log: log_text = 'estimated win rate, ' + str( my_win_rate) + ', ' + 'target, ' + str(target) print(log_text) state.logger.info(log_text) print("FINISH--- %s seconds ---" % (time.time() - start_time)) return decision
def ai(id, state): weight = [0, 1, 2, 4, 8, 16, 32, 64, 128, 256, 512] remain_card = list(range(0, 52)) cards = state.sharedcards + state.player[id].cards num = len(cards) for x in cards: remain_card.pop(remain_card.index(x)) cnt = [0 for col in range(11)] # 模拟发牌1000次 for i in range(1000): heap = remain_card[:] mycards = cards[:] random.shuffle(heap) while len(mycards) != 7: mycards.append(heap.pop()) hand = Hand(mycards) level = hand.level cnt[level] += weight[level] # sum为评估值 sum = 0 for x in cnt: sum += x / 1000 decision = Decision() totalbet = 0 delta = state.minbet - state.player[state.currpos].bet if delta >= state.player[state.currpos].money: totalbet = 1000 else: totalbet = state.player[state.currpos].totalbet + state.minbet if num == 2: # 两张牌 if cards[0] != cards[1]: # 非对子 if max(cards) <= 8 and 0 not in cards: # 最大不超过9:若跟注后超过100,放弃。否则跟注 if totalbet <= 100: decision.callbet = 1 else: decision.giveup = 1 if max(cards) <= 11 and 0 not in cards: # 最大为10-Q:若跟注后超过150,放弃。否则跟注 if totalbet <= 150: decision.callbet = 1 else: decision.giveup = 1 else: # 最大为K-A: 若跟注后超过200,放弃。否则跟注 if totalbet <= 200: decision.callbet = 1 else: decision.giveup = 1 else: # 对子 if max(cards) <= 11 and 0 not in cards: # 对子,不超过Q:跟注。若跟注后低于200,加注到200以上 if totalbet < 200: decision = add_bet(state, 200) else: decision.callbet = 1 else: # 双A、双K:跟注。若跟注后低于300,加注到300 if totalbet < 300: decision = add_bet(state, 300) else: decision.callbet = 1 elif num == 5: # 五张牌 if sum < 4: # 直接放弃 decision.giveup = 1 elif sum >= 4 and sum < 10: # 若跟注后超过150,放弃。否则跟注 # 若已下的注额大于200, 且本次需跟注额不大于50, 则跟注 if totalbet < 150: decision.callbet = 1 elif state.player[state.currpos].totalbet + state.player[ state.currpos].bet > 200 and delta < 50: decision.callbet = 1 else: decision.giveup = 1 elif sum >= 10 and sum < 20: # 跟注。若跟注后低于300,加注到300 if totalbet < 300: decision = add_bet(state, 300) else: decision.callbet = 1 elif sum >= 20 and sum < 50: # 跟注。若跟注后低于600,加注到600 if totalbet < 600: decision = add_bet(state, 600) else: decision.callbet = 1 else: # allin decision.allin = 1 elif num == 6: # 六张牌 if sum < 2: # 直接放弃 decision.giveup = 1 elif sum >= 2 and sum < 8: # 若跟注后超过300,放弃。否则跟注 # 若已下的注额大于200, 且本次需跟注额不大于50, 则跟注 if totalbet < 300: decision.callbet = 1 elif state.player[state.currpos].totalbet + state.player[ state.currpos].bet > 200 and delta < 50: decision.callbet = 1 else: decision.giveup = 1 elif sum >= 8 and sum < 20: # 跟注。若跟注后低于300,加注到300 if totalbet < 300: decision = add_bet(state, 300) else: decision.callbet = 1 elif sum >= 20 and sum < 40: # 跟注。若跟注后低于600,加注到600 if totalbet < 600: decision = add_bet(state, 600) else: decision.callbet = 1 else: # allin decision.allin = 1 elif num == 7: # 七张牌 if level == 7: # allin decision.allin = 1 elif level == 6: # 跟注,若跟注后低于600,加注到600 if totalbet < 600: decision = add_bet(state, 600) else: decision.callbet = 1 elif level == 5: # 跟注,若跟注后低于500,加注到500 if totalbet < 500: decision = add_bet(state, 500) else: decision.callbet = 1 elif level == 4: # 跟注,若跟注后低于400,加注到400 if totalbet < 400: decision = add_bet(state, 400) else: decision.callbet = 1 elif level == 3: # 若跟注后超过500,放弃。否则跟注。若跟注后低于300,加注到300 # 若已下的注额大于200, 且本次需跟注额不大于50, 则跟注 if totalbet < 300: decision = add_bet(state, 300) elif totalbet < 500: decision.callbet = 1 elif state.player[state.currpos].totalbet + state.player[ state.currpos].bet > 200 and delta < 50: decision.callbet = 1 else: decision.giveup = 1 elif level == 2: if cards.count(0) == 2 or cards.count(12) == 2: # 双A双K 若跟注后超过200,放弃。否则跟注 # 若已下的注额大于200, 且本次需跟注额不大于50, 则跟注 if totalbet < 200: decision.callbet = 1 elif state.player[state.currpos].totalbet + state.player[ state.currpos].bet > 200 and delta < 50: decision.callbet = 1 else: decision.giveup = 1 else: # 不超过双Q 若跟注后超过200,放弃。否则跟注 if totalbet > 200: decision.giveup = 1 else: decision.callbet = 1 elif level == 1: decision.giveup = 1 else: print('the num of cards is {}'.format(num)) assert (0) if decision.callbet == 1 and delta == state.player[state.currpos].money: decision.callbet = 0 decision.allin = 1 if decision.callbet == 1 and state.minbet == 0: t = random.randint(0, 2) if t == 0: decision.callbet = 0 decision.raisebet = 1 decision.amount = state.bigBlind return decision