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(">")
Related
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.
My problem actually occurs in LockedRoom():
The error python throws is:
Traceback (most recent call last):
File "C:\Users\Tank\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Enthought\CastleGame1.py", line 479, in <module>
a_game.play()
File "C:\Users\Tank\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Enthought\CastleGame1.py", line 33, in play
next_scene_name = current_scene.enter()
File "C:\Users\Tank\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Enthought\CastleGame1.py", line 147, in enter
has_key = "key" in Person.items
AttributeError: class Person has no attribute 'items'
So, I believe the problem is to do with checking for, or putting "Key" in the
person's items. I then want to check this list to see if the warrior is carrying it. If he is, then he should be able to open the door. If not, then the door should remain closed. I need to repeat this again at the end for TowerRoom. In that case, I need to check for up to 3 different items. I have attached the code. Hopefully, the error is a very simple one.
from sys import exit
from random import randint
key = False
brick = False
candle = False
Cup = False
class Scene(object):
def enter(self):
print "This scene is not yet configured."
exit(1)
class Person:
def __init__(self, name):
self.name = name
self.items = []
class Engine(object):
def __init__(self, scene_map):
self.scene_map = scene_map
def play(self):
current_scene = self.scene_map.opening_scene()
last_scene = self.scene_map.next_scene('finished')
while current_scene != last_scene:
next_scene_name = current_scene.enter()
current_scene = self.scene_map.next_scene(next_scene_name)
current_scene.enter()
class Death(Scene):
quips =[
"You really suck at this.",
"Why don't you try a little harder next time.",
"Well... that was a very stupid thing to do.",
"I have a small puppy that's better at this than you.",
"why don't you just give up now.",
"Please, stop killing me!",
"Your mom would be proud of you... if she were smarter."
]
def enter(self):
print Death.quips[randint(0, len(self.quips)-1)]
exit(0)
class MainGate(Scene):
def enter(self):
print "Welcome to Luke's first Text based game."
print "It currently has no name, nor will it ever have one."
print "Because it kind of sucks a little bit."
print"----------------------------------------"
print "Evil Dr. Onion has stollen the Mushroom Kingdoms princess"
print "You have chased him down for months through rain, snow"
print "and desserts. You have finally tracked him down."
print "In front of you is a huge castle. You go through the giant"
print "entrance to begin your search for the princess. Nobody"
print "know what may await you ahead."
print "Do you want to enter the Castle?"
print "1. Yes"
print "2. No"
action = raw_input(">")
if action == '1':
return 'central_corridor'
elif action == '2':
print "What? You are leaving and giving up on the princess"
print "already? God will certainly smite you for this!!!"
return 'death'
else:
print "Please choose an action numerically using the numpad"
print "on your computer."
return 'MainGate'
class CentralCorridor(Scene):
def enter(self):
print "You enter the castle. In fron of you stands a giant onion"
print "monster. It looks at you with its big, bulging eye. Your"
print "own eyes begin to weep as you look at this... thing."
print "The giant onion monster begins to charge at you, waving its"
print "sword over what I suppose would be its head."
print "what do you do?"
print "1. Try and fight the giant onion with your sword."
print "2. Try and dodge out of the way of the onion and run past it."
print "3. Throw something at the onion."
print "4. Stand there and scream at the onion."
action = raw_input(">")
if action == '1':
print "You take your sword out of its sheath. Waiting for the onion"
print "to reach you so that you can stab it in its giant eye."
print "however as it gets closer its stench gets worse and worse."
print "It gets so bad that you can hardly see!"
print "You try and swing at the onion, and miss!"
print "You feel a stabbing pain in your right shoulder"
print "and then everything goes black."
return 'death'
elif action == '2':
print "As the onion charges you, you jump out of the way."
print "However, the giant onion is much quicker than you expected."
print "You look down to see a sword protruding from your stomach."
print "You scream in pain and die."
return 'death'
elif action == '3':
print "You look in your pockets to find something to throw at"
print "the onion."
print "You find a rubber duck and throw it at the onion. Unfortunately, it"
print "does nothing but distracts the onion from you for a few"
print "short seconds. After it focuses its attention back on you,"
print "it eats your face off."
return 'death'
elif action == '4':
print "You choose to stand and scream at the onion at the highest"
print "pitch your girly little voice will allow."
print "The onion, hearing your scream, is terrified. It turns"
print "around and rolls away as quickly as its little legs and can"
print "carry it. You quickly catch up with it and cut its little"
print "legs right off, before hurrying to the next room."
return 'locked_room'
else:
print "please choose an appropriate action dear sir. Otherwise,"
print "you will never be able to rescue the princess."
return 'central_corridor'
class LockedRoom(Scene):
def enter(self):
print "You are standing in a room with just a door in front of you."
print "What do you do?"
print "1. Try and open the door."
has_key = "key" in Person.items
if not has_key: print "2. pick up the key"
action = raw_input(">")
if (action == '1' and has_key):
print "You unlock and open the door."
return 'monty_hall_room'
elif (action == '1' and not has_key):
print "the door will not budge"
return 'locked_room'
elif (action == '2' and not has_key):
print "you picked up the key."
Person.items.append("key")
return 'locked_room'
else:
print "Please enter a numeric value as something to do."
print "Otherwise we might be here all day."
return 'locked_room'
class Finished(Scene):
def enter(self):
print "You won! Good job."
return 'finished'
class Map(object):
scenes = {
'main_gate': MainGate(),
'central_corridor': CentralCorridor(),
'locked_room': LockedRoom(),
'monty_hall_room': MontyHallRoom(),
'pickel_room': PickleRoom(),
'death': Death(),
'finished': Finished(),
}
def __init__(self, start_scene):
self.start_scene = start_scene
def next_scene(self, scene_name):
val = Map.scenes.get(scene_name)
return val
def opening_scene(self):
return self.next_scene(self.start_scene)
warrior = Person("Soldat")
a_map = Map('central_corridor')
a_game = Engine(a_map)
a_game.play()
I just need a way to use a class 'list' and put things in and out of it in the other classes. Then, use whatever is contained in that list to open a door or slay a monster.
Any help anyone could provide would be greatly appreciatd.
You need create a "person" instance (you already did this), instead of using the class:
warrior = Person.new("penne12")
Or use the one you created
Then you can use your "warrior":
warrior.name #=> "penne12"
warrior.items #=> []
This is because the class itself doesn't store the name or items, the instance of the class (created when you do Person.new) contains the item array and the name. Trying to get the attributes of the class won't work.
Further reading
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
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.
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