5
\$\begingroup\$

I recently started programming and ran into a problem in the battle algorithm. This piece of code checks if there is someone in the position of the main character. If there is, then the battle begins (action() function). If several enemies are in the same position, then the battle will go on until all the enemies in this position die.

What I wrote works, but I don't understand how to make the code shorter, more productive and smarter. In general, point out all the shortcomings of the code. I started just recently, I don't want to continue with mistakes.

import random
from random import randint

######################################HERO_CLASS##############################################################
class Hero():
    def __init__(self, name, level, race, position):
        self.name = name
        self.level = level
        self.race = race
        self.position = position
        self.maxhealth = 300
        self.health = 300
        self.attack = 20
        self.money = 2000
        self.bag = []
        self.weapon = []
        print(f"Player {self.name} created")

    def walk(self):
        self.position += 1
        print(f"{self.name} go for a walk straight....your position is {self.position}")

    def reverse_walk(self):
        self.position -= 1
        if self.position < 0:
            self.position = 0
        print(f"{self.name} go for a walk back....your position is {self.position}")
######################################ENEMY_CLASS##############################################################
class Enemy():
    def __init__(self, health, attack, race):
        self.health = health
        self.attack = attack
        self.race = race
        self.position = randint(1, 5)
        print(f"{race} create, enemy position is {self.position}")
######################################VARIABLES##############################################################
Pers = Hero("JohnnyBravo", 1, "Human", 0)

Orc = Enemy(200, 50, "Orc")
Human = Enemy(200, 50, "Human")
Goblin = Enemy(200, 50, "Goblin")

enemys = [Orc, Human, Goblin]


######################################FUNCTIONS##############################################################
def attack(point):
    damage = enemy.attack
    point = point - damage
    print(f"{enemy.race} damage is {enemy.attack}")
    return point


def attack_enemy(Enemy):
    damage = Pers.attack
    Enemy = Enemy - damage
    return Enemy

def main_attack():
    print(f"You attack {enemy.race} he have {enemy.health} health point!")
    enemy.health = attack_enemy(enemy.health)
    if enemy.health <= 0:
        enemy.health = 0
        print(f"After your attack {enemy.race} have {enemy.health} health point")
        print(f"You killed {enemy.race}\n\n")
        return enemy.health
    else:
        print(f"After your attack {enemy.race} have {enemy.health} health point")

def enemy_attack():
    Pers.health = attack(Pers.health)
    if Pers.health <= 0:
        Pers.health = 0
        print(f"{Pers.name} you die:(")
    else:
        print(f"{Pers.health} health left")

def action():
    if enemy.position == Pers.position and Pers.health > 0:
        print(f"{enemy.race} attack you! Watch out!\n\n")
        while True:
            answer = input(f"""
_______________________________________

Press '1' to ATTACK!!!\n
Press '2' walk straight\n
Press '3' walk back\n
_______________________________________
\n Your answer?\t\t""")
            if answer == "1":
                if Pers.health > 0:
                    enemy_attack()
                if Pers.health <= 0:
                    print("text for testing2")
                    break
                if enemy.health > 0 and Pers.health > 0:
                    main_attack()
                if enemy.health <= 0:
                    enemys.remove(enemy)
                    break
            elif answer == "2":
                Pers.walk()
                break
            elif answer == "3":
                Pers.reverse_walk()
                break
    if len(enemys) == 0:
        print("There are no enemies left")
        print(f"{Pers.name} you WIN!!!")

######################################START_GAME##############################################################
while len(enemys) > 0 and Pers.health > 0:
    for enemy in enemys:
        if len(enemys) > 0 and Pers.health > 0:
            action()
    if len(enemys) <= 0 or Pers.health <= 0:
        print("text for testing1")
        break
    answer = input("""
    Press D walk to the right\n
    Press A walk to the left\n
    Your answer?\t""").upper()
    if answer == "D":
        Pers.walk()
        for enemy in enemys:
            if len(enemys) > 0 and Pers.health > 0:
                action()
    elif answer == "A":
        Pers.reverse_walk()
        for enemy in enemys:
            if len(enemys) > 0 and Pers.health > 0:
                action()
\$\endgroup\$
2
\$\begingroup\$

You will do many mistakes

And this is totally normal. I don't know anyone who didn't do any mistake in his life. Everyone learns on mistakes. So don't be afraid to make mistakes - be afraid of not fixing them or not learning on them.

Extra import

import random

is unneeded.

from random import randint

does the thing. Of course, if you need several functions and/or classes from the module, or have some other concerns (like if you use tens of modules and want to track every function source), you should use the first form.

Think in OOP way

You have two objects interacting? Create a method (or several). Like

class Hero:
    ...
    def attack(self, enemy):
        enemy.health -= self.attack

or even

    def attack(self, enemy):
        enemy.get_damage(self.attack)

The second code allows enemy to control what happens when damage is done. Don't manipulate objects with external functions - make objects do something themselves.

Create a class for battlefield

Scene, Battlefield, Arena - name it as you wish; but your game probably will be bigger at some point, including menus, levels etc., and you've some useful global code stuck to current game configuration. Move all global functions and variables there.

Have only one main loop

Now you have two loops: one at the end of file, and it calls action(), which also has a loop. This is bad for many reasons - like if you want enemies to walk or heal or something every step of an outer loop, they will freeze while the inner loop is executing; you should rethink all the actions that happen in a game loop and break the code into several functions, like

class Arena: ... def main_loop(self): while True: self.draw() self.get_user_action() self.player_action() #according to get_user_action self.enemies_action()

Be ready to transform it into a single-step function (no loop) if you move to something like PyGame.

Read PEP8

It's a good habit to stick to style guides

\$\endgroup\$
1
  • \$\begingroup\$ thank you very much for the advice! about the method, yes, I thought about it, but the thought of the battle algorithm does not allow me to think about anything. I do not understand how to double-check the presence of an enemy in a position, even if there are several enemies. and be able to leave the position and go back, in general, with any movement, check for the presence of an enemy, and if you kill him, then do not leave the loop if someone is still there. \$\endgroup\$ – JohnnyBravo Jul 16 at 20:18

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.