Class variable can't be defined by function [closed] - python

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 8 years ago.
Improve this question
For some reason, the class variable self cannot be defined in a function.
Function:
def pickapoo_specialattack(opponent):
print("PICKAPOO's FLATULENCE BOLTS WAS EFFECTIVE")
self.damage -= float(self.damage / 20)
damage_dealt = random.randrange(200, 250)
defender.health -= damage_dealt
print("\nPICKAPOO's DAMAGE RATING WAS DECREASED BY 20%")
print("PICKAPOO's DAMAGE RATING IS NOW {}".format(str(self.damage)))
return self.damage
Class:
class Deskemon(object):
def __init__(self, name, health, damage, defense):
self.base_name = name
self.base_health = health
self.base_damage = damage
self.base_defense = defense
self.name = self.base_name
self.health = self.base_health
self.damage = self.base_damage
self.defense = self.base_defense
Traceback:
Traceback (most recent call last):
File "DESKEMON PRE ALPHA.py", line 378, in <module>
Battle(deskemon, Jack)
File "DESKEMON PRE ALPHA.py", line 168, in Battle
Deskemon_Attack(D1, D2, special=(random.randrange(1, 100) <= 45))
File "DESKEMON PRE ALPHA.py", line 216, in Deskemon_Attack
pickapoo_specialattack(defender)
File "DESKEMON PRE ALPHA.py", line 115, in pickapoo_specialattack
self.damage -= float(self.damage / 20)
NameError: name 'self' is not defined
Here is my full code: http://pastebin.com/8Xn6UCKS

that's because the self variable has to be explicitely given to methods in python. As you write it, are you expecting python to read your mind so it guesses that self shall be something from a class your function is not related at all with?
So to have it bound you need:
add self to argument list of def pickapoo_specialattack(self, opponent)
to move pickapoo_specialattack(opponent) in your Deskemon class
looking further in your code, what you're doing is definitely wrong, as you're defeating the whole purpose of OOP! Use classes and subclasses to do what you're aiming.
Let me give you an incomplete example of what I mean:
class Deskemon(object):
def specialattack(self, opponent):
raise NotImplementedError
…
class Pickapoo(Deskemon):
def specialattack(self, opponent):
… # content of the pickapoo_specialattak() function
class Tamosha(Deskemon):
def specialattack(opponent):
… # content of the tamosha_specialattak() function
and then:
def main():
pickapoo = Pickapoo(…)
tamosha = Tamosha(…)
instead of monkey patching Deskemon instances, use proper OOP conception and make Deskemon the base class of all your instances. Then you create a specialized instance for each Deskemon object, and that's the thing you initialize.
N.B.1: you should init all your objects in a main function:
N.B.2: you should place all your code at the end in a main function:
def main():
# init
pickapoo = Pickapoo(…)
tamosha = Tamosha(…)
lilwilly = Lilwilly(…)
bigbboy = Biggboy(…)
# start up
print("Welcome to Deskemon Pre-Alpha V1.2".upper())
…
# play loop
while True:
deskemon_selection_menu()
deskemon_selection_input = input("> ")
if deskemon_selection_input == "1":
deskemon = tamosha
elif deskemon_selection_input == "2":
deskemon = pickapoo
elif deskemon_selection_input == "3":
deskemon = lilwilly
elif deskemon_selection_input == "4":
deskemon = biggboi
else:
continue
print("You have selected {} as your Deskemon".upper().format(deskemon))
break
# shut down
print("Professor Andrew: Alright Jack, it's time to pick your Deskemon.")
…
print("Jack: OI! " + name + "!")
time.sleep(1)
Battle(deskemon, Jack)
if __name__ == "__main__":
main()

Related

