0

(For those who saw this question the last time I asked it, I sincerely apologize, I used the term "module" when I meant "function", but thank you for your very helpful advice nontheless! I'll make sure to keep it in mind when I begin to add other files into the equation.)

I'm trying to make a text based adventure game using python, and as a result it requires a lot of variables, and as backtracking is a must, I need to use global variables for the essential ones. I have run into speed bumps when trying to get these to be read by other functions. This is the line of code used to define the universal variables, and their starting value

def reset():
    global gold, exp, etnl, maxHP, curHP, maxmana, curmana, attack, defence, helm, armtop, armbot, boots, gloves, weapons
    gold = 0
    exp = 0
    etnl = 100 #exp to next level
    maxHP = 50
    curHP = 50
    maxmana = 10
    curmana = 10
    attack = 5
    defence = 5
    helm = "none"
    armtop = "none"
    armbot = "none"
    boots = "none" 
    gloves = "none"
    weapon = "fists"

And for example, when I try to display one of the global variables, it shows up as the variable being undefined, as shown here:

def gamestart():
    clear() #this command is fine, simply to make it look neater when it is run again
    print("you wake up in a clearing in the forest, you can't remember what happened.")
    print("you feel numb, you realize you're lying flat on your back.")
    print
    print("HP " + str(curHP) + "/" + str(maxHP))

Can someone help me out with this? Is there an easier way to do this? All help is appreciated! (yes, I make sure to run the reset function before the newgame function)

A much simpler version if this, at least according to me is:

def variable():
    global foo
    foo = 7

def trigger():
    variable():
    output():

def output():
    print(foo)
  • 2
    Can you create a [mcve]? i.e. a block of code that we can copy and paste to reproduce the error – DavidG Sep 27 '18 at 15:57
  • 1
    First, you don't need separate `global` statements in `reset`; you can write `global gold, exp, etnal, ...` – chepner Sep 27 '18 at 15:59
  • Have you called `reset` (or otherwise set the values of `curHP` and `maxHP`) before you call `gamestart`? Do you have more than one module involved? (Global variables aren't truly global; they are local to a module.) This is why we need a minimal, complete, and verifiable example to reproduce your error. – chepner Sep 27 '18 at 16:00
  • no, all the coding is in one file, and the reset function is triggered before the gamestart one – Bearded Pancake Sep 27 '18 at 16:03
  • there, I hope this helps you guys – Bearded Pancake Sep 27 '18 at 16:14
  • Note: *reset* function looks awful, you might want to group global declarations like `global a, b, c, .....` – CristiFati Sep 27 '18 at 16:15
  • Your simplified example works fine, assuming you call `trigger` first after defining the three functions (and ignoring the trailing `:`s in the definition of `trigger`). You still haven't provided a concrete example that reproduces the error you are getting. – chepner Sep 27 '18 at 16:22

3 Answers3

0

Here is a simple example of what I think you are trying to accomplish. If you are using global variables, then you need to be sure you are not inadvertently creating local variables with the same names in your functions (when you mean to be modifying the global variable).

You should look at using classes which I think would help you with some of the semantic confusion here.

value = 10

def reset():
    global value
    value = 10

def start():
    print(f'initial value: {value}')
    global value
    value += 1
    print(f'updated value: {value}')
    reset()
    print(f'reset value: {value}')

start()

# OUTPUT
# initial value: 10
# updated value: 11
# reset value: 10
benvc
  • 14,448
  • 4
  • 33
  • 54
0

You could store those things into a class used as storage-container. If you declare them classvariables and any accessors as @classmethods you do not need an instance.

class GameState:
    gold = 0
    exp = 0
    etnl = 100 #exp to next level
    maxHP = 50
    curHP = 50
    maxmana = 10
    curmana = 10
    helm = "none"
    armtop = "none"
    armbot = "none"
    boots = "none"
    gloves = "none"
    weapon = "fists"

    weapons = {"fists":(5,5),"sword":(15,12),"mace":(30,3),"cushion":(2,20)}

    @classmethod
    def reset(cls):
        cls.gold = 0
        cls.exp = 0
        cls.etnl = 100 #exp to next level
        cls.maxHP = 50
        cls.curHP = 50
        cls.maxmana = 10
        cls.curmana = 10
        cls.helm = "none"
        cls.armtop = "none"
        cls.armbot = "none"
        cls.boots = "none"
        cls.gloves = "none"
        cls.weapon = "fists"

    @classmethod
    def attack(cls):
        return cls.weapons.get(cls.weapon,(0,0))[0]

    @classmethod
    def defense(cls):         
        return cls.weapons.get(cls.weapon,(0,0))[1]


for w in State.weapons:
    State.weapon = w
    print("{} has attack {} and defense {}.".format(w, State.attack(),State.defense()))

Output:

fists has attack 5 and defense 5.
sword has attack 15 and defense 12.
mace has attack 30 and defense 3.
cushion has attack 2 and defense 20.

You might want to seperate some things out - f.e. an extra class for the weapon/damage/defense related stuff ...

More reading:

Patrick Artner
  • 50,409
  • 9
  • 43
  • 69
0

Instead of global variables have you considered storing all the stats in a class/struct? Create an instance of the class at the start of the game, with its default values being specified in the constructor.

G = StartClass()

def gamestart():       
    print("you wake up in a clearing in the forest, you can't remember what happened.")
    print("you feel numb, you realize you're lying flat on your back.")
    print("HP " + str(G.curHP) + "/" + str(G.maxHP))

Alternatively, declaring G globally and passing it into gamestart(G) and/or re-instantiating in the reset() function might be options.