NameError: name 'stats' is not defined - python

i am messing about on python trying out classes but i am getting a name error which i dont know how to fix. it works fine when not in a class but now it is it doesnt work i presume this is a obvious problem , or just the whole thing is wrong, and i now look stupid lol, the other variables are things i havent got round to doing yet so ignore them. (yes the stats are ripped straight from fallout")
import time, random
class User():
def players():
players = 0
def stats(self):
perks = 20
print ("you have 20 perk points to spend")
print(""" you have several choices of what to spend
them in:
STRENGTH - what it says on the tin
PERCEPTION - awareness
ENDURANCE - how long you can endure something
CHARISMA - yet again what it says on the tin
INTELLIGENCE - how smart you are
AGILITY - how much of a slippery bugger you are
LUCK - how lucky you are""")
strength = int(input("What level is your strength?"))
perks = perks - strength
perception = int(input("What level is your perception?"))
perks = perks - perception
endurance = int(input("What level is your endurance?"))
perks = perks - endurance
charisma = int(input("What level is your charisma?"))
perks = perks - charisma
intelligence = int(input("What level is your intelligence?"))
perks = perks - intelligence
agility = int(input("What level is your agility?"))
perks = perks - agility
luck = int(input("What level is your luck?"))
perks = perks - luck
if perks >= 0:
print ("this works")
elif perks <=-1:
print("this also works")
def __init__(self,username,stats):
self.username = username
self.stats = stats
players +=1
story = "on"
while story == "on":
print ("Start of story")
stats()
Welcome to my story
Traceback (most recent call last):
File "C:/Users/----/----/python/----.py", line 45, in <module>
stats()
NameError: name 'stats' is not defined
>>>

your problem is that you have the attribute stats and the method stats you can rename your stats attribute to _stats, and also you need to make an object from User class for example
class User():
def __init__(self,username,stats):
self.username = username
self._stats = stats
...
def stats(self):
...
user = User('test', 1)
story = "on"
while story == "on":
print ("Start of story")
user.stats() # method
user._stats # attribute

stats() is a method of your class User. That means stats() exists within the scope of User, but out of the scope it is not defined.
Then there's another problem: Your __init__ takes an argument with the same name (stats), and then you set stats as an attribute of self. That means you override your method stats() with whatever you pass to the __init__ call (when you set self.stats = stats). You should rename this attribute, maybe to self._stats = stats.
And in your global scope, you have never instantiated your class User. So you could do something like this:
user = User("Jeremy", "whatever your stats are")
story = "on"
while story == "on":
print ("Start of story")
user.stats()
This will resolve the error. However I'm not sure if the code will do what you expect it to do. You define a lot of variables within stats(), like strength etc. Maybe you'd want to define them as attributes to self, so self.strength = ....
You can then access them in the global scope via user.strength etc.

Related

I cannot import from another file

I am making a soccer game. I am new to Python. I am trying to make soccerplayers on a file, then import it to my main game.
Here is soccerplayer.py
class soccerp:
def __init__(self,overall,name,speed,shoot,ballc,defence):
self.overall = overall
self.name = name
self.speed = speed
self.shoot = shoot
self.ballc = ballc
self.defence = defence
Here is soccerkeeper.py
class soccerk:
def __init__(self,overall,name,dive,reactspeed,reach,jump):
self.overall = overall
self.name = name
self.dive = dive
self.reactspeed = reactspeed
self.reach = reach
self.jump = jump
Here is soccerplayerlist.py
from soccerplayer import soccerp
from soccerkeeper import soccerk
#name overall speed shootingpower ballcontrol defence
david = soccerp("david",114,181,179,183,148)
john = soccerp("john",119,179,185,187,151)
soccerplayers = [david,john]
And here is my game.py
import time
from soccerplayerlist import soccerplayers
#name overall speed shootingpower ballcontrol defence
ovr = [120,124,158,132,109] #will edit as the players overalls
teamovr = round(sum(ovr) / len(ovr))
def start():
print("Please pick your teams name : ")
team = input("> ")
print("")
time.sleep(1)
return team
def menu(team):
print("teams name : " + team)
print("team overall : " + str(teamovr))
def game():
team = start()
#while True:
teamovr = round(sum(ovr) / len(ovr))
menu(team)
print(david.name) #checking if the players were imported from soccerplayerlist.py
game()
when I run the code, It says
NameError: name 'david' is not defined
I think that it didnt import the players, I may be wrong, what am I doing wrong here?
The issue is that you're importing the list and not the values of the list.
If you do
print(soccerplayers[0].name)
You should get the desired result.
The name david is not the one you import it is the list of soccerplayers
what you can do is instead of this line.
print(david.name)
do this:
for player in soccerplayers:
if player.name == "david":
david = player
I personaly recommend on pygame it is a library in python which allows to make high level games.

Changing a local variable in multiple functions in Python?

background: I'm currently writing a text-based adventure and each enemy has a certain amount of turns you can attack it before it attacks back.
So to handle this the code sets an argument in the function for the fight dictating how many times you can attack.
def fight_sequence(rounds):
while rounds > 0:
attack = input()
if attack == magic:
magic("you teleport away to safety. Congratulations you have stayed alive through your journey and found a few souvenoirs. nice job!", 1, "you muster up all of your energy, chant the spell.... and nothing happens.Cthulu... seems unimpressed", 1, "")
elif attack == sword:
sword(1)
def magic(teleportmessage, teleportsuccess, firemessage, firefail, winmessage):
x = 0
while x == 0:
fightorflight = input("""you open the book to cast a spell
Do you want to try teleporting or use a fireball?""").lower()
if "teleport" in fightorflight:
if teleportsuccess = 1:
print(teleportmessage)
x = 1
else:
choice = input("You can't teleport out of this battle. Would you like to try a fireball?")
if choice == yes:
fightorflight = "fireball"
else:
x = 1
elif "fire" in fightorflight:
print(firemessage)
if firefail == 1:
choice = input("do you want to try to teleport instead?").lower()
if "yes" in choice:
fightorflight = "teleport"
else:
x = 1
else:
print(winmessage)
else:
print("Sorry not sure what you mean")
def sword(attacksuccess):
if attacksuccess == 1:
print("You pull out the sword and swing at the monster damaging it severely.")
else:
print("You pull out the sword and swing at the monster, but its immune to blunt objects.")
fight_sequence(3)
both magic() and sword() need to be able to decrease rounds by 1, originally i just did that before entering the magic or sword function. however some items to attack with allow you to attack more than once if you want so that won't work for them. Such as magic if they also choose to teleport. Is there a way to allow me to change the variable rounds while inside of another function?
I think using a return value might help but I'm not sure how to go about it
You can simply add a new argument to the magic function, and pass the 'rounds' variable through when you call it.
e.g.
def fight_sequence(rounds):
...
magic("some message", false, "fired", false, "you won", rounds)
def magic(teleportmessage, teleportsuccess, firemessage, firefail, winmessage, rounds):
Your passing through the variable (not just the value) so it will change in every context where rounds can be seen.
HTH.
I would recommend using classes to create this game rather than lots of functions, an example of a class in a hero game below.
class Hero:
def __init__(self):
self.health = 10
def eatApple(self):
self.health += 1
def takeDamage(self):
self.health -= 1
init function runs as class is initialized.
player = Hero()
print(player.health) # will print 10
player.takeDamage()
print(player.health) # will print 9
This way you can have global variables for you functions which can be changed in each function and is much more organised.

Variable refrenced before assignment Python

I went through this a couple of times and couldnt fine anything wrong so its probably something over my head. I also apology for what is going to be an assault on your eyes, its my first year of programming and have probably made multiple etiquette errors.
print('Befor we begin, when you are given options, I ask you to type your input as show, failure to do so will break the program and you will lose all of your progress')
def test():
print('it has worked!')
def stats():
global attack
global health
global mashealth
global agility
if race in ('human','Human'):
maxatk=4
maxagi=4
attack = lambda:random.randint(2,maxatk)
maxhealth = 20
health=20
agility = random.randint(maxagi,10)
elif race in ('Orc','orc'):
attack = random.randint(3,maxATK)
maxhealth = 25
agility = random.radint(maxAGI,10)
def main():
while True:
print('What would you like to do')
print('Rest Shop Fight')
answer=input('-')
if answer in ('Rest','rest'):
health=maxhealth
continue
def character():
global race
global name
global gender
print('What would you like the name of your character to be?')
name=input('-')
print()
print('What race will your character be?')
print('Human Orc Elf')
while True:
race = input('-')
if race in ('human','Human','Orc','orc','Elf','elf'):
break
else:
print('Not a valid response, try again')
continue
print()
print('What gender is your character')
gender=input('-')
print()
def goblin():
goblinatk=1
goblinhealth=100
while True:
print('You have encountered a goblin, what will you do?')
do=input('-')
if do == 'attack':
damage=attack()
goblinhealth=goblinhealth-damage
print('You did',damage,'damage to the goblin')
print('The goblin has',goblinhealth,'hp')
goblinatk=lambda:random.randint(3,10)
health=health-goblinatk
print('the goblin did',goblinatk,'to you')
print('you have',health,'hp')
if goblinhealth <0:
print('The goblin has died')
break
if health <0:
print('you have died')
break
character()
stats()
goblin()
test()
The error is here
Traceback (most recent call last):
File "H:\16CoFrega\Code\Python\GAME.py", line 255, in <module>
goblin()
File "H:\16CoFrega\Code\Python\GAME.py", line 238, in goblin
health=health-goblinatk
UnboundLocalError: local variable 'health' referenced before assignment
You need to specify the health as a global variable, otherwise it would be considered as a local variable, since you assign to it inside the function. Example -
def goblin():
global health
goblinatk=1
goblinhealth=100
def goblin():
............
health=health-goblinatk
............
Look at this function definition. Your function doesn't know what health is, so it won't allow you to subscript something from health.
So, somehow function has to recognize what is health. Two most common way:
First way, Declare health as a global variable. Now health can be recognized globally. But this is not the best way, as dealing with global variables are hard and error-prone and you are already handling too many global variables. So, i won't recommend it. I would rather suggest you to replace all the global variables with method 2. To understand why I am telling this, Read This Question
Second way, the recommended way, is to pass the health variable as the parameter of the function and at the end, return it from the function.
Like this:
def goblin(health):
............
health=health-goblinatk
............
return health
If you are already returning something, don't worry. With python, you can return more than one variable as a tuple.
return statement:
return a,b,c
calling statement:
a,b,c = func()
Hope this helps :)

