Как написать покер на питоне

import random import itertools from collections import Counter from tkinter import * from PIL import ImageTk, Image # only non_standard dependency you need to DL import threading import queue import time def main(): class Card(object): def __init__(self, value, suit): self.value = value self.suit = suit self.showing = True def __repr__(self): value_name = «» suit_name = «» if self.showing: if self.value == 0: value_name = «Two» if self.value == 1: value_name = «Three» if self.value == 2: value_name = «Four» if self.value == 3: value_name = «Five» if self.value == 4: value_name = «Six» if self.value == 5: value_name = «Seven» if self.value == 6: value_name = «Eight» if self.value == 7: value_name = «Nine» if self.value == 8: value_name = «Ten» if self.value == 9: value_name = «Jack» if self.value == 10: value_name = «Queen» if self.value == 11: value_name = «King» if self.value == 12: value_name = «Ace» if self.suit == 0: suit_name = «Diamonds» if self.suit == 1: suit_name = «Clubs» if self.suit == 2: suit_name = «Hearts» if self.suit == 3: suit_name = «Spades» return value_name + » of « + suit_name else: return «[CARD]» class StandardDeck(list): def __init__(self): super().__init__() suits = list(range(4)) values = list(range(13)) [[self.append(Card(i, j)) for j in suits] for i in values] def __repr__(self): return f»Standard deck of cardsn{len(self)} cards remaining» def shuffle(self): random.shuffle(self) print(«nn—deck shuffled—«) def deal(self, location, times=1): for i in range(times): location.cards.append(self.pop(0)) def burn(self): self.pop(0) class Player(object): def __init__(self, name=None): self.name = name self.chips = 0 self.stake = 0 self.stake_gap = 0 self.cards = [] self.score = [] self.fold = False self.ready = False self.all_in = False self.list_of_special_attributes = [] self.win = False def __repr__(self): name = self.name return name class Game(object): def __init__(self): self.need_raise_info = False self.game_over = False self.acting_player = Player() self.possible_responses = [] self.round_counter = 0 self.cards = [] self.pot = 0 self.pot_dict = {} self.pot_in_play = 0 self.list_of_player_names = [] self.dealer = Player() self.small_blind = Player() self.big_blind = Player() self.first_actor = Player() self.winners = [] self.deck = StandardDeck() self.list_of_scores_from_eligible_winners = [] self.setup = ask_app(«Start?») while True: try: self.number_of_players = len(self.setup[«players»]) break except ValueError: print(«Invalid response») if 1 < self.number_of_players < 11: pass else: print(«Invalid number of players») main() self.list_of_players = [Player(name) for name in self.setup[«players»] if name != «»] while True: try: self.starting_chips = int(self.setup[«chips»][0]) if self.starting_chips > 0: break print(«Invalid number, try greater than 0») except ValueError: print(«Invalid response») continue for player in self.list_of_players: player.chips = self.starting_chips self.ready_list = [] while True: try: self.small_blind_amount = int(self.setup[«chips»][1]) if self.starting_chips > self.small_blind_amount > 0: break print(«Invalid number: try bigger than zero, smaller than starting chips») except ValueError: print(«Invalid response») continue while True: try: self.big_blind_amount = int(self.setup[«chips»][2]) if self.starting_chips > self.big_blind_amount > self.small_blind_amount: break print(«Invalid number: try bigger than small blind, smaller than starting chips») except ValueError: print(«Invalid response») continue self.winner = None self.action_counter = 0 self.attribute_list = [«d», «sb», «bb», «fa»] self.highest_stake = 0 self.fold_list = [] self.not_fold_list = [] self.round_ended = False self.fold_out = False self.list_of_scores_eligible = [] self.list_of_players_not_out = list(set(self.list_of_players)) self.number_of_player_not_out = int(len(list(set(self.list_of_players)))) def print_game_info(self): pass def print_round_info(self): print(«n«) for player in self.list_of_players: print(«n«) print(f»Name: {player.name}«) print(f»Cards: {player.cards}«) print(f»Player score: {player.score}«) print(f»Chips: {player.chips}«) print(f»Special Attributes: {player.list_of_special_attributes}«) if player.fold: print(f»Folded») if player.all_in: print(f»All-in») print(f»Stake: {player.stake}«) print(f»Stake-gap: {player.stake_gap}«) print(«n«) print(f»Pot: {self.pot}«) print(f»Community cards: {self.cards}«) print(«n«) def establish_player_attributes(self): address_assignment = 0 self.dealer = self.list_of_players_not_out[address_assignment] self.dealer.list_of_special_attributes.append(«dealer») address_assignment += 1 address_assignment %= len(self.list_of_players_not_out) self.small_blind = self.list_of_players_not_out[address_assignment] self.small_blind.list_of_special_attributes.append(«small blind») address_assignment += 1 address_assignment %= len(self.list_of_players_not_out) self.big_blind = self.list_of_players_not_out[address_assignment] self.big_blind.list_of_special_attributes.append(«big blind») address_assignment += 1 address_assignment %= len(self.list_of_players_not_out) self.first_actor = self.list_of_players_not_out[address_assignment] self.first_actor.list_of_special_attributes.append(«first actor») self.list_of_players_not_out.append(self.list_of_players_not_out.pop(0)) def deal_hole(self): for player in self.list_of_players_not_out: self.deck.deal(player, 2) def deal_flop(self): self.deck.burn() self.deck.deal(self, 3) def deal_turn(self): self.deck.burn() print(«n—card burned—«) self.deck.deal(self, 1) print(nCommunity Cards: {self.cards}«) def deal_river(self): self.deck.burn() print(«n—card burned—«) self.deck.deal(self, 1) print(nnCommunity Cards: {self.cards}«) def hand_scorer(self, player): seven_cards = player.cards + self.cards all_hand_combos = list(itertools.combinations(seven_cards, 5)) list_of_all_score_possibilities = [] for i in all_hand_combos: suit_list = [] value_list = [] for j in i: suit_list.append(j.suit) value_list.append(j.value) initial_value_check = list(reversed(sorted(value_list))) score1 = 0 score2 = 0 score3 = 0 score4 = initial_value_check.pop(0) score5 = initial_value_check.pop(0) score6 = initial_value_check.pop(0) score7 = initial_value_check.pop(0) score8 = initial_value_check.pop(0) list_of_pair_values = [] other_cards_not_special = [] pair_present = False pair_value = int value_counter = dict(Counter(value_list)) for value_name, count in value_counter.items(): if count == 2: pair_present = True pair_value = value_name list_of_pair_values.append(value_name) if pair_present: for value in value_list: if value not in list_of_pair_values: other_cards_not_special.append(value) other_cards_not_special = list(reversed(sorted(other_cards_not_special))) if len(set(list_of_pair_values)) == 1: score1 = 1 score2 = max(list_of_pair_values) try: score3 = other_cards_not_special.pop(0) score4 = other_cards_not_special.pop(0) score5 = other_cards_not_special.pop(0) score6 = other_cards_not_special.pop(0) score7 = other_cards_not_special.pop(0) score8 = other_cards_not_special.pop(0) except IndexError: pass if len(set(list_of_pair_values)) == 2: list_of_pair_values = list(reversed(sorted(list_of_pair_values))) score1 = 2 score2 = list_of_pair_values.pop(0) score3 = list_of_pair_values.pop(0) try: score4 = other_cards_not_special.pop(0) score5 = other_cards_not_special.pop(0) score6 = other_cards_not_special.pop(0) score7 = other_cards_not_special.pop(0) score8 = other_cards_not_special.pop(0) except IndexError: pass three_of_a_kind_value = int other_cards_not_special = [] three_of_a_kind_present = False for value_name, count in value_counter.items(): if count == 3: three_of_a_kind_present = True three_of_a_kind_value = value_name if three_of_a_kind_present: for value in value_list: if value != three_of_a_kind_value: other_cards_not_special.append(value) other_cards_not_special = list(reversed(sorted(other_cards_not_special))) score1 = 3 score2 = three_of_a_kind_value try: score3 = other_cards_not_special.pop(0) score4 = other_cards_not_special.pop(0) score5 = other_cards_not_special.pop(0) score6 = other_cards_not_special.pop(0) score7 = other_cards_not_special.pop(0) score8 = other_cards_not_special.pop(0) except IndexError: pass if sorted(value_list) == list(range(min(value_list), max(value_list) + 1)): score1 = 4 score2 = max(value_list) if sorted(value_list) == [0, 1, 2, 3, 12]: score1 = 4 score2 = 3 if len(set(suit_list)) == 1: score1 = 5 score2 = max(value_list) if three_of_a_kind_present and pair_present: score1 = 6 score2 = three_of_a_kind_value score3 = pair_value four_of_a_kind_value = int other_card_value = int four_of_a_kind = False for value_name, count in value_counter.items(): if count == 4: four_of_a_kind_value = value_name four_of_a_kind: True for value in value_list: if value != four_of_a_kind_value: other_card_value = value if four_of_a_kind: score1 = 7 score2 = four_of_a_kind_value score3 = other_card_value if sorted(value_list) == [0, 1, 2, 3, 12] and len(set(suit_list)) == 1: score1 = 8 score2 = 3 if sorted(value_list) == list(range(min(value_list), max(value_list) + 1)) and len(set(suit_list)) == 1: score1 = 8 score2 = max(value_list) if max(value_list) == 12: score1 = 9 list_of_all_score_possibilities.append([score1, score2, score3, score4, score5, score6, score7, score8]) best_score = max(list_of_all_score_possibilities) player.score = best_score def score_all(self): for player in self.list_of_players_not_out: self.hand_scorer(player) def find_winners(self): if self.fold_out: for player in list(set(self.winners)): player.chips += int((self.pot / len(list(set(self.winners))))) print({player.name} wins {int((self.pot / len(list(set(self.winners)))))} chips!») else: list_of_stakes = [] for player in self.list_of_players_not_out: list_of_stakes.append(player.stake) list_of_stakes = list(set(list_of_stakes)) list_of_stakes = sorted(list_of_stakes) for stake in list_of_stakes: print(stake) for player in self.list_of_players_not_out: print(player.name) print(player.stake) print(self.list_of_players_not_out) list_of_players_at_stake = [] list_of_list_of_players_at_stake = [] for i in range(len(list_of_stakes)): for player in self.list_of_players_not_out: if player.stake >= list_of_stakes[i]: list_of_players_at_stake.append(player) list_of_list_of_players_at_stake.append(list(set(list_of_players_at_stake))) list_of_players_at_stake.clear() print(list_of_list_of_players_at_stake) list_of_pot_seeds = [] for i in list_of_stakes: list_of_pot_seeds.append(i) list_of_pot_seeds.reverse() for i in range(len(list_of_pot_seeds)): try: list_of_pot_seeds[i] -= list_of_pot_seeds[i + 1] except IndexError: pass list_of_pot_seeds.reverse() list_of_pots = [] for i in range(len(list_of_pot_seeds)): print(len(list_of_list_of_players_at_stake[i])) for i in range(len(list_of_pot_seeds)): list_of_pots.append(list_of_pot_seeds[i] * len(list_of_list_of_players_at_stake[i])) for i in range(len(list_of_pots)): winners = [] self.list_of_scores_eligible.clear() for player in list_of_list_of_players_at_stake[i]: if player.fold: pass else: self.list_of_scores_eligible.append(player.score) max_score = max(self.list_of_scores_eligible) for player in list_of_list_of_players_at_stake[i]: if player.fold: pass else: if player.score == max_score: player.win = True winners.append(player) prize = int(list_of_pots[i] / len(winners)) for player in winners: print({player.name} wins {prize} chips!») player.chips += prize self.pot -= prize for player in self.list_of_players_not_out: if player.win: print( «n« + player.name + «: « + str( player.cards) + «t<-WINNER WINNER WINNER WINNER WINNER WINNER « «WINNER WINNER» + «nt« + score_interpreter(player)) elif player.fold: print(«n« + player.name + «: « + str(player.cards) + «nt« + «[FOLDED]») else: print(«n« + player.name + «: « + str(player.cards) + «nt« + score_interpreter(player)) print(tScoreCode: {player.score}«) print(f»Pot: {self.pot}«) [print(player.name, player.chips) for player in self.list_of_players_not_out] def clear_board(self): self.possible_responses.clear() self.cards.clear() self.deck = StandardDeck() self.deck.shuffle() self.pot = 0 self.pot_dict.clear() self.winners.clear() self.list_of_scores_from_eligible_winners.clear() self.action_counter = 0 self.highest_stake = 0 self.fold_list.clear() self.not_fold_list.clear() self.fold_out = False self.list_of_scores_eligible.clear() self.round_ended = False for player in self.list_of_players: player.score.clear() player.cards.clear() player.stake = 0 player.stake_gap = 0 player.ready = False player.all_in = False player.fold = False player.list_of_special_attributes.clear() player.win = False def end_round(self): self.list_of_players_not_out = list(set(self.list_of_players_not_out)) for player in self.list_of_players_not_out: if player.chips <= 0: self.list_of_players_not_out.remove(player) print({player.name} is out of the game!») self.number_of_player_not_out = len(set(self.list_of_players_not_out)) if self.number_of_player_not_out == 1: self.game_over = True self.winner = self.list_of_players_not_out[0] print(f»Game is over: {self.winner} wins with {self.winner.chips}) quit() new_round = str(ask_app(«Start a new round? (yes/no)»)) if new_round == «yes»: print(«nntttt—ROUND OVER—«) print(«nnttt—STARTING NEW ROUND—n«) self.round_counter += 1 pass else: quit() time.sleep(0.3) self.clear_board() def answer(self, player): player.stake_gap = self.highest_stake player.stake if player.all_in or player.fold or self.fold_out: return True if player.chips <= 0: print({player.name} is all in!») player.all_in = True print(f»Highest stake: {self.highest_stake}«) print(f»Put in at least {player.stake_gap} to stay in.nDon’t Have that much? You’ll have to go all-in!») print(f»Chips available: {player.chips}«) self.possible_responses.clear() if player.stake_gap > 0: self.possible_responses.append(«fold») if player.stake_gap == player.chips: self.possible_responses.append(«all_in_exact») if player.stake_gap > player.chips: self.possible_responses.append(«all_in_partial») if player.stake_gap < player.chips: self.possible_responses.append(«call_exact») self.possible_responses.append(«call_and_raise») self.possible_responses.append(«call_and_all_in») if player.stake_gap == 0: self.possible_responses.append(«check») self.possible_responses.append(«raise») self.possible_responses.append(«fold») self.possible_responses.append(«all_in») while True: print(self.possible_responses) response = str(ask_app({player}‘s actionn->», self)) if response not in self.possible_responses: print(«Invalid response») continue if response == «all_in_partial»: player.stake += player.chips self.pot += player.chips player.stake_gap -= player.chips player.chips = 0 print({player.name} is all-in!») player.all_in = True return True if response == «all_in_exact»: print({player.name} is all-in!») player.all_in = True player.stake += player.stake_gap self.pot += player.stake_gap player.chips = 0 player.stake_gap = 0 return True if response == «fold»: player.fold = True self.fold_list.append(player) if len(self.fold_list) == (len(self.list_of_players_not_out) 1): for player in self.list_of_players_not_out: if player not in self.fold_list: self.fold_out = True print({player} wins!») self.winners.append(player) for player in self.winners: player.win = True self.round_ended = True return True if response == «call_exact»: player.stake += player.stake_gap self.pot += player.stake_gap player.chips -= player.stake_gap player.stake_gap = 0 return True if response == «check»: player.stake_gap = 0 return True if response == «raise»: self.need_raise_info = True while True: bet = int( ask_app(f»How much would {player.name} like to raise? ({player.chips} available)n->», self)) if bet > player.chips or bet <= 0: print(«Invalid response») continue if bet == player.chips: print({player.name} is all-in!») player.all_in = True self.need_raise_info = False player.stake += bet self.pot += bet player.chips -= bet self.highest_stake = player.stake self.ready_list.clear() player.stake_gap = 0 return True if response == «call_and_raise»: self.need_raise_info = True player.stake += player.stake_gap self.pot += player.stake_gap player.chips -= player.stake_gap player.stake_gap = 0 while True: try: bet = int( ask_app(f»How much would {player.name} like to raise? ({player.chips} available)n->», self)) except ValueError: continue if bet > player.chips or bet <= 0: print(«Invalid response») continue if bet == player.chips: print({player.name} is all-in!») player.all_in = True self.need_raise_info = False player.stake += bet self.pot += bet player.chips -= bet self.highest_stake = player.stake self.ready_list.clear() return True if response == «call_and_all_in»: player.stake += player.stake_gap self.pot += player.stake_gap player.chips -= player.stake_gap player.stake_gap = 0 player.stake += player.chips self.pot += player.chips player.stake_gap -= player.chips player.chips = 0 print({player.name} is all-in!») player.all_in = True self.highest_stake = player.stake self.ready_list.clear() return True if response == «all_in»: player.stake_gap = 0 player.stake += player.chips self.pot += player.chips player.chips = 0 print({player.name} is all-in!») player.all_in = True self.highest_stake = player.stake self.ready_list.clear() return True print(«Invalid Response») def ask_players(self): self.ready_list.clear() starting_index = self.list_of_players_not_out.index(self.first_actor) for player in self.list_of_players_not_out: player.ready = False while True: self.acting_player = self.list_of_players_not_out[starting_index] player_ready = self.answer(self.list_of_players_not_out[starting_index]) starting_index += 1 starting_index %= len(self.list_of_players_not_out) if player_ready: self.ready_list.append(«gogo») if len(self.ready_list) == len(self.list_of_players_not_out): break def act_one(self): if self.small_blind_amount > self.small_blind.chips: self.small_blind.stake += self.small_blind.chips self.highest_stake = self.small_blind.chips self.pot += self.small_blind.chips self.small_blind.chips = 0 print({self.small_blind.name} is all-in!») self.small_blind.all_in = True else: self.small_blind.chips -= self.small_blind_amount self.small_blind.stake += self.small_blind_amount self.highest_stake = self.small_blind_amount self.pot += self.small_blind_amount if self.big_blind_amount > self.big_blind.chips: self.big_blind.stake += self.big_blind.chips self.highest_stake = self.big_blind.chips self.pot += self.big_blind.chips self.big_blind.chips = 0 print({self.big_blind} is all-in!») self.big_blind.all_in = True else: self.big_blind.chips -= self.big_blind_amount self.big_blind.stake += self.big_blind_amount self.highest_stake = self.big_blind_amount self.pot += self.big_blind_amount self.ask_players() class App(Tk): def __init__(self, *args, **kwargs): Tk.__init__(self, *args, **kwargs) self.game_object = object container = Frame(self) container.pack(side=«top», fill=«both», expand=True) container.grid_rowconfigure(0, weight=1) container.grid_columnconfigure(0, weight=1) self.frames = {} list_of_frames = [StartPage, GamePage] for F in list_of_frames: frame = F(container, self) self.frames[F] = frame frame.grid(row=0, column=0, sticky=«nsew») self.fresh = True self.show_frame(StartPage) def show_frame(self, context): frame = self.frames[context] print(«waiting») if not self.fresh: time.sleep(0.1) frame.update(game_info_q.get()) self.fresh = False frame.tkraise() class StartPage(Frame): def __init__(self, parent, controller): Frame.__init__(self, parent) height = 500 width = 800 canvas = Canvas(self, height=height, width=width, bg=«light green») canvas.pack() left_frame = Frame(canvas, bg=‘green’, bd=5) left_frame.place(relx=0, rely=0, relwidth=0.5, relheight=1, anchor=‘nw’) name_frame = Frame(left_frame, bg=«light green», bd=5) name_frame.place(relx=0.5, rely=0.17, relwidth=0.9, relheight=0.7, anchor=«n») self.entry_p0 = Entry(name_frame, font=(«Courier», 12), bd=3) self.entry_p0.place(relwidth=0.5, relheight=0.2) self.entry_p1 = Entry(name_frame, font=(«Courier», 12), bd=3) self.entry_p1.place(relx=0.5, rely=0, relwidth=0.5, relheight=0.2) self.entry_p2 = Entry(name_frame, font=(«Courier», 12), bd=3) self.entry_p2.place(relx=0, rely=0.2, relwidth=0.5, relheight=0.2) self.entry_p3 = Entry(name_frame, font=(«Courier», 12), bd=3) self.entry_p3.place(relx=0.5, rely=0.2, relwidth=0.5, relheight=0.2) self.entry_p4 = Entry(name_frame, font=(«Courier», 12), bd=3) self.entry_p4.place(relx=0, rely=0.4, relwidth=0.5, relheight=0.2) self.entry_p5 = Entry(name_frame, font=(«Courier», 12), bd=3) self.entry_p5.place(relx=0.5, rely=0.4, relwidth=0.5, relheight=0.2) self.entry_p6 = Entry(name_frame, font=(«Courier», 12), bd=3) self.entry_p6.place(relx=0, rely=0.6, relwidth=0.5, relheight=0.2) self.entry_p7 = Entry(name_frame, font=(«Courier», 12), bd=3) self.entry_p7.place(relx=0.5, rely=0.6, relwidth=0.5, relheight=0.2) self.entry_p8 = Entry(name_frame, font=(«Courier», 12), bd=3) self.entry_p8.place(relx=0, rely=0.8, relwidth=0.5, relheight=0.2) self.entry_p9 = Entry(name_frame, font=(«Courier», 12), bd=3) self.entry_p9.place(relx=0.5, rely=0.8, relwidth=0.5, relheight=0.2) enter_player_label = Label(left_frame, text=«Player Names:», font=(«Courier», 12), bd=3) enter_player_label.place(relx=0.25, rely=0.07, relwidth=0.5, relheight=0.05) # self.entry.bind(«<Return>», lambda _: self.button_click(self.entry.get())) right_frame = Frame(canvas, bg=‘green’, bd=5) right_frame.place(relx=1, rely=0, relwidth=0.5, relheight=1, anchor=‘ne’) self.sc_label = Label(right_frame, text=«Starting Chips:», font=(«Courier», 12), bd=3) self.sc_label.place(relx=0.25, rely=0.1, relwidth=0.5, relheight=0.05) self.sc_entry = Entry(right_frame, font=(«Courier»), bd=3) self.sc_entry.place(relx=0.5, rely=0.17, relwidth=0.5, relheight=0.07, anchor=«n») self.sb_label = Label(right_frame, text=«Small-Blind Chips:», font=(«Courier», 12), bd=3) self.sb_label.place(relx=0.25, rely=0.33, relwidth=0.5, relheight=0.05) self.sb_entry = Entry(right_frame, font=(«Courier»), bd=3) self.sb_entry.place(relx=0.5, rely=0.4, relwidth=0.5, relheight=0.07, anchor=«n») self.bb_label = Label(right_frame, text=«Big-Blind Chips:», font=(«Courier», 12), bd=3) self.bb_label.place(relx=0.25, rely=0.56, relwidth=0.5, relheight=0.05) self.bb_entry = Entry(right_frame, font=(«Courier»), bd=3) self.bb_entry.place(relx=0.5, rely=0.63, relwidth=0.5, relheight=0.07, anchor=«n») self.bb_entry.bind(«<Return>», lambda _: self.button_click(self.entry_p0.get(), self.entry_p1.get(), self.entry_p2.get(), self.entry_p3.get(), self.entry_p4.get(), self.entry_p5.get(), self.entry_p6.get(), self.entry_p7.get(), self.entry_p8.get(), self.entry_p9.get(), self.sc_entry.get(), self.sb_entry.get(), self.bb_entry.get(), controller)) button = Button(right_frame, text=«START», font=(«Courier», 12), command=lambda: self.button_click(self.entry_p0.get(), self.entry_p1.get(), self.entry_p2.get(), self.entry_p3.get(), self.entry_p4.get(), self.entry_p5.get(), self.entry_p6.get(), self.entry_p7.get(), self.entry_p8.get(), self.entry_p9.get(), self.sc_entry.get(), self.sb_entry.get(), self.bb_entry.get(), controller)) button.place(relx=0.5, rely=0.9, relwidth=0.3, relheight=0.1, anchor=«n») def button_click(self, entry0, entry1, entry2, entry3, entry4, entry5, entry6, entry7, entry8, entry9, entrysc, entrysb, entrybb, controller): entry_list = [entry0, entry1, entry2, entry3, entry4, entry5, entry6, entry7, entry8, entry9, entrysc, entrysb, entrybb] player_entry_list = [entry0, entry1, entry2, entry3, entry4, entry5, entry6, entry7, entry8, entry9] print(player_entry_list) player_entry_list = list(set(player_entry_list)) for player in player_entry_list: if player == «»: player_entry_list.remove(player) print(player_entry_list) if len(player_entry_list) < 2: print(«not enough players») return chip_entry_list = [entrysc, entrysb, entrybb] for chips in chip_entry_list: try: chips = int(chips) except ValueError: print(«Value Error») return if chips == «» or chips <= 0: print(«chip entry error») return if not int(entrysc) > int(entrybb) > int(entrysb): print(«chip entry error2 «) return setup = { «players»: player_entry_list, «chips»: chip_entry_list } response_q.put(setup) game_event.set() controller.show_frame(GamePage) class GamePage(Frame): def __init__(self, parent, controller): Frame.__init__(self, parent) self.restart = False self.responses = [] self.list_of_button_r = [] height = 500 width = 800 canvas = Canvas(self, height=height, width=width, bg=«light green») canvas.pack() left_frame = Frame(canvas, bg=‘green’, bd=5) left_frame.place(relx=0, rely=0, relwidth=0.5, relheight=1, anchor=‘nw’) name_frame = Frame(left_frame, bg=«light green», bd=5) name_frame.place(relx=0.5, rely=0, relwidth=1, relheight=1, anchor=«n») self.frame_p0 = Frame(name_frame, bd=3, relief=«groove») self.frame_p0.place(relwidth=0.5, relheight=0.2) self.name_label_p0 = Label(self.frame_p0, font=(«Courier», 10), bd=3) self.name_label_p0.place(relx=0, rely=0, relheight=(1 / 3), relwidth=0.38) self.chips_label_p0 = Label(self.frame_p0, font=(«Courier», 10), bd=3) self.chips_label_p0.place(relx=0, rely=(1 / 3), relheight=(1 / 3), relwidth=0.38) self.cards_frame_p0 = Frame(self.frame_p0, bd=3, relief=«groove») self.cards_frame_p0.place(relx=0.38, relheight=1, relwidth=0.62) self.card1_p0 = Label(self.cards_frame_p0) self.card1_p0.place(relwidth=0.5, relheight=1) self.card2_p0 = Label(self.cards_frame_p0) self.card2_p0.place(relx=0.5, relwidth=0.5, relheight=1) self.stake_label_p0 = Label(self.frame_p0, bd=1, relief=«groove») self.stake_label_p0.place(relx=0, rely=(2 / 3), relheight=(1 / 3), relwidth=0.38) self.frame_p1 = Frame(name_frame, bd=3, relief=«groove») self.frame_p1.place(relx=0.5, rely=0, relwidth=0.5, relheight=0.2) self.name_label_p1 = Label(self.frame_p1, font=(«Courier», 10), bd=3) self.name_label_p1.place(relx=0, rely=0, relheight=(1 / 3), relwidth=0.38) self.chips_label_p1 = Label(self.frame_p1, font=(«Courier», 10), bd=3) self.chips_label_p1.place(relx=0, rely=(1 / 3), relheight=(1 / 3), relwidth=0.38) self.cards_frame_p1 = Frame(self.frame_p1, bd=3, relief=«groove») self.cards_frame_p1.place(relx=0.38, relheight=1, relwidth=0.62) self.card1_p1 = Label(self.cards_frame_p1) self.card1_p1.place(relwidth=0.5, relheight=1) self.card2_p1 = Label(self.cards_frame_p1) self.card2_p1.place(relx=0.5, relwidth=0.5, relheight=1) self.stake_label_p1 = Label(self.frame_p1, bd=1, relief=«groove») self.stake_label_p1.place(relx=0, rely=(2 / 3), relheight=(1 / 3), relwidth=0.38) self.frame_p2 = Frame(name_frame, bd=3, relief=«groove») self.frame_p2.place(relx=0, rely=0.2, relwidth=0.5, relheight=0.2) self.name_label_p2 = Label(self.frame_p2, font=(«Courier», 10), bd=3) self.name_label_p2.place(relx=0, rely=0, relheight=(1 / 3), relwidth=0.38) self.chips_label_p2 = Label(self.frame_p2, font=(«Courier», 10), bd=3) self.chips_label_p2.place(relx=0, rely=(1 / 3), relheight=(1 / 3), relwidth=0.38) self.cards_frame_p2 = Frame(self.frame_p2, bd=3, relief=«groove») self.cards_frame_p2.place(relx=0.38, relheight=1, relwidth=0.62) self.card1_p2 = Label(self.cards_frame_p2) self.card1_p2.place(relwidth=0.5, relheight=1) self.card2_p2 = Label(self.cards_frame_p2) self.card2_p2.place(relx=0.5, relwidth=0.5, relheight=1) self.stake_label_p2 = Label(self.frame_p2, bd=1, relief=«groove») self.stake_label_p2.place(relx=0, rely=(2 / 3), relheight=(1 / 3), relwidth=0.38) self.frame_p3 = Frame(name_frame, bd=3, relief=«groove») self.frame_p3.place(relx=0.5, rely=0.2, relwidth=0.5, relheight=0.2) self.name_label_p3 = Label(self.frame_p3, font=(«Courier», 10), bd=3) self.name_label_p3.place(relx=0, rely=0, relheight=(1 / 3), relwidth=0.38) self.chips_label_p3 = Label(self.frame_p3, font=(«Courier», 10), bd=3) self.chips_label_p3.place(relx=0, rely=(1 / 3), relheight=(1 / 3), relwidth=0.38) self.cards_frame_p3 = Frame(self.frame_p3, bd=3, relief=«groove») self.cards_frame_p3.place(relx=0.38, relheight=1, relwidth=0.62) self.card1_p3 = Label(self.cards_frame_p3) self.card1_p3.place(relwidth=0.5, relheight=1) self.card2_p3 = Label(self.cards_frame_p3) self.card2_p3.place(relx=0.5, relwidth=0.5, relheight=1) self.stake_label_p3 = Label(self.frame_p3, bd=1, relief=«groove») self.stake_label_p3.place(relx=0, rely=(2 / 3), relheight=(1 / 3), relwidth=0.38) self.frame_p4 = Frame(name_frame, bd=3, relief=«groove») self.frame_p4.place(relx=0, rely=0.4, relwidth=0.5, relheight=0.2) self.name_label_p4 = Label(self.frame_p4, font=(«Courier», 10), bd=3) self.name_label_p4.place(relx=0, rely=0, relheight=(1 / 3), relwidth=0.38) self.chips_label_p4 = Label(self.frame_p4, font=(«Courier», 10), bd=3) self.chips_label_p4.place(relx=0, rely=(1 / 3), relheight=(1 / 3), relwidth=0.38) self.cards_frame_p4 = Frame(self.frame_p4, bd=3, relief=«groove») self.cards_frame_p4.place(relx=0.38, relheight=1, relwidth=0.62) self.card1_p4 = Label(self.cards_frame_p4) self.card1_p4.place(relwidth=0.5, relheight=1) self.card2_p4 = Label(self.cards_frame_p4) self.card2_p4.place(relx=0.5, relwidth=0.5, relheight=1) self.stake_label_p4 = Label(self.frame_p4, bd=1, relief=«groove») self.stake_label_p4.place(relx=0, rely=(2 / 3), relheight=(1 / 3), relwidth=0.38) self.frame_p5 = Frame(name_frame, bd=3, relief=«groove») self.frame_p5.place(relx=0.5, rely=0.4, relwidth=0.5, relheight=0.2) self.name_label_p5 = Label(self.frame_p5, font=(«Courier», 10), bd=3) self.name_label_p5.place(relx=0, rely=0, relheight=(1 / 3), relwidth=0.38) self.chips_label_p5 = Label(self.frame_p5, font=(«Courier», 10), bd=3) self.chips_label_p5.place(relx=0, rely=(1 / 3), relheight=(1 / 3), relwidth=0.38) self.cards_frame_p5 = Frame(self.frame_p5, bd=3, relief=«groove») self.cards_frame_p5.place(relx=0.38, relheight=1, relwidth=0.62) self.card1_p5 = Label(self.cards_frame_p5) self.card1_p5.place(relwidth=0.5, relheight=1) self.card2_p5 = Label(self.cards_frame_p5) self.card2_p5.place(relx=0.5, relwidth=0.5, relheight=1) self.stake_label_p5 = Label(self.frame_p5, bd=1, relief=«groove») self.stake_label_p5.place(relx=0, rely=(2 / 3), relheight=(1 / 3), relwidth=0.38) self.frame_p6 = Frame(name_frame, bd=3, relief=«groove») self.frame_p6.place(relx=0, rely=0.6, relwidth=0.5, relheight=0.2) self.name_label_p6 = Label(self.frame_p6, font=(«Courier», 10), bd=3) self.name_label_p6.place(relx=0, rely=0, relheight=(1 / 3), relwidth=0.38) self.chips_label_p6 = Label(self.frame_p6, font=(«Courier», 10), bd=3) self.chips_label_p6.place(relx=0, rely=(1 / 3), relheight=(1 / 3), relwidth=0.38) self.cards_frame_p6 = Frame(self.frame_p6, bd=3, relief=«groove») self.cards_frame_p6.place(relx=0.38, relheight=1, relwidth=0.62) self.card1_p6 = Label(self.cards_frame_p6) self.card1_p6.place(relwidth=0.5, relheight=1) self.card2_p6 = Label(self.cards_frame_p6) self.card2_p6.place(relx=0.5, relwidth=0.5, relheight=1) self.stake_label_p6 = Label(self.frame_p6, bd=1, relief=«groove») self.stake_label_p6.place(relx=0, rely=(2 / 3), relheight=(1 / 3), relwidth=0.38) self.frame_p7 = Frame(name_frame, bd=3, relief=«groove») self.frame_p7.place(relx=0.5, rely=0.6, relwidth=0.5, relheight=0.2) self.name_label_p7 = Label(self.frame_p7, font=(«Courier», 10), bd=3) self.name_label_p7.place(relx=0, rely=0, relheight=(1 / 3), relwidth=0.38) self.chips_label_p7 = Label(self.frame_p7, font=(«Courier», 10), bd=3) self.chips_label_p7.place(relx=0, rely=(1 / 3), relheight=(1 / 3), relwidth=0.38) self.cards_frame_p7 = Frame(self.frame_p7, bd=3, relief=«groove») self.cards_frame_p7.place(relx=0.38, relheight=1, relwidth=0.62) self.card1_p7 = Label(self.cards_frame_p7) self.card1_p7.place(relwidth=0.5, relheight=1) self.card2_p7 = Label(self.cards_frame_p7) self.card2_p7.place(relx=0.5, relwidth=0.5, relheight=1) self.stake_label_p7 = Label(self.frame_p7, bd=1, relief=«groove») self.stake_label_p7.place(relx=0, rely=(2 / 3), relheight=(1 / 3), relwidth=0.38) self.frame_p8 = Frame(name_frame, bd=3, relief=«groove») self.frame_p8.place(relx=0, rely=0.8, relwidth=0.5, relheight=0.2) self.name_label_p8 = Label(self.frame_p8, font=(«Courier», 10), bd=3) self.name_label_p8.place(relx=0, rely=0, relheight=(1 / 3), relwidth=0.38) self.chips_label_p8 = Label(self.frame_p8, font=(«Courier», 10), bd=3) self.chips_label_p8.place(relx=0, rely=(1 / 3), relheight=(1 / 3), relwidth=0.38) self.cards_frame_p8 = Frame(self.frame_p8, bd=3, relief=«groove») self.cards_frame_p8.place(relx=0.38, relheight=1, relwidth=0.62) self.card1_p8 = Label(self.cards_frame_p8) self.card1_p8.place(relwidth=0.5, relheight=1) self.card2_p8 = Label(self.cards_frame_p8) self.card2_p8.place(relx=0.5, relwidth=0.5, relheight=1) self.stake_label_p8 = Label(self.frame_p8, bd=1, relief=«groove») self.stake_label_p8.place(relx=0, rely=(2 / 3), relheight=(1 / 3), relwidth=0.38) self.frame_p9 = Frame(name_frame, bd=3, relief=«groove») self.frame_p9.place(relx=0.5, rely=0.8, relwidth=0.5, relheight=0.2) self.name_label_p9 = Label(self.frame_p9, font=(«Courier», 10), bd=3) self.name_label_p9.place(relx=0, rely=0, relheight=(1 / 3), relwidth=0.38) self.chips_label_p9 = Label(self.frame_p9, font=(«Courier», 10), bd=3) self.chips_label_p9.place(relx=0, rely=(1 / 3), relheight=(1 / 3), relwidth=0.38) self.cards_frame_p9 = Frame(self.frame_p9, bd=3, relief=«groove») self.cards_frame_p9.place(relx=0.38, relheight=1, relwidth=0.62) self.card1_p9 = Label(self.cards_frame_p9) self.card1_p9.place(relwidth=0.5, relheight=1) self.card2_p9 = Label(self.cards_frame_p9) self.card2_p9.place(relx=0.5, relwidth=0.5, relheight=1) self.stake_label_p9 = Label(self.frame_p9, bd=1, relief=«groove») self.stake_label_p9.place(relx=0, rely=(2 / 3), relheight=(1 / 3), relwidth=0.38) # self.entry.bind(«<Return>», lambda _: self.button_click(self.entry.get())) right_frame = Frame(canvas, bg=‘green’, bd=5) right_frame.place(relx=1, rely=0, relwidth=0.5, relheight=1, anchor=‘ne’) self.cc_frame = Frame(right_frame, bd=2, relief=«raised») self.cc_frame.place(relx=0, rely=0, relwidth=1, relheight=0.2) self.cc_1 = Label(self.cc_frame, bg=«green») self.cc_1.place(relwidth=(.50 / 3), relheight=1) card_d1 = ImageTk.PhotoImage( Image.open(«cardsdefault0.png»).resize((55, 85), Image.ANTIALIAS)) self.cc_1.image = card_d1 self.cc_1.configure(image=card_d1) self.cc_2 = Label(self.cc_frame, bg=«green») self.cc_2.place(relx=(.50 / 3), relwidth=(.50 / 3), relheight=1) card_d2 = ImageTk.PhotoImage( Image.open(«cardsdefault1.png»).resize((55, 85), Image.ANTIALIAS)) self.cc_2.image = card_d2 self.cc_2.configure(image=card_d2) self.cc_3 = Label(self.cc_frame, bg=«green») self.cc_3.place(relx=(.50 / 3) * 2, relwidth=(.50 / 3), relheight=1) card_d3 = ImageTk.PhotoImage( Image.open(«cardsdefault1.png»).resize((55, 85), Image.ANTIALIAS)) self.cc_3.image = card_d3 self.cc_3.configure(image=card_d3) self.cc_4 = Label(self.cc_frame, bg=«green») self.cc_4.place(relx=(.50 / 3) * 3, relwidth=0.25, relheight=1) card_d4 = ImageTk.PhotoImage( Image.open(«cardsdefault1.png»).resize((55, 85), Image.ANTIALIAS)) self.cc_4.image = card_d4 self.cc_4.configure(image=card_d4) self.cc_5 = Label(self.cc_frame, bg=«green») self.cc_5.place(relx=((.50 / 3) * 3) + 0.25, relwidth=0.25, relheight=1) card_d5 = ImageTk.PhotoImage( Image.open(«cardsdefault1.png»).resize((55, 85), Image.ANTIALIAS)) self.cc_5.image = card_d5 self.cc_5.configure(image=card_d5) self.pot_label = Label(right_frame, text=«pot: «, font=(«Courier», 12), bd=3) self.pot_label.place(relx=0, rely=0.2, relwidth=0.5, relheight=0.04) # self.dealer_label = Label(right_frame, text=»dealer: «, font=(«Courier», 12), bd=3) # self.dealer_label.place(relx=0, rely=0.28, relwidth=0.5, relheight=0.04) # self.sb_label = Label(right_frame, text=»small-blind: «, font=(«Courier», 12), bd=3) # self.sb_label.place(relx=0, rely=0.33, relwidth=0.5, relheight=0.04) # self.bb_label = Label(right_frame, text=»big-blind: «, font=(«Courier», 12), bd=3) # self.bb_label.place(relx=0, rely=0.38, relwidth=0.5, relheight=0.04) self.action_frame = Frame(right_frame, bd=2, relief=«raised», bg=«green») self.action_frame.place(rely=0.5, relwidth=1, relheight=0.5) self.action_cover_label = Label(self.action_frame, bg=«light green») self.action_cover_label.place(relx=0, rely=0, relheight=1, relwidth=1) self.actor_label = Label(self.action_frame, text=«Actor: «, font=(«Courier», 12), bd=3) self.actor_label.place(relwidth=1, relheight=0.06) self.new_round_label = Label(self.action_frame, text=«New Round?», font=(«Courier», 9), bd=3) self.new_round_label.place(relx=0.8, rely=0.05, relheight=0.1, relwidth=0.2) self.button_y = Button(self.action_frame, text=«Yes», command=lambda: self.action_input(«yes»)) self.button_y.place(relx=0.8, rely=0.15, relheight=0.1, relwidth=0.2) self.button_n = Button(self.action_frame, text=«No», command=lambda: self.action_input(«no»)) self.button_n.place(relx=0.8, rely=0.25, relheight=0.1, relwidth=0.2) self.raise_entry = Entry(self.action_frame, font=(«Courier», 9), bd=3) self.raise_entry.place(relx=0, rely=1, relheight=0.12, relwidth=0.22, anchor=«sw») self.raise_button = Button(self.action_frame, text=«RAISE», font=(«Courier», 9), bd=3, command=lambda: self.action_input(self.raise_entry.get())) self.raise_button.place(relx=0.22, rely=1, relheight=0.12, relwidth=0.22, anchor=«sw») self.winner_label = Label(self.action_frame, font=(«Courier», 12), bd=3) self.winner_label.place(relx=0, rely=(1/3), relwidth=0.75, relheight=0.3) def update(self, game): self.new_round_label.lower(self.action_cover_label) self.button_y.lower(self.action_cover_label) self.button_n.lower(self.action_cover_label) self.raise_entry.lower(self.action_cover_label) self.raise_button.lower(self.action_cover_label) self.winner_label.lower(self.action_cover_label) if self.restart: card1 = ImageTk.PhotoImage(Image.open(str(«cardsdefault0.png»)).resize((55, 85), Image.ANTIALIAS)) self.cc_1.image = card1 self.cc_1.configure(image=card1) card1 = ImageTk.PhotoImage(Image.open(str(«cardsdefault0.png»)).resize((55, 85), Image.ANTIALIAS)) self.cc_2.image = card1 self.cc_2.configure(image=card1) card1 = ImageTk.PhotoImage(Image.open(str(«cardsdefault0.png»)).resize((55, 85), Image.ANTIALIAS)) self.cc_3.image = card1 self.cc_3.configure(image=card1) card1 = ImageTk.PhotoImage(Image.open(str(«cardsdefault0.png»)).resize((55, 85), Image.ANTIALIAS)) self.cc_4.image = card1 self.cc_4.configure(image=card1) card1 = ImageTk.PhotoImage(Image.open(str(«cardsdefault0.png»)).resize((55, 85), Image.ANTIALIAS)) self.cc_5.image = card1 self.cc_5.configure(image=card1) self.restart = False if game.round_ended: time.sleep(0.3) self.new_round_label.lift(self.action_cover_label) self.button_y.lift(self.action_cover_label) self.button_n.lift(self.action_cover_label) winners = [] scores = [] for player in game.list_of_players_not_out: if player.win: winners.append(player) scores.append(player.score) print(f»gui thinks winners are: {winners}«) print(f»and thinks scores are: {scores}«) if scores == [[]]: self.winner_label[«text»] = «Winner: « + str(winners) else: try: for player in game.list_of_players_not_out: if player.win: if player.score == max(scores): self.winner_label[«text»] = «Winner: « + str(winners) + «n« + score_interpreter(player) except IndexError: pass self.winner_label.lift(self.action_cover_label) self.restart = True return if game.need_raise_info: self.raise_entry.lift(self.action_cover_label) self.raise_button.lift(self.action_cover_label) try: card1 = ImageTk.PhotoImage( Image.open(«cards\« + str(game.cards[0]) + «.png»).resize((55, 85), Image.ANTIALIAS)) self.cc_1.image = card1 self.cc_1.configure(image=card1) card1 = ImageTk.PhotoImage( Image.open(«cards\« + str(game.cards[1]) + «.png»).resize((55, 85), Image.ANTIALIAS)) self.cc_2.image = card1 self.cc_2.configure(image=card1) card1 = ImageTk.PhotoImage( Image.open(«cards\« + str(game.cards[2]) + «.png»).resize((55, 85), Image.ANTIALIAS)) self.cc_3.image = card1 self.cc_3.configure(image=card1) card1 = ImageTk.PhotoImage( Image.open(«cards\« + str(game.cards[3]) + «.png»).resize((55, 85), Image.ANTIALIAS)) self.cc_4.image = card1 self.cc_4.configure(image=card1) card1 = ImageTk.PhotoImage( Image.open(«cards\« + str(game.cards[4]) + «.png»).resize((55, 85), Image.ANTIALIAS)) self.cc_5.image = card1 self.cc_5.configure(image=card1) except IndexError: pass try: self.name_label_p0[«text»] = game.list_of_players[0] self.name_label_p1[«text»] = game.list_of_players[1] self.name_label_p2[«text»] = game.list_of_players[2] self.name_label_p3[«text»] = game.list_of_players[3] self.name_label_p4[«text»] = game.list_of_players[4] self.name_label_p5[«text»] = game.list_of_players[5] self.name_label_p6[«text»] = game.list_of_players[6] self.name_label_p7[«text»] = game.list_of_players[7] self.name_label_p8[«text»] = game.list_of_players[8] self.name_label_p9[«text»] = game.list_of_players[9] except IndexError: pass try: self.chips_label_p0[«text»] = «Chips:n« + str(game.list_of_players[0].chips) self.chips_label_p1[«text»] = «Chips:n« + str(game.list_of_players[1].chips) self.chips_label_p2[«text»] = «Chips:n« + str(game.list_of_players[2].chips) self.chips_label_p3[«text»] = «Chips:n« + str(game.list_of_players[3].chips) self.chips_label_p4[«text»] = «Chips:n« + str(game.list_of_players[4].chips) self.chips_label_p5[«text»] = «Chips:n« + str(game.list_of_players[5].chips) self.chips_label_p6[«text»] = «Chips:n« + str(game.list_of_players[6].chips) self.chips_label_p7[«text»] = «Chips:n« + str(game.list_of_players[7].chips) self.chips_label_p8[«text»] = «Chips:n« + str(game.list_of_players[8].chips) self.chips_label_p9[«text»] = «Chips:n« + str(game.list_of_players[9].chips) except IndexError: pass try: card1 = ImageTk.PhotoImage( Image.open(«cards\« + str(game.list_of_players[0].cards[0]) + «.png»).resize((55, 85), Image.ANTIALIAS)) self.card1_p0.image = card1 self.card1_p0.configure(image=card1) card1 = ImageTk.PhotoImage( Image.open(«cards\« + str(game.list_of_players[1].cards[0]) + «.png»).resize((55, 85), Image.ANTIALIAS)) self.card1_p1.image = card1 self.card1_p1.configure(image=card1) card1 = ImageTk.PhotoImage( Image.open(«cards\« + str(game.list_of_players[2].cards[0]) + «.png»).resize((55, 85), Image.ANTIALIAS)) self.card1_p2.image = card1 self.card1_p2.configure(image=card1) card1 = ImageTk.PhotoImage( Image.open(«cards\« + str(game.list_of_players[3].cards[0]) + «.png»).resize((55, 85), Image.ANTIALIAS)) self.card1_p3.image = card1 self.card1_p3.configure(image=card1) card1 = ImageTk.PhotoImage( Image.open(«cards\« + str(game.list_of_players[4].cards[0]) + «.png»).resize((55, 85), Image.ANTIALIAS)) self.card1_p4.image = card1 self.card1_p4.configure(image=card1) card1 = ImageTk.PhotoImage( Image.open(«cards\« + str(game.list_of_players[5].cards[0]) + «.png»).resize((55, 85), Image.ANTIALIAS)) self.card1_p5.image = card1 self.card1_p5.configure(image=card1) card1 = ImageTk.PhotoImage( Image.open(«cards\« + str(game.list_of_players[6].cards[0]) + «.png»).resize((55, 85), Image.ANTIALIAS)) self.card1_p6.image = card1 self.card1_p6.configure(image=card1) card1 = ImageTk.PhotoImage( Image.open(«cards\« + str(game.list_of_players[7].cards[0]) + «.png»).resize((55, 85), Image.ANTIALIAS)) self.card1_p7.image = card1 self.card1_p7.configure(image=card1) card1 = ImageTk.PhotoImage( Image.open(«cards\« + str(game.list_of_players[8].cards[0]) + «.png»).resize((55, 85), Image.ANTIALIAS)) self.card1_p8.image = card1 self.card1_p8.configure(image=card1) card1 = ImageTk.PhotoImage( Image.open(«cards\« + str(game.list_of_players[9].cards[0]) + «.png»).resize((55, 85), Image.ANTIALIAS)) self.card1_p9.image = card1 self.card1_p9.configure(image=card1) except IndexError: pass try: card2 = ImageTk.PhotoImage( Image.open(«cards\« + str(game.list_of_players[0].cards[1]) + «.png»).resize((55, 85), Image.ANTIALIAS)) self.card2_p0.image = card2 self.card2_p0.configure(image=card2) card2 = ImageTk.PhotoImage( Image.open(«cards\« + str(game.list_of_players[1].cards[1]) + «.png»).resize((55, 85), Image.ANTIALIAS)) self.card2_p1.image = card2 self.card2_p1.configure(image=card2) card2 = ImageTk.PhotoImage( Image.open(«cards\« + str(game.list_of_players[2].cards[1]) + «.png»).resize((55, 85), Image.ANTIALIAS)) self.card2_p2.image = card2 self.card2_p2.configure(image=card2) card2 = ImageTk.PhotoImage( Image.open(«cards\« + str(game.list_of_players[3].cards[1]) + «.png»).resize((55, 85), Image.ANTIALIAS)) self.card2_p3.image = card2 self.card2_p3.configure(image=card2) card2 = ImageTk.PhotoImage( Image.open(«cards\« + str(game.list_of_players[4].cards[1]) + «.png»).resize((55, 85), Image.ANTIALIAS)) self.card2_p4.image = card2 self.card2_p4.configure(image=card2) card2 = ImageTk.PhotoImage( Image.open(«cards\« + str(game.list_of_players[5].cards[1]) + «.png»).resize((55, 85), Image.ANTIALIAS)) self.card2_p5.image = card2 self.card2_p5.configure(image=card2) card2 = ImageTk.PhotoImage( Image.open(«cards\« + str(game.list_of_players[6].cards[1]) + «.png»).resize((55, 85), Image.ANTIALIAS)) self.card2_p6.image = card2 self.card2_p6.configure(image=card2) card2 = ImageTk.PhotoImage( Image.open(«cards\« + str(game.list_of_players[7].cards[1]) + «.png»).resize((55, 85), Image.ANTIALIAS)) self.card2_p7.image = card2 self.card2_p7.configure(image=card2) card2 = ImageTk.PhotoImage( Image.open(«cards\« + str(game.list_of_players[8].cards[1]) + «.png»).resize((55, 85), Image.ANTIALIAS)) self.card2_p8.image = card2 self.card2_p8.configure(image=card2) card2 = ImageTk.PhotoImage( Image.open(«cards\« + str(game.list_of_players[9].cards[1]) + «.png»).resize((55, 85), Image.ANTIALIAS)) self.card2_p9.image = card2 self.card2_p9.configure(image=card2) except IndexError: pass try: self.stake_label_p0[«text»] = «Stake: « + str(game.list_of_players[0].stake) self.stake_label_p1[«text»] = «Stake: « + str(game.list_of_players[1].stake) self.stake_label_p2[«text»] = «Stake: « + str(game.list_of_players[2].stake) self.stake_label_p3[«text»] = «Stake: « + str(game.list_of_players[3].stake) self.stake_label_p4[«text»] = «Stake: « + str(game.list_of_players[4].stake) self.stake_label_p5[«text»] = «Stake: « + str(game.list_of_players[5].stake) self.stake_label_p6[«text»] = «Stake: « + str(game.list_of_players[6].stake) self.stake_label_p7[«text»] = «Stake: « + str(game.list_of_players[7].stake) self.stake_label_p8[«text»] = «Stake: « + str(game.list_of_players[8].stake) self.stake_label_p9[«text»] = «Stake: « + str(game.list_of_players[9].stake) except IndexError: pass self.pot_label[«text»] = «Pot: « + str(game.pot) if game.game_over: self.actor_label[«text»] = «Winner!: « + str(game.winner.name) return print(f»round ended {game.round_ended}«) self.actor_label[«text»] = str(game.acting_player.name) variable = StringVar(self.action_frame) variable.initialize(«ACTION») w = OptionMenu(self.action_frame, variable, *game.possible_responses) w.place(relx=0, rely=0.05, relheight=0.1, relwidth=0.3) button_go = Button(self.action_frame, text=«GO», font=(«Courier», 10), command=lambda: self.action_input(variable.get())) button_go.place(relx=1, rely=1, relheight=0.3, relwidth=0.3, anchor=«se») def action_input(self, entry0): response_q.put(entry0) game_event.set() time.sleep(0.1) if not game_info_q.empty(): self.update(game_info_q.get()) def score_interpreter(player): list_of_hand_types = [«High Card», «One Pair», «Two Pair», «Three of a Kind», «Straight», «Flush», «Full House», «Four of a Kind», «Straight Flush», «Royal Flush»] list_of_values_to_interpret = [«Two», «Three», «Four», «Five», «Six», «Seven», «Eight», «Nine», «Ten», «Jack», «Queen», «King», «Ace»] hand_type = list_of_hand_types[player.score[0]] mod1 = list_of_values_to_interpret[player.score[1]] mod2 = list_of_values_to_interpret[player.score[2]] mod3 = list_of_values_to_interpret[player.score[3]] if player.score[0] == 0: return hand_type + «: « + mod3 if player.score[0] == 1: return hand_type + «: « + mod1 + «s» if player.score[0] == 2: return hand_type + «: « + mod1 + «s» + » and « + mod2 + «s» if player.score[0] == 3: return hand_type + «: « + mod1 + «s» if player.score[0] == 4: return hand_type + «: « + mod1 + » High» if player.score[0] == 5: return hand_type + «: « + mod1 + » High» if player.score[0] == 6: return hand_type + «: « + mod1 + «s» + » and « + mod2 + «s» if player.score[0] == 7: return hand_type + «: « + mod1 + «s» if player.score[0] == 8: return hand_type + «: « + mod1 + » High» if player.score[0] == 9: return hand_type def ask_app(question, game=«»): print(«asking…») print(question) answer = «» if game != «»: game_info_q.put(game) game_event.wait() if not response_q.empty(): answer = response_q.get() game_event.clear() return answer def update_gui(game1): print(«updating gui…») print(game1) def play(game): game.deck.shuffle() game_info_q.put(game) update_gui(game) game.establish_player_attributes() game.deal_hole() game.print_round_info() game.act_one() game.print_round_info() if not game.round_ended: game.deal_flop() game.print_round_info() if not game.round_ended: game.ask_players() game.print_round_info() if not game.round_ended: game.deal_turn() game.print_round_info() if not game.round_ended: game.ask_players() game.print_round_info() if not game.round_ended: game.deal_river() game.print_round_info() if not game.round_ended: game.ask_players() game.print_round_info() if not game.round_ended: game.score_all() game.print_round_info() game.find_winners() game_info_q.put(game) game.print_round_info() game.round_ended = True print(game.winners, game.winner, [player for player in game.list_of_players_not_out if player.win]) game.end_round() def run_app(): app = App() app.mainloop() def run_game_data(): game0 = Game() while True: play(game0) game_event = threading.Event() response_q = queue.Queue() game_info_q = queue.Queue() end_update = threading.Event() t1 = threading.Thread(target=run_app) t1.start() t2 = threading.Thread(target=run_game_data()) t2.start() if __name__ == «__main__»: main()

