5
PREPARING THE SPACE STATION EQUIPMENT

image

Now that the space station walls are in place, we can start installing the equipment. We’ll need detailed information about the different pieces of equipment, including the furniture, survival systems, and experimental machinery. In this chapter, you’ll add information about all the items on the space station, including their images and descriptions. You’ll also experiment with designing your own room and view it using the Explorer program you created in Chapter 4.

CREATING A SIMPLE PLANETS DICTIONARY

To store the information about the space station equipment, we’ll use a programming concept called dictionaries. A dictionary is a bit like a list but with a built-in search engine. Let’s take a closer look at how it works.

UNDERSTANDING THE DIFFERENCE BETWEEN A LIST AND A DICTIONARY

As with a paper dictionary, you can use a word or phrase to look up information in a Python dictionary. That word or phrase is called the key, and the information linked to the key is called the value. Unlike in a paper dictionary, the entries in a Python dictionary can be in any order. They don’t have to be alphabetical. Python can go directly to the entry you need, wherever it is.

Imagine you have a list that contains information about previous space missions. You could get the first item from that list by using this line:

print(mission_info[0])

If mission_info was a dictionary instead of a list, you could use a mission name instead of an index number to get the information on that mission, like this:

print(mission_info["Apollo 11"])

The key can be a word or phrase but can also be a number. We’ll start by using words because it’s easier to understand the difference between a list and a dictionary that way.

MAKING AN ASTRONOMY CHEAT SHEET DICTIONARY

All astronauts need a good understanding of the solar system, so let’s learn about the planets as we build our first dictionary. We’ll use the planet names as the keys and connect each name to information about that planet.

Take a look at Listing 5-1, which creates a dictionary called planets. When you make a dictionary, you use curly brackets {} to mark the start and end of it, instead of the square brackets you use for a list.

Each entry in the dictionary is made up of the key, followed by a colon and then the information for that entry. As with a list, we separate the entries with commas and put double quotes around pieces of text.

Open a new file in IDLE (File New File) and enter the following program. Save it as listing5-1.py.

listing5-1.py

   planets = { "Mercury": "The smallest planet, nearest the Sun",
               "Venus": "Venus takes 243 days to rotate",
               "Earth": "The only planet known to have native life",
               "Mars": "The Red Planet is the second smallest planet",
               "Jupiter": "The largest planet, Jupiter is a gas giant",
               "Saturn": "The second largest planet is a gas giant",
               "Uranus": "An ice giant with a ring system",
               "Neptune": "An ice giant and farthest from the Sun"
               }

while True:
     query = input("Which planet would you like information on? ")
     print(planets[query])

Listing 5-1: Your first dictionary program

This program doesn’t use Pygame Zero, so you can run it by clicking Run Run Module at the top of the IDLE window. (It will still work if you run it using pgzrun, but it’s easier to use the menu.) When you run the program, it asks you which planet you want information on using the input() built-in function . Try entering Earth or Jupiter for the planet name.

Which planet would you like information on? Earth
The only planet known to have native life
Which planet would you like information on? Jupiter
The largest planet, Jupiter is a gas giant

Whichever planet name you enter is stored in the variable query. That variable is then used to look up the information for that planet in the planets dictionary . Instead of using an index number inside the square brackets as we did with a list, we use the word we entered to get the information, and that word is stored in the variable query.

In Python, we can use a while loop to repeat a set of instructions. Unlike a for loop, which we use to repeat a certain number of times, a while loop usually repeats until something changes. Often in a game, the while command will check a variable to decide whether to keep repeating instructions. For example, the instruction while lives > 0 could keep a game going until the player runs out of lives. When the lives variable changes to 0, the instructions in the loop would stop repeating.

The while True command we use in listing5-1.py will keep repeating forever, because it means “while True is True,” which is always. For this while True command to work, make sure you capitalize True and place a colon at the end of the line.

