Part 2: Go places
Contents
Part 2: Go places#
In this section we’ll be writing the go command, and the system to go from
one place to another.
To start out we’ll add just two places: "home" and the "town-square". A map
of the game world would look something like this:
You are welcome to add your own places. However, I strongly recommend that you
first get your go command working with these two places.
You also may want to keep a map of the game world in a docstring or another text file. Here’s an example of how you might represent a slightly more populated world.
1"""
2Text-based adventure game
3https://alissa-huskey.github.io/python-class/exercises/adventure.html
4
5 =========
6 World Map
7 =========
8
9 market
10 |
11 home -- town square -- woods -- hill
12 | |
13 bakery cave
14
15"""
Part 2.1: Split reply into command and arguments#
This will be the first command that we’ve written that takes an argument. That
is, the player needs to type not just go, but also which direction to go like
north.
That means we need to split the string that is returned from input() into a
list. That way we if the player types go north we can figure out that go is
the command, and north is the direction.
Demo
A. Define do_go()#
[ ]Define ado_go()function that takes one argument:args.[ ]Indo_go()printTrying to go: args
B. In main(), in the while loop#
[ ]Strip the value returned frominput()using the.strip()method.This means if a player enters
" quit"or"quit "the program still knows to calldo_quit().[ ]Call.split()onreplyand assign it to the variableargs.Now the
argsvariable will contain a list where each word is an item in the list.[ ]Use anifstatement to check ifargsis falsy. If it is,continue.This means that if a player doesn’t enter anything, the program will ignore it and start the loop over.
[ ]Remove the first item fromargsusing the.pop()method and assign it to the variablecommand.Now
commandwill contain the first word the player entered, andargswill contain a list of the remaining commands. If there were no additional words, thenargswill be an empty list.[ ]In each clause of theifstatement where we check the value ofreply, change it tocommand.[ ]Add anelifclause that checks ifcommandis equal to"g"or"go". If it is, calldo_go()and passargs.
Code
1"""
2Text-based adventure game
3https://alissa-huskey.github.io/python-class/exercises/adventure.html
4"""
5
6ITEMS = {
7 "elixir": {
8 "key": "elixir",
9 "name": "healing elixir",
10 "description": "a magical elixir that will heal what ails ya",
11 "price": -10,
12 },
13 "dagger": {
14 "key": "dagger",
15 "name": "a dagger",
16 "description": "a 14 inch dagger with a double-edged blade",
17 "price": -25,
18 }
19}
20
21def do_shop():
22 """List the items for sale."""
23 print("\nItems for sale.\n")
24
25 for item in ITEMS.values():
26 print(f'{item["name"]:<13} {item["description"]}')
27
28 print()
29
30def do_quit():
31 """Exit the game."""
32 print("Ok, goodbye.")
33 quit()
34
35def do_go(args):
36 """Move to a different place"""
37 print(f"Trying to go: {args}")
38
39def main():
40 print("Welcome!")
41 while True:
42 reply = input("> ").strip()
43 args = reply.split()
44
45 if not args:
46 continue
47
48 command = args.pop(0)
49
50 if command in ["q", "quit", "exit"]:
51 do_quit()
52
53 elif command in ["shop"]:
54 do_shop()
55
56 elif command in ["g", "go"]:
57 do_go(args)
58
59 else:
60 print("No such command.")
61 continue
62
63 print()
64
65if __name__ == "__main__":
66 main()
67
Part 2.2: Create PLAYER and PLACES#
Now we’ll make global PLACES dictionary which will store information about
the different areas in the game.
Like the ITEMS dictionary, PLACES will be a nested dictionary, where the
key is a unique identifier for each place, and the value is a dictionary with
detailed information about that place.
The keys of the child dictionary will be:
"key"– the same thing as the key"name"– a short description"description"– a longer description"east","west","north","south"– the key to the place in that direction. (More on that next.)
Here is an example:
PLACES = {
"home": {
"key": "home",
"name": "Your Cottage",
"east": "town-square",
"description": "A cozy stone cottage with a desk and a neatly made bed.",
},
}
The "north", "south", "east" and "west" values will be used to tell
which way the player can go from a particular place and what is in that
direction.
For example, going "east" from "home" is the "town-square".
PLACES = {
"home": {
"key": "home",
"name": "Your Cottage",
"east": "town-square",
...
},
"town-square": {
"key": "town-square",
"name": "The Town Square",
"west": "home",
...
},
}
PLACES = {
"home": {
"key": "home",
"name": "Your Cottage",
"east": "town-square",
...
},
"town-square": {
"key": "town-square",
"name": "The Town Square",
"west": "home",
...
},
}
Likewise, going "west" from the "town-square" is "home".
PLACES = {
"home": {
"key": "home",
"name": "Your Cottage",
"east": "town-square",
...
},
"town-square": {
"key": "town-square",
"name": "The Town Square",
"west": "home",
...
},
}
PLACES = {
"home": {
"key": "home",
"name": "Your Cottage",
"east": "town-square",
...
},
"town-square": {
"key": "town-square",
"name": "The Town Square",
"west": "home",
...
},
}
We’ll also make a global PLAYER dictionary that will save information about
the current game.
For now it will just have one key, the place, which point to where the player
is at. In the do_go() function, we will change that value to move the player
from one place to another.
PLAYER = {
"place": "home",
}
PLACES = {
"home": {
"key": "home",
"name": "Your Cottage",
"east": "town-square",
...
},
...
}
A. At the top of adventure.py#
[ ]Create aPLAYERdictionary with the key"place"and the value"home".[ ]Create aPLACESdictionary where the key is a unique identifier for each place. The value is a dictionary that with information about each place:"key"– the same thing as the key"name"– a short description"description"– a longer description"east","west","north","south"– the key to the place in that
Add two places,
"home"and"town-square".
Code
1"""
2Text-based adventure game
3https://alissa-huskey.github.io/python-class/exercises/adventure.html
4"""
5
6PLAYER = {
7 "place": "home",
8}
9
10PLACES = {
11 "home": {
12 "key": "home",
13 "name": "Your Cottage",
14 "east": "town-square",
15 "description": "A cozy stone cottage with a desk and a neatly made bed.",
16 },
17 "town-square": {
18 "key": "town-square",
19 "name": "The Town Square",
20 "west": "home",
21 "description": (
22 "A large open space surrounded by buildings with a burbling "
23 "fountain in the center."
24 ),
25 },
26}
27
28ITEMS = {
Part 2.3: Write message functions#
We’re going to take a brief interlude here to write a couple of functions for printing messages to the player.
We’ll add a debug() function which will print messages intended for us (the
programmer), but only if a global variable indicates that the program is in
debug mode.
We’ll also add a error() function which will print an error message.
Demo
A. At the top of adventure.py#
[ ]Add a global variableDEBUGand set it toTrue
Code
1"""
2Text-based adventure game
3https://alissa-huskey.github.io/python-class/exercises/adventure.html
4"""
5
6DEBUG = True
7
8PLAYER = {
9 "place": "home",
10}
11
B. Define debug()#
[ ]Write a function named:debugwith one parameter:message[ ]In the function, check ifDEBUGisTrue(or truthy)[ ]If so, then printmessage[ ]Bonus: Print something before it like"DEBUG: ", or"# ", so you can more easily tell that it is a debug message
Code
1def debug(message):
2 """Print a debug message if in debug mode."""
3 if not DEBUG:
4 return
5 print(f"# {message}")
C. Define error()#
[ ]Write a function named:errorwith one parameter:message[ ]Printmessagewith something before it like"Error: ".
Code
1def error(message):
2 """Print an error message."""
3 print(f"! Error: {message}\n")
D. Modify do_go()#
[ ]Calldebug()instead ofprint()for the messageTrying to go: args
Code
69def do_go(args):
70 """Move to a different place"""
71 debug(f"Trying to go: {args}")
E. In main(), in the while loop#
[ ]At the beginning of thewhileloop calldebug()with the messageYou are at: PLACE. ReplacePLACEwith the value in thePLAYERdictionary associated with the"place"keyThis will print a debug message with your current location every time the loop runs.
[ ]After assigningcommand, usedebug()to printcommandandargs.[ ]Callerror()instead ofprint()for the messageNo such command.
Code
73def main():
74 print("Welcome!")
75
76 while True:
77 debug(f"You are at: {PLAYER['place']}")
78
79 reply = input("> ").strip()
80 args = reply.split()
81
82 if not args:
83 continue
84
85 command = args.pop(0)
86 debug(f"Command: {command!r}, args: {args!r}")
87
88 if command in ["q", "quit", "exit"]:
89 do_quit()
90
91 elif command in ["shop"]:
92 do_shop()
93
94 elif command in ["g", "go"]:
95 do_go(args)
96
97 else:
98 error("No such command.")
99 continue
100
101 print()
F. Test debug messages#
[ ]Test withDEBUGset toTrueas well as withDEBUGset toFalse
Part 2.4: Fill in go command#
In this section we’ll be filling in the rest of the go command.
We’ll need to make sure that we get a valid direction in args. Then look up
where we are now from PLAYER["place"] and PLACES; and look up where we want
to go by looking at direction (ie "east") key in the current place dictionary.
Finally, we’ll change the current "place" in the PLAYER dictionary, and
print the "name" and "description".
Demo
A. Modify do_go(): ensure that the player typed a valid direction#
In this section we’ll be making sure there is at least one item in the args
list and that it is a valid direction.
[ ]Check to see ifargsis falsy, if so:[ ]Use theerror()function to print a message saying:"Which way do you want to go?"[ ]return
[ ]assign the first item of theargslist to the variabledirectionand make it lowercase[ ]Check ifdirectionis one of"north","south","east","west". If not:[ ]Use theerror()function to print a message saying:"Sorry, I don't know how to go: direction.")[ ]return
Code
69def do_go(args):
70 """Move to a different place"""
71 debug(f"Trying to go: {args}")
72
73 # make sure the player included a direction
74 if not args:
75 error("Which way do you want to go?")
76 return
77
78 # get the direction from arguments
79 # and make it lowercase
80 direction = args[0].lower()
81
82 # make sure it's a valid direction
83 if direction not in ('north', 'south', 'east', 'west'):
84 error(f"Sorry, I don't know how to go: {direction}.")
85 return
B. Modify do_go(): look up where the player is at#
In this section we’ll be using the PLAYER["place"] to get the current place
from the PLACES dictionary, as shown here.
[ ]get the value fromPLAYERassociated with the"place"key and assign it toold_name[ ]get the value fromPLACESassociated withold_nameand assign it toold_place
Code
87 # look up where the user is at now
88 old_name = PLAYER["place"]
89 old_place = PLACES[old_name]
C. Modify do_go(): look up what is in that direction from here#
In this section we’ll use the direction (ie. "east") the player wants to go
to look up the name of the next place (if any) in the current place dictionary
as seen here.
[ ]use the.get()method onold_placeto get the value associated with thedirectionkey and assign it tonew_name[ ]Check ifnew_nameis falsy. If so:[ ]Use theerror()function to print a message saying:"Sorry, you can't go direction from here.")[ ]return
Code
91 # look up what is in that direction from here
92 new_name = old_place.get(direction)
93
94 # print an error if there is nothing in that direction
95 if not new_name:
96 error(f"Sorry, you can't go {direction} from here.")
97 return
D. Modify do_go(): figure out where we’re going#
Next we’ll get the info for where the player is going from PLACES, or print an
error message if it’s not found.
[ ]use the.get()method onPLACESto get the value associated with thenew_namekey and assign it tonew_place[ ]Check ifnew_placeis falsy. If so:[ ]Use theerror()function to print a message saying:"Woops! The information about new_name seems to be missing."
This will only happen if you made a mistake somewhere in your code. But just in case we do, we want to have a clear error message so we can tell what went wrong.
[ ]return
Code
99 # look up the place information
100 new_place = PLACES.get(new_name)
101
102 # this should never happen if we write the code correctly
103 # but just in case there is no key in PLACES matching
104 # the new name, print an error
105 if not new_place:
106 error(f"Woops! The information about {new_name} seems to be missing.")
107 return
E. Modify do_go(): update the players place and describe it#
Finally, we can now update the PLAYER dictionary to point to the new place
name and print the place information.
[ ]In thePLAYERdictionary change value associated with the"place"key tonew_name[ ]Print the values associated with the"name"and"description"keys of thenew_placedictionary
Code
109 # move the player to the new place
110 PLAYER["place"] = new_name
111
112 # print information about the new place
113 print(f"\n{new_place['name']}\n")
114 print(new_place["description"], "\n")