Hi all,
Im making a test text game and i got this error when i was trying to run it, after i had told it i wanted to attack:

Traceback (most recent call last):
  File "/home/tom/Desktop/Python/Text game/main.py", line 109, in <module>
    main()
  File "/home/tom/Desktop/Python/Text game/main.py", line 105, in main
    print 'his attributes are:' + new_monster.getAttributesInfo()
  File "/home/tom/Desktop/Python/Text game/main.py", line 84, in getAttributesInfo
    Monster.getAttributesInfo()
TypeError: unbound method getAttributesInfo() must be called with Monster instance as first argument (got nothing instead)

Heres the code for the game:

#!/usr/bin/env python

import random

choice = 0

class weapon(object):
    def _init_(self, attack, defense):
        self.attack = self.attack
        defense = self.defense

    def getAttributesInfo(self):
        attributes = ['Attack:' + self.attack,
        'Defense:' + self.defense]
        return ' '.join(attributes)

class sword(weapon):
    def _init_(self):
        wepon._init_(self, random.randrange(1,3), random.randrange(1,3))

    def getAttributesInfo(self):
        weapon.getAttributesInfo()

class axe(weapon):
    def _init_(self):
        weapon._init_(self, random.randrange(1,5), random.randrange(1,5))
        print 'This Axe\'s Attributes are:'
        print 'Attack:' + self.attack
        print 'Defense:' + self.defense

    def getAttributesInfo(self):
        weapon.getAttributesInfo()
        
class player():
    def _init_(self):
        self.health = 10
        self.defense = 4
        self.base_attack = 3
        self.attacking = 1

    def weapon(self):
        self.weapon = random.range(1,2)
        if self.weapon == 1:
            self.weapon = sword()
            print "you got a sword."
        elif self.weapon == 2:
            self.weapon = axe()
            print "you got an axe."

    def attack(Monster):
        if not self.attacking == 1:
            self.attacking = 1
        if self.weapon.attack > monster.defense:
            hit = True
            monster.health = monster.health - self.weapon.damage
            print 'You hit him for ' + self.damage + 'damage!'
        for self.damage in axe() and sword():
            if self.attack > troll.defense or orc.defense:
                self.damage = (player.attack +self.attack) - monster.defense
            elif self.attack < troll.defense or orc.defense:
                print 'You did\'nt do any damage...' 


class Monster(object):
    def __init__(self, attack, health, defense,):
        self.attack = attack
        self.health = health
        self.defense = defense
    def getAttributesInfo():
        attributes = [ "Attack: " + self.attack,
        "Health: " +self.health,
        "Defense: " + self.defense]
        return " ".join(attributes)        
    
class orc(Monster):
    def _init_(self):
        Monster._init_(self, 4, 30, 5,) 
        if player.attacking == 1:
            print "You are attacking an orc."
        if self.health <= 0:
            print 'You killed the Orc'
            
    def getAttributesInfo(self):
        Monster.getAttributesInfo()
            
class troll(Monster):
    def _init_(self):
        Monster._init_(self, 7, 50, 7,)
        if player.attacking == 1:
            print "You are attacking a Troll."
        if self.health <= 0:
            print 'You killed the Troll'
        
    def getAttributesInfo(self):
        Monster.getAttributesInfo()

def main():
    monster_attacking = random.randrange(1,2)
    if monster_attacking == 1:
        new_monster = orc(4, 30, 5)
    elif monster_attacking == 2:
        new_monster = troll(7, 50, 7)
    choice = raw_input('Do you want to attack:')
    if choice == 'yes' or 'yer' or ' yes' or ' yer':
        print 'his attributes are:' + new_monster.getAttributesInfo()
        attack()
            
if __name__ == '__main__':
      main()

Any ideas and help would be appreciated.

Recommended Answers

All 40 Replies

In your code you go:

Monster.getAttributesInfo()
#and
weapon.getAttributesInfo()

The problem with this is that you are not instanciating your class. First creat an instance of the class and then you can call methods then. Otherwise you will keep getting this error.

