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.
Related
I've found a few versions of this question on the site, but none of the answers quite give me an answer I understand (this question is the closest, but the 'already answered' answer seemed to go off in a different direction).
I'm working my way through the learn python the hard way book and have gotten to the point where I'm trying to build a simple combat system for a game. The good news is that it seems to work when I leave it as a stand alone program. The bad news is that it breaks as soon as I try and add it as a class. I can add the full code if it is helpful, but I think the question is essentially related to code that looks like this:
class Room1(Scene):
def kick():
#things happen here
def start():
move = raw_input("> ")
if move == "kick":
kick()
start()
This worked fine when it was just a standalone set of defs, but now that I've added classes it throws up a global name error when move == kick. What am I missing?
Thanks in advance, sorry if there is an obvious answer that I'm missing.
Thanks to everyone for the quick responses! It looks like it may be helpful for me to add the entire code. Just to be clear, this is part of a larger game modeled on example 43 from Learn Python the Hard Way. I very much appreciate the suggestions on improving the structure, but my sense right now is that I want to figure out why this doesn't work with the structure I almost understand before moving on to change more things. Of course, I'm more than willing to accept an answer of "what you are trying to do does not fit in the structure you are trying to use."
When I run the code below as part of a larger structure (in the interest of space I won't paste the entire thing, but the game engine structure is linked to above) I get the error I described. I tried adding 'self.start()' or 'Room1.start()' I get errors that name 'self' or name 'Room1' is not defined.
class Room1(Scene):
gothon_power = 500
move_points = 10
damage = 0
def kick(self):
global gothon_power
global move_points
global damage
damage = randint(10,201)
gothon_power = gothon_power - damage
move_points = move_points - 2
result()
def punch(self):
global gothon_power
global move_points
global damage
damage = randint(1, 101)
gothon_power = gothon_power - damage
move_points = move_points -1
result()
def result(self):
if gothon_power > 0 and move_points > 1:
print "You did %s damage." % damage
print "The Gothon is down to %s health points." % gothon_power
print "You are down to %s move points." % move_points
print "\n"
print "What's your next move?"
move = raw_input("> ")
if move == "kick":
kick()
elif move == "punch":
punch()
else:
print "This isn't going to go anywhere unless you type 'kick' or 'punch'"
print "\n"
result()
elif gothon_power > 0 and move_points == 1:
print "You did %s damage." % damage
print "The Gothon is down to %s health points." % gothon_power
print "You are down to %s move points." % move_points
print "\n"
print "What's your next move? Remember, you only have 1 move point."
move = raw_input("> ")
if move == "kick":
print "You don't have enough move points for a kick."
print "\n"
result()
elif move == "punch":
punch()
else:
print "This isn't going to go anywhere unless you type 'kick' or 'punch'"
print "\n"
result()
elif gothon_power < 1 and move_points > 0:
print "Congratuations, you killed the Gothon!"
return 'room2'
else:
print "The Gothon still has health but you don't have moves."
print "You know what that means."
print "\n"
print "The Gothon killed you."
return 'death'
def start(self):
print "It is time to fight the Gothon"
print "First, let's pause to explain the fighting rules."
print "\n"
print "The Gothon has 500 health points."
print "You have 10 move points."
print "\n"
print "Kicks cost 2 move points and do between 10 and 200 points of damage."
print "Punches cost 1 move opint and do between 1 and 100 points of damage."
print "\n"
print "If you get rid of all 500 Gothon health points before you run out of"
print "move points you win. If you run out of move points before the Gothon"
print "moves out of health points you lose."
print "\n"
print "What's your first move?"
move = raw_input("> ")
if move == "kick":
kick()
elif move == "punch":
punch()
else:
print "This isn't going to go anywhere unless you type 'kick' or 'punch'"
start()
start()
A proper set of methods on a class will look like:
class Room1(Scene):
def kick(self):
#things happen here
def start(self):
move = raw_input("> ")
if move == "kick":
self.kick()
Room1().start()
But you might want to rethink your design a little bit. It really doesn't make sense for a Scene to query for input. You'll have to replicate that code in every room in your game.
Think about this kind of top-level driver for a minute:
game = Game()
starting_room = FrontPorch()
game.move_to(starting_room)
while not game.is_over():
move = raw_input("> ")
cmd, args = move.split(None, 1)
game.current_room.do_command(cmd, args)
Then let each room process the commands that it does specially. At the base level Room class, you can implement commands that are common to most rooms, like "GOTO", "LOOK", "WHERE", etc. Then rooms that allow kicking would override do_command and include logic like you have now.
Here is a presentation I gave at PyCon '06 on writing a text adventure. Skip over the parsing stuff, and go to the part where the game/room/items design is described. You don't have to follow this design verbatim, but you might get some ideas about how your objects and classes will interact. Think about that before actually diving in to write a lot of code.
You can't execute instance methods of a class, without creating an instance. For example, you could instead write:
class Room1(Scene):
def kick(self):
#things happen here
def start(self):
move = raw_input("> ")
if move == "kick":
self.kick()
room = Room1()
room.start()
However, I don't recommend using a class at all in this case. Classes are meant to give a way to represent your own custom objects with state. For example, you could have a Monster class with attributes damage, name, etc.
For this example that you show, it's probably better to just use a function for Room1.
To call kick() as a method you need to use the self.<method Name> syntax and add self as the first argument to it:
def kick(self):
#things happen here
print('kicking')
#call method
self.kick()
or additionally make kick() a static method by calling simply
A.kick()
I'm teaching myself python with Learn Python the hard way and I've run into a problem on ex36.
I'm at a fairly early stage in development and I can't figure out what's wrong with my if statement. For whatever reason my code never makes it past
elif "1" or "2" in choice and not key.
even if "1" or "2" aren't in the statement. I don't understand why this is happening. Look is fine. When I was using another nested if statement for this the nested statement got past this point, but it got hung up on another point so I moved my initializing variables-Not really sure if that's a thing in python or not--I did move them though-outside of the while loop.
Here's the code in its entirety before I ramble on too much.
I understand that the logic isn't complete and that more than half the code isn't finished, but I need to know why this statement isn't working.
#write function definition statements.
def darkRoom():
door = raw_input(">>> ")
if "1" in door:
lions()
elif "2" in door:
tiger()
elif "3" in door:
bear()
else:
print """A thunderous voice booms through the room exclaiming,
"CHOOSE DOOR 1, 2, OR 3!"""
darkRoom()
def lions():
#naming error somewhere here
keys = False
lions = False #lions are calm if false. They are pissed if true
warning = True
while True:
choice = raw_input(">>> ")
print " %r %r %r" % (keys, lions, warning)
x = "1" or "2" not in choice and not key and lions
if "take" and "key" in choice:
key = True
print """There are two doors behind the angry pride of lions.
Which door are you going to run to and open before the lions eat you?"""
door = raw_input(">>> ")
if "1" in door and key == True:
threeBrickRoads()
elif "2" in door and key == True:
quickSand()
else:
youDie("You take too long to decide which door to take and the lions eat you.")
elif "look" in choice:
print "Looks like you're going to have to take the key from the lions"
#never gets past this statement even when 1 and two not in choice. This is what my question
#is about
elif "1" or "2" in choice and not key:
print "The Door is locked and the lions are starting to stare."
lions = True
print " %r %r %r" % (keys, lions, warning)
print "%r" % choice
#never reaches this point. I don't know why.
elif x and warning:
print """The lions leave the key and start to chase you. Quick get the
key before they catch you"""
warning = False
#Statement never reaches this point. It should
elif x and not warning:
youDie("You take too long to take the key and the lions eat you for it.")
# entering jig in statement should put me here and not at line 46
else:
print """"You quickly realize that doesn't do you any good.
You take another look at your surroundings"""
#don't think I need that while I have the while loop.
#lions()
##def tiger():
##def bear():
##def threeBrickRoads():
##def quickSand():
##def sizePuzzle():
##def riddlesOnWall():
##def wolfSheepCabbage():
##def duckHunt():
##def hangman():
##def goldRoom():
##def oceanShore():
##def winScreen():
def youDie():
print why, """You lay there pondering your mistake as
the last fleeting pulses of life slowly beat out of you."""
#exit(0)
darkRoom()
elif "1" or "2" in choice and not key
This is interpretted as follows ("1" or (("2" in choice) and (not key)))
Since "1" is always true, this is always true. I think what you mean is:
elif choice in ['1', '2'] and not key
Let's have a look at this line:
elif "1" or "2" in choice and not key:
What this line actually states is that it basically requires one of the following two conditions to be True:
if "1" (without anything else)
if "2" in choice and not key
This is a typical mistake if you are a beginner and you can fix this easily if you write it as follows (easiest fix):
elif choice in [1, 2] and not key:
What this means is: If choice is equal to any of the elements contained in the list [1,2] and key is not True.
elif any(x in ["1", "2"] for x in choice) and not key:
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 having an issue. Speedy responses would be greatly appreciated! My program is failing IF conditions becuase my functions are not changing the global variable properly for me. They're supposed to, for example, be able to go south and take a key. With that key they can go East and open a locked drawer. Except... they fail the if check to be able to open the drawer.
Thanks in advance! The code blocks in question should be below!
def south():
print ("You can see a key just lying there on the table! What luck!")
choice = raw_input("You better TAKE that!")
if choice == 'TAKE' :
print "You took the key!"
return Key1 == 1, moverooms()
else:
print "You didn't take the key to freedom!?"
south()
def east():
print("You can see a drawer here! Wonder what is inside?")
choice = raw_input("You can MOVEROOMS, or try to USE the drawer and TAKE what's inside...\n ")
if choice == 'USE' :
print "You try to open the drawer... \n"
if Key1 == 1 :
print "You use the key to open the drawer and find a flashlight inside! Better TAKE it!"
Drawer == 1
east()
else:
print ("It's locked! Better find a key...\n")
east()
You really don't want to use global variables, but if you must, your problem seems to be that you're not assigning Key1 = 1 in your TAKE conditional, but returning True or False according to whether or not it already has that value (Key1==1). Note that you need to set it before the return.
Note that if you want to do this (you don't), you'll need to assert global Key at the top of your south() function.
To avoid global variables, return a value for Key1 from south and pass it to east:
def south():
print ("You can see a key just lying there on the table! What luck!")
choice = raw_input("You better TAKE that!")
if choice == 'TAKE' :
print "You took the key!"
Key1 = 1
else:
print "You didn't take the key to freedom!?"
Key1 = 0
return Key1
def east(Key1):
print("You can see a drawer here! Wonder what is inside?")
choice = raw_input("You can MOVEROOMS, or try to USE the drawer and TAKE what's inside...\n ")
if choice == 'USE' :
print "You try to open the drawer... \n"
if Key1 == 1 :
print "You use the key to open the drawer and find a flashlight inside! Better TAKE it!"
Drawer = 1
return Drawer
else:
print ("It's locked! Better find a key...\n")
Drawer = 0
return Drawer
You'll have to handle the logic of the calls to south and east yourself, though.
This might be overkill, but ideally you'll do something along these lines:
class Character(object):
"""
This class represents the player.
It keeps track of found items, opened drawers, etc...
"""
def __init__(self):
# game start: Key not found, drawer not opened.
self.has_key= False
self.has_opened_drawer= False
def go_south(self):
print "You can see a key just lying there on the table! What luck!"
choice = raw_input("You better TAKE that!\n")
if choice == 'TAKE' :
print "You took the key!"
self.has_key= True
else:
print "You didn't take the key to freedom!?"
def go_east(self):
print "You can see a drawer here! Wonder what is inside?"
choice = raw_input("You can MOVEROOMS, or try to USE the drawer and TAKE what's inside...\n")
if choice == 'USE':
print "You try to open the drawer... \n"
if self.has_key:
print "You use the key to open the drawer and find a flashlight inside! Better TAKE it!"
self.has_opened_drawer= True
else:
print "It's locked! Better find a key...\n"
def input_loop(self):
while True:
choice= raw_input('Do you want to go SOUTH or EAST?\n')
if choice=='SOUTH':
self.go_south()
elif choice=='EAST':
self.go_east()
player= Character() # create a Character
player.input_loop() # and let the user control it
Instead of using global variables, you create a Character to store all necessary data, like whether the key was found, or whether the drawer has been opened. That way you won't clutter your global scope with variables.
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(">")