Passing on the parameters of a function into another one?

I'm not really sure how to word this, but I'll try my best. I've created a function for a zombie, and another one for attacks. But I don't know how to pass on the parameters of the zombie function into the attack function. Also if there is a more technical way to word this please let me know. Here is my test code for it, I'm sure this community will be able to figure out what I mean. The end goal is to create a function where I can plug in a monster name and have it's assigned parameters (health, defense, etc..) be run in through the combat function. ie def combat(monster_name): Any and all advice is much appreciated. Thank you!
#Functions
def zombie():
global zombie_hp
zombie_hp = 10
print "Zombie encounter"
print "Current Health:", zombie_hp
def attack(monster):
if monster > 0:
while monster > 0:
user_action = raw_input("Do you attack the zombie? [y]: ")
if user_action == "y":
monster_hp = monster_hp - 1
print "Health remaining: ", monster_hp
def user_action():
global user_action
user_action = raw_input("Do you attack the zombie? [y]: ")
# Zombie Encounter (attack_testing)
attack(zombie())
if zombie_hp == 0:
print "Zombie Defeated"
I suggest you use a class:
class Zombie:
def __init__(self):
self.defense = 10
self.hp = 100
def hit(self, hp):
self.hp-=hp
def upgrade(self, level):
self.defense+=level
This will remember the hp and defense for every zombie that you create
>>> Max = Zombie()
>>> Max.hit(17)
>>> Max.upgrade(2)
>>> Max.hp
83
>>> Max.defense
12
>>>

