A Mini adventure in Inform 7

I recently discovered Inform 7, a tool for creating text adventure games easily in (semi-)natural English - in this article we see how Inform 7 can be used to implement a small text adventure, and some interesting features of the language along the way. The game is based on MINI, an example adventure in Peter Killworth’s How To Write Adventure Games for the BBC Microcomputer Model B and Acorn Electron (1984). And, after the discussions on how to fit games into small amounts of RAM in my previous article, we shall see how the size of the game varies between BBC BASIC and Inform 7.

Background

In researching my previous post Adventures in Accidental and Essential Complexity - prompted by Peter Killworth’s book How To Write Adventure Games for the BBC Microcomputer Model B and Acorn Electron (1984) - I discovered Inform 7, a tool for creating interactive fiction / text adventure games.

After reading the Inform 7 documentation - with a tutorial/guide to the language, and an accompanying Recipe Book of examples - I was excited by how approachable it was, and keen to see what it could do by trying to implement a small game. And Killworth’s book had a handy example - a four-room adventure, appropriately named MINI - which he shows how to implement in BBC BASIC.

So I have used the design of that game - the map, the objects, the puzzles - but instead of looking at the BBC BASIC implementation, I have developed it from scratch in Inform 7. This is based on just a few hours of looking at the Inform 7 documentation and experimenting with the language - there may well be more idiomatic or neater ways to accomplish some of this.

