I'm creating a text-based game in python and have hit a road block. I have a function that checks if user input contains certain words, and if it does it returns the user-input, otherwise it will re-ask for the input. If you write something that doesn't contains one of the words, it will re-call the function.
def contains_words(prompt, words):
user_input = raw_input(prompt).strip().lower()
if user_input == "instructions":
print
instructions()
print
contains_words(prompt, words)
elif user_input == "i" or user_input == "inventory":
if len(inventory) == 0:
print
print "There is nothing in your inventory."
print
contains_words(prompt, words)
else:
print "Your inventory contains: " + inventory
contains_words(prompt, words)
else:
if user_input in words:
return user_input
else:
print
print "I did not understand your answer, consider rephrasing."
contains_words(prompt , words)
Here is me calling it:
pizza = contains_words("Do you like pizza?", ["yes", "no"])
Within this function you can bring up the instructions or your inventory and then it will recall the function. Everything works like normal if you put one of the words in your answer the first time you are asked. The problem happens when you enter something incorrect, bring up the inventory or bring up the instructions. It causes the function to return nothing, instead of user-input. Why is this happening? Is it because the function resets so the parameter equal none?
Let's walk through a sample call of this function.
pizza = contains_words("Do you like pizza?", ["yes", "no"])
Say the user inputs instructions
. Your first if
statement is True
, so we enter that block, instructions()
is called (presumably printing instructions to the console), and contains_words
is called again. Let's say the user inputs yes
this time. We'll get down to the last if
statement, it'll be True
, and this call of contains_words
will return yes
-- to where it was called.
So, now we're back up the stack to the original call of contains_words
. The return value is ignored, because the function is called on a line by itself and not as an argument to another function or statement. Now we're done with this if
block, and the next thing in the function is ... nothing. The rest of the if
s. elif
s and else
s mean nothing (as the original if
evaluated to True
), and we drop out of the bottom of the function. It returns nothing (actually None
). (Check the type of pizza
to see.)
The solution is to either change your recursive calls to return contains_words(prompt, words)
so when the function drops out of each recursive call it passes the return value up the stack, or, since this is just tail-recursion anyway, replace it with a loop:
def contains_words(prompt, words):
while True:
user_input = raw_input(prompt).strip().lower()
if user_input == "instructions":
print
instructions()
print
elif user_input == "i" or user_input == "inventory":
if len(inventory) == 0:
print
print "There is nothing in your inventory."
print
else:
print "Your inventory contains: " + inventory
else:
if user_input in words:
return user_input
else:
print
print "I did not understand your answer, consider rephrasing."
Which will avoid memory issues involved with potentially many recursions.