Level 2 Python projects are projects meant for those who have a grasp on the basics of Python already. If you are familiar with most of the Super Simple Python projects and can do each of them in under 30 minutes, you’re ready to go. The goal of the Level 2 Python projects is to get you familiar with using well known Python libraries, building more logically complex applications, and learning API development.

In this tutorial, we’ll be building a simple version of Texas Hold Em. This is an exercise for building more logically complex applications. Not going to lie, I thought this would be a beginner level Python project until I started working on it and I was like oh, this is harder than I thought it would be. In fact, Texas Hold Em is such a complex game, that we will leave the full implementation as a Level 3 Python tutorial. Before we get into the code make sure you have a solid understanding of the basics of Python classes. I’ve attached the source code for this project at the end.

Creating the Card Deck

The first thing we need to do is create a deck of cards. There are 13 values and 4 suits in a standard deck of 52 cards. The values range from 2 to 14 with 11, 12, 13, and 14 being Jack, Queen, King, and Ace respectively. The suits are clubs, diamonds, hearts, and spades. For purposes of displaying the cards in a standard manner, let’s also create a dictionary that translates the numbers to the face cards and vice versa. Each card can be represented as a value and a suit, you can do this with a class or a tuple in Python. I have chosen to do it with a class for added clarity.

import random
# 11 = J, 12 = Q, 13 = K, 14 = A
card_values = [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]
suits = ["clubs", "diamonds", "hearts", "spades"]
 
