0

Im working on a simple poker game just to improve my OOP experience, i ran into an error that might be beyond my knowledge.

The program goes like this, i have a class called Deck() which is of course the deck, a class called player and a class called table. In the player class i have couple of methods but i'm only gonna name what is necessary for the sake of keeping this as short as possible. I have the following methods (in the player class) bet(), call() fold(), all_in() and player_choice(). The first four method i named are all invoked by the player_choice method(). However the problem is in the bet(), all_in() and call method. the following methods looks like this

        def all_in(self):
    table.table_money += self.money
    self.money = 0
    print('{} went all in!').format(self.name)

def cal(self, last_bet):
    if last_bet > self.money:
        while True:
            res = input('You dont have enough money to call.\tyou have=> {}\nDo you want to go all in?\ty/n\n>>> ').format(str(self.money))
            if res.lower() == 'y':
                self.all_in()
                break
            elif res.lower() == 'n':
                self.fold()
                break
            else:
                print('Invalid input. Try again...')
    else:
        table.table_money += self.money - last_bet
        self.money -= last_bet
        print('{} called.').format(self.name)


def bet(self, last_bet):
    res = int(input('Enter bet below.\t must be over {}\n>>> '.format(str(last_bet))))
    table.latest_bet += res
    table.table_money += res
    self.money -= res
    print('{} has bet {}$').format(self.name, str(res))

The problem is that when i call one of these methods and the method is in the process of subtracting the players money and adding it to the table.table_money() (as shown in the code above) thats when i get a NameError saying 'table' is not defined.

here is the Table() class:

    class Table():
def __init__(self):
    self.table_money = 0
    self.latest_bet = 0

    if players == '':
        print('Table is empty!')
    else:
        print(str(len(players)) + ' players on the table.')

def list_table(self):
    for i in players:
        print(i.__str__())

I know what you might be thinking that i typed table instead of Table. but he is he thing, when i run the code in the main() function i initialize a Table object into a variable called table which is supposed to be the same variable as the one being called by the Player() class methods.

Here is a short view of the main() function:

    def main():
while welcome():
    rond = 1
    while rond <= 5:
        table = Table()
        deck = Deck()
        deck.deal()
        user = players[0]
        user.list_hand()
        user.player_choice(table.latest_bet)
        break
    break

the structure of the problem is like this:

  1. first i define the player class.
  2. 2nd i define the table.
  3. 3rd i define main().

This is the output of the error:

    Traceback (most recent call last):
    File "C:/Users/Alex/PycharmProjects/GUI_prject/venv/Lib/site- 
    packages/resors2.py", line 161, in <module>
    main()
    File "C:/Users/Alex/PycharmProjects/GUI_prject/venv/Lib/site- 
    packages/resors2.py", line 157, in main
    user.player_choice(table.latest_bet)
    File "C:/Users/Alex/PycharmProjects/GUI_prject/venv/Lib/site- 
    packages/resors2.py", line 38, in player_choice
    self.cal(last_bet)
    File "C:/Users/Alex/PycharmProjects/GUI_prject/venv/Lib/site- 
    packages/resors2.py", line 71, in cal
    table.table_money += self.money - last_bet
    NameError: name 'table' is not defined

If i didn't include enough details about the program let me know i will share more if needed. I apologize if i didn't explain all this in the best way and if the post is too long. I am more then grateful for any comment. Thanks for reading.