Sorry wait, that only solves half of the problem. The thing i only just spotted was that you go Monster.__init__. That then means that all of Monsters methods will now be stored in self. So you can call self.getAttributesInfo But the problem with that is there are two methods called self.getAttibutesInfo One is in the Orc and Troll classes and the other is in the Monster class so then we have to change the name of one of them to make sure that the program does not call the method over and over and over.

I fiddled with the code and here is what i got:

#!/usr/bin/env python

import random

choice = 0

class weapon(object):
    def _init_(self, attack, defense):
        self.attack = self.attack
        defense = self.defense

    def getAttributesInfo(self):
        attributes = ['Attack:' + self.attack,
        'Defense:' + self.defense]
        return ' '.join(attributes)

class sword(weapon):
    def _init_(self):
        wepon._init_(self, random.randrange(1,3), random.randrange(1,3))

    def getAttributesInfo(self):
        weapon.getAttributesInfo()

class axe(weapon):
    def _init_(self):
        weapon._init_(self, random.randrange(1,5), random.randrange(1,5))
        print 'This Axe\'s Attributes are:'
        print 'Attack:' + self.attack
        print 'Defense:' + self.defense

    def getAttributesInfo(self):
        weapon.getAttributesInfo()
        
class player():
    def _init_(self):
        self.health = 10
        self.defense = 4
        self.base_attack = 3
        self.attacking = 1

    def weapon(self):
        self.weapon = random.range(1,2)
        if self.weapon == 1:
            self.weapon = sword()
            print "you got a sword."
        elif self.weapon == 2:
            self.weapon = axe()
            print "you got an axe."

    def attack(Monster):
        if not self.attacking == 1:
            self.attacking = 1
        if self.weapon.attack > monster.defense:
            hit = True
            monster.health = monster.health - self.weapon.damage
            print 'You hit him for ' + self.damage + 'damage!'
        for self.damage in axe() and sword():
            if self.attack > troll.defense or orc.defense:
                self.damage = (player.attack +self.attack) - monster.defense
            elif self.attack < troll.defense or orc.defense:
                print 'You did\'nt do any damage...' 


class Monster(object):
    def __init__(self, attack, health, defense,):
        self.attack = attack
        self.health = health
        self.defense = defense
    def getAttributesInfo(self):
        attributes = [ "Attack: "+ str( self.attack),
        "Health: "+str(self.health),
        "Defense: "+str(self.defense)]
        return " ".join(attributes)        
    
class orc(Monster):
    def _init_(self):
        Monster._init_(self, 4, 30, 5,) 
        if player.attacking == 1:
            print "You are attacking an orc."
        if self.health <= 0:
            print 'You killed the Orc'
            
    def getInfo(self):
       
        self.getAttributesInfo()
            
class troll(Monster):
    def _init_(self):
        Monster._init_(self, 7, 50, 7,)
        if player.attacking == 1:
            print "You are attacking a Troll."
        if self.health <= 0:
            print 'You killed the Troll'
        
    def getInfo(self):
        
        self.getAttributesInfo()

def main():
    monster_attacking = random.randrange(1,2)
    if monster_attacking == 1:
        new_monster = orc(4, 30, 5)
    elif monster_attacking == 2:
        new_monster = troll(7, 50, 7)
    choice = raw_input('Do you want to attack:')
    if choice == 'yes' or 'yer' or ' yes' or ' yer':
        print "FFFF"
        print 'his attributes are:' , new_monster.getInfo()
        attack()
            
if __name__ == '__main__':
      main()

Some very basic errors there. You failed to declare the instance of your class. One recommended way to avoid that is to start your class names with a capital letter and your instance name with lower case.

As your game gets larger, you may want to interest yourself in a thing called debugging.

An alternative to changing the method's name is this

class Troll(Monster):
    def getAttributesInfo(self):
        Monster.getAttributesInfo(self)

It's a standard way of overloading a method in python: the method in the derived class calls the method with the same name in the parent's class. This allows you to define troll-specific behaviour in the derived class method.

Sorry wait, that only solves half of the problem. The thing i only just spotted was that you go Monster.__init__. That then means that all of Monsters methods will now be stored in self. So you can call self.getAttributesInfo But the problem with that is there are two methods called self.getAttibutesInfo One is in the Orc and Troll classes and the other is in the Monster class so then we have to change the name of one of them to make sure that the program does not call the method over and over and over.