face_cards = {
    "J": 11,
    "Q": 12,
    "K": 13,
    "A": 14,
    11: "J",
    12: "Q",
    13: "K",
    14: "A"
}
class Card:
    def __init__(self, value, suit):
        self.value = value
        self.suit = suit

Once we’ve set up our `Card` class and the lists of possible values and suits, we can generate our deck of cards. Let’s create a `generate_cards` function which will initialize an empty list of cards and populate it. We’ll do this by looping through all the values and suits and initializing a card object for each possible combination. If the value is in the `face_cards` dictionary we created earlier, we’ll save it with the appropriate face card representation (J, Q, K, A). Our `generate_cards` function will then return that list of cards. To use it, we’ll simply set a variable, `cards` equal to the list of cards returned by the function.

def generate_cards():
    cards = []
    for value in card_values:
        for suit in suits:
            if value in face_cards:
                _card = Card(face_cards[value], suit)
            else:
                _card = Card(value, suit)
            cards.append(_card)
    return cards
 
cards = generate_cards()

Dealing the Cards for the Poker Game

Now that we have a deck of cards stored in our `cards` variable it’s time to deal the cards. We’ll start by making a function to deal a card. Our `deal_card` function will intake a list, `cards`. Unlike real life, we won’t be dealing the top card, we’ll be picking a random card from the deck to deal. We’ll be using the `randint` function from the `random` library we imported earlier. We’ll pick a random index and pop the card. Then we’ll return the card and the edited card deck.

