changing response based on variable - python

I'm trying to figure out how to use an if statement before the assignment to change it is made. The point of this script is to check if the knife is taken before it prompts with the question to take it from the table. It's to make it so that you can walk back to the table and get another response if you've already taken it. What am I doing wrong?
def table ():
if knife_taken == False:
print "it's an old, brown wooden table, and atop it you find a knife"
print "Will you take the knife or go back?"
knife = raw_input ("> ")
if knife.strip().lower() in ["back", "b", "no"]:
basement2()
elif knife.strip().lower() in ["take knife", "knife", "yes", "k"]:
knife_taken = True
print "You now have the knife, good, you are going to need it"
raw_input()
basement2()
else:
print "I did not understand that."
raw_input()
table()
else:
print "There's nothing on the table"
raw_input()
basement2()

Basically when you change the variable knife_taken in your function you change it at a local level, this means when the function ends the changes are lost. There are two ways to fix this either use global (but thats the bad way)
global knife_taken
knife_taken = True
Or you can return the state of the knife from the function
return knife_taken
# later on
kitchen(knife_taken)
and store it in a variable, passing it back to kitchen later as an arguement
Or as an extra little bonus, you can store game state in a dictionary. You could then update the dictionary as the game state changes e.g.
game_state = {}
game_state['knife_taken'] = False
def kitchen():
if not game_state['knife_taken']:
print "Take the knife!"
game_state['knife_taken'] = True
else:
print "Nothing to see here."
kitchen()
kitchen()

Related

How do I get my code to run the if statement?

I'm a beginner in Python and I'm writing a code for a school project and ran into an early bug.
For some reason my if function won't run.
import time #imports computer time to program(buit in function)
count= 0
print(" Gymship") # center this
print("--------------------------------------") # this should go across the whole screen
print("Input a level to view the description or InputSign up to begin signing up for a card")
print("--------------------------------------------------------------------------")
print("Bronze")
time.sleep(1) # this wil pause the program for 1 second(for effect)
print("Silver")
time.sleep(1)
print("Gold")
time.sleep(1)
print("Platinum")
time.sleep(2)
print("-----------------------------------------------") # this should go across the whole screen
print("Sign up")
print(" ")
input()
if input == "Bronze":
print("Bronze")
print("--------------------------------------------")
print("You acquire a bronze card when you use two or less gym services")
print("2 Hours limit in the gym")
print("-------------------------------------")
print(input("Back to return to menu screen"))
count = count + 1
This is not correct:
input()
if input == "Bronze":
The way input() works is by returning a value. The name input refers to the function itself, so the function input will never equal the text "Bronze" unless you explicitly do something bad, like input = "Bronze" (it's bad because if you overwrite input, you'll no longer be able to access that function).
Instead, you should be using the returned value:
usr_input = input()
if usr_input == "Bronze":
Also, the line print(input("Back to return to menu screen")) is unnecessarily complicated; the print() will print whatever was returned by input(), but input() will display the "Back to return to menu screen" prompt without wrapping it in an if statement. So, input("Back to return to menu screen") is all you need. If you keep it the way you have it, if someone typed some text and then hit enter, the text would display again, because the print() is printing whatever that text was that the user typed.
You first need to assign a variable to the input and then check if the variable is equal to "Bronze"
Right now you are taking the input, but are not storing it anywhere. So the fixed code would be
user_input = input()
if user_input == "Bronze":

Is there a way to include either a user input prompt or a time.sleep() function within a key value pair of a dictionary?

