def __init__(self, seats=8, quiet=False, training=False): self._blind_index = 0 [self._smallblind, self._bigblind] = Table.BLIND_INCREMENTS[0] self._deck = Deck() self._evaluator = Evaluator() self.community = [] self._round = 0 self._button = 0 self._discard = [] self._side_pots = [0] * seats self._current_sidepot = 0 # index of _side_pots self._totalpot = 0 self._tocall = 0 self._lastraise = 0 self._number_of_hands = 0 # fill seats with dummy players self._seats = [Player(0, 'empty', 0, None, True) for _ in range(seats)] self.emptyseats = seats self._player_dict = {} self._quiet = quiet self._training = training
def __init__(self, seats=8, quiet=False, training=False): self._blind_index = 0 [self._smallblind, self._bigblind] = Table.BLIND_INCREMENTS[0] self._deck = Deck() self._evaluator = Evaluator() self.community = [] self._round = 0 self._button = 0 self._discard = [] self._side_pots = [0] * seats self._current_sidepot = 0 # index of _side_pots self._totalpot = 0 self._tocall = 0 self._lastraise = 0 self._number_of_hands = 0 # fill seats with dummy players self._seats = [ Player(-1, -1, 0, 'empty', 0, True) for _ in range(seats) ] self.emptyseats = seats self._player_dict = {} self.teacher = xmlrpc.client.ServerProxy('http://0.0.0.0:8080') self._quiet = quiet self._training = training self._run_thread = Thread(target=self.run, args=()) self._run_thread.daemon = True
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 __init__(self, seats = 8, quiet = False, training = False): self._blind_index = 0 [self._smallblind, self._bigblind] = Table.BLIND_INCREMENTS[0] self._deck = Deck() self._evaluator = Evaluator() self.community = [] self._round = 0 self._button = 0 self._discard = [] self._side_pots = [0]*seats self._current_sidepot = 0 # index of _side_pots self._totalpot = 0 self._tocall = 0 self._lastraise = 0 self._number_of_hands = 0 # fill seats with dummy players self._seats = [Player(-1,-1,0,'empty',0,True) for _ in range(seats)] self.emptyseats = seats self._player_dict = {} self.teacher = xmlrpc.client.ServerProxy('http://0.0.0.0:8080') self._quiet = quiet self._training = training self._run_thread = Thread(target = self.run, args=()) self._run_thread.daemon = True
def numbers_of_hole_cards_random(n): """Return a dict counting combos in each hand, but built by drawing 2 at random (not normalizing to n). """ Table = {} for i in range(n): d = Deck() hole = d.draw(2) s = reduce_h(hole) if s[2] == 'o': s = s[0:2] if s in Table.keys(): Table[s] += 1 else: Table[s] = 1 return Table
def test_predrawn(self): d1 = Deck(seed=0.1) d2 = Deck(seed=0.1, num_drawn=2) self.assertEquals(0, d1.num_drawn) self.assertEquals(2, d2.num_drawn) d1.draw() d1.draw() self.assertEquals(2, d1.num_drawn) self.assertEquals(d1.draw(), d2.draw())
def test_shuffle(self): d1 = Deck(seed=0.1) d2 = Deck(seed=0.1) self.assertEquals(d1.draw(), d2.draw()) self.assertEquals(1, d1.num_drawn) self.assertEquals(1, d2.num_drawn)
def test_multi_draw(self): d1 = Deck(seed=0.1) d2 = Deck(seed=0.1) self.assertEquals(d1.draw(3), d2.draw(3)) self.assertEquals(3, d1.num_drawn) self.assertEquals(3, d2.num_drawn)
def __init__(self): self.deck = Deck() self.reset() self._evaluator = Evaluator() self.monte_carlo_rounds = 1000
class Analyzer: def __init__(self): self.deck = Deck() self.reset() self._evaluator = Evaluator() self.monte_carlo_rounds = 1000 def reset(self): self.deck.shuffle() self.hole_cards = [] self.community_cards = [] def set_num_opponents(self, n): self.num_opponents = n def set_monte_carlo_rounds(self, n): self.monte_carlo_rounds = n def set_pocket_cards(self, card1, card2): self.deck.remove(card1) self.deck.remove(card2) self.hole_cards.append(card1) self.hole_cards.append(card2) def community_card(self, card): self.deck.remove(card) self.community_cards.append(card) def analyze(self): wins = 0 ties = 0 to_flop = 5 - len(self.community_cards) to_draw = to_flop + 2 * self.num_opponents total_rounds = self.monte_carlo_rounds total_opponent_hands = total_rounds * self.num_opponents # Monte Carlo simulation for _ in range(self.monte_carlo_rounds): # Draw a uniformly random combination of unseen cards (remaining # community cards + 2 hole cards per opponent) drawn_cards = self.deck.sample(to_draw) all_comms = self.community_cards + drawn_cards[:to_flop] my_ranking = self._evaluator.evaluate(self.hole_cards, all_comms) # 2: win, 1: tie, 0: loss winner = 2 for i in range(self.num_opponents): their_cards = drawn_cards[to_flop + 2 * i:to_flop + 2 * i + 2] their_ranking = self._evaluator.evaluate( their_cards, all_comms) if my_ranking > their_ranking: winner = 0 elif my_ranking == their_ranking: winner = min(winner, 1) if winner == 2: wins += 1 elif winner == 1: ties += 1 win_ratio = wins / total_rounds return win_ratio
import numpy as np import random from holdem import Analyzer, NeuralNetwork, HoldemAI from deuces.deuces import Card, Deck, Evaluator if __name__ = '__main__': a = Analyzer() a.monte_carlo_rounds = 2000 nn = NeuralNetwork([206,206,100,1], 'analyzer_network', 0.1) deck = Deck() hand = [] community = [] opponents = 0 game_stage = [0,3,4,5] for i in range(1000000): community = [] deck.shuffle() a.reset() hand = deck.draw(2) for _ in range(game_stage[random.randint(0,3)]): community.append(deck.draw(1)) opponents = random.randint(1,7) a.set_num_opponents(opponents) a.set_pocket_cards(*hand) for card in community:
class Table(object): BLIND_INCREMENTS = [[10,25],[25,50],[50,100],[75,150],[100,200],[150,300],[200,400],[300,600],[400,800],[500,10000],[600,1200],[800,1600],[1000,2000]] def __init__(self, seats = 8, quiet = False, training = False): self._blind_index = 0 [self._smallblind, self._bigblind] = Table.BLIND_INCREMENTS[0] self._deck = Deck() self._evaluator = Evaluator() self.community = [] self._round = 0 self._button = 0 self._discard = [] self._side_pots = [0]*seats self._current_sidepot = 0 # index of _side_pots self._totalpot = 0 self._tocall = 0 self._lastraise = 0 self._number_of_hands = 0 # fill seats with dummy players self._seats = [Player(-1,-1,0,'empty',0,True) for _ in range(seats)] self.emptyseats = seats self._player_dict = {} self.teacher = xmlrpc.client.ServerProxy('http://0.0.0.0:8080') self._quiet = quiet self._training = training self._run_thread = Thread(target = self.run, args=()) self._run_thread.daemon = True def start(self): self._run_thread.start() def run(self): while True: self.run_game() def run_game(self): self.ready_players() # for p in self._seats: # print('Player ',p.playerID, ' playing hand: ', p.playing_hand, 'sitting out', p.sitting_out) players = [player for player in self._seats if not player.emptyplayer and not player.sitting_out] self._number_of_hands = 1 # start hand if table full # if len(players) == len(self._seats): [self._smallblind, self._bigblind] = Table.BLIND_INCREMENTS[0] # keep playing until there's a single player (shotgun style) while(self.emptyseats < len(self._seats)-1): # answer = input('Press [enter] to start a game:') # if not answer: self.start_hand(players) self._number_of_hands += 1 if not self._quiet: print('Starting game number: ', self._number_of_hands) for p in self._seats: if p.playing_hand: print('Player ',p.playerID, ' stack size: ', p.stack) # increment blinds every 15 hands (based on avg hands/hour of 30) if (self._number_of_hands % 15) == 0 and self._number_of_hands < 60: self.increment_blinds() if len([p for p in players if p.playing_hand]) == 1: winner = [p for p in players if p.playing_hand][0] if self._training: self.teacher.add_winner(winner.server.get_ai_id()) break if self._number_of_hands == 200: print('no winner in 200 hands') break def start_hand(self, players): players = [p for p in players if p.playing_hand] assert sum([p.stack for p in players]) == 2000*len(self._seats) self.new_round() self._round=0 player = self._first_to_act(players) self.post_smallblind(player) player = self._next(players, player) self.post_bigblind(player) player = self._next(players, player) self._tocall = self._bigblind # rounds self._round = 0 while self._round<4 and len(players)>1: if self._round == 0: self.deal() elif self._round == 1: self.flop() elif self._round == 2: self.turn() elif self._round ==3: self.river() folded_players = [] while not player.playedthisround and len([p for p in players if not p.isallin]) >=1: if player.isallin: # print('player ', player.playerID, 'is all in, skipping their turn') player = self._next(players, player) continue # print('requesting move from ',player.playerID) move = player.server.player_move(self.output_state(player)) if move[0] == 'call': self.player_bet(player, self._tocall) if not self._quiet: print('Player', player.playerID, move) player = self._next(players, player) elif move[0] == 'check': self.player_bet(player, player.currentbet) if not self._quiet: print('Player', player.playerID, move) player = self._next(players, player) elif move[0] == 'raise': self.player_bet(player, move[1]+player.currentbet) if not self._quiet: print('Player', player.playerID, move) for p in players: if p != player: p.playedthisround = False player = self._next(players, player) elif move[0] == 'fold': player.playing_hand = False folded_player = player if not self._quiet: print('Player', player.playerID, move) player = self._next(players, player) players.remove(folded_player) folded_players.append(folded_player) # break if a single player left if len(players) ==1: break player = self._first_to_act(players) self.resolve_sidepots(players + folded_players) self.new_round() if not self._quiet: print('totalpot', self._totalpot) assert sum([p.stack for p in self._seats]) + self._totalpot == 2000*len(self._seats) self.resolve_game(players) self.reset() def increment_blinds(self): self._blind_index = min(self._blind_index+1,len(Table.BLIND_INCREMENTS)-1) [self._smallblind, self._bigblind] = Table.BLIND_INCREMENTS[self._blind_index] def post_smallblind(self, player): if not self._quiet: print('player ', player.playerID, 'small blind', self._smallblind) self.player_bet(player, self._smallblind) player.playedthisround = False def post_bigblind(self, player): if not self._quiet: print('player ', player.playerID, 'big blind', self._bigblind) self.player_bet(player, self._bigblind) player.playedthisround = False self._lastraise = self._bigblind def player_bet(self, player, total_bet): # relative_bet is how much _additional_ money is the player betting this turn, on top of what they have already contributed # total_bet is the total contribution by player to pot in this round relative_bet = min(player.stack, total_bet - player.currentbet) player.bet(relative_bet + player.currentbet) self._totalpot += relative_bet self._tocall = max(self._tocall, total_bet) if self._tocall >0: self._tocall = max(self._tocall, self._bigblind) self._lastraise = max(self._lastraise, relative_bet - self._lastraise) def _first_to_act(self, players): if self._round == 0 and len(players) == 2: return self._next(sorted(players + [self._seats[self._button]], key=lambda x:x.get_seat()), self._seats[self._button]) try: first = [player for player in players if player.get_seat() > self._button][0] except IndexError: first = players[0] return first def _next(self, players, current_player): idx = players.index(current_player) return players[(idx+1) % len(players)] def deal(self): for player in self._seats: if player.playing_hand: player.hand = self._deck.draw(2) def flop(self): self._discard.append(self._deck.draw(1)) #burn self.community = self._deck.draw(3) def turn(self): self._discard.append(self._deck.draw(1)) #burn self.community.append(self._deck.draw(1)) def river(self): self._discard.append(self._deck.draw(1)) #burn self.community.append(self._deck.draw(1)) def add_player(self, host, port, playerID, name, stack): if playerID not in self._player_dict: new_player = Player(host, port, playerID, name, stack) for i,player in enumerate(self._seats): if player.emptyplayer: self._seats[i] = new_player new_player.set_seat(i) break self._player_dict[playerID] = new_player self.emptyseats -= 1 def ready_players(self): if len([p for p in self._seats if not p.emptyplayer and p.sitting_out]) == len(self._seats): for p in self._seats: if not p.emptyplayer: p.sitting_out = False p.playing_hand = True def remove_player(self, playerID): try: idx = self._seats.index(self._player_dict[playerID]) self._seats[idx] = Player(-1,-1,0,'empty',0,True) del self._player_dict[playerID] self.emptyseats += 1 except ValueError: pass def resolve_sidepots(self, players_playing): players = [p for p in players_playing if p.currentbet] if not self._quiet: print('current bets: ', [p.currentbet for p in players]) print('playing hand: ', [p.playing_hand for p in players]) if not players: return try: smallest_bet = min([p.currentbet for p in players if p.playing_hand]) except ValueError: for p in players: self._side_pots[self._current_sidepot] += p.currentbet p.currentbet = 0 return smallest_players_allin = [p for p,bet in zip(players, [p.currentbet for p in players]) if bet == smallest_bet and p.isallin] for p in players: self._side_pots[self._current_sidepot] += min(smallest_bet, p.currentbet) p.currentbet -= min(smallest_bet, p.currentbet) p.lastsidepot = self._current_sidepot if smallest_players_allin: self._current_sidepot += 1 self.resolve_sidepots(players) if not self._quiet: print('sidepots: ', self._side_pots) def new_round(self): for player in self._player_dict.values(): player.currentbet = 0 player.playedthisround = False self._round += 1 self._tocall = 0 self._lastraise = 0 def resolve_game(self, players): # print('Community cards: ', end='') # Card.print_pretty_cards(self.community) if len(players)==1: players[0].refund(sum(self._side_pots)) # print('Player', players[0].playerID, 'wins the pot (',sum(self._side_pots),')') self._totalpot = 0 else: # compute hand ranks for player in players: player.handrank = self._evaluator.evaluate(player.hand, self.community) # trim side_pots to only include the non-empty side pots temp_pots = [pot for pot in self._side_pots if pot>0] # compute who wins each side pot and pay winners for pot_idx,_ in enumerate(temp_pots): # print('players last pots', [(p.playerID, p.lastsidepot) for p in players]) # find players involved in given side_pot, compute the winner(s) pot_contributors = [p for p in players if p.lastsidepot >= pot_idx] winning_rank = min([p.handrank for p in pot_contributors]) winning_players = [p for p in pot_contributors if p.handrank == winning_rank] for player in winning_players: split_amount = int(self._side_pots[pot_idx]/len(winning_players)) if not self._quiet: print('Player', player.playerID, 'wins side pot (',int(self._side_pots[pot_idx]/len(winning_players)),')') player.refund(split_amount) self._side_pots[pot_idx] -= split_amount # any remaining chips after splitting go to the winner in the earliest position if self._side_pots[pot_idx]: earliest = self._first_to_act([player for player in winning_players]) earliest.refund(self._side_pots[pot_idx]) def reset(self): for player in self._seats: if not player.emptyplayer and not player.sitting_out: player.reset_hand() self.community = [] self._current_sidepot = 0 self._totalpot = 0 self._side_pots = [0]*len(self._seats) self._deck.shuffle() self._button = (self._button + 1) % len(self._seats) while not self._seats[self._button].playing_hand: self._button = (self._button + 1) % len(self._seats) def output_state(self, current_player): return {'players':[player.player_state() for player in self._seats], 'community':self.community, 'my_seat':current_player.get_seat(), 'pocket_cards':current_player.hand, 'pot':self._totalpot, 'button':self._button, 'tocall':(self._tocall-current_player.currentbet), 'stack':current_player.stack, 'bigblind':self._bigblind, 'playerID':current_player.playerID, 'lastraise':self._lastraise, 'minraise':max(self._bigblind, self._lastraise + self._tocall)}
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()
def r2t(x): return evaluator.class_to_string(evaluator.get_rank_class(x)) def r2c(x): return evaluator.get_rank_class(x) def list_to_pretty_str(card_ints): output = " " for i in range(len(card_ints)): c = card_ints[i] if i != len(card_ints) - 1: output += Card.int_to_pretty_str(c) + "," else: output += Card.int_to_pretty_str(c) + " " return output print "nut_hand,flop_leader,num_players" for num_players in range(2,7): for i in range(5000): deck = Deck() flop = deck.draw(3) rank_clasess= [] for p in range(num_players): player = deck.draw(4) realrank = omaha_eval(player, flop) rank_clasess.append(r2c(realrank)) winner = min(rank_clasess) print nut_hand(flop) + "," + str(winner) + ' ' + evaluator.class_to_string(winner) + "," + str(num_players)
from deuces.deuces import Card, Deck from pokermodules.nuts import nut_hand ### How does the nut hand evolve over several streets? print "flop,turn,river" for i in range(10000): deck = Deck() flop = deck.draw(3) turn = [deck.draw(1)] river = [deck.draw(1)] def f(x): return nut_hand(x).replace('.', '') progression = map(f, [flop, flop + turn, flop + turn + river]) print ','.join(progression)
from deuces.deuces import Evaluator, Deck, Card from pokermodules.convenience import pr, draw_sure from itertools import combinations from sys import argv if '--test' in argv: pause = False else: pause = True e = Evaluator() deck = Deck() hole = deck.draw(2) pr(hole) def card_pairs_board(c, b): card_rank = Card.get_rank_int(c) board_ranks = map(Card.get_rank_int, b) return card_rank in board_ranks def deck_without(cards): returnme = [] for c in Deck.GetFullDeck(): if c not in cards: returnme.append(c) return returnme flop = deck.draw(3) pr(flop) h_rc_flop = e.get_rank_class(e.evaluate(hole, flop))
class Table(object): #BLIND_INCREMENTS = [[10,25],[25,50],[50,100],[75,150],[100,200],[150,300],[200,400],[300,600],[400,800],[500,10000],[600,1200],[800,1600],[1000,2000]] BLIND_INCREMENTS = [[3, 6], [25, 50], [50, 100], [75, 150], [100, 200], [150, 300], [200, 400], [300, 600], [400, 800], [500, 10000], [600, 1200], [800, 1600], [1000, 2000]] def __init__(self, seats=8, quiet=False, training=False): self._blind_index = 0 [self._smallblind, self._bigblind] = Table.BLIND_INCREMENTS[0] self._deck = Deck() self._evaluator = Evaluator() self.community = [] self._round = 0 self._button = 0 self._discard = [] self._side_pots = [0] * seats self._current_sidepot = 0 # index of _side_pots self._totalpot = 0 self._tocall = 0 self._lastraise = 0 self._number_of_hands = 0 # fill seats with dummy players self._seats = [ Player(-1, -1, 0, 'empty', 0, True) for _ in range(seats) ] self.emptyseats = seats self._player_dict = {} self.teacher = xmlrpc.client.ServerProxy('http://0.0.0.0:8080') self._quiet = quiet self._training = training self._run_thread = Thread(target=self.run, args=()) self._run_thread.daemon = True def start(self): self._run_thread.start() def run(self): while True: self.run_game() def run_game(self): self.ready_players() # for p in self._seats: # print('Player ',p.playerID, ' playing hand: ', p.playing_hand, 'sitting out', p.sitting_out) players = [ player for player in self._seats if not player.emptyplayer and not player.sitting_out ] self._number_of_hands = 1 # start hand if table full # if len(players) == len(self._seats): [self._smallblind, self._bigblind] = Table.BLIND_INCREMENTS[0] # keep playing until there's a single player (shotgun style) while (self.emptyseats < len(self._seats) - 1): # answer = input('Press [enter] to start a game:') # if not answer: self.start_hand(players) self._number_of_hands += 1 if not self._quiet: print('Starting game number: ', self._number_of_hands) for p in self._seats: if p.playing_hand: print('Player ', p.playerID, ' stack size: ', p.stack) # increment blinds every 15 hands (based on avg hands/hour of 30) # if (self._number_of_hands % 15) == 0 and self._number_of_hands < 60: # self.increment_blinds() if len([p for p in players if p.playing_hand]) == 1: winner = [p for p in players if p.playing_hand][0] if self._training: self.teacher.add_winner(winner.server.get_ai_id()) break if self._number_of_hands == 200: print('no winner in 200 hands') break def start_hand(self, players): players = [p for p in players if p.playing_hand] assert sum([p.stack for p in players]) == 2000 * len(self._seats) self.new_round() self._round = 0 player = self._first_to_act(players) self.post_smallblind(player) player = self._next(players, player) self.post_bigblind(player) player = self._next(players, player) self._tocall = self._bigblind # rounds self._round = 0 while self._round < 4 and len(players) > 1: if self._round == 0: self.deal() elif self._round == 1: self.flop() elif self._round == 2: self.turn() elif self._round == 3: self.river() folded_players = [] while not player.playedthisround and len( [p for p in players if not p.isallin]) >= 1: if player.isallin: # print('player ', player.playerID, 'is all in, skipping their turn') player = self._next(players, player) continue # print('requesting move from ',player.playerID) move = player.server.player_move( self.output_state(player)) # MAKE PLAYER MOVE! if move[0] == 'call': self.player_bet(player, self._tocall) if not self._quiet: print('Player', player.playerID, move) player = self._next(players, player) elif move[0] == 'check': self.player_bet(player, player.currentbet) if not self._quiet: print('Player', player.playerID, move) player = self._next(players, player) elif move[0] == 'raise': self.player_bet(player, move[1] + player.currentbet) if not self._quiet: print('Player', player.playerID, move) for p in players: if p != player: p.playedthisround = False player = self._next(players, player) elif move[0] == 'fold': player.playing_hand = False folded_player = player if not self._quiet: print('Player', player.playerID, move) player = self._next(players, player) players.remove(folded_player) folded_players.append(folded_player) # break if a single player left if len(players) == 1: break player = self._first_to_act(players) self.resolve_sidepots(players + folded_players) self.new_round() if not self._quiet: print('totalpot', self._totalpot) assert sum([p.stack for p in self._seats ]) + self._totalpot == 2000 * len(self._seats) self.resolve_game(players) self.reset() def increment_blinds(self): self._blind_index = min(self._blind_index + 1, len(Table.BLIND_INCREMENTS) - 1) [self._smallblind, self._bigblind] = Table.BLIND_INCREMENTS[self._blind_index] def post_smallblind(self, player): if not self._quiet: print('player ', player.playerID, 'small blind', self._smallblind) self.player_bet(player, self._smallblind) player.playedthisround = False def post_bigblind(self, player): if not self._quiet: print('player ', player.playerID, 'big blind', self._bigblind) self.player_bet(player, self._bigblind) player.playedthisround = False self._lastraise = self._bigblind def player_bet(self, player, total_bet): # relative_bet is how much _additional_ money is the player betting this turn, on top of what they have already contributed # total_bet is the total contribution by player to pot in this round relative_bet = min(player.stack, total_bet - player.currentbet) player.bet(relative_bet + player.currentbet) self._totalpot += relative_bet self._tocall = max(self._tocall, total_bet) if self._tocall > 0: self._tocall = max(self._tocall, self._bigblind) self._lastraise = max(self._lastraise, relative_bet - self._lastraise) def _first_to_act(self, players): if self._round == 0 and len(players) == 2: return self._next( sorted(players + [self._seats[self._button]], key=lambda x: x.get_seat()), self._seats[self._button]) try: first = [ player for player in players if player.get_seat() > self._button ][0] except IndexError: first = players[0] return first def _next(self, players, current_player): idx = players.index(current_player) return players[(idx + 1) % len(players)] def deal(self): for player in self._seats: if player.playing_hand: player.hand = self._deck.draw(2) def flop(self): self._discard.append(self._deck.draw(1)) #burn self.community = self._deck.draw(3) def turn(self): self._discard.append(self._deck.draw(1)) #burn self.community.append(self._deck.draw(1)) def river(self): self._discard.append(self._deck.draw(1)) #burn self.community.append(self._deck.draw(1)) def add_player(self, host, port, playerID, name, stack): if playerID not in self._player_dict: new_player = Player(host, port, playerID, name, stack) for i, player in enumerate(self._seats): if player.emptyplayer: self._seats[i] = new_player new_player.set_seat(i) break self._player_dict[playerID] = new_player self.emptyseats -= 1 def ready_players(self): if len([p for p in self._seats if not p.emptyplayer and p.sitting_out]) == len(self._seats): for p in self._seats: if not p.emptyplayer: p.sitting_out = False p.playing_hand = True def remove_player(self, playerID): try: idx = self._seats.index(self._player_dict[playerID]) self._seats[idx] = Player(-1, -1, 0, 'empty', 0, True) del self._player_dict[playerID] self.emptyseats += 1 except ValueError: pass def resolve_sidepots(self, players_playing): players = [p for p in players_playing if p.currentbet] if not self._quiet: print('current bets: ', [p.currentbet for p in players]) print('playing hand: ', [p.playing_hand for p in players]) if not players: return try: smallest_bet = min( [p.currentbet for p in players if p.playing_hand]) except ValueError: for p in players: self._side_pots[self._current_sidepot] += p.currentbet p.currentbet = 0 return smallest_players_allin = [ p for p, bet in zip(players, [p.currentbet for p in players]) if bet == smallest_bet and p.isallin ] for p in players: self._side_pots[self._current_sidepot] += min( smallest_bet, p.currentbet) p.currentbet -= min(smallest_bet, p.currentbet) p.lastsidepot = self._current_sidepot if smallest_players_allin: self._current_sidepot += 1 self.resolve_sidepots(players) if not self._quiet: print('sidepots: ', self._side_pots) def new_round(self): for player in self._player_dict.values(): player.currentbet = 0 player.playedthisround = False self._round += 1 self._tocall = 0 self._lastraise = 0 def resolve_game(self, players): # print('Community cards: ', end='') # Card.print_pretty_cards(self.community) if len(players) == 1: players[0].refund(sum(self._side_pots)) # print('Player', players[0].playerID, 'wins the pot (',sum(self._side_pots),')') self._totalpot = 0 else: # compute hand ranks print("Board: ", Card.print_pretty_cards(self.community)) for player in players: player.handrank = self._evaluator.evaluate( player.hand, self.community) print("Player: {}".format(player.playerID), Card.print_pretty_cards(player.hand)) # trim side_pots to only include the non-empty side pots temp_pots = [pot for pot in self._side_pots if pot > 0] # compute who wins each side pot and pay winners for pot_idx, _ in enumerate(temp_pots): # print('players last pots', [(p.playerID, p.lastsidepot) for p in players]) # find players involved in given side_pot, compute the winner(s) pot_contributors = [ p for p in players if p.lastsidepot >= pot_idx ] winning_rank = min([p.handrank for p in pot_contributors]) winning_players = [ p for p in pot_contributors if p.handrank == winning_rank ] for player in winning_players: split_amount = int(self._side_pots[pot_idx] / len(winning_players)) if not self._quiet: print( 'Player', player.playerID, 'wins side pot (', int(self._side_pots[pot_idx] / len(winning_players)), ')') player.refund(split_amount) self._side_pots[pot_idx] -= split_amount # any remaining chips after splitting go to the winner in the earliest position if self._side_pots[pot_idx]: earliest = self._first_to_act( [player for player in winning_players]) earliest.refund(self._side_pots[pot_idx]) def reset(self): for player in self._seats: if not player.emptyplayer and not player.sitting_out: player.reset_hand() self.community = [] self._current_sidepot = 0 self._totalpot = 0 self._side_pots = [0] * len(self._seats) self._deck.shuffle() self._button = (self._button + 1) % len(self._seats) while not self._seats[self._button].playing_hand: self._button = (self._button + 1) % len(self._seats) def output_state(self, current_player): return { 'players': [player.player_state() for player in self._seats], 'community': self.community, 'my_seat': current_player.get_seat(), 'pocket_cards': current_player.hand, 'pot': self._totalpot, 'button': self._button, 'tocall': (self._tocall - current_player.currentbet), 'stack': current_player.stack, 'bigblind': self._bigblind, 'playerID': current_player.playerID, 'lastraise': self._lastraise, 'minraise': max(self._bigblind, self._lastraise + self._tocall) }
from deuces.deuces import Deck, Card from pokermodules.convenience import ring_winners ### Winning cards/hand if all 9 players show down. ### Takes about 38 sec on Intel Core i5 at 3.1 GHz. ### 1 min on my macbook (2.7ghz i7). for n in range(75000): deck = Deck() ## Deal the hole cards ring = [] for i in range(9): p = deck.draw(2) p.sort(reverse=True) ring.append(p) ## Deal board board = deck.draw(5) ## Show down [winners, winrank] = ring_winners(board, ring) for i, hole in enumerate(ring): hole_str = Card.int_to_str(hole[0])[0] + Card.int_to_str(hole[1])[0] if Card.get_suit_int(hole[0]) == Card.get_suit_int(hole[1]): hole_str += 's' else: hole_str += 'o' wl = '' if i in winners: wl = 'w'
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()