Now You See Me – Pick a Card
def deal_card(cards):
    i = random.randint(0, len(cards)-1)
    card = cards[i]
    cards.pop(i)
    return card, cards

Now that we’ve created a way to deal a card, let’s create a `deal` function to deal hands to the players’. This function will take two parameters, the cards and the number of opponents. For this example, we’ll set the default of the `cards` parameter to the `cards` variable we created earlier and set the default number of opponents to 2.

We’ll start off this function by dealing the opponents’ hands. In real Texas Hold Em, they deal one card at a time, but this is just a simple example. Note that I use the `_` placeholder variable in the for loop, that’s because we never need to access the index. After we deal the opponents’ hands, we deal our hand. Finally, we’ll return two variables, our hand, and the list of our opponents’ hands.

def deal(cards = cards, num_opp = 2):
    opp_hands = []
    for _ in range(num_opp):
        card1, cards = deal_card(cards)
        card2, cards = deal_card(cards)
        opp_hands.append([card1, card2])
    card1, cards = deal_card(cards)
    card2, cards = deal_card(cards)
    your_hand = [card1, card2]
    return your_hand, opp_hands
 
your_hand, opp_hands = deal()
print([(card.value, card.suit) for card in your_hand])

Let’s print here out here to see what your hand should look like at this point.

