DM4 §3: Objects and classes

## §3 Objects and classes

> Objects make up the substance of the world.
> —Ludwig Wittgenstein (1889–1951), Tractatus

### §3.1 Objects, classes, metaclasses and `nothing`

In Inform, objects are little bundles of routines and variables tied up together. Dividing up the source code into objects is a good way to organise any large, complicated program, and makes particular sense for an adventure game, based as it usually is on simulated items and places. One item in the simulated world corresponds to one “object” in the source code. Each of these pieces of the story file should take responsibility for its own behaviour, so for instance a brass lamp in an adventure game might be coded with an Inform object called `brass_lamp`, containing all of the game rules which affect the lamp. Then again, objects do have to interact.

In West Pit
You are at the bottom of the western pit in the twopit room. There is a large hole in the wall about 25 feet above you.
There is a tiny little plant in the pit, murmuring “Water, water,…”

In this moment from ‘Advent’, the player is more or less openly invited to water the plant. There might be many ways to bring water to it, or indeed to bring liquids other than water, and the rules for what happens will obviously affect the bottle carrying the water, the water itself and the plant. Where should the rules appear in the source code? Ideally, the `plant` object should know about growing and the `bottle` about being filled up and emptied. Many people feel that the most elegant approach is for the `bottle`, or any other flask, not to interfere with the plant directly but instead to send a “message” to the `plant` to say “you have been watered”. It's then easy to add other solutions to the same puzzle: a successful rain dance, for instance, could also result in a “you have been watered” message being sent to `plant`. The whole behaviour of the `plant` could be altered without needing even to look at the rain-dance or the bottle source code. Objects like this can frequently be cut out of the source code for one game and placed into another, still working.

This traffic of messages between objects goes on continuously in Inform-compiled adventure games. When the player tries to pick up a wicker cage, the Inform library sends a message to the cage object asking if it minds being picked up. When the player tries to go north from the Hall of Mists, the library sends a message to an object called `Hall_of_Mists` asking where that would lead, and so on.

· · · · ·

Typical large story files have so many objects (‘Curses’, for instance, has 550) that it is convenient to group similar objects together into “classes”. For instance, ‘Advent’ began life as a simulation of part of the Mammoth and Flint Ridge cave system of Kentucky, caves which contain many, many dead ends. The Inform source code could become very repetitive without a class like so:

    Class DeadEndRoom
     with short_name "Dead End",
          description "You have reached a dead end.",
          cant_go "You'll have to go back the way you came.";

Leaving the exact syntax for later, this code lays out some common features of dead ends. All kinds of elegant things can be done with classes if you like, or not if you don't.

Objects can belong to several different classes at once, and it is sometimes convenient to be able to check whether or not a given object belongs to a given class. For instance, in adventures compiled with the Inform library, a variable called `location` always holds the player's current position, so it might be useful to do this:

    if (location ofclass DeadEndRoom) "Perhaps you should go back.";

· · · · ·

Items and places in an Inform game always belong to at least one class, whatever you define, because they always belong to the “metaclass” `Object`. (“Meta” from the Greek for “beyond”.) As we shall see, all of the objects explicitly written out in Inform source code always belong to `Object`. Though you seldom need to know this, there are three other metaclasses. Classes turn out to be a kind of object in themselves, and belong to `Class`. (So that `Class` belongs to itself. If you enjoy object-oriented programming, this will give you a warm glow inside). And although you almost never need to know or care, routines as in §1 are internally considered as a kind of object, of class `Routine`; while strings in double-quotes are likewise of class `String`. That's all, though. If in doubt, you can always find out what kind of object `obj` is, using the built-in function `metaclass(obj)`. Here are some example values:

    metaclass("Violin Concerto no. 1") == String
    metaclass(Main) == Routine
    metaclass(DeadEndRoom) == Class
    metaclass(silver_bars) == Object

Classes are useful and important, but for most game-designing purposes it's now safe to forget all about metaclasses.

It turns out to be useful to have a constant called `nothing` and meaning “no object at all”. It really does mean that: nothing is not an object. If you try to treat it as one, many programming errors will be printed up when the story file is played.

▲ If `X` is not an object at all, then `metaclass(X)` is `nothing`, and in particular `metaclass(nothing)` is `nothing`.

### §3.2 The object tree

Objects declared in the source code are joined together in an “object tree” which grows through every Inform story file. Adventure games use this to represent which items are contained inside which other items.

It's conventional to think of this as a sort of family tree without marriages. Each object has a parent, a child and a sibling. Such a relation is always either another object in the tree, or else `nothing`, so for instance the parent of an orphan would be `nothing`. Here is a sample object tree:

`Meadow` |
↓child |
`Mailbox` | sibling | `Player` |
→
↓child |  | ↓child |
`Note` |  | `Sceptre` | sibling | `Bottle` | sibling | `Torch` | sibling | `Stone`
→ | → | →
| ↓child |
| `Battery` |

The `Mailbox` and `Player` are both children of the `Meadow`, which is their parent, but only the `Mailbox` is the child of the `Meadow`. The `Stone` is the sibling of the `Torch`, which is the sibling of the `Bottle`, and so on.