calling method outside class python

I'm relatively new to Python and OOP, I'm trying to write a mini adventure game with classes and have gotten stuck with my BattleEngine class.
The idea is to have options to fight or outwit an opponent based on your characters and the opponents 'strength' and 'wit'.
I get an error when I try to call my attack method here:
class Armory(Scene):
def enter(self):
print "This room appears to be some kind of armory. There are shelves full of weaponry lining"
print "the walls. You walk around admiring the shiny weapons, you reach out to pick up a"
print "massive battleaxe. Right as your fingers touch it you hear voices from behind the"
print "next door. They sound like they're getting closer. As the voices grow nearer you must make"
print "a decision. Will you stand and fight (enter 'fight') or will you use your wit to outsmart"
print "your opponent(enter 'wit')?"
decision = raw_input("> ")
battle = BattleEngine()
if decision == "fight":
attack(self, Player.strength, 3)
if player_wins:
print "A man in light armour walks in and sees you with your sword drawn. A look of"
print "shock and disbelief is on his face. You act quickly and lunge at him."
print "The soldier struggles to unsheath his sword as you run him through."
print "He collapses to the ground wearing the same look of disbelief."
print "Your strength has increased by 1."
Player.strength += 1
elif decision == "wit":
outwit(self, Player.wit, 3)
Here is where I defined my BattleEngine class:
class BattleEngine(object):
def attack(self, player_strength, nonplayer_strength):
player_roll = randint(1,6)
nonplayer_roll = randint(1,6)
if (player_roll + player_strength) >= (nonplayer_roll + nonplayer_strength):
return player_wins
else:
return 'death'
def outwit(self, player_wit, nonplayer_wit):
player_roll = randint(1,6)
nonplayer_roll = randint(1,6)
if (player_roll + player_wit) >= (nonplayer_roll + nonplayer_wit):
return player_wins
else:
return 'death'
Once I get to this point in my program is receive the error that : 'attack global name is not defined'
I'm not sure what I'm doing wrong exactly. Any help would be fantastic!
You need to call attack on your BattleEngine instance, and you do not need to pass in self:
battle = BattleEngine()
if decision == "fight":
player_wins = battle.attack(Player.strength, 3)
Note that you need to receive the return value of the .attack() method.
The same applies to the .outwit() method further on:
elif decision == "wit":
player_wins = battle.outwit(Player.wit, 3)
You probably need to fix the return values in the .attack() and .outwit() methods; instead of return player_wins and return 'death', return True or False perhaps.
The self parameter is taken care of for you by Python, and will refer to the specific BattleEngine instance.
Not that you really need classes here, your BattleEngine() class currently has no per-instance state, for example. You don't use self in any of the methods, because there is nothing on the instance to refer to.

Categories