Python Texas Hold Em - Dealing Your Hand
Python Texas Hold Em – Dealing Your Hand

Flop, Turn, and River

Other than the player hands that are dealt, Texas Hold Em also has a “table”. The table is dealt as the Flop, Turn, and River. The Flop is the first three cards, the Turn is the fourth, and the River is the fifth. There is usually betting involved between each deal, but we’ll leave that to the advanced course (Level 3). For this we’ll make two functions, `flop`, and `table_deal`. We’ll use `table_deal` for both the turn and river because they’re both the same deal. Could we use the `deal_card` function and simply not deal with the returned deck of `cards`? Yes, but in this tutorial, we won’t. This is just an example of another possible design choice.

Let’s start with the `flop` function. The `flop` function will take `cards` as a parameter and use `deal_card` to deal three cards and then return a list of those cards. The `table_deal` function will take `cards` as a parameter and call `deal_card` to deal a card and return only the card dealt. 

We’ll initialize the table using the `flop()` function and print out the cards on the table. Then we’ll call the `table_deal` function two times to deal the Turn and River.

def flop(cards=cards):
    card1, cards = deal_card(cards)
    card2, cards = deal_card(cards)
    card3, cards = deal_card(cards)
    return [card1, card2, card3]
 
def table_deal(cards=cards):
    card, cards = deal_card(cards)
    return card
 