Under the while command, we use four spaces to indent the instructions that should repeat. Here, we’ve indented the lines that ask you for a planet name and then give you the planet information, so they’re the instructions that repeat. After you enter a planet name and get the information, the program asks you for another planet name, and another, forever. Or until you stop the program by pressing CTRL-C, at least.

Although this program works, it isn’t complete yet. You might get an unhelpful error if you enter a planet name that isn’t in the dictionary. Let’s fix the code so it returns a useful message instead.

ERROR-PROOFING THE DICTIONARY

When you enter a key that isn’t in the dictionary, you’ll see an error message. Python looks for an exact match. So, if you try to look up something that isn’t in the dictionary or make even a tiny spelling mistake, you won’t get the information you want.

Dictionary keys, like variable names, are case sensitive, so if you type earth instead of Earth, the program will crash. If you enter a planet that doesn’t exist, this is what happens:

Which planet would you like information on? Pluto
Traceback (most recent call last):
  File "C:UsersSeanDocumentsEscapelisting5-1.py", line 13, in <module>
    print(planets[query])
KeyError: 'Pluto'
>>>

Poor Pluto! After 76 years of service, it was disqualified as a planet in 2006, so it’s not in our planets dictionary.

When the program looks for an item in the dictionary that isn’t there, it stops the program and drops you back at the Python shell prompt. To avoid this, we need the program to check whether the word entered is one of the keys in the dictionary before it tries to use it.

You can see which keys are in the dictionary by entering the dictionary name followed by a dot and keys(). The technical jargon for this is a method. Roughly speaking, a method is a set of instructions that you can attach to a piece of data using a period. Run the following code in the Python shell:

>>> print(planets.keys())
dict_keys(['Mars', 'Pluto', 'Jupiter', 'Earth', 'Uranus', 'Saturn', 'Mercury',
'Neptune', 'Venus'])

You might notice something odd here. When I completed Training Mission #1, I added Pluto to the dictionary as the last item. But in this output, it’s in second place in my list of keys. When you add items to a list, they’re placed at the end, but in a dictionary, that is not always the case. It depends on which version of Python you’re using. (The latest version does keep dictionary items in the same order you added them.) As mentioned earlier, the order of the keys in the dictionary doesn’t matter, though. Python figures out where the keys are in the dictionary, so you never need to think about it.

To stop the program from crashing when a user asks for information on a planet that isn’t in the dictionary, modify your program with the new lines shown in Listing 5-2.

listing5-2.py

   --snip--
   while True:
       query = input("Which planet would you like information on? ")
     if query in planets.keys():
         print(planets[query])
       else:
         print("No data available! Sorry!")

Listing 5-2: Error proofing the dictionary lookup

Save the program as listing5-2.py, and run it by clicking Run Run Module. Check that it works by entering a planet correctly, and then enter another planet that isn’t in the list of keys. Here’s an example:

Which planet would you like information on? Venus
Venus takes 243 days to rotate
Which planet would you like information on? Tatooine
No data available! Sorry!

We protect our program from crashing by making it check whether the key in query exists in the dictionary before the program tries to use it . If the key does exist, we use the query as we did before . Otherwise, we send a message to users telling them that we don’t have that information in our dictionary . Now the program is much friendlier.

PUTTING LISTS INSIDE DICTIONARIES

Our planet dictionary is a bit limited at the moment. What if we want to add extra information, such as whether the planet has rings and how many moons it has? To do so, we can use a list to store multiple pieces of information about a planet and then put that list inside the dictionary.

For example, here is a new entry for Venus:

"Venus": ["Venus takes 243 days to rotate", False, 0]

The square brackets mark the start and end of the list, and there are three items in the list: a short description, a True or False value that indicates whether or not the planet has rings, and the number of moons it has. Because Venus doesn’t have rings, the second entry is False. It also doesn’t have any moons, so the third entry is 0.

RED ALERT

True and False values need to start with a capital letter and shouldn’t be in quotes. The words turn orange when you type them correctly in IDLE.

Change your dictionary code so each key has a list, as shown in Listing 5-3, keeping the rest of the code the same. Remember that dictionary entries are separated by commas, so there’s a comma after the closing bracket for all the lists except the last one. Save your updated program as listing5-3.py.