Inform provides special functions for reading off positions in the tree: `parent`, `sibling` do the obvious things, and `child` gives the first child: in addition there's a function called `children` which counts up how many children an object has (note that grandchildren don't count as children). Here are some sample values:

    parent ( Mailbox )  == Meadow
    children ( Player ) == 4
    child ( Player )    == Sceptre
    child ( Sceptre )   == nothing
    sibling ( Torch )   == Stone

• WARNING
It is incorrect to apply these functions to the value `nothing`, since it is not an object. If you write a statement like `print children(x);` when the value of `x` happens to be `nothing`, the interpreter will print up the message:

[** Programming error: tried to find the “children” of nothing **]

You get a similar error message if you try to apply these tree functions to a routine, string or class.

### §3.3 Declaring objects 1: setting up the tree

Objects are made with the directive `Object`. Here is a portion of source code, with the bulk of the definitions abbreviated to “...”:

    Object Bucket ...
    Object -> Starfish ...
    Object -> Oyster ...
    Object -> -> Pearl ...
    Object -> Sand ...

The resulting tree looks a little like the source code turned on its side:

`Bucket` |
↓child
`Starfish` | sibling | `Oyster` | sibling | `Sand`
→ | →
| ↓child |
`Pearl`

The idea is that if no arrows `->` are given in the `Object` definition, then the object has no parent. If one `->` is given, then the object is made a child of the last object defined with no arrows; if two are given, it's made a child of the last object defined with only one arrow; and so on.

An object definition consists of a “head” followed by a “body”, itself divided into “segments”, though there the similarity with caterpillars ends. The head takes the form:

`Object` ‹arrows› ‹identifier› `"textual name"` ‹parent›

1. The ‹arrows› are as described above. Note that if one or more arrows are given, that automatically specifies what object this is the child of, so a ‹parent› cannot be given as well.
2. The ‹identifier› is what the object can be called inside the program, in the same way that a variable or a routine has a name.
3. The `"textual name"` can be given if the object's name ever needs to be printed by the program when it is running.
4. The ‹parent› is an object which this new object is to be a child of. This is an alternative to supplying arrows.

All four parts are optional, so that even this bare directive is legal:

    Object;

though it makes a nameless and featureless object which is unlikely to be useful.

### §3.4 Tree statements: `move`, `remove`, `objectloop`

The positions of objects in the tree are by no means fixed: objects are created in a particular formation but then shuffled around extensively during the story file's execution. (In an adventure game, where the objects represent items and rooms, objects are moved across the tree whenever the player picks something up or moves around.) The statement

`move` ‹object› `to` ‹object›

moves the first-named object to become a child of the second-named one. All of the first object's own children “move along with it”, i.e., remain its own children.

For instance, starting from the tree as shown in the diagram of §3.2 above,

    move Bottle to Mailbox;

results in the tree

`Meadow` |
↓child |
`Mailbox` |  | sibling |  | `Player` |
→
↓child |  | ↓child |
`Bottle` | sibling | `Note` |  | `Sceptre` | sibling | `Torch` | sibling | `Stone`
→ | → | →
| ↓child |
| `Battery` |

When an object becomes the child of another in this way, it always becomes the “eldest” child: that is, it is the new `child()` of its parent, pushing the previous children over into being its siblings. In the tree above, `Bottle` has displaced `Note` just so.

You can only move one object in the tree to another: you can't

    move Torch to nothing;

because `nothing` is not an object. Instead, you can detach the `Torch` branch from the tree with

    remove Torch;

and this would result in:

`Meadow` |  | `Torch`
↓child |  | ↓child
`Mailbox` |  | sibling |  | `Player` |  | `Battery`
→
↓child |  | ↓child |
`Bottle` | sibling | `Note` |  | `Sceptre` | sibling | `Stone` |
→ | →

The “object tree” is often fragmented like this into many little trees, and is not so much a tree as a forest.

• WARNING
It would make no sense to have a circle of objects each containing the next, so if you try to move `Meadow` to `Note`; then you'll only move the interpreter to print up:

[** Programming error: tried to move the Meadow to the note, which would make a loop: Meadow in note in mailbox in Meadow **]

· · · · ·

Since objects move around a good deal, it's useful to be able to test where an object currently is, and the condition `in` is provided for this. For example,

    Bottle in Mailbox

is true if and only if the `Bottle` is one of the direct children of the `Mailbox`. (`Bottle in Mailbox` is true, but `Bottle in Meadow` is false.) Note that

    X in Y

is only an abbreviation for `parent(X)==Y` but it occurs so often that it's worth having. Similarly, `X notin Y` means `parent(X)~=Y`. `X` has to be a bona-fide member of the object tree, but `Y` is allowed to be `nothing`, and testing `X in nothing` reveals whether or not `X` has been removed from the rest of the tree.

· · · · ·

The remaining loop statement left over from §1 is `objectloop`.

`objectloop(`‹variable-name›`)` ‹statement›

runs through the ‹statement› once for each object in the game, putting each object in turn into the variable. For example,

    objectloop(x) print (name) x, "^";

prints out a list of the textual names of every object in the game. More powerfully, any condition can be written in the brackets, as long as it begins with a variable name.

    objectloop (x in Mailbox) print (name) x, "^";

prints the names only of those objects which are direct children of the `Mailbox` object.

