Structuring Inform 7 code

Questions about organizing Inform 7 code tend to pop up regularly. Here's the method I use, which is of course not the official or the only way to do it.

Taking a ready-made header structure and trying to adapt your own code to it by filling in the blanks would be too inflexible, so I build the structure dynamically as I go along. A new project starts with no headers at all. New headers are added when code gets diverse enough to justify a new classification.

Include Rideable Vehicles by Graham Nelson.
The Front Yard is a room.

In this example the extension and the room definition don't have anything in common, so they're split into different headings.

Volume 1 — Extensions
Include Rideable Vehicles by Graham Nelson.
Volume 2 — Rooms
The Front Yard is a room.

When we add a new room, there's another split (although in real life the split would come only after they have a bit more content, we'll come back to that soon).

Volume 1 — Extensions
Include Rideable Vehicles by Graham Nelson.
Volume 2 — Rooms
Book 1 — Front Yard
The Front Yard is a room.
Book 2 — Driveway
The Driveway is a room. The Driveway is west of Front Yard.

Notice how the two similar headers are grouped together with a common parent header.

The general rule of thumb is that when something has at least two paragraphs of code, it gets its own header. For example, assuming we have the following code:

Chapter 1 — Engine room
The Engine room is south of Cable-car platform. The description is "The wooden shack houses a large diesel generator that moves the cableway. The shack's walls are rotten and patchy. The exit leads back out to the north."
The diesel generator is a device in the Engine room. "The diesel generator [if switched on]is running loudly, turning the cableway.[otherwise]looks like it hasn't been used in quite some while." The diesel generator is fixed in place.
The shack walls are scenery in the Engine room. The description is "Light is shining through the wall boards."

Each thing in this room (including the room itself) has only one paragraph of code, so they'd all stay under the same heading for now. Later when the code gets some meat around the bones, some things get more paragraphs and it's time to split them under more headings.

Chapter 1 — Engine room
The Engine room is south of Cable-car platform. The description is "The wooden shack houses a large diesel generator that moves the cableway. The shack's walls are rotten and patchy. The exit leads back out to the north."
Section 1 — Diesel generator
The diesel generator is a device in the Engine room. "The diesel generator [if switched on]is running loudly, turning the cableway.[otherwise]looks like it hasn't been used in quite some while." The diesel generator is fixed in place.
After switching on the diesel generator:
say "The generator makes some suspicious noises but then comes to life. The cableway starts moving again."
After switching off the diesel generator:
say "The generator shuts down and the cableway stops."
Section 2 — Shack walls
The shack walls are scenery in the Engine room. The description is "Light is shining through the wall boards."

The two-paragraphs rule is not absolute; sometimes it makes more sense to keep everything under one header when the code is not that important, like decorative scenery. Inform has only five header levels which also limits the size of the pieces into which you can split the code.

The five header levels are volume, book, part, chapter and section. I haven't really attached any specific fixed meaning to different header levels. Volumes contain top-level abstractions ("Metadata", "World", "Debugging") and any subheaders just use the next immediate type (volumes contain only books, books contain only parts etc.) This means that header levels in different parts of the source text aren't comparable: an NPC in one place might be under "part" level and another NPC could be under "section" level somewhere else, with neither being necessarily more important than the other.

The header structure is generally best arranged into a tree shape so that subheaders have a logical relationship with their parent headers, and headers on the same level under the same parent header belong to the same group. In other words, the diesel generator is a subheader under the Engine room because that's where the generator is. That much should be obvious, but subheaders under the the same parent header should also share a "theme" between each other: in the above example, if one of the subheaders is a new room-specific action, it's then better to group the objects under a new parent header so that the new action is not on the same level with the objects.

The important thing here is to not get hung up on getting it right the first time. The structure is allowed to live, and I tend to move parts of code around constantly while writing. The time it takes to keep the code organized is more than generously paid back later when navigating the code is fast and intuitive.

All that said, in the end the general top-level structure tends to usually be more or less something like this:

  1. Meta

    • License
    • Changelog
    • Extensions
    • Bibliographical information
    • Releasing
  2. Mechanics (any of these headers could get promoted to their own volume if there's a lot of content)

    • Commands
      • Modifications to standard commands
      • New commands
      • Out of world commands
        • Credits
        • Instructions
        • Hints
    • Default messages
    • Modifications to standard rules
    • New kinds
    • Scenes
    • Gameplay logic
    • Conversation system
    • Special mechanics
  3. World

    • Rooms
      • Room 1

        • Thing in room
        • Misc scenery
      • Backdrops
    • Major NPCs
  4. Debugging

But, as said, this is not a rigid structure but something that tends to form as a result of the dynamic method.

Here are sources of some full projects that use this method: Sparkle, Escapade!, Raising the Flag on Mount Yo Momma. For more ideas: source code by other people.


Did you find this article useful? By subscribing to the blog's mailing list you will receive an email whenever a new blog post is published. The address won't be used for any other purposes.