DM4 §12: Containers, supporters and sub-objects

## §12 Containers, supporters and sub-objects

> The year has been a good one for the Society (hear, hear). This year our members have put more things on top of other things than ever before. But, I should warn you, this is no time for complacency. No, there are still many things, and I cannot emphasize this too strongly, not on top of other things.
> — ‘The Royal Society For Putting Things On Top Of Other Things’ sketch, Monty Python's Flying Circus, programme 18 (1970)

In almost every game, certain objects need to be thought of as on top of or inside other objects. The library provides actions `Insert` and `PutOn` for placing things inside or on top of something, and `Remove` for taking things out of or off the top of something. Many objects, such as house-bricks, cannot sensibly contain things, and a designer usually only wants certain specific items ever to have other things on top of them. In the model world, then, only objects which the designer has given the `container` attribute can contain things, and only those given the `supporter` attribute can have items on top.

The packing case brought by our archaeologist hero to the scene of the ‘Ruins’ (found in the opening location, the Forest) is a thoroughly typical `container`:

    Object -> packing_case "packing case"
      with name 'packing' 'case' 'box' 'strongbox',
           initial
               "Your packing case rests here, ready to hold any important
               cultural finds you might make, for shipping back to
               civilisation.",
           before [;
               Take, Remove, PushDir:
                   "The case is too heavy to bother moving, as long as
                   your expedition is still incomplete.";
           ],
      has  static container open openable;

A container can hold anything up to 100 items, but this limit can be modified by giving the container a `capacity` property.

Note that the packing case is defined having an attribute called `open`. This is essential, because the library will only allow the player to put things in a `container` if it is currently `open`. (There is no attribute called `closed`, as any container lacking `open` is considered closed.) If a container has `openable`, the player can open and close it at will, unless it also has `locked`. A `locked` object, whether it be a door or a container, cannot be opened. But if it has `lockable` then it can be locked or unlocked with the key object given in its `with_key` property. If `with_key` is undeclared or equal to `nothing`, then no key will fit, but this will not be told to the player. The actions `Open`, `Close`, `Lock` and `Unlock` handle all of this.

• EXERCISE 15
Construct a musical box with a silver key.

· · · · ·

An object having `supporter` can have up to 100 items put on top of it, or, once again, its `capacity` value if one is given. An object cannot be both a `container` and a `supporter` at once, and there's no concept of being “open” or “locked” for supporters. Here is an example from the Shrine:

    Object -> stone_table "slab altar"
      with name 'stone' 'table' 'slab' 'altar' 'great',
           initial "A great stone slab of a table, or altar, dominates
               the Shrine.",
      has  enterable supporter static;

See §15 for `enterable` and its consequences.

· · · · ·

Containers and supporters are able to react to things being put inside them, or removed from them, by acting on the signal to `Receive` or `LetGo`. For example, further down in the ‘Ruins’ is a chasm which, perhaps surprisingly, is implemented as a container:

    Object -> chasm "horrifying chasm"
      with name 'blackness' 'chasm' 'pit' 'horrifying' 'bottomless',
           react_before [;
               Jump: <<Enter self>>;
               Go: if (noun == d_obj) <<Enter self>>;
           ],
           before [;
               Enter: deadflag = true;
                   "You plummet through the silent void of darkness!";
               JumpOver: "It's far too wide.";
           ],
           after [;
               Receive: remove noun;
                   print_ret (The) noun, " tumbles silently into the
                       darkness of the chasm.";
               Search: "The chasm is deep and murky.";
           ],
      has  scenery open container;

(Actually the definition will grow in §23, so that the chasm reacts to an eight-foot pumice-stone ball being rolled into it.) Note the use of an `after` rule for the `Search` action: this is because an attempt to “examine” or “look inside” the chasm will cause this action. `Search` means, in effect, “tell me what is inside the container” and the `after` rule prevents a message like “There is nothing inside the chasm.” from misleading the player. Note also that the chasm ‘steals’ any stray `Jump` action in the vicinity using `react_before` and converts it into an early death.

• EXERCISE 16
Make an acquisitive bag which will swallow things up but refuses to disgorge them.

▲ `Receive` is sent to an object O when a player tries to put something in O, or on O. In the rare event that O needs to react differently to these two attempts, it may consult the library's variable `receive_action` to find out whether `##PutOn` or `##Insert` is the cause.

· · · · ·

Not all containment is about carrying or supporting things. For instance, suppose a machine has four levers. If the machine is fixed in place somewhere, like a printing press, the levers could be provided as four further `static` objects. But if it is portable, like a sewing machine, we need to make sure that the levers always move whenever it moves, and vice versa. The natural solution is to make the lever-objects children of the machine-object, as though the machine were a container and the levers were its contents.

However, members of an object which isn't a `container` or `supporter` are normally assumed by the library to be hidden invisibly inside. In the case of the levers, this would defeat the point. We can get around this by giving the machine the `transparent` attribute, making the levers visible but not removable.

Containers can also be `transparent`, making their contents visible even when closed. The items on top of a `supporter` are of course always visible, and it makes no sense for a `supporter` to be `transparent`. See §26 for further details on when contents are listed in inventories and room descriptions.

• EXERCISE 17
Make a glass box and a steel box, which behave differently when a lamp is shut up inside them.

• EXERCISE 18
Make a television set with attached power button and screen.

•▲ EXERCISE 19
Implement a macramé bag hanging from the ceiling, inside which objects are visible, audible and so forth, but cannot be touched or manipulated in any way.

▲ The most difficult case to handle is when an object needs to be portable, and to have sub-objects like lamps and buttons, and also to be a container in its own right. The solution to this will have to be left until the “scope addition” rules in §32, but briefly: an object's `add_to_scope` property may contain a list of sub-objects to be kept attached to it but which are not its children.

• REFERENCES
Containers and supporters abound in the example games (except ‘Advent’, which is too simple, though see the water-and-oil carrying bottle). Interesting containers include the lottery-board and the podium sockets from ‘Balances’ and the ‘Adventureland’ bottle. •For supporters, the hearth-rug, chessboard, armchair and mantelpiece of ‘Alice Through the Looking-Glass’ are typical examples; the mantelpiece and spirit level of ‘Toyshop’ make a simple puzzle, and the pile of building blocks a complicated one; see also the scales in ‘Balances’.