The simple case where the condition reads “‹variable› `in` ‹object›” is handled in a faster and more predictable way than other kinds of `objectloop`: the loop variable is guaranteed to run through the children of the object in sibling order, eldest down to youngest. (This is faster because it doesn't waste time considering every object in the game, only the children.) If the condition is not in this form then no guarantee is made as to the order in which the objects are considered.

• WARNING
When looping over objects with `in`, it's not safe to move these same objects around: this is like trying to cut a branch off an elm tree while sitting on it. Code like this:

    objectloop(x in Meadow) move x to Sandy_Beach;

looks plausible but is not a safe way to move everything in the `Meadow`, and will instead cause the interpreter to print up

[** Programming error: objectloop broken because the object mailbox was moved while the loop passed through it **]

Here is a safer way to move the meadow's contents to the beach:

    while (child(Meadow)) move child(Meadow) to Sandy_Beach;

This works because when the `Meadow` has no more children, its child is then `nothing`, which is the same as `false`.

▲ But it moves the eldest child first, with the possibly undesirable result that the children arrive in reverse order (`Mailbox` and then `Player`, say, become `Player` and then `Mailbox`). Here is an alternative, moving the youngest instead of the eldest child each time, which keeps them in the same order:

    while (child(Meadow)) {
        x = child(Meadow); while (sibling(x)) x = sibling(x);
        move x to Sandy_Beach;
    }

Keeping children in order can be worth some thought when game designing. For instance, suppose a tractor is to be moved to a farmyard in which there is already a barn. The experienced game designer might do this like so:

    move tractor to Farmyard;
    move barn to Farmyard;

Although the barn was in the farmyard already, the second statement wasn't redundant: because a moved object becomes the eldest child, the statement does this:

`Farmyard` |  | `Farmyard` |
↓child |  | => | ↓child |
`tractor` | sibling | `barn` |  | `barn` | sibling | `tractor`
→ | →

And this is desirable because the ordering of paragraphs in room descriptions tends to follow the ordering of items in the object tree, and the designer wants the barn mentioned before the tractor.

▲ An `objectloop` range can be any condition so long as a named local or global variable appears immediately after the open bracket. This means that

    objectloop (child(x) == nothing) ...

isn't allowed, because the first thing after the bracket is `child`, but a dodge to get around this is:

    objectloop (x && child(x) == nothing) ...

The loop variable of an `objectloop` can never equal `false`, because that's the same as `nothing`, which isn't an object.

▲▲ The `objectloop` statement runs through all objects of metaclass `Object` or `Class`, but skips any `Routine` or `String`.

### §3.5 Declaring objects 2: `with` and `provides`

So far `Objects` are just tokens with names attached which can be shuffled around in a tree. They become interesting when data and routines are attached to them, and this is what the body of an object definition is for. The body contains four different kinds of segments, introduced by the keywords:

    with    has    class    private

These are all optional and can be given in any order.

▲ They can even be given more than once: that is, there can be two or more of a given kind, which Inform will combine together as if they had been defined in one go. (This is only likely to be useful for automated Inform-writing programs.)

· · · · ·

The most important segment is `with`, which specifies variables and, as we shall see, routines and even arrays, to be attached to the object. For example,

    Object magpie "black-striped bird"
      with wingspan, worms_eaten;

attaches two variables to the bird, one called `wingspan`, the other called `worms_eaten`. Commas are used to separate them and the object definition as a whole ends with a semicolon, as always. Variables of this kind are called properties, and are referred to in the source code thus:

    magpie.wingspan
    magpie.worms_eaten

Properties are just like global variables: any value you can store in a variable can be stored in a property. But note that

    crested_grebe.wingspan
    magpie.wingspan

are different and may well have different values, which is why the object whose wingspan it is (the magpie or the grebe) has to be named.

The property `wingspan` is said to be provided by both the `magpie` and `crested_grebe` objects, whereas an object whose `with` segment didn't name `wingspan` would not provide it. The dot `.` operator can only be used to set the value of a property which is provided by the object on the left of the dot: if not a programming error will be printed up when the story file is played.

The presence of a property can be tested using the `provides` condition. For example,

    objectloop (x provides wingspan) ...

executes the code `...` for each object `x` in the program which is defined with a `wingspan` property.

▲ Although the provision of a property can be tested, it can't be changed while the program is running. The value of `magpie.wingspan` may change, but not the fact that the magpie provides a `wingspan`.

▲▲ Some special properties, known as “common properties”, can have their values read (but not changed) even for an object which doesn't provide them. All of the properties built into the Inform library are common properties. See §3.14.

· · · · ·

When the magpie is created as above, the initial values of

    magpie.wingspan
    magpie.worms_eaten

are both 0. To create the magpie with a given wingspan, we have to specify an initial value, which we do by giving it after the name, e.g.:

    Object magpie "black-striped bird"
      with wingspan 5, worms_eaten;

The story file now begins with `magpie.wingspan` equal to 5, though `magpie.worms_eaten` still equal to 0.

· · · · ·

A property can contain a routine instead of a value. In the definition

    Object magpie "black-striped bird"
      with name 'magpie' 'bird' 'black-striped' 'black' 'striped',
           wingspan 5,
           flying_strength [;
               return magpie.wingspan + magpie.worms_eaten;
           ],
           worms_eaten;

The value of `magpie.flying_strength` is given as a routine, in square brackets as usual. Note that the `Object` continues where it left off after the routine-end marker, `]`. Routines which are written in as property values are called “embedded” and are the way objects receive messages, as we shall see.

▲ If, during play, you want to change the way a magpie's flying strength is calculated, you can simply change the value of its property:

    magpie.flying_strength = ExhaustedBirdFS;

where `ExhaustedBirdFS` is the name of a routine to perform the new calculation.

▲ Embedded routines are just like ordinary ones, with two exceptions:

1. An embedded routine has no name of its own, since it is referred to as a property such as `magpie.flying_strength` instead.
2. If execution reaches the `]` end-marker of an embedded routine, then it returns `false`, not `true` (as a non-embedded routine would).

▲▲ Properties can be arrays instead of variables. If two or more consecutive values are given for the same property, it becomes an array. Thus,

    Object magpie "black-striped bird"
      with name 'magpie' 'bird' 'black-striped' 'black' 'striped',
           wingspan 5, worms_eaten;

You can't write `magpie.name` because there is no single value: rather, there is an `-->` array (see §2.4). This array must be accessed using two special operators, `.&` and `.#`, for the array and its length, as follows.

    magpie.&name

means “the array held in magpie's name property”, so that the actual name values are in the entries

    magpie.&name-->0, magpie.&name-->1, ..., magpie.&name-->4

The size of this array can be discovered with

    magpie.#name

which evaluates to the twice the number of entries, in this case, to 10. Twice the number of entries because that is the number of bytes in the array: people fairly often use property arrays as byte arrays to save on memory.

▲ `name` is a special property created by Inform, intended to hold dictionary words which can refer to an object.

### §3.6 Declaring objects 3: `private` properties

▲ A system is provided for “encapsulating” certain properties so that only the object itself has access to them. These are defined by giving them in a segment of the object declaration called `private`. For instance,

    Object sentry "sentry"
      private pass_number 16339,
      with challenge [ attempt;
               if (attempt == sentry.pass_number)
                   "Approach, friend!";
               "Stand off, stranger.";
      ];

provides for two properties: `challenge`, which is public, and `pass_number`, which can be used only by the sentry's own embedded routines.

▲▲ This makes the `provides` condition slightly more interesting than it appeared in the previous section. The answer to the question of whether or not

    sentry provides pass_number

depends on who's asking: this condition is true if it is tested in one of the sentry's own routines, and elsewhere false. A `private` property is so well hidden that nobody else can even know whether or not it exists.

### §3.7 Declaring objects 4: `has` and `give`

In addition to properties, objects have flags attached, called “attributes”. Recall that flags are a limited form of variable which can only have two values, sometimes called set and clear.) Unlike property names, attribute names have to be declared before use with a directive like:

    Attribute hungry;

