Welcome to Adventure: Lesson 8 (A Maze of Twisty Little Passages…)

Introduction

This is the eighth in a series of quick-start Inform 7 tutorials using examples from Colossal Cave Adventure. More information about this tutorial series can be found here: A Quick-Start Guide to Inform 7.

There are two significant mazes in the cave. One is the maze of twisty little passages all alike, and one is the maze of twisty little passages all different. This lesson will cover techniques for both of them.

A Maze of Twisty Little Passages All Alike

Normally, we declare rooms in the source like this:

There is a room called Maze. The description of Maze is “A maze of twisty little passages all alike.”

That’s all very well for the first room, but we can’t create multiple rooms named Maze. There’s no way to tell them apart in the source code. And isn’t there some way to avoid pasting “A maze of twisty little passages all alike” over and over?

The prior lesson involved creating a kind of room, the cave room, in order to control where the dwarves appeared. We can use a related technique here.

When we declare a new kind, we can overwrite any of the properties of the base kind. Using SHOWME, let’s take a look at the properties of a base room.

Maze  >showme maze Maze - room yourself - person singular-named, proper-named; lighted, visited list grouping key: none printed name: "Maze" printed plural name: none indefinite article: none description: none

The properties of interest to us are “printed name” and “description”. By changing the default values for these properties, we can create rooms that have identical headers and identical descriptions. After that, we can name the maze rooms whatever we want in the source code – there won’t be any way for players to tell.

Here’s the source code:

A maze room is a kind of room.
The printed name of a maze room is usually “Maze”.
The description of a maze room is usually “A twisty maze of passages all alike.”

There is a maze room called Maze1.

A maze room called Maze2 is east of Maze1.

A maze room called Maze3 is north of Maze1.

That’s all it takes. Every maze room will display “Maze” as its printed name, and every maze room will display “A twisty maze of passages all alike” as its description.

Adventure Tutorial An Interactive Fiction by Carolyn VanEseltine Release 1 / Serial number 150108 / Inform 7 build 6L38 (I6/v6.33 lib 6/12N) SD  Maze A twisty maze of passages all alike.  >e  Maze A twisty maze of passages all alike.  >w  Maze A twisty maze of passages all alike.  >n  Maze A twisty maze of passages all alike.  >

Note that the word usually is used when setting default property values. If you wanted to make one maze room a bit different from the others, you could set the values for that room specifically. For example, if you wanted one room to be called “Frustrating Maze”, you could do this:

A maze room called Maze4 is south of Maze1. The printed name of Maze4 is “Frustrating Maze”.

This would override just the printed name at the top of the room. The description would be the same default as before.

Maze A twisty maze of passages all alike.  >s  Frustrating Maze A twisty maze of passages all alike.  >

A Maze of Twisty Little Passages All Different

Disclaimer: The techniques described here are unusually advanced for this quick-start guide. Tables are extremely useful, but it will be difficult to repurpose this example without reading chapter 16 in the Inform 7 documentation. If you are currently at a game jam, you may wish to skip this section.

We could use a similar approach for the maze of twisty little passages all different. The room names are again all the same, with only the descriptions being different. But the source code would be annoying to read.

Instead, I’m going to use a table to define the rooms. Tables allow you to define a group of related things very rapidly. They are more typically used for things than rooms, but we’re going to make an exception.

Really important: In Inform 7, tables are laid out with tabs. They cannot be laid out with spaces. Copying and pasting the source code below will not work unless you replace the spaces with tabs.

A d_maze is a kind of room. The printed name of a d_maze is usually “Maze”.

Some d_mazes are defined by the Table of Different Maze Rooms.

Table of Different Maze Rooms
d_maze     description
DMaze1     “You are in a maze of twisty little passages, all different.”
DMaze2     “You are in a little maze of twisting passages, all different.”

This compiles and produces two rooms, as shown below:

World Index map showing two rooms, DMaze1 and DMaze2, existing but unconnected

But the rooms aren’t connected yet. To connect them, we need to do two things:

  1. Add the exits to the table.
  2. Hook up the exits in the game.

We can create new variables to hold the additional exits like so:

A d_maze has a room called the n_exit.
A d_maze has a room called the e_exit.
A d_maze has a room called the s_exit.
A d_maze has a room called the w_exit.

And then we can add those exits into our table, using two dashes to indicate a blank entry. (Disclaimer: directions below do not reflect the original Adventure.)