I am working on a Python text RPG, and I'm using dictionaries to give initial information to the player about the area they're visiting. (see code for example). When the player types 'look' or 'examine,' I want the console to print out what I have in the value of the EXAMINATION key. What I'd like to have it do is print a section of text at a time, and either wait for the player to hit enter before continuing or at least wait a couple of seconds before printing the next block. Is there a way to achieve this? Perhaps I'm coming at this from the wrong direction?
import time
import sys
def prompt():
print("\n" + "=========================")
print("What would you like to do?")
player_action = input("> ")
acceptable_actions = ['move', 'go', 'travel', 'walk', 'quit', 'examine', 'inspect', 'interact', 'look']
while player_action.lower() not in acceptable_actions:
print("Unknown action, try again.\n")
player_action = input("> ")
if player_action.lower() == 'quit':
sys.exit()
elif player_action.lower() in ['move', 'go', 'travel', 'walk']:
player_move(player_action.lower())
elif player_action.lower() in ['examine', 'inspect', 'interact', 'look']:
player_examine(player_action.lower())
def player_examine(player_action):
if zonemap[myPlayer.location][SOLVED]:
print("There's nothing more here to examine.")
elif zonemap[myPlayer.location][EXAMINATION]:
slowprint(zonemap[myPlayer.location][EXAMINATION])
ZONENAME = ''
DESCRIPTION = 'description'
EXAMINATION = 'examine'
SOLVED = False
UP = 'up', 'north'
DOWN = 'down', 'south'
LEFT = 'left', 'west'
RIGHT = 'right', 'east'
zonemap = {
'Fields': {
ZONENAME: "Western Fields",
DESCRIPTION: "A grassy field to the west of town.",
EXAMINATION: "The grass in this field is extremely soft." + input("> ") + "The wind feels cool on your face." + time.sleep(2) + "The sun is beginning to set.",
SOLVED: False,
UP: "The Mountains",
DOWN: "The Town",
LEFT: "",
RIGHT: "The Ocean",
},
When trying to use the time.sleep() method, I get the following error:
TypeError: can only concatenate str (not "NoneType") to str
When trying to use the input("> ") function, the text simply prints on without waiting.
Your approach doesn't work because you are immediately calling the input() or time.sleep() functions as you build the dictionary. time.sleep(), for example, returns None and that's why you get your error.
You need to call those functions later on, when you retrieved the value from the dictionary and actually want to 'slow print' the description.
You can do so in loads of different ways. You could
use a sequence (such as a list or a tuple) of strings instead of a single string, and have your slowprint() function accept a sequence and pause after printing each element.
use a sequence of strings and mix in special values that slowprint() looks for to do different things, like sleeping or asking for input.
Store a function in the dictionary, that you then call. Functions are objects too, just like strings. The function would handle all the printing and pausing.
E.g. storing a tuple of strings:
EXAMINATION: (
"The grass in this field is extremely soft.",
"The wind feels cool on your face.",
"The sun is beginning to set.",
)
then have your slowprint() function handle that:
def slowprint(lines):
"""Print each line with a pause in between"""
for line in lines:
print(line)
input("> ") # or use time.sleep(2), or some other technique
The second option, to insert special values, gives you the most power to delegate all sorts of extra functionality to other code. You'd need to test for the type of object in the sequence, but this would let you insert arbitrary actions in your examination description. Like the difference between sleeping and asking for the user to hit a key:
class ExaminationAction:
def do_action(self):
# the default is to do nothing
return
class Sleep(ExaminationAction):
def __init__(self, duration):
self.duration = duration
def do_action(self):
time.sleep(self.duration)
class Prompt(ExaminationAction):
def __init__(self, prompt):
self.prompt = prompt
def do_action(self):
return input(self.prompt)
and have the slowprint() function look for these instances:
def slowprint(examine_lines):
for action_or_line in examine_lines:
if isinstance(action_or_line, ExamineAction):
# special action, execute it
action_or_line.do_action()
else:
# string, print it
print(action_or_line)
You can make any number such actions; the point is that they all subclass ExamineAction so can be distinguished from plain strings. Put them into your sequence for the EXAMINATION key:
EXAMINATION: (
"The grass in this field is extremely soft.",
Prompt("> "),
"The wind feels cool on your face.",
Sleep(2),
"The sun is beginning to set.",
)
The possibilities are endless.

How to return to beginning of loop?

search_room = raw_input("Search the:")
if search_room == "classroom":
print "You quitly make your way to the classroom, which is empty besides last night's homework"
sleep(3)
print "Enter 'inspect' into the command line to inspect the homework, or enter exit, to return to the kitchen."
action = raw_input("Command:")
if action == "inspect":
print "Hmph, uncompleted. Thats strange."
print "Enter 'inspect' into the command line to inspect the homework, or enter exit, to return to the kitchen."
action = raw_input("Command:")
if action == "exit":
print "you return to the kitchen"
search_room = raw_input("Search the:")
if action == "classroom":
I'm trying to figure out how to have this loop so i one could travel back and forth between the kitchen and the classroom, but if I try to go back to the classroom after exiting, I get an error message regarding a later 'for loop'.
If I understand your question correctly, your trying to figure out how to set up a loop that will let you go from kitchen back to classroom and so on and so forth without needing to nest an infinite amount of conditionals. I suggest you have an outer while(true) loop power the sequence of steps, and add conditions to check if a move is valid (to go to to the kitchen you must currently be in the classroom and have entered exit, ect)
You need to put the code block inside its own loop with a simple boolean sentinel value (while not stop) and if stop is set to true at any point, the otherwise endless loop will stop. Also remember the importance of python indentations for distinguishing code scopes, different from languages like java where it doesn't matter where you put the code as long as it is between the { }. Also consecutive if statements will each be executed individually unless you use if..elif which is what I think you want because you are comparing the same variable in the same scope.
Also if you have more than two rooms, like something in the game Clue, you should define some sort of scoping for each room. If you are in a room, which rooms can you access from there? I did this just with a simple dictionary scopes where each room is associated with a list of rooms it can access which is verified on getting search_room. They only have access to each other right now, but you can add more to each list to increase scope to other rooms (and add more if branches)
stop = false;
scopes = {"kitchen": ["classroom"], "classroom": ["kitchen"]}
locCur = "kitchen" #starting room
locPrev = "kitchen"
while not stop:
search_room = raw_input("Search the:")
if scopes[locCur].index(search_room) > -1 : #validate the room choice
if search_room == "classroom":
locCur = "classroom" #update current scope
print "You quietly make your way to the classroom, which is empty besides last night's homework"
sleep(3)
print "Enter 'inspect' into the command line to inspect the homework, or enter exit, to return to the kitchen."
action = raw_input("Command:")
if action == "inspect":
print "Hmph, uncompleted. Thats strange."
print "Enter 'inspect' into the command line to inspect the homework, or enter exit, to return to the kitchen."
action = raw_input("Command:")
if action == "inspect":
#print/do something else
elif action == "exit":
locCur = locPrev #set scope back to what it was
print "you return to the " + locPrev
locPrev = "classroom" #store this location
continue
elif search_room == "kitchen":
#do something for this room
print "message"
continue
elif search_room == "some other room":
#do something for this room
continue
elif search_room == "stop":
stop = true

What is wrong with my simple code here?

Hi I am having problems writing this simple program. I am just starting out with Python and was hoping for some help. When I run the start() function at the bottom of the programme, everything works fine until after the first raw_input(). If the user types "get coffee" for example, the string "Fair enough take a break" is printed but after this, rather than running the coffee() function like I would like, it just loops through to the start() function again.
Would someone be able to help please?
Thanks a lot.
def engine(next_scene):
scenes = {"start":start(),"coffee":coffee(),"work":work()}
return scenes[next_scene]
def start():
print "you are in the office"
print "you wonder what to do"
action = raw_input("what do you do? Get coffee or work?")
if action == "get coffee":
print "Fair enough take a break"
next_scene = "coffee"
engine(next_scene)
if action == "work":
print "Good man, you are well on your way to being a coder"
next_scene = "work"
engine(next_scene)
def coffee():
print "You walk out of the room"
print "You head down the stairs and into the cafe"
print "You order an espresso"
print "You neck it down"
print "Yumm"
print "You are wired"
action = raw_input("Now what? Work or go home? > ")
if action == "work":
print "You head back upstairs"
next_scene = "work"
engine(next_scene)
if action == "go home":
print "You lazy git"
def work():
print "You beaver away and become a cool coder"
next_scene = "start"
engine(next_scene)
start()
This
scenes = {"start":start(),"coffee":coffee(),"work":work()}
should be
scenes = {"start":start,"coffee":coffee,"work":work}
You called the functions in the dictionary definition, but you just want to get the function object.
Your engine function should like.
def engine(next_scene):
scenes = {"start":start,"coffee":coffee,"work":work}
scenes[next_scene]()

How to make a function change the True/False statements for other functions

Here's the basic idea I'm having trouble with: I'm trying to make a simple game where you are in one room and you have 2 rooms branching from the first that need to be "completed" before continuing. I want the 2'nd and 3'rd room to change my original True statements to False statements that all need to be switched before proceeding in the game.
from sys import exit
def room_1():
print "You're in room one, there are two doors to room 2 and 3."
print "Where do you want to go?"
done_2=True
done_3=True
while True:
move=raw_input("'room 2' or 'room 3'? >")
if move == 'room 2':
room_2()
elif move == 'room 3':
room_3()
else:
print "not a valid answer"
print "You Win!"
exit(0)
def room_2():
print "You finished room 2!"
done_1=False
raw_input('Press button')
room_1()
def room_3():
print "You finished room 3!"
raw_input('press button')
done_3=False
room_1()
room_1()
How do I change the done_ statements from within rooms 2 and 3?
~
In Python, you have to declare global variables before you can assign to them; otherwise, any assignment will shadow the global variable.
def room_2():
global done_1 # <- right here
print "You finished room 2!"
done_1=False
raw_input('Press button')
room_1()
def room_3():
global done_3 # <- right here
print "You finished room 3!"
raw_input('press button')
done_3=False
room_1()
However!
This is generally bad style, especially for such a simple case as this. It makes it more difficult to reason about how your functions work, what they change, and in what order.
It'd be much easier, more readable, and simpler to just return True or False from your functions as needed.
If you try to think of your functions as "black boxes" which have inputs, and guarantee certain outputs, it will generally help in avoiding many confusing bugs that can arise.
You need to declare done_1 and done_2 as global variables, outside of function room_1()

Categories