Once this declaration is made, every object in the tree has a `hungry` flag attached, which is either `true` or `false` at any given time. The state can be tested with the `has` condition:

    magpie has hungry

is true if and only if the magpie's `hungry` flag is currently set. You can also test if `magpie hasnt hungry`. There's no apostrophe in `hasnt`.

The magpie can now be born `hungry`, using the `has` segment in its declaration:

    Object magpie "black-striped bird"
      with wingspan, worms_eaten
      has  hungry;

The `has` segment contains a list (without commas in between) of the attributes which are initially set: for instance, the steel grate in the Inform example game ‘Advent’ includes the line

    has  static door openable lockable locked;

The state of an attribute can be changed during play using the `give` statement:

    give magpie hungry;

sets the magpie's `hungry` attribute, and

    give magpie ~hungry;

clears it again. The `give` statement can take more than one attribute at a time, too:

    give double_doors_of_the_horizon ~locked openable open;

means “clear `locked` and set `openable` and `open`”.†

† The refrain from the prelude to Act I of Philip Glass's opera Akhnaten is “Open are the double doors of the horizon/ Unlocked are its bolts”.

▲▲ An attribute can also have a tilde `~` placed in front in the `has` part of an object declaration, indicating “this is definitely not held”. This is usually what would have happened anyway, except that class inheritance (see below) might have passed on an attribute: if so, this is how to get rid of it again. Suppose there is a whole class of steel grates like the one in ‘Advent’ mentioned above, providing for a dozen grates scattered through a game, but you also want a loose grate `L` whose lock has been smashed. If `L` belongs to the class, it will start the game with attributes making it locked like the others, because the class sets these automatically: but if you include `has ~lockable ~locked;` in its declaration, these two attributes go away again.

### §3.8 Declaring objects 5: `class` inheritance

A class is a prototype design from which other objects are manufactured. These resulting objects are sometimes called instances or members of the class, and are said to inherit from it.

Classes are useful when a group of objects are to have common features. In the definition of the `magpie` above, a zoologically doubtful formula was laid out for flying strength:

    flying_strength [;
        return magpie.wingspan + magpie.worms_eaten;
    ],

