Here is my code I am trying to run
# -*- coding: utf-8 -*-
import pydealer
from pokerlib import HandParser
from pokerlib.enums import Value, Suit
class Player:
def __init__(self, name: str, chips=500):
self.name = name
self.hand = pydealer.Stack()
self.fold = False
self.matching_pot = True
self.hand_rank = None
if name == "AI":
self.chips = 500
else:
self.chips = chips
def __str__(self):
return self.name
class PokerGame:
def __init__(self, players):
self.deck = pydealer.Deck()
self.discard_pile = pydealer.Stack()
self.table = pydealer.Stack()
self.players = players
self.pot = 0
"""
TLDR: (bet_pot=starting ante) --> pots right --> (pot=bet_pot) and bet_pot is reset --> someone raises -->repeat
Pot and bet pot work as described, pot starts at zero and bet_pot has the initial buy in, the betting round and
pots right make sure that players either fold or match, at the end of that round, then bet_pot is transferred to
pot and cleared for the next round. Bet_pot is updated only when players raise and at the beginning.
In addition, when a player matches his chips go to the pot not bet_pot.
"""
self.bet_pot = 0 # Add starting bet
self.stage = 0
self.stage_dict = {
0: "Pre-flop",
1: "Post-flop/Pre-turn",
2: "Post-turn/Pre-river",
3: "Post-river/Final Betting round",
}
print("Created a game with {} players.".format(len(self.players)))
def poker(self):
self.deck.shuffle()
self.deal()
self.flop()
self.turn()
self.river()
self.rank_hands()
self.award_pot()
def deal(self):
for player in self.players:
new_card = self.deck.deal(2)
player.hand.add(new_card)
def flop(self):
self.discard_pile = self.deck.deal(1)
self.table = self.deck.deal(3)
self.stage += 1
print("The flop is\n", self.table, "\n")
def turn(self):
self.discard_pile = self.deck.deal(1)
turn_card = self.deck.deal(1)
self.table += turn_card
self.stage += 1
print("The turn adds\n", turn_card)
print("The table is\n", self.table, "\n")
def river(self):
self.discard_pile = self.deck.deal(1)
river_card = self.deck.deal(1)
self.table += river_card
self.stage += 1
print("The river adds\n", river_card)
print("The table is\n", self.table, "\n")
def convert_cards(self, convert_what, player=None):
values = {2: Value.TWO, 3: Value.THREE, 4: Value.FOUR, 5: Value.FIVE, 6: Value.SIX, 7: Value.SEVEN,
8: Value.EIGHT, 9: Value.NINE, 10: Value.TEN, "Jack": Value.JACK, "Queen": Value.QUEEN,
"King": Value.KING, "Ace": Value.ACE}
suits = {"Hearts": Suit.HEART, "Spades": Suit.SPADE, "Diamonds": Suit.DIAMOND, "Clubs": Suit.CLUB}
if convert_what == "hand":
stack = player.hand
elif convert_what == "table":
stack = self.table
else:
raise Exception("In Convert_cards, convert_what is either empty, or is an invalid option(Not hand or table")
converted_cards = []
for card in stack:
card = str(card)
temp_list = ["value", "suit"]
for value in values.keys():
if card.find(str(value)) == -1:
continue
else:
temp_list[0] = values[value]
break
for suit in suits.keys():
if card.find(suit) == -1:
continue
else:
temp_list[1] = suits[suit]
break
temp_list = tuple(temp_list)
converted_cards.append(temp_list)
return converted_cards
def rank_hands(self):
for player in self.players:
cards_to_rank = list(self.convert_cards("hand", player)) + list(self.convert_cards("table"))
player.hand_rank = HandParser(cards_to_rank)
def find_winner(self):
winning_hand = HandParser([(Value.TWO, Suit.HEART)]) # Might need object to compare - I would try None
winning_hand.parse()
temp_winner = []
dual_winners = False
for player in self.players:
player.hand_rank.parse()
if player.hand_rank > winning_hand:
winning_hand = player.hand
temp_winner.append(player)
print(player.hand_rank.handenum)
elif player.hand_rank == winning_hand:
dual_winners = True
print(player.hand_rank.handenum)
winner = temp_winner
return winner, winning_hand, dual_winners
def award_pot(self):
winner, winning_hand, dual_winners = self.find_winner()
if dual_winners:
winnings = self.pot / 2
winner[0].chips = winnings
winner[1].chips = winnings
print(f"The winners are {winner[0]}, and {winner[1]} with {winning_hand}. They each win {winnings}")
quit()
else:
winner[0].chips = self.pot
print(f"The winner is {winner}, who won the pot of {self.pot} with {winning_hand}")
quit()
class PokerAi(PokerGame):
def __init__(self, name):
super().__init__(name)
def ai_poker(self):
self.poker()
if __name__ == "__main__":
game_type = "ai" # Defaults
user_name = "default_name"
if game_type == "ai":
game = PokerAi([Player(user_name, 600), Player("AI")]) # Ai player index is 1
game.ai_poker()
And after inputing nothing(by pressing return) until the end, I get the error:
Traceback (most recent call last):
File "/Users/jchampeau/PycharmProjects/CP2-Final-Project/main.py", line 319, in <module>
game.ai_poker()
File "/Users/jchampeau/PycharmProjects/CP2-Final-Project/main.py", line 306, in ai_poker
self.poker()
File "/Users/jchampeau/PycharmProjects/CP2-Final-Project/main.py", line 63, in poker
self.award_pot()
File "/Users/jchampeau/PycharmProjects/CP2-Final-Project/main.py", line 270, in award_pot
winner, winning_hand, dual_winners = self.find_winner()
File "/Users/jchampeau/PycharmProjects/CP2-Final-Project/main.py", line 259, in find_winner
if player.hand_rank > winning_hand:
File "/Users/jchampeau/Library/Python/3.8/lib/python/site-packages/pokerlib/_handparser.py", line 69, in __gt__
if self.handenum != other.handenum:
AttributeError: 'Stack' object has no attribute 'handenum'
Based on my understanding of the error, the function is receiving the wrong class/object which I don't know why it is happening. Which is interesting because the if statement works because I can see the handenum of the winning hand.
I have tried debugging it but the variable look fine in the debugger and the code prints the print(player.handenums)
I am not expecting to get an error, instead I am expecting the code to run/move on to and display the award pot print statements.
I believe this is your problem.
class Player:
def __init__(self, name: str, chips=500):
self.name = name
self.hand = pydealer.Stack()
...
class PokerGame:
...
def find_winner(self):
winning_hand = HandParser([(Value.TWO, Suit.HEART)])
...
for player in self.players:
...
if player.hand_rank > winning_hand:
winning_hand = player.hand
winning_hand
and player.hand_rank
both start as HandParser
objects.
But then inside the loop, when player.hand_rank > winning_hand
is true, winning_hand
is reassigned to player.hand
, which is a Stack
object.
So on the next loop iteration, you try to compare a HandParser
object to a Stack
object, and you get the error.