I’ve slipped in information for Pluto too. Some speculate that Pluto might have rings, and exploration continues. By the time you read this book, our understanding of Pluto might have changed.

listing5-3.py

planets = { "Mercury": ["The smallest planet, nearest the Sun", False, 0],
            "Venus": ["Venus takes 243 days to rotate", False, 0],
            "Earth": ["The only planet known to have native life", False, 1],
            "Mars": ["The second smallest planet", False, 2],
            "Jupiter": ["The largest planet, a gas giant", True, 67],
            "Saturn": ["The second largest planet is a gas giant", True, 62],
            "Uranus": ["An ice giant with a ring system", True, 27],
            "Neptune": ["An ice giant and farthest from the Sun", True, 14],
            "Pluto": ["Largest dwarf planet in the Solar System", False, 5]
            }
--snip--

Listing 5-3: Putting a list in a dictionary

Run the program by selecting Run Run Module. Now when you ask for information on a planet, the program should display the entire list for that planet:

Which planet would you like information on? Venus
['Venus takes 243 days to rotate', False, 0]
Which planet would you like information on? Mars
['The second smallest planet', False, 2]

EXTRACTING INFORMATION FROM A LIST INSIDE A DICTIONARY

We know how to get a list of information from a dictionary, so the next step is to get individual pieces of information from that list. For example, the False entry doesn’t mean much by itself. If we can separate it from the list, we can add an explanation beside it so the results are easier to understand. We previously used lists inside lists for the room map in Chapter 4. Now, as then, we’ll use index numbers to get items from a list in a dictionary.

Because planets[query] is the entire list, we can see just the description (the first item in the list) by using planets[query][0]. We can see whether it has rings or not by using planets[query][1]. Briefly, here is what we’re doing:

  1. We’re using the planet name, stored in the variable query, to access a particular list from the planets dictionary.
  2. We’re using an index number to take an individual item from that list.

Modify your program to look like Listing 5-4. As before, change only the lines that are not grayed out. Save your program as listing5-4.py, and run it by clicking Run Run Module.

listing5-4.py

   --snip--
   while True:
       query = input("Which planet would you like information on? ")
       if query in planets.keys():
         print(planets[query][0])
         print("Does it have rings? ", planets[query][1])
       else:
           print("Databanks empty. Sorry!")

Listing 5-4: Displaying information from the list stored in the dictionary

When you run the listing5-4.py program, you should see something like the following:

Which planet would you like information on? Earth
The only planet known to have native life
Does it have rings?  False
Which planet would you like information on? Saturn
The second largest planet is a gas giant
Does it have rings?  True

This should work for every planet in the dictionary!

When you enter the name of a planet that’s in the dictionary, the program now prints the first item from its list of information, which is the description . On the next line, the program asks itself whether that planet has rings and then shows you the True or False answer, which is the second item in that planet’s list of information . You can display some text and some data using the same print() instruction, by separating them with a comma. The display is much clearer than printing the entire list, and the information is easier to understand.

MAKING THE SPACE STATION OBJECTS DICTIONARY

Let’s put our knowledge of how to use dictionaries, and lists inside dictionaries, to use in the space station. With all the furniture, life support equipment, tools, and personal effects required on the space station, there’s a lot of information to keep track of. We’ll use a dictionary called objects to store information about all the different items in the game.

We’ll use numbers as the keys for the objects. It’s simpler than using a word for each object. Also, using numbers makes it easier to understand the room map if you want to print it as we did in Chapter 4. There’s less risk of mistyping, too. When we create the code for the puzzles later, it’ll be less obvious what the solution is, which means there will be fewer spoilers if you’re building the game before playing it.

You might remember that we used the numbers 0, 1, and 2 to represent floor tiles, wall pillars, and soil in Chapter 4. We’ll continue using those numbers for those items, and the rest of the objects will use numbers 3 to 81.

