Always go to: global name is not defined - python

That's my codes. When it runs it always shows:
nameerror: global name "weapon_choice" is not defined.
But i have already put in the weapon_choice. Why?
from sys import exit
def dead(why):
print why,"YOU ARE EATEN BY ZOMBIES!"
exit(0)
def start():
print "You wake up alone in a room.A crowed of corpses around you."
print "You find some tools beside maybe helpful."
print "What will you get?"
weapons = ['axe', 'bat', 'knife', 'pistol']
print weapons
while True:
weapon_choice = raw_input(">")
if weapon_choice in weapons:
print "Zombies walk towards you, now it's in urgency!"
print "You can't deal with them.You must flee!"
print "You find door and window.Where you will go?"
paths = raw_input(">")
if paths == "window":
dead("You fall down to the ground.")
elif paths == "door":
lift()
else:
dead("oops!")
else:
print "Can't understand what you say."
def lift():
print "You can't recognize the number in the lift."
print "Get out of the lift or tap a floor whatever. "
floor_choice = raw_input(">")
if floor_choice == "get out" and weapon_choice != "pistol":
dead("Outside full of zombies.You have nowhere to go.")
elif floor_choice == "get out" and weapon_choice == "pistol":
print "WOW!!!YOU KILL ALL THE ZOMBIES!!"
print "you get back to the bed for another sleep."
start()
elif floor_choice == "tap a floor" and weapon_choice == "axe":
street_1()
elif floor_choice == "tap a floor" and weapon_choice == "bat":
friends_axe()
elif floor_choice == "tap a floor" and weapon_choice == "pistol":
kill_frinends()
else:
print "Can't understand what you say."
start()
I thought when it runs,at the very beginning,it have already ask the inputer to input the weapon_choice.

First, it looks like you have an indention error. Everything from
while True:
to
else:
print "Can't understand what you say."
should be tabbed over one level so that it is inside the start function.
There is also a scope issue In your lift function: weapon_choice is not defined.
You should pass weapon_choice as a parameter to the lift function when calling it:
def start():
print "You wake up alone in a room.A crowed of corpses around you."
print "You find some tools beside maybe helpful."
print "What will you get?"
weapons = ['axe', 'bat', 'knife', 'pistol']
print weapons
while True:
# your while loop code here
elif paths == "door":
lift(weapon_choice)
# the rest of your while loop code here
def lift(weapon_choice):
# your lift function code here
After that, you just need to write the functions street_1, friends_axe, and kill_frinends--then you're done!

You should be getting: NameError: name 'weapons' is not defined
while True:
weapon_choice = raw_input(">")
is called before start() hence the error. Try enclosing code blocks in functions for better readability and debugging.
Update: I believe your code indentation above is not correct. It works fine, and as expected without the error you mentioned.

Related

Text Game Closes after every command - NOTE: I just started out

