def test_everyone_agree_logic_regression(self): players = [Player("uuid%d" % i, 100) for i in range(4)] players[0].stack = 150 players[1].stack = 150 players[2].stack = 50 players[3].stack = 50 deck = Deck(cheat=True, cheat_card_ids=range(1, 53)) table = Table(cheat_deck=deck) for player in players: table.seats.sitdown(player) table.dealer_btn = 3 table.set_blind_pos(0, 1) state, _ = RoundManager.start_new_round(1, 5, 0, table) state, _ = RoundManager.apply_action(state, "raise", 15) state, _ = RoundManager.apply_action(state, "raise", 20) state, _ = RoundManager.apply_action(state, "raise", 25) state, _ = RoundManager.apply_action(state, "raise", 30) state, _ = RoundManager.apply_action(state, "raise", 50) state, _ = RoundManager.apply_action(state, "call", 50) state, _ = RoundManager.apply_action(state, "raise", 125) state, _ = RoundManager.apply_action(state, "call", 125) state, _ = RoundManager.apply_action(state, "fold", 0) state, _ = RoundManager.apply_action(state, "fold", 0) self.eq(Const.Street.FINISHED, state["street"])
def __setup_table(self): players = [Player("uuid%d" % i, 100) for i in range(3)] deck = Deck(cheat=True, cheat_card_ids=range(1,53)) table = Table(cheat_deck=deck) for player in players: table.seats.sitdown(player) table.dealer_btn = 2 table.set_blind_pos(0, 1) return table
def __setup_table(self): players = [Player("uuid%d" % i, 100) for i in range(3)] deck = Deck(cheat=True, cheat_card_ids=range(1, 53)) table = Table(cheat_deck=deck) for player in players: table.seats.sitdown(player) table.dealer_btn = 2 table.set_blind_pos(0, 1) return table
def __init__(self, small_blind_amount=None, initial_stack=None, ante=None): self.small_blind_amount = small_blind_amount self.ante = ante if ante else 0 self.initial_stack = initial_stack self.uuid_list = self.__generate_uuid_list() self.message_handler = MessageHandler() self.message_summarizer = MessageSummarizer(verbose=0) self.table = Table() self.blind_structure = {}
def generate_initial_game_state(self, players_info): table = Table() for uuid, info in players_info.items(): table.seats.sitdown(Player(uuid, info["stack"], info["name"])) table.dealer_btn = len(table.seats.players) - 1 return { "round_count": 0, "small_blind_amount": self.game_rule["sb_amount"], "street": Const.Street.PREFLOP, "next_player": None, "table": table }
def deepcopy_game_state(game_state): tabledeepcopy = Table.deserialize(game_state["table"].serialize()) return { "round_count": game_state["round_count"], "small_blind_amount": game_state["small_blind_amount"], "street": game_state["street"], "next_player": game_state["next_player"], "table": tabledeepcopy }
def deepcopy_game_state(game_state): tabledeepcopy = Table.deserialize(game_state['table'].serialize()) return { 'round_count': game_state['round_count'], 'small_blind_amount': game_state['small_blind_amount'], 'street': game_state['street'], 'next_player': game_state['next_player'], 'table': tabledeepcopy }
def deepcopy_game_state(game_state): tabledeepcopy = Table.deserialize(game_state["table"].serialize()) return { "round_count": game_state["round_count"], "small_blind_amount": game_state["small_blind_amount"], "street": game_state["street"], "next_player": game_state["next_player"], "table": tabledeepcopy }
def __deep_copy_state(self, state): table_deepcopy = Table.deserialize(state['table'].serialize()) return { 'round_count': state['round_count'], 'small_blind_amount': state['small_blind_amount'], 'street': state['street'], 'next_player': state['next_player'], 'table': table_deepcopy }
def __deep_copy_state(self, state): table_deepcopy = Table.deserialize(state["table"].serialize()) return { "round_count": state["round_count"], "small_blind_amount": state["small_blind_amount"], "street": state["street"], "next_player": state["next_player"], "table": table_deepcopy }
def _restore_table(round_state): table = Table() table.dealer_btn = round_state["dealer_btn"] table.set_blind_pos(round_state["small_blind_pos"], round_state["big_blind_pos"]) _restore_community_card_on_table(table, round_state["community_card"]) table.deck = _restore_deck(round_state["community_card"]) table.seats = _restore_seats(round_state["seats"], round_state["action_histories"]) return table
def __setup_players_with_table(self): p1 = Player('uuid1', 100) p2 = Player('uuid2', 100) p3 = Player('uuid3', 100) p2.pay_info.update_to_fold() p3.pay_info.update_to_allin() table = Table() for player in [p1, p2, p3]: table.seats.sitdown(player) return table
def __init__(self, small_blind_amount=None, initial_stack=None, ante=None, log_file_location: str = ''): self.small_blind_amount = small_blind_amount self.ante = ante if ante else 0 self.initial_stack = initial_stack self.uuid_list = self.__generate_uuid_list() self.message_handler = MessageHandler() self.message_summarizer = MessageSummarizer(verbose=0) self.table = Table() self.blind_structure = {} self.log_file_location = log_file_location self.game_history = {}
def _restore_table(round_state): table = Table() table.dealer_btn = round_state['dealer_btn'] table.set_blind_pos(round_state['small_blind_pos'], round_state['big_blind_pos']) _restore_community_card_on_table(table, round_state['community_card']) table.deck = _restore_deck(round_state['community_card']) table.seats = _restore_seats(round_state['seats'], round_state['action_histories']) return table
def start_game(self, players_info, game_config): self.config = game_config # setup table table = Table() for uuid, name in players_info.items(): player = Player(uuid, game_config['initial_stack'], name) table.seats.sitdown(player) # start the first round state, msgs = self._start_new_round(1, game_config['blind_structure'], table) self.current_state = state return _parse_broadcast_destination(msgs, self.current_state['table'])
def test_serialization(self): table = self.__setup_players_with_table() for card in table.deck.draw_cards(3): table.add_community_card(card) table.shift_dealer_btn() table.set_blind_pos(1, 2) serial = table.serialize() restored = Table.deserialize(serial) self.eq(table.dealer_btn, restored.dealer_btn) self.eq(Seats.serialize(table.seats), Seats.serialize(restored.seats)) self.eq(Deck.serialize(table.deck), Deck.serialize(restored.deck)) self.eq(table.get_community_card(), restored.get_community_card()) self.eq(1, restored.sb_pos()) self.eq(2, restored.bb_pos())
def test_everyone_agree_logic_regression(self): players = [Player("uuid%d" % i, 100) for i in range(4)] players[0].stack = 150 players[1].stack = 150 players[2].stack = 50 players[3].stack = 50 deck = Deck(cheat=True, cheat_card_ids=range(1,53)) table = Table(cheat_deck=deck) for player in players: table.seats.sitdown(player) table.dealer_btn = 3 table.set_blind_pos(0, 1) state, _ = RoundManager.start_new_round(1, 5, 0, table) state, _ = RoundManager.apply_action(state, "raise", 15) state, _ = RoundManager.apply_action(state, "raise", 20) state, _ = RoundManager.apply_action(state, "raise", 25) state, _ = RoundManager.apply_action(state, "raise", 30) state, _ = RoundManager.apply_action(state, "raise", 50) state, _ = RoundManager.apply_action(state, "call", 50) state, _ = RoundManager.apply_action(state, "raise", 125) state, _ = RoundManager.apply_action(state, "call", 125) state, _ = RoundManager.apply_action(state, "fold", 0) state, _ = RoundManager.apply_action(state, "fold", 0) self.eq(Const.Street.FINISHED, state["street"])
def setup_table(): table = Table() players = [Player("uuid%d" % i, 100, "hoge") for i in range(3)] table.seats.players = players table.add_community_card(Card.from_id(1)) table.dealer_btn = 2 table.set_blind_pos(2, 0) p1, p2, p3 = table.seats.players p3.add_action_history(Const.Action.RAISE, 10, 5) p1.add_action_history(Const.Action.FOLD) p2.add_action_history(Const.Action.RAISE, 20, 10) p3.add_action_history(Const.Action.CALL, 20) [ p.save_street_action_histories(Const.Street.PREFLOP) for p in [p1, p2, p3] ] p3.add_action_history(Const.Action.CALL, 5) p2.add_action_history(Const.Action.RAISE, 5, 5) return table
def setup_table(): table = Table() players = [Player("uuid%d"%i, 100, "hoge") for i in range(3)] table.seats.players = players table.add_community_card(Card.from_id(1)) table.dealer_btn = 2 table.set_blind_pos(2, 0) p1, p2, p3 = table.seats.players p3.add_action_history(Const.Action.RAISE, 10, 5) p1.add_action_history(Const.Action.FOLD) p2.add_action_history(Const.Action.RAISE, 20, 10) p3.add_action_history(Const.Action.CALL, 20) [p.save_street_action_histories(Const.Street.PREFLOP) for p in [p1, p2, p3]] p3.add_action_history(Const.Action.CALL, 5) p2.add_action_history(Const.Action.RAISE, 5, 5) return table
def __setup_table(self, players): table = Table() for player in players: table.seats.sitdown(player) return table
def __init__(self, small_blind_amount=None, initial_stack=None, ante=None): super().__init__(self, small_blind_amount=small_blind_amount, initial_stack=initial_stack, ante=ante) self.table = Table(cheat_deck=EmptyCheatDeck())
class TableTest(BaseUnitTest): def setUp(self): self.__setup_table() self.__setup_player() self.table.seats.sitdown(self.player) def test_set_blind(self): self.assertIsNone(self.table._blind_pos) self.table.set_blind_pos(1, 2) self.assertIsNotNone(self.table._blind_pos) self.eq(1, self.table.sb_pos()) self.eq(2, self.table.bb_pos()) def test_set_blind_error(self): with self.assertRaises(Exception) as e1: self.table.sb_pos() with self.assertRaises(Exception) as e2: self.table.bb_pos() for e in [e1, e2]: self.eq('blind position is not yet set', str(e.exception)) def test_reset_deck(self): self.table.reset() self.eq(52, self.table.deck.size()) def test_reset_commynity_card(self): self.table.reset() for card in self.table.deck.draw_cards(5): self.table.add_community_card(card) def test_reset_player_status(self): self.table.reset() self.eq(0, len(self.player.hole_card)) self.eq(0, len(self.player.action_histories)) self.eq(PayInfo.PLAY_TILL_END, self.player.pay_info.status) @raises(ValueError) def test_community_card_exceed_size(self): self.table.add_community_card(Card.from_id(1)) def test_shift_dealer_btn_skip(self): table = self.__setup_players_with_table() table.shift_dealer_btn() self.eq(2, table.dealer_btn) table.shift_dealer_btn() self.eq(0, table.dealer_btn) def test_next_ask_waiting_player_pos(self): table = self.__setup_players_with_table() self.eq(0, table.next_ask_waiting_player_pos(0)) self.eq(0, table.next_ask_waiting_player_pos(1)) self.eq(0, table.next_ask_waiting_player_pos(2)) def test_next_ask_waitint_player_pos_when_no_one_waiting(self): table = self.__setup_players_with_table() table.seats.players[0].pay_info.update_to_allin() self.eq(table._player_not_found, table.next_ask_waiting_player_pos(0)) self.eq(table._player_not_found, table.next_ask_waiting_player_pos(1)) self.eq(table._player_not_found, table.next_ask_waiting_player_pos(2)) def test_serialization(self): table = self.__setup_players_with_table() for card in table.deck.draw_cards(3): table.add_community_card(card) table.shift_dealer_btn() table.set_blind_pos(1, 2) serial = table.serialize() restored = Table.deserialize(serial) self.eq(table.dealer_btn, restored.dealer_btn) self.eq(Seats.serialize(table.seats), Seats.serialize(restored.seats)) self.eq(Deck.serialize(table.deck), Deck.serialize(restored.deck)) self.eq(table.get_community_card(), restored.get_community_card()) self.eq(1, restored.sb_pos()) self.eq(2, restored.bb_pos()) def __setup_table(self): self.table = Table() for card in self.table.deck.draw_cards(5): self.table.add_community_card(card) def __setup_player(self): self.player = Player('uuid', 100) self.player.add_holecard([Card.from_id(cid + 1) for cid in range(2)]) self.player.add_action_history(Const.Action.CALL, 10) self.player.pay_info.update_to_fold() def __setup_players_with_table(self): p1 = Player('uuid1', 100) p2 = Player('uuid2', 100) p3 = Player('uuid3', 100) p2.pay_info.update_to_fold() p3.pay_info.update_to_allin() table = Table() for player in [p1, p2, p3]: table.seats.sitdown(player) return table
def __setup_table(self): self.table = Table() for card in self.table.deck.draw_cards(5): self.table.add_community_card(card)
def __setup_table(self): table = Table() table.set_blind_pos(0, 1) table.seats = self.__setup_seats() table.add_community_card(Card.from_id(1)) return table
class Dealer: def __init__(self, small_blind_amount=None, initial_stack=None, ante=None): self.small_blind_amount = small_blind_amount self.ante = ante if ante else 0 self.initial_stack = initial_stack self.uuid_list = self.__generate_uuid_list() self.message_handler = MessageHandler() self.message_summarizer = MessageSummarizer(verbose=0) self.table = Table() self.blind_structure = {} def register_player(self, player_name, algorithm): self.__config_check() uuid = self.__escort_player_to_table(player_name) algorithm.set_uuid(uuid) self.__register_algorithm_to_message_handler(uuid, algorithm) def set_verbose(self, verbose): self.message_summarizer.verbose = verbose def start_game(self, max_round): table = self.table self.__notify_game_start(max_round) ante, sb_amount = self.ante, self.small_blind_amount for round_count in range(1, max_round + 1): ante, sb_amount = self.__update_forced_bet_amount( ante, sb_amount, round_count, self.blind_structure) table = self.__exclude_short_of_money_players( table, ante, sb_amount) if self.__is_game_finished(table): break table = self.play_round(round_count, sb_amount, ante, table) table.shift_dealer_btn() return self.__generate_game_result(max_round, table.seats) def set_table(self): return self.table.set_player() def play_round(self, round_count, blind_amount, ante, table): state, msgs = RoundManager.start_new_round(round_count, blind_amount, ante, table) while True: self.__message_check(msgs, state["street"]) if state["street"] != Const.Street.FINISHED: # continue the round action, bet_amount = self.__publish_messages(msgs) state, msgs = RoundManager.apply_action( state, action, bet_amount) else: # finish the round after publish round result self.__publish_messages(msgs) break return state["table"] def set_small_blind_amount(self, amount): self.small_blind_amount = amount def set_initial_stack(self, amount): self.initial_stack = amount def set_blind_structure(self, blind_structure): self.blind_structure = blind_structure def __update_forced_bet_amount(self, ante, sb_amount, round_count, blind_structure): if round_count in blind_structure: update_info = blind_structure[round_count] msg = self.message_summarizer.summairze_blind_level_update(\ round_count, ante, update_info["ante"], sb_amount, update_info["small_blind"]) self.message_summarizer.print_message(msg) ante, sb_amount = update_info["ante"], update_info["small_blind"] return ante, sb_amount def __register_algorithm_to_message_handler(self, uuid, algorithm): self.message_handler.register_algorithm(uuid, algorithm) def __escort_player_to_table(self, player_name): uuid = self.__fetch_uuid() player = Player(uuid, self.initial_stack, player_name) self.table.seats.sitdown(player) return uuid def __notify_game_start(self, max_round): config = self.__gen_config(max_round) start_msg = MessageBuilder.build_game_start_message( config, self.table.seats) self.message_handler.process_message(-1, start_msg) self.message_summarizer.summarize(start_msg) def __is_game_finished(self, table): return len([ player for player in table.seats.players if player.is_active() ]) == 1 def __message_check(self, msgs, street): address, msg = msgs[-1] invalid = msg["type"] != 'ask' invalid &= street != Const.Street.FINISHED or msg["message"][ "message_type"] == 'round_result' if invalid: raise Exception("Last message is not ask type. : %s" % msgs) def __publish_messages(self, msgs): for address, msg in msgs[:-1]: self.message_handler.process_message(address, msg) self.message_summarizer.summarize_messages(msgs) return self.message_handler.process_message(*msgs[-1]) def __exclude_short_of_money_players(self, table, ante, sb_amount): sb_pos, bb_pos = self.__steal_money_from_poor_player( table, ante, sb_amount) self.__disable_no_money_player(table.seats.players) table.set_blind_pos(sb_pos, bb_pos) if table.seats.players[table.dealer_btn].stack == 0: table.shift_dealer_btn() return table def __steal_money_from_poor_player(self, table, ante, sb_amount): players = table.seats.players # exclude player who cannot pay ante for player in [p for p in players if p.stack < ante]: player.stack = 0 if players[table.dealer_btn].stack == 0: table.shift_dealer_btn() search_targets = players + players + players search_targets = search_targets[table.dealer_btn + 1:table.dealer_btn + 1 + len(players)] # exclude player who cannot pay small blind sb_player = self.__find_first_elligible_player(search_targets, sb_amount + ante) sb_relative_pos = search_targets.index(sb_player) for player in search_targets[:sb_relative_pos]: player.stack = 0 # exclude player who cannot pay big blind search_targets = search_targets[sb_relative_pos + 1:sb_relative_pos + len(players)] bb_player = self.__find_first_elligible_player(search_targets, sb_amount * 2 + ante, sb_player) if sb_player == bb_player: # no one can pay big blind. So steal money from all players except small blind for player in [p for p in players if p != bb_player]: player.stack = 0 else: bb_relative_pos = search_targets.index(bb_player) for player in search_targets[:bb_relative_pos]: player.stack = 0 return players.index(sb_player), players.index(bb_player) def __find_first_elligible_player(self, players, need_amount, default=None): if default: return next( (player for player in players if player.stack >= need_amount), default) return next( (player for player in players if player.stack >= need_amount)) def __disable_no_money_player(self, players): no_money_players = [player for player in players if player.stack == 0] for player in no_money_players: player.pay_info.update_to_fold() def __generate_game_result(self, max_round, seats): config = self.__gen_config(max_round) result_message = MessageBuilder.build_game_result_message( config, seats) self.message_summarizer.summarize(result_message) return result_message def __gen_config(self, max_round): return { "initial_stack": self.initial_stack, "max_round": max_round, "small_blind_amount": self.small_blind_amount, "ante": self.ante, "blind_structure": self.blind_structure } def __config_check(self): if self.small_blind_amount is None: raise Exception("small_blind_amount is not set!!\ You need to call 'dealer.set_small_blind_amount' before.") if self.initial_stack is None: raise Exception("initial_stack is not set!!\ You need to call 'dealer.set_initial_stack' before.") def __fetch_uuid(self): return self.uuid_list.pop() def __generate_uuid_list(self): return [self.__generate_uuid() for _ in range(100)] def __generate_uuid(self): uuid_size = 22 chars = [chr(code) for code in range(97, 123)] return "".join([random.choice(chars) for _ in range(uuid_size)])