1

So i am making a small game with damage and the terminal always gets printed "Nukupana does 0 damage" Any idea why this would be? Here is the code:

Strength = 5
Magic = 5
Speed = 5
Lifeforce =5
base_health = Lifeforce *10 +50
damage_done=0
curent_health = base_health - damage_done
##functions for stuff
def glacius():
  magic_damage = 5 * random.randint(1,5)
  damage_done = magic_damage
def nukapana_moves():
  moves = ["Glacius"]
  attack = random.choice(moves)
  if attack == "Glacius" :
    glacius()
  print(f"nukapana uses {attack} it does {damage_done}.")
chris
  • 21
  • 3

1 Answers1

1

In your glacius function, damage_done is a local variable. The damage_done in global namespace doesn't see the change unless you use the global keyword in the glacius function to tell Python damage_done should be global:

import random

Strength = 5
Magic = 5
Speed = 5
Lifeforce = 5
base_health = Lifeforce * 10 + 50
damage_done = 0
curent_health = base_health - damage_done


##functions for stuff
def glacius():
    global damage_done   # <----  here
    magic_damage = 5 * random.randint(1, 5)
    damage_done = magic_damage


def nukapana_moves():
    moves = ["Glacius"]
    attack = random.choice(moves)
    if attack == "Glacius":
        glacius()
    print(f"nukapana uses {attack} it does {damage_done}.")


nukapana_moves()

note: Often depending on global variables considered a bad practice. Instead you should free your code from depending on a global variable by returning values from functions. Functions should do their jobs independently.

Re-implementation using class:

import random

class Hero:
    def __init__(self):
        self.strength = 5
        self.magic = 5
        self.speed = 5
        self.lifeforce = 5
        self.base_health = self.lifeforce * 10 + 50
        self.damage_done = 0

    @property
    def current_health(self):
        return self.base_health - self.damage_done

    def glacius(self):
        self.damage_done = 5 * random.randint(1, 5)

    def nukapana_moves(self, moves):
        attack = random.choice(moves)
        if attack == "Glacius":
            self.glacius()
            print(f"nukapana uses {attack} it does {self.damage_done}.")


player = Hero()
print(player.current_health)
player.nukapana_moves(['Glacius'])
print(player.current_health)

output:

100
nukapana uses Glacius it does 25.
75

note: When you hit damage you need to re-calculate the current_health, Or as I've done here use a property that gives you the correct value. Otherwise you hit damage but the self.current_health doesn't change because it calculated once in the initializer.

S.B
  • 13,077
  • 10
  • 22
  • 49
  • Why, oh why would you recommend that? The right course of action here is to simply return the value from the function and use it when calling the function. There is no real reason to use globals here and it should generally be avoided – Tomerikoo Jan 27 '22 at 14:21
  • @Tomerikoo You're right I should have pointed that it's a bad practice(edited). But OP really wanted to know *why* he/she gets always the same result every time, what is the possible fix to it. Why the random doesn't affect here. The reason is what I said in my answer. I didn't do anything wrong except not telling the better way. – S.B Jan 27 '22 at 14:30
  • I didn't say you did anything wrong... – Tomerikoo Jan 27 '22 at 14:43
  • @Tomerikoo if you do not mind can you tell me what do you mean by that in your first coment so i can try and do that instead – chris Jan 27 '22 at 16:12
  • @chris check the edited answer using class. – S.B Jan 27 '22 at 16:27
  • @chris See [Python: Passing variables between functions](https://stackoverflow.com/q/16043797/6045800) – Tomerikoo Jan 27 '22 at 17:43