table = flop()
print(f"Cards on the table: {[(card.value, card.suit) for card in table]}")
table.append(table_deal())
print(f"Cards after turn: {[(card.value, card.suit) for card in table]}")
table.append(table_deal())
print(f"Cards after river: {[(card.value, card.suit) for card in table]}")

At this point if we print run our program, we should see something like the image below.

Python Texas HoldEm Code – Hand + Table

Evaluating the Hands

In real Texas Hold Em, you’ll need to compare your hand to the cards on the table and create your highest hand of 5. However, that’s out of the scope of a Level 2 Python project. We’ll cover that in the Level 3 version. Let’s create a function called `evaluate`. The `evaluate` function will take a players’ hand and the cards on the table as its parameters, combine the hands, and evaluate what the highest hand is in that combined set of cards.

To do the evaluation, we’ll need to know the counts of each value and the counts of each suit. We’ll initialize those to empty dictionaries. We’ll also keep a set of values, initialized to an empty set. Why have values separate from the counts of the values? Because `counts` will be used for calculating pairs/triples and `vals` will be used to see if we have a straight. Can we just use a `counts` and later check its indices? Yes, but once again, design choice. It’s just easier to loop through the list in order with `vals`.

We will populate the sets and dictionaries we created earlier by iterating through the cards in the `total_hand`. If the card’s value is in `face_cards` we’ll convert back from the letter representation (J, Q, K, A) into its numerical value. One of the nice things about Python dictionaries is that they can contain indices of any type or combination of types.

def evaluate(hand, table):
    total_hand = hand + table
    # count values and suit
    counts = {}
    suits = {}
    vals = set()
    # loop through all the cards
    for card in total_hand:
        if card.value in face_cards:
            card_value = face_cards[card.value]
        else:
            card_value = card.value
        vals.add(card_value)
        if card_value in counts:
            counts[card_value] += 1
        else:
            counts[card_value] = 1
        if card.suit in suits:
            suits[card.suit] += 1
        else:
            suits[card.suit] = 1

Sort Counts of Values, Suits, and actual Values

Continuing our function, we’ll sort our `counts`, our `suits`, and `vals`. We do this in reverse order and by the number of occurrences of the value or the suit. Once we’ve gotten everything sorted out, we’ll check for straights and flushes. This is because the order of hands in Poker is high, pair, 2 pair, 3 kind, straight, flush, full house, quads, and straight flush.

    # sort counts and suits
    sorted_counts = sorted(counts.items(), key=lambda item:(item[1], item[0]), reverse=True)
    sorted_suits = sorted(suits.items(), key=lambda item:(item[1], item[0]), reverse=True)
 
    # check if vals contains a straight
    run = [sorted(list(vals))[0]]
    lastval = sorted(list(vals))[0]
    is_straight = False
    for val in sorted(list(vals)):
        if val - lastval == 1:
            run.append(val)
        else:
            run = [val]
        lastval = val
        if len(run) == 5:
            is_straight = True
            break
    # check if sorted_suits contains a flush
    is_flush = False
    if sorted_suits[0][1] == 5:
        is_flush = True

Find Highest Hand

Alright let’s get into the annoying logic of this program. Earlier I listed the winning hands in order → high, pair, 2 pair, 3 kind, straight, flush, full house, quads, and straight flush. So, we’re going to check for each of these in backwards order to optimize run time. If we see a straight flush, we’ll return a straight flush automatically. You can set the values of the straight flush as well, but it’s so rare to see (odds are 649,739 to 1) that if you see a straight flush, your chance of winning is almost 100%. After the straight flush, we’ll check for quads based on the highest count of a card value in `counts`. Then we go down the list, a full house is a triple and a double. We’ve already checked for flushes and straights for the straight flush, here we just check them separately for a flush and a straight respectively. After straight, it’s a triple, a two pair, a pair, and then the high card. All of these are easily checked using the `counts` dictionary.

    # check for straight flush
    if is_straight:
        if is_flush:
            return "Straight Flush!"
    if sorted_counts[0][1] == 4:
        return f"Quad {face_cards.get(sorted_counts[0][0]) if sorted_counts[0][0] in face_cards else sorted_counts[0][0]}s!"
    if sorted_counts[0][1] == 3:
        if sorted_counts[1][1] == 2:
            return f"Full house {face_cards.get(sorted_counts[0][0]) if sorted_counts[0][0] in face_cards else sorted_counts[0][0]}s over {face_cards.get(sorted_counts[1][0]) if sorted_counts[1][0] in face_cards else sorted_counts[1][0]}s!"
    if is_flush:
        return f"Flush in {face_cards.get(sorted_counts[0][0]) if sorted_counts[0][0] in face_cards else sorted_counts[0][0]}!"
    if is_straight:
        return f"Straight! {run}"
    # check for groups
       
    if sorted_counts[0][1] == 3:
        return f"Triple {face_cards.get(sorted_counts[0][0]) if sorted_counts[0][0] in face_cards else sorted_counts[0][0]}s!"
    if sorted_counts[0][1] == 2:
        if sorted_counts[1][1] == 2:
            return f"Two pair {face_cards.get(sorted_counts[0][0]) if sorted_counts[0][0] in face_cards else sorted_counts[0][0]} and {face_cards.get(sorted_counts[1][0]) if sorted_counts[1][0] in face_cards else sorted_counts[1][0]}!"
        else:
            return f"Pair of {face_cards.get(sorted_counts[0][0]) if sorted_counts[0][0] in face_cards else sorted_counts[0][0]}!"
    if sorted_counts[0][1] == 1:
        return f"High Card {face_cards.get(sorted_counts[0][0]) if sorted_counts[0][0] in face_cards else sorted_counts[0][0]}!"