Each entry in the dictionary is a list containing information about the item, similar to how we made the planets dictionary earlier in this chapter. The lists contain the following information for each object:

An object image file Different objects can use the same image file. For example, all the access cards use the same image.

A shadow image file We use shadows to enhance the 3D perspective in the game. The two standard shadows are images.full_shadow, which fills a full tile space and is for larger objects, and images.half_shadow, which fills half a tile space for smaller objects. Objects with a distinctive outline, such as the cactus, have their own shadow image file that is used only for that object. Some items, like the chair, have the shadow within the image file. Some items have no shadow, like the crater and any items the player can carry. When an image has no shadow, we write None where its shadow filename belongs in the dictionary. The word None is a special data type in Python. Like with True and False, you don’t need any quotes around it, and it should start with a capital letter. When you enter it correctly, None turns orange in the code.

A long description A long description is displayed when you examine or select an object while playing the game. Some of the long descriptions include clues, and others simply describe the environment.

A short description Typically just a few words, such as “an access card,” a short description is shown onscreen when you do something with the object while playing the game. For example, “You have dropped an access card.” A short description is only required for items that the player can pick up or use, such as an access card or the vending machine.

The game can reuse items in the objects dictionary. For example, if a room is made of 60 or more identical wall pillars, the game can just reuse the same wall pillar object. It only needs to be in the dictionary once.

There are some items that use the same image files but have other differences, which means we must store them separately in the dictionary. For example, the access cards have different descriptions depending on who they belong to, and the doors have different descriptions to tell you which key to use. Each access card and door has its own entry in the objects dictionary.

ADDING THE FIRST OBJECTS IN ESCAPE

Open listing4-3.py, which you created in Chapter 4. This listing contains the game map and the code to generate the room map. We’ll add to this program to continue building the Escape game.

First, we need to set up some additional variables. Before the adventure begins, a research craft, called the Poodle lander, crash-lands on the planet surface. We’ll store coordinates for a random crash site in these new variables. We’ll add these variables now because the map object (number 27) will require them for its description.

Add the new lines in Listing 5-5 to the VARIABLES section, marked out with a hashed box, in your existing listing4-3.py file. I recommend adding them at the end of your other variables, just above where the MAP section begins, so your listing and my listing are consistent. Save your program as listing5-5.py. The program won’t do anything new if you run it now, but if you want to try it, enter pgzrun listing5-5.py.

listing5-5.py

--snip--
###############
## VARIABLES ##
###############

--snip--

DEMO_OBJECTS = [images.floor, images.pillar, images.soil]

LANDER_SECTOR = random.randint(1, 24)
LANDER_X = random.randint(2, 11)
LANDER_Y = random.randint(2, 11)

###############
##    MAP    ##
###############
--snip--

Listing 5-5: Adding the crash site location variables

These new instructions create variables to remember the sector (or room number) the Poodle landed on, and its x and y position in that sector. The instructions use the random.randint() function, which picks a random number between the two numbers you give it. These instructions run once at the start of the game, so the lander location is different each time you play but doesn’t change during the game.

Now let’s add the first chunk of the objects data, shown in Listing 5-6. This section provides the data for objects 0 to 12. Because the player cannot pick up or use these objects, they don’t have a short description.

Place this section of the listing just above the MAKE MAP section of your existing program (listing5-5.py). To help you find your way around the listing, you can press CTRL-F in IDLE to search for a particular word or phrase. For example, try searching for make map to see where to start adding the code in Listing 5-6. After searching, click Close on the search dialog box. Remember that if you get lost in the listing, you can always refer to the complete game listing in Appendix A.

If you prefer not to type the data, use the file data-chapter5.py, in the listings folder. It contains the objects dictionary, so you can copy and paste it into your program. You can start by just pasting the first 12 items.

listing5-6.py

--snip--

assert len(GAME_MAP)-1 == MAP_SIZE, "Map size and GAME_MAP don't match"

###############
##  OBJECTS  ##
###############