This formula ought to apply to birds in general, not just to magpies, and in the following definition it does:

    Attribute flightless;
    Class Bird
      with wingspan 7,
           flying_strength [;
               if (self has flightless) return 0;
               return self.wingspan + self.worms_eaten;
           ],
           worms_eaten;
    Bird "ostrich" with wingspan 3, has flightless;
    Bird "magpie" with wingspan 5;
    Bird "crested grebe";
    Bird "Great Auk" with wingspan 15;
    Bird "early bird" with worms_eaten 1;

Facts about birds in general are now located in a class called `Bird`. Every example of a `Bird` automatically provides `wingspan`, a `flying_strength` routine and a count of `worms_eaten`. Notice that the Great Auk is not content with the average avian wingspan of 7, and insists on measuring 15 across. This is an example of inheritance from a class being over-ridden by a definition inside the object. The actual values set up are as follows:

`B` | `B.wingspan` | `B.worms_eaten`
ostrich | 3 | 0
magpie | 5 | 0
crested grebe | 7 | 0
Great Auk | 15 | 0
early bird | 7 | 1

Note also the use of the special value `self` in the definition of `Bird`. It means “whatever bird I am”: if the `flying_strength` routine is being run for the ostrich, then `self` means the ostrich, and so on.

The example also demonstrates a general rule: to create something, begin its declaration with the name of the class you want it to belong to: a plain `Object`, a `Class` or now a `Bird`.

▲ Sometimes you need to specify that an object belongs to many classes, not just one. You can do this with the `class` segment of the definition, like so:

    Object "goose that lays the golden eggs"
      class Bird Treasure;

This goose belongs to three classes: `Object` of course, as all declared objects do, but also `Bird` and `Treasure`. (It inherits from `Object` first and then `Bird` and then `Treasure`, attribute settings and property values from later-mentioned classes overriding earlier ones, so if these classes should give contradictory instructions then `Treasure` gets the last word.) You can also make class definitions have classes, or rather, pass on membership of other classes:

    Class BirdOfPrey
    class Bird
     with wingspan 15,
          people_eaten;
    BirdOfPrey kestrel;

makes `kestrel` a member of both `BirdOfPrey` and of `Bird`. Dutiful apostles of object-oriented programming may want to call `BirdOfPrey` a “subclass” of `Bird`. Indeed, they may want to call Inform a “weakly-typed language with multiple-inheritance”, or more probably a “shambles”.

▲▲ For certain “additive” common properties, clashes between what classes say and what an instance says are resolved differently: see §5. Inform's built-in property `name` is one of these.

### §3.9 Messages

Objects communicate with each other by means of messages. A message has a sender, a receiver and some parameter values attached, and it always produces a reply, which is just a single value. For instance,

    x = plant.pour_over(cold_spring_water);

sends the message `pour_over` with a single parameter, `cold_spring_water`, to the object `plant`, and puts the reply value into `x`.

In order to receive this message, `plant` has to provide a `pour_over` property. If it doesn't, then the interpreter will print something like

[** Programming error: the plant (object number 21) has no property pour over to send message **]

when the story file is played. The `pour_over` property will normally be a routine, perhaps this one:

    pour_over [ liquid;
        remove liquid;
        switch(liquid) {
            oil: "The plant indignantly shakes the oil off its
                  leaves and asks, ~Water?~";
            ...
        }
    ];

Inside such a routine, `self` means the object receiving the message and `sender` means the object which sent it. In a typical Inform game situation, `sender` will often be the object `InformLibrary`, which organises play and sends out many messages to items and places in the game, consulting them about what should happen next. Much of any Inform game designer's time is spent writing properties which receive messages from `InformLibrary`: `before`, `after`, `each_turn` and `n_to` among many others.

You can see all the messages being sent in a game as it runs using the debugging verb “messages”: see §7 for details. This is the Inform version of listening in on police-radio traffic.

▲ It was assumed above that the receiving property value would be a routine. But this needn't always be true. It can instead be: `nothing`, in which case the reply value is also `nothing` (which is the same as zero and the same as `false`). Or it can be an `Object` or a `Class`, in which case nothing happens and the object or class is sent back as the reply value. Or it can be a string in double-quotes, in which case the string is printed out, then a new-line is printed, and the reply value is `true`.

▲ This can be useful. Here is approximately what happens when the Inform library tries to move the player northeast from the current room (the `location`) in an adventure game (leaving out some complications to do with doors):

    if (location provides ne_to) {
        x = location.ne_to();
        if (x == nothing) "You can't go that way.";
        if (x ofclass Object) move player to x;
    } else "You can't go that way.";

This neatly deals with all of the following cases:

    Object Octagonal_Room "Octagonal Room"
      with ...
           ne_to "The way north-east is barred by an invisible wall!",
           w_to Courtyard,
           e_to [;
               if (Amulet has worn) {
                   print "A section of the eastern wall suddenly parts
                          before you, allowing you into...^";
                   return HiddenShrine;
               }
           ],
           s_to [;
               if (random(5) ~= 1) return Gateway;
               print "The floor unexpectedly gives way, dropping you
                      through an open hole in the plaster...^";
               return random(Maze1, Maze2, Maze3, Maze4);
           ];

Noteworthy here is that the `e_to` routine, being an embedded routine, returns `false` which is the same as `nothing` if the `]` end-marker is reached, so if the Amulet isn't being worn then there is no map connection east.