Full code:

    import random as r

    suits = ['H','C','S','D']
    values = ['A','2','3','4','5','6','7','8','9','10','J','Q','K']
    players = []

    class Card():
        def __init__(self, suit, value):
            self.suit = suit
            self.value = value

        def valu(self):
            return self.value + self.suit

    class Player():
        def __init__(self, name, money):
            global players
            self.name = name
            self.money = money
            print(self.name+ ' joined the table!')
            players.append(self)
            self.hand = []

        def __str__(self):
            return '{}: {}'.format(self.name, str(self.money))

        def add_to_hand(self, cards):
            self.hand.append(cards)

        def list_hand(self):
            for i in self.hand:
                print(i)

        def player_choice(self, last_bet):
            while True:
                resu = input('c - Call | b - bet | a - all in | f - fold\n>>> 
    ').lower()
            if resu == 'c':
                self.cal(last_bet)
                break
            elif resu == 'b':
                self.bet(last_bet)
                break
            elif resu == 'a':
                self.all_in()
                break
            elif resu == 'f':
                self.fold()
                break
            else:
                print('Invalid input. Try again...')


        def all_in(self):
            table.table_money += self.money
            self.money = 0
            print('{} went all in!').format(self.name)

        def cal(self, last_bet):
            if last_bet > self.money:
                while True:
                    res = input('You dont have enough money to call.\tyou have=> {}\nDo you want to go all in?\ty/n\n>>> ').format(str(self.money))
                    if res.lower() == 'y':
                    self.all_in()
                    break
                    elif res.lower() == 'n':
                    self.fold()
                    break
            else:
                print('Invalid input. Try again...')
        else:
            table.table_money += self.money - last_bet
            self.money -= last_bet
            print('{} called.').format(self.name)


    def bet(self, last_bet):
        res = int(input('Enter bet below.\t must be over {}\n>>> '.format(str(last_bet))))
        table.latest_bet += res
        table.table_money += res
        self.money -= res
        print('{} has bet {}$').format(self.name, str(res))

    def fold(self):
        players.remove(self)
        print('{} has folded.').format(self.name)


    class Table():
        def __init__(self):
            self.table_money = 0
            self.latest_bet = 0

            if players == '':
                print('Table is empty!')
            else:
                print(str(len(players)) + ' players on the table.')

        def list_table(self):
            for i in players:
            print(i.__str__())




    class Deck():
        def __init__(self):
            self.cards = []

            for suit in suits:
                for value in values:
                   self.cards.append(Card(suit, value).valu())

            r.shuffle(self.cards)

        def show_deck(self):
            return self.cards

        def shuffle_d(self):
            r.shuffle(self.cards)

        def deal(self):
            for p in players:
                for c in range(0, 1):
                    p.add_to_hand((self.cards.pop(), self.cards.pop()))

    #The welcome function is not a method for any of the classes above 

    def welcome():
        global players
print('''
        Welcome to the poker table. 
        q - Quit
        s - Take a seat
''')
res = ''
while res != 'q' or 's':
    res = input('>>> ')
    if res == 'q':
        return False
    elif res == 's':
        name = input('Enter your name: ')
        money = int(input('Enter how much money you wish to have(max 500$): '))
        Player(name, money)
        return True
    else:
        print('Invalid input. q - Quit\ts - Take a seat')



    def main():
        while welcome():
        rond = 1
            while rond <= 5:
                table = Table()
                deck = Deck()
                deck.deal()
                user = players[0]
                user.list_hand()
                user.player_choice(table.latest_bet)
                break
            break

    main()

Try to ignore the miss

  • Can you put the full code at the bottom? – Alec May 02 '19 at 02:55
  • Please fix your code indentation. Why do you have the first line of each snippet indented extra? – Barmar May 02 '19 at 03:00
  • Yeah i apologize @Barmar this is my second post on stackoverflow and im still getting used to it, the code glitched when i pasted it in, i did edit it manually though. – Henry_physics_42 May 02 '19 at 03:14
  • "table" is local to main; it doesn't exist in the context of player methods. Make it global or pass it in. Also, "call" has 2 Ls, and "table.table_money += self.money - last_bet" is clearly wrong. I have $100, the bet to me is $5, so I put $95 in the pot? – Lee Daniel Crocker May 02 '19 at 18:48

2 Answers2

1

tables is a local variable in the main() function. You should add it as an attribute of the player class.

def go_to_table(self, table):
    self.table = table

Then all the methods should use self.table instead of just table. In main, you do:

def main():
    while welcome():
        rond = 1
        while rond <= 5:
            table = Table()
            deck = Deck()
            deck.deal()
            user = players[0]
            user.go_to_table(table)
            user.list_hand()
            user.player_choice(table.latest_bet)
            break
        break
Barmar
  • 741,623
  • 53
  • 500
  • 612
0

You're confusion a type (like Table) with a single instance of an object of that type like table after table = Table().

The line table = Table() creates a new object of type Table and assigns it to the variable table, so you can refer to it later. However, this variable is defined inside of the function main and is only available there. Inside of the method cal (which I assume is a misspelling of call), there is no table, since you might have many games going on and it doesn't know what table it belongs to.

Since the player is sitting at a specific table, it makes sense to keep a reference to that Table inside the Player, and to assign it in its constructor with something like self.table = table. Then you can reference it from the call method using self.table.

class Player:
    def __init__(self, table):
        self.table = table

    def call(self):
        self.table.money += 1


class Table:
    def __init__(self):
        self.money = 0


table = Table()
player = Player(table)
player.call()
print(table.money)
Grismar
  • 27,561
  • 4
  • 31
  • 54
  • right, i understand, thank you for the help. btw cal isnt misspelled i just didnt want to overwrite the built-in function call :D – Henry_physics_42 May 02 '19 at 03:19
  • Perhaps you're using a library that gives you a function named `call`, but `call` is not actually a built-in for Python - here's a complete list https://docs.python.org/3/library/functions.html - it *is* a very good motivation, to avoid built-ins, by the way. Normally however, I wouldn't recommend using an alternative spelling, since this is something other developers will have to guess at later (your future you included). Instead, consider something safe that will always work, like `play_call`, `play_check`, etc. – Grismar May 02 '19 at 03:24
  • you're right, i'm new to programming, thanks for the tip. – Henry_physics_42 May 02 '19 at 03:30
  • A common convention is a trailing underscore: call_, if_, and_, etc. – Lee Daniel Crocker May 02 '19 at 18:51