objects = {
    0: [images.floor, None, "The floor is shiny and clean"],
    1: [images.pillar, images.full_shadow, "The wall is smooth and cold"],
    2: [images.soil, None, "It's like a desert. Or should that be dessert?"],
    3: [images.pillar_low, images.half_shadow, "The wall is smooth and cold"],
    4: [images.bed, images.half_shadow, "A tidy and comfortable bed"],
    5: [images.table, images.half_shadow, "It's made from strong plastic."],
    6: [images.chair_left, None, "A chair with a soft cushion"],
    7: [images.chair_right, None, "A chair with a soft cushion"],
    8: [images.bookcase_tall, images.full_shadow,
        "Bookshelves, stacked with reference books"],
    9: [images.bookcase_small, images.half_shadow,
        "Bookshelves, stacked with reference books"],
    10: [images.cabinet, images.half_shadow,
         "A small locker, for storing personal items"],
    11: [images.desk_computer, images.half_shadow,
         "A computer. Use it to run life support diagnostics"],
    12: [images.plant, images.plant_shadow, "A spaceberry plant, grown here"]
    }

###############
## MAKE MAP  ##
###############
--snip--

Listing 5-6: Adding the first objects

Remember that the colors of the code can help you spot errors. If your text sections aren’t green, you’ve left out the opening double quotes. If there is too much green, you might have forgotten the closing double quotes. Some of the lists continue on the next line, and Python knows the list isn’t complete until it sees the closing bracket. If you struggle to get any of the listings to work, you can use my version of the code (see “Using My Example Listings” on page 21) and pick up the project from any point.

Listing 5-6 looks similar to our earlier planets dictionary: we use curly brackets to mark the start and end of the dictionary, and each entry in the dictionary is a list so it is inside square brackets. The main difference is that this time the key is a number instead of a word.

Save your new program as listing5-6.py. This program uses Pygame Zero for the graphics, so you need to run your new program by entering pgzrun listing5-6.py. It should work the same as it did previously because we’ve added new data but haven’t done anything with that data yet. It’s worth running the program anyway, because if you see an error message in the command line window, you can fix the new code before you go any further.

VIEWING OBJECTS WITH THE SPACE STATION EXPLORER

To see the objects, we have to tell the game to use the new dictionary. Change the following line in the EXPLORER part of the program from this:

image_to_draw = DEMO_OBJECTS[room_map[y][x]]

to the following:

image_to_draw = objects[room_map[y][x]][0]

This small change makes the Explorer code use our new objects dictionary instead of the DEMO_OBJECTS list we told it to use previously.

Notice that we’re now using lowercase letters instead of capital letters. In this program, I use capital letters for constants whose values won’t change. The DEMO_OBJECTS list never changed: it was only used for looking up the image filenames. But the objects dictionary will sometimes have its content changed as the game is played.

The other difference is that [0] is on the end of the line now. This is because when we pull an item from the objects dictionary, it gives us an entire list of information. But we just want to use the image here, which is the first item in that list, so we use the index number [0] to extract it.

Save the program and run it again, and you should see that the rooms look the same as before. That’s because we haven’t added any new objects yet, and we kept the object numbers for the floor, wall, and soil the same as the index numbers we were using for them before.

DESIGNING A ROOM

Let’s add some items to the room display. In the EXPLORER section of the code, add the new lines shown in Listing 5-7:

listing5-7.py

--snip--

###############
## EXPLORER  ##
###############

def draw():
    global room_height, room_width, room_map
    print(current_room)
    generate_map()
    screen.clear()
    room_map[2][4] = 7
    room_map[2][6] = 6
    room_map[1][1] = 8
    room_map[1][2] = 9
    room_map[1][8] = 12
    room_map[1][9] = 9
--snip--

Listing 5-7: Adding some objects in the room display

These new instructions add objects to the room_map list at different positions before the room is displayed.

Remember that room_map uses the y-coordinate before the x-coordinate. The first index number says how far from the back of the room the objects are; the smaller the number the nearer to the back they are. The smallest useful number is usually 1 because the wall is in row 0.