▲▲ The receiving property can even hold an array of values, in which case the message is sent to each entry in the array in turn. The process stops as soon as one of these entries replies with a value other than `nothing` or `false`. If every entry is tried and they all replied `nothing`, then the reply value sent back is `nothing`. (This is useful to the Inform library because it allows `before` rules to be accumulated from the different classes an object belongs to.)

### §3.10 Passing messages up to the superclass

▲ It fairly often happens that an instance of a class needs to behave almost, but not quite, as the class would suggest. For instance, suppose the following `Treasure` class:

    Class Treasure
      with deposit [;
          if (self provides deposit_points)
              score = score + self.deposit_points;
          else score = score + 5;
          move self to trophy_case;
          "You feel a sense of increased esteem and worth.";
      ];

and we want to create an instance called `Bat_Idol` which flutters away, resisting deposition, but only if the room is dark:

    Treasure Bat_Idol "jewelled bat idol"
      with deposit [;
               if (location == thedark) {
                   remove self;
                   "There is a clinking, fluttering sound!";
               }
               ...
           ];

In place of `...`, what we want is all of the previous source code about depositing treasures. We could just copy it out again, but a much neater trick is to write:

    self.Treasure::deposit();

Instead of sending the message `deposit`, we send the message `Treasure::deposit`, which means “what `deposit` would do if it used the value defined by `Treasure`”. The double-colon `::` is called the “superclass operator”. (The word “superclass”, in this context, is borrowed from the Smalltalk-80 language.)

▲▲ `object.class::property` is the value of `property` which the given object would normally inherit from the given `class`. (Or it gives an error if the class doesn't provide that property or if the object isn't a member of that class).

▲▲ It's perfectly legal to write something like `x = Treasure::deposit;` and then to send `Bat_Idol.x();`.

### §3.11 Creating and deleting objects during play

In an adventure-game setting, object creation is useful for something like a beach full of stones: if the player wants to pick up more and more stones, the game needs to create a new object for each stone brought into play.

Besides that, it is often elegant to grow structures organically. A maze of caves being generated during play, for example, should have new caves gradually added onto the map as and when needed.

The trouble with this is that since resources cannot be infinite, the cave-objects have to come from somewhere, and at last they come no more. The program must be able to cope with this, and it can present the programmer with real difficulties, especially if the conditions that will prevail when the supply runs out are hard to predict.

Inform does allow object creation during play, but it insists that the programmer must specify in advance the maximum resources which will ever be needed. (For example, the maximum number of beach stones which can ever be in play.) This is a nuisance, but means that the resulting story file will always work, or always fail, identically on every machine running it. It won't do one thing on the designer's 256-megabyte Sun workstation in Venice and then quite another on a player's personal organiser in a commuter train in New Jersey.

· · · · ·

If you want to create objects, you need to define a class for them and to specify N, the maximum number ever needed at once. Objects can be deleted once created, so if all N are in play then deleting one will allow another to be created.

Suppose the beach is to contain up to fifty pebbles. Then:

    Class Pebble(50)
     with name 'smooth' 'pebble',
          short_name "smooth pebble from the beach";

`Pebble` is an ordinary class in every respect, except that it has the ability to create up to N = 50 instances of itself.

Creating and destroying objects is done by sending messages to the class `Pebble` itself, so for instance sending the message `Pebble.create()` will bring another pebble into existence. Classes can receive five different messages, as follows:

`remaining()`
How many more instances of this class can be created?

`create(`‹parameters›`)`
Replies with a newly created object of this class, or else with `nothing` if no more can be created. If given, the parameters are passed on to the object so that it can use them to configure itself (see below).

`destroy(I)`
Destroys the instance `I`, which must previously have been created. You can't destroy an object which you defined by hand in the source code. (This is quite unlike `remove`, which only takes an object out of the tree for a while but keeps it in existence, ready to be moved back again later.)

`recreate(I`, ‹parameters›`)`
Re-initialises the instance `I`, as if it had been destroyed and then created again.

`copy(I, J)`
Copies the property and attribute values from `I` to be equal to those of `J`, where both have to be instances of the class. (If a property holds an array, this is copied over as well.)

▲ It's rather useful that `recreate` and `copy` can be sent for any instances, not just instances which have previously been created. For example,

    Plant.copy(Gilded_Branch, Poison_Ivy)

copies over all the features of a `Plant` from `Poison_Ivy` to `Gilded_Branch`, but leaves any other properties and attributes of the gilded branch alone. Likewise,

    Treasure.recreate(Gilded_Branch)

only resets the properties to do with `Treasure`, leaving the `Plant` properties alone.

▲ If you didn't give a number like `(50)` in the class definition, then you'll find that N is zero. `copy` will work as normal, but `remaining` will return zero and `create` will always return `nothing`. There is nothing to `destroy` and since this isn't a class which can create objects, `recreate` will not work either. (Oh, and don't try to send these messages to the class `Class`: creating and destroying classes is called “programming”, and it's far too late when the game is already being played.)

▲▲ You can even give the number as `(0)`. You might do this either so that `Class Gadget(MAX_GADGETS)` in some library file will work even if the constant `MAX_GADGETS` happens to be zero. Or so that you can at least `recreate` existing members of the class even if you cannot create new ones.

