Welcome to Adventure: Lesson 7 (Dwarves)

Introduction

This is the seventh 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.

Dwarf Overview

In Adventure, dwarves are threatening little men that occasionally appear in the cave and throw weapons at you from the shadows. The first dwarf throws a nasty little axe, which lands on the ground, and successive dwarves throw nasty little knives, which vanish after being thrown. After the first dwarf leaves the axe, you can pick it up and hurl it at later dwarves, often converting them into clouds of greasy black smoke.

Dwarves Appearing

Everything covered in these lessons so far has been triggered by player commands. But the dwarves of Adventure aren’t triggered by a player action. Under the right circumstances, they appear without any action by the player.

Every turn rules are a way to make things happen in the game that aren’t triggered by the player. Per the name, they will indeed happen every turn by default. To avoid bombarding the player constantly with dwarves, we should bring in a dwarf only when a random check succeeds.

Since the dwarves are all identical, and since only one dwarf can be in play at a time, I’ve decided to use only one dwarf and bring him back repeatedly to harass the player.

A threatening little dwarf is a man.

Every turn:
    if a random chance of 1 in 20 succeeds and the dwarf is not in the location of the player:
        now the dwarf is in the location of the player;
        say “A threatening little dwarf comes out of the shadows!”

Limiting Dwarves to the Cave

The last tutorial covered the Inform 7 concept of kinds in order to make treasure. Let’s harness that concept again, except this time with rooms.

A cave is a kind of room.

Now, instead of declaring the dwarf-accessible rooms to be rooms, we declare them to be caves. The rooms that are not caves will remain rooms.

There is a cave called Sloping E/W Canyon. Sloping E/W Canyon is west of In Debris Room.

This lets us test to make sure the player is in a dwarf-appropriate room before summoning a dwarf. I’m going to modify the first line with a when condition so that it only fires in caves, but I could have done this instead by adding a third if onto the second line.

Every turn when the location of the player is a cave:
    if a random chance of 1 in 20 succeeds and the dwarf is not in the location of the player:
        now the dwarf is in the location of the player;
        say “A threatening little dwarf comes out of the shadows!”

Note that creating caves as a kind of room is only one way to set up the test for whether the player is in an appropriate location. Other ways to do it include:

  • adding all appropriate rooms into a region and testing for the region (§3.4, Regions and the index map)
  • declaring a new either-or property for rooms and testing for the property (§3.6, Either/or properties)

Choosing among these three is primarily a matter of personal style.

Dwarves Throwing Axes

The first dwarf to appear throws a nasty little axe at the player. We could do this with an every turn rule, but I’m going to use a timer instead, because timers are incredibly useful. Timers do exactly what they sound like: count down X number of turns and then fire off.

A nasty little axe is a thing.

Every turn:
    if a random chance of 1 in 20 succeeds and the dwarf is not in the location of the player and the location of the player is a cave:
        now the dwarf is in the location of the player;
        say “A threatening little dwarf comes out of the shadows!”;
        if the nasty little axe is nowhere:
            the dwarf throws the axe in 1 turn from now.

At the time when the dwarf throws the axe:
    say “The dwarf throws a nasty little axe at you, misses, curses, and runs away.”;
    move the axe to the location of the player;
    remove the dwarf from play.

What’s this about the axe being nowhere? Usually, a thing is attached to a room or another thing, but I didn’t define the location of the axe anywhere in the source code. Therefore, the axe is “nowhere”. (The opposite of this is “somewhere”, which will be useful in the next section.)

One design note: this is only a sensible way to set things up because I know the axe will always be attached to a room after it enters play. If the design of Adventure called for the axe to be removed from the game (via a destruction mechanic), then the axe would be nowhere again, and that would cause the dwarf to throw the axe at the next opportunity.

The timer part is set up by “the dwarf throws the axe in 1 turn from now” and triggers on “At the time when the dwarf throws the axe”. The key phrase is “the dwarf throws the axe” – that’s operating the timer. This is a sensible, easy-to-understand version, but it could be anything else, as in this example:

Same source as before, but replaces "the dwarf throws the axe" with "AARDVARKS RULE THE WORLD".

What can I say? Aardvarks are cool.

All right! That’s working well so far.

A threatening little dwarf comes out of the shadows!  >z Time passes.  The dwarf throws a nasty little axe at you, misses, curses, and runs away.  >get axe Taken.

Dwarves Throwing Knives

There isn’t anything new in this section, except maybe the parentheses. (They aren’t necessary from the compiler’s perspective for this particular code, but it’s sometimes easier to read code when the logic checks are bound together visually.)

After the first dwarf throws an axe, the successive dwarves swap over to throwing knives. These knives have a chance of hitting and even killing the player. (I’m out of orange smoke at the moment, so I’ll ignore Adventure’s rather complicated death mechanics.)

Knife-flinging dwarves also stick around for a bit rather than running off immediately, including a mechanic where they chase the player from room to room if they aren’t driven off. Because the dwarves continue to harass the player over multiple turns, this is better suited to a new every turn rule than a timer.

Every turn when the dwarf is somewhere:
    if (the location of the dwarf is not the location of the player) and (the location of the player is a cave):
        say “The dwarf stalks after you…”;
        move the dwarf to the location of the player;
    if (the axe is somewhere) and (a random chance of 3 in 4 succeeds):
        say “The dwarf throws a nasty little knife at you, “;
        if a random chance of 95 in 1000 succeeds:
            say “and hits!”;
            end the story saying “It looks as though you’re dead. I think we’ll just call it a day.”;
        else:
            say “but misses!”;
    if a random chance of 1 in 3 succeeds:
        say “Tiring of this, the dwarf slips away.”;
        remove the dwarf from play.

The actual implementation is a lot more complicated, with special cases for things like interacting with the dragon and pirate, but this is a good start.

Throwing Axes at Dwarves

Nothing new here, either! This section just revisits Lesson 5, which covered altering an existing action. In this case, the “throw” action gets an “instead” rule for this specific circumstance.

Instead of throwing the nasty little axe at the dwarf:
    move the axe to the location of the player;
    if a random chance of 2 in 3 succeeds:
        remove the dwarf from play;
        say “You killed a little dwarf! The body vanishes in a cloud of greasy black smoke.”;
    else:
        say “Missed! The little dwarf dodges out of the way of the axe.”

Say No to Infinite Dwarves

Right now, the dwarves will just keep mobbing you until you eventually fall down, but in the original game, there are limits on this kind of thing. A value that varies can be used to establish those limits. (In a different language, we’d call this a global variable.)

Here’s the variable itself:

Dwarf-count is a number that varies. Dwarf-count is 5.

This declaration sits outside the rest of the code, just like the declaration of a thing or a room. It can be accessed from any piece of code, tested like an object property, and adjusted at will within code by using the word now.

And here’s the updated dwarf appearance code.

Every turn when the location of the player is a cave and dwarf-count > 0:
    if a random chance of 1 in 2 succeeds and the dwarf is not in the location of the player:
        now dwarf-count is dwarf-count – 1;
        now the dwarf is in the location of the player;
        say “A threatening little dwarf comes out of the shadows!”;
        if the nasty little axe is nowhere:
            the dwarf throws the axe in 1 turn from now.

Final Source

This lesson covered a lot of ground! Here’s a link for the assembled version: Dwarf source code

Further Reading

The material covered in this lesson came primarily from chapters 8 and 9 in the Inform 7 documentation. Some specific places for further reading:

§4.2 Using new kinds
§8.1 Change of values that vary
§8.10 Removing things from play
§8.11 Now…
§8.18 Randomness
§9.4 When play ends
§9.5. Every turn
§9.11 Future events

Bookmark the permalink.

Leave a Reply

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