print "Welcome to the game. In the game you can 'look around' and 'examine things'."
print "There is also some hidden actions.
print "You wake up."
input = raw_input("> ")
haveKey = False
applesExist = True
if input == "look around":
print "You are in a dusty cell. There is a barrel in the corner of the room, an unmade bed,"
print "a cabinet and chest. There is also a cell door."
elif haveKey == False and input == "use door":
print "The door is locked."
elif haveKey == True and input == "use door":
print "You open the door and immediately gets shot with an arrow. You won, kinda."
elif input == "examine barrel":
print "There is apples in the barrel."
elif applesExist == True and input == "eat apple":
print "Mmmmh, that was yummy! But now there are no apples left..."
applesExist = False
elif applesExist == False and input == "eat apple":
print "sury, u et al aples befur!!1111"
elif input == "examine bed":
print "The bed is unmade, and has very dusty sheets. This place really needs a maid."
elif input == "sleep on bed":
print "You lie down and try to sleep, but you can't because of all the bugs crawling on you."
elif input == "examine chest":
print "There is a key in the chest."
elif input == "take key":
haveKey = True
print "You take the key."
elif input == "examine cabinet":
print "The cabinet is made of dark oak wood. There is a endless cup of tea in it."
elif input == "drink tea":
print "You put some tea in your mouth, but immediately spit it out."
print "It seems it has been here for quite some time."
else:
print "Huh, what did you say? Didn't catch that."
No syntax errors, no errors of any kind. Not. One.
The problem is that after I examine, look around and eat apples the
game closes. How do I fix this? With a While loop?
plz halp
You're obviously very beginner, I won't hammer you about how to do the best architecture. Get used to write code a little first.
If you want to repeat an action, that means a loop (here it's called the main game loop). You code currently takes an input, do a lot of checks to do an action on it, do that action and then... reach the end of the file and stops.
If you wan to go back to the input, you need to enclose all the code you want to repeat in a repetitive code structure, i.e. a loop.
Here is a basic pseudo-code of a game main loop.
playing=True:
while playing:
instruction = takeUserInputOfSomeForm();
if instruction == something:
doStuff()
# etc ...
elif instruction == "quit":
playing=False
You need a loop otherwise when the code hits the bottom of the file Python will exit. http://www.tutorialspoint.com/python/python_loops.htm

changing variables in one function from another function

I'm working on a text based adventure game in python. Nothing super fancy. I want to have a lever in 2 different rooms unlock a gate in a third room. Both levers need to be pulled in order for the gate to be unlocked.
here are the two rooms with the levers.
def SnakeRoom():
choice = raw_input("> ")
elif "snake" in choice:
FirstRoom.SnakeLever = True
print "As you pull the lever... You hear something click down the hall behind you."
SnakeRoom()
elif "back" in choice:
FirstRoom()
else:
dead("Arrows shoot out from the walls. You don't make it.")
def WolfRoom():
choice = raw_input("> ")
elif "wolf" in choice:
FirstRoom.WolfLever = True
print "As you pull the lever... You hear something click down the hall behind you."
WolfRoom()
elif "back" in choice:
FirstRoom()
else:
dead("Arrows shoot out from the walls. You don't make it.")
Here is the room with the gate.
def FirstRoom():
Lever = WolfLever and SnakeLever
choice = raw_input("> ")
if "straight" in choice and Lever != True:
print "You see a large gate in front of you. The gate is locked, there doesn't seem to be any way to open it."
FirstRoom()
elif "straight" in choice and Lever == True:
SecondRoom()
elif "left" in choice:
WolfRoom()
elif "right" in choice:
SnakeRoom()
elif "lever" in choice:
print "WolfLever: %s" % WolfLever
print "SnakeLever: %s" % SnakeLever
print "Lever: %s" % Lever
FirstRoom()
I shortened the code so you don't have to read through all the unnecessary stuff.
My biggest problem is I'm not super familiar with the Python language yet, so I'm not sure how to word everything to find the answers I'm looking for.
edit: Instead of FirstRoom.WolfLever I also tried just using WolfLever, in the body of my code, above Start() I have:
WolfLever
SnakeLever
Lever = WolfLever and SnakeLever
But my functions weren't updating these values. So I tried the FirstRoom. approach.
Credit to #Anthony and the following link: Using global variables in a function other than the one that created them
Globals definitely were the answer (With the exception of using classes). Here's what my WolfRoom() and SnakeRoom() functions look like now:
def WolfRoom():
global WolfLever
choice = raw_input("> ")
elif "wolf" in choice:
WolfLever = True
print "As you pull the lever... You hear something click down the hall behind you."
WolfRoom()
For FirstRoom() I added
global Lever
to the beginning of the function and right before Start() I have
WolfLever = False
SnakeLever = False
this way I have no errors or warnings (Was getting syntax warnings for assigning a value to my levers before declaring them as global) and everything works perfectly.

Why does this one chunk of code come up with error but the other one doesn't?

I have two sections of Python code - one works and the other one comes up with an error. What rule makes this the case?
Here is the chunk of code that got the error, along with the error:
Code:
elif door == "2":
print "You stare into the endless abyss at Cthulhu's retina."
print "1. blueberries."
print "2. Yellow jacket clothespins."
print "3. Understanding revolvers yelling melodies."
insanity = raw_input("> ")
if insanity == "1" or insanity == "2":
print "Your body survives powered by a mind of jello. Good job!"
print "Now what will you do with the jello?"
print "1. Eat it."
print "2. Take it out and load it in a gun."
print "3 Nothing."
jello = raw_input("> ")
if jello == "1" or jello == "2":
print "Your mind is powered by it remember? Now you are dead!"
elif jello == "3":
print "Smart move. You will survive."
else:
print "Do something!"
else:
print "The insanity rots your eyes into a pool of muck. Good job!"
I got this error message in prompt:
File "ex31.py", line 29
print "Now what will you do with the jello?"
^
IndentationError: unindent does not match any outer indentation level
BUT when my code is like this:
elif door == "2":
print "You stare into the endless abyss at Cthulhu's retina."
print "1. blueberries."
print "2. Yellow jacket clothespins."
print "3. Understanding revolvers yelling melodies."
insanity = raw_input("> ")
if insanity == "1" or insanity == "2":
print "Your body survives powered by a mind of jello. Good job!"
print "Now what will you do with the jello?"
print "1. Eat it."
print "2. Take it out and load it in a gun."
print "3 Nothing."
jello = raw_input("> ")
if jello == "1" or jello == "2":
print "Your mind is powered by it remember? Now you are dead!"
elif jello == "3":
print "Smart move. You will survive."
else:
print "Do something!"
else:
print "The insanity rots your eyes into a pool of muck. Good job!"
I get no error message.
Basically my question is - why do I not get an error message if I indent the line
print "Now what will you do with the jello?"
...and the rest of the block of code below it.
But I get an error code if I leave it with the same indentation as the line above it?
Does this mean that the print line after an if statement can only be one line in total, with no other print lines allowed to be linked to the output of the if statement above the first print line of that block?
Thanks.
I suspect you're mixing spaces and tabs. It's best to use only spaces so that your visual indentation matches the logical indentation.
Examining your source code, there's a tab character in the second line here:
if insanity == "1" or insanity == "2":
\t print "Your body survives powered by a mind of jello. Good job!"
print "Now what will you do with the jello?"
I've marked it with \t, which makes the mixed up indentation stick out.
Have you checked that your indentation is consistent? Are you using 4 spaces everywhere (not tabs)? I cut and paste your code from your first example(starting from the insanity raw input) and it ran fine on my machine.
You're not indenting after the elif at the top of this code:
elif door == "2":
print "You stare into the endless abyss at Cthulhu's retina."
print "1. blueberries."
print "2. Yellow jacket clothespins."
print "3. Understanding revolvers yelling melodies."
Have you tried:
elif door == "2":
print "You stare into the endless abyss at Cthulhu's retina."
print "1. blueberries."
print "2. Yellow jacket clothespins."
print "3. Understanding revolvers yelling melodies."
and see what happens?
Off on a tangent:
As you are already finding out, trying to do a story of any size with cascading if-else clauses very quickly becomes unwieldy.
Here is a quick state-machine implementation that makes it easy to write a story room-by-room:
# assumes Python 3.x:
def get_int(prompt, lo=None, hi=None):
"""
Prompt user to enter an integer and return the value.
If lo is specified, value must be >= lo
If hi is specified, value must be <= hi
"""
while True:
try:
val = int(input(prompt))
if (lo is None or lo <= val) and (hi is None or val <= hi):
return val
except ValueError:
pass
class State:
def __init__(self, name, description, choices=None, results=None):
self.name = name
self.description = description
self.choices = choices or tuple()
self.results = results or tuple()
def run(self):
# print room description
print(self.description)
if self.choices:
# display options
for i,choice in enumerate(self.choices):
print("{}. {}".format(i+1, choice))
# get user's response
i = get_int("> ", 1, len(self.choices)) - 1
# return the corresponding result
return self.results[i] # next state name
class StateMachine:
def __init__(self):
self.states = {}
def add(self, *args):
state = State(*args)
self.states[state.name] = state
def run(self, entry_state_name):
name = entry_state_name
while name:
name = self.states[name].run()
and your story rewritten to use it
story = StateMachine()
story.add(
"doors",
"You are standing in a stuffy room with 3 doors.",
("door 1", "door 2", "door 3" ),
("wolves", "cthulhu", "treasury")
)
story.add(
"cthulhu",
"You stare into the endless abyss at Cthulhu's retina.",
("blueberries", "yellow jacket clothespins", "understanding revolvers yelling melodies"),
("jello", "jello", "muck")
)
story.add(
"muck",
"The insanity rots your eyes into a pool of muck. Good job!"
)
story.add(
"jello",
"Your body survives, powered by a mind of jello. Good job!\nNow, what will you do with the jello?",
("eat it", "load it into your gun", "nothing"),
("no_brain", "no_brain", "survive")
)
story.add(
"no_brain",
"With no brain, your body shuts down; you stop breathing and are soon dead."
)
story.add(
"survive",
"Smart move, droolio!"
)
if __name__ == "__main__":
story.run("doors")
For debugging, I added a method to StateMachine which uses pydot to print a nicely formatted state graph,
# belongs to class StateMachine
def _state_graph(self, png_name):
# requires pydot and Graphviz
from pydot import Dot, Edge, Node
from collections import defaultdict
# create graph
graph = Dot()
graph.set_node_defaults(
fixedsize = "shape",
width = 0.8,
height = 0.8,
shape = "circle",
style = "solid"
)
# create nodes for known States
for name in sorted(self.states):
graph.add_node(Node(name))
# add unique edges;
ins = defaultdict(int)
outs = defaultdict(int)
for name,state in self.states.items():
# get unique transitions
for res_name in set(state.results):
# add each unique edge
graph.add_edge(Edge(name, res_name))
# keep count of in and out edges
ins[res_name] += 1
outs[name] += 1
# adjust formatting on nodes having no in or out edges
for name in self.states:
node = graph.get_node(name)[0]
i = ins[name]
o = outs.get(name, 0)
if not (i or o):
# stranded node, no connections
node.set_shape("octagon")
node.set_color("crimson")
elif not i:
# starting node
node.set_shape("invtriangle")
node.set_color("forestgreen")
elif not o:
# ending node
node.set_shape("square")
node.set_color("goldenrod4")
# adjust formatting of undefined States
graph.get_node("node")[0].set_style("dashed")
for name in self.states:
graph.get_node(name)[0].set_style("solid")
graph.write_png(png_name)
and calling it like story._state_graph("test.png") results in
I hope you find it interesting and useful.
Things to think about next:
room inventory: things you can pick up
player inventory: things you can use or drop
optional choices: you can only unlock the red door if you have the red key in inventory
modifiable rooms: if you enter the secluded grove and set it on fire, it should be a charred grove when you return later

Variable is not updating in function

I'm new in Python but bear with me.
In my code, I am trying to make variable room to 2, via west() function.
Code:
EDIT: I have isolated most of the non-essential code.
room = 1
cmds = 'west'.lower()
def isValidCMD(cmd):
if cmd in cmds:
return True
else:
print("Unknown command. For help type /help, for available options type /options")
cmd = input(">> ")
if isValidCMD(cmd):
runCMD(cmd)
return False
def runCMD(cmd):
if cmd == '/help':
help()
elif cmd == '/exit':
exit()
elif cmd == '/about':
about()
elif cmd == '/stats':
stats()
elif cmd == '/options':
options()
elif cmd == 'north':
north()
elif cmd == 'south':
south()
elif cmd == 'east':
east()
elif cmd == 'west':
west()
elif cmd == '/lookaround':
look_around()
def west():
if room == 1:
print("You head on over to the lab, to get some advice from Professor Andrew.")
return 2 #LINE 40 < -------
elif room == 7:
print("You head back to Auderban Square feeling primed for battle.")
else:
print("You cannot go west.")
cmd = input(">> ")
if isValidCMD(cmd):
runCMD(cmd)
def main():
while True:
# Town
if room == 1:
print("\nYou are at the centre of town, Auderban Square.".upper())
print("\nYou look at the signpost and see 4 signs.")
print("\t- North - Twinleaf Forest")
print("\t- South - Store of Celestia")
print("\t- East - Deskemon Training Ground")
print("\t- West - Auderban's Deskemon centre")
# Lab
elif room == 2:
print("You are at Auderban's Deskemon Centre")
AndrewConv()
print("\nYou see the exit at the door.")
print("\t- East - Auderban Square")
cmd = input(">> ")
if isValidCMD(cmd):
runCMD(cmd)
main()
Output:
But room keeps its value, 1.
Please give some advice for the future so I won't make the same mistake twice.
Replace west() function with this:
def west():
global room
...
Global variables are widely considered bad programming practice because it is extremely difficult to determine where and when they might be modified in a large program. They also make thread-safe and reentrant code almost impossible to write.
A simple approach would be to have each function accept the room as a parameter and return the “new room.” You can then always update the room in your main function every time you invoke a command.
You will probably end up keeping track of more than the room, though. Consider using a mutable data structure like a dictionary or a class to store the game state, and then passing it into your command functions. That way, it is just as simple to keep up with many state variables as one, and you still do not need global variables.
def main():
state = {'room': 1}
while True:
[...]
if isValidCMD(cmd, state):
runCMD(cmd, state)
def west(state):
thisroom = state['room']
if thisroom == 1:
print("You head on over to the lab, to get some advice from Professor Andrew.")
state.update(room=2)
elif thisroom == 7:
print("You head back to Auderban Square feeling primed for battle.")
else:
print("You cannot go west.")
cmd = input(">> ")
if isValidCMD(cmd):
runCMD(cmd)
There are some additional issues with this code. For example, you duplicate the command prompt code in each command prompt, which is brittle and error prone, and unnecessary since you will be returning to main() anyway.
Edited: Here is a minimal, runnable example:
def main():
state = {'room': 1}
for i in range(20):
oldroom = state['room']
nextroom(state)
print("Went from room {} to room {}.".format(oldroom, state['room']))
def nextroom(state):
state['room'] += 2

Use of lists for collecting items

I'm currently going through the book "Learning Python The Hard Way", and I'm trying to make a simple game. In this game, I want to be able to pick up at item "Flashlight" in one room, to be able to get into another room. I can, however, not make it work :-(
So the question is, how do I carry the same list through several functions, and how do I put things in it? I want to be able to put multiple things in it.
I tried to call the pick() function within it self, but keep getting a "TypeERROR: 'str' is not callable, though I am providing my function with a list?
Hope you can help me out, thanks :-)
Code:
def start(bag):
print "You have entered a dark room"
print "You can only see one door"
print "Do you want to enter?"
answer = raw_input(">")
if answer == "yes":
light_room(bag)
elif answer == "no":
print "You descidede to go home and cry!"
exit()
else:
dead("That is not how we play!")
def light_room(bag):
print "WOW, this room is amazing! You see magazines, cans of ass and a flashlight"
print "What do you pick up?"
print "1. Magazine"
print "2. Cans of ass"
print "3. Flashlight"
pick(bag)
def pick(bag):
pick = raw_input(">")
if int(pick) == 1:
bag.append("Magazine")
print "Your bag now contains: \n %r \n" % bag
elif int(pick) == 2:
bag.append("Can of ass")
print "Your bag now contains: \n %r \n" % bag
elif int(pick) == 3:
bag.append("Flashlight")
print "Your bag now contains: \n %r \n" % bag
else:
print "You are dead!"
exit()
def start_bag(bag):
if "flashlight" in bag:
print "You have entered a dark room"
print "But your flashlight allows you to see a secret door"
print "Do you want to enter the 'secret' door og the 'same' door as before?"
answer = raw_input(">")
if answer == "secret":
secret_room()
elif answer == "same":
dead("A rock hit your face!")
else:
print "Just doing your own thing! You got lost and died!"
exit()
else:
start(bag)
def secret_room():
print "Exciting!"
exit()
def dead(why):
print why, "You suck!"
exit()
bag = []
start(bag)
I tried to call the pick() function within it self, but keep getting a "TypeERROR: 'str' is not callable, though I am providing my function with a list?
The problem here is that in this line:
def pick(bag):
pick = raw_input(">")
you bind pick to a new value (a str) so it doesn't reference a function anymore. Change that to something like:
def pick(bag):
picked = raw_input(">")

Categories

Resources