I fiddled with the code and here is what i got:

#!/usr/bin/env python

import random

choice = 0

class weapon(object):
    def _init_(self, attack, defense):
        self.attack = self.attack
        defense = self.defense

    def getAttributesInfo(self):
        attributes = ['Attack:' + self.attack,
        'Defense:' + self.defense]
        return ' '.join(attributes)

class sword(weapon):
    def _init_(self):
        wepon._init_(self, random.randrange(1,3), random.randrange(1,3))

    def getAttributesInfo(self):
        weapon.getAttributesInfo()

class axe(weapon):
    def _init_(self):
        weapon._init_(self, random.randrange(1,5), random.randrange(1,5))
        print 'This Axe\'s Attributes are:'
        print 'Attack:' + self.attack
        print 'Defense:' + self.defense

    def getAttributesInfo(self):
        weapon.getAttributesInfo()
        
class player():
    def _init_(self):
        self.health = 10
        self.defense = 4
        self.base_attack = 3
        self.attacking = 1

    def weapon(self):
        self.weapon = random.range(1,2)
        if self.weapon == 1:
            self.weapon = sword()
            print "you got a sword."
        elif self.weapon == 2:
            self.weapon = axe()
            print "you got an axe."

    def attack(Monster):
        if not self.attacking == 1:
            self.attacking = 1
        if self.weapon.attack > monster.defense:
            hit = True
            monster.health = monster.health - self.weapon.damage
            print 'You hit him for ' + self.damage + 'damage!'
        for self.damage in axe() and sword():
            if self.attack > troll.defense or orc.defense:
                self.damage = (player.attack +self.attack) - monster.defense
            elif self.attack < troll.defense or orc.defense:
                print 'You did\'nt do any damage...' 


class Monster(object):
    def __init__(self, attack, health, defense,):
        self.attack = attack
        self.health = health
        self.defense = defense
    def getAttributesInfo(self):
        attributes = [ "Attack: "+ str( self.attack),
        "Health: "+str(self.health),
        "Defense: "+str(self.defense)]
        return " ".join(attributes)        
    
class orc(Monster):
    def _init_(self):
        Monster._init_(self, 4, 30, 5,) 
        if player.attacking == 1:
            print "You are attacking an orc."
        if self.health <= 0:
            print 'You killed the Orc'
            
    def getInfo(self):
       
        self.getAttributesInfo()
            
class troll(Monster):
    def _init_(self):
        Monster._init_(self, 7, 50, 7,)
        if player.attacking == 1:
            print "You are attacking a Troll."
        if self.health <= 0:
            print 'You killed the Troll'
        
    def getInfo(self):
        
        self.getAttributesInfo()

def main():
    monster_attacking = random.randrange(1,2)
    if monster_attacking == 1:
        new_monster = orc(4, 30, 5)
    elif monster_attacking == 2:
        new_monster = troll(7, 50, 7)
    choice = raw_input('Do you want to attack:')
    if choice == 'yes' or 'yer' or ' yes' or ' yer':
        print "FFFF"
        print 'his attributes are:' , new_monster.getInfo()
        attack()
            
if __name__ == '__main__':
      main()

Thanks for all that, i only changed the attack() function in main() to be player.attack(), which solved another error that i got but after that i got this error:

Traceback (most recent call last):
  File "/home/tom/Desktop/Python/Text game/main.py", line 112, in <module>
    main()
  File "/home/tom/Desktop/Python/Text game/main.py", line 109, in main
    player.attack()
TypeError: unbound method attack() must be called with player instance as first argument (got nothing instead)

Any ideas?

Again you need to create an instance of player so somewhere put this:

p = player()
#then when you want to attack
p.attack()

hope that helps.

Thanks again, but now i get this error:

Traceback (most recent call last):
  File "/home/tom/Desktop/Python/Text game/main.py", line 115, in <module>
    main()
  File "/home/tom/Desktop/Python/Text game/main.py", line 112, in main
    new_player.attack()
  File "/home/tom/Desktop/Python/Text game/main.py", line 55, in attack
    if self.weapon.attack > monster.defense:
