0

I am creating a small game because this is my first day on Python and I'm trying to make a small game that allows me to select an option to either Attack or Heal. When I press 1 in my terminal, it attacks the enemy and causes the enemy health to reduce. How do I make it so that this enemy health is reduced throughout the entire loop? So that when it loops again, the health will just keep reducing and doesn't reset when code is looped?

Image of what happens: enter image description here

What I'd prefer it to do is when I attack, it will keep the health as 204 for the next loop so when I attack again it will deduct from 204?

Here's my code:

import pygame
import os
import time
import random

# Characters

# barbarian
health = 200
attack = random.randint(0, 20)
heal = random.randint(0, 40)
bStats = [health, attack, heal]

# barb_stats[2] is equal to health

# enemy
eHealth = 220
eAttack = random.randint(0, 25)
eHeal = random.randint(0, 35)
eStats = [eHealth, eAttack, eHeal]


while health > 0:

    choice = input("Enter your choice of action: \n1 - Attack\n2 - Heal\nChoice: ")
    choice = str(choice)

    if choice == "1":

        def player_attack(eHealth):
            attack = random.randint(0, 20)
            eHealth = eHealth - attack
            return eHealth

        print("Enemy health is now " + str(player_attack(eHealth)))

    elif choice == "2":

        def player_heal(health):
            new_health = health + heal
            return new_health

        print("Player health is now " + str(player_heal(health)))
4
  • 1
    You need to modify health. When you say "Player health is now...", that's not true because you've not modified health. Commented Jul 13, 2021 at 8:30
  • Although your functions return the modified health values, those values are only ever printed and never reassigned back to the original variables. See the answers on how this should be done. Commented Jul 13, 2021 at 8:31
  • When you are calling the function within the loop, you need to update ehealth variable with what your function returns. Currently, your function is called inside print, and returned ehealth is not being stored Commented Jul 13, 2021 at 8:32
  • Both of the functions player_attack and player_heal compute the new health values in local variables, and return those new values. But the caller needs to assign the results to eHealth, which it doesn't. All it does is print them, then discard them. The calls need to look like eHealth = player_attach(eHealth), after which you can print the new value of eHealth. Commented Jul 13, 2021 at 8:34

2 Answers 2

2

The short answer would have been "add global to the functions", but we don't want to do that because it makes it hard to understand what's truly going on.

You'll have a better time with a function that executes an attack or a heal and returns the new health of the target, something like the below.