TypeError: 'int' object is not callable - Python beginner [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 11 months ago.
Improve this question
I'm a fairly new programmer and I started learning Python. I've given myself the task of programming a text-based RPG with a kind of round-based fighting like Pokémon or the older Final Fantasy games. Right now I'm working on the battle mechanics, but I ran into an error which I couldn't fix. When I call the 'battle' function in my main I always get the error: 'TypeError: 'int' object is not callable'. I'd be happy if you could help me with this one, like I said, I'm still very new to programming.
My error-Message:
Traceback (most recent call last): File "C:\Doku\Python310\Scripts\text_adventure.py", line 169, in <module>
battle(main.health, main.attack, main.defence, enemy.health, enemy.attack, enemy.defence, main, enemy) File "C:\Doku\Python310\Scripts\text_adventure.py", line 106, in battle
x = player.attack(enemy.health) TypeError: 'int' object is not callable
line 169
#call battle function with the stats of my main character and an enemy
battle(main.health, main.attack, main.defence, enemy.health, enemy.attack, enemy.defence, main, enemy)
line 103-112
#choose between attack and special attack - error occurs with both descisions the same way
while True:
desc = choose()
if desc == 'A' or desc == 'a':
x = player.attack(enemy)
y = player.check_battle()
break
elif desc == 'B' or desc == 'b':
player.specialmove(enemy)
player.check_battle()
break
my choose function:
#couldn't run it without it, don't know why
def choose():
desc = input()
return desc
my main (shortened)character class:
class Main:
#init
def __init__(self, Mhealth, Mattack, Mdefence):
self.health = Mhealth
self.attack = Mattack
self.defence = Mdefence
self.multiplier = 1.00
#attacks
def attack(self, enemy):
x = enemy.health - (self.attack-enemy.defence)
enemy.setHealth(x)
def specialmove(self, enemy):
enemy.health -= round((self.attack*1.5)-enemy.defence)
def movelist(self):
moves = ['A - Attack', 'B - Special']
return moves
my enemy class is built the same way
self.attack is an integer. You set it in __init__ part of the class. Rename either the attack function or this number.

Python dictionary nested within method auto-executes all values (methods) when outer method is called

I'm working on a simple skeleton for a game, and in an effort to try and be more "pythonic", I'm using objects/classes/dictionaries to try and capture all my actions/behaviors (as methods over functions, etc).
For some reason, every time I execute the method 'act' within the class "Player", the dictionary embedded within act runs all of its values (which are, in turn, methods from within the same instance of the class "Player"). In other words, the player chooses "attack, heal, and flee" every time, all at once, before being prompted.
I'm sure there's a simple explanation, but I've been looking for hours and can't find another example of someone's dictionary auto-running all the methods embedded within. Can you help?
Thanks!
- Jake
from random import randint
### BEGIN ALL CLASSES HERE
# To be used for all game objects (living and non-living)
class gameObject(object):
def __init__(self, name):
self.name = name
# To be used for all characters who can act in some way/be killed/change
class livingThing(gameObject):
def __init__(self, name, HP=1):
self.name = name
self.HP = HP
# The playable character(s)
class Player(livingThing):
def __init__(self,name="The Stranger", HP=4, MP=5, strength=1, intellect=1, spirit=1, luck=5, gil=6):
self.name = name
self.HP = HP
self.MP = MP
self.gil = gil
self.strength = strength
self.intellect = intellect
self.spirit = spirit
self.luck = luck
def act(player, enemy):
actions = {
"attack" : player.attack(enemy),
"heal" : player.heal(enemy),
"flee" : player.flee()
}
#Takes input from the player
decision = input("What would you like to do? ")
if decision.lower() in actions:
actions[decision.lower()]
else:
print("That didn't work! Try again.")
# Prints both player and enemy HP
def printHP(player, enemy):
print("{0}'s' HP: {1} \n{2}'s HP: {3}".format(player.name, player.HP, enemy.name, enemy.HP))
# Allows the player to attack an enemy (currently functional)
def attack(player, enemy):
enemy.HP -= player.strength
print("You strike {0} for {1} damage!".format(enemy.name, player.strength))
player.printHP(enemy)
# Allows the player to heal a certain amount of health based on its "spirit" stat (currently functional)
def heal(player, enemy):
healed = randint(0, player.spirit)
player.HP += healed
print("You've healed for {0}!".format(healed))
player.printHP(enemy)
#Allows the player to attempt to run away
def flee(player):
randluck = randint(0, player.luck)
if randluck > 3:
print("You successfully escaped!")
return player.HP
else:
print("You weren't able to escape!")
# Anything that can act with/against the player
class Actor(livingThing):
def __init__(self, name="Unknown Entity", HP=10, MP=2, gil=3):
self. name = name
self.HP = HP
self.MP = MP
self.gil = gil
### END ALL CLASSES ###
### DICTIONARIES CONTAINING ACTIONS ###
### CHARACTERS ###
fighter = Player()
monster = Actor()
fighter.act(monster)
I see the problem. When you are executing Python code, and you have a dictionary as you do, Python evaluates the dictionary fully. If you wanted your values (in your key:value) pairs to be the results of those methods, this is surely one way to do it.
In your case, what you can do is reference the function itself, and not invoke it. You can do this by getting rid of the parentheses, like this:
player.attack
instead of
player.attack()
Then, to call the function you can do something like
actions[decision.lower()](enemy)
Since one of your functions, flee, doesn't accept any parameters, you could give flee a parameter that you simply don't use in the function. If you were designing many many methods that your player can act with, then one strategy would be to give them all only named parameters, like this:
def f1(enemy=None,something=None,foo=None):
if enemy is None:
raise Exception("enemy cannot be None")
#process_enemy
If however, you also have a very high amount of parameters, then you could do this:
def attack(**kwargs):
#kwargs is a dictionary of parameters provided to the function
enemy = kwargs.get('enemy',None)
if enemy is None:
raise Exception("enemy cannot be None")
def eat(**kwargs):
food = kwargs.get('food',None)
if enemy is None:
raise Exception("food cannot be None")
attack(enemy="someenemyobject")
eat(food="somefoodobject")
attack() # raises Exception
attack(food="somefoodobject") # raises Exception
food(enemy="someenemyobject") # raises Exception
food(food="somefoodobject",enemy="someenemyobject") # does not raise Exception

Python: Why is it saying my method isn't defined when it clearly is?

class GameMech:
def __init__(self ,aCharacter):
print("A battle is starting")
def getMP(self, aCharacter):
return aCharacter.mp
def getHP(aCharacter):
return aCharacter.hp
def getAtk(aCharacter):
return aCharacter.atk
def getDef(aCharacter):
return aCharacter.defense
def usePotion(aCharacter):
aCharacter.hp += 100
return aCharacter.hp
def useSpecial(self, aCharacter, target):
if aCharacter.mp >= 100:
target.hp -= 45
def dead(self, aCharacter):
return aCharacter.name +" is now dead"
def attack(self, aCharacter, target):
if target.hp - (aCharacter.atk/aCharacter.defense) <= 0:
dead(target)
else:
target.hp - aCharacter.atk/aCharacter.defense
print(getHP(target))
def guard(self, aCharacter):
print(aCharacter + "was unharmed")
if aCharacter.hp <= 50:
retaliation(aCharacter, target)
def retaliation(self ,aCharacter, target):
target.hp - (aCharacter.atk/10)
print(getHP(target))
def battleMenu(aNumber, self):
if aNumber == 1:
attack(aCharacter, target)
if aNumber == 2:
guard(aCharacter)
print(aCharacter + " was unharmed!")
if aNumber == 3:
useSpecial(aCharacter, target)
print(getHP(target))
if aNumber == 4:
heal = useItem(aCharacter)
print(heal)
def myTurn(self):
print("ATTACK")
print("GUARD")
print("SPECIAL")
print("ITEM")
aNumber = int(input("What would you like to do? "))
battleMenu(aNumber)
def oppTurn(self):
print("It is the opponent's turn")
randomNum = random.randint(1,4)
battleMenu(randomNum)
a few notes, obviously due to this formatting you can't tell that all my methods are actually under the class, but they are.
you can ignore the first few parts, the part im focusing on is battle menu.
So i'm creating a little text game as a project for myself, pure leisure nothing academic or for a job. Just a little game for myself to help me jog my memory in regards to python. So that's where the gut of my game is, the character class is an another file and there's nothing important in there just the attributes of character (hp, mp, atk, def)
here's the main
import random
import character
import battle
#create a battle menu
#and a character value check menu
#add buttons
def main():
char1 = character.Character("Charlie", 5000, 2000, 1500, 750)
char2 = character.Character("Mark", 2000, 4000, 2000, 900)
newGame = battle.GameMech(char1)
while char1.hp != 0 or char2.hp != 0:
newGame.myTurn()
newGame.oppTurn()
main()
(not sure why it's not including the definition of my main in the code snippet)
Any how I'm getting this error saying "name 'battleMenu' is not defined".
Name usually applies to variables correct? But battleMenu is a method is there a reason i'm getting this error?
Traceback (most recent call last):
File "E:\PythonGame\mainGame.py", line 22, in <module>
main()
File "E:\PythonGame\mainGame.py", line 20, in main
newGame.myTurn()
File "E:\PythonGame\battle.py", line 55, in myTurn
battleMenu(self,aNumber)
NameError: name 'battleMenu' is not defined
To call a method, you need to mention the instance you're calling it on, so you need to do self.battleMenu(). You need to make similar changes for all of the method calls in your code. You also need to add a self argument to all your methods so that these changes will work. You also need to read the Python tutorial to get an understanding of Python basics.
self.battleMenu(...) # note the "self" here
You are calling it wrongly, def battleMenu(aNumber): , your function is not defined as an instance function, neither as a static method, If you want a static function you should first annotate the method as a static one , by using #staticmethod annotation.
Then call your function as - GameMech.battleMenu(random) .
If you want it to be an instance function, change the definition to def battleMenu(self, aNumber): and then check.

Python 3.3 Class method not working, why? [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 8 years ago.
Improve this question
Hi below is the relevant code for my problem:
class Player:
def __init__(self, name, x, y, isEvil):
self.health = 50
self.attack = randint(1, 5)
self.name = name
self.x = x
self.y = y
self.isEvil = isEvil
def checkIsAlive(self):
if self.health <= 0:
return False
else:
return True
# implicit in heritance. if the child doesn't have a function that the parent has
# the functions of the parent can be called as if it were being called on the
# parent itself
class Enemy(Player):
#def __init__(self, name, x, y, isEvil):
# self.health = 50
# self.name = name
# self.x = x
# self.y = y
pass
and a little more code:
e = Enemy('Goblin', 10, 11, True)
p = Player('Timmeh', 0, 1, False)
isLight()
while True:
if p.checkIsAlive() == True and e.checkIsALive() == True:
fight()
else:
if p.checkIsAlive() == True:
print('%s is victorious!!! %s survived with %s health points.' % (p.name, p.name, p.health))
else:
print('%s shrieks in its bloodlust!!! %s has %s health points' % (e.name, e.name, e.health))
however when i try and run this I get the following error:
Traceback (most recent call last):
File "<string>", line 420, in run_nodebug
File "C:\Python33\practice programs\textstrat\classees.py", line 94, in <module>
if p.checkIsAlive() == True and e.checkIsALive() == True:
AttributeError: 'Player' object has no attribute 'checkIsAlive'
However when using the interactive console I can do this:
if p.checkIsAlive() == True and e.checkIsAlive() == True:
... print('they are')
...
they are
all I want to do is call the boolean values for checkIsAlive to determine whether the two objects fight. It works in every other respect and I could just use:
if p.health <= 0 or e.health <= 0:
however that would make my checkIsAlive() method pretty useless when i would also want to be able to recycle as much code ass possible.
I really can't figure out why it is behaving this way and would sure love to understand it. Thanks in advance for your input.
As was pointed out swiftly in the comments above. I had missed a typo in the attribute name checkIsAlive.

Error: unbound method Dragon( ) must be called with Enemy instance as first argument (got Player instance instead)

class Character:
def __init__(self):
self.name = ""
self.health = 1
self.health_max = 1
class Player(Character):
def __init__(self):
Character.__init__(self)
self.state = 'normal'
self.health = 10
self.health_max = 10
class Monster(Character):
def Dragon(self):
self.name = "Dragon"
self.health = 20
def Goblin(self):
name = "Goblin"
health = 5
p = Player()
p.name = raw_input("Please enter your name: ")
print p.name
print p.state
print p.health
print p.health_max
m = Monster()
enemy = m.Dragon
print enemy.name
print enemy.health
Sorry, I've made this a little simpler to explain what I'm having difficulty with. I'm having a little bit of trouble with the basics of OOP, and I'm running into an issue with this snippet of code. I'm trying to create a "Dragon" here but I'm running into the following error:
Traceback (most recent call last):
File "test2.py", line 32, in
print enemy.name
AttributeError: 'function' object has no attribute 'name'
Can you tell me what I'm doing wrong here? Thanks.
You have to create an instance of a class first before you call any functions from it:
myenemy = Enemy()
myenemy.Dragon()
In your code, it looks like you created self.enemy, but later you call self.enemy = Enemy.Dragon(self). Instead of this last line, put self.enemy = self.enemy.Dragon(self).
It seems to be a recurring issue in the rest of your code as well. Commands = {'explore': Player.explore} should probably be Commands = {'explore': p.explore} (after you have created the instance p).
Since your updated code, I think you're getting functions and classes mixed up. Dragon is a function, and when you do enemy = m.Dragon, you are simply copying the function onto enemy. And thus when you do enemy.name, thinking it's a class, an error is raised, because enemy is now a function, not an instance.
You will have to create separate classes for different monsters:
class Dragon:
self.name = "Dragon"
self.health = 20
class Goblin:
name = "Goblin"
health = 5

Categories

Resources