AttributeError: 'function' object has no attribute 'attack'

any more ideas?

That is because when you go self.weapon.attack it logically goes, well self.weapon is a function in the class and then it looks for the variable attack as part of the method weapon. This is a problem and you should change this.

I noticed a lot of the things that you are using in your code have not actually been declared. Make sure to declare all of your variables.

How do you think that i would do that?

Well i think that you should declare things like the players attack in the __init__ statement of player and make sure that their variable names dont point to anything else such as a method or an already made variable. So for example you could put your attack in a variable called self.attack_points.

That way there are no other variables or methods called the same things as well as you would just replace the old self.weapon.attack with self.attack_points and everything would hopefully work a lot better.

OMG soo many errors, that fixed that 1 but now i get:

Traceback (most recent call last):
  File "/home/tom/Desktop/Python/Text game/main.py", line 109, in <module>
    main()
  File "/home/tom/Desktop/Python/Text game/main.py", line 106, in main
    new_player.attack()
  File "/home/tom/Desktop/Python/Text game/main.py", line 52, in attack
    if self.attack > Monster.defense:
AttributeError: type object 'Monster' has no attribute 'defense'

Okay, i think your problem here is that you are giving your class player all the attributes of monster but you forget to initialise monster. Try adding

Monster.__init__()

to your player class __init__ code. Then you can refer to anything from monster as self. So it would be self.defense rather then monster. Might cause some issues with conficting variable names, just fiddle around a bit with it.

That did'nt work, any other ideas?

I noticed in your previous code for your attack function you did not have self in the arguments. Is that how it is now? If not make sure self is in the arguments/parameters, whatever they are called :P.

Perhaps maybe post an update of your code as it is now.

Ah wait!! I found something wrong in your code!! Wow im amazed i didnt spot it before! You know your _init_ statement in player only has one _ when it needs two __. Replace _init_ with this __init__ . That should solve some major issues!

Can you go through my code and replace those things with the right things please, im getting kinda confused lol

Heres my code:

#!/usr/bin/env python

import random

choice = 0

class weapon(object):
    def _init_(self, defense):
        self.attack = self.attack
        defense = self.defense

    def getAttributesInfo(self):
        attributes = ['Attack:' + self.attack,
        'Defense:' + self.defense]
        return ' '.join(attributes)

class sword(weapon):
    def _init_(self):
        wepon._init_(self, random.randrange(1,3))
        player.attack = player.attack + random.randrange(1,3)

    def getAttributesInfo(self):
        weapon.getAttributesInfo()

class axe(weapon):
    def _init_(self):
        weapon._init_(self, random.randrange(1,5))
        player.attack = player.attack + random.randrange(1,5)
                                
    def getAttributesInfo(self):
        weapon.getAttributesInfo()
        
class player():
    def _init_(self):
        self.attacking = 0
        self.health = 10
        self.defense = 4
        self.attack = 3
        self.attacking = 1

    def weapon(self):
        self.weapon = random.range(1,2)
        if self.weapon == 1:
            self.weapon = sword()
            print "you got a sword."
        elif self.weapon == 2:
            self.weapon = axe()
            print "you got an axe."

    def attack(self):
        self.attacking = 1
        if self.attack > Monster.defense:
            hit = True
            monster.health = monster.health - self.weapon.damage
            print 'You hit him for ' + self.damage + 'damage!'
        for self.damage in axe() and sword():
            if self.attack > troll.defense or orc.defense:
                self.damage = (player.attack +self.attack) - monster.defense
            elif self.attack < troll.defense or orc.defense:
                print 'You did\'nt do any damage...' 


class Monster(object):
    def __init__(self, attack, health, defense,):
        self.attack = attack
        self.health = health
        self.defense = defense
    def getAttributesInfo(self):
        attributes = [ "Attack: "+ str( self.attack),
        "Health: "+str(self.health),
        "Defense: "+str(self.defense)]
        return " ".join(attributes)        
    
class orc(Monster):
    def _init_(self):
        Monster._init_(self, 4, 30, 5,) 
        if player.attacking == 1:
            print "You are attacking an orc."
        if self.health <= 0:
            print 'You killed the Orc'
            
    def getInfo(self):
        self.getAttributesInfo()
            
