patternpythonModerate
Simple adventure game
Viewed 0 times
gamesimpleadventure
Problem
I'm new to programming, became interested in learning a while ago and only got to it recently. I'm working on a very simple text-based adventure game using Python, and would like some tips on simplifying my code. Any other tips are also welcome. Please don't criticize the storyline though, since this is not the point of this post.
```
def prompt():
x = raw_input("What should you do? ")
return x
def cpuprompt1():
x = raw_input("Enter a website or [exit].")
return x
def cpuprompt2():
x = raw_input("NAME/PASSWORD please. Type [exit] to exit.")
return x
def trailerpk1():
print "You're in the trailer park."
print "You have your [door] close to you and an unknown [stoner] standing next to a car."
command3 = prompt()
if command3 == "stoner":
print "[STONER]: Hey! Want to take a hit?"
print "[YOU]: Would love to!"
print "You take a hit. Some dank shit."
print "You start seeing things... some weird things..."
print "www.plan7286.org"
trailerpk2()
command5 = prompt()
if command5 == "door":
home1()
elif command3 == "door":
home()
def trailerpk2():
print "What was that?!"
print "You have your [door] close to you."
def trailerpk3():
print "You're in the trailer park. Nothing too interesting here."
print "Your [door] is right next to you. You should probably go home."
def trailerpk4():
print "You're in the trailer park. I should probably take one more hit with that [stoner] over there."
command2 = prompt()
if command2 == "stoner":
stoner1()
def trailerpk5():
print "The stoner is gone. You should probably head to that [lake]!"
command2 = prompt()
if command2 == "lake":
lake1()
def trailerpk6():
print "You're at the trailer park. The stoner is gone."
print "You can either go to the [lake] or [home]"
command2 = prompt()
if command2 == "lake":
lake2()
el
```
def prompt():
x = raw_input("What should you do? ")
return x
def cpuprompt1():
x = raw_input("Enter a website or [exit].")
return x
def cpuprompt2():
x = raw_input("NAME/PASSWORD please. Type [exit] to exit.")
return x
def trailerpk1():
print "You're in the trailer park."
print "You have your [door] close to you and an unknown [stoner] standing next to a car."
command3 = prompt()
if command3 == "stoner":
print "[STONER]: Hey! Want to take a hit?"
print "[YOU]: Would love to!"
print "You take a hit. Some dank shit."
print "You start seeing things... some weird things..."
print "www.plan7286.org"
trailerpk2()
command5 = prompt()
if command5 == "door":
home1()
elif command3 == "door":
home()
def trailerpk2():
print "What was that?!"
print "You have your [door] close to you."
def trailerpk3():
print "You're in the trailer park. Nothing too interesting here."
print "Your [door] is right next to you. You should probably go home."
def trailerpk4():
print "You're in the trailer park. I should probably take one more hit with that [stoner] over there."
command2 = prompt()
if command2 == "stoner":
stoner1()
def trailerpk5():
print "The stoner is gone. You should probably head to that [lake]!"
command2 = prompt()
if command2 == "lake":
lake1()
def trailerpk6():
print "You're at the trailer park. The stoner is gone."
print "You can either go to the [lake] or [home]"
command2 = prompt()
if command2 == "lake":
lake2()
el
Solution
Prompt
A few mistakes made while prompting the user for an action:
The first thing you can do to improve that is redefine
You can eliminate the need for intermediate variables by chaining operators:
You can then call it using
Next you’ll want to check if the action makes sense. You can either add an
You can then use it like so, for instance:
or like:
But, as you can see, there are quite some repetitions involved here. Let’s try something better.
On recursion and expanding your story
One of the main drawback of your code, beside user input, is that it’s hard to follow the path of the story. Worse, when you’ll want to expand some part of the story you might have to spend quite some time to figure out (again) the interactions between methods.
The last thing to note is that you’re using functions calls within functions calls within functions calls… and if your story grows bigger and bigger, you may end up with some users getting a
One way to handle that (and remove the redundancy we saw above) is to use dictionaries. They allow you to map things to other things. In your case, you can map places to actions; and actions to other places. For instance:
I simplified on purpose, but see how close to your functions this code look? The advantage being that you can better see how the different actions lead to different places.
An other advantage appears when checking for valid actions. Since you already have a structure that store them, there is no need for redundancy:
You can then have a unique
OK, we’ve got some navigation going on but the s
A few mistakes made while prompting the user for an action:
- You use an intermediate variable but don't make anything out of it before returning it;
- Your
prompt,cpuprompt1, andcpuprompt2are very similar: you could simplify the overall design by using a default argument inprompt;
- You never check for user input and assume it will always fit the proposed choices: what if the user inputs
'home'intrailerpk5? Or'Door'at the very beginning? It’s the end of story without notice.
The first thing you can do to improve that is redefine
prompt as such:def prompt(message="What should you do? "):
answer = raw_input(message)
stripped = answer.strip()
lowered = stripped.lower()
return loweredYou can eliminate the need for intermediate variables by chaining operators:
def prompt(message="What should you do? "):
return raw_input(message).strip().lower()You can then call it using
prompt() as you already do or using prompt("Enter a website or [exit]. ") or prompt("NAME/PASSWORD please. Type [exit] to exit. ") to replace cpuprompt1 and cpuprompt2.Next you’ll want to check if the action makes sense. You can either add an
else clause in the caller so that inputing 'stone' in trailerpk1 (for instance) will execute it again, or you can handle it in prompt by using variable-length arguments:def prompt(*args, message="What should you do? "):
answer = raw_input(message).strip().lower()
if args:
# Check that the user inputed something useful
while answer not in args:
print "Unknown action, try again."
answer = raw_input(message).strip().lower()
return answerYou can then use it like so, for instance:
def trailerpk7():
print "You're at the trailer park. You can either go to the [lake] or [home]"
action = prompt('lake', 'home')
if command2 == "lake":
lake3()
else: # We know that nothing else than 'lake' or 'home' has been inputed
home4()or like:
def computer():
print "Your computer. Many hours spent here."
computercmd1 = cpuprompt1("www.plan7286.org", "exit", message="Enter a website or [exit]. ")
if computercmd1 == "www.plan7286.org":
print "Welcome to the official Plan 7286 website."
computercmd2 = cpuprompt2("Todd Henley/indigo7286", "exit", message="NAME/PASSWORD please. Type [exit] to exit. ")
if computercmd2 == "Todd Henley/indigo7286":
print "Welcome, Todd."
print "36.444890, -116.688752"
else:
home()
else:
home()But, as you can see, there are quite some repetitions involved here. Let’s try something better.
On recursion and expanding your story
One of the main drawback of your code, beside user input, is that it’s hard to follow the path of the story. Worse, when you’ll want to expand some part of the story you might have to spend quite some time to figure out (again) the interactions between methods.
The last thing to note is that you’re using functions calls within functions calls within functions calls… and if your story grows bigger and bigger, you may end up with some users getting a
RecursionError: maximum recursion depth exceeded.One way to handle that (and remove the redundancy we saw above) is to use dictionaries. They allow you to map things to other things. In your case, you can map places to actions; and actions to other places. For instance:
MAP = {
"HOME": {
"door": "PARK1",
"computer": "COMPUTER1",
},
"PARK1": {
"door": "HOME",
"stoner": "PARK2",
},
"COMPUTER1": {
"www.plan7286.org": "COMPUTER2",
"exit": "HOME",
},
"COMPUTER2": {
"exit": "HOME",
},
}I simplified on purpose, but see how close to your functions this code look? The advantage being that you can better see how the different actions lead to different places.
An other advantage appears when checking for valid actions. Since you already have a structure that store them, there is no need for redundancy:
def go_elsewhere(starting_place, message="What should you do? "):
valid_actions = MAP[starting_place] # grab the content out of the MAP dictionary
# Note that `valid_actions` is also a dictionary
while True:
answer = raw_input(message).strip().lower()
if answer in valid_actions:
# if the action actualy exists in the second dictionary, we’re all good
break
print "Unknown action, try again."
# Return the new place associated to the action
return valid_actions[answer]You can then have a unique
story function that will just loop and print messages related to places:def story():
place = "HOME"
while place != "PARK2": # stop here since we didn't implement after that
place = go_elsewhere(place)OK, we’ve got some navigation going on but the s
Code Snippets
def prompt(message="What should you do? "):
answer = raw_input(message)
stripped = answer.strip()
lowered = stripped.lower()
return lowereddef prompt(message="What should you do? "):
return raw_input(message).strip().lower()def prompt(*args, message="What should you do? "):
answer = raw_input(message).strip().lower()
if args:
# Check that the user inputed something useful
while answer not in args:
print "Unknown action, try again."
answer = raw_input(message).strip().lower()
return answerdef trailerpk7():
print "You're at the trailer park. You can either go to the [lake] or [home]"
action = prompt('lake', 'home')
if command2 == "lake":
lake3()
else: # We know that nothing else than 'lake' or 'home' has been inputed
home4()def computer():
print "Your computer. Many hours spent here."
computercmd1 = cpuprompt1("www.plan7286.org", "exit", message="Enter a website or [exit]. ")
if computercmd1 == "www.plan7286.org":
print "Welcome to the official Plan 7286 website."
computercmd2 = cpuprompt2("Todd Henley/indigo7286", "exit", message="NAME/PASSWORD please. Type [exit] to exit. ")
if computercmd2 == "Todd Henley/indigo7286":
print "Welcome, Todd."
print "36.444890, -116.688752"
else:
home()
else:
home()Context
StackExchange Code Review Q#110503, answer score: 10
Revisions (0)
No revisions yet.