I'm trying to make a battle function but am having some trouble. Is there a way to do this? At the moment I'm getting an error "AttributeError: 'function'object has no attribute 'att'. My guess is that this would be easier with classes, but I've not learned classes yet. So is this possible?

import random

def player():
    hp = 100
    att = random.randint(10, 30)

def rat():
    hp = 20
    att = random.randint(5, 25)

def attack(player, enemy):
    attack = player.att - enemy.hp
    print(enemy.hp)

Dani AI

Generated

The AttributeError comes from treating the name player as if it were an object with attributes. In your first post you defined player() as a function that only sets local variables, so player is still a function object and has no att attribute. was right to suggest using a data structure (dictionary) for actors. Two key fixes: make your actor creation return a data object, and run the battle loop while both combatants are alive (don’t rely on a single unchanging firstAtt or a global running flag).

Example (factory + safe loop, attack rolls generated each strike):

import random

def make_actor(name, hp, att_min, att_max):
    return {"name": name, "hp": hp, "att_min": att_min, "att_max": att_max}

def roll_damage(actor):
    return random.randint(actor["att_min"], actor["att_max"])

def battle(p, e):
    turn = random.choice([p, e])    # who starts this fight
    while p["hp"] > 0 and e["hp"] > 0:
        attacker = turn
        defender = e if attacker is p else p
        dmg = roll_damage(attacker)
        defender["hp"] -= dmg
        print("{0} hits {1} for {2} (remaining: {3})".format(
            attacker["name"], defender["name"], dmg, max(defender["hp"], 0)))
        if defender["hp"] <= 0:
            print("{0} is defeated.".format(defender["name"]))
            break
        turn = defender   # alternate

Why this helps

  • Returning a dict from a factory avoids the function vs. object confusion — you operate on the returned dict.
  • Looping while both hp > 0 guarantees termination once someone dies; toggling turn prevents an infinite loop caused when firstAtt never changes.
  • Rolling damage each attack gives variability; if you want fixed attack values, set them once at creation.

Later, when comfortable with classes, replace the dict with a simple class that stores hp and exposes an attack() method. Avoid globals for state, and add small sanity prints or asserts while debugging to see hp and turn values each loop.

Recommended Answers

All 3 Replies

Use dictionary of strengths. Your functions player and rat do nothing.

import random

player= dict(
    hp = 100,
    att = random.randint(10, 30))

enemy = dict(
    hp = 20,
    att = random.randint(5, 25)
)

attack = player['att'] - enemy['hp']

print(enemy['hp'])

Thanks pyTony, I've been trying to expand a little but I'm getting problems with everything I've tried. Here's my latest attempt.

import random
running = True

player = dict(
    hp = 100,
    att = random.randint(10,30))

enemy = dict(
    name = "Rat",
    hp = 20,
    att = random.randint(5, 25))

def attack(player, enemy):
    global running
    firstAtt = random.randint(1, 2)#1 player goes first, 2 enemy goes first
    while running:
        if firstAtt == 1:
            if enemy["hp"] > 0:
                playerAttack = player["att"]
                enemy["hp"] = enemy["hp"] - playerAttack
                print("You have dealt {0} damage to the {1}!".format(playerAttack, enemy["name"]))
            elif player["hp"] > 0:
                enemyAttack = enemy["att"]
                player["hp"] = player["hp"] - enemyAttack
                print("The {0} has dealt {1} damage to you!".format(enemy["name"], enemyAttack))
            else:
                running = False

This one crashes my editor, I think it's because the while loop isn't exiting out. Any ideas/tips?

You are not covering case when firstAtt is 2

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.