class troll(Monster):
    def _init_(self):
        Monster._init_(self, 7, 50, 7,)
        if player.attacking == 1:
            print "You are attacking a Troll."
        if self.health <= 0:
            print 'You killed the Troll'
        
    def getInfo(self):
        self.getAttributesInfo()

def main():
    monster_attacking = random.randrange(1,2)
    if monster_attacking == 1:
        new_monster = orc(4, 30, 5)
    elif monster_attacking == 2:
        new_monster = troll(7, 50, 7)
    choice = raw_input('Do you want to attack:')
    if choice == 'yes' or 'yer' or ' yes' or ' yer':
        print 'his attributes are:', new_monster.getInfo()
        new_player = player()
        new_player.attack()
            
if __name__ == '__main__':
      main()

Okay, well at the moment there are so many errors that i really cant begin to start. I have spent about 20 minutes trying to get your code to work but there are lots of fundamental things you need to do. I will outline the changes you need to do so it will be easier for all of us to help you.

ONE:
Change all _init_ methods in ALL of your classes to __init__ methods, you need those extra underscores for it to run, notice you will get a few errors when you try and instantise them, thats fine, just remove the arguments. Look at the exception carefully, it can tell you a lot.

TWO

for self.damage in axe() and sword():

That just dosent work. You cant iterate over things like that, your going to have to work out something else.

THREE

if self.attack > troll.defense or orc.defense:

This dosent work either. Python checks if self.attack is more then troll.defence. If False then it checks the other requirement which is orc.defence but seeing nothing is being compared with it as long as it is not 0 then it is True and the if runs. Also you cant use classes like that. Instantise all classes!

FOUR
Think through things logically and fiddle around, try things for yourself and see how things go. If you are stumped and cant think of anything, google it. Then ask us if nothing works. We cant do everything.

Well i hope that helps.
:)

Ok, im just going to start again, and clean up my code, i think it was just failing because of complexity.

Okay, well if you have any question just post them. It is a good idea to also test code as you go. That way you dont end up with massive errors that you need to re-write your code for.

But good luck!

Nice webstie by the way, and nice GUI that you are making, i liked the way that you planned it all out before you started and stuff like that, good work !

Planning is probably one of the best things you can do in a programming project. A lot of people when given a project will start typing straight away, i find that if i plan my code. Determine what features i want and work out how i am going to get them then i find the actual coding part a lot easier.

Im glad you liked it.

Mabey thats why i'v been having errors, i hav'nt been planning at all with this game.

I'm verry happy that i started again, alot of errors have been fixed, and thanks thom for telling me about __init__ having 2 _ _ instead of 1_, but now i am getting this error:

Traceback (most recent call last):
  File "/home/tom/Desktop/Python/Text game/main.py", line 97, in <module>
    main()
  File "/home/tom/Desktop/Python/Text game/main.py", line 93, in main
    P = player()
  File "/home/tom/Desktop/Python/Text game/main.py", line 65, in __init__
    sword.GetAttributesInfo2()
TypeError: unbound method GetAttributesInfo2() must be called with sword instance as first argument (got nothing instead)

heres my code as it is now(as you can see, alot cleaner than before):

#!/usr/bin/env python

import random

class monster(object):
    def __init__(self, attack, health, defense, name):
        self.attack = attack
        self.health = health
        self.defense = defense
        self.name = name

    def GetAttributesInfo(self):
        attributes = ['Name:' + self.name,
        'Health:' + self.health,
        'Attack:' + self.attack,
        'Defense:' + self.defense]
        return ''.join(attributes)

class orc(monster):
    def __init__(self):
        monster.__init__(self, 3, 10, 3, 'Orc')

    def GetAttributesInfo(self):
        monster.GetAttributesInfo(self)

class troll(monster):
    def __init__(self):
        monster.__init__(self, 5, 20, 5, 'Troll')

    def GetAttributesInfo(self):
        monster.GetAttributesInfo(self)

class weapon(object):
    def __init__(self, attack, name):
        self.attack = attack
        self.name = name
        
    def GetAttributesInfo2(self):
        attributes2 = ['Attack:' + self.attack,
        'Name' + self.name]
        return ''.join(attributes2)

