def start(self, channel): self.state = START_STATE self.timer = WAIT self.players = [] self.deck = Deck() self.current_player = 0 self.chat = Chat(self.slack_client, channel) self.pot_manager = PotManager(self.chat) self.join_manager = JoinManager(self.slack_client, channel, self.players) self.bet_manager = BetManager(self.pot_manager, self.players) self.board = [] self.last_message = None self.board_message = None
class Game: def __init__(self, slack_client): self.state = DEAD_STATE self.timer = WAIT self.players = [] self.deck = None self.current_player = 0 self.pot_manager = None self.slack_client = slack_client self.join_manager = None self.chat = None self.dealer_id = 0 self.bet_manager = None self.board = [] self.evaluator = Evaluator() self.last_message = None self.board_message = None def start(self, channel): self.state = START_STATE self.timer = WAIT self.players = [] self.deck = Deck() self.current_player = 0 self.chat = Chat(self.slack_client, channel) self.pot_manager = PotManager(self.chat) self.join_manager = JoinManager(self.slack_client, channel, self.players) self.bet_manager = BetManager(self.pot_manager, self.players) self.board = [] self.last_message = None self.board_message = None def process(self, data): if 'text' in data: text = data['text'] quit_text = '{}: quit'.format(bot_name) if quit_text.lower() in text.lower(): if PAUSE_BETWEEN_GAME_STATE == self.state: player_to_remove = None for player in self.players: if player.slack_id == data['user']: player_to_remove = player self.players.remove(player_to_remove) self.chat.message("{} has quit.".format(player_to_remove)) else: self.chat.message("You can't quit now, wait between games.") if DEAD_STATE == self.state: self.process_dead(data) if START_STATE == self.state: self.process_start(data) if BET_STATE == self.state: self.bet_manager.process(data) def process_dead(self, data): text = data['text'] deal_text = '{}: deal'.format(bot_name) if deal_text.lower() in text.lower(): self.start(data['channel']) def process_start(self, data): self.join_manager.process_message(data) def set_state(self, state): self.state = state self.timer = WAIT self.last_message = None self.board_message = None def enough_players(self): if len(self.players) < 2: self.chat.message("Not enough players.") self.set_state(DEAD_STATE) return False return True def deal_state(self): self.current_player = 0 if not self.enough_players(): return # burn card self.deck.draw(1) for player in self.players: player.deal(self.deck.draw(2)) self.set_state(BLIND_STATE) def post_blind(self, blind_func): while True: player = self.players[self.current_player % len(self.players)] can_post = blind_func(player) if not can_post: self.players.pop(0) if not self.enough_players(): return False self.current_player += 1 return True def blind_state(self): if not self.post_blind(self.pot_manager.post_small_blind): return if not self.post_blind(self.pot_manager.post_big_blind): return self.pot_manager.add_other_players(self.players) self.dealer_id = self.current_player self.display_board() flop_callback = partial(self.set_state, FLOP_STATE) fold_win_callback = partial(self.set_state, FOLD_WIN_STATE) self.bet_manager.request_bets(self.dealer_id, flop_callback, fold_win_callback, self.display_board) self.set_state(BET_STATE) def display_board(self): board_str = '```' for i, player in enumerate(self.players): if i == self.current_player % len(self.players): board_str += '->' else: board_str += ' ' board_str += '<@{}>\t\t\t${}\t{}\t{} {}\n'.format(player.slack_id, player.money, player.state, player.action, player.bet) board_str += '```\n' board_str += self.pot_manager.get_pot_string() board_str += "\n{}".format(Game.board_to_string(self.board)) self.board_message = self.chat.message(board_str, self.board_message) @staticmethod def board_to_string(board): result = "" for card in board: result += "{} ".format(Card.int_to_pretty_str(card)) return result def flop_state(self): # burn card self.deck.draw(1) self.board.extend(self.deck.draw(3)) self.chat.message("*Dealing the flop:*\n{}".format(Game.board_to_string(self.board))) turn_callback = partial(self.set_state, TURN_STATE) fold_win_callback = partial(self.set_state, FOLD_WIN_STATE) self.bet_manager.request_bets(0, turn_callback, fold_win_callback, self.display_board) self.set_state(BET_STATE) def turn_state(self): # burn card self.deck.draw(1) self.board.append(self.deck.draw(1)) self.chat.message("*Dealing the turn:*\n{}".format(Game.board_to_string(self.board))) turn_callback = partial(self.set_state, RIVER_STATE) fold_win_callback = partial(self.set_state, FOLD_WIN_STATE) self.bet_manager.request_bets(0, turn_callback, fold_win_callback, self.display_board) self.set_state(BET_STATE) def river_state(self): # burn card self.deck.draw(1) self.board.append(self.deck.draw(1)) self.chat.message("*Dealing the river:*\n{}".format(Game.board_to_string(self.board))) self.set_state(SHOW_HANDS_STATE) def count_down(self, new_state): self.timer -= 1 if self.timer < 0: self.set_state(new_state) return def show_hands_state(self): for player in self.players: if player.state == Player.FOLD_STATE: continue card_score = self.evaluator.evaluate(self.board, player.cards) card_class = self.evaluator.get_rank_class(card_score) self.chat.message('{} had: {} {}'.format(player, player.card_str(), card_class)) self.set_state(DETERMINE_WINNER_STATE) def determine_winner_state(self): for pot in reversed(self.pot_manager.pots): pot_score = 9999 pot_winners = [] if len(pot.players) == 1: self.chat.message(SINGLE_WINNER_MESSAGE.format(pot.players[0], pot.amount, pot.name)) pot.players[0].money += pot.amount else: for player in pot.players: card_score = self.evaluator.evaluate(self.board, player.cards) if card_score == pot_score: pot_winners.append(player) if card_score < pot_score: pot_winners = [player] pot_score = card_score if len(pot_winners) == 1: self.chat.message(SINGLE_WINNER_MESSAGE.format(pot_winners[0], pot.amount, pot.name)) pot_winners[0].money += pot.amount else: self.chat.message(SPLIT_WINNER_MESSAGE.format(pot_winners, pot.amount, pot.name)) for pot_winner in pot_winners: pot_winner.money += (pot.amount / len(pot_winners)) self.set_state(PREPARE_NEW_GAME_STATE) def prepare_new_game_state(self): # rotate players self.players.append(self.players.pop(0)) self.set_state(PAUSE_BETWEEN_GAME_STATE) def pause_between_game_state(self): self.last_message = self.chat.message(PAUSE_MESSAGE.format(self.timer), self.last_message) self.timer = NEW_GAME_WAIT self.count_down(DEAL_STATE) def tick(self): if START_STATE == self.state: self.join_manager.tick(self.timer) self.count_down(DEAL_STATE) if DEAL_STATE == self.state: self.deal_state() if BLIND_STATE == self.state: self.blind_state() if BET_STATE == self.state: self.bet_manager.tick() if FLOP_STATE == self.state: self.flop_state() if TURN_STATE == self.state: self.turn_state() if RIVER_STATE == self.state: self.river_state() if FOLD_WIN_STATE == self.state: self.set_state(DETERMINE_WINNER_STATE) if SHOW_HANDS_STATE == self.state: self.show_hands_state() if DETERMINE_WINNER_STATE == self.state: self.determine_winner_state() if PREPARE_NEW_GAME_STATE == self.state: self.prepare_new_game_state() if PAUSE_BETWEEN_GAME_STATE == self.state: self.pause_between_game_state()
class Game: def __init__(self, slack_client): self.state = DEAD_STATE self.timer = WAIT self.players = [] self.deck = None self.current_player = 0 self.pot_manager = None self.slack_client = slack_client self.join_manager = None self.chat = None self.dealer_id = 0 self.bet_manager = None self.board = [] self.evaluator = Evaluator() self.last_message = None self.board_message = None def start(self, channel): self.state = START_STATE self.timer = WAIT self.players = [] self.deck = Deck() self.current_player = 0 self.chat = Chat(self.slack_client, channel) self.pot_manager = PotManager(self.chat) self.join_manager = JoinManager(self.slack_client, channel, self.players) self.bet_manager = BetManager(self.pot_manager, self.players) self.board = [] self.last_message = None self.board_message = None def process(self, data): if 'text' in data: text = data['text'] quit_text = '{}: quit'.format(bot_name) if quit_text.lower() in text.lower(): if PAUSE_BETWEEN_GAME_STATE == self.state: player_to_remove = None for player in self.players: if player.slack_id == data['user']: player_to_remove = player self.players.remove(player_to_remove) self.chat.message("{} has quit.".format(player_to_remove)) else: self.chat.message( "You can't quit now, wait between games.") if DEAD_STATE == self.state: self.process_dead(data) if START_STATE == self.state: self.process_start(data) if BET_STATE == self.state: self.bet_manager.process(data) def process_dead(self, data): text = data['text'] deal_text = '{}: deal'.format(bot_name) if deal_text.lower() in text.lower(): self.start(data['channel']) def process_start(self, data): self.join_manager.process_message(data) def set_state(self, state): self.state = state self.timer = WAIT self.last_message = None self.board_message = None def enough_players(self): if len(self.players) < 2: self.chat.message("Not enough players.") self.set_state(DEAD_STATE) return False return True def deal_state(self): self.current_player = 0 if not self.enough_players(): return # burn card self.deck.draw(1) for player in self.players: player.deal(self.deck.draw(2)) self.set_state(BLIND_STATE) def post_blind(self, blind_func): while True: player = self.players[self.current_player % len(self.players)] can_post = blind_func(player) if not can_post: self.players.pop(0) if not self.enough_players(): return False self.current_player += 1 return True def blind_state(self): if not self.post_blind(self.pot_manager.post_small_blind): return if not self.post_blind(self.pot_manager.post_big_blind): return self.pot_manager.add_other_players(self.players) self.dealer_id = self.current_player self.display_board() flop_callback = partial(self.set_state, FLOP_STATE) fold_win_callback = partial(self.set_state, FOLD_WIN_STATE) self.bet_manager.request_bets(self.dealer_id, flop_callback, fold_win_callback, self.display_board) self.set_state(BET_STATE) def display_board(self): board_str = '```' for i, player in enumerate(self.players): if i == self.current_player % len(self.players): board_str += '->' else: board_str += ' ' board_str += '<@{}>\t\t\t${}\t{}\t{} {}\n'.format( player.slack_id, player.money, player.state, player.action, player.bet) board_str += '```\n' board_str += self.pot_manager.get_pot_string() board_str += "\n{}".format(Game.board_to_string(self.board)) self.board_message = self.chat.message(board_str, self.board_message) @staticmethod def board_to_string(board): result = "" for card in board: result += "{} ".format(Card.int_to_pretty_str(card)) return result def flop_state(self): # burn card self.deck.draw(1) self.board.extend(self.deck.draw(3)) self.chat.message("*Dealing the flop:*\n{}".format( Game.board_to_string(self.board))) turn_callback = partial(self.set_state, TURN_STATE) fold_win_callback = partial(self.set_state, FOLD_WIN_STATE) self.bet_manager.request_bets(0, turn_callback, fold_win_callback, self.display_board) self.set_state(BET_STATE) def turn_state(self): # burn card self.deck.draw(1) self.board.append(self.deck.draw(1)) self.chat.message("*Dealing the turn:*\n{}".format( Game.board_to_string(self.board))) turn_callback = partial(self.set_state, RIVER_STATE) fold_win_callback = partial(self.set_state, FOLD_WIN_STATE) self.bet_manager.request_bets(0, turn_callback, fold_win_callback, self.display_board) self.set_state(BET_STATE) def river_state(self): # burn card self.deck.draw(1) self.board.append(self.deck.draw(1)) self.chat.message("*Dealing the river:*\n{}".format( Game.board_to_string(self.board))) self.set_state(SHOW_HANDS_STATE) def count_down(self, new_state): self.timer -= 1 if self.timer < 0: self.set_state(new_state) return def show_hands_state(self): for player in self.players: if player.state == Player.FOLD_STATE: continue card_score = self.evaluator.evaluate(self.board, player.cards) card_class = self.evaluator.get_rank_class(card_score) self.chat.message('{} had: {} {}'.format(player, player.card_str(), card_class)) self.set_state(DETERMINE_WINNER_STATE) def determine_winner_state(self): for pot in reversed(self.pot_manager.pots): pot_score = 9999 pot_winners = [] if len(pot.players) == 1: self.chat.message( SINGLE_WINNER_MESSAGE.format(pot.players[0], pot.amount, pot.name)) pot.players[0].money += pot.amount else: for player in pot.players: card_score = self.evaluator.evaluate( self.board, player.cards) if card_score == pot_score: pot_winners.append(player) if card_score < pot_score: pot_winners = [player] pot_score = card_score if len(pot_winners) == 1: self.chat.message( SINGLE_WINNER_MESSAGE.format(pot_winners[0], pot.amount, pot.name)) pot_winners[0].money += pot.amount else: self.chat.message( SPLIT_WINNER_MESSAGE.format(pot_winners, pot.amount, pot.name)) for pot_winner in pot_winners: pot_winner.money += (pot.amount / len(pot_winners)) self.set_state(PREPARE_NEW_GAME_STATE) def prepare_new_game_state(self): # rotate players self.players.append(self.players.pop(0)) self.set_state(PAUSE_BETWEEN_GAME_STATE) def pause_between_game_state(self): self.last_message = self.chat.message(PAUSE_MESSAGE.format(self.timer), self.last_message) self.timer = NEW_GAME_WAIT self.count_down(DEAL_STATE) def tick(self): if START_STATE == self.state: self.join_manager.tick(self.timer) self.count_down(DEAL_STATE) if DEAL_STATE == self.state: self.deal_state() if BLIND_STATE == self.state: self.blind_state() if BET_STATE == self.state: self.bet_manager.tick() if FLOP_STATE == self.state: self.flop_state() if TURN_STATE == self.state: self.turn_state() if RIVER_STATE == self.state: self.river_state() if FOLD_WIN_STATE == self.state: self.set_state(DETERMINE_WINNER_STATE) if SHOW_HANDS_STATE == self.state: self.show_hands_state() if DETERMINE_WINNER_STATE == self.state: self.determine_winner_state() if PREPARE_NEW_GAME_STATE == self.state: self.prepare_new_game_state() if PAUSE_BETWEEN_GAME_STATE == self.state: self.pause_between_game_state()