Table of Different Maze Rooms d_maze n_exit e_exit s_exit w_exit description DMaze1 -- -- DMaze2 DMaze3 "You are in a maze of twisty little passages, all different." DMaze2 DMaze1 -- -- -- "You are in a little maze of twisting passages, all different." DMaze3 -- DMaze1 -- -- "You are in a little maze of twisting passages, all different."

That compiles, but n_exit doesn’t mean anything to the game. What we need is to actually go through and tell Inform “hey, put the n_exit room to the north, put the e_exit room to the east, put the s_exit room to the south”, and so forth.

We’re going to do that with a new phrase. A phrase is essentially a subroutine. It sits around outside any other code and waits to be called by the program.

To map the rooms correctly:
    repeat through the Table of Different Maze Rooms:
        if there is a n_exit entry:
            now the n_exit entry is mapped north of the d_maze entry;
        if there is a e_exit entry:
            now the e_exit entry is mapped east of the d_maze entry;
        if there is a s_exit entry:
            now the s_exit entry is mapped south of the d_maze entry;
        if there is a w_exit entry:
            now the w_exit entry is mapped west of the d_maze entry.

Why include “if there is a n_exit entry”? Otherwise, Inform would attempt to map a blank (the two dashes) in some places. This will cause a runtime error, because a blank is not a room.

This chunk of code will compile just fine, but it will not do anything unless we call it. Inform provides when play begins as an easy way to do that. (It’s also useful for things like writing an introductory cut-scene, since when play begins happens before the title and author.)

When play begins:
    map the rooms correctly.

When the game encounters this code, it will go searching for a phrase that starts “To map the rooms correctly:” and run the code in that phrase.

Everything works now, and the table is relatively compact and easy to read.

All source code together on the left, plus a runthrough of the code on the right, demonstrating that the descriptions show up appropriately.

This barely scrapes the surface of tables or activities. Activities are one of the most powerful systems in Inform 7, allowing pieces of code to be reused all over the game. Tables have a more limited utility, but when they are called for, they are extremely useful.

It can be tempting sometimes to forget that Inform 7 does not really understand English. Do not make this mistake while working with tables. The syntax to work with tables is logical, but it is neither flexible nor intuitive. Trying to guess at how tables work is a sure route to failure. (I had to repair my own syntax repeatedly while writing this lesson.)

Further Reading

§4.3 Degrees of certainty
§4.6 Properties again
§6.14 Adjacent rooms and routes through the map
§8.5 Change of properties with values
§8.11 Now…
§9.1 When play begins
§11.1 What are phrases?
§11.2 The phrasebook
§11.3 Pattern matching
§16.1 Laying out tables
§16.6 Repeating through tables
§16.7 Blank entries
§16.16 Defining things with tables

Example 9 – The Unbuttoned Elevator Affair
Example 125 – Bee Chambers

Bookmark the permalink.

3 Comments

  1. Wow! I just worked through this example and it really made sense. I finally understood tables in Inform. Thank you!

  2. As I was following these tutorials I kept adding them all to the same project in Inform. I’m having a bit of trouble figuring out how to link the twisty passages from this lesson to the rest of the story. I was going to connect them to another cave room created in a previous lesson.

    First, I tried creating the connection in the source as:
    North of Low N/S Passage is DMaze1.
    That caused it not to compile, “which I ought to create as a new value of an object. But I can’t do that: it already has a meaning (as an object).”

    Then I tried putting the Low N/S Passage as the s_exit for Dmaze1 in the table. This compiled, but the three DMaze rooms were still off by themselves on the Index>World Map, and going N in Low N/S Passage wasn’t possible.

    I’ll look in the documentation and Aaron A. Reed’s book for more info. But if someone would like to offer a hint, I’d appreciate it.

    • Hi Aaron,

      This is a tricky bit of Inform, and I’m glad you called it out. The problem you’re having is that, when the compiler hits the table, it thinks you’re declaring DMaze1 a second time.

      But this can be fixed! Make sure to put

      DMaze1 is south of Low N/S Passage.

      *after* the table, and everything should be fine.

      Alternately, you can add it to your instructions in the “when play begins:” section, like this:

      When play begins:
      say "(Mapping rooms....)";
      map the rooms correctly;
      change the south exit of Low N/S Passage to DMaze1;
      change the north exit of DMaze1 to Low N/S Passage.

      (Pretend everything except “When play begins” is indented.)

Leave a Reply to Carolyn VanEseltine Cancel reply

Your email address will not be published. Required fields are marked *