class sword(weapon):
    def __init__(self):
        weapon.__init__(self, random.randrange(1,5), 'Sword')

    def GetAttributesInfo(self):
        weapon.GetAttributesInfo2(self)

class axe(weapon):
    def __init__(self):
        weapon.__init__(self, random.randrange(1,7), 'Axe')

    def GetAttributesInfo(self):
        weapon.GetAttributesInfo2(self)

class player():
    def __init__(self):
        self.alive = True
        self.health = 30
        self.weapon = random.randrange(1,2)
        if self.weapon == 1:
            self.weapon = sword()
            sword.GetAttributesInfo2()
            print GetAttributesInfo2
        elif self.weapon == 2:
            self.weapon = axe()
            axe.GetAttributesInfo2
            print GetAttributesInfo2
    
    def attack(self):
        if not self.attacking == 1:
            self.attacking = 1
        if self.weapon.attack > monster.defense:
            print 'You hit him for', self.damage, 'damage!'
        if self.weapon.attack < monster.defense:
            print 'You did\'nt do any damage...'

def main():
    new_monster = random.randrange(1,2)
    if new_monster == 1:
        new_monster = orc()
    elif new_monster == 2:
        new_monster == troll()
    P = player()
    P.attack()

if __name__ == '__main__':
    main()

Any ideas?

You must not call sword.getAttributeInfo2() because sword is a class and getAttributeInfo2 is an instance method. It applies to an instance (an object). Here, your sword object is self.weapon, so you should write print self.weapon.getAttributeInfo2()

Also, your methods getAttribute info in troll and orc return None instead of what they should return. You shoud write

def getAttributeInfo(self):
        return monster.getAttributeInfo(self)

I cleaned up your code a while. Here is a code that runs. Compare the details with your version to understand how it works.

#!/usr/bin/env python

import random

class monster(object):
    def __init__(self, attack, health, defense, name):
        self.attack = attack
        self.health = health
        self.defense = defense
        self.name = name

    def GetAttributesInfo(self):
        attributes = ['Name: %s' % self.name,
        'Health: %d' % self.health,
        'Attack: %d' % self.attack,
        'Defense: %d' % self.defense]
        return ', '.join(attributes)

class orc(monster):
    def __init__(self):
        monster.__init__(self, 3, 10, 3, 'Orc')

    def GetAttributesInfo(self):
        return monster.GetAttributesInfo(self)

class troll(monster):
    def __init__(self):
        monster.__init__(self, 5, 20, 5, 'Troll')

    def GetAttributesInfo(self):
        return monster.GetAttributesInfo(self)

class weapon(object):
    def __init__(self, attack, name):
        self.attack = attack
        self.name = name
        
    def GetAttributesInfo(self):
        attributes2 = ['Attack: %d' %  self.attack,
        'Name: %s' % self.name]
        return ', '.join(attributes2)

class sword(weapon):
    def __init__(self):
        weapon.__init__(self, random.randrange(1,5), 'Sword')

    def GetAttributesInfo(self):
        return weapon.GetAttributesInfo(self)

class axe(weapon):
    def __init__(self):
        weapon.__init__(self, random.randrange(1,7), 'Axe')

    def GetAttributesInfo(self):
        return weapon.GetAttributesInfo(self)

class player():
    def __init__(self):
        self.alive = True
        self.health = 30
        self.damage = 5
        choice = random.randrange(1,2)
        if choice == 1:
            self.weapon = sword()
        else:
            self.weapon = axe()
        print self.weapon.GetAttributesInfo()
    
    def attack(self, monster):
        #if not self.attacking == 1: ?
        #    self.attacking = 1 ?
        if self.weapon.attack > monster.defense:
            print 'You hit him for %d damage!' % self.damage
        if self.weapon.attack < monster.defense:
            print 'You did\'nt do any damage...'

def main():
    new_monster = random.randrange(1,2)
    if new_monster == 1:
        new_monster = orc()
    elif new_monster == 2:
        new_monster == troll()
    P = player()
    P.attack(new_monster)

if __name__ == '__main__':
    main()

THanks for that it works now

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.