Finalized Function

I just want to add what the finalized function for the Level 2 Python version of evaluating a hand looks like.

def evaluate(hand, table):
    total_hand = hand + table
    # count values and suit
    counts = {}
    suits = {}
    vals = set()
    # loop through all the cards
    for card in total_hand:
        if card.value in face_cards:
            card_value = face_cards[card.value]
        else:
            card_value = card.value
        vals.add(card_value)
        if card_value in counts:
            counts[card_value] += 1
        else:
            counts[card_value] = 1
        if card.suit in suits:
            suits[card.suit] += 1
        else:
            suits[card.suit] = 1
    # sort counts and suits
    sorted_counts = sorted(counts.items(), key=lambda item:(item[1], item[0]), reverse=True)
    sorted_suits = sorted(suits.items(), key=lambda item:(item[1], item[0]), reverse=True)
 
    # check if vals contains a straight
    run = [sorted(list(vals))[0]]
    lastval = sorted(list(vals))[0]
    is_straight = False
    for val in sorted(list(vals)):
        if val - lastval == 1:
            run.append(val)
        else:
            run = [val]
        lastval = val
        if len(run) == 5:
            is_straight = True
            break
   
    # check if sorted_suits contains a flush
    is_flush = False
    if sorted_suits[0][1] == 5:
        is_flush = True
    # check for straight flush
    if is_straight:
        if is_flush:
            return "Straight Flush!"
    if sorted_counts[0][1] == 4:
        return f"Quad {face_cards.get(sorted_counts[0][0]) if sorted_counts[0][0] in face_cards else sorted_counts[0][0]}s!"
    if sorted_counts[0][1] == 3:
        if sorted_counts[1][1] == 2:
            return f"Full house {face_cards.get(sorted_counts[0][0]) if sorted_counts[0][0] in face_cards else sorted_counts[0][0]}s over {face_cards.get(sorted_counts[1][0]) if sorted_counts[1][0] in face_cards else sorted_counts[1][0]}s!"
    if is_flush:
        return f"Flush in {face_cards.get(sorted_counts[0][0]) if sorted_counts[0][0] in face_cards else sorted_counts[0][0]}!"
    if is_straight:
        return f"Straight! {run}"
    # check for groups
       
    if sorted_counts[0][1] == 3:
        return f"Triple {face_cards.get(sorted_counts[0][0]) if sorted_counts[0][0] in face_cards else sorted_counts[0][0]}s!"
    if sorted_counts[0][1] == 2:
        if sorted_counts[1][1] == 2:
            return f"Two pair {face_cards.get(sorted_counts[0][0]) if sorted_counts[0][0] in face_cards else sorted_counts[0][0]} and {face_cards.get(sorted_counts[1][0]) if sorted_counts[1][0] in face_cards else sorted_counts[1][0]}!"
        else:
            return f"Pair of {face_cards.get(sorted_counts[0][0]) if sorted_counts[0][0] in face_cards else sorted_counts[0][0]}!"
    if sorted_counts[0][1] == 1:
        return f"High Card {face_cards.get(sorted_counts[0][0]) if sorted_counts[0][0] in face_cards else sorted_counts[0][0]}!"

“Playing” the Poker Game in Python

Now that we’ve finished up all the coding, let’s take a look at running the game. We’ll just have the game automatically play for us by dealing the cards and then calculating the winning hand. This function will take three parameters – your hand, the opponents’ hands, and the cards on the table. It will evaluate all of the hands and print out the highest possible poker hand from each one.

"""
takes your hand, the opponents hands, and the cards on the table
determines the values
returns a winner with all values shown
"""
def determine(hand, opp_hands, table):
    print(f"Your highest poker hand: {evaluate(hand, table)}")
    for opp in opp_hands:
        print(f"Opponent hand: {opp[0].value} {opp[0].suit}, {opp[1].value} {opp[1].suit}")
        print(f"Your opponents highest poker hand: {evaluate(opp, table)}")
 
determine(your_hand, opp_hands, table)

When we run this, we should get an output like the image below. In the image below the first opponent with the pair of 3’s has won. In the Level 2 Python version, we’re not going to implement a way to calculate the winner’s hand.

python poker game output
Python Poker Game Output

An Exercise for the Reader

As I stated above, there are some things that I have left for the Level 3 Python version of Texas Hold Em. The reason I’ve left these out of the Level 2 Python version is because they add quite some complexity to the program. For example, the real way to calculate a hand requires you to sort through 10 different possible hands (5 choose 3 is 10) and pick the highest one. There’s quite a few things I’ve left out on purpose that you can try to figure out or wait for me to drop the Level 3 article to find out 🙂

Thanks for reading! Here’s the Source Code.

Further Reading

  • Python Counting Sort Guide and Implementation
  • Create Animations with animation.funcanimation
  • Level 2 Python: Creating Your Own Quiz
  • Build Your Own AI Text Summarizer
  • Neural Network Code in Python

I run this site to help you and others like you find cool projects and practice software skills. If this is helpful for you and you enjoy your ad free site, please help fund this site by donating below! If you can’t donate right now, please think of us next time.

Make a one-time donation

Your contribution is appreciated.

Donate


Make a monthly donation

Your contribution is appreciated.

Donate monthly


Make a yearly donation

Your contribution is appreciated.

Donate yearly

Yujian Tang

In this tutorial, you will learn step-by-step how to implement a poker bot in Python.

Step 1 – Setup Python and Install Packages

First, we need an engine in which we can simulate our poker bot. Install the following package (PyPokerEngine) using pip:

1
pip install PyPokerEngine

It also has a GUI available which can graphically display a game. If you are interested, you can optionally install the following package (PyPokerGUI):

Both the engine and the GUI have excellent tutorials on their GitHub pages in how to use them. The choice for the engine (and/or the GUI) is arbitrary and can be replaced by any engine (and/or GUI) you like. However, the implementation of the bot in this tutorial depends on this choice, so you need to rewrite some if the code if you plan to change the engine (and/or GUI).

Small note on the GUI: it did not work for my directly using Python 3. This fix explains how to make it work.

Step 2 – Implement your Bot!

The first step is to setup the skeleton of the code such that it works. In order to do so, I created three files. One file containing the code for the bot (databloggerbot.py), another file containing the code for a bot which always calls and another file for simulating one game of poker (simulate.py) in which many runs are simulated. The files initially have the following contents:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
from pypokerengine.engine.hand_evaluator import HandEvaluator
from pypokerengine.players import BasePokerPlayer
from pypokerengine.utils.card_utils import _pick_unused_card, _fill_community_card, gen_cards


# Estimate the ratio of winning games given the current state of the game
def estimate_win_rate(nb_simulation, nb_player, hole_card, community_card=None):
 if not community_card: community_card = []

 # Make lists of Card objects out of the list of cards
 community_card = gen_cards(community_card)
 hole_card = gen_cards(hole_card)

 # Estimate the win count by doing a Monte Carlo simulation
 win_count = sum([montecarlo_simulation(nb_player, hole_card, community_card) for _ in range(nb_simulation)])
 return 1.0 * win_count / nb_simulation


def montecarlo_simulation(nb_player, hole_card, community_card):
 # Do a Monte Carlo simulation given the current state of the game by evaluating the hands
 community_card = _fill_community_card(community_card, used_card=hole_card + community_card)
 unused_cards = _pick_unused_card((nb_player - 1) * 2, hole_card + community_card)
 opponents_hole = [unused_cards[2 * i:2 * i + 2] for i in range(nb_player - 1)]
 opponents_score = [HandEvaluator.eval_hand(hole, community_card) for hole in opponents_hole]
 my_score = HandEvaluator.eval_hand(hole_card, community_card)
 return 1 if my_score >= max(opponents_score) else 0


class DataBloggerBot(BasePokerPlayer):
 def __init__(self):
 super().__init__()
 self.wins = 0
 self.losses = 0

 def declare_action(self, valid_actions, hole_card, round_state):
 # Estimate the win rate
 win_rate = estimate_win_rate(100, self.num_players, hole_card, round_state['community_card'])

 # Check whether it is possible to call
 can_call = len([item for item in valid_actions if item['action'] == 'call']) > 0
 if can_call:
 # If so, compute the amount that needs to be called
 call_amount = [item for item in valid_actions if item['action'] == 'call'][0]['amount']
 else:
 call_amount = 0

 amount = None

 # If the win rate is large enough, then raise
 if win_rate > 0.5:
 raise_amount_options = [item for item in valid_actions if item['action'] == 'raise'][0]['amount']
 if win_rate > 0.85:
 # If it is extremely likely to win, then raise as much as possible
 action = 'raise'
 amount = raise_amount_options['max']
 elif win_rate > 0.75:
 # If it is likely to win, then raise by the minimum amount possible
 action = 'raise'
 amount = raise_amount_options['min']
 else:
 # If there is a chance to win, then call
 action = 'call'
 else:
 action = 'call' if can_call and call_amount == 0 else 'fold'

 # Set the amount
 if amount is None:
 items = [item for item in valid_actions if item['action'] == action]
 amount = items[0]['amount']

 return action, amount

 def receive_game_start_message(self, game_info):
 self.num_players = game_info['player_num']

 def receive_round_start_message(self, round_count, hole_card, seats):
 pass

 def receive_street_start_message(self, street, round_state):
 pass

 def receive_game_update_message(self, action, round_state):
 pass

 def receive_round_result_message(self, winners, hand_info, round_state):
 is_winner = self.uuid in [item['uuid'] for item in winners]
 self.wins += int(is_winner)
 self.losses += int(not is_winner)


def setup_ai():
 return DataBloggerBot()

databloggerbot.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
from pypokerengine.players import BasePokerPlayer
import numpy as np
from sklearn.neural_network import MLPRegressor


class CallBot(BasePokerPlayer):
 def declare_action(self, valid_actions, hole_card, round_state):
 actions = [item for item in valid_actions if item['action'] in ['call']]
 return list(np.random.choice(actions).values())

 def receive_game_start_message(self, game_info):
 pass

 def receive_round_start_message(self, round_count, hole_card, seats):
 pass

 def receive_street_start_message(self, street, round_state):
 pass

 def receive_game_update_message(self, action, round_state):
 pass

 def receive_round_result_message(self, winners, hand_info, round_state):
 pass


