class Game: def __init__(self, game_state, hole_card, player): self.player = player self.initial_state = game_state self.hole_card = hole_card self.emulator = Emulator() self.emulator.set_game_rule(2, 10, 10, 0) def actions(self, state): """Return a list of the allowable moves at this point.""" return list( map(lambda x: x['action'], self.emulator.generate_possible_actions(state))) def result(self, state, move): """Return the state that results from making a move from a state.""" return self.emulator.apply_action(state, move)[0] def utility(self, state, player): """Return the value of this final state to player.""" score = estimate_hole_card_win_rate(100, 2, self.hole_card, state['table']._community_card) # 1 is MAX player if self.player == player: return score else: return -score def terminal_test(self, state): """Return True if this is a final state for the game.""" return self.emulator._is_last_round(state, self.emulator.game_rule) def to_move(self, state): """Return the player whose move it is in this state.""" return state['next_player'] def display(self, state): """Print or otherwise display the state.""" print(state) def __repr__(self): return '<{}>'.format(self.__class__.__name__) def play_game(self, *players): """Play an n-person, move-alternating game.""" state = self.initial_state while True: for player in players: move = player(self, state) state = self.result(state, move) if self.terminal_test(state): self.display(state) return self.utility(state, self.to_move(self.initial_state))
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))
class Game: def __init__(self, hole_card, player, state, num_rounds, valid_actions, round_state, weights): self.hole_card = hole_card self.player = player self.init_state = state self.emulator = Emulator() self.num_rounds = num_rounds self.valid_actions = valid_actions self.weights = weights self.round_state = round_state self.emulator.set_game_rule(2, self.num_rounds, 10, 0) def terminal_test(self, state): """ Check if game tree ends """ return self.emulator._is_last_round(state, self.emulator.game_rule) def actions(self, state): """ generate legal moves at this state """ temp = list( map(lambda x: x['action'], self.emulator.generate_possible_actions(state))) return temp def eval_heuristics(self, player, state, win_rate): if isDebug: print("Evaluating heuristics") if isHeuristicTimed: start = time.time() print(time.time()) amount_in_pot = float(self.round_state['pot']['main']['amount']) / 8.8 EHS = (EffectiveHandStrength( self.hole_card, state['table']._community_card) + 10) / 20 * 100 if isDebug: print("=======Got heuristics") if isHeuristicTimed: end = start = time.time() print("==========Got heuristics in time: " + str(end - start) + " secs") heuristics = [win_rate, amount_in_pot, EHS] res = np.dot(self.weights, heuristics) return res def future_move(self, state): return state['next_player'] def project(self, curr_state, move): """ projects what happens when making a move from current state """ return self.emulator.apply_action(curr_state, move)[0] def minimax(self, newState, max_depth, hole_cards, community_cards): """ MiniMax decision strategy """ player = self.future_move(newState) inf = float('inf') if (community_cards == []): # Preflop win_rate = eval_pre_flop.eval_pre_flop(hole_cards) / 100 * 50 + 50 else: win_rate = eval_post_flop.eval_post_flop_rank( hole_cards, community_cards) / 100 * 50 + 50 def min_value(newState, alpha, beta, depth): """ determines what the strategy of the Min palyer should be. It is limited by max depth""" if isDebug: print("In MIN") if depth == max_depth or self.terminal_test(newState): return self.eval_heuristics(player, newState, win_rate) v = inf for a in self.actions(newState): v = min( max_value(self.project(newState, a), alpha, beta, depth + 1), v) if v <= alpha: return v beta = min(beta, v) return v def max_value(newState, alpha, beta, depth): """ determines what the strategy of the Max palyer should be. It is limited by max depth""" if isDebug: print("In MAX") if depth == max_depth or self.terminal_test(newState): return self.eval_heuristics(player, newState, win_rate) v = -inf for a in self.actions(newState): v = max( min_value(self.project(newState, a), alpha, beta, depth + 1), v) if (v >= beta): return v alpha = max(alpha, v) return v # alpha-beta pruning code # considers the next best action to take by starting off the Minimax recursion # and pruning out the nodes that no longer need to be considered best_score = -inf beta = inf best_action = None for a in self.actions(newState): v = min_value(self.project(newState, a), best_score, beta, 0) if v > best_score: best_score = v best_action = a # TODO: Since our player folds a lot. Please update/remove as required if best_action == 'fold': # print('fold') return 'call' else: # print(best_action) return best_action return best_action
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))