Section 7: Getting started

Contents Back Forward | ### 7. Getting started
| Nothing so difficult as a beginning In poesy, unless perhaps the end. ...Lord Byron (1788--1824), Don Juan, IV iv The examples in Chapters III and IV of this manual will put together a small game called 'Ruins'. Its first state is very close to the minimal 'Shell' game supplied with Inform:
    Constant Story "RUINS";
    Constant Headline "^An Interactive Worked Example^
                 Copyright (c) 1995 by Graham Nelson.^";

    Include "Parser";
    Include "VerbLib";

    Object Forest "Dark Forest"
      with description
              "In this tiny clearing, the pine-needle carpet is broken by
               stone-cut steps leading down into darkness.  Dark olive
               trees crowd in on all sides, the air steams with warm recent
               rain, midges hang in the air.",
      has  light;

    [ Initialise;
      location = Forest;
     "^^^^^Days of searching, days of thirsty hacking through the briars of
      the forest, but at last your patience was rewarded. A discovery!^";
    ];

    Include "Grammar";
If you can compile this successfully, Inform is probably set up and working properly on your computer. Compilation may take a few seconds, because the game 'includes' three library files which contain a great deal more code. These files are themselves written in Inform and contain the core of ordinary rules common to all games:
`Parser` | a program for decoding what the player types;
`VerbLib` | how verbs, like "take'' or "drop'', work;
`Grammar` | the grammar table, or what the Parser understands.
(If compilation is annoyingly slow, it should be easy enough to "link the library files'', which is much faster: see Section 4.3) Apart from the inclusions, 'Ruins' contains: (a) -- strings (that is, quoted text) giving the game's name and a copyright message, to be printed out when appropriate; (b) -- a routine, called `Initialise`, which is run when the game begins, and simply sets where the player starts (not that there's much choice yet!) and prints a 'welcome' message; (c) -- an object, so far the only room. 'Ruins' is at this stage an extremely dull game:
    Days of searching, days of thirsty hacking through the briars of the forest,
    but at last your patience was rewarded. A discovery!

    RUINS
    An Interactive Worked Example
    Copyright (c) 1995 by Graham Nelson.
    Release 1 / Serial number 960825 / Inform v6.04 Library 6/1

    Dark Forest
    In this tiny clearing, the pine-needle carpet is broken by stone-cut steps
    leading down into darkness.  Dark olive trees crowd in on all sides, the air
    steams with warm recent rain, midges hang in the air.

    >i
    You are carrying nothing.

    >north
    You can't go that way.

    >wait
    Time passes.

    >quit
    Are you sure you want to quit? yes
(The "Release'' number is 1 unless you set it otherwise, putting a directive like `Release 2;` into the source code. The "Serial number'' is set by Inform to the date of compilation.) In an Inform game, objects are used to simulate everything: rooms and items to be picked up, scenery, intangible things like mist and even some abstract ideas (like the direction 'north'). The library is also present in every game, and can be thought of as a referee, or umpire, rather than part of the game's world. Our second object is added by writing the following just after the `Forest` ends and just before `Initialise` begins:
    Object -> mushroom "speckled mushroom"
      with name "speckled" "mushroom" "fungus" "toadstool";
(The arrow `->` means that the mushroom begins inside the Forest rather than alongside it.) If the game is recompiled, the mushroom is now in play: the player can call it "speckled mushroom'', "mushroom'', "toadstool'' and so on. It can be taken, dropped, looked at, looked under and so on. However, it only adds the rather plain line "There is a speckled mushroom here.'' to the Forest's description. So here is a more lavish version:
    Object -> mushroom "speckled mushroom"
      with name "speckled" "mushroom" "fungus" "toadstool",
           initial
              "A speckled mushroom grows out of the sodden earth, on a long stalk.";
The `initial` message is used to tell the player about the mushroom when the Forest is described. (Once the mushroom has been picked or moved, the message is no longer used: hence the name 'initial'.) The mushroom is, however, still "nothing special'' when the player asks to "look at'' or "examine'' it. To provide a more interesting close-up view, we must give the mushroom its own `description`:
    Object -> mushroom "speckled mushroom"
      with name "speckled" "mushroom" "fungus" "toadstool",
           initial
              "A speckled mushroom grows out of the sodden earth, on a long stalk.",
           description
              "The mushroom is capped with blotches, and you aren't at all sure
               it's not a toadstool.",
      has  edible;
Now if we examine the mushroom, as is always wise before eating, we get a cautionary hint; still, thanks to the `edible` notation, we're now able to eat it. These show the two kinds of feature something can have: a "property'', which has some definite value or list of values (such as `name`), and an "attribute'', which is either present or not but has no particular value (such as `edible`). Values of properties change during play, and attributes come and go. For instance,
            mushroom.description = "You're sure it's a toadstool now.";
            give mushroom general;
            if (mushroom has edible) print "It's definitely edible.^";
manipulate the attributes and properties. (`general` is the name used for an attribute with no particular meaning to the game, but which is left free for your program to use as it likes. Similarly, `number` is a general-purpose property.) We can go much further with form-filling like this, but for the sake of example we'll begin some honest programming by adding the following property to the mushroom:
           after
           [;  Take: "You pick the mushroom, neatly cleaving its thin stalk.";
               Drop: "The mushroom drops to the ground, battered slightly.";
           ],
The property `after` doesn't just have a string for a value: it has a routine of its own. Now after something happens to the mushroom, the `after` routine is called to see if any special rules apply. In this case, `Take` and `Drop` are the only actions tampered with, and the only effect is that the usual messages ("Taken.'' "Dropped.'') are replaced. The game can now manage a brief but plausible dialogue:
    Dark Forest
    In this tiny clearing, the pine-needle carpet is broken by stone-cut steps
    leading down into darkness.  Dark olive trees crowd in on all sides, the air
    steams with warm recent rain, midges hang in the air.
    A speckled mushroom grows out of the sodden earth, on a long stalk.
    >get mushroom
    You pick the mushroom, neatly cleaving its thin stalk.
    >look at it
    The mushroom is capped with blotches, and you aren't at all sure it's not a
    toadstool.
    >drop it
    The mushroom drops to the ground, battered slightly.
The mushroom is a little more convincing now, but still passive. We can give it a somewhat sad new rule by adding yet another property, this time with a more substantial routine:
           before
           [; Eat: if (random(100) <= 30)
                   {   deadflag = 1;
                      "The tiniest nibble is enough. It was a toadstool,
                       and a poisoned one at that!";
                   }
                   "You nibble at one corner, but the curious taste repels you.";
           ],
The `before` routine is called before the player's intended action takes place. So when the player tries typing, say, "eat the mushroom", what happens is: in 30% of cases, she dies of toadstool poisoning; and in the other 70%, she simply nibbles a corner of fungus (without consuming it completely).
| Like many programming languages, Inform braces together blocks of code so that several statements can come under the `if` condition. `deadflag` is a global variable, whose value does not belong to any particular object (or routine). It is defined somewhere in the depths of the library: it's usually 0; setting it to 1 causes the game to be lost, and setting it to 2 causes a win.
| Note that if the first text is printed, the rule ends there, and does not flow on into the second text. So one and only one message is printed. Here is how this is achieved: although it's not obvious from the look of the program, the `before` routine is being asked the question "Do you want to interfere with the usual rules?''. It must reply, that is, "return'', either "true'' or "false'' meaning yes or no. Because this question is asked and answered many times in a large Inform game, there are several abbreviations for how to reply. For example,
        return true;
        rtrue;
both do the same thing. Moreover,
        print_ret "The tiniest nibble... ...at that!";
performs three useful tasks: prints the message, then prints a carriage return, and then returns true. And this is so useful that a bare string
        "The tiniest nibble... ...at that!";
is understood to mean the same thing. To just print the text, the statement `print` has to be written out in full. Here is an example:
           before
           [; Taste: print "You extend your tongue nervously.^";
                     rfalse;
           ];
In this rule, the text is printed, but the answer to "Do you want to interfere?'' is no, so the game will then go on to print something anodyne like "You taste nothing unexpected.'' (In fact the `rfalse` was unnecessary, because if a rule like this never makes any decision, then the answer is assumed to be "false''.)
| EXERCISE 1: (link to the answer)
| The present `after` routine for the mushroom is misleading, because it says the mushroom has been picked every time it's taken (which will be odd if it's taken, dropped then taken again). Correct this to complete the definition of the 'Ruins' mushroom.
| More generally, some `before` or `after` rules ought to apply only once in the course of a game. For instance, examining the tapestry reveals a key, only once. A sneaky way to do this is to make the appropriate rule destroy itself, so for example
        tapestry.before = NULL;
removes the entire `before` rule for the tapestry. `NULL` is a special value, which the properties `before`, `after`, `life` and `describe` hold to indicate "none''.
| Here is another typical object definition:
    Object "stone-cut steps" Forest
      with name "steps" "stone" "stairs" "stone-cut",
           description
              "The cracked and worn steps descend into a dim chamber.  Yours
               might be the first feet to tread them for five hundred years.",
           door_to Square_Chamber,
           door_dir d_to
      has  scenery door open;
This is the conventional way to lay out an `Object` declaration: with the header first, then `with` a list of properties and their starting values, finishing up with the attributes it initially `has`. (Though `with` and `has` can be given the other way round.) Note that the first line, the so-called header, is a little different in form to those above. Firstly, it gives no "program name'' for the steps (in the way that `mushroom` was given as program-name for the speckled mushroom) -- there is a blank in between the `Object` directive and the text of the words "short-cut steps''. This is perfectly legal, and is sensible because the program never needs to refer to the steps object directly. Secondly, the initial position of the steps is specified not by using arrows `->` but by actually quoting the object it is to be placed inside, the `Forest`. This is sometimes convenient and is only legal if the `Forest` has already been defined (earlier on in the program). Such a restriction is actually useful as it prevents you from setting up a 'loop' -- one object in another in a third in the first, for instance.

Contents / Back / Forward
Chapter I / Chapter II / Chapter III / Chapter IV / Chapter V / Chapter VI / Appendix

Mechanically translated to HTML from third edition as revised 16 May 1997. Copyright © Graham Nelson 1993, 1994, 1995, 1996, 1997: all rights reserved.