I removed unnecessary variables and imports for the time being to keep things simple. Also, to disambiguate things (so the functions won't shadow any global names), the player barbarian's health is now explicitly barb_health and so on. (I took the liberty of changing the spelling to Python's snake_case instead of the camelCase they were before.)

import random


def execute_attack(health, attack):
    damage = random.randint(0, attack)
    return health - damage


def execute_heal(health, heal):
    return health + heal


# barbarian
barb_health = 200
barb_attack = random.randint(0, 20)
barb_heal = random.randint(0, 40)

# enemy
enemy_health = 220
enemy_attack = random.randint(0, 25)
enemy_heal = random.randint(0, 35)

while barb_health > 0:
    choice = input("Enter your choice of action: \n1 - Attack\n2 - Heal\nChoice: ")
    choice = str(choice)
    if choice == "1":
        enemy_health = execute_attack(enemy_health, barb_attack)
        print(f"Enemy health is now {enemy_health}")
    elif choice == "2":
        barb_health = execute_heal(barb_health, barb_heal)
        print(f"Player health is now {barb_health}")
Sign up to request clarification or add additional context in comments.

8 Comments

Wow thanks! That really helped. What does 'f' do in print(f"Player health is now {bHealth}") haha nvm, I figured it out! Thanks!!!
@Toknn That's a f string
@Toknn Those are "f strings". They allow the values of variables to be inserted into the string. For example, if name is a string, then the following are equivalent: "My name is " + name, and "My name is {}".format(name), and f"My name is {name}". Oh and also "My name is %s" % name. There are lots of ways to do it. F-strings are the most recent of them.
I have one more issue. How do I make it so that the code AKX had made would display how much damage was dealt?
@Toknn That's a very bad way to do it. Passing arguments through globals is a common beginner's mistake. There's a reason why you were advised not to do it that way. Probably the best approach would be to have a class that holds the enemy health (among other things), then give that class a damage method that updates the health and returns the damage. But that might be a bit more than you're ready for. Also, all of this code should be in a function, not at the top-level of the file.
|
1

You can use the class called BaseUnit/Player/Enemy and create a instance called dragonslayer/dragon1/dragon2 to store the values for each instance.

Then, you can define a function called battle to let them fight.

This path will be more difficult to understand. But if you match this, you can do easily to handle with mutli enemies.

import logging
import random


class BaseUnit(object):
    def __init__(self, unit_name, base_health, base_attack, base_heal=None):
        self.name = unit_name
        self.max_health = base_health
        self.current_health = base_health
        self.current_attack = base_attack
        self.current_heal = base_heal

    def attack(self, target):
        point = random.randint(self.current_attack[0], self.current_attack[1])
        if target.current_health >= point:
            target.current_health = target.current_health - point
        else:
            target.current_health = 0
        print('{0} does {1} points damage to {2}.'.format(self.name, point, target.name))

    def heal(self):
        point = random.randint(self.current_heal[0], self.current_heal[1])
        if self.current_health + point <= self.max_health:
            self.current_health = self.current_health + point
        else:
            self.current_health = self.max_health
        print('{0} heals himself {1} points of health.'.format(self.name, point))

    def get_current_health(self):
        print('The health of {0} is {1} now.'.format(self.name, self.current_health))


class Enemy(BaseUnit):
    def heal(self):
        print("The enemy don't know how to heal himself.")
        pass


class Player(BaseUnit):
    def upgrade(self, uppoint_min, uppoint_max):
        max_health_up = random.randint(uppoint_min, uppoint_max) * 10

        max_attack_up = random.randint(uppoint_min, uppoint_max)
        min_attack_up = random.randint(uppoint_min, uppoint_max)
        if min_attack_up > max_attack_up:
            min_attack_up = max_attack_up

        max_heal_up = random.randint(uppoint_min, uppoint_max)
        min_heal_up = random.randint(uppoint_min, uppoint_max)
        if min_heal_up > max_heal_up:
            min_heal_up = max_heal_up

        self.max_health = self.max_health + max_health_up
        self.base_attack = (self.current_attack[0] + min_attack_up, self.current_attack[1] + max_attack_up)
        self.base_heal = (self.current_heal[0] + min_heal_up, self.current_heal[1] + max_heal_up)
        print("""You are upgraded!
Your max health is {0} now.
Your base_attack is {1}~{2} now.
Your base_heal is {3}~{4} now.
""".format(self.max_health, self.base_attack[0], self.base_attack[1], self.base_heal[0], self.base_heal[1]))


def battle(player, enemy):
    while player.current_health > 0 and enemy.current_health > 0:
        choice = input("Enter your choice of action: \n1 - Attack\n2 - Heal\nChoice: ")
        choice = str(choice)

        if choice == "1":
            player.attack(enemy)
            enemy.attack(player)
            player.get_current_health()
            enemy.get_current_health()

        if choice == "2":
            player.heal()
            enemy.attack(player)
            player.get_current_health()
            enemy.get_current_health()

    if player.current_health == 0 and enemy.current_health > 0:
        print('You are defeated, but {0} still alive.'.format(enemy.name))
    elif player.current_health > 0 and enemy.current_health == 0:
        print('At last You defeat {0}.'.format(enemy.name))
        dragonslayer.upgrade(1, 5)
    elif player.current_health == 0 and enemy.current_health == 0:
        print('You defeat {0}, but {0} also defeats you.'.format(enemy.name))


if __name__ == '__main__':
    logging.basicConfig(
        level=logging.INFO,
        # filename=os.path.basename(__file__) + '_' + time.strftime('%Y%m%d', time.localtime()) + '.log',
        # filemode='a',
        format='%(asctime)s %(name)s %(levelname)s %(message)s',
        datefmt='%Y-%m-%d %H:%M:%S')
    logging.debug('start DEBUG')
    logging.debug('==========================================================')

    dragonslayer = Player('shiratori', base_health=100, base_attack=(2, 15), base_heal=(5, 20))
    dragon1 = Enemy('SmallDragon', base_health=50, base_attack=(5, 10))
    dragon2 = Enemy('BigDragon', 200, (7, 15))

    battle(dragonslayer, dragon1)
    if dragonslayer.current_health > 0:
        battle(dragonslayer, dragon2)

    logging.debug('==========================================================')
    logging.debug('end DEBUG')

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.