class GenPlayer(BasePokerPlayer): # Setup Emulator object by registering game information def receive_game_start_message(self, game_info): player_num = game_info["player_num"] max_round = game_info["rule"]["max_round"] small_blind_amount = game_info["rule"]["small_blind_amount"] ante_amount = game_info["rule"]["ante"] blind_structure = game_info["rule"]["blind_structure"] self.emulator = Emulator() self.emulator.set_game_rule(player_num, max_round, small_blind_amount, ante_amount) self.emulator.set_blind_structure(blind_structure) # Register algorithm of each player which used in the simulation. for player_info in game_info["seats"]["players"]: self.emulator.register_player(player_info["uuid"], RandomPlayer()) def declare_action(self, valid_actions, hole_card, round_state): game_state = restore_game_state(round_state) # decide action by using some simulation result updated_state, events = self.emulator.apply_action(game_state, "fold") # updated_state, events = self.emulator.run_until_round_finish(game_state) # updated_state, events = self.emulator.run_until_game_finish(game_state) if self.is_good_simulation_result(updated_state): return # you would declare CALL or RAISE action else: return "fold", 0
class ModelPlayer(BasePokerPlayer): table_name = "gameinfotbl" standard_insert = "Player_name, win_rate, hole_cards, community_cards, action, stack, small_blind_amount" db_name = "game_information.db" street = ['preflop', 'flop', 'turn', 'river', 'showdown'] def __init__(self, name): self.name = name self.seat = None self.raise_amount = 0 self.win_rate = None self.stack = None self.small_blind_amount = None self.hole_card = None self.community_card = None self.action = None self.opponent_raise_threshold = 0.7 self.opponent_bluffing_ratio = 0.5 self.__init_database() self.Opponent_Model = OpponentModel("Opponent", 0.5, 0.5) self.my_model = MyModel() def declare_action(self, valid_actions, hole_card, round_state): # try_actions = [MyModel.FOLD, MyModel.CALL, MyModel.RAISE] # community_card = round_state['community_card'] pot = round_state['pot']['main']['amount'] call_amount = valid_actions[1]['amount'] self.raise_amount = valid_actions[2]['amount']['min'] # round_strategy = {'preflop' : 0, 'flop' : 0, 'turn' : 0, 'river' : 0, 'showdown' : 0} # street_now = round_state['street'] # # self.win_rate = estimate_hole_card_win_rate(nb_simulation = NB_SIMULATION, # # nb_player = self.nb_player, # # hole_card=gen_cards(hole_card), # # community_card=gen_cards(community_card)) # action_results = [0 for i in range(len(try_actions))] # # win_rate = calculate_win_rate_with_model(hole_card, community_card) # log("hole_card of emulator player is %s" % hole_card) # for action_now in try_actions: # round_strategy[round_state['street']] = action_now # for street in enumerate(self.street, self.street.index(street_now) + 1): # for action_later in try_actions: # round_strategy[street] = action_later # self.my_model.set_round_strategy(round_strategy) # simulation_results = [] # for _ in range(NB_SIMULATION): # game_state = self._setup_game_state(round_state, hole_card) # round_finished_state, _events = self.emulator.run_until_round_finish(game_state) # new_winner_uuid = _events[-1]['winners'][-1]['uuid'] # my_stack = [player for player in round_finished_state['table'].seats.players if player.uuid == self.uuid][0].stack # simulation_results.append(my_stack) # if action_results[action_now] < 1.0 * sum(simulation_results) / NB_SIMULATION: # action_results[action_now] = 1.0 * sum(simulation_results) / NB_SIMULATION # log("average stack after simulation when declares %s : %s" % ( # {0:'FOLD', 1:'CALL', 2:'RAISE'}[action_now], action_results[action_now]) # ) # best_action = max(zip(action_results, try_actions))[1] # round_strategy[round_state['street']] = best_action # self.my_model.set_round_strategy(round_strategy) # declare_action, amount = self.my_model.declare_action(valid_actions, hole_card, round_state) # if declare_action == "FOLD": # self.action = 0 # elif declare_action == "CALL": # self.action = 1 # else: # self.action = 2 # self.record_action() win_rate_with_model = self.estimate_win_rate_with_model_to_convergent( hole_card, round_state) print(win_rate_with_model) ev = self.ev_calculation(win_rate_with_model, pot, call_amount) if ev.index(max(ev)) == 0: return valid_actions[0]['action'], valid_actions[0]['amount'] elif ev.index(max(ev)) == 1: return valid_actions[1]['action'], valid_actions[1]['amount'] else: return valid_actions[2]['action'], valid_actions[2]['amount'][ 'min'] def receive_game_start_message(self, game_info): self.nb_player = game_info['player_num'] self.small_blind_amount = game_info['rule']['small_blind_amount'] self.Opponent_Model.set_nb_player(self.nb_player) self.my_model = MyModel() max_round = game_info['rule']['max_round'] sb_amount = game_info['rule']['small_blind_amount'] ante_amount = game_info['rule']['ante'] for player in game_info['seats']: if player['uuid'] == self.uuid: self.seat = game_info['seats'].index(player) break else: raise ('not participating!') self.emulator = Emulator() self.emulator.set_game_rule(self.nb_player, max_round, sb_amount, ante_amount) for player_info in game_info['seats']: uuid = player_info['uuid'] player_model = self.my_model if uuid == self.uuid else self.Opponent_Model self.emulator.register_player(uuid, player_model) def receive_round_start_message(self, round_count, hole_card, seats): self.self_bet = 0 self.hole_card = hole_card def receive_street_start_message(self, street, round_state): self.community_card = round_state['community_card'] def receive_game_update_message(self, action, round_state): if action['player_uuid'] == self.uuid: self.self_bet = self.self_bet + action['amount'] Opponent_bet = round_state['pot']['main']['amount'] - self.self_bet self.Opponent_Model.set_bet(Opponent_bet) self.stack = round_state['seats'][self.seat]['stack'] def receive_round_result_message(self, winners, hand_info, round_state): pass def record_action(self): msg_record = self.__make_message() con = lite.connect(self.db_name) with con: cur = con.cursor() cur.execute( "INSERT INTO gameinfotbl(Player_name, win_rate, hole_cards, community_cards, action, stack, small_blind_amount) VALUES(?,?,?,?,?,?,?)", msg_record) ####################################################################### def ev_calculation(self, win_rate, pot, call_amount): ev = [0 for i in range(3)] ev[0] = -self.self_bet ev[1] = win_rate * (pot - self.self_bet) - (1 - win_rate) * ( self.self_bet + call_amount) ev[2] = win_rate * (pot - self.self_bet + self.raise_amount) - \ (1 - win_rate) * (self.self_bet + self.raise_amount + call_amount) return ev # def choose_action(self, win_rate, pot, valid_actions): # r = rand.random() # ev = self.ev_calculation(win_rate, pot, valid_actions[1]['amount']) # if win_rate >= self.raise_threshold: # return valid_actions[2]['action'], 2 * self.small_blind_amount # elif r >= self.bluffing_ratio: # return valid_actions[2]['action'], 2 * self.small_blind_amount # elif ev[1] >= ev[0]: # return valid_actions[1]['action'], valid_actions[1]['amount'] # else: # return valid_actions[0]['action'], valid_actions[0]['amount'] def _setup_game_state(self, round_state, my_hole_card): game_state = restore_game_state(round_state) game_state['table'].deck.shuffle() community_card = round_state['community_card'] current_street = round_state['street'] player_uuids = [ player_info['uuid'] for player_info in round_state['seats'] ] for uuid in player_uuids: if uuid == self.uuid: game_state = attach_hole_card( game_state, uuid, gen_cards(my_hole_card)) # attach my holecard else: while True: opponent_card = assuming_card(gen_cards(my_hole_card)) if not self.is_already_fold(opponent_card, current_street, community_card): break game_state = attach_hole_card( game_state, uuid, opponent_card) # attach opponents holecard at random return game_state def __make_message(self): msg = [] msg.append(self.name) msg.append(self.win_rate) msg.append(str(self.hole_card)) msg.append(str(self.community_card)) msg.append(self.action) msg.append(self.stack) msg.append(self.small_blind_amount) return msg def __init_database(self): con = lite.connect(self.db_name) with con: cur = con.cursor() cur.execute( "CREATE TABLE IF NOT EXISTS {tbl_name}(_Id INTEGER PRIMARY KEY, Player_name TEXT, win_rate REAL, \ hole_cards TEXT, community_cards TEXT, action INT, stack INT, small_blind_amount INT)" .format(tbl_name=self.table_name)) def _modify_round_strategy_list(self, action, street, round_strategy): round_strategy['street'] = action def is_already_fold(self, opponent_card, current_street, community_card): win_rate = 0 r = rand.random() str_card = [str(a) for a in opponent_card] for street in street_table.keys(): win_rate = get_broad_win_rate( str_card, community_card[0:street_table[street]]) if win_rate < self.opponent_raise_threshold and r < self.opponent_bluffing_ratio: return True if street == current_street or street == 'river': break return False def simulate_one_time(self, round_state, hole_card): game_state = self._setup_game_state(round_state, hole_card) _round_finished_state, _events = self.emulator.run_until_round_finish( game_state) if _events[-1]['type'] == 'event_game_finish': return 0 #if not 0, the last round will report a error new_winner_uuid = _events[-1]['winners'][-1]['uuid'] # my_stack = [player for player in round_finished_state['table'].seats.players if player.uuid == self.uuid][0].stack # simulation_results.append(my_stack) return 1 if new_winner_uuid == self.uuid else 0 def calculate_win_rate_with_model_serval_time(self, round_state, hole_card, nb_simulation): win_count = sum([ self.simulate_one_time(round_state, hole_card) for _ in range(nb_simulation) ]) return 1.0 * win_count / nb_simulation def estimate_win_rate_with_model_to_convergent(self, hole_card, round_state): ls_win_rate = [.0 for _ in range(10)] rpt_times = 50 counter = 0 ##the newer calculated win percentage must be the avarage number while True: newer_win_rate = self.calculate_win_rate_with_model_serval_time( round_state, hole_card, rpt_times) ls_win_rate.pop(0) itered_win_rate = (ls_win_rate[-1] * counter + newer_win_rate) / (counter + 1) ls_win_rate.append(itered_win_rate) if (np.max(ls_win_rate) - np.min(ls_win_rate)) < 0.1: break counter = counter + 1 return ls_win_rate[-1]
class EmulatorTest(BaseUnitTest): def setUp(self): self.emu = Emulator() def test_set_game_rule(self): self.emu.set_game_rule(2, 8, 5, 3) self.eq(2, self.emu.game_rule['player_num']) self.eq(8, self.emu.game_rule['max_round']) self.eq(5, self.emu.game_rule['sb_amount']) self.eq(3, self.emu.game_rule['ante']) def test_register_and_fetch_player(self): p1, p2 = FoldMan(), FoldMan() self.emu.register_player('uuid-1', p1) self.emu.register_player('uuid-2', p2) self.eq(p1, self.emu.fetch_player('uuid-1')) self.eq(p2, self.emu.fetch_player('uuid-2')) @raises(TypeError) def test_register_invalid_player(self): self.emu.register_player('uuid', 'hoge') def test_blind_structure(self): game_state = restore_game_state(TwoPlayerSample.round_state) game_state = attach_hole_card_from_deck(game_state, 'tojrbxmkuzrarnniosuhct') game_state = attach_hole_card_from_deck(game_state, 'pwtwlmfciymjdoljkhagxa') self.emu.set_game_rule(2, 10, 5, 0) self.emu.set_blind_structure({5: {'ante': 5, 'small_blind': 60}}) p1 = TestPlayer([('fold', 0), ('raise', 55), ('call', 0)]) p2 = TestPlayer([('call', 15), ('call', 55), ('fold', 0)]) self.emu.register_player('tojrbxmkuzrarnniosuhct', p1) self.emu.register_player('pwtwlmfciymjdoljkhagxa', p2) game_state, events = self.emu.run_until_round_finish(game_state) self.eq(65, game_state['table'].seats.players[0].stack) self.eq(135, game_state['table'].seats.players[1].stack) game_state, events = self.emu.start_new_round(game_state) game_state, events = self.emu.run_until_round_finish(game_state) self.eq(120, game_state['table'].seats.players[0].stack) self.eq(80, game_state['table'].seats.players[1].stack) game_state, events = self.emu.start_new_round(game_state) self.eq('event_game_finish', events[0]['type']) self.eq(0, game_state['table'].seats.players[0].stack) self.eq(80, game_state['table'].seats.players[1].stack) def test_blind_structure_update(self): self.emu.set_game_rule(2, 8, 5, 3) p1, p2 = FoldMan(), FoldMan() self.emu.register_player('uuid-1', p1) self.emu.register_player('uuid-2', p2) blind_structure = { 3: { 'ante': 5, 'small_blind': 10 }, 5: { 'ante': 10, 'small_blind': 20 } } self.emu.set_blind_structure(blind_structure) players_info = { 'uuid-1': { 'name': 'hoge', 'stack': 100 }, 'uuid-2': { 'name': 'fuga', 'stack': 100 } } state = self.emu.generate_initial_game_state(players_info) self.eq(5, state['small_blind_amount']) state, _ = self.emu.start_new_round(state) state, _ = self.emu.apply_action(state, 'fold') self.eq(5, state['small_blind_amount']) state, _ = self.emu.apply_action(state, 'fold') self.eq(5, state['small_blind_amount']) state, _ = self.emu.apply_action(state, 'fold') self.eq(10, state['small_blind_amount']) state, _ = self.emu.apply_action(state, 'fold') self.eq(10, state['small_blind_amount']) state, _ = self.emu.apply_action(state, 'fold') self.eq(20, state['small_blind_amount']) state, _ = self.emu.apply_action(state, 'fold') self.eq(20, state['small_blind_amount']) def test_apply_action(self): game_state = restore_game_state(TwoPlayerSample.round_state) game_state = attach_hole_card_from_deck(game_state, 'tojrbxmkuzrarnniosuhct') game_state = attach_hole_card_from_deck(game_state, 'pwtwlmfciymjdoljkhagxa') self.emu.set_game_rule(2, 10, 5, 0) p1, p2 = FoldMan(), FoldMan() self.emu.register_player('tojrbxmkuzrarnniosuhct', FoldMan()) self.emu.register_player('pwtwlmfciymjdoljkhagxa', FoldMan()) game_state, events = self.emu.apply_action(game_state, 'call', 15) self.eq(Const.Street.RIVER, game_state['street']) self.eq( TwoPlayerSample.p1_action_histories, game_state['table'].seats.players[0].round_action_histories[ Const.Street.TURN]) self.eq(2, len(events)) self.eq('event_new_street', events[0]['type']) self.eq('event_ask_player', events[1]['type']) game_state, events = self.emu.apply_action(game_state, 'call', 0) self.eq(1, len(events)) self.eq('event_ask_player', events[0]['type']) game_state, events = self.emu.apply_action(game_state, 'call', 0) self.eq(1, len(events)) self.eq('event_round_finish', events[0]['type']) def test_apply_action_game_finish_detect(self): game_state = restore_game_state(TwoPlayerSample.round_state) game_state = attach_hole_card_from_deck(game_state, 'tojrbxmkuzrarnniosuhct') game_state = attach_hole_card_from_deck(game_state, 'pwtwlmfciymjdoljkhagxa') self.emu.set_game_rule(2, 3, 5, 0) p1, p2 = FoldMan(), FoldMan() self.emu.register_player('tojrbxmkuzrarnniosuhct', FoldMan()) self.emu.register_player('pwtwlmfciymjdoljkhagxa', FoldMan()) game_state, events = self.emu.apply_action(game_state, 'fold') self.eq('event_game_finish', events[-1]['type']) def test_apply_action_start_next_round(self): game_state = restore_game_state(TwoPlayerSample.round_state) game_state = attach_hole_card_from_deck(game_state, 'tojrbxmkuzrarnniosuhct') game_state = attach_hole_card_from_deck(game_state, 'pwtwlmfciymjdoljkhagxa') self.emu.set_game_rule(2, 4, 5, 0) p1, p2 = FoldMan(), FoldMan() self.emu.register_player('tojrbxmkuzrarnniosuhct', FoldMan()) self.emu.register_player('pwtwlmfciymjdoljkhagxa', FoldMan()) game_state, events = self.emu.apply_action(game_state, 'fold') self.eq(120, game_state['table'].seats.players[0].stack) self.eq(80, game_state['table'].seats.players[1].stack) game_state, events = self.emu.apply_action(game_state, 'raise', 20) self.eq('event_ask_player', events[-1]['type']) self.eq(100, game_state['table'].seats.players[0].stack) self.eq(70, game_state['table'].seats.players[1].stack) @raises(Exception) def test_apply_action_when_game_finished(self): game_state = restore_game_state(TwoPlayerSample.round_state) game_state = attach_hole_card_from_deck(game_state, 'tojrbxmkuzrarnniosuhct') game_state = attach_hole_card_from_deck(game_state, 'pwtwlmfciymjdoljkhagxa') self.emu.set_game_rule(2, 3, 5, 0) p1, p2 = FoldMan(), FoldMan() self.emu.register_player('tojrbxmkuzrarnniosuhct', FoldMan()) self.emu.register_player('pwtwlmfciymjdoljkhagxa', FoldMan()) game_state, events = self.emu.apply_action(game_state, 'fold') self.emu.apply_action(game_state, 'fold') def test_run_until_round_finish(self): game_state = restore_game_state(TwoPlayerSample.round_state) game_state = attach_hole_card_from_deck(game_state, 'tojrbxmkuzrarnniosuhct') game_state = attach_hole_card_from_deck(game_state, 'pwtwlmfciymjdoljkhagxa') self.emu.set_game_rule(2, 10, 5, 0) p1 = TestPlayer([('fold', 0)]) p2 = TestPlayer([('call', 15)]) self.emu.register_player('tojrbxmkuzrarnniosuhct', p1) self.emu.register_player('pwtwlmfciymjdoljkhagxa', p2) game_state, events = self.emu.run_until_round_finish(game_state) self.eq('event_new_street', events[0]['type']) self.eq('event_ask_player', events[1]['type']) self.eq('event_round_finish', events[2]['type']) def test_run_until_round_finish_when_already_finished(self): game_state = restore_game_state(TwoPlayerSample.round_state) game_state = attach_hole_card_from_deck(game_state, 'tojrbxmkuzrarnniosuhct') game_state = attach_hole_card_from_deck(game_state, 'pwtwlmfciymjdoljkhagxa') self.emu.set_game_rule(2, 10, 5, 0) p1 = TestPlayer([('fold', 0)]) p2 = TestPlayer([('call', 15)]) self.emu.register_player('tojrbxmkuzrarnniosuhct', p1) self.emu.register_player('pwtwlmfciymjdoljkhagxa', p2) game_state, events = self.emu.run_until_round_finish(game_state) game_state, events = self.emu.run_until_round_finish(game_state) self.eq(0, len(events)) def test_run_until_round_finish_game_finish_detect(self): uuids = ['tojrbxmkuzrarnniosuhct', 'pwtwlmfciymjdoljkhagxa'] holecards = [[Card.from_str(s) for s in ss] for ss in [['Ac', '2d'], ['8c', '5h']]] game_state = restore_game_state(TwoPlayerSample.round_state) game_state = reduce(lambda a, e: attach_hole_card(a, e[0], e[1]), zip(uuids, holecards), game_state) game_state = attach_hole_card_from_deck(game_state, 'pwtwlmfciymjdoljkhagxa') self.emu.set_game_rule(2, 10, 5, 0) p1 = TestPlayer([('raise', 65)]) p2 = TestPlayer([('call', 15), ('call', 65)]) self.emu.register_player('tojrbxmkuzrarnniosuhct', p1) self.emu.register_player('pwtwlmfciymjdoljkhagxa', p2) game_state['table'].deck.deck.append(Card.from_str('7c')) game_state, events = self.emu.run_until_round_finish(game_state) self.eq('event_new_street', events[0]['type']) self.eq('event_ask_player', events[1]['type']) self.eq('event_ask_player', events[2]['type']) self.eq('event_round_finish', events[3]['type']) self.eq('event_game_finish', events[4]['type']) self.eq(0, events[4]['players'][0]['stack']) self.eq(200, events[4]['players'][1]['stack']) def test_run_until_game_finish(self): game_state = restore_game_state(TwoPlayerSample.round_state) game_state = attach_hole_card_from_deck(game_state, 'tojrbxmkuzrarnniosuhct') game_state = attach_hole_card_from_deck(game_state, 'pwtwlmfciymjdoljkhagxa') self.emu.set_game_rule(2, 10, 5, 1) self.emu.register_player('tojrbxmkuzrarnniosuhct', FoldMan()) self.emu.register_player('pwtwlmfciymjdoljkhagxa', FoldMan()) game_state, events = self.emu.run_until_game_finish(game_state) self.eq('event_game_finish', events[-1]['type']) self.eq(114, game_state['table'].seats.players[0].stack) self.eq(86, game_state['table'].seats.players[1].stack) def test_run_until_game_finish_when_one_player_is_left(self): uuids = [ 'ruypwwoqwuwdnauiwpefsw', 'sqmfwdkpcoagzqxpxnmxwm', 'uxrdiwvctvilasinweqven' ] holecards = [[Card.from_str(s) for s in ss] for ss in [['2c', '3c'], ['Ah', 'Ac'], ['5d', '6d']]] game_state = restore_game_state(ThreePlayerGameStateSample.round_state) game_state = reduce( lambda state, item: attach_hole_card(state, item[0], item[1]), zip(uuids, holecards), game_state) sb_amount, ante = 5, 7 self.emu.set_game_rule(3, 10, sb_amount, ante) p1_acts = [('fold', 0), ('call', 10), ('call', 0), ('call', 10), ('fold', 0)] p2_acts = [] p3_acts = [('raise', 10)] players = [TestPlayer(acts) for acts in [p1_acts, p2_acts, p3_acts]] [ self.emu.register_player(uuid, player) for uuid, player in zip(uuids, players) ] game_state['table'].deck.deck.append(Card.from_str('7c')) game_state, events = self.emu.run_until_game_finish(game_state) self.eq('event_game_finish', events[-1]['type']) self.eq(0, game_state['table'].seats.players[0].stack) self.eq(0, game_state['table'].seats.players[1].stack) self.eq(292, game_state['table'].seats.players[2].stack) def test_run_until_game_finish_when_final_round(self): uuids = [ 'ruypwwoqwuwdnauiwpefsw', 'sqmfwdkpcoagzqxpxnmxwm', 'uxrdiwvctvilasinweqven' ] holecards = [[Card.from_str(s) for s in ss] for ss in [['2c', '3c'], ['Ah', 'Ac'], ['5d', '6d']]] game_state = restore_game_state(ThreePlayerGameStateSample.round_state) game_state = reduce( lambda state, item: attach_hole_card(state, item[0], item[1]), zip(uuids, holecards), game_state) sb_amount, ante = 5, 7 self.emu.set_game_rule(3, 10, sb_amount, ante) [self.emu.register_player(uuid, FoldMan()) for uuid in uuids] game_state['table'].deck.deck.append(Card.from_str('7c')) game_state, events = self.emu.run_until_game_finish(game_state) self.eq('event_game_finish', events[-1]['type']) self.eq(10, game_state['round_count']) self.eq(35, game_state['table'].seats.players[0].stack) self.eq(0, game_state['table'].seats.players[1].stack) self.eq(265, game_state['table'].seats.players[2].stack) def test_last_round_judge(self): game_state = restore_game_state(TwoPlayerSample.round_state) self.emu.set_game_rule(2, 3, 5, 0) self.false(self.emu._is_last_round(game_state, self.emu.game_rule)) game_state['street'] = Const.Street.FINISHED self.true(self.emu._is_last_round(game_state, self.emu.game_rule)) game_state['round_count'] = 2 self.false(self.emu._is_last_round(game_state, self.emu.game_rule)) game_state['table'].seats.players[0].stack = 0 self.true(self.emu._is_last_round(game_state, self.emu.game_rule)) def test_start_new_round(self): game_state = restore_game_state(TwoPlayerSample.round_state) game_state = attach_hole_card_from_deck(game_state, 'tojrbxmkuzrarnniosuhct') game_state = attach_hole_card_from_deck(game_state, 'pwtwlmfciymjdoljkhagxa') p1, p2 = FoldMan(), FoldMan() self.emu.set_game_rule(2, 10, 5, 0) self.emu.register_player('tojrbxmkuzrarnniosuhct', FoldMan()) self.emu.register_player('pwtwlmfciymjdoljkhagxa', FoldMan()) # run until round finish game_state, event = self.emu.apply_action(game_state, 'call', 15) game_state, event = self.emu.apply_action(game_state, 'call', 0) game_state, event = self.emu.apply_action(game_state, 'call', 0) game_state, events = self.emu.start_new_round(game_state) self.eq(4, game_state['round_count']) self.eq(1, game_state['table'].dealer_btn) self.eq(0, game_state['street']) self.eq(0, game_state['next_player']) self.eq('event_new_street', events[0]['type']) self.eq('event_ask_player', events[1]['type']) self.eq('preflop', events[0]['street']) self.eq('tojrbxmkuzrarnniosuhct', events[1]['uuid']) def test_start_new_round_exclude_no_money_players(self): uuids = [ 'ruypwwoqwuwdnauiwpefsw', 'sqmfwdkpcoagzqxpxnmxwm', 'uxrdiwvctvilasinweqven' ] game_state = restore_game_state(ThreePlayerGameStateSample.round_state) original = reduce( lambda state, uuid: attach_hole_card_from_deck(state, uuid), uuids, game_state) sb_amount, ante = 5, 7 self.emu.set_game_rule(3, 10, sb_amount, ante) [self.emu.register_player(uuid, FoldMan()) for uuid in uuids] # case1: second player cannot pay small blind finish_state, events = self.emu.apply_action(original, 'fold') finish_state['table'].seats.players[0].stack = 11 stacks = [p.stack for p in finish_state['table'].seats.players] game_state, events = self.emu.start_new_round(finish_state) self.eq(2, game_state['table'].dealer_btn) self.eq(1, game_state['next_player']) self.eq(stacks[1] - sb_amount - ante, game_state['table'].seats.players[1].stack) self.eq(stacks[2] - sb_amount * 2 - ante, game_state['table'].seats.players[2].stack) self.eq(PayInfo.FOLDED, game_state['table'].seats.players[0].pay_info.status) self.eq( sb_amount * 3 + ante * 2, GameEvaluator.create_pot( game_state['table'].seats.players)[0]['amount']) # case2: third player cannot pay big blind finish_state, events = self.emu.apply_action(original, 'fold') finish_state['table'].seats.players[1].stack = 16 stacks = [p.stack for p in finish_state['table'].seats.players] game_state, events = self.emu.start_new_round(finish_state) self.eq(2, game_state['table'].dealer_btn) self.eq(0, game_state['next_player']) self.eq(stacks[0] - sb_amount - ante, game_state['table'].seats.players[0].stack) self.eq(stacks[2] - sb_amount * 2 - ante, game_state['table'].seats.players[2].stack) self.eq(PayInfo.FOLDED, game_state['table'].seats.players[1].pay_info.status) self.eq(PayInfo.PLAY_TILL_END, game_state['table'].seats.players[0].pay_info.status) self.eq( sb_amount * 3 + ante * 2, GameEvaluator.create_pot( game_state['table'].seats.players)[0]['amount']) def test_start_new_round_exclude_no_money_players2(self): uuids = [ 'ruypwwoqwuwdnauiwpefsw', 'sqmfwdkpcoagzqxpxnmxwm', 'uxrdiwvctvilasinweqven' ] game_state = restore_game_state(ThreePlayerGameStateSample.round_state) original = reduce( lambda state, uuid: attach_hole_card_from_deck(state, uuid), uuids, game_state) sb_amount, ante = 5, 7 self.emu.set_game_rule(3, 10, sb_amount, ante) [self.emu.register_player(uuid, FoldMan()) for uuid in uuids] # case1: second player cannot pay small blind finish_state, events = self.emu.apply_action(original, 'fold') finish_state['table'].seats.players[2].stack = 6 stacks = [p.stack for p in finish_state['table'].seats.players] game_state, events = self.emu.start_new_round(finish_state) self.eq(0, game_state['table'].dealer_btn) self.eq(1, game_state['table'].sb_pos()) self.eq(1, game_state['next_player']) def test_start_new_round_game_finish_judge(self): uuids = [ 'ruypwwoqwuwdnauiwpefsw', 'sqmfwdkpcoagzqxpxnmxwm', 'uxrdiwvctvilasinweqven' ] game_state = restore_game_state(ThreePlayerGameStateSample.round_state) original = reduce( lambda state, uuid: attach_hole_card_from_deck(state, uuid), uuids, game_state) sb_amount, ante = 5, 7 self.emu.set_game_rule(3, 10, sb_amount, ante) [self.emu.register_player(uuid, FoldMan()) for uuid in uuids] finish_state, events = self.emu.apply_action(original, 'fold') finish_state['table'].seats.players[2].stack = 11 finish_state['table'].seats.players[1].stack = 16 game_state, events = self.emu.start_new_round(finish_state) self.eq(1, len(events)) self.eq('event_game_finish', events[0]['type']) def test_generate_initial_game_state(self): self.emu.set_game_rule(2, 8, 5, 3) p1, p2 = FoldMan(), FoldMan() players_info = OrderedDict() players_info['uuid-1'] = {'name': 'hoge', 'stack': 100} players_info['uuid-2'] = {'name': 'fuga', 'stack': 100} state = self.emu.generate_initial_game_state(players_info) table = state['table'] self.eq(0, state['round_count']) self.eq(5, state['small_blind_amount']) self.eq(100, table.seats.players[0].stack) self.eq('uuid-1', table.seats.players[0].uuid) self.eq(100, table.seats.players[1].stack) self.eq('uuid-2', table.seats.players[1].uuid) self.eq(1, table.dealer_btn) state, events = self.emu.start_new_round(state) self.eq(0, state['table'].dealer_btn) self.eq(1, state['table'].sb_pos()) self.eq(0, state['table'].bb_pos()) self.eq(1, state['next_player']) state, events = self.emu.apply_action(state, 'call', 10) self.eq(1, state['next_player']) def test_generate_possible_actions(self): state1 = restore_game_state(TwoPlayerSample.round_state) self.eq(TwoPlayerSample.valid_actions, self.emu.generate_possible_actions(state1)) state2 = restore_game_state(ThreePlayerGameStateSample.round_state) self.eq(ThreePlayerGameStateSample.valid_actions, self.emu.generate_possible_actions(state2))
class EmulatorTest(BaseUnitTest): def setUp(self): self.emu = Emulator() def test_set_game_rule(self): self.emu.set_game_rule(2, 8, 5, 3) self.eq(2, self.emu.game_rule["player_num"]) self.eq(8, self.emu.game_rule["max_round"]) self.eq(5, self.emu.game_rule["sb_amount"]) self.eq(3, self.emu.game_rule["ante"]) def test_register_and_fetch_player(self): p1, p2 = FoldMan(), FoldMan() self.emu.register_player("uuid-1", p1) self.emu.register_player("uuid-2", p2) self.eq(p1, self.emu.fetch_player("uuid-1")) self.eq(p2, self.emu.fetch_player("uuid-2")) @raises(TypeError) def test_register_invalid_player(self): self.emu.register_player("uuid", "hoge") def test_blind_structure(self): game_state = restore_game_state(TwoPlayerSample.round_state) game_state = attach_hole_card_from_deck(game_state, "tojrbxmkuzrarnniosuhct") game_state = attach_hole_card_from_deck(game_state, "pwtwlmfciymjdoljkhagxa") self.emu.set_game_rule(2, 10, 5, 0) self.emu.set_blind_structure({5: {"ante": 5, "small_blind": 60}}) p1 = TestPlayer([("fold", 0), ('raise', 55), ('call', 0)]) p2 = TestPlayer([("call", 15), ("call", 55), ('fold', 0)]) self.emu.register_player("tojrbxmkuzrarnniosuhct", p1) self.emu.register_player("pwtwlmfciymjdoljkhagxa", p2) game_state, events = self.emu.run_until_round_finish(game_state) self.eq(65, game_state["table"].seats.players[0].stack) self.eq(135, game_state["table"].seats.players[1].stack) game_state, events = self.emu.start_new_round(game_state) game_state, events = self.emu.run_until_round_finish(game_state) self.eq(120, game_state["table"].seats.players[0].stack) self.eq(80, game_state["table"].seats.players[1].stack) game_state, events = self.emu.start_new_round(game_state) self.eq("event_game_finish", events[0]["type"]) self.eq(0, game_state["table"].seats.players[0].stack) self.eq(80, game_state["table"].seats.players[1].stack) def test_blind_structure_update(self): self.emu.set_game_rule(2, 8, 5, 3) p1, p2 = FoldMan(), FoldMan() self.emu.register_player("uuid-1", p1) self.emu.register_player("uuid-2", p2) blind_structure = { 3: { "ante": 5, "small_blind": 10 }, 5: { "ante": 10, "small_blind": 20 } } self.emu.set_blind_structure(blind_structure) players_info = { "uuid-1": { "name": "hoge", "stack": 100 }, "uuid-2": { "name": "fuga", "stack": 100 } } state = self.emu.generate_initial_game_state(players_info) self.eq(5, state["small_blind_amount"]) state, _ = self.emu.start_new_round(state) state, _ = self.emu.apply_action(state, "fold") self.eq(5, state["small_blind_amount"]) state, _ = self.emu.apply_action(state, "fold") self.eq(5, state["small_blind_amount"]) state, _ = self.emu.apply_action(state, "fold") self.eq(10, state["small_blind_amount"]) state, _ = self.emu.apply_action(state, "fold") self.eq(10, state["small_blind_amount"]) state, _ = self.emu.apply_action(state, "fold") self.eq(20, state["small_blind_amount"]) state, _ = self.emu.apply_action(state, "fold") self.eq(20, state["small_blind_amount"]) def test_apply_action(self): game_state = restore_game_state(TwoPlayerSample.round_state) game_state = attach_hole_card_from_deck(game_state, "tojrbxmkuzrarnniosuhct") game_state = attach_hole_card_from_deck(game_state, "pwtwlmfciymjdoljkhagxa") self.emu.set_game_rule(2, 10, 5, 0) p1, p2 = FoldMan(), FoldMan() self.emu.register_player("tojrbxmkuzrarnniosuhct", FoldMan()) self.emu.register_player("pwtwlmfciymjdoljkhagxa", FoldMan()) game_state, events = self.emu.apply_action(game_state, "call", 15) self.eq(Const.Street.RIVER, game_state["street"]) self.eq(TwoPlayerSample.p1_action_histories, \ game_state["table"].seats.players[0].round_action_histories[Const.Street.TURN]) self.eq(2, len(events)) self.eq("event_new_street", events[0]["type"]) self.eq("event_ask_player", events[1]["type"]) game_state, events = self.emu.apply_action(game_state, "call", 0) self.eq(1, len(events)) self.eq("event_ask_player", events[0]["type"]) game_state, events = self.emu.apply_action(game_state, "call", 0) self.eq(1, len(events)) self.eq("event_round_finish", events[0]["type"]) def test_apply_action_game_finish_detect(self): game_state = restore_game_state(TwoPlayerSample.round_state) game_state = attach_hole_card_from_deck(game_state, "tojrbxmkuzrarnniosuhct") game_state = attach_hole_card_from_deck(game_state, "pwtwlmfciymjdoljkhagxa") self.emu.set_game_rule(2, 3, 5, 0) p1, p2 = FoldMan(), FoldMan() self.emu.register_player("tojrbxmkuzrarnniosuhct", FoldMan()) self.emu.register_player("pwtwlmfciymjdoljkhagxa", FoldMan()) game_state, events = self.emu.apply_action(game_state, "fold") self.eq("event_game_finish", events[-1]["type"]) def test_apply_action_start_next_round(self): game_state = restore_game_state(TwoPlayerSample.round_state) game_state = attach_hole_card_from_deck(game_state, "tojrbxmkuzrarnniosuhct") game_state = attach_hole_card_from_deck(game_state, "pwtwlmfciymjdoljkhagxa") self.emu.set_game_rule(2, 4, 5, 0) p1, p2 = FoldMan(), FoldMan() self.emu.register_player("tojrbxmkuzrarnniosuhct", FoldMan()) self.emu.register_player("pwtwlmfciymjdoljkhagxa", FoldMan()) game_state, events = self.emu.apply_action(game_state, "fold") self.eq(120, game_state["table"].seats.players[0].stack) self.eq(80, game_state["table"].seats.players[1].stack) game_state, events = self.emu.apply_action(game_state, "raise", 20) self.eq("event_ask_player", events[-1]["type"]) self.eq(100, game_state["table"].seats.players[0].stack) self.eq(70, game_state["table"].seats.players[1].stack) @raises(Exception) def test_apply_action_when_game_finished(self): game_state = restore_game_state(TwoPlayerSample.round_state) game_state = attach_hole_card_from_deck(game_state, "tojrbxmkuzrarnniosuhct") game_state = attach_hole_card_from_deck(game_state, "pwtwlmfciymjdoljkhagxa") self.emu.set_game_rule(2, 3, 5, 0) p1, p2 = FoldMan(), FoldMan() self.emu.register_player("tojrbxmkuzrarnniosuhct", FoldMan()) self.emu.register_player("pwtwlmfciymjdoljkhagxa", FoldMan()) game_state, events = self.emu.apply_action(game_state, "fold") self.emu.apply_action(game_state, "fold") def test_run_until_round_finish(self): game_state = restore_game_state(TwoPlayerSample.round_state) game_state = attach_hole_card_from_deck(game_state, "tojrbxmkuzrarnniosuhct") game_state = attach_hole_card_from_deck(game_state, "pwtwlmfciymjdoljkhagxa") self.emu.set_game_rule(2, 10, 5, 0) p1 = TestPlayer([("fold", 0)]) p2 = TestPlayer([("call", 15)]) self.emu.register_player("tojrbxmkuzrarnniosuhct", p1) self.emu.register_player("pwtwlmfciymjdoljkhagxa", p2) game_state, events = self.emu.run_until_round_finish(game_state) self.eq("event_new_street", events[0]["type"]) self.eq("event_ask_player", events[1]["type"]) self.eq("event_round_finish", events[2]["type"]) def test_run_until_round_finish_when_already_finished(self): game_state = restore_game_state(TwoPlayerSample.round_state) game_state = attach_hole_card_from_deck(game_state, "tojrbxmkuzrarnniosuhct") game_state = attach_hole_card_from_deck(game_state, "pwtwlmfciymjdoljkhagxa") self.emu.set_game_rule(2, 10, 5, 0) p1 = TestPlayer([("fold", 0)]) p2 = TestPlayer([("call", 15)]) self.emu.register_player("tojrbxmkuzrarnniosuhct", p1) self.emu.register_player("pwtwlmfciymjdoljkhagxa", p2) game_state, events = self.emu.run_until_round_finish(game_state) game_state, events = self.emu.run_until_round_finish(game_state) self.eq(0, len(events)) def test_run_until_round_finish_game_finish_detect(self): uuids = ["tojrbxmkuzrarnniosuhct", "pwtwlmfciymjdoljkhagxa"] holecards = [[Card.from_str(s) for s in ss] for ss in [["CA", "D2"], ["C8", "H5"]]] game_state = restore_game_state(TwoPlayerSample.round_state) game_state = reduce(lambda a, e: attach_hole_card(a, e[0], e[1]), zip(uuids, holecards), game_state) game_state = attach_hole_card_from_deck(game_state, "pwtwlmfciymjdoljkhagxa") self.emu.set_game_rule(2, 10, 5, 0) p1 = TestPlayer([("raise", 65)]) p2 = TestPlayer([("call", 15), ("call", 65)]) self.emu.register_player("tojrbxmkuzrarnniosuhct", p1) self.emu.register_player("pwtwlmfciymjdoljkhagxa", p2) game_state["table"].deck.deck.append(Card.from_str("C7")) game_state, events = self.emu.run_until_round_finish(game_state) self.eq("event_new_street", events[0]["type"]) self.eq("event_ask_player", events[1]["type"]) self.eq("event_ask_player", events[2]["type"]) self.eq("event_round_finish", events[3]["type"]) self.eq("event_game_finish", events[4]["type"]) self.eq(0, events[4]["players"][0]["stack"]) self.eq(200, events[4]["players"][1]["stack"]) def test_run_until_game_finish(self): game_state = restore_game_state(TwoPlayerSample.round_state) game_state = attach_hole_card_from_deck(game_state, "tojrbxmkuzrarnniosuhct") game_state = attach_hole_card_from_deck(game_state, "pwtwlmfciymjdoljkhagxa") self.emu.set_game_rule(2, 10, 5, 1) self.emu.register_player("tojrbxmkuzrarnniosuhct", FoldMan()) self.emu.register_player("pwtwlmfciymjdoljkhagxa", FoldMan()) game_state, events = self.emu.run_until_game_finish(game_state) self.eq("event_game_finish", events[-1]["type"]) self.eq(114, game_state["table"].seats.players[0].stack) self.eq(86, game_state["table"].seats.players[1].stack) def test_run_until_game_finish_when_one_player_is_left(self): uuids = [ "ruypwwoqwuwdnauiwpefsw", "sqmfwdkpcoagzqxpxnmxwm", "uxrdiwvctvilasinweqven" ] holecards = [[Card.from_str(s) for s in ss] for ss in [["C2", "C3"], ["HA", "CA"], ["D5", "H6"]]] game_state = restore_game_state(ThreePlayerGameStateSample.round_state) game_state = reduce( lambda state, item: attach_hole_card(state, item[0], item[1]), zip(uuids, holecards), game_state) sb_amount, ante = 5, 7 self.emu.set_game_rule(3, 10, sb_amount, ante) p1_acts = [("fold", 0), ("call", 10), ('call', 0), ('call', 10), ("fold", 0)] p2_acts = [] p3_acts = [("raise", 10)] players = [TestPlayer(acts) for acts in [p1_acts, p2_acts, p3_acts]] [ self.emu.register_player(uuid, player) for uuid, player in zip(uuids, players) ] game_state["table"].deck.deck.append(Card.from_str("C7")) game_state, events = self.emu.run_until_game_finish(game_state) self.eq("event_game_finish", events[-1]["type"]) self.eq(0, game_state["table"].seats.players[0].stack) self.eq(0, game_state["table"].seats.players[1].stack) self.eq(292, game_state["table"].seats.players[2].stack) def test_run_until_game_finish_when_final_round(self): uuids = [ "ruypwwoqwuwdnauiwpefsw", "sqmfwdkpcoagzqxpxnmxwm", "uxrdiwvctvilasinweqven" ] holecards = [[Card.from_str(s) for s in ss] for ss in [["C2", "C3"], ["HA", "CA"], ["D5", "H6"]]] game_state = restore_game_state(ThreePlayerGameStateSample.round_state) game_state = reduce( lambda state, item: attach_hole_card(state, item[0], item[1]), zip(uuids, holecards), game_state) sb_amount, ante = 5, 7 self.emu.set_game_rule(3, 10, sb_amount, ante) [self.emu.register_player(uuid, FoldMan()) for uuid in uuids] game_state["table"].deck.deck.append(Card.from_str("C7")) game_state, events = self.emu.run_until_game_finish(game_state) self.eq("event_game_finish", events[-1]["type"]) self.eq(10, game_state["round_count"]) self.eq(35, game_state["table"].seats.players[0].stack) self.eq(0, game_state["table"].seats.players[1].stack) self.eq(265, game_state["table"].seats.players[2].stack) def test_last_round_judge(self): game_state = restore_game_state(TwoPlayerSample.round_state) self.emu.set_game_rule(2, 3, 5, 0) self.false(self.emu._is_last_round(game_state, self.emu.game_rule)) game_state["street"] = Const.Street.FINISHED self.true(self.emu._is_last_round(game_state, self.emu.game_rule)) game_state["round_count"] = 2 self.false(self.emu._is_last_round(game_state, self.emu.game_rule)) game_state["table"].seats.players[0].stack = 0 self.true(self.emu._is_last_round(game_state, self.emu.game_rule)) def test_start_new_round(self): game_state = restore_game_state(TwoPlayerSample.round_state) game_state = attach_hole_card_from_deck(game_state, "tojrbxmkuzrarnniosuhct") game_state = attach_hole_card_from_deck(game_state, "pwtwlmfciymjdoljkhagxa") p1, p2 = FoldMan(), FoldMan() self.emu.set_game_rule(2, 10, 5, 0) self.emu.register_player("tojrbxmkuzrarnniosuhct", FoldMan()) self.emu.register_player("pwtwlmfciymjdoljkhagxa", FoldMan()) # run until round finish game_state, event = self.emu.apply_action(game_state, "call", 15) game_state, event = self.emu.apply_action(game_state, "call", 0) game_state, event = self.emu.apply_action(game_state, "call", 0) game_state, events = self.emu.start_new_round(game_state) self.eq(4, game_state["round_count"]) self.eq(1, game_state["table"].dealer_btn) self.eq(0, game_state["street"]) self.eq(0, game_state["next_player"]) self.eq("event_new_street", events[0]["type"]) self.eq("event_ask_player", events[1]["type"]) self.eq("preflop", events[0]["street"]) self.eq("tojrbxmkuzrarnniosuhct", events[1]["uuid"]) def test_start_new_round_exclude_no_money_players(self): uuids = [ "ruypwwoqwuwdnauiwpefsw", "sqmfwdkpcoagzqxpxnmxwm", "uxrdiwvctvilasinweqven" ] game_state = restore_game_state(ThreePlayerGameStateSample.round_state) original = reduce( lambda state, uuid: attach_hole_card_from_deck(state, uuid), uuids, game_state) sb_amount, ante = 5, 7 self.emu.set_game_rule(3, 10, sb_amount, ante) [self.emu.register_player(uuid, FoldMan()) for uuid in uuids] # case1: second player cannot pay small blind finish_state, events = self.emu.apply_action(original, "fold") finish_state["table"].seats.players[0].stack = 11 stacks = [p.stack for p in finish_state["table"].seats.players] game_state, events = self.emu.start_new_round(finish_state) self.eq(2, game_state["table"].dealer_btn) self.eq(1, game_state["next_player"]) self.eq(stacks[1] - sb_amount - ante, game_state["table"].seats.players[1].stack) self.eq(stacks[2] - sb_amount * 2 - ante, game_state["table"].seats.players[2].stack) self.eq(PayInfo.FOLDED, game_state["table"].seats.players[0].pay_info.status) self.eq( sb_amount * 3 + ante * 2, GameEvaluator.create_pot( game_state["table"].seats.players)[0]["amount"]) # case2: third player cannot pay big blind finish_state, events = self.emu.apply_action(original, "fold") finish_state["table"].seats.players[1].stack = 16 stacks = [p.stack for p in finish_state["table"].seats.players] game_state, events = self.emu.start_new_round(finish_state) self.eq(2, game_state["table"].dealer_btn) self.eq(0, game_state["next_player"]) self.eq(stacks[0] - sb_amount - ante, game_state["table"].seats.players[0].stack) self.eq(stacks[2] - sb_amount * 2 - ante, game_state["table"].seats.players[2].stack) self.eq(PayInfo.FOLDED, game_state["table"].seats.players[1].pay_info.status) self.eq(PayInfo.PAY_TILL_END, game_state["table"].seats.players[0].pay_info.status) self.eq( sb_amount * 3 + ante * 2, GameEvaluator.create_pot( game_state["table"].seats.players)[0]["amount"]) def test_start_new_round_exclude_no_money_players2(self): uuids = [ "ruypwwoqwuwdnauiwpefsw", "sqmfwdkpcoagzqxpxnmxwm", "uxrdiwvctvilasinweqven" ] game_state = restore_game_state(ThreePlayerGameStateSample.round_state) original = reduce( lambda state, uuid: attach_hole_card_from_deck(state, uuid), uuids, game_state) sb_amount, ante = 5, 7 self.emu.set_game_rule(3, 10, sb_amount, ante) [self.emu.register_player(uuid, FoldMan()) for uuid in uuids] # case1: second player cannot pay small blind finish_state, events = self.emu.apply_action(original, "fold") finish_state["table"].seats.players[2].stack = 6 stacks = [p.stack for p in finish_state["table"].seats.players] game_state, events = self.emu.start_new_round(finish_state) self.eq(0, game_state["table"].dealer_btn) self.eq(1, game_state["table"].sb_pos()) self.eq(1, game_state["next_player"]) def test_start_new_round_game_finish_judge(self): uuids = [ "ruypwwoqwuwdnauiwpefsw", "sqmfwdkpcoagzqxpxnmxwm", "uxrdiwvctvilasinweqven" ] game_state = restore_game_state(ThreePlayerGameStateSample.round_state) original = reduce( lambda state, uuid: attach_hole_card_from_deck(state, uuid), uuids, game_state) sb_amount, ante = 5, 7 self.emu.set_game_rule(3, 10, sb_amount, ante) [self.emu.register_player(uuid, FoldMan()) for uuid in uuids] finish_state, events = self.emu.apply_action(original, "fold") finish_state["table"].seats.players[2].stack = 11 finish_state["table"].seats.players[1].stack = 16 game_state, events = self.emu.start_new_round(finish_state) self.eq(1, len(events)) self.eq("event_game_finish", events[0]["type"]) def test_generate_initial_game_state(self): self.emu.set_game_rule(2, 8, 5, 3) p1, p2 = FoldMan(), FoldMan() players_info = OrderedDict() players_info["uuid-1"] = {"name": "hoge", "stack": 100} players_info["uuid-2"] = {"name": "fuga", "stack": 100} state = self.emu.generate_initial_game_state(players_info) table = state["table"] self.eq(0, state["round_count"]) self.eq(5, state["small_blind_amount"]) self.eq(100, table.seats.players[0].stack) self.eq("uuid-1", table.seats.players[0].uuid) self.eq(100, table.seats.players[1].stack) self.eq("uuid-2", table.seats.players[1].uuid) self.eq(1, table.dealer_btn) state, events = self.emu.start_new_round(state) self.eq(0, state["table"].dealer_btn) self.eq(1, state["table"].sb_pos()) self.eq(0, state["table"].bb_pos()) self.eq(1, state["next_player"]) state, events = self.emu.apply_action(state, "call", 10) self.eq(1, state["next_player"]) def test_generate_possible_actions(self): state1 = restore_game_state(TwoPlayerSample.round_state) self.eq(TwoPlayerSample.valid_actions, self.emu.generate_possible_actions(state1)) state2 = restore_game_state(ThreePlayerGameStateSample.round_state) self.eq(ThreePlayerGameStateSample.valid_actions, self.emu.generate_possible_actions(state2))
from players.risky_player import RiskyPlayer import pandas as pd # 1. Set game settings on emulator n_players = 3 emulator = Emulator() #quuid = "uuid-q" p_uuid = ["low-IQ", "high-IQ", "low-IQ2", "wut"] #qlearner_player = RLPlayer(n_players, quuid) df = pd.DataFrame(columns=['uuid', 'stack', 'game']) for i in range(0, 60): print("starting game " + str(i)) df1 = pd.DataFrame(columns=['uuid', 'stack', 'round']) df2 = pd.DataFrame(columns=['uuid', 'stack', 'round']) df3 = pd.DataFrame(columns=['uuid', 'stack', 'round']) emulator.register_player(uuid=p_uuid[0], player=HonestPlayer(n_players, 100)) emulator.register_player(uuid=p_uuid[1], player=HonestPlayer(n_players, 1000)) emulator.register_player(uuid=p_uuid[2], player=HonestPlayer(n_players, 100)) emulator.set_game_rule(player_num=3, max_round=10000, small_blind_amount=20, ante_amount=0) # 2. Setup GameState object players_info = { p_uuid[0]: { "name": "player1", "stack": 10000 }, p_uuid[1]: {
def run_episode(agents): emulator = Emulator() temp_final_state = {} winner_counts = [0] * N_AGENTS n_games_played = 0 for game in range(GAMES_PER_EPISODE): wrappers = [] player_info = {} for i, agent in enumerate(agents): if PERSISTENT_STACKS: if temp_final_state: for seat in temp_final_state: player_info[seat.uuid] = {'name': 'Player ' + str(seat.uuid), 'stack': seat.stack if seat.stack else STACK_SIZE} else: player_info[i] = {'name': 'Player ' + str(i), 'stack': STACK_SIZE} else: player_info[i] = {'name': 'Player ' + str(i), 'stack': STACK_SIZE} wrappers.append(DQNAgentWrapper(agent, STACK_SIZE)) emulator.register_player(uuid=i, player=wrappers[-1]) emulator.set_game_rule(N_AGENTS, 2, BB_SIZE / 2, 0) initial_game_state = emulator.generate_initial_game_state(player_info) game_state, events = emulator.start_new_round(initial_game_state) game_finish_state, events = emulator.run_until_round_finish(game_state) # import json # if game == 0 or game == 1: # print('dumping') # with open('event_dump_' + str(game), 'w') as f: # json.dump(events, f, indent=2) if 'winners' not in events[-1]: events.pop() winner = events[-1]['winners'][0]['uuid'] winner_counts[winner] += 1 n_games_played += 1 for i in range(N_AGENTS): new_stack_size = game_finish_state['table'].seats.players[i].stack reward = (new_stack_size - wrappers[i].prev_stack_size) / BB_SIZE #print('Remembering {} reward for {} action'.format(reward, wrappers[i].prev_action)) wrappers[i].agent.remember(wrappers[i].prev_state, wrappers[i].prev_action, reward, None, 1) temp_final_state = game_finish_state['table'].seats.players # print('====') print('\rGame:{}, epsilon:{}'.format(game, wrappers[0].agent.epsilon), end='') # print(game_finish_state) # print('\n') # print(events[-5:]) # print('====') if (game % REPLAY_EVERY_N_GAMES == 0) or (game == GAMES_PER_EPISODE - 1): # replay memory for every agent # for agent in agents: # agent.replay(BATCH_SIZE) agents[0].replay(BATCH_SIZE) for i in range(N_AGENTS): agents[i].model.reset_states() clear_memory() return agents[0], temp_final_state, winner_counts, n_games_played
class TexasHoldemTask(BaseTask): def __init__(self, final_round=max_round, scale_reward=False, lose_penalty=False, shuffle_position=False, action_record=False): self.final_round = final_round self.scale_reward = scale_reward self.lose_penalty = lose_penalty self.shuffle_position = shuffle_position self.action_record = action_record self.emulator = Emulator() self.emulator.set_game_rule(nb_player, final_round, sb_amount, ante) self.emulator.set_blind_structure(blind_structure) self.opponent_value_functions = {} if shuffle_position: print "Warning: shuffle_position is set True. Are you sure?" for uuid in players_info: self.emulator.register_player(uuid, DummyPlayer()) if uuid != my_uuid: self.opponent_value_functions[uuid] = None def set_opponent_value_functions(self, value_functions): assert len(value_functions) == 9 opponent_uuids = [ uuid for uuid in self.opponent_value_functions if uuid != my_uuid ] for uuid, value_function in zip(opponent_uuids, value_functions): self.opponent_value_functions[uuid] = value_function def generate_initial_state(self): return self.generate_initial_state_without_action_record() if not self.action_record\ else self.generate_initial_state_with_action_record() def generate_initial_state_without_action_record(self): p_info = _get_shuffled_players_info( ) if self.shuffle_position else players_info clear_state = self.emulator.generate_initial_game_state(p_info) state, _events = self.emulator.start_new_round(clear_state) while not self._check_my_turn(state): action, amount = self._choose_opponent_action(state) state, _events = self.emulator.apply_action(state, action, amount) if state[ "street"] == Const.Street.FINISHED and not self.is_terminal_state( state): state, _events = self.emulator.start_new_round(state) return state if not self.is_terminal_state( state) else self.generate_initial_state() def generate_initial_state_with_action_record(self): p_info = _get_shuffled_players_info( ) if self.shuffle_position else players_info clear_state = self.emulator.generate_initial_game_state(p_info) p_act_record = { p.uuid: [[], [], [], []] for p in clear_state["table"].seats.players } state, _events = self.emulator.start_new_round(clear_state) while not self._check_my_turn(state): state[ACTION_RECORD_KEY] = p_act_record opponent_uuid, action_info = self._choose_opponent_action( state, detail_info=True) p_act_record = self._update_action_record(state, p_act_record, opponent_uuid, action_info) action, amount = action_info["action"], action_info["amount"] state, _events = self.emulator.apply_action(state, action, amount) if state[ "street"] == Const.Street.FINISHED and not self.is_terminal_state( state): state, _events = self.emulator.start_new_round(state) state[ACTION_RECORD_KEY] = p_act_record return state if not self.is_terminal_state( state) else self.generate_initial_state() def is_terminal_state(self, state): me = pick_me(state) round_finished = state["street"] == Const.Street.FINISHED active_players = [ p for p in state["table"].seats.players if p.stack > 0 ] short_of_players = len(active_players) <= table_break_threshold i_am_loser = me.stack == 0 is_final_round = state["round_count"] >= self.final_round return round_finished and (short_of_players or i_am_loser or is_final_round) def transit_state(self, state, action): return self.transit_state_without_action_record(state, action) if not self.action_record\ else self.transit_state_with_action_record(state, action) def transit_state_without_action_record(self, state, action): assert self._check_my_turn(state) assert not self.is_terminal_state(state) action, amount = action["action"], action["amount"] state, _events = self.emulator.apply_action(state, action, amount) if state[ "street"] == Const.Street.FINISHED and not self.is_terminal_state( state): state, _events = self.emulator.start_new_round(state) while not self._check_my_turn(state) and not self.is_terminal_state( state): action, amount = self._choose_opponent_action(state) state, _events = self.emulator.apply_action(state, action, amount) if state[ "street"] == Const.Street.FINISHED and not self.is_terminal_state( state): state, _events = self.emulator.start_new_round(state) return state def transit_state_with_action_record(self, state, action_info): assert self._check_my_turn(state) assert not self.is_terminal_state(state) assert state.has_key(ACTION_RECORD_KEY) p_act_record = _deepcopy_action_record(state) p_act_record = self._update_action_record(state, p_act_record, my_uuid, action_info) action, amount = action_info["action"], action_info["amount"] state, _events = self.emulator.apply_action(state, action, amount) state[ACTION_RECORD_KEY] = p_act_record if state[ "street"] == Const.Street.FINISHED and not self.is_terminal_state( state): state, _events = self.emulator.start_new_round(state) while not self._check_my_turn(state) and not self.is_terminal_state( state): state[ACTION_RECORD_KEY] = p_act_record opponent_uuid, action_info = self._choose_opponent_action( state, detail_info=True) p_act_record = self._update_action_record(state, p_act_record, opponent_uuid, action_info) action, amount = action_info["action"], action_info["amount"] state, _events = self.emulator.apply_action(state, action, amount) if state[ "street"] == Const.Street.FINISHED and not self.is_terminal_state( state): state, _events = self.emulator.start_new_round(state) state[ACTION_RECORD_KEY] = p_act_record return state def _check_my_turn(self, state): players = state["table"].seats.players return state["next_player"] != "not_found" and my_uuid == players[ state["next_player"]].uuid def _choose_opponent_action(self, state, detail_info=False): players = state["table"].seats.players opponent_uuid = players[state["next_player"]].uuid value_function = self.opponent_value_functions[opponent_uuid] action_info = choose_best_action(self, value_function, state) return (opponent_uuid, action_info) if detail_info else (action_info["action"], action_info["amount"]) def generate_possible_actions(self, state): action_info = self.emulator.generate_possible_actions(state) min_raise_amount = action_info[2]["amount"]["min"] max_raise_amount = action_info[2]["amount"]["max"] player = state["table"].seats.players[state["next_player"]] actions = [ gen_fold_action(), gen_call_action(action_info[1]["amount"]) ] if min_raise_amount != -1: actions.append(gen_min_raise_action(min_raise_amount)) if min_raise_amount != -1 and min_raise_amount * 2 < max_raise_amount: actions.append(gen_double_raise_action(min_raise_amount * 2)) if min_raise_amount != -1 and min_raise_amount * 3 < max_raise_amount: actions.append(gen_triple_raise_action(min_raise_amount * 3)) if max_raise_amount != -1: actions.append(gen_max_raise_action(max_raise_amount)) return actions def calculate_reward(self, state): if self.is_terminal_state(state): if pick_me(state).stack == 0 and self.lose_penalty: return -1 if self.scale_reward: return 1.0 * pick_me(state).stack / (nb_player * initial_stack) else: return pick_me(state).stack else: return 0 def _update_action_record(self, state, action_record, uuid, action_info): action, amount = action_info["action"], action_info["amount"] if 'fold' == action: idx = 0 elif 'call' == action: idx = 1 elif 'raise' == action: idx = 2 else: raise Exception("unexpected action [ %s ] received" % action) # allin check. the idx of allin is 3. action_player = [ player for player in state["table"].seats.players if player.uuid == uuid ] assert len(action_player) == 1 if amount >= action_player[0].stack and 'fold' != action: idx = 3 action_record[uuid][idx].append(amount) return action_record
class EmulatorPlayer(BasePokerPlayer): def set_opponents_model(self, model_player): self.opponents_model = model_player # setup Emulator with passed game information def receive_game_start_message(self, game_info): self.my_model = MyModel() nb_player = game_info['player_num'] max_round = game_info['rule']['max_round'] sb_amount = game_info['rule']['small_blind_amount'] ante_amount = game_info['rule']['ante'] self.emulator = Emulator() self.emulator.set_game_rule(nb_player, max_round, sb_amount, ante_amount) for player_info in game_info['seats']: uuid = player_info['uuid'] player_model = self.my_model if uuid == self.uuid else self.opponents_model self.emulator.register_player(uuid, player_model) def declare_action(self, valid_actions, hole_card, round_state): try_actions = [MyModel.FOLD, MyModel.CALL, MyModel.MIN_RAISE, MyModel.MAX_RAISE] action_results = [0 for i in range(len(try_actions))] log("hole_card of emulator player is %s" % hole_card) for action in try_actions: self.my_model.set_action(action) simulation_results = [] for i in range(NB_SIMULATION): game_state = self._setup_game_state(round_state, hole_card) round_finished_state, _events = self.emulator.run_until_round_finish(game_state) my_stack = [player for player in round_finished_state['table'].seats.players if player.uuid == self.uuid][0].stack simulation_results.append(my_stack) action_results[action] = 1.0 * sum(simulation_results) / NB_SIMULATION log("average stack after simulation when declares %s : %s" % ( {0:'FOLD', 1:'CALL', 2:'MIN_RAISE', 3:'MAX_RAISE'}[action], action_results[action]) ) best_action = max(zip(action_results, try_actions))[1] self.my_model.set_action(best_action) return self.my_model.declare_action(valid_actions, hole_card, round_state) def _setup_game_state(self, round_state, my_hole_card): game_state = restore_game_state(round_state) game_state['table'].deck.shuffle() player_uuids = [player_info['uuid'] for player_info in round_state['seats']] for uuid in player_uuids: if uuid == self.uuid: game_state = attach_hole_card(game_state, uuid, gen_cards(my_hole_card)) # attach my holecard else: game_state = attach_hole_card_from_deck(game_state, uuid) # attach opponents holecard at random return game_state def receive_round_start_message(self, round_count, hole_card, seats): pass def receive_street_start_message(self, street, round_state): pass def receive_game_update_message(self, new_action, round_state): pass def receive_round_result_message(self, winners, hand_info, round_state): pass
small_blind_amount=SB, ante_amount=ANTE["initial"]) # simulate 1 round to obtain the starting game state and player info config = setup_config(max_round=1, initial_stack=STARTING_STACK, small_blind_amount=SB) for player in hall_of_fame: config.register_player(name=player.name, algorithm=player) game_result = start_poker(config, verbose=0) # obtain simulated player info for player in game_result['players']: for _player in hall_of_fame: if _player.name == player['name']: _player.uuid = player['uuid'] emulator.register_player(_player.uuid, _player) break for i in range(1, TOTAL_EPISODES + 1): print(">>>>>>>>>>Initializing game %d<<<<<<<<<<<<" % (i)) current_state = restore_game_state(hall_of_fame[0].last_pre_flop_state) print("Simulating the game") while True: current_state, events = emulator.start_new_round(current_state) if Event.GAME_FINISH == events[-1]["type"]: break #update game rules round_num = current_state["round_count"] new_ante = int(ANTE["initial"] *
max_round=max_round, small_blind_amount=sb_amount, ante_amount=ante_amount) players_info = { "uuid-" + str(i): { 'name': 'player' + str(i), 'stack': random.randint(80, 120) } for i in range(0, nb_player) } initial_state = emulator.generate_initial_game_state(players_info) [ emulator.register_player( k, Alpha0Regret( 100, model, 1, k, initialize_new_emulator(nb_player, max_round, sb_amount, ante_amount), memory)) for k in players_info.keys() ] game_state = initial_state events = [{'type': None}] while events[-1]['type'] != "event_game_finish": game_state, events = emulator.start_new_round(game_state) if events[-1]['type'] != "event_game_finish": pay_history = merge_pkmn_dicts_same_key( [{ x['uuid']: parse_action(x, 1)[6] } for k in events[-1]['round_state']['action_histories'].keys() for x in events[-1]['round_state']['action_histories'][k]])
class RLPokerPlayer(BasePokerPlayer): def __init__( self, study_mode=False, model_file=None, new_model_file=None, gammaReward=0.1, alphaUpdateNet=0.1, epsilonRandom=0.05, decayRandom=0.5, players=[RandomPlayer()] * 8 + [None], max_history_len=1000, new_model_file=None, ): self.stats = commons.PlayerStats() self.new_model_file = new_model_file self.gammaReward = gammaReward self.alphaUpdateNet = alphaUpdateNet self.decayRandom = decayRandom self.epsilonRandom = epsilonRandom self.study_mode = study_mode self.max_history_len = max_history_len # self.my_seat = 0 if self.study_mode: self.players = players for i in np.arange(len(self.players)): if self.players[i] is None: self.my_seat = i self.history = deque() if model_file is not None: self.model = load(model_file) else: self.model = commons.model1() def good_moves(self, valid_actions, my_stack): good_moves = [] good_moves.append({'action': 'fold', 'amount': 0, 'type': 0}) good_moves.append({ 'action': 'call', 'amount': valid_actions[1]['amount'], 'type': 1 }) if valid_actions[2]['amount']['min'] == -1: return good_moves raise_min, raise_max = valid_actions[2]['amount'][ 'min'], valid_actions[2]['amount']['max'] fix = lambda x: max(min(x, raise_max), raise_min) good_moves.append({ 'action': 'raise', 'amount': fix(self.small_blind_amount * 2), 'type': 2 }) good_moves.append({ 'action': 'raise', 'amount': fix(my_stack // 2), 'type': 3 }) good_moves.append({ 'action': 'raise', 'amount': fix(my_stack), 'type': 4 }) return good_moves def turn2vec(self, state_vec, move): move_numb = move['type'] move_amount = move['amount'] # print(move_numb, move_amount) X = np.concatenate( (np.array(state_vec), np.array([move_numb, move_amount]))) return X.reshape((1, -1)) def find_best_strat(self, valid_actions, cur_state_vec, my_stack): best_move, best_reward = None, -1500 * 9 good_moves = self.good_moves(valid_actions, my_stack) if sps.bernoulli.rvs(p=self.epsilonRandom): ind = sps.randint.rvs(low=0, high=len(good_moves)) move = good_moves[ind] reward = float( self.model.predict(self.turn2vec(cur_state_vec, move), batch_size=1)) return move, reward for move in good_moves: # print(cur_state_vec, move) cur_reward = float( self.model.predict(self.turn2vec(cur_state_vec, move), batch_size=1)) # print(cur_reward) if cur_reward > best_reward: best_move = move best_reward = cur_reward return best_move, best_reward def declare_action(self, valid_actions, hole_card, round_state): self.stats.update(hole_card, round_state) round_state_vec = self.stats.calc_fine_params(hole_card, round_state) my_stack = round_state['seats'][self.my_seat]['stack'] best_move, best_reward = self.find_best_strat(valid_actions, round_state_vec, my_stack) action, amount = best_move['action'], best_move['amount'] print('action {}, amount {}'.format(action, amount)) if self.study_mode: self.update_history(round_state_vec, best_move, best_reward, round_state) return action, amount def update_history(self, round_state_vec, best_move, best_reward, round_state): cur_data_dict = { 'states_vec': round_state_vec, 'states_original': round_state, 'moves': best_move, 'rewards': best_reward, 'stats': deepcopy(self.stats), } self.history.append(cur_data_dict) if len(self.history) == self.max_history_len: self.history.popleft() def receive_game_start_message(self, game_info): # self.my_name = game_info['seats'][self.my_seat]['name'] if self.study_mode: self.uuid = game_info["seats"][self.my_seat]['uuid'] self.stats.init_player_names(game_info) self.player_num = game_info["player_num"] self.max_round = game_info["rule"]["max_round"] self.small_blind_amount = game_info["rule"]["small_blind_amount"] self.ante_amount = game_info["rule"]["ante"] # self.blind_structure = game_info["rule"]["blind_structure"] self.emulator = Emulator() self.emulator.set_game_rule(self.player_num, self.max_round, self.small_blind_amount, self.ante_amount) # self.emulator.set_blind_structure(blind_structure) if self.study_mode: # Register algorithm of each player which used in the simulation. for i in np.arange(self.player_num): self.emulator.register_player( uuid=game_info["seats"][i]["uuid"], player=self.players[i] if self.players[i] is not None else self) def receive_round_start_message(self, round_count, hole_card, seats): self.start_round_stack = seats[self.my_seat]['stack'] def receive_street_start_message(self, street, round_state): pass def receive_game_update_message(self, action, round_state): if self.new_model_file is not None and self.study_mode: self.model.save(self.new_model_file) def receive_round_result_message(self, winners, hand_info, round_state): if self.study_mode: best_move = {'action': 'finish', 'amount': 0, 'type': 5} round_state_vec = -np.ones(commons.FEATURES_LEN - 2) best_reward = round_state['seats'][ self.my_seat]['stack'] - self.start_round_stack self.update_history(round_state_vec, best_move, best_reward, round_state) if len(self.history) > 10 and sps.bernoulli.rvs( p=self.alphaUpdateNet): ind = sps.randint.rvs(low=0, high=len(self.history) - 2) self.learn_with_states(self.history[ind], self.history[ind + 1]) self.epsilonRandom *= self.decayRandom # def generate_possible_actions(self, game_state): # players = game_state["seats"] # player_pos = game_state["next_player"] # sb_amount = game_state["small_blind_amount"] # return ActionChecker.legal_actions(players, player_pos, sb_amount) def do_best_simulation(self, next_state, next_state_vec, next_state_stats): # pp = pprint.PrettyPrinter(indent=4) # pp.pprint(next_state) # pp.pprint('*********************************************') game_state = restore_game_state(next_state) possible_actions = self.emulator.generate_possible_actions(game_state) good_actions = self.good_moves( possible_actions, next_state['seats'][self.my_seat]['stack']) best_reward = -1500 * 9 for action in good_actions: # print(action) try: next_next_game_state = self.emulator.apply_action( game_state, action['action'], action['amount']) next_next_state = next_next_game_state[1][-1]['round_state'] # next_next_state = next_next_game_state['action_histories'] # pp = pprint.PrettyPrinter(indent=4) # pp.pprint(next_next_state) if next_next_state['street'] in ['showdown', 'finished', 4, 5]: best_reward = max( best_reward, next_next_state['seats'][self.my_seat]['stack'] - self.start_round_stack) else: next_next_game_state = restore_game_state(next_next_state) hole_card = attach_hole_card_from_deck( next_next_game_state, self.uuid) next_state_stats.update(hole_card, next_next_state) next_next_state_vec = self.stats.calc_fine_params( hole_card, next_next_state) next_next_actions = self.emulator.generate_possible_actions( next_next_game_state) best_reward = max( best_reward, self.find_best_strat( next_next_actions, next_next_state_vec, next_next_state['seats'][self.my_seat]['stack'], )[1]) except: continue return best_reward def learn_with_states(self, state, next_state): if next_state['states_original']['street'] in [ 'showdown', 'finished', 4, 5 ]: reward = next_state['rewards'] else: reward = next_state['rewards'] +\ self.gammaReward * self.do_best_simulation( next_state['states_original'], next_state['states_vec'], next_state['stats'], ) X = self.turn2vec(state['states_vec'], state['moves']) y = np.array([reward]) # print(X, y, X.shape, y.shape) self.model.fit(x=X, y=y, epochs=1, verbose=0, batch_size=1)
max_round=max_round, small_blind_amount=sb_amount, ante_amount=ante_amount) players_info = { "uuid-" + str(i): { 'name': 'player' + str(i), 'stack': random.randint(80, 120) } for i in range(0, nb_player) } initial_state = emulator.generate_initial_game_state(players_info) [ emulator.register_player( k, Alpha0Regret( config.mccfr['MCCFR_SIMS'], model, 1, k, initialize_new_emulator(nb_player, max_round, sb_amount, ante_amount), memory)) for k in players_info.keys() ] game_state = initial_state events = [{'type': None}] while events[-1]['type'] != "event_game_finish": game_state, events = emulator.start_new_round(game_state) if events[-1]['type'] != "event_game_finish": pay_history = merge_pkmn_dicts_same_key( [{ x['uuid']: parse_action(x, 1)[6] } for k in events[-1]['round_state']['action_histories'].keys() for x in events[-1]['round_state']['action_histories'][k]])
class CFRBase: def __init__(self): self.emulator = Emulator() #try: self._sigma = pickle.load(open("strategy.pickle", "rb")) #except (OSError, IOError, EOFError) as e: #self._sigma = {} #pickle.dump(self._sigma, open("strategy.pickle", "wb")) self.cumulative_regrets = {} self.cumulative_sigma = {} def get_tree(self,game_state): if game_state[1][-1]['type'] != 'event_game_finish': hist = game_state[1][-1]['round_state']['action_histories'] game_string = "#" for i in hist['preflop']: game_string = game_string + i['action'][0] if "flop" in hist and len(hist['flop']) > 0: for i in hist['flop']: game_string = game_string + i['action'][0] if "turn" in hist and len(hist['turn']) > 0: for i in hist['turn']: game_string = game_string + i['action'][0] if "river" in hist and len(hist['river']) > 0: for i in hist['river']: game_string = game_string + i['action'][0] else: hist = game_state[1][0]['round_state']['action_histories'] game_string = "#" for i in hist['preflop']: game_string = game_string + i['action'][0] if "flop" in hist and len(hist['flop']) > 0: for i in hist['flop']: game_string = game_string + i['action'][0] if "turn" in hist and len(hist['turn']) > 0: for i in hist['turn']: game_string = game_string + i['action'][0] if "river" in hist and len(hist['river']) > 0: for i in hist['river']: game_string = game_string + i['action'][0] return game_string def is_terminal(self,game_state): return game_state[1][-1]['type'] == 'event_game_finish' def state_evaluation(self,game_state): return game_state[1][1]['players'][1]['stack'] - 1000 def _available_actions(self,game_state): actions = [] for i in game_state[1][-1]['valid_actions']: actions.append(i['action']) return actions def load_data(self): with open('strategy.pickle','rb') as handle: self._sigma = pickle.load(handle) def store_data(self): with open('strategy.pickle', 'wb') as handle: pickle.dump(self._sigma, handle, protocol=pickle.HIGHEST_PROTOCOL) def getsigma(self, game_state, percentile, action): tree = self.get_tree(game_state) available_actions = self._available_actions(game_state) if tree not in self._sigma: self._sigma[tree] = {percentile:{}} for i in available_actions: self._sigma[tree][percentile][i] = 1./len(available_actions) elif percentile not in self._sigma[tree]: self._sigma[tree][percentile] = {} for i in available_actions: self._sigma[tree][percentile][i] = 1./len(available_actions) return self._sigma[tree][percentile][action] def _statetomove(self,game_state): next_player_pos = game_state[0]["next_player"] if next_player_pos == 1: return 1 else: return -1 def _getcards(self,game_state): hole_cards = [] next_player_pos = game_state[0]["next_player"] hole_cards.append(game_state[0]['table'].seats.players[next_player_pos].hole_card[0].__str__()) hole_cards.append(game_state[0]['table'].seats.players[next_player_pos].hole_card[1].__str__()) return hole_cards def _getboard(self,game_state): return game_state[0]['table']._community_card def _myround(self,x, base=10): return int(base * round(float(x)/base)) def evaluate_hs(self,game_state): #print('evaluating hs') hole_cards = gen_cards(self._getcards(game_state)) #print('hole cards = ' + str(self._getcards(game_state))) community_cards = self._getboard(game_state) #print('community = ' + str(self._getboard(game_state))) hs = estimate_hole_card_win_rate(100,2, hole_cards,community_cards) #print('hs = ' + str(hs)) percentile = self._myround(hs*100) return percentile def _state_play(self, game_state, action): new_game_state = self.emulator.apply_action(game_state[0], action, 0) return new_game_state def utility_recursive(self): final_value = self._utility_recursive(self.game_state,1,1) #print("##################CUMULATIVE REGRETS#####################") #pprint.pprint(self.cumulative_regrets) #print("##################CUMULATIVE SIGMA#####################") #pprint.pprint(self.cumulative_sigma) return final_value def _cumulate_cfr_regret(self, game_state, percentile, action, regret): tree = self.get_tree(game_state) available_actions = self._available_actions(game_state) if tree not in self.cumulative_regrets: self.cumulative_regrets[tree] = {percentile:{}} for i in available_actions: self.cumulative_regrets[tree][percentile][i] = 0 elif percentile not in self.cumulative_regrets[tree]: self.cumulative_regrets[tree][percentile] = {} for i in available_actions: self.cumulative_regrets[tree][percentile][i] = 0 self.cumulative_regrets[tree][percentile][action] += regret def _cumulate_sigma(self, game_state, percentile, action, prob): tree = self.get_tree(game_state) available_actions = self._available_actions(game_state) if tree not in self.cumulative_sigma: self.cumulative_sigma[tree] = {percentile:{}} for i in available_actions: self.cumulative_sigma[tree][percentile][i] = 0 elif percentile not in self.cumulative_sigma[tree]: self.cumulative_sigma[tree][percentile] = {} for i in available_actions: self.cumulative_sigma[tree][percentile][i] = 0 self.cumulative_sigma[tree][percentile][action] += prob def __update_sigma_recursively(self, game_state): # stop traversal at terminal node if self.is_terminal(game_state): return percentile = self.evaluate_hs(game_state) self._update_sigma(game_state,percentile) # go to subtrees for action in self._available_actions(game_state): self.__update_sigma_recursively(self._state_play(game_state,action)) def _update_sigma(self, game_state, percentile): tree = self.get_tree(game_state) #print("Current State--------") #print(self.get_tree(game_state)) #print(percentile) #if percentile not in self._sigma[tree]: # percentile = (min(100, percentile + 5)) if (min(100, percentile + 5) in self._sigma[tree]) else (max(0, percentile - 5)) if percentile not in self.cumulative_regrets[tree]: #print('Enter unable to find percentile') if (min(100, percentile + 5) in self.cumulative_regrets[tree]): percentile = (min(100, percentile + 5)) elif (max(0, percentile - 5) in self.cumulative_regrets[tree]): percentile = (max(0, percentile - 5)) elif (min(100, percentile + 10) in self.cumulative_regrets[tree]): percentile = (min(100, percentile + 10)) elif (max(0, percentile - 10) in self.cumulative_regrets[tree]): percentile = (max(0, percentile - 10)) elif (min(100, percentile + 20) in self.cumulative_regrets[tree]): percentile = (min(100, percentile + 20)) elif (max(0, percentile - 20) in self.cumulative_regrets[tree]): percentile = (max(0, percentile - 20)) elif (min(100, percentile + 30) in self.cumulative_regrets[tree]): percentile = (min(100, percentile + 30)) elif (max(0, percentile - 30) in self.cumulative_regrets[tree]): percentile = (max(0, percentile - 30)) elif (min(100, percentile + 40) in self.cumulative_regrets[tree]): percentile = (min(100, percentile + 40)) elif (max(0, percentile - 40) in self.cumulative_regrets[tree]): percentile = (max(0, percentile - 40)) elif (min(100, percentile + 50) in self.cumulative_regrets[tree]): percentile = (min(100, percentile + 50)) elif (max(0, percentile - 50) in self.cumulative_regrets[tree]): percentile = (max(0, percentile - 50)) #print('New Percentile = ' + str(percentile)) rgrt_sum = sum(filter(lambda x : x > 0, self.cumulative_regrets[tree][percentile].values())) nr_of_actions = len(self.cumulative_regrets[tree][percentile].keys()) for a in self.cumulative_regrets[tree][percentile]: self._sigma[tree][percentile][a] = max(self.cumulative_regrets[tree][percentile][a], 0.) / rgrt_sum if rgrt_sum > 0 else 1. / nr_of_actions def _utility_recursive(self,game_state, reach_sb, reach_bb): children_states_utilities = {} if self.is_terminal(game_state): return self.state_evaluation(game_state) percentile = self.evaluate_hs(game_state) #print("Current State--------") #print(self.get_tree(game_state)) #print(percentile) #pprint.pprint(game_state[1][-1]['round_state']['community_card']) value = 0. for action in self._available_actions(game_state): probability = self.getsigma(game_state,percentile,action) child_reach_sb = reach_sb * ( probability if self._statetomove(game_state) == 1 else 1) child_reach_bb = reach_bb * ( probability if self._statetomove(game_state) == -1 else 1) child_state_utility = self._utility_recursive(self._state_play(game_state,action),reach_sb,reach_bb) value += (probability * child_state_utility) children_states_utilities[action] = child_state_utility (cfr_reach, reach) = (reach_bb, reach_sb) if self._statetomove(game_state) == 1 else (reach_sb, reach_bb) for action in self._available_actions(game_state): action_cfr_regret = self._statetomove(game_state) * cfr_reach * (children_states_utilities[action] - value) self._cumulate_cfr_regret(game_state, percentile, action, action_cfr_regret) self._cumulate_sigma(game_state, percentile, action, reach * self.getsigma(game_state,percentile,action)) return value def run(self, iterations = 1): print(datetime.datetime.now()) for myiter in range(0, iterations): #initialize new game state with new hole cards self.emulator.set_game_rule(player_num=2, max_round=1, small_blind_amount=10, ante_amount=0) players_info = { "uuid-1": { "name": "player1", "stack": 1000 }, "uuid-2": { "name": "player2", "stack": 1000 } } player1 = RandomPlayer() player2 = RandomPlayer() self.emulator.register_player('uuid-1',player1) self.emulator.register_player('uuid-2',player2) initial_state = self.emulator.generate_initial_game_state(players_info) self.game_state = self.emulator.start_new_round(initial_state) #goto later gamestate #self.game_state = self.emulator.apply_action(self.game_state[0], 'call', 0) self._utility_recursive(self.game_state, 1, 1) self.__update_sigma_recursively(self.game_state) self.store_data() print('data stored, i = ' + str(myiter) ) print(datetime.datetime.now()) print(datetime.datetime.now())
j=0 emulator = Emulator() #quuid = "uuid-q" p_uuid=["A1","A2","A3","A4"] #qlearner_player = RLPlayer(n_players, quuid) monte_carlos_tries=[[RandomPlayer(p_uuid[0]),RiskyPlayer()],[RiskyPlayer(),CallPlayer()],[RiskyPlayer(),BluffPlayer()]] names=[['Rand','Risk'],['Call','Risk'],['Bluff','Risk']] for tryM in monte_carlos_tries: df = pd.DataFrame(columns = ['uuid', 'stack', 'game']) for i in range(0,1): print("starting game " + str(i) + " from try " + str(j)) df1 = pd.DataFrame(columns = ['uuid', 'stack', 'round']) df2 = pd.DataFrame(columns = ['uuid', 'stack', 'round']) df3 = pd.DataFrame(columns = ['uuid', 'stack', 'round']) df4 = pd.DataFrame(columns = ['uuid', 'stack', 'round']) emulator.register_player(uuid=p_uuid[0], player=tryM[0]) emulator.register_player(uuid=p_uuid[1], player=tryM[1]) emulator.set_game_rule(player_num=2, max_round=1000, small_blind_amount=20, ante_amount=0) # 2. Setup GameState object players_info = { p_uuid[0]: { "name": "player1", "stack": 10000 }, p_uuid[1]: { "name": "player2", "stack": 10000 } } initial_state = emulator.generate_initial_game_state(players_info) game_state, events = emulator.start_new_round(initial_state) # 3. Run simulation and get updated GameState object game_finish_state, events = emulator.run_until_game_finish(game_state) #qlearner_player.clear_stack() for event in events: if(event['type']=="event_round_finish"): for player in event['round_state']['seats']:
class EmulatorTest(BaseUnitTest): def setUp(self): self.emu = Emulator() def test_set_game_rule(self): self.emu.set_game_rule(2, 8, 5, 3) self.eq(2, self.emu.game_rule["player_num"]) self.eq(8, self.emu.game_rule["max_round"]) self.eq(5, self.emu.game_rule["sb_amount"]) self.eq(3, self.emu.game_rule["ante"]) def test_register_and_fetch_player(self): p1, p2 = FoldMan(), FoldMan() self.emu.register_player("uuid-1", p1) self.emu.register_player("uuid-2", p2) self.eq(p1, self.emu.fetch_player("uuid-1")) self.eq(p2, self.emu.fetch_player("uuid-2")) @raises(TypeError) def test_register_invalid_player(self): self.emu.register_player("uuid", "hoge") def test_blind_structure(self): game_state = restore_game_state(TwoPlayerSample.round_state) game_state = attach_hole_card_from_deck(game_state, "tojrbxmkuzrarnniosuhct") game_state = attach_hole_card_from_deck(game_state, "pwtwlmfciymjdoljkhagxa") self.emu.set_game_rule(2, 10, 5, 0) self.emu.set_blind_structure({5: { "ante": 5, "small_blind": 60 } }) p1 = TestPlayer([("fold", 0), ('raise', 55), ('call', 0)]) p2 = TestPlayer([("call", 15), ("call", 55), ('fold', 0)]) self.emu.register_player("tojrbxmkuzrarnniosuhct", p1) self.emu.register_player("pwtwlmfciymjdoljkhagxa", p2) game_state, events = self.emu.run_until_round_finish(game_state) self.eq(65, game_state["table"].seats.players[0].stack) self.eq(135, game_state["table"].seats.players[1].stack) game_state, events = self.emu.start_new_round(game_state) game_state, events = self.emu.run_until_round_finish(game_state) self.eq(120, game_state["table"].seats.players[0].stack) self.eq(80, game_state["table"].seats.players[1].stack) game_state, events = self.emu.start_new_round(game_state) self.eq("event_game_finish", events[0]["type"]) self.eq(0, game_state["table"].seats.players[0].stack) self.eq(80, game_state["table"].seats.players[1].stack) def test_blind_structure_update(self): self.emu.set_game_rule(2, 8, 5, 3) p1, p2 = FoldMan(), FoldMan() self.emu.register_player("uuid-1", p1) self.emu.register_player("uuid-2", p2) blind_structure = { 3: { "ante": 5, "small_blind": 10 }, 5: {"ante": 10, "small_blind": 20 } } self.emu.set_blind_structure(blind_structure) players_info = { "uuid-1": { "name": "hoge", "stack": 100 }, "uuid-2": { "name": "fuga", "stack": 100 } } state = self.emu.generate_initial_game_state(players_info) self.eq(5, state["small_blind_amount"]) state, _ = self.emu.start_new_round(state) state, _ = self.emu.apply_action(state, "fold") self.eq(5, state["small_blind_amount"]) state, _ = self.emu.apply_action(state, "fold") self.eq(5, state["small_blind_amount"]) state, _ = self.emu.apply_action(state, "fold") self.eq(10, state["small_blind_amount"]) state, _ = self.emu.apply_action(state, "fold") self.eq(10, state["small_blind_amount"]) state, _ = self.emu.apply_action(state, "fold") self.eq(20, state["small_blind_amount"]) state, _ = self.emu.apply_action(state, "fold") self.eq(20, state["small_blind_amount"]) def test_apply_action(self): game_state = restore_game_state(TwoPlayerSample.round_state) game_state = attach_hole_card_from_deck(game_state, "tojrbxmkuzrarnniosuhct") game_state = attach_hole_card_from_deck(game_state, "pwtwlmfciymjdoljkhagxa") self.emu.set_game_rule(2, 10, 5, 0) p1, p2 = FoldMan(), FoldMan() self.emu.register_player("tojrbxmkuzrarnniosuhct", FoldMan()) self.emu.register_player("pwtwlmfciymjdoljkhagxa", FoldMan()) game_state, events = self.emu.apply_action(game_state, "call", 15) self.eq(Const.Street.RIVER, game_state["street"]) self.eq(TwoPlayerSample.p1_action_histories, \ game_state["table"].seats.players[0].round_action_histories[Const.Street.TURN]) self.eq(2, len(events)) self.eq("event_new_street", events[0]["type"]) self.eq("event_ask_player", events[1]["type"]) game_state, events = self.emu.apply_action(game_state, "call", 0) self.eq(1, len(events)) self.eq("event_ask_player", events[0]["type"]) game_state, events = self.emu.apply_action(game_state, "call", 0) self.eq(1, len(events)) self.eq("event_round_finish", events[0]["type"]) def test_apply_action_game_finish_detect(self): game_state = restore_game_state(TwoPlayerSample.round_state) game_state = attach_hole_card_from_deck(game_state, "tojrbxmkuzrarnniosuhct") game_state = attach_hole_card_from_deck(game_state, "pwtwlmfciymjdoljkhagxa") self.emu.set_game_rule(2, 3, 5, 0) p1, p2 = FoldMan(), FoldMan() self.emu.register_player("tojrbxmkuzrarnniosuhct", FoldMan()) self.emu.register_player("pwtwlmfciymjdoljkhagxa", FoldMan()) game_state, events = self.emu.apply_action(game_state, "fold") self.eq("event_game_finish", events[-1]["type"]) def test_apply_action_start_next_round(self): game_state = restore_game_state(TwoPlayerSample.round_state) game_state = attach_hole_card_from_deck(game_state, "tojrbxmkuzrarnniosuhct") game_state = attach_hole_card_from_deck(game_state, "pwtwlmfciymjdoljkhagxa") self.emu.set_game_rule(2, 4, 5, 0) p1, p2 = FoldMan(), FoldMan() self.emu.register_player("tojrbxmkuzrarnniosuhct", FoldMan()) self.emu.register_player("pwtwlmfciymjdoljkhagxa", FoldMan()) game_state, events = self.emu.apply_action(game_state, "fold") self.eq(120, game_state["table"].seats.players[0].stack) self.eq(80, game_state["table"].seats.players[1].stack) game_state, events = self.emu.apply_action(game_state, "raise", 20) self.eq("event_ask_player", events[-1]["type"]) self.eq(100, game_state["table"].seats.players[0].stack) self.eq(70, game_state["table"].seats.players[1].stack) @raises(Exception) def test_apply_action_when_game_finished(self): game_state = restore_game_state(TwoPlayerSample.round_state) game_state = attach_hole_card_from_deck(game_state, "tojrbxmkuzrarnniosuhct") game_state = attach_hole_card_from_deck(game_state, "pwtwlmfciymjdoljkhagxa") self.emu.set_game_rule(2, 3, 5, 0) p1, p2 = FoldMan(), FoldMan() self.emu.register_player("tojrbxmkuzrarnniosuhct", FoldMan()) self.emu.register_player("pwtwlmfciymjdoljkhagxa", FoldMan()) game_state, events = self.emu.apply_action(game_state, "fold") self.emu.apply_action(game_state, "fold") def test_run_until_round_finish(self): game_state = restore_game_state(TwoPlayerSample.round_state) game_state = attach_hole_card_from_deck(game_state, "tojrbxmkuzrarnniosuhct") game_state = attach_hole_card_from_deck(game_state, "pwtwlmfciymjdoljkhagxa") self.emu.set_game_rule(2, 10, 5, 0) p1 = TestPlayer([("fold", 0)]) p2 = TestPlayer([("call", 15)]) self.emu.register_player("tojrbxmkuzrarnniosuhct", p1) self.emu.register_player("pwtwlmfciymjdoljkhagxa", p2) game_state, events = self.emu.run_until_round_finish(game_state) self.eq("event_new_street", events[0]["type"]) self.eq("event_ask_player", events[1]["type"]) self.eq("event_round_finish", events[2]["type"]) def test_run_until_round_finish_when_already_finished(self): game_state = restore_game_state(TwoPlayerSample.round_state) game_state = attach_hole_card_from_deck(game_state, "tojrbxmkuzrarnniosuhct") game_state = attach_hole_card_from_deck(game_state, "pwtwlmfciymjdoljkhagxa") self.emu.set_game_rule(2, 10, 5, 0) p1 = TestPlayer([("fold", 0)]) p2 = TestPlayer([("call", 15)]) self.emu.register_player("tojrbxmkuzrarnniosuhct", p1) self.emu.register_player("pwtwlmfciymjdoljkhagxa", p2) game_state, events = self.emu.run_until_round_finish(game_state) game_state, events = self.emu.run_until_round_finish(game_state) self.eq(0, len(events)) def test_run_until_round_finish_game_finish_detect(self): uuids = ["tojrbxmkuzrarnniosuhct", "pwtwlmfciymjdoljkhagxa"] holecards = [[Card.from_str(s) for s in ss] for ss in [["CA", "D2"], ["C8", "H5"]]] game_state = restore_game_state(TwoPlayerSample.round_state) game_state = reduce(lambda a,e: attach_hole_card(a, e[0], e[1]), zip(uuids, holecards), game_state) game_state = attach_hole_card_from_deck(game_state, "pwtwlmfciymjdoljkhagxa") self.emu.set_game_rule(2, 10, 5, 0) p1 = TestPlayer([("raise", 65)]) p2 = TestPlayer([("call", 15), ("call", 65)]) self.emu.register_player("tojrbxmkuzrarnniosuhct", p1) self.emu.register_player("pwtwlmfciymjdoljkhagxa", p2) game_state["table"].deck.deck.append(Card.from_str("C7")) game_state, events = self.emu.run_until_round_finish(game_state) self.eq("event_new_street", events[0]["type"]) self.eq("event_ask_player", events[1]["type"]) self.eq("event_ask_player", events[2]["type"]) self.eq("event_round_finish", events[3]["type"]) self.eq("event_game_finish", events[4]["type"]) self.eq(0, events[4]["players"][0]["stack"]) self.eq(200, events[4]["players"][1]["stack"]) def test_run_until_game_finish(self): game_state = restore_game_state(TwoPlayerSample.round_state) game_state = attach_hole_card_from_deck(game_state, "tojrbxmkuzrarnniosuhct") game_state = attach_hole_card_from_deck(game_state, "pwtwlmfciymjdoljkhagxa") self.emu.set_game_rule(2, 10, 5, 1) self.emu.register_player("tojrbxmkuzrarnniosuhct", FoldMan()) self.emu.register_player("pwtwlmfciymjdoljkhagxa", FoldMan()) game_state, events = self.emu.run_until_game_finish(game_state) self.eq("event_game_finish", events[-1]["type"]) self.eq(114, game_state["table"].seats.players[0].stack) self.eq(86, game_state["table"].seats.players[1].stack) def test_run_until_game_finish_when_one_player_is_left(self): uuids = ["ruypwwoqwuwdnauiwpefsw", "sqmfwdkpcoagzqxpxnmxwm", "uxrdiwvctvilasinweqven"] holecards = [[Card.from_str(s) for s in ss] for ss in [["C2","C3"],["HA","CA"],["D5","H6"]]] game_state = restore_game_state(ThreePlayerGameStateSample.round_state) game_state = reduce(lambda state, item: attach_hole_card(state, item[0], item[1]), zip(uuids, holecards), game_state) sb_amount, ante = 5, 7 self.emu.set_game_rule(3, 10, sb_amount, ante) p1_acts = [("fold",0), ("call", 10), ('call', 0), ('call', 10), ("fold",0)] p2_acts = [] p3_acts = [("raise", 10)] players = [TestPlayer(acts) for acts in [p1_acts, p2_acts, p3_acts]] [self.emu.register_player(uuid, player) for uuid, player in zip(uuids, players)] game_state["table"].deck.deck.append(Card.from_str("C7")) game_state, events = self.emu.run_until_game_finish(game_state) self.eq("event_game_finish", events[-1]["type"]) self.eq(0, game_state["table"].seats.players[0].stack) self.eq(0, game_state["table"].seats.players[1].stack) self.eq(292, game_state["table"].seats.players[2].stack) def test_run_until_game_finish_when_final_round(self): uuids = ["ruypwwoqwuwdnauiwpefsw", "sqmfwdkpcoagzqxpxnmxwm", "uxrdiwvctvilasinweqven"] holecards = [[Card.from_str(s) for s in ss] for ss in [["C2","C3"],["HA","CA"],["D5","H6"]]] game_state = restore_game_state(ThreePlayerGameStateSample.round_state) game_state = reduce(lambda state, item: attach_hole_card(state, item[0], item[1]), zip(uuids, holecards), game_state) sb_amount, ante = 5, 7 self.emu.set_game_rule(3, 10, sb_amount, ante) [self.emu.register_player(uuid, FoldMan()) for uuid in uuids] game_state["table"].deck.deck.append(Card.from_str("C7")) game_state, events = self.emu.run_until_game_finish(game_state) self.eq("event_game_finish", events[-1]["type"]) self.eq(10, game_state["round_count"]) self.eq(35, game_state["table"].seats.players[0].stack) self.eq(0, game_state["table"].seats.players[1].stack) self.eq(265, game_state["table"].seats.players[2].stack) def test_last_round_judge(self): game_state = restore_game_state(TwoPlayerSample.round_state) self.emu.set_game_rule(2, 3, 5, 0) self.false(self.emu._is_last_round(game_state, self.emu.game_rule)) game_state["street"] = Const.Street.FINISHED self.true(self.emu._is_last_round(game_state, self.emu.game_rule)) game_state["round_count"] = 2 self.false(self.emu._is_last_round(game_state, self.emu.game_rule)) game_state["table"].seats.players[0].stack = 0 self.true(self.emu._is_last_round(game_state, self.emu.game_rule)) def test_start_new_round(self): game_state = restore_game_state(TwoPlayerSample.round_state) game_state = attach_hole_card_from_deck(game_state, "tojrbxmkuzrarnniosuhct") game_state = attach_hole_card_from_deck(game_state, "pwtwlmfciymjdoljkhagxa") p1, p2 = FoldMan(), FoldMan() self.emu.set_game_rule(2, 10, 5, 0) self.emu.register_player("tojrbxmkuzrarnniosuhct", FoldMan()) self.emu.register_player("pwtwlmfciymjdoljkhagxa", FoldMan()) # run until round finish game_state, event = self.emu.apply_action(game_state, "call", 15) game_state, event = self.emu.apply_action(game_state, "call", 0) game_state, event = self.emu.apply_action(game_state, "call", 0) game_state, events = self.emu.start_new_round(game_state) self.eq(4, game_state["round_count"]) self.eq(1, game_state["table"].dealer_btn) self.eq(0, game_state["street"]) self.eq(0, game_state["next_player"]) self.eq("event_new_street", events[0]["type"]) self.eq("event_ask_player", events[1]["type"]) self.eq("preflop", events[0]["street"]) self.eq("tojrbxmkuzrarnniosuhct", events[1]["uuid"]) def test_start_new_round_exclude_no_money_players(self): uuids = ["ruypwwoqwuwdnauiwpefsw", "sqmfwdkpcoagzqxpxnmxwm", "uxrdiwvctvilasinweqven"] game_state = restore_game_state(ThreePlayerGameStateSample.round_state) original = reduce(lambda state, uuid: attach_hole_card_from_deck(state, uuid), uuids, game_state) sb_amount, ante = 5, 7 self.emu.set_game_rule(3, 10, sb_amount, ante) [self.emu.register_player(uuid, FoldMan()) for uuid in uuids] # case1: second player cannot pay small blind finish_state, events = self.emu.apply_action(original, "fold") finish_state["table"].seats.players[0].stack = 11 stacks = [p.stack for p in finish_state["table"].seats.players] game_state, events = self.emu.start_new_round(finish_state) self.eq(2, game_state["table"].dealer_btn) self.eq(1, game_state["next_player"]) self.eq(stacks[1]-sb_amount-ante, game_state["table"].seats.players[1].stack) self.eq(stacks[2]-sb_amount*2-ante, game_state["table"].seats.players[2].stack) self.eq(PayInfo.FOLDED, game_state["table"].seats.players[0].pay_info.status) self.eq(sb_amount*3 + ante*2, GameEvaluator.create_pot(game_state["table"].seats.players)[0]["amount"]) # case2: third player cannot pay big blind finish_state, events = self.emu.apply_action(original, "fold") finish_state["table"].seats.players[1].stack = 16 stacks = [p.stack for p in finish_state["table"].seats.players] game_state, events = self.emu.start_new_round(finish_state) self.eq(2, game_state["table"].dealer_btn) self.eq(0, game_state["next_player"]) self.eq(stacks[0]-sb_amount-ante, game_state["table"].seats.players[0].stack) self.eq(stacks[2]-sb_amount*2-ante, game_state["table"].seats.players[2].stack) self.eq(PayInfo.FOLDED, game_state["table"].seats.players[1].pay_info.status) self.eq(PayInfo.PAY_TILL_END, game_state["table"].seats.players[0].pay_info.status) self.eq(sb_amount*3 + ante*2, GameEvaluator.create_pot(game_state["table"].seats.players)[0]["amount"]) def test_start_new_round_exclude_no_money_players2(self): uuids = ["ruypwwoqwuwdnauiwpefsw", "sqmfwdkpcoagzqxpxnmxwm", "uxrdiwvctvilasinweqven"] game_state = restore_game_state(ThreePlayerGameStateSample.round_state) original = reduce(lambda state, uuid: attach_hole_card_from_deck(state, uuid), uuids, game_state) sb_amount, ante = 5, 7 self.emu.set_game_rule(3, 10, sb_amount, ante) [self.emu.register_player(uuid, FoldMan()) for uuid in uuids] # case1: second player cannot pay small blind finish_state, events = self.emu.apply_action(original, "fold") finish_state["table"].seats.players[2].stack = 6 stacks = [p.stack for p in finish_state["table"].seats.players] game_state, events = self.emu.start_new_round(finish_state) self.eq(0, game_state["table"].dealer_btn) self.eq(1, game_state["table"].sb_pos()) self.eq(1, game_state["next_player"]) def test_start_new_round_game_finish_judge(self): uuids = ["ruypwwoqwuwdnauiwpefsw", "sqmfwdkpcoagzqxpxnmxwm", "uxrdiwvctvilasinweqven"] game_state = restore_game_state(ThreePlayerGameStateSample.round_state) original = reduce(lambda state, uuid: attach_hole_card_from_deck(state, uuid), uuids, game_state) sb_amount, ante = 5, 7 self.emu.set_game_rule(3, 10, sb_amount, ante) [self.emu.register_player(uuid, FoldMan()) for uuid in uuids] finish_state, events = self.emu.apply_action(original, "fold") finish_state["table"].seats.players[2].stack = 11 finish_state["table"].seats.players[1].stack = 16 game_state, events = self.emu.start_new_round(finish_state) self.eq(1, len(events)) self.eq("event_game_finish", events[0]["type"]) def test_generate_initial_game_state(self): self.emu.set_game_rule(2, 8, 5, 3) p1, p2 = FoldMan(), FoldMan() players_info = OrderedDict() players_info["uuid-1"] = { "name": "hoge", "stack": 100 } players_info["uuid-2"] = { "name": "fuga", "stack": 100 } state = self.emu.generate_initial_game_state(players_info) table = state["table"] self.eq(0, state["round_count"]) self.eq(5, state["small_blind_amount"]) self.eq(100, table.seats.players[0].stack) self.eq("uuid-1", table.seats.players[0].uuid) self.eq(100, table.seats.players[1].stack) self.eq("uuid-2", table.seats.players[1].uuid) self.eq(1, table.dealer_btn) state, events = self.emu.start_new_round(state) self.eq(0, state["table"].dealer_btn) self.eq(1, state["table"].sb_pos()) self.eq(0, state["table"].bb_pos()) self.eq(1, state["next_player"]) state, events = self.emu.apply_action(state, "call", 10) self.eq(1, state["next_player"]) def test_generate_possible_actions(self): state1 = restore_game_state(TwoPlayerSample.round_state) self.eq(TwoPlayerSample.valid_actions, self.emu.generate_possible_actions(state1)) state2 = restore_game_state(ThreePlayerGameStateSample.round_state) self.eq(ThreePlayerGameStateSample.valid_actions, self.emu.generate_possible_actions(state2))
n_players = 4 j=0 emulator = Emulator() #quuid = "uuid-q" p_uuid=["high-iq","low-iq","low-iq2","low-iq3"] #qlearner_player = RLPlayer(n_players, quuid) monte_carlos_tries=[[10,10],[10,20],[10,30],[10,50],[10,100],[10,200],[10,400],[10,800],[10,1000],[10,1500]] for tryM in monte_carlos_tries: df = pd.DataFrame(columns = ['uuid', 'stack', 'game']) for i in range(0,2): print("starting game " + str(i) + " from try " + str(j)) df1 = pd.DataFrame(columns = ['uuid', 'stack', 'round']) df2 = pd.DataFrame(columns = ['uuid', 'stack', 'round']) df3 = pd.DataFrame(columns = ['uuid', 'stack', 'round']) df4 = pd.DataFrame(columns = ['uuid', 'stack', 'round']) emulator.register_player(uuid=p_uuid[0], player=RiskyPlayer(n_players,tryM[1],0.7)) emulator.register_player(uuid=p_uuid[1], player=RiskyPlayer(n_players,tryM[0],0.7)) emulator.register_player(uuid=p_uuid[2], player=RiskyPlayer(n_players,tryM[0],0.7)) emulator.register_player(uuid=p_uuid[3], player=RiskyPlayer(n_players,tryM[0],0.7)) emulator.set_game_rule(player_num=4, max_round=1000, small_blind_amount=20, ante_amount=0) # 2. Setup GameState object players_info = { p_uuid[0]: { "name": "player1", "stack": 10000 }, p_uuid[1]: { "name": "player2", "stack": 10000 }, p_uuid[2]: { "name": "player3", "stack": 10000 }, p_uuid[3]: { "name": "player4", "stack": 10000 }, } initial_state = emulator.generate_initial_game_state(players_info) game_state, events = emulator.start_new_round(initial_state) # 3. Run simulation and get updated GameState object game_finish_state, events = emulator.run_until_game_finish(game_state)
# 1. Set game settings on emulator n_players = 2 emulator = Emulator() quuid = "uuid-q" qlearner_player = RLPlayer(n_players, quuid) df1 = pd.DataFrame(columns=['uuid', 'win_ratio', 'stack-diff']) df2 = pd.DataFrame(columns=['uuid', 'win_ratio', 'stack-diff']) df3 = pd.DataFrame(columns=['uuid', 'win_ratio', 'stack-diff']) df4 = pd.DataFrame(columns=['uuid', 'win_ratio', 'stack-diff']) max_round = 50 learning_rates = np.arange(0.1, 1, 0.1) #learning_rates = [0.3] for j in learning_rates: qlearner_player = RLPlayer(n_players, quuid, j) for i in range(0, 150): emulator.register_player(uuid="uuid-1", player=HonestPlayer(n_players)) #emulator.register_player(uuid="uuid-2", player=RiskyPlayer(n_players)) emulator.register_player(uuid=quuid, player=qlearner_player) emulator.set_game_rule(player_num=n_players, max_round=max_round, small_blind_amount=20, ante_amount=0) players_info = { "uuid-1": { "name": "player1", "stack": 1000 }, #"uuid-2": { "name": "player2", "stack": 1000 }, quuid: { "name": "q-learning", "stack": 1000
from pypokerengine.utils.card_utils import gen_cards SAVE_PATH = 'saved_models/second_test/policy_net_after' STACK = 1000 N_PLAYER = 2 MAX_ROUND = 2 SMALL_BLIND_AMOUNT = 5 ANTE_AMOUNT = 1 if __name__ == '__main__': emul = Emulator() emul.set_game_rule(N_PLAYER, MAX_ROUND, SMALL_BLIND_AMOUNT, ANTE_AMOUNT) console = ConsolePlayer() bot = PGBot("bot", pickle.load(open(SAVE_PATH + "105980", "rb"))) emul.register_player("target", bot) emul.register_player("baseline", console) players_info = { "target": { "name": "PGBot", "stack": STACK }, "baseline": { "name": "console", "stack": STACK } } game_state = emul.generate_initial_game_state(players_info) while True: game_state, events = emul.start_new_round(game_state)