(A PDF scan of the book is now available at https://www.mocagh.org/softguide/writeadventuregames.pdf. The MINI adventure is described in Chapter 3, but I describe the game as well as its implementation here in any case.)

Cover of “How to Write Adventure Games” by Peter Killworth, 1984

A neat feature of Inform 7 is that it can publish the story file along with a Javascript interpreter to produce, so we get an in-browser playable version of the MINI adventure if you want to try it out - either before reading on for spoilers, or later.

An overview of the MINI adventure

MINI is a small adventure, with four rooms. The player’s objective is to get the crown, which is in the Treasure Room. But there are a few puzzles to solve to get there…

  • The door from the Cobwebby Room (where the player starts) to the Treasure Room is closed. The only way to open it is to wave the black rod.
  • Where is the black rod? It is in an Alcove behind a barrier of whirling blades. To pass through the blades safely, the player must pick up and wear a shield (which is destroyed by the blades).
  • Having got into the Alcove and collected the black rod, how does the player get back to the Cobwebby Room without being shredded by the blades? By remembering and saying the magic word BLAH scrawled on the wall in the Pink Room, which will teleport the player back to the Cobwebby Room.
  • There is also a countdown timer - water rising turn-by-turn until it closes over a slow-moving player’s head…

Implementing MINI

To provide a structure, I have split the code into 6 sections, described in the 6 sections below. For each section, there is an explanation of what we are trying to achieve in terms of the game design, the Inform 7 code itself, and finally some comments on the Inform 7 code and features used. Examples of Inform 7 are either from MINI itself, or the Inform 7 documentation.

The full code is available in my Github repository: https://github.com/terryboon/Mini-Adventure/blob/master/Mini.inform/Source/story.ni

Section 1: The Map

The map of the MINI adventure is shown below:

Map

In this map, grey is used to show the rooms themselves, blue icons represent doors (in the Inform 7 sense of the word, discussed below), and red icons represent objects which the player can pick up. This is coded as follows:

The Cobwebby Room is a room. "You are in a crumbling room full of cobwebs. A passage leads west. [if the barred door is closed]A barred door blocks the way north.[otherwise]A barred door stands open to the north." A shield is here. The shield is wearable.
The Treasure Chamber is a room. "You are in a vast treasure chamber, with an exit south. [if the barred door is closed]A barred door blocks the way south.[otherwise]A barred door stands open to the south." A jewelled crown is here.
A barred door is north of the Cobwebby Room and south of the Treasure Chamber.  The barred door is a door. It is not openable. It is scenery.
The Pink Room is west of the Cobwebby Room. "You are in a cheerful pink room. The word BLAH is inscribed on the ceiling. A passage leads east, and a doorway full of whirling blades leads north."
The whirling blades are north of the Pink Room and south of the Alcove. The whirling blades are a door. The whirling blades are open. The whirling blades are not openable. The whirling blades are scenery.
The Alcove is a room. "You're to the north of the pink room in an alcove The only exit seems to be back the way you came, south through the whirling blades." A black rod is here.

(Map icons are from https://game-icons.net, a tremendously handy resource, and licensed under CC BY 3.0. Spinning blades, Doorway, Checked Shield and Crown by Lorc, and Bo and Brick Wall are by Delapouite.)

  • Rooms: As you can see, the author can define rooms (The Cobwebby Room is a room.) using semi-natural language. Following the definition of room is a description, which can vary depending on the state of the game, e.g. "You are in a crumbling room full of cobwebs. A passage leads west. [if the barred door is closed]A barred door blocks the way north.[otherwise]A barred door stands open to the north.". The geography is defined by the connections between rooms, e.g. The Pink Room is west of the Cobwebby Room.
  • Things (objects): Similarly, the author defines things (objects) in semi-natural English (e.g. A shield is here.). They can define kinds (properties) (The shield is wearable means that the player can WEAR SHIELD.) Inform 7 will infer the kinds of objects where it can. For example, based on A billiards table is in the Gazebo. On it is a trophy cup. A starting pistol is in the cup., Inform 7 will identify that the billiards table is a supporter (i.e. objects can be put on it), and that the cup is a container (i.e. objects can be put in it).
  • Doors: Some rooms connect directly to other rooms. For example, The Pink Room is west of the Cobwebby Room. In other cases, there is a door between two rooms, e.g. A barred door is north of the Cobwebby Room and south of the Treasure Chamber. The barred door is a door. If the door is open, then it is a single step to go betwen the two rooms (i.e. NORTH from the Cobwebby Room will reach the Treasure Chamber - the player doesn’t spend a turn standing in the doorway). But doors can be closed, locked, or - as we shall see below - trigger checks when the player passes through them.
  • Scenery: Where an object is defined as scenery, this means that, while it may be included in the room description, it is not shown in the list of objects in the room.

Section 2: Getting through the whirling blades

We need to get through the closed barred door.

There isn’t anything to help us do that in either the Cobwebby Room or the Pink Room, so we will need to find a way through the blades whirling in the northern exit of the Pink Room.

If we try simply going through that exit, we are - unsurprisingly - shredded by the blades.

There is a shield in the Cobwebby Room which looks a hopeful option for protecting us. However, it isn’t quite as simple as that. If we simply carry the shield (by TAKING or GETTING it), that isn’t enough, and will again be sliced up if we try to go through the blades - but we get a hint!

We have to WEAR the shield in order to make it safely through the blades. If we do that before attempting to go through the exit, then the shield is shattered by the blades, but we succesfully make it to the alcove.

Section 2 - Getting through the whirling blades by wearing a shield

Check going through the whirling blades:
    say "The knives stab at you while you pass.";
    if the shield is worn:
        say "They bounce off the shield, which shatters.";
        now the shield is nowhere;
    otherwise if the shield is carried:
        say "You're not actually wearing the shield, so the knives get you.";
        end the story instead;
    otherwise:
        say "They slice you to ribbons. You have departed the world.";
        end the story instead.

The code under Check going through the whirling blades is triggered whenever the player goes through the whirling blades door, whether going north from the Pink Room or south from the Alcove.

now the shield is nowhere has the effect of destroying the shield.

end the story triggers the “game over” routine.

instead in a check means that the normal outcome of the action doesn’t happen. If there is no instead then the code in the check runs, but the normal outcome of the action also happens - for example, in this code, if the player is wearing the shield, the shield is destroyed, but the motion through the whirling blades also completes successfully.

Section 3: Escaping the Alcove

Once we have made it through the whirling blades, we find ourselves in the alcove, with no apparent exits except for going back through the whirling blades - and with our shield shattered, that is unappealing (and would indeed be terminal). In the absence of other options, maybe now is the time to try saying that mysterious magic word which we saw in the description of the Pink Room - and indeed, that teleports us back to the Cobwebby Room! There is a black rod here, which we should take in case it just happens to come in useful later.

Section 3 - Escaping the alcove by saying a magic word

Understand "blah" or "say blah" as casting blah.
Casting blah is an action applying to nothing.
Check casting blah:
    if the player is not in the Alcove:
        say "Nothing happens." instead.
Carry out casting blah:
    say "There is a fanfare of cream horns, and you are thrown through the air!";
    now the player is in the Cobwebby Room.

Inform 7 has two related concepts for defining what a player can attempt to do.

  • Actions: Inform 7 defines an action as an impulse or an attempt to do something. These are expressed as present participles. Here, casting blah is an action - other examples of actions include going south, closing door. Inform 7 comes with a wide range of actions already built in.
  • Understanding: The author defines, through lines of grammar, the commands which a player can type to trigger actions. The line Understand "blah" or "say blah" as casting blah. is a line of grammar indicating the commands which a player can type to trigger the action casting blah. More complex lines of grammar could be Understand "photograph [someone]" as photographing. or Understand "fill [an open container] with [something]" as inserting it into (with nouns reversed).

Section 4: Opening the barred door

Now we are back in the Cobwebby Room, hopefully having remembered to GET the black rod from the Alcove before teleporting out of there. So inspiration needs to strike that it’s time to wave the black rod - and, if we do so, the door to the Treasure Room opens.

Section 4 - Opening the barred door to the treasure room by waving the black rod

After waving (noun):
    if the player is in the Cobwebby Room and the barred door is closed and noun is black rod:
        say "The barred door quietly swings open.";
        now the barred door is open;
    otherwise:
        say "Nothing happens."

Inform 7 allows the player to wave objects, but with no particular effect unless specified otherwise. The code here is a check if we are waving the only object which has an effect when waved, while we are in the room where it will have an effect.

now the barred door is open is an instruction to change the state of the barred door. As you’d expect - when the door is open, the player can step through them - and when it is shut, they can’t.

(Close readers of Peter Killworth’s book may note that in his design, the door vanishes completely, while I have the door swinging open. Why did I change it? To make the development easier for this quick trial. Inform 7 allows us to destroy objects, as shown with the shield above, but doesn’t allow doors to be destroyed. And I didn’t want the player to be able to interact with the door after it has been declared to have vanished. I’m sure there are ways to faithfully implement the vanishing door, but for this little experiment, I didn’t dig deeply into how - yet.)

Section 5: A countdown timer

We have to do all this reasonably swiftly, as water is bubbling up from beneath us - imposing a countdown timer on the number of turns we have before an unpleasant watery death.

Section 5 - The countdown - rising water levels

Table of Water Levels
Turn Number	Message
1	"There are faint sounds of water."
2	"The sounds are slightly nearer."
3	"The water sounds are quite loud."
4	"That water's getting nearer!"
5	"Water is soaking up through the floor!"
6	"Pools of water are on the ground."
7	"The water is ankle-deep!"
8	"The water is knee-deep!"
9	"The water is waist-deep!"
10	"The water is up to your chest."
11	"The water closes over your head..."

Every turn:
    say "[the message corresponding to a Turn Number of turn count in the Table of Water Levels]";
    if Turn Count is 11:
        end the story saying "You have departed the world!".

Inform 7 supports tables as a structured and efficient way to store data, similar to SQL tables. The table here is called Table of Water Levels and has two columns: Turn Number (containing integers) and Message (containing strings).

There is then code called every turn which looks up a message to show the player to warn them of the impending threat. The lookup is based on Turn Count, a variable built into Inform 7. This could have been achieved without using a table by coding a long sequence of if statements, but this approach is neater.

Section 6: Achieving victory

Having managed to open the barred door to the Treasure Room, we can enter it and win the game by taking the crown!

Section 6 - Achieving victory by taking the crown

Carry out taking the crown:
    end the story finally saying "The crown is yours! Well done!".

end the game finally is used to indicate the player has won, in contrast to the other end the story lines we have seen above indicating a less favourable end to the game.

Comparing sizes

The games from Peter Killworth’s book can be downloaded from https://www.everygamegoing.com/litem/How-To-Write-Adventure-Games/201/. (This is a file in SSD format, which can be read in a BBC Micro emulator such as Beebem.) This shows the source code for MINI weighing in at 4.6 K, saved in the tokenised form used by BBC BASIC.

In comparison, the Inform 7 source is around 3.3K in size. But that isn’t executable - it can be run in Inform 7, or it can be compiled into a “story file”, of which Inform 7 supports two formats. In the older, more portable, Z-Code format, I got a blorb (package) of 406 K; in the newer, more sophisticated Glulx format, I got a blorb of 602 K. And to actually play the story file, you need an interpreter - for example, Windows Glulxe, an interpreter for (as the observant reader might guess) playing Glulx story files under Windows, is a further 275 K. As mentioned early in the article, Inform 7 can produce a story file and bundled Javascript interpreter for a version playable in a web browser: for MINI, this bundle weighs in at 1.1 MB.

So - the source code itself was smaller in Inform 7, it was easier to write the game, and you do get a lot of features built in “for free” (this example barely scratches the surface of what Inform 7 can do) - but for this small game, to get a playable version, you end up with a file around 100x larger than the BBC BASIC implementation. With modern computing power, that is still very manageable. But when seeing the size of today’s software, I am impressed at what can be achieved in 4.6 K of BASIC!


Comment on this article on Twitter:


Sign up to the newsletter: If you would like to be notified of new posts on this blog, please sign up to the Eclectic Stacks email newsletter.

See also