Reputation: 69
I have got a program which determines the outcome of two characters. There is an error, and I do not know how to fix it. I have tried create the variables global, but it doesn't work.
code:
import random, sys
y_n = ["yes", "Yes", "y", "ye", "yeah", "Ye", "Yeah", "Y"] # list of all possible inputs for Yes.
r = random.randrange # this is to make getting a random number shorter.
class Character(): # class. holds attributes, and methods.
name = "" #name of the character
random_attr = "" # do you want the attributes to be randomly generated or inputted manually?
strength, skill = 0,0 #strength and skill attributes
dice = 0 # dice score
def charInputs(self, random_attr): #method
#holds prompts for input
prompts = ("Enter Strength Attribute, between 1 and 50: ", "Enter Skill Attribute, between 1 and 50: ")
if random_attr in y_n: # if the user has said anything in the y_n list,
strength, skill = r(1,50), r(1,50) #create random attributes
#prints out your name, and your attributes
print(self.name + " - STRENGTH = ", strength, " SKILL = ", skill)
else: # if no
try: # 'try' is used for error handling
answers = [int(input(p)) for p in prompts]
# this is a list comprehension. it loops through the prompts and gets inputs from them
if not all(0 < a <=50 for a in answers): # generator expression - loops through the answers list
# and if it is above 50 or below 0, it returns false. else it returns true (because of the
# all() function).
print("You did not enter an attribute(s) between 1 and 50. Program closing.")
#exit here
else: # if the above expression returns True
strength, skill = answers #gets the attributes from the answer lists
print(self.name + " - STRENGTH = ", strength, ", SKILL = ", skill) #prints them out
except ValueError: # if user has not entered a integer
print("Program exiting. You did not enter a valid data type.") #prints
#exit here
return strength, skill; #returns attributes so they can be used outside the function and placed
# into variables
def Mods(self, oth_chr, strength, skill, name): # method for creating the modifiers.
#(you, other character, strength, skill, your name) <---- this is what is inside those brackets
if c1.strength > oth_chr.strength: # if your strength is greater than the enemies
str_diff = c1.strength - oth_chr.strength #create strength differences
elif c1.strength == oth_chr.strength: # if they are both the same
print("no outcome. both strengths were the same. No modifier could be created.")
quit()
else: # if enemies character is greater than yours
str_diff = oth_chr.strength - c1.strength
if c1.skill > oth_chr.skill: # if your skill is greater than the enemies
ski_diff = c1.skill - oth_chr.skill #create skill difference
elif c1.skill == oth_chr.strength: # if they are the same
print("No outcome. Both skills were the same, no modifier could be created.")
quit()
else: # if the enemies is greater than yours
ski_diff = oth_chr.skill - c1.skill
str_mod = str_diff // 5 # creates strength and skill modifiers
ski_mod = ski_diff // 5
return str_mod, ski_mod; #returns them so they can be used outside the method and be put into variables
def diceRollAndOutcome(self, ch2, strength, skill, str_mod, ski_mod, name): # method that is for determining
# the dice roll and outcome
c1.dice, ch2.dice = r(1,6), r(1,6) # rolls the dice
if c1.dice == ch2.dice: # if the dice are the same
print("No outcome. Both sides are the same.") # no outcome
#exit here
elif c1.dice > c2.dice: # if character 1's is greater
c1.strength += str_mod # adds strength modifier
c1.skill += ski_mod # adds skill modifier
print(self.name + "'s dice is greater than " + ch2.name + "'s dice!\n")
ch2.strength -= str_mod # subtract strength mod from character 2 strength
print("STRENGTH MODIFIER = ", str_mod, " has been subtracted from " + ch2.name + "'s strength attribute. It's strength is now ", ch2.strength, "\n") # prints
ch2.skill -= ski_mod # subtract skill modifier from character 2 skill
print("SKILL MODIFIER = ", ski_mod, " has been subtracted from " + ch2.name + "'s skill attribute. It's skill is now ", ch2.skill, "\n") # prints
if ch2.strength <= 0: # is character 2's strength less than or = to 0?
ch2.strength = 0 # make character 2 strength 0
else: # if not
print(ch2.name + " has not died! It's remaining strength is ", ch2.strength) # print character 2 has some strength remaining
if ch2.skill <= 0: # if c2's skill is less than or = to 0
print(ch2.name + "'s skill has ran out!\n") # skill has ran out
else:
print(ch2.name + " has some skill left! It's remaining skill is ", ch2.skill) # print c2 has some skill remaining
else: # if character 2's dice is greater than c1's
print(ch2.name + "'s dice is greater than " + name + "'s dice! \n")
self.strength -= str_mod # strength mod is subtracted from character 1's strength
print("STRENGTH MODIFIER = ", str_mod, " has been subtracted from " + self.name + "'s strength attribute. It's strength is now ", self.strength, "\n")
self.skill -= ski_mod # skill mod is subtracted from character 1's skill
print("SKILL MODIFIER = ", ski_mod, " has been subtracted from " + self.name + "'s skill attribute. It's skill is now ", self.skill, "\n")
if self.strength <= 0: # if c1's strength is less than or = to 0
self.strength = 0 # c1's strength is 0
else: # if not
print(self.name + " has not died! It's remaining strength is ", self.strength) # c1 has not died
if self.skill <= 0: # if c1's skill is less than or = to 0
print(self.name + "'s skill has ran out!\n") # c1's skill has ran out
else:
print(self.name + " has some skill left! It's remaining skill is ", self.skill) # c1's skill has not ran out
c1 = Character() # creates instance of Character class inside "c1"
c2 = Character() # creates instance of Character class inside "c2"
c1.name = str(input("PLAYER 1 - Enter your characters name: ")) # input character name
c2.name = str(input("PLAYER 2 - Enter your characters name: ")) # input character name
c1.random_attr = str(input("PLAYER 1 - Would you like your attributes to be randomly generated? Yes or No: ").lower()) # would the character like their attributes randomly generated or not
c1.strength, c1.skill = c1.charInputs(c1.random_attr) # returned strength and skill attributes are put into variables
c2.random_attr = str(input("PLAYER 2 - Would you like your attributes to be randomly generated? Yes or No: ").lower()) # would the character like their attributes randomly generated or not
c2.strength, c2.skill = c2.charInputs(c2.random_attr) # returned strength and skill attributes are put into variables
str_mod, ski_mod = c1.Mods(c2, c1.strength, c1.skill, c1.name) # returned strength and skill modifiers are put into variables
c1.diceRollAndOutcome(c2,c1.strength, c1.skill, str_mod, ski_mod, c1.name) # calls diceRollAndOutcome method
Error:
Traceback (most recent call last):
File "N:\CA\task 3\task 3.py", line 118, in <module>
c1.strength, c1.skill = c1.charInputs(c1.random_attr) # returned strength and skill attributes are put into variables
File "N:\CA\task 3\task 3.py", line 41, in charInputs
return strength, skill; #returns attributes so they can be used outside the function and placed
UnboundLocalError: local variable 'strength' referenced before assignment
How can I fix this? What is wrong with it - and how can I prevent doing this in the future?
The error points to line 118 and 41, I have looked through other questions but they don't make sense, as it is not my code they are working on.
Upvotes: 0
Views: 380
Reputation: 2482
In your charInputs
function there is a flow path that does not assign any value to strength
nor skill
.
The class variables that you define in your class are not visible inside your function, unless you use self.strength
and self.skill
inside charInputs
.
But, looking closer at your class, I'd rather define some defaults inside an __init__
function.
Upvotes: 2
Reputation: 1121386
In your charInputs
function there is a path where you can end up without strength
and skill
being assigned to.
If random_attr in y_n
is False, the else
branch is taken. In that branch you only assign no strength
and skill
if answers = [int(input(p)) for p in prompts]
does not throw an exception and all(0 < a <=50 for a in answers)
is True. If neither of these are true (so the user enters a string, or a value outside the valid range), you end up at the end of the function with no assignments for these two names.
Your code has comments for those cases stating you need to exit, but you don't actually do so.
Upvotes: 1
Reputation: 2166
Your second else
and your return
statements in the charInputs
function don't know who strength
is. This variable does not exist inside the scope of charInputs
function
Upvotes: 0