2

I am trying to work on a text adventure to help keep my interest while trying to learn the concepts and nuances of Python. I originally followed along to a YouTube tutorial (6 part series, part 1 link provided: https://www.youtube.com/watch?v=MFW8DJ6qsak).

I created the player class as shown:

class Player:
    def __init__(self):
        self.name = ''
        self.jobclass = ''
        self.currenthp = 0
        self.totalhp = 0
        self.currentmp = 0
        self.totalmp = 0
        self.physical_damage = 0
        self.physical_defense = 0
        self.magic_attack = 0
        self.magic_defense = 0
        self.speed = 0
        self.luck = 0
        self.status_effect = []
        self.location ='b2'
        self.game_over = False

myPlayer = Player()

My current issue is trying to assign the player certain stats based on their chosen character job i.e.:

def setup_game():
    ...
    player_jobclass = input("> ")
    myPlayer.jobclass = player_jobclass
    valid_jobs = ['warrior', 'mage', 'thief', 'cleric']
    while player_jobclass.lower() not in valid_jobs:
        print("Please choose a valid class")
        player_jobclass = input("> ")
    if player_jobclass.lower() in valid_jobs:
            myPlayer.jobclass = player_jobclass
            print("Ah, the " +player_jobclass.lower()+ ". Fine choice!\n")

    #Class Starting Stats
    if myPlayer.jobclass is 'warrior':
        self.currenthp = 20
        self.totalhp = 20
        self.currentmp = 10
        self.totalmp = 10
        self.physical_damage = 10
        self.physical_defense = 10
        self.magic_attack = 2
        self.magic_defense = 3
        self.speed = 4
        self.luck = 4
        self.location = 'd1'
    elif myPlayer.jobclass is 'mage':
        self.currenthp = 10
        self.totalhp = 10
        self.currentmp = 20
        self.totalmp = 20
        self.physical_damage = 2
        self.physical_defense = 3
        self.magic_attack = 10
        self.magic_defense = 7
        self.speed = 7
        self.luck = 3
        self.location = 'a1'
    ...
    main_game_loop()

Because after this all runs, I get into the game fine, and all my movements and little actions work fine, however if I try to print the player "stats" via something like:

def show_stats():
hpmpadarmPrint = ("" + str(myPlayer.currenthp) + "/" + str(myPlayer.totalhp) + " hp " + str(myPlayer.currentmp) + "/" + str(myPlayer.totalmp) + " mp " + str(myPlayer.physical_damage) + " ATK " + str(myPlayer.physical_defense) + " ARM \n")
mgclckspdPrint = ("" + str(myPlayer.magic_attack) + " AP " + str(myPlayer.magic_defense) + " MR " + str(myPlayer.speed) + " SPD " + str(myPlayer.luck) + " LCK \n")

All that prints is:
0/0 hp 0/0 mp 0 ATK 0 ARM 0 AP 0 MR 0 SPD 0 LCK

I can tell there is some larger concept that is eluding me as far as assigning the values as even the self.location = 'b2' MUST be there or the game won't run as myPlayer is not actually being assigned the values I believe it should. This also prevents my change_text_speed() function from working and also ... you get it.

Guess main question would be: how to keep the new values once assigned?

Mureinik
  • 297,002
  • 52
  • 306
  • 350
Chris
  • 23
  • 1
  • 5
  • 1
    Read about inheritance. Also, I think the stats should be set in the `__init__` method. – Brian Jul 29 '18 at 06:51
  • 1
    Don't compare strings with `is`. Use `==`. – Aran-Fey Jul 29 '18 at 06:56
  • 4
    It's very hard to understand what is going on with your `setup_game` function. Where does the `self` come from? In any event, your immediate issue likely stems from comparing strings with `is` instead of `==`. Don't do that. `is` is for identity, `==` is for equality. You cannot guarantee that equal strings will be identical strings, i.e. the *same* string object. – juanpa.arrivillaga Jul 29 '18 at 06:57
  • Also, inheritance is an option here. But don't think it's the only option. – juanpa.arrivillaga Jul 29 '18 at 06:59
  • Thank you for the clarification for `is` vs `==`. The `self` is how the (now I'm guessing not as good as I once thought) tutorial had it based on the initial `__init__(self)` – Chris Jul 29 '18 at 07:03
  • `self` is the (conventional) name of the class instance that's used _inside_ the methods of the class. But it doesn't have any relevance outside the class definition. So when code outside the `Player` definition wants to access the attributes (including methods) of the `myPlayer` class instance it needs to use `myPlayer` not `self`. – PM 2Ring Jul 29 '18 at 07:11
  • Style guide (aka formatting): https://www.python.org/dev/peps/pep-0008/ – Patrick Artner Jul 29 '18 at 07:20
  • @Chris right... `self` is usually the first parameter of a *method*, but in your function signature, it defines no parameters, so `self` would be undefined. Note, no errors are being thrown because that code is never reached because of the issues with `is`/`==` – juanpa.arrivillaga Jul 29 '18 at 07:34

2 Answers2

3

self and myPlayer are two different objects. There are two fixes you could make. First, replace self with myPlayer when setting the stats.

if myPlayer.jobclass is 'warrior':
    myPlayer.currenthp = 20
    myPlayer.totalhp = 20
    myPlayer.currentmp = 10
    ...

The second and in my option, better approach is to set the stats in __init__. It would look something like this.

if self.jobclass is 'warrior':
    self.currenthp = 20
    self.totalhp = 20
    self.currentmp = 10
    ...

To make the code even better, read about inheritance and make a class for each jobclass. You called it job class after all.

Brian
  • 823
  • 6
  • 14
1

is checks if two variables point to the exact same object. In cases like your's, when inputting a user strings, you'll most probably have two different string objects with the same value. E.g.:

>>> x = input("")
ab
>>> x
'ab'
>>> x == "ab"
True
>>> x is "ab"
False

To make a long story short - use ==, not is when you check the players jobClass.

Mureinik
  • 297,002
  • 52
  • 306
  • 350