· · · · ·

The following example shows object creation used in a tiny game, dramatising a remark attributed to Isaac Newton (though it appears only in Brewster's Memoirs of Newton).

    Constant Story "ISAAC NEWTON'S BEACH";
    Constant Headline "^An Interactive Metaphor^";
    Include "Parser";
    Include "VerbLib";
    Class Pebble(50)
     with name 'smooth' 'pebble' 'stone' 'pebbles//p' 'stones//p',
          short_name "smooth pebble from the beach",
          plural "smooth pebbles from the beach";
    Object Shingle "Shingle"
     with description
             "You seem to be only a boy playing on a sea-shore, and
              diverting yourself in finding a smoother pebble or a
              prettier shell than ordinary, whilst the great ocean of
              truth lies all undiscovered before you.",
     has  light;
    Object -> "pebble"
      with name 'smoother' 'pebble' 'stone' 'stones' 'shingle',
           initial "The breakers drain ceaselessly through the shingle,
                   spilling momentary rock-pools.",
           before [ new_stone;
               Take:
                   new_stone = Pebble.create();
                   if (new_stone == nothing)
                      "You look in vain for a stone smoother than
                       the fifty ever-smoother stones you have
                       gathered so far.";
                   move new_stone to Shingle;
                   <<Take new_stone>>;
           ],
      has  static;
    [ Initialise;
      location = Shingle;
      "^^^^^Welcome to...^";
    ];
    Include "Grammar";

In this very small adventure game, if the player types “take a pebble”, he will get one: more surprisingly, if he types “take a smoother pebble” he will get another one, and so on until his inventory listing reads “fifty smooth pebbles from the beach”. (See §29 for how to make sure identical objects are described well in Inform adventure games.) Notice that a newly-created object is in `nothing`, that is, is outside the object tree, so it must be moved to `Shingle` in order to come to the player's hand.

· · · · ·

However smooth, one pebble is much like another. More complicated objects sometimes need some setting-up when they are created, and of course in good object-oriented style they ought to do this setting-up for themselves. Here is a class which does:

    Class Ghost(7)
     with haunting,
          create [;
              self.haunting = random(Library, Ballroom, Summer_House);
              move self to self.haunting;
              if (self in location)
                  "^The air ripples as if parted like curtains.";
          ];

What happens is that when the program sends the message

    Ghost.create();

the class `Ghost` creates a new ghost `G`, if there aren't already seven, and then sends a further message

    G.create();

This new object `G` chooses its own place to haunt and moves itself into place. Only then does the class `Ghost` reply to the outside program. A class can also give a `destroy` routine to take care of the consequences of destruction, as in the following example:

    Class Axe(30);
    Class Dwarf(7)
     with create [ x;
              x = Axe.create(); if (x ~= nothing) move x to self;
          ],
          destroy [ x;
              objectloop (x in self && x ofclass Axe) Axe.destroy(x);
          ];

A new axe is created whenever a new dwarf is created, while stocks last, and when a dwarf is destroyed, any axes it carries are also destroyed.

Finally, you can supply `create` with up to 3 parameters. Here is a case with only one:

    Class GoldIngot(10)
     with weight, value,
          create [ carats;
              self.value = 10*carats;
              self.weight = 20 + carats;
          ];

and now `GoldIngot.create(24)` will create a 24-carat gold ingot.

### §3.12 Sending messages to routines and strings

▲ §3.9 was about sending messages to `Object`s, and then in §3.11 it turned out that there are five messages which can be sent to a `Class`. That's two of the four metaclasses, and it turns out that you can send messages to a `Routine` and a `String` too.

The only message you can send to a `Routine` is `call`, and all this does is to call it. So if `Explore` is the name of a routine,

`Explore.call(2, 4);` and `Explore(2, 4);`

do exactly the same as each other. This looks redundant, except that it allows a little more flexibility: for instance

    (random(Hello, Goodbye)).call(7);

has a 50% chance of calling `Hello(7)` and a 50% chance of calling `Goodbye(7)`. As you might expect, the `call` message replies with whatever value was returned by the routine.

Two different messages can be sent to a `String`. The first is `print`, which is provided because it logically ought to be, rather than because it's useful. So, for example,

    ("You can see an advancing tide of bison!").print();

prints out the string, followed by a new-line, and evaluates as `true`.

The second is `print_to_array`. This copies out the text of the string into entries 2, 3, 4,… of the supplied byte array, and writes the number of characters as a word into entries 0 and 1. (Make sure that the byte array is large enough to hold the text of the string.) For instance:

    Array Petals->30;
    ...
        ("A rose is a rose is a rose").print_to_array(Petals);

will leave `Petals-->0` set to 26 and place the letters `'A'`, `' '`, `'r'`, `'o'`, …, `'e'` into the entries `Petals->2`, `Petals->3`, …, `Petals->27`. For convenience, the reply value of the message `print_to_array` is also 26. You can use this message to find the length of a string, copying the text into some temporary array and only making use of this return value.

### §3.13 Common properties and `Property`

▲▲ Many classes, the `Bird` class for example, pass on properties to their members. Properties coming from the class `Object` are called “common properties”. Every item and place in an adventure game belongs to class `Object`, so a property inherited from `Object` will be not just common but well-nigh universal. Properties which aren't common are sometimes called “individual”.

The Inform library sets up the class `Object` with about fifty common properties. Story files would be huge if all of the objects in a game actually used all of these common properties, so a special rule applies: you can read a common property for any `Object`, but you can only write to it if you've written it into the object's declaration yourself.

For instance, the library contains the directive

    Property cant_go "You can't go that way.";

This tells Inform to add `cant_go` to the class definition for `Object`. The practical upshot is that you can perform

    print_ret (string) location.cant_go;

whatever the location is, and the resulting text will be “You can't go that way.” if the `location` doesn't define a `cant_go` value of its own. On the other hand

    location.cant_go = "Please stop trying these blank walls.";

will only work if `location` actually provides a `cant_go` value of its own, which you can test with the condition `location provides cant_go`.

▲▲ Using the superclass operator you can read and even alter the default values of common properties at run-time: for instance,

    location.Object::cant_go = "Another blank wall. Tsk!";

will substitute for “You can't go that way.”

▲▲ The Inform library uses common properties because they're marginally faster to access and marginally cheaper on memory. Only 62 are available, of which the compiler uses 3 and the library a further 47. On the other hand, you can have up to 16,320 individual properties, which in practical terms is as good as saying they are unlimited.

### §3.14 Philosophy

▲▲ “Socialism is all very well in practice, but does it work in theory?” (Stephen Fry). While the chapter is drizzling out into small type, this last section is aimed at those readers who might feel happier with Inform's ideas about classes and objects if only there were some logic to it all. Other readers may feel that it's about as relevant to actual Inform programming as socialist dialectic is to shopping for groceries. Here are the rules anyway:

1. Story files are made up of objects, which may have variables attached of various different kinds, which we shall here call “properties”.
2. Source code contains definitions of both objects and classes. Classes are abstract descriptions of common features which might be held by groups of objects.
3. Any given object in the program either is, or is not, a member of any given class.
4. For every object definition in the source code, an object is made in the story file. The definition specifies which classes this object is a member of.
5. If an object `X` is declared as a member of class `C`, then `X` “inherits” property values as given in the class definition of `C`.

Exact rules of inheritance aren't relevant here, except perhaps to note that one of the things inherited from class `C` might be the membership of some other class, `D`.

6. For every class definition, an object is made in the story file to represent it, called its “class-object”. For example, suppose we have a class definition like:

    Class Shrub
     with species;

The class `Shrub` will generate a class-object in the final program, also called `Shrub`. This class-object exists to receive messages like `create` and `destroy` and, more philosophically, to represent the concept of “being a shrub” within the simulated world.

The class-object of a class is not normally a member of that class. The concept of being a shrub is not itself a shrub, and the condition `Shrub ofclass Shrub` is `false`. Individual shrubs provide a property called `species`, but the class-object of `Shrub` does not: the concept of being a shrub has no single species.

7. Classes which are automatically defined by Inform are called “metaclasses”. There are four of these: `Class`, `Object`, `Routine` and `String`.

It follows by rule (6) that every Inform program contains the class-objects of these four, also called `Class`, `Object`, `Routine` and `String`.

8. Every object is a member of one, and only one, metaclass:
   1. The class-objects are members of `Class`, and no other class.
   2. Routines in the program, including those given as property values, are members of `Routine` and no other class.
   3. Constant strings in the program, including those given as property values, are members of `String`, and of no other class.
   4. The objects defined in the source code are members of `Object`, and possibly also of other classes defined in the source code.

It follows from (8.1) that `Class` is the unique class whose class-object is one of its own members: so `Class ofclass Class` is `true`.

9. Contrary to rules (5) and (8.1), the class-objects of the four metaclasses do not inherit from `Class`.
10. Properties inherited from the class-object of the metaclass `Object` are read-only and cannot be set.

· · · · ·

To see what the rules entail means knowing the definitions of the four metaclasses. These definitions are never written out in any textual form inside Inform, as it happens, but this is what they would look like if they were. (`Metaclass` is an imaginary directive, as the programmer isn't allowed to create new metaclasses.)

    Metaclass Object
     with name,
          ...;

A class from which the common properties defined by `Property` are inherited, albeit (by rule (10), an economy measure) in read-only form.

    Metaclass Class
    with create    [ ...; ... ],
         recreate  [ instance ...; ... ],
         destroy   [ instance; ... ],
         copy      [ instance1 instance2; ... ],
         remaining [; ... ];

So class-objects respond only to these five messages and provide no other properties: except that by rule (9), the class-objects `Class`, `Object`, `Routine` and `String` provide no properties at all. The point is that these five messages are concerned with object creation and deletion at run time. But Inform is a compiler and not, like Smalltalk-80 or other highly object-oriented languages, an interpreter. Rule (9) expresses our inability to create the program while it is actually running.

    Metaclass Routine
    with call [ parameters...; ... ];

Routines therefore provide only call.

    Metaclass String
    with print          [; print_ret (string) self; ],
         print_to_array [ array; ... ];

Strings therefore provide only `print` and `print_to_array`.

• REFERENCES
L. Ross Raszewski's library extension `"imem.h"` manages genuinely dynamic memory allocation for objects, and is most often used when memory is running terribly short.