The second number says how far across the room the objects are, from left to right. There’s usually a wall in column 0, so 1 is the smallest useful number for this position too.

The number on the other side of the equal sign is the key for a particular object. You can check which object each number represents by looking at the objects dictionary in Listing 5-6.

So this line:

room_map[1][1] = 8

places object 8 (a tall bookcase) into the top-left corner of the room. And this line:

room_map[2][6] = 6

places a chair (object 6) three rows from the top and seven positions from the left. (Remember that index numbers start at 0.)

Save your program as listing5-7.py and enter pgzrun listing5-7.py to run it. Figure 5-1 shows what you should see now.

image

Figure 5-1: Cozy! Some objects displayed in the space station Explorer program

Because the Explorer program is just a demo, some things don’t work yet. For example, some objects have a black square under them because there’s no floor tile there. Also, all the rooms look the same because we’ve coded the objects into the EXPLORER section, so they appear in every room we display. This means you can’t view all the rooms anymore, because the objects won’t fit in some of them. As a result, you can’t use the arrow keys to look at all the rooms. The program doesn’t display wide objects such as the bed correctly yet, either. We’ll fix all of these problems later, but we can continue building and testing the space station in the meantime.

ADDING THE REST OF THE OBJECTS

So far we’ve added objects 0 to 12 to the objects dictionary. There are 81 objects in total in the game, so let’s add the rest now by adding the new lines in Listing 5-8. Remember to add a comma after item 12 before adding the rest of the items in the dictionary.

When the same filename or a similar description is used for more than one object, you can just copy and paste it. To copy code, click and hold down the mouse button at the beginning of the chunk of code, move the mouse to highlight it, and then press CTRL-C. Then click the mouse where you want to paste that code and press CTRL-V. Remember too that you can copy and paste the whole dictionary from the data-chapter5.py file if you want to save time typing.

Save the program as listing5-8.py. You can test that the program still works by entering pgzrun listing5-8.py, although you won’t see anything new yet.

This is Listing 5-8:

listing5-8.py

   ###############
   ##  OBJECTS  ##
   ###############

   objects = {
       0: [images.floor, None, "The floor is shiny and clean"],
       --snip--

       12: [images.plant, images.plant_shadow, "A spaceberry plant, grown locally"],
     13: [images.electrical1, images.half_shadow,
            "Electrical systems used for powering the space station"],
       14: [images.electrical2, images.half_shadow,
            "Electrical systems used for powering the space station"],
       15: [images.cactus, images.cactus_shadow, "Ouch! Careful on the cactus!"],
       16: [images.shrub, images.shrub_shadow,
            "A space lettuce. A bit limp, but amazing it's growing here!"],
       17: [images.pipes1, images.pipes1_shadow, "Water purification pipes"],
       18: [images.pipes2, images.pipes2_shadow,
            "Pipes for the life support systems"],
       19: [images.pipes3, images.pipes3_shadow,
            "Pipes for the life support systems"],
     20: [images.door, images.door_shadow, "Safety door. Opens automatically
   for astronauts in functioning spacesuits."],
       21: [images.door, images.door_shadow, "The airlock door.
   For safety reasons, it requires two person operation."],
       22: [images.door, images.door_shadow, "A locked door. It needs "
            + PLAYER_NAME + "'s access card"],
       23: [images.door, images.door_shadow, "A locked door. It needs "
            + FRIEND1_NAME + "'s access card"],
       24: [images.door, images.door_shadow, "A locked door. It needs "
            + FRIEND2_NAME + "'s access card"],
       25: [images.door, images.door_shadow,
            "A locked door. It is opened from Main Mission Control"],
       26: [images.door, images.door_shadow,
            "A locked door in the engineering bay."],
     27: [images.map, images.full_shadow,
            "The screen says the crash site was Sector: "
            + str(LANDER_SECTOR) + " // X: " + str(LANDER_X) +
            " // Y: " + str(LANDER_Y)],
       28: [images.rock_large, images.rock_large_shadow,
            "A rock. Its coarse surface feels like a whetstone", "the rock"],
       29: [images.rock_small, images.rock_small_shadow,
            "A small but heavy piece of Martian rock"],
       30: [images.crater, None, "A crater in the planet surface"],
       31: [images.fence, None,
            "A fine gauze fence. It helps protect the station from dust storms"],
       32: [images.contraption, images.contraption_shadow,
            "One of the scientific experiments. It gently vibrates"],
       33: [images.robot_arm, images.robot_arm_shadow,
            "A robot arm, used for heavy lifting"],
       34: [images.toilet, images.half_shadow, "A sparkling clean toilet"],
       35: [images.sink, None, "A sink with running water", "the taps"],
       36: [images.globe, images.globe_shadow,
            "A giant globe of the planet. It gently glows from inside"],
       37: [images.science_lab_table, None,
            "A table of experiments, analyzing the planet soil and dust"],
       38: [images.vending_machine, images.full_shadow,
            "A vending machine. It requires a credit.", "the vending machine"],
       39: [images.floor_pad, None,
            "A pressure sensor to make sure nobody goes out alone."],
       40: [images.rescue_ship, images.rescue_ship_shadow, "A rescue ship!"],
       41: [images.mission_control_desk, images.mission_control_desk_shadow,
            "Mission Control stations."],
       42: [images.button, images.button_shadow,
            "The button for opening the time-locked door in engineering."],
       43: [images.whiteboard, images.full_shadow,
            "The whiteboard is used in brainstorms and planning meetings."],
       44: [images.window, images.full_shadow,
            "The window provides a view out onto the planet surface."],
       45: [images.robot, images.robot_shadow, "A cleaning robot, turned off."],
       46: [images.robot2, images.robot2_shadow,
            "A planet surface exploration robot, awaiting set-up."],
       47: [images.rocket, images.rocket_shadow, "A 1-person craft in repair."],
       48: [images.toxic_floor, None, "Toxic floor - do not walk on!"],
       49: [images.drone, None, "A delivery drone"],
       50: [images.energy_ball, None, "An energy ball - dangerous!"],
       51: [images.energy_ball2, None, "An energy ball - dangerous!"],
       52: [images.computer, images.computer_shadow,
            "A computer workstation, for managing space station systems."],
       53: [images.clipboard, None,
            "A clipboard. Someone has doodled on it.", "the clipboard"],
       54: [images.bubble_gum, None,
            "A piece of sticky bubble gum. Spaceberry flavour.", "bubble gum"],
       55: [images.yoyo, None, "A toy made of fine, strong string and plastic.
   Used for antigrav experiments.", PLAYER_NAME + "'s yoyo"],
       56: [images.thread, None,
            "A piece of fine, strong string", "a piece of string"],
       57: [images.needle, None,
            "A sharp needle from a cactus plant", "a cactus needle"],
       58: [images.threaded_needle, None,
            "A cactus needle, spearing a length of string", "needle and string"],
       59: [images.canister, None,
            "The air canister has a leak.", "a leaky air canister"],
       60: [images.canister, None,
            "It looks like the seal will hold!", "a sealed air canister"],
       61: [images.mirror, None,
            "The mirror throws a circle of light on the walls.", "a mirror"],
       62: [images.bin_empty, None,
            "A rarely used bin, made of light plastic", "a bin"],
       63: [images.bin_full, None,
            "A heavy bin full of water", "a bin full of water"],
       64: [images.rags, None,
            "An oily rag. Pick it up by a corner if you must!", "an oily rag"],
       65: [images.hammer, None,
            "A hammer. Maybe good for cracking things open...", "a hammer"],
       66: [images.spoon, None, "A large serving spoon", "a spoon"],
       67: [images.food_pouch, None,
            "A dehydrated food pouch. It needs water.", "a dry food pack"],
       68: [images.food, None,
            "A food pouch. Use it to get 100% energy.", "ready-to-eat food"],
       69: [images.book, None, "The book has the words 'Don't Panic' on the
   cover in large, friendly letters", "a book"],
       70: [images.mp3_player, None,
            "An MP3 player, with all the latest tunes", "an MP3 player"],
       71: [images.lander, None, "The Poodle, a small space exploration craft.
   Its black box has a radio sealed inside.", "the Poodle lander"],
       72: [images.radio, None, "A radio communications system, from the
   Poodle", "a communications radio"],
       73: [images.gps_module, None, "A GPS Module", "a GPS module"],
       74: [images.positioning_system, None, "Part of a positioning system.
   Needs a GPS module.", "a positioning interface"],
       75: [images.positioning_system, None,
            "A working positioning system", "a positioning computer"],
       76: [images.scissors, None, "Scissors. They're too blunt to cut
   anything. Can you sharpen them?", "blunt scissors"],
       77: [images.scissors, None,
            "Razor-sharp scissors. Careful!", "sharpened scissors"],
       78: [images.credit, None,
            "A small coin for the station's vending systems",
            "a station credit"],
       79: [images.access_card, None,
            "This access card belongs to " + PLAYER_NAME, "an access card"],
       80: [images.access_card, None,
            "This access card belongs to " + FRIEND1_NAME, "an access card"],
       81: [images.access_card, None,
            "This access card belongs to " + FRIEND2_NAME, "an access card"]
       }

items_player_may_carry = list(range(53, 82))
   # Numbers below are for floor, pressure pad, soil, toxic floor.
items_player_may_stand_on = items_player_may_carry + [0, 39, 2, 48]

   ###############
   ## MAKE MAP  ##
   ###############
   --snip--

Listing 5-8: Completing the objects data for the Escape game

Some of the lists for objects extend over more than one line in the program . This is fine because Python knows the list isn’t complete until it sees a closing bracket. To break a string (or any other piece of code) over more than one line, you can use a at the end of the line . The line breaks in listing5-8.py are just there to make the code fit onto the book page neatly: onscreen, the code can extend to the right if you want it to.

Object 27 is a map showing the Poodle’s crash site. Its long description includes the variables that you set in Listing 5-5 for the Poodle’s position. The str() function is used to convert the numbers in those variables into strings so they can be combined with other strings to make up the long description .

We’ve also set up some additional lists we’ll need in the game: items_player_may_carry stores the numbers of the objects the player can pick up . These are objects 53 to 81. Because they’re grouped together, we can set up the items_player_may_carry list using a range. A range is a sequence of numbers that starts from the first number given and finishes at the one before the last number. (We used ranges in Chapter 3.) We turn that range into a list using list(range(53 to 82)), which makes a list of all the numbers from 53 to 81.

If you add more objects that a player can carry later, you can add them to the end of this list. For example, to add new objects numbered 89 and 93 that the player can carry, use items_player_may_carry = list(range(54, 82)) + [89, 93]. You can also add new objects to the end of the objects list and just extend the range used to set up items_player_may_carry.

The other new list is items_player_may_stand_on, which specifies whether a player is allowed to stand on a particular item . Players can only stand on objects small enough to be picked up and on the different types of floor. We make this list by adding the object numbers for the different floor types to the items_player_may_carry list.

After you’ve entered Listing 5-8, you’ve completed the OBJECTS section of the Escape game! But we haven’t put the objects into the game map yet. We’ll start to do that in Chapter 6.

ARE YOU FIT TO FLY?

Check the following boxes to confirm that you’ve learned the key lessons in this chapter.

Images  To get information from a dictionary, you use the key for that information. The key can be a word or a number and can also be stored in a variable.

Images  If you try to use a key that isn’t in the dictionary, you’ll cause an error.

Images  To avoid an error, check whether the key is in the dictionary before the program tries to use it.

Images  You can put lists inside dictionaries. Then you can use the dictionary key followed by the list index to get a particular item from the list. For example: planets["Earth"][1].

Images  The Escape game uses the objects dictionary to store information about all the objects in the game. Each item in the dictionary is a list.

Images  You can use the index number of that list to access the object’s image file, shadow image file, and long and short description.

image
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.145.34.176