def setup_ai():
 return CallBot()

callbot.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
from pypokerengine.api.game import start_poker, setup_config

from callbot import CallBot
from databloggerbot import DataBloggerBot
import numpy as np

if __name__ == '__main__':
 blogger_bot = DataBloggerBot()

 # The stack log contains the stacks of the Data Blogger bot after each game (the initial stack is 100)
 stack_log = []
 for round in range(1000):
 p1, p2 = blogger_bot, CallBot()

 config = setup_config(max_round=5, initial_stack=100, small_blind_amount=5)
 config.register_player(name="p1", algorithm=p1)
 config.register_player(name="p2", algorithm=p2)
 game_result = start_poker(config, verbose=0)

 stack_log.append([player['stack'] for player in game_result['players'] if player['uuid'] == blogger_bot.uuid])
 print('Avg. stack:', '%d' % (int(np.mean(stack_log))))

simulate.py

The bot uses Monte Carlo simulations running from a given state. Suppose you start with 2 high cards (two Kings for example), then the chances are high that you will win. The Monte Carlo simulation then simulates a given number of games from that point and evaluates which percentage of games you will win given these cards. If another King shows during the flop, then your chance of winning will increase. The Monte Carlo simulation starting at that point, will yield a higher winning probability since you will win more games on average.

If we run the simulations, you can see that the bot based on Monte Carlo simulations outperforms the always calling bot. If you start with a stack of $100,-, you will on average end with a stack of $120,- (when playing against the always-calling bot).

It is also possible to play against our bot in the GUI. You first need to setup the configuration (as described in the Git repository) and you can then run the following command to start up the GUI:

1
pypokergui serve poker_conf.yaml --port 8000 --speed moderate

Good luck beating the bot!

Conclusion (TL;DR)

In this simple tutorial, we created a bot based on Monte Carlo simulations. In a later blog post, we will implement a more sophisticated Poker bot using different AI methods. If you have any preference for an AI method, please let me know in the comments!

To put it simply, this article will discuss all the ins and outs of developing a computer vision-based poker bot in Python. Developers can refer to the information given below while building bots for routinely testing their web poker platforms. It’s essential mentioning that the codes and libraries necessary for this task are typically Windows-specific.

Is It Possible To Make A Poker Bot?

There’s no denying that ever since online poker platforms started emerging back in the early 2000s, people have been trying hard to find out how to beat a poker bot for greater rewards. Whenever any hardworking grinder took up the mantle of honing their bluffs, others have delegated the grafting almost instantaneously.

This was when poker bots entered the picture, primarily as a form of artificial intelligence. All the founding bright minds decided to use poker bots to profitably “solve” poker.

Creating a Poker Bot on Python

There’s no denying that digital language programming seems like a foreign language to any first-timer when they begin studying it. But then again, with all the resources available on the internet, the process of learning more about programming becomes convenient. Similarly, people can dive back on the internet to find niche resources that explore the basics of creating a bot.

How Do You Set Up A Poker Bot?

Here’s a detailed breakdown of how you set up a poker bot from scratch. You can use the below-listed commands to determine players:

  • Import Pypokerengine
  • From Consoleplayer Import Consoleplayer
  • From Fishplayer Import Fishplayer
  • From Randomplayer Import Randomplayer

Up next, you must enter the code for building a poker cash tournament or game. Eventually, the developer must allow the game to play out and judge the success of their bot. It’s noteworthy that your Artificial Intelligence (AI) won’t function as per satisfaction if you don’t employ any advanced programming.

Are Poker Bots Illegal?

Most people believe that internet poker rooms struggle big time arresting AI. This is primarily since the lack of a qualified security team. Most poker sites are on the hunt for efficient bots. It is essential mentioning that they’ll suspend associated accounts that use programs.

How Do Poker Sites Detect Bots?

There’s no denying that it’s hardly possible for anybody to play poker online across the clock. However, they put a substitution in place of them, i.e., some poker bots. This allows them continuous gameplay until the poker rooms realize. For any first-timer, it’s essential to note that bots can win real cash for the players.

How Much Can You Win With A Bot?

In conclusion, it only fits mentioning that not every poker bot is a winner. There are loads of players who have gone gung-ho with such programs and still lose. And accompanying the problem is that players could face suspensions from poker sites when caught. That’s undoubtedly a bummer- developing or purchasing an AI, only to get banned from the poker sites instead of earning cash.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
def check_combination(cards: list) -> str:
    minimal_value = min(cards)
    if sorted(cards) == list(range(minimal_value, minimal_value + 5)):
        return 'Straight'
    uniques = list(set(cards))
    uniques_length = len(uniques)
    if uniques_length == 1:
        return 'Impossible'
    if uniques_length == 4:
        return 'One Pair'
    if uniques_length == 2:
        if any(filter(lambda x: cards.count(x) == 4, uniques)):
            return 'Four of a Kind'
        else:
            return 'Full House'
    if uniques_length == 3:
        if any(filter(lambda x: cards.count(x) == 3, uniques)):
            return 'Three of a Kind'
        else:
            return 'Two Pairs'
    return 'Nothing'
 
 
assert check_combination([1, 1, 1, 1, 1]) == "Impossible"
assert check_combination([1, 1, 1, 1, 0]) == "Four of a Kind"
assert check_combination([1, 1, 1, 2, 2]) == "Full House"
assert check_combination([1, 2, 3, 4, 5]) == "Straight"
assert check_combination([1, 5, 3, 2, 4]) == "Straight"
assert check_combination([1, 1, 1, 2, 4]) == "Three of a Kind"
assert check_combination([1, 1, 2, 2, 4]) == "Two Pairs"
assert check_combination([1, 1, 2, 3, 4]) == "One Pair"
assert check_combination([1, 9, 2, 3, 4]) == "Nothing"

How to make a poker game in Python?

#poker
print("poker username: ")
name = input("")
print("age: ")
age = input("")

#continue
input("nnPress the [enter key]")

#make random cards by importing
import random

#player cards
print("your cards: ")
card1 = random.randint(1, 12)
card2 = random.randint(1, 12)
player_cards = card1, card2
print(player_cards)

#first table cards
table1 = random.randint(1, 12)
table2 = random.randint(1, 12)
table3 = random.randint(1, 12)
table_full = table1, table2, table3
print("the first table cards are:")
print(table_full)

#bet
print("put in the amount you would like to bet")
bet1 = input("")

#next table card
table4 = random.randint(1, 12)
print("full table is now: ")
table = table1, table2, table3, table4
print(table)

#bet number 2
print("put in the amount you would like to bet")
bet2 = input("")

#next next table card
table5 = random.randint(1, 12)
print("full table is now: ")
table12345 = table1, table2, table3, table4, table5
print(table12345)

#loser or winner?
print("player2 had: ")
card12 = random.randint(1, 12)
card22 = random.randint(1, 12)
player2 = card12, card22
print(player2)

#full layout
print("this is the full table now")
print(player_cards)
print(table12345)
print(player2)

#play again?
play = input("do you want to play again")
if play == "yes":
    exec(open("./pokerface.py").read())
else:
        exit()

First impressions — this code is very clear. I like the variable names — that makes lines like if straight and flush read very naturally.


I don’t think there’s a need to treat a Royal Flush separately — this is the same rank as Straight Flush, just with the largest possible high-card. The «should not occur» comment is irrelevant — no matter how rare, we must correctly score Straight Flush (and we would expect a thorough test set to include some).


Instead of needing a separate tiebreaker function to evaluate the kickers, we could return a tuple from eval_hand, with the kickers following the rank+value. We’re already doing something like that for Full House; it’s easy to extend that throughout. I’d collect values in descending order:

values = sorted([c[0] for c in hand], reverse=True)
straight = (values == range(max(values), min(values)-1, -1)) # but see below

Then we can return as much as is necessary for the rank:

if straight and flush:
    return 8, values[0]
if three_of_a_kind and pair_present: return 6, three_value, pairs[0], values
if flush: return 5, values
if straight: return 4, values[0]
if three_of_a_kind: return 3, three_value, values
if len(pairs) == 2: return 2, pairs, values
if len(pairs) == 1: return 1, pairs[0], values

Counting pairs/trips/quads can be simplified, given that we have the values in sorted order. We can use itertools.groupby() to get the count of identical values, rather than needing to search with values.count():

trips = []
pairs = []
for v, group in itertools.groupby(values):
    count = sum(1 for _ in group)
    if count == 4:
        return 7, v, values
    if count == 3:
        trips.append(v)
    elif count == 2:
        pairs.append(v)

Some additional test cases indicated a few problems:

  • The test for a straight doesn’t work when I compare a list against a range (Python 3.6.5). I needed to materialise it as a list first:

    straight = values == list(range(values[0], values[-1]-1, -1))
    
  • We don’t test for an ace-low straight:

    straight = (values == list(range(values[0], values[0]-5, -1))
                or values == [14, 5, 4, 3, 2])
    
  • Flushes should be comparable — highest differing card still tie-breaks between flushes of different suits.

And some simplifications:

  • Straights and flushes can both be returned before checking for pairs/trips/quads
  • We don’t need boolean flags to say that three_value or pairs is populated — we can directly test those variables are truthy or not.
  • For ranks 0, 1, 2, the rank is exactly the number of pairs found.
  • Instead of try/except, we can populate value_dict with the digits 2 to 9.
  • We’re not required to find anything other than the number of Player 1 wins, so remove the code that was useful while debugging.

Applying the above, I get the following modified code:

import itertools

value_dict = {'T': 10, 'J': 11, 'Q': 12, 'K': 13, 'A': 14}
value_dict.update((str(x), x) for x in range(2,10))

def eval_hand(hand):
    # Return ranking followed by tie-break information.
    # 8. Straight Flush
    # 7. Four of a Kind
    # 6. Full House
    # 5. Flush
    # 4. Straight
    # 3. Three of a Kind
    # 2. Two pair
    # 1. One pair
    # 0. High card

    values = sorted([c[0] for c in hand], reverse=True)
    suits = [c[1] for c in hand]
    straight = (values == list(range(values[0], values[0]-5, -1))
                or values == [14, 5, 4, 3, 2])
    flush = all(s == suits[0] for s in suits)

    if straight and flush: return 8, values[1]
    if flush: return 5, values
    if straight: return 4, values[1]

    trips = []
    pairs = []
    for v, group in itertools.groupby(values):
        count = sum(1 for _ in group)
        if count == 4: return 7, v, values
        elif count == 3: trips.append(v)
        elif count == 2: pairs.append(v)

    if trips: return (6 if pairs else 3), trips, pairs, values
    return len(pairs), pairs, values


player1_wins = 0
with open("p054_poker.txt") as f:
    for line in f:
        cards = [(value_dict[x[0]], x[1]) for x in line.split(' ')]
        player1_wins += eval_hand(cards[:5]) > eval_hand(cards[5:])

print(player1_wins)

Понравилась статья? Поделить с друзьями:
  • Как написать показатель степени на клавиатуре
  • Как написать показания счетчиков электроэнергии
  • Как написать пока что нет
  • Как написать пока не знаю
  • Как написать пойдемте