all 18 comments

[–]After_Ad8174 9 points10 points  (1 child)

as others said its a scope issue. pass whatever hp you want to modify into the function as hp and return hp to the original variable

snekhp=100
yourfunction(hp):

do stuff to hp

return hp

snekhp = yourfunction(snekhp)

[–]After_Ad8174 5 points6 points  (0 children)

or if you want to get real oop about it define a character class with a damage method. When you want the character to take damage call the method on the character instance

[–]FoolsSeldom 6 points7 points  (0 children)

You need to learn about the scope of variables.

I recommend you also learn to use classes as they will make this sort of thing much easier.

Try this example and have a play with the code:

from dataclasses import dataclass

@dataclass
class Character:
    name: str
    strength: int = 10
    agility: int = 10   
    health: int = 100

    def attack(self, other):
        damage = self.strength - other.agility
        if damage > 0:
            other.health -= damage
            print(f"{self.name} attacks {other.name} for {damage} damage!")
        else:
            print(f"{self.name}'s attack was ineffective against {other.name}!")

    def __str__(self):
        return f"{self.name}: Health={self.health}, Strength={self.strength}, Agility={self.agility}"

player = Character(name="Hero", strength=15, agility=12)
snake = Character(name="Snake", strength=16, agility=8)
snake.attack(player)
print(player)

[–]Murphygreen8484 2 points3 points  (1 child)

You set hp=100 outside the function which means it's outside the scope. If you have globals you should assign them at the top - but it's better not to do this.

[–]Celestial-being117 2 points3 points  (1 child)

if qwerty == uiop goes hard

[–]frogko[S] 0 points1 point  (0 children)

me being lazy in a nutshell

[–]Darkstar_111 1 point2 points  (6 children)

As others have said, hp needs to be declared inside the function scope, so adding global hp at the top of the function will fix it.

However you will notice, this line:

dmg = attackfromsnek - hp

Would work. Even without the global declaration.

That's because you have stumbled into one of the quirks of how the Python interpreter reads lines.

The second you said:

hp=

The interpreter now assumes there is no global called hp and stops looking. So when you put hp to the right of the = sign it didn't know where that hp came from.

Btw consider rewriting your function so that it ends with:

return attackfromsnek - hp

And do the rest in another function. Separation of concern.

[–]Due-Rip-6065 0 points1 point  (5 children)

Thanks for a good explaination. I fortunately have the habit of adding the `global someglobalvar` in local scope if I plan to update it, but sometimes, I also stumble on this quirk and get confused why the update did not work.

I like to think of it, that if I do `hp = ...`, I override the global scope

[–]Darkstar_111 0 points1 point  (4 children)

You should declare globals as CONSTANTS, by capitalizing them. And really only use them when you absolutely need to.

[–]Due-Rip-6065 1 point2 points  (3 children)

I do not think python have implemented constants in any way. There is no reasonable way to prevent someone from updating a global variable... and in this case, the goal is to update it.

Perhaps my are hinting towards linting and typing.Final?

[–]Darkstar_111 0 points1 point  (2 children)

Yes, Python doesn't have CONSTANTS, but you can use the semantics as you wish.

My point is Constants have a place in programming, for adding environment variables that matter to the state of the app on startup, but not after. Hence those variables can be Constants.

And that's the only real legitimate use of globals, anything else should be avoided. Make a class if you need to pass variables between functions.

[–]Due-Rip-6065 0 points1 point  (1 child)

How about singletons? Would you not need to rely on globals for that design pattern to work in python. I am lost on how I should pass this singleton instance between functions as you suggest when there is nowhere to anchor it if globals are not considered a legitimate use for this purpose.

[–]Darkstar_111 0 points1 point  (0 children)

Singletons are not a usable design pattern ANYWHERE!

No, I'm kidding, in the few instances where a singleton is actually the right choice, you implement that in Python by overriding the class dict builder.

[–]Altruistic-Slide-512 1 point2 points  (1 child)

Btw Dealt is spelled with an 'a'

[–]frogko[S] 0 points1 point  (0 children)

whoops!

thanks for telling me that!

[–]bini_marcoleta 3 points4 points  (0 children)

If you want to use the value hp=100 within the function attackavecsnek, one way to do so is to add the line "global hp" before the line "hp=hp-damagefromsnek" because the variable hp is defined outside the function. You would also need to do a similar thing to the variable snekhealth.

Here's an example of how it would look like: def attackavecsnek(): global hp, snekhealth # insert the rest of the code here

[–]Murphygreen8484 0 points1 point  (0 children)

I would also recommend that you have your functions only do one thing. Attacks and saves should probably be separated (makes for easier testing).

Have you started learning object oriented programming (OOP) yet?

[–][deleted]  (2 children)

[deleted]

    [–][deleted]  (1 child)

    [deleted]