Roger Firth's IF pages

Home

Inform 6: Frequently Asked Questions

Email
Back up

Into
the Intro

Setting
the scene

Preparing
to program

Learning
the lingo

Dabbling
in data

Operating
on objects

Verbal
versatility

Bothered
by bugs

History and
hereafter

Worldly
woes

Inside
information

Tips and
techniques

These topics are about defining Inform objects:

Is a 'room' a special sort of object?
How does Inform distinguish nouns from adjectives?
When should I use scenery/static/concealed attributes?
How can I tell that one object is 'within' another?
    The object tree
    Moving objects around
How do I get rid of an object in mid-game?
What are the various 'description' properties for?
How are plural objects managed?
    Plural types and examples:
        Gunpowder; Instructions; String of pearls; Sticks of dynamite; Gold coins; Fuses; Matches; Cage of birds
Why do my pronouns keep changing?
    The MANUAL_PRONOUNS constant
How do I define a new object property?
    Common versus local properties
    Turning properties into arrays
How do I use my new object property?
    Routine or string? doesn't matter
Do I need to understand private properties?
How do I define a new object attribute?
How can I use individual properties as attributes?
What does class inheritance do for me?
When is a Dynamic class useful?
How can I reconfigure the Player Character (PC)?
Why does my game crash when I use move in an objectloop?
    objectloop formats
Can I loop through all of an object's dependents?

Is a 'room' a special sort of object?

No: a 'room' is simply an Inform object which the player can enter by some means, and which doesn't have a parent. Thereís nothing more to it than that.

How does Inform distinguish nouns from adjectives?

It doesn't. In an object's name property, you need to list all of the words that a player might think to use when referring to that object. For example, in this object, introduced when talking about apostrophes and quotes:

More information in the DM:
§28

  Object  old_man "grumpy old man"
    with  name 'man' 'grumpy' 'cross' 'old' 'elderly' 'ancient' 'gnome',
          description "The grumpy old man stands silently in the corner.",
          ...
    has   animate;

you'll see there are two nouns -- 'man' and 'gnome' -- and five adjectives. The player could use these seven words (also THE which is always available) in every possible combination, both sensible (GRUMPY OLD MAN, THE GNOME, THE ELDERLY MAN, CROSS GNOME) and not so sensible (THE ANCIENT CROSS, GRUMPY GRUMPY, MAN OLD ELDERLY ANCIENT GNOME). In all of these cases, Inform will infer that the player is referring to the "grumpy old man" object. As it happens, players have become accustomed to this behaviour, and don't find it much of a problem.

Occasionally, you'll create a set of objects with similar names, in which circumstance having Inform react to nouns more strongly than to adjectives is helpful to players. (Without such special treatment, your players may have difficulty picking up, for example, a JEWEL which occurs in the same location as a JEWEL BOX.) Neil Cerutti's pname.h from the Archive offers a good solution in these circumstances.

When should I use scenery/static/concealed attributes?

You affect an object's behaviour using these attributes. The main differences are:

attribute

Does LOOK mention it?

Can you TAKE it?

Does TAKE ALL attempt it?

scenery

no

no -- "hardly portable"

yes (annoyingly)

static

yes

no -- "fixed in place"

yes

concealed

no

yes -- listed in your inventory, but disappears again if you drop it

no

none of these

yes

yes

yes

One of the main uses of concealed is for something that can be 'discovered' during the game, for example when you SEARCH another object. Using this technique, you might use an after property on the object being searched to remove the hidden object's concealed attribute, thereby bringing it into view. The alternative method is to use that same after property to bring the hidden object into the room from elsewhere; this has the disadvantage that second-time-around players still need to SEARCH even though they know that the hidden object is present. (On the other hand, if you allow them this shortcut, you need to remove the concealed attribute anyhow if they do TAKE without SEARCH.)

(An alternative to the concealed attribute, useful only rarely, is to give the object this property: describe [; rtrue; ], -- the object behaves in much the same way, except that it's included in a TAKE ALL attempt.)

On the subject of scenery and static, you occasionally run into trouble with the parser being too helpful. If the player types a command like TAKE without specifying an object, the parser usually asks "What do you want to take?", which is fine. If, however, there is only one object in scope, the parser guesses that that must be what you want, even if it's non-takeable. For example:

  >TAKE
  (the writing desk)
  The writing desk is too heavy for that.

The best way to avoid this is by ensuring that there's always a choice of objects with the same attribute level -- two without static/scenery, or failing that two with static, or as a last resort two with scenery.

How can I tell that one object is 'within' another?

General object tree

A typical Inform program defines dozens of objects: rooms, furniture, pieces of scenery, Non-Player Characters (NPCs), artefacts of all shapes and sizes. Rather than floating independently in some abstract space, most of those objects are linked by formal (but fluid) relationships. An important part of Inform programming is managing the changes in those relationships: keeping track of which objects are 'in' or 'on' other objects at each turn in the game.

For example, you might visualize the relationship between several objects in a bank thus. In this diagram, the money, diamond and certificate are in the strongbox, which is in the safe (along with the will), and the safe is in the same room as the counter, on which is a key. It's common to talk about an object's parent and its children: thus, the safe's parent is the bank, and its children are the strongbox and the will. If the player was to enter the bank and type TAKE THE KEY, the diagram would need redrawing to show the player as a child of the bank, and the key as a child of the player.

Inform object tree

The diagram above shows a conceptual representation in which each object has a single parent object (or nothing) above it, and zero, one or more child objects below it. However, this representation doesn't precisely reflect the way in which Inform stores its data. The relationship between Inform objects -- the object tree -- is actually defined by three pointers. Each object has an 'upwards' pointer towards its parent, a 'downwards' pointer towards its child, and a 'sideways' pointer towards its sibling; a pointer contains the constant nothing if there is no object above, below or to the side.

This system of pointers means that the set of objects in the bank is actually connected as shown alongside. You might notice that there is a small discrepancy between the conceptual model -- in which an object like the strongbox can have several children -- and the physical model, where an object has one (eldest) child, with any younger children being linked out to the side. The built-in functions parent(), sibling() and child() reflect this physical view:

More information in the DM:
§3.2 §3.4

  parent(bank) == nothing
  sibling(bank) == nothing
  child(bank) == counter

  parent(counter) == bank
  sibling(counter) == safe
  child(counter) == key

  parent(safe) == bank
  sibling(safe) == nothing
  child(safe) == strongbox

and so on.

You can change object relationships with the move and remove statements, but it's relatively rare that you need to do so -- most of the time, the Library does everything necessary to move objects around the tree. What you frequently do need is the ability to discover where an object is currently located. You can test whether one object is a child of another object -- its parent -- using either of:

  if (parent(c_obj) == p_obj) { ... }
  if (c_obj in p_obj) { ... }

You can't reliably use this test:

  if (c_obj == child(p_obj)) { ... }

because the child() function returns only an object's eldest child, rather than a list of all children; for example (safe == child(bank)) evaluates to false.

The first two tests, although reliable, are also limited in scope: they concern themselves only with an object's immediate children. So, (parent(safe) == bank) and (safe in bank) both evaluate to true, but (parent(strongbox) == bank) and (strongbox in bank) both evaluate to false -- the strongbox object is a grandchild of the bank object, not a direct child.

To get round this problem, you can use the Library routine IndirectlyContains():

  if (IndirectlyContains(p_obj, c_obj)) { ... }

This routine returns true if p_obj is a parent, or grandparent, or great-grandparent, or great-great-grandparent..., of c_obj; that is, if c_obj lies anywhere below p_obj in the tree. So, IndirectlyContains(bank,strongbox) evaluates to true.

A related routine, CommonAncestor(c_obj1, c_obj2), returns the nearest object which has a parental relationship to both c_obj1 and c_obj2, or nothing. For example, CommonAncestor(diamond,will) would return the safe.

How do I get rid of an object in mid-game?

More information in the DM:
§3.4

You don't actually delete an unwanted object during the course of a game; you just reposition it out of the way so that the player won't ever encounter it. You usually do this by making its parent nothing, which detaches it from the object tree. However, you can't type move myObj to nothing; since nothing isn't an object; instead you use:

  remove myObj;

The removed object now lurks out of sight, until either the game ends or you choose to resurrect it. To bring the object back into play, you simply need something like:

  move myObj to location;

That's really all there is to it, though while we're here we'll mention a few related points. You can test whether an object has been removed by either of these:

  if (myObj in nothing) { ... }
  if (parent(myObj) == nothing) { ... }

but what you can't so easily do is identify all of the removed objects. This is a valid statement:

  objectloop (x && x in nothing) { ... }

but it finds too much: several Library objects and all of the rooms, as well as any objects which you've shifted out of play. If you need to loop through out-of-play objects, a better approach is not to use the remove statement. Instead, create an inaccessible room -- commonly called "Limbo" -- and move unwanted objects into it. This is all you need:

  Object  limbo "Limbo"
    with  description "How the hell did you get in here?";
  ...
  move myObj to limbo;
  ...
  objectloop (x in limbo) { ... }

More information in the DM:
§8

If you've given myObj a found_in property -- so that it magically pops up in various rooms as the player visits them -- you've got a little more work to do. If you just move or remove such an object out of play, the Library will promptly transport it back again. You need to prevent this, by applying the absent attribute:

  move myObj to limbo;   ! or: remove myObj;
  give MyObj absent;

More information in the DM:
§3.11

Finally, the rather more complex business of creating and deleting objects during play. We'll skip most of the detail and just sketch the outline of dynamic object manipulation. First, you need a class from which to create your objects (the "10" specifies the maximum number which can be in play concurrently):

  Class   myObj(10)
    with  ... ;

and then you use statements like these to add a new object to the game, and later to get rid of it again:

  x = myObj.create();
  ...
  myObj.destroy(x);

Note that destroy() works only for objects which have previously been added using create(), not for normal objects which have existed throughout the game.

What are the various 'description' properties for?

Two of the more popular commands during a game are LOOK (or L) and EXAMINE or (X). Here's a typical example:

  >LOOK

  Dingy hall
  Steps lead down into darkness.

  You can see a trunk (which is closed) and a flashlight here.

  >EXAMINE THE TRUNK
  The trunk is large enough to get inside.

Here you can see the ubiquitous 'description' property doing its stuff: LOOK displays the current location's name, its description and a list of its notable contents, while EXAMINE displays the description of the specified object:

  Object  hallway "Dingy hall"
    with  description "Steps lead down into darkness.",
          d_to cellar,
    has   light;

  Object  -> "trunk"
    with  name 'trunk' 'chest' 'box',
          description "The trunk is large enough to get inside.",
    has   static container enterable openable ~open;

  Object  -> "flashlight"
    with  name 'flashlight' 'torch',
          description "It's a battery-powered flashlight, of the sort that switches on and off.",
          after [;
            SwitchOn:  give self light;
            SwitchOff: give self ~light;
          ],
    has   switchable ~on ~light;

More information in the DM:
§26

The library provides a number of standard object properties which are used in specific circumstances to display descriptive information about the object; description is the one most commonly found, but the others all have their place. This table summarises their usage:

Property

For a room

For an object

description

The first text (after the room's name) displayed by LOOK in that room, and on initial entry to the room.

Displayed by EXAMINE of the object.

This is the only property which is consulted by the EXAMINE command; all of the other entries in this table are associated with the LOOK command.

inside_description

Displayed after the room's description text.

For an enterable object which the player is inside, displayed after the parent room's description text (if the room is still visible) or instead of it (if not). Over-rides initial and when_open/when_closed.

describe

The first text (after the room's name) displayed by LOOK in that room, and on initial entry to the room. Over-rides description (but provides no additional functionality and so is effectively redundant for a room).

Displayed after the parent room's description text.

If this property is a string or a routine returning true, any of the properties below are ignored.

initial

Displayed before the room's name when the player moves to that room.

For an object which hasn't moved, displayed after the parent room's description text. Once the object has moved, this property is ignored and the object is included in the "You can [also] see..." list.

when_on

Ignored.

For a switchable object which has on, displayed after the parent room's description text. Over-rides initial.

when_off

Ignored.

For a switchable object which hasn't on, displayed after the parent room's description text. Over-rides initial.

when_open

Ignored.

For a door or container object which has open, displayed after the parent room's description text. Over-rides initial and when_on/when_off.

when_closed

Ignored.

For a door or container object which hasn't open, displayed after the parent room's description text. Over-rides initial and when_on/when_off.

none of these

-

Displayed in the list of "You can [also] see..." objects at the end of the room description (except for concealed or scenery objects).

It's hard to predict the precise presentation -- trial and error is your best bet -- but as a rule-of-thumb, the library automatically prints a newline before each property value (except for describe), and also prints one after each property whose value is a string (if a property value is a routine, the terminating newline is under your control).

Here's our previous example, now ornamented with a few of these properties:

  Object  hallway "Dingy hall"
    with  description "Steps lead down into darkness.",
          d_to cellar,
    has   light;

  Object  -> "trunk"
    with  name 'trunk' 'chest' 'box',
          description "The trunk is large enough to get inside.",
          inside_description "From the inside, the trunk doesn't now seem so big.",
          when_open "An open trunk sits in one corner.",
          when_closed "The trunk in the corner looks like it can be opened.",
    has   static container enterable openable ~open;

  Object  -> "flashlight"
    with  name 'flashlight' 'torch',
          description "It's a battery-powered flashlight, of the sort that you switch on and off.",
          after [;
            SwitchOn:  give self light;
            SwitchOff: give self ~light;
          ],
          when_on "The flashlight provides a faint glimmer.",
    has   switchable ~on ~light;

And this is the result:

  >LOOK

  Dingy hall
  Steps lead down into darkness.

  The trunk in the corner looks like it can be opened.

  You can also see a flashlight here.

  >SWITCH ON THE FLASHLIGHT
  You switch the flashlight on.

  >OPEN THE TRUNK
  You open the trunk.

  >LOOK

  Dingy hall
  Steps lead down into darkness.

  An open trunk sits in one corner.

  The flashlight provides a faint glimmer.

  >ENTER TRUNK
  You get into the trunk.

  >LOOK

  Dingy hall (in the trunk)
  Steps lead down into darkness.

  The flashlight provides a faint glimmer.

  From the inside, the trunk doesn't now seem so big.

How are plural objects managed?

While most of your game objects will be singular -- A SHINY SWORD, AN ANCIENT BRASS LANTERN, THE GRUMPY OLD MAN -- you will occasionally need to represent plurals: multiple objects such as A HANDFUL OF BEANS, THREE GOLD COINS, A BRACE OF PHEASANTS. The Library provides several standard properties and attributes which are useful when dealing with plural objects; here are some of the basic techniques:

Mass noun (singular)

For example: gunpowder, machinery, foliage

Referenced by the player as:
THE GUNPOWDER
SOME GUNPOWDER
IT

Referenced by the game as:
You can see some gunpowder here.
You see nothing special about the gunpowder.
That's not something you can close.
You can't wear that!

More information in the DM:
§26

Object  -> "gunpowder"
  with  name 'gunpowder' 'blasting' 'powder',
        article "some";
  

Commentary:
Use the article property: the game understands the object as singular, but incorporates the possibility of using a special prefix in place of "a" or "an" -- in this case, "some".

The article property lets you define whatever word or group of words will best suit your needs. In the example, you could replace "some" with "lots of", "several tons of", "a few grains of", etc.
 

Mass noun (plural)

For example: instructions, grapes, scissors

Referenced by the player as:
THE INSTRUCTIONS
SOME INSTRUCTIONS
THEM

Referenced by the game as:
You can see some instructions here.
You see nothing special about the instructions.
They're not something you can close.
You can't wear those!

More information in the DM:
§26 §29

Object  -> "instructions"
  with  name 'instructions',
  has   pluralname;
  

Commentary:
Use the pluralname attribute: the game marks the object as plural, automatically changing pronouns and articles as needed.

The name property of the object should list only plural names and synonyms, because the pluralname attribute tells the parser and the library to consider the object as plural in all cases. Consider the following (erroneous) code:

  Object  -> "instructions"
    with  name 'sheet' 'of' 'instructions',
          article "a sheet of",
    has   pluralname;

Here the player could type, for example, OPEN SHEET (which is singular) and get the mismatched plural response "They're not something you can open.". For a way round this, see the next example.
 

Singular/plural noun

For example: string of pearls, sheet of instructions, bunch of grapes

Referenced by the player as:
THE STRING
THE STRING OF PEARLS
THE PEARLS

Referenced by the game as:
You can see {a string of pearls|some pearls on a string} here.
{That's|They're} not something you can close.

More information in the DM:
§26 §28

Object  ->
  with  name 'string' 'of' 'pearls' 'pearl',
        parse_name [ wd num singular;
            for (wd=NextWord() :
                    WordInProperty(wd,self,name) :
                        wd=NextWord()) {
                num++;
                if (wd == 'string') singular = true;
                }
            if (num) {
                if (singular) give self ~pluralname;
                else          give self pluralname;
                }
            return num;
            ],
        short_name [;
            if (self has pluralname)
                print "pearls on a string";
            else print "string of pearls";
            rtrue;
            ],
  has   ~pluralname;
  

Commentary:
If you supply a parse_name property, it overrides any name property. These three examples work identically:

  name 'string' 'of' 'pearls',

  parse_name [ wd num;
                 for (wd=NextWord() :
                     wd=='string' or 'of' or 'pearls' :
                         wd=NextWord()) num++;
                 return num; ],

  name 'string' 'of' 'pearls',
  parse_name [ wd num;
                 for (wd=NextWord() :
                     WordInProperty(wd,self,name) :
                         wd=NextWord()) num++;
                 return num; ],

The advantage of a parse_name property is the capability of recognising certain trigger words, and then modifying or extending the standard behaviour. Here, EXAMINE STRING makes the object singular, while EXAMINE PEARLS makes it plural.

The printable name is supplied by a short_name property rather than being given on the object's header line, so that it too can toggle between singular and plural forms.
 

Enumerated set of indistinguishable nouns #1

For example: sticks of dynamite, throwing knives

Referenced by the player as:
THE STICK
TWO [THREE,4,...] STICKS
ALL STICKS
IT

Referenced by the game as:
You can see some sticks of dynamite here.
You see nothing special about the stick of dynamite.
That's not something you can close.
You can't wear that!

More information in the DM:
§29

Class   TNT
  with  name 'stick' 'sticks//p' 'of' 'dynamite' 'tnt',
        short_name "stick of dynamite",
        plural "sticks of dynamite";

TNT     ->;
TNT     ->;
TNT     ->;
  

Commentary:
Make the objects 'indistinguishable' by creating a Class definition which includes a short_name property (to tell the game how to name a single instance of the object) and a plural property (to tell the game how to name a group of these objects). Add the modifier //p to the plural dictionary word in the name property.

The player canít refer to THEM when they are grouped.

Most verbs (except TAKE, DROP) produce: "You canít use multiple objects with that verb." if the player refers to more than one stick.
 

Enumerated set of indistinguishable nouns #2

For example: gold coins

Referenced by the player as:
THE COIN
TEN [100,1000,...] COINS
ALL COINS
THEM

Referenced by the game as:
You can see one thousand gold coins here.
You see nothing special about the gold coins.
They're not something you can close.
You can't wear those!

More information in the DM:
§3.11

Class   Money(10)
  with  name 'money' 'cash' 'gold',
        sing_name 'coin' 'dollar' 'zorkmid',
        plur_name 'coins' 'dollars' 'zorkmids',
        parse_name [ wd qty b p s;
          qty = TryNumber(wn);
          if (qty >= 0) { b++; wn++; }
          wd = NextWord();
          while (wd) {
            if (WordInProperty(wd,self,name)) b++;
            else
              if (WordInProperty(wd,self,plur_name)) p++;
              else
                if (WordInProperty(wd,self,sing_name)) s++;
                else break;
            wd = NextWord();
          }
          if (qty < 0)  ! TryNumber() didn't find a number
            if (s > p) qty = 1;
            else       qty = self.current_qty;
          if (p+s) self.request_qty = qty;
          return b+p+s;
        ],
        current_qty 0,  ! Number of coins in this object
        request_qty 0,  ! Number requested by player
        article [;
          if (self.current_qty == 1) print "a single";
          else        print (number) self.current_qty;
          rtrue;
        ],
        short_name [;
          if (self.current_qty == 1) print "gold coin";
          else                       print "gold coins";
          rtrue;
        ],
        before [ o;     ! Before any cmd for these coins
          if (self.request_qty == 0)
            self.request_qty = self.current_qty;
          if (self.request_qty > self.current_qty)
            return L__M(##Miscellany,42,self.current_qty);
          if (self.request_qty < self.current_qty) {
            o = self.current_qty - self.request_qty;
            o = Money.create(o, parent(self));
            if (o == nothing) "BUG: Money creation failed!";
            self.current_qty = self.request_qty;
            self.request_qty = 0;
          }
        ],
        each_turn [ o;
          self.request_qty = 0;
          objectloop (o ofclass Money &&
                      parent(o) ~= Money &&
                      o ~= self)
            if (parent(o) == parent(self)) {
              self.current_qty =
                self.current_qty + o.current_qty;
              Money.destroy(o);
            }
        ],
        adjust [ qty;
          if (qty >= 0)
            self.current_qty = self.current_qty + qty;
          else {
            qty = -qty;
            if (qty < self.current_qty)
              self.current_qty = self.current_qty - qty;
            else
              Money.destroy(self);
          }
        ],
        create [ qty loc;
          self.current_qty = qty;
          self.request_qty = 0;
          if (loc) move self to loc;
        ],
  has   pluralname;

Commentary:
The previous approach works well for relatively small numbers of indistinguishable items (say, fewer than 50), but because each item is an individual object, doesn't perform well for larger quantities. In a situation where the player has, for example, 1000 coins which he can spent, give to beggars, throw into fountains, and so on, you need something different (and more complex).

This example uses a single object to represent all 1000 coins, which is fast and economical of Z-machine memory but causes some other problems: basically, you need to do a lot of the work that in the previous approach was done automatically by the library.

We supplement the standard name property (which contains 'neutral' words) with two of our own: sing_name and plur_name. Then, we use a parse_name routine to match against all of those, and also to look for a possible number typed first (TEN DOLLARS, 100 GOLD COINS); the routine stores such a value in the request_qty property as well as returning the number of matched words in the usual way. If no explicit number is typed, request_qty is set to either 1 (if the player typed just COIN), or -- if he typed COINS -- to the total number of coins available (which is stored in current_qty). We also need our own article and short_name properties, to handle the value in current_qty.

Having a single object for all 1000 coins is fine... until the player decides to DROP 50 COINS. At that point we need two objects: one representing the 50 coins on the ground, the other representing the 950 coins which the player is still holding. So, our before property creates a new object of the Money class, and adjust the current_qty properties of both objects. Then, the action continues... but only affects the object containing the specified quantity. The new object, respresenting the remainder of the coins, stays in the player's possession.

So far, so good... but what if the player decides to TAKE 50 COINS back into his inventory, or to DROP 100 COINS next to the original 50? We've now got two Money objects, where we want only one. The each_turn property takes care of this; it runs each turn looking for multiple Money objects with the same parent, and it combines them back into a single object.

Two final properties: adjust is provided so that other objects can add and subtract from current_quantity, destroying the Money object if that value reaches zero (adjust isn't used here, but might come into play if the player typed something like BUY BEANS FROM PEDDLER). And create brings a new Money object into being: we use it in the before property, and also in our Initialise routine -- the call is simply Money.create(1000, player); -- to give the player his initial stash of cash. Note that we have to use this technique, instead of defining an object's initial location within the object tree, because we are creating and destroying objects dynamically. The first line -- Class Money(10) -- says that up to ten separate collections of coins can be lying around at any one time; the actual number of coins in each of those collections is immaterial.
 

Grouped set of indistinguishable nouns

For example: fuses, grains of rice, rusty nails

Referenced by the player as:
THE FUSE
THE FUSES
IT

Referenced by the game as:
You can see several fuses here.
You see nothing special about the fuse.
That's not something you can close.
You can't wear that!

More information in the DM:
§27

Class   Fuse
  with  name 'fuse' 'fuses//p',
        short_name "fuse",
        list_together [;
            if (inventory_stage == 1) {
                print "several fuses";
                if (c_style & NEWLINE_BIT) new_line;
                rtrue;
                }
            ];

Fuse    ->;
Fuse    ->;
  

Commentary:
These are objects where two or more in the same place forms a group of indeterminate size. Define a Class, as in the previous example, and supply a list_together property with the listing rules you want to apply; this overrides the default library operation that would try to number how many instances are grouped together.

A terminating new_line is needed when the player's inventory includes "several fuses", but not when "several fuses" appear at the end of a room's description.

The player canít refer to THEM when they are grouped.
 

Inexhaustible set, with ability to reference a single instance

For example: matches, pad of paper, bag of sweets

Referenced by the player as:
THE MATCHES
THE MATCH

Referenced by the game as:
You can see some matches here.
You see nothing special about the matches.
They're not something you can close.
You can't wear those!

More information in the DM:
§6 §20

Object  -> "matches"
  with  name 'matches',
        before [; Burn: <<Burn (child(self))>>; ],
  has   pluralname transparent;

Object  -> -> "match"
  with  name 'match',
        before [; PronounNotice(parent(self));
            Burn: return burning_match.light_me();
            default: <<(action) (parent(self)) second>>;
            ],
  has    pluralname;

Object  burning_match "burning match"
  with  name 'burning' 'lit' 'match',
        before [; Burn: "You've already lit one."; ],
        light_me [;
            if (parent(self)) <<Burn self>>;
            PronounNotice(self); move self to player;
            StartTimer(self, 4);
            "You light a match.";
            ],
        time_left 0,
        time_out [;
            remove self;
            "^The match burns to nothing.";
            ];
  

Commentary:
These are objects which exist as a group of infinite size, from which at any time no more than one instance can be detached: references to a single instance are normally taken as referring to the whole group, except where the action makes more sense applied to the individual. For example, TAKE MATCH, DROP PAPER and EXAMINE SWEET might apply to the group, while LIGHT MATCH, FOLD PAPER and UNWRAP SWEET might be more applicable to a single instance.

A single-instance object is defined as a child of the group object, which is given the transparent attribute to bring the child into scope (though not into view). The child delegates all actions other than Burn up to its parent, while the parent delegates a Burn action down to the child.

The act of lighting a match brings a new burning_match object temporarily into play; the processing is handled by that object's own light_me property, thus encapsulating the nitty-gritty details within the one place.
 

Virtual nouns

For example: cage of birds, bowl of fish, shopping list

Referenced by the player as:
THE CAGE
THE BIRDS
IT

Referenced by the game as:
You can see a cage of birds here.
You see nothing special about the bird cage.
That's not something you can close.
You can't wear that!

More information in the DM:
§26

Object  ->
  with  name 'bird' 'birds' 'cage',
        short_name [;
            if (self.number) print "cage of birds";
            else             print "bird cage";
            rtrue;
            ],
        invent [;
            if (inventory_stage == 1)
              switch (self.number) {
                0: print "an empty bird cage";
                1: print "a cage containing a bird";
                2: print "a pair of birds in a cage";
                default: print "a cage full of birds";
                }
            rtrue;
            ],
        number 2;
  

Commentary:
Occasionally you encounter a set of items, variable in number, which can't exist in isolation, only in the context of some other object. To avoid coding lots of objects, you might be able to simply instantiate the items by using their parent's short_name and invent properties.
 

Other examples of plural objects include: a pair of gloves (DM Exercise 14); the Scrabble pieces (DM Exercise 67); various coins (DM Exercises 68 and 69, also Balances.inf); and a book of matches, a box of candles and a pile of blocks (all from Toyshop.inf).

Most of these examples are actually fairly simplistic, with even the relatively intricate Gold Coins object having some gaps in its implementation. There are often object-specific complexities -- typically related to manipulating them singly, in combination and as a group -- which mean that significant additional coding is needed. If you are trying to model real-world handling of a tricky subject like, for example, containers of liquid, you will need considerable patience to get things working properly; trial and error is usually the best approach.

Why do my pronouns keep changing?

The library manipulates four pronouns -- IT, HIM, HER and THEM -- on the player's behalf, so that the most recently-mentioned objects match the appropriate pronouns. So far, so good: if you EXAMINE THE GRUMPY OLD MAN, that assigns the HIM pronoun to mean the old_man object; GIVE AXE TO HIM makes IT refer to the axe, and so on. You can use the PRONOUNS verb to check this out; the game's behaviour is nicely predictable.

Where, arguably, things start to fall apart is having the library adjust the pronoun assignments without your knowledge. After you type INVENTORY, then typically IT now refers to the last item that the player is carrying; after you type LOOK then typically IT refers to the item listed last in the room's contents. The other pronouns are similarly adjusted if there are NPCs or plural objects present. This can be highly confusing, especially since a TAKEn object appears first in the inventory, and a DROPped one first in the room description:

  You can see a rusty axe, a bomb, some cartridges, a dagger and an executioner here.

  >X AXE
  You see nothing special about the rusty axe.

  >TAKE IT
  Taken.

  >INV
  You are carrying:
    a rusty axe
    a shiny sword
    some grenades
    a nail-studded club

  >X IT
  You see nothing special about the nail-studded club.

To many players, this re-assignment of the settings can seem arbitrary and unpredictable, causing them to avoid the use of pronouns altogether. So, I recommend that you turn off the pronoun checking performed by INV and LOOK. It's easy to do; just define a MANUAL_PRONOUNS constant at the start of your game:

  Constant Story "MYGAME";
  Constant Headline "^My first Inform game.^";
  Constant MANUAL_PRONOUNS;

Pronouns are now assigned only when the player refers directly to an object. Of course, this may mean that, as you move around, the object referenced by a pronoun is no longer in scope, but at least you can understand what's going on.

How do I define a new object property?

There are two ways: using common properties (rarely found), and using individual properties (very commonly found).

More information in the DM:
§3.5 §3.13

You can define a common property, one that is possessed by every object in the game, by adding a line like this near the start of the game:

  Property weight 0;

There's an Inform limit of 62 common properties in total, and the Library already defines 50 of them. This isn't actually much of a restriction, because it's quite rare to need common properties; most of the time, you can do the job better using individual properties.

You can define an individual property which applies only to one object, or to a class of objects, simply by mentioning its name in the with segment when defining the object or class; you don't need to use the Property directive. For example, you might say:

  Object  old_man "grumpy old man"
    with  name 'man' 'grumpy' 'cross' 'old' 'elderly' 'ancient' 'gnome',
          grumpiness 3,
          ...
    has   animate;

in order to vary the old man's behaviour according to how grumpy he was at that moment. Perhaps his description property then becomes:

          description [;
              print "The grumpy old man ";
              switch(self.grumpiness) {
                  0:  "smiles bashfully.";
                  1:  "stares back without emotion.";
                  2:  "frowns in your direction.";
                  3:  "glowers at you ferociously.";
                  4:  "seems incandescent with rage.";
                  default: "stands silently in the corner.";
              } ],

In this example, the new grumpiness property contains a decimal value 0, 1, 2... etc. You can, however, assign other types of data to your property, as we explain next. Furthermore, you can assign more than one value to a property, thus turning it into an array. The syntax is exactly the same, except that you supply several values rather than just one. The familiar name property works just like this; here's another example, showing an alternative way of handling the grumpiness descriptions (though it would be sensible to include a check that grumpiness lay in the range 0..5):

More information in the DM:
§3.5

          description [; print_ret "The grumpy old man ",
                  (string) self.&grumpydesc-->(self.grumpiness);
              ],
          grumpydesc "smiles bashfully." "stares back without emotion."
              "frowns in your direction." "glowers at you ferociously."
              "seems incandescent with rage." "stands silently in the corner.",

How do I use my new object property?

You talk about it in the same way as the standard properties pre-defined by the library: that is, you'd refer to the previous topic's grumpiness property as self.grumpiness within the old_man object, or as old_man.grumpiness from within any other object. It's simple, consistent, and very powerful.

As for how you use your new property, that depends on what you store in it -- a true/false flag, a number, an object's address, a string or a routine (or an array of any of those, but we'll concentrate here on the basics). For example, you might create a flammable property, controlling what happens to an object when you set fire to it, as any of these formats:

More information in the DM:
§3.9

Property definition

Reference to the property

What's the outcome?

flammable,

X = self.flammable;

X contains zero.

flammable 20,

X = self.flammable;

X contains 20.

flammable obj_name,

X = self.flammable;

X contains the address of the obj_name.

flammable "string",

X = self.flammable;

X contains the address of the string.

X = self.flammable();

the string is printed; X contains true.

flammable [;
    statement;
    statement;
    ...
    ],

X = self.flammable;

X contains the address of the routine.

X = self.flammable();

the routine is executed; X contains its return value.

The really interesting -- and rather surprising -- information in that table relates to the self.flammable() format. Read the table again: you'll see that the same format does something useful both when the property value is a routine (which you'd expect), or a string (which you certainly wouldn't expect). This is a great feature (and is discussed in more detail later)!

It's often useful, especially when creating your own object classes, to construct properties which can be either a string or a routine. The library has several of these: article, cant_go, description, each_turn, initial, inside_description, plural, when_XXX and all of the direction properties. They're handy because they cater both for the simple case -- when you always want to display the same information -- and for more complex requirements where what you print depends on the object state, or the time of day, or some other factor.

Suppose that you've got an object, such as a flashlight, which can be pointed at other objects. Most objects don't react, but a few do... those that have a when_lit property, which could be a routine or string. You can choose one of three techniques.

Technique

For example

Commentary

Testing the property type yourself

if (otherObject.when_lit ofclass Routine)
    otherObject.when_lit();
else
    print (string) otherObject.when_lit;

Not recommended -- it's too easy to make a mistake.

Using a library routine

PrintOrRun(otherObject, when_lit);

PrintOrRun(otherObject, when_lit, true);

Simpler and more reliable.
In the first example a newline is automatically added after a printed string; in the second example this is suppressed.

Letting the system handle it automatically

otherObject.when_lit();

otherObject.when_lit(p1,p2, ...);

Simplest of all.
A newline is always added after a printed string.
In the second example, the parameters are available to the when_lit routine.

To help clarify what's happening, here's some actual code:

  Object  -> "flashlight"
    with  name 'flashlight',
          before [;
            PointAt:
              if (self has light && second provides when_lit) return second.when_lit();
          ],
          after [;
            SwitchOn:  give self light;
            SwitchOff: give self ~light;
          ],
    has   switchable ~on ~light;

  Object  -> "owl"
    with  name 'owl',
          when_lit "The owl blinks in mild surprise.",
    has   animate;

  Object  -> "mouse"
    with  name 'mouse',
          when_lit [;
              remove self;
              "The startled mouse disappears into the undergrowth.";
          ],
    has   animate;

  [ PointAtSub; "Pointless."; ];

  Verb 'aim' 'point'
      * held 'at'/'on'/'towards' noun -> PointAt;

  Extend only 'shine'
      * held 'at'/'on'/'towards' noun -> PointAt;

So, if you're coding a property whose value can be a routine or a string -- and, given it's so easy, why not? -- my advice is to invoke it with the obj.prop() syntax at all times unless you especially don't want that automatic newline afterwards, when you should instead use PrintOrRun(objprop, true).

Do I need to understand private properties?

More information in the DM:
§3.6

No. They offer no meaningful advantage over regular properties, and you can forget all about them.

How do I define a new object attribute?

Unlike properties, you can't define an attribute which applies only to one object, or to a class of objects. Inform's attributes are globally-defined, and are always associated with all objects in the game. You would create a new attribute by saying, near the start of the game, something like:

More information in the DM:
§3.7

  Attribute large;

and then including:

    has   large;

in the definition of objects which were, for example, too bulky to be pushed through a crack, or hidden in a rabbit hole, or whatever your game demanded.

There's an Inform limit of 48 attributes in total, and the Library already defines 31 of them. This, too, isn't actually much of a restriction, because it's quite rare to need new attributes; most of the time, you can do the job better using individual properties, as we explain next.

How can I use individual properties as attributes?

Attributes are variables which may have only two states: they're either present, or they're absent. These variables -- usually called 'flags' in programming jargon (the flag is either 'up' or 'down', meaning: set or clear, on or off, true or false, yes or no...) -- become really useful when you want to work with binary states: is the chest open, or closed? Has the banana been peeled, or not? etc.

More information in the DM:
§3.7

The use of attributes is very easy and straightforward. As we have seen in the previous topic, you can create a new attribute with the directive:

  Attribute peeled;

And then you can check whether an object has the attribute set (or not set) with:

  if (banana has peeled) ...
  if (banana hasnt peeled) ...

You can set the attribute with:

  give banana peeled;

and clear it with:

  give banana ~peeled;

Inform, however, has a limited stock of attributes; you can create only about 17 additional customised flags. Moreover, once you define an attribute, you do it for all the objects in the game; by default, the new attribute is not set for any of the objects, but nevertheless it feels a bit awkward to have the possibility of, for example, a peeled television set.

Individual properties are variables which may hold much more than just two states, so they can function as flags with room to spare. An individual property is defined within one object and it affects only that object: if you have a banana and an orange, you'll have to define a peeled property for each (or maybe create a Fruit class -- see below -- from which they both inherit such a property). The syntax is a little bit more complex, but hardly a nuisance. To define a new individual property to act as flag, simply write:

More information in the DM:
§3.5 §3.13

  Object  banana "banana" fruitbowl
    with  name 'banana',
          peeled false,
          ...

Now you can test if the banana has been peeled (or not) with:

  if (banana.peeled == true) ...
  if (banana.peeled == false) ...

and change the state of the banana with:

  banana.peeled = true;
  banana.peeled = false;

Note the use of '==' to test the value of the property, and '=' to assign the value of the property.

If these tests or changes are made from within the banana object, we recommend the use of self instead of banana:

  self.peeled = true;
  if (self.peeled == false) ...

So what's so hot about this slightly more verbose method for flags? Three main reasons.

To illustrate this last point (admittedly, we're not talking about simple flags any more), suppose that you want to create a set of 'flaming torch' objects which can be unlit, alight or burnt-out (and therefore useless). One way is to define two new attributes:

  Attribute usable;
  Attribute burning;

and you could then test an object's state by:

  if (myObject has usable && myObject hasnt burning) ...                ! It's unlit
  if (myObject has usable && myObject has burning) ...                  ! It's lit
  if (myObject hasnt usable) ...                                        ! It's burnt-out

But that's a clumsy approach; a better way is to use a single torch_state property:

  if (myObject provides torch_state && myObject.torch_state == 0) ...   ! It's unlit
  if (myObject provides torch_state && myObject.torch_state == 1) ...   ! It's lit
  if (myObject provides torch_state && myObject.torch_state == 2) ...   ! It's burnt-out

Note that we're testing whether myObject provides torch_state; this is unnecessary if we know that myObject is a torch and therefore will definitely have a torch_state property, but essential if myObject might be an ordinary object which didn't have such a property as part of its definition. Note also that the 'attribute' method doesn't enable you to deduce reliably whether any given object is in fact a torch or not, whereas with the 'local property' method it's easy:

  if (myObject provides torch_state) ...                                ! It's a torch of some sort

An even better way, incidentally, would be to define a Class of torch objects (more about Classes in the next topic):

  Class  Torch
    with torch_state;

  Torch  myObject
         ...

  if (myObject ofclass Torch) ...                                       ! It's a torch of some sort
  if (myObject ofclass Torch && myObject.torch_state == 1) ...          ! It's lit

In general, we advise you to define new attributes only where they will apply to a considerable number of objects in your game. When the same state settings apply to only one or two objects, the use of local properties is just as easy, and a lot more powerful.

If your game needs a lot of flags to control the state of play and you really can't afford the memory consumed by making each one a Global variable or an individual property, you might be interested in the newflags.h library contribution, Fredrik Ramsberg's revision of Adam Cadre's flags.h. (But if you do, be sure to define some meaningful constant names, for example

  Constant FED_RACCOON = 0;      ! Has Beauford eaten the corn and fed
                                 ! the raccoon in the proper order?
  Constant BOOKED_PLANE = 1;     ! Has Hildegard booked her plane tickets
                                 ! with the correct credit card?
  ...
  Constant WEASEL_IN_PANTS = 53; ! Is the weasel hiding in the pantaloons?

rather than using raw numbers in your code.)

What does class inheritance do for me?

Defining your own classes, so that you can create objects which are instances of those classes, is an easy and yet powerful technique. Whenever you find yourself defining two or more objects which have some common characteristics, ask yourself whether they could possibly belong to the same class. The most obvious example is a class used for rooms. Almost every time that you add a new location to your game, youíll want it to have light. So you can readily create a basic template:

More information in the DM:
§3.8

  Class    Room
    with  description "A bare and featureless room.",
    has   light;

and then take that as the starting point for your new room objects:

  Room    hallway "Dingy hall"
    with  description "Steps lead down into darkness.",
          d_to cellar;

  Room    cellar "Cellar"
    with  description "Once the home of vintage wine; now only spiders remain."
          u_to hallway,
    has   ~light;

For more information on objects, classes and the use of properties and attributes, see Roger Firth's InFancy pages

Using classes like this makes a game easier to write and easier to read, so it's worth mastering the technique early on.

There's no reason why an object can't be a member of two classes. For example, here's a class whose only purpose is to be tested against by the "snow" object:

  Class   Snowy;

  Object  "snow"
    with  name 'snow' 'drift' 'drifts',
          article "some",
          description "Pure white billowy drifts.",
          found_in [; return(location ofclass Snowy); ],
          before [; Take: "It's too fine and powdery."; ];

Given those definitions, you can conjure up the start of an icy landscape:

  Room    northpole "The North Pole"
    class Snowy
    with  description "Windy, and white, and very very cold.",
          ...

When is a Dynamic class useful?

A class definition is a good way of handling similar objects, and an excellent way of dealing with identical objects. For example, this is all that's needed to put some eggs into a nest:

More information in the DM:
§29

  Object  -> "nest"
    with  name 'nest'
    has   container open;

  Class   Egg
    with  short_name "egg",
          plural "eggs",
          name 'egg' 'eggs//p',
          description "Speckled blue and green.";

  Egg     -> ->;
  Egg     -> ->;
  Egg     -> ->;

The game reports this as "You can see a nest (in which are three eggs) here". The "three eggs" are grouped because they're 'indistinguishable' -- they provide a plural property, and their name properties are the same.

Usually, this technique is all you need -- there are three eggs at the start and hopefully still three at the end -- but just occasionally you'll come across a situation where similar objects appear and disappear during the course of a game. If you find yourself needing to create identical objects as the game progresses, you might consider using a Dynamic class. We'll illustrate this by blowing bubbles (you'll have to imagine the wire loop and the soap solution). Here's a basic class:

  Class   Bubble(10)
    with  short_name "bubble",
          plural "bubbles",
          name 'bubble' 'bubbles//p',
          description "The bubble floats gently in the air.";

That's hardly any different from the definition of the Egg class, is it? Just the (10) after the class name, which you should read as specifying that "no more than ten bubbles can exist at any one time". What has changed is the way that the bubbles are brought into existence. We'll conjure them up by enabling the player to type BLOW BUBBLE, using this extension of the library's standard BLOW verb:

More information in the DM:
§3.11

  [ BlowBubbleSub obj;
      obj = Bubble.create();
      if (obj == nothing)
          "Sorry, you've run out of bubbles.";
      move obj to location;
      "You carefully blow a bubble.";
  ];

  Extend 'blow' first
  	* 'bubble'/'bubbles'    -> BlowBubble;

The statement obj = Bubble.create(); does the trick. Sending a create message to a Dynamic class definition brings a new object of that class into existence, and returns the number used to identify the object. The object is created in limbo -- without a parent -- so you'll usually need to move it into play; move obj to location; does that, and finally, you tell the player what's happened. If instead Bubble.create() returns nothing then the object couldn't be created (because you've already blown all of the specified 10), apologise to the player, and give up.

So far so good, but we can make a few improvements to our code. First, we simplify BlowBubbleSub() by making the newly-created object responsible for its own initialisation. We do this by adding a create property to the class:

  Class   Bubble(10)
    with  short_name "bubble",
          plural "bubbles",
          name 'bubble' 'bubbles//p',
          description "The bubble floats gently in the air.",
          create [;
              move self to location;
              "You carefully blow a bubble.";
          ];

  [ BlowBubbleSub;
      if (Bubble.create() == nothing)
          "You've run out of bubbles.";
  ];

The use of Bubble.create() tells the Bubble class to create a new Bubble object; the library contains all the code to do that. Then, the library calls the create property of the new object -- if it provides one -- to enable the object to set itself up: here, by moving itself to the current location and announcing its own birth.

The bubbles that we're creating here aren't very realistic, since they can be taken and dropped like solid objects. Let's make them burst if touched...

  Class   Bubble(10)
    with  short_name "bubble",
          plural "bubbles",
          name 'bubble' 'bubbles//p',
          description "The bubble floats gently in the air.",
          create [;
              move self to location;
              "You carefully blow a bubble.";
          ],
          before [;
            Attack,Cut,Push,PushDir,Rub,Squeeze,Take,Taste,Tie,Touch,Turn,Wave:
              Bubble.destroy(self);
              "With a gentle 'pop', the bubble bursts.";
          ];

...or if deliberatly popped...

  [ BurstSub;
      "You can't burst that!";
  ];

  Verb 'burst' 'deflate' 'pop' 'prick' 'puncture'
      * multi                 -> Burst;

...or of their own accord after a few turns:

  Class   Bubble(10)
    with  short_name "bubble",
          plural "bubbles",
          name 'bubble' 'bubbles//p',
          description "The bubble floats gently in the air.",
          create [;
              StartTimer(self, random(5));
              move self to location;
              "You carefully blow a bubble.";
          ],
          before [ player_gone;
            Attack,Burst,Cut,Push,PushDir,Rub,Squeeze,Take,Taste,Tie,Touch,Turn,Wave:
              StopTimer(self);
              player_gone = (self notin location);
              Bubble.destroy(self);
              if (player_gone) rtrue;
              "With a gentle 'pop', the bubble bursts.";
          ],
          time_left 0,
          time_out [; <<Burst self>>; ];

  [ BlowBubbleSub;
      if (Bubble.create() == nothing)
          "You pause for a moment to get your breath back.";
  ];

Note how we handle the destruction of a burst bubble. Rather than just moving it out of sight by remove self, we use Bubble.destroy(self) which has the effect making the destroyed object re-usable by a subsequent call to Bubble.create(). We suppress the message about the bubble bursting if the player is no longer in the room. Once we've got ten bubbles in the air at the same time and so can't blow any more, we have only to wait until one of them bursts... and we can blow another one. We therefore change the message from BlowBubbleSub() to suggest that the ban on creation is a temporary limitation.

One final flourish: we'll stop the bubbles being indistinguishable by giving them some size and colour characteristics, chosen at random.

  Class   Bubble(10)
    with  short_name [;
              print (address) self.&name-->0, " ", (address) self.&name-->1, " bubble";
              rtrue;
          ],
          name '.size' '.colour' 'bubble' 'bubbles//p',
          description [; print_ret (The) self, " floats gently in the air."; ],
          create [;
              self.&name-->0 = random('tiny','small','regular','large','enormous');
              self.&name-->1 = random('red','green','blue');
              PronounNotice(self);
              move self to location;
              StartTimer(self, random(5));
              "You carefully blow ", (a) self, ".";
          ],
          before [ player_gone s c;
            Attack,Burst,Cut,Push,PushDir,Rub,Squeeze,Take,Taste,Tie,Touch,Turn,Wave:
              StopTimer(self);
              player_gone = (self notin location);
              s = self.&name-->0; c = self.&name-->1;
              Bubble.destroy(self);
              self.&name-->0 = s; self.&name-->1 = c;
              if (player_gone) rtrue;
              "With a gentle 'pop', ", (the) self, " bursts.";
          ],
          time_left 0,
          time_out [; <<Burst self>>; ];

Several changes here. We've reserved two entries at the start of the name property to hold a pair of adjectives representing the bubble's size and colour; we write appropriate random values into these entries at the start of the create property. The short_name property uses the two adjectives to compose the object's name (for example, "tiny red bubble"). The various messages use print rules like "(The) self" in order to display that composite name. We've added PronounNotice(self) so that BLOW BUBBLE THEN BURST IT works as you'd imagine it should. And, somewhat obscurely, we remember the bubble's size and colour just before we destroy it, and reinstate them afterwards. Huh?

A bit of inside information may be helpful here. The declaration Class Bubble(10) ... ; actually compiles 11 identical bubble objects, and makes them all children of the Bubble class (which is also an object). The Bubble.create() call doesn't do much more than make one of the first ten of those child objects available to the game, and the Bubble.destroy() call just returns the 'destroyed' object to the pool of children. The eleventh object is never made available; it's there to provide a template so that, when an object is destroyed, its property values can be reset to their default state. Which means that the randomised size and colour values are lost, and you may see "You can't see 'it' (the .size .colour bubble) at the moment". That's why we reinstate the size and colour values after destroying a bubble. All of which means that our bubbles now behave something like this:

  >BLOW BUBBLE
  You carefully blow a small blue bubble.

  >BLOW BUBBLE
  You carefully blow a large red bubble.

  >EXAMINE IT
  The large red bubble floats gently in the air.

  >BURST IT
  With a gentle 'pop', the large red bubble bursts.

  >EXAMINE IT
  You can't see "it" (the large red bubble) at the moment.

  >LOOK
  ...
  You can see a small blue bubble here.

There's one other thing you should know. You might imagine that a statement like objectloop (o ofclass Bubble) ... would loop through your 'created' bubbles. Wrong: it loops through all 11 of the compiled bubbles. The statement you want is probably objectloop (o ofclass Bubble && o notin Bubble) ...

How can I reconfigure the Player Character (PC)?

In Parserm.h, the Library defines a standard object selfobj which represents the human person who is playing your game, and a variable player which normally contains the address of selfobj. The INVENTORY command lists the objects which are the children of player, while EXAMINE ME invokes its description property. By default, that outputs "As good-looking as ever.", but you may well wish to change it; here are a couple of methods. The standard selfobj looks rather like this:

More information in the DM:
§21

  Object  selfobj "(self object)"
    with  short_name  [; return L__M(##Miscellany, 18); ],
          description [; return L__M(##Miscellany, 19); ],
          ...
    has   animate concealed proper transparent;

So, one way to change the descriptive text is to define a LibraryMessages object to intercept Miscellany message 19:

More information in the DM:
§25

  Include "Parser";

  Object  LibraryMessages
    with  before [;
              Miscellany:
                  if (lm_n == 19) "Not much change since you last looked.";
              ];

  Include "VerbLib";

However, it's easier just to change the description property itself. For example, you could add this line to your Initialise() routine:

  [ Initialise;
          player.description = "Not much change since you last looked.";
          ...
          ];

or this one, referencing the address of a suitable property routine:

  [ PlayerDesc;
          if (children(self) == 0) "Forlorn and empty-handed.";
          "Your possessions don't inspire much confidence.";
          ];

  [ Initialise;
          player.description = PlayerDesc;
          ...
          ];

Or, yet another possibility, you could supply your own player object, a modified version of the one in Parserm.h:

  Object  mySelfobj "(self object)"
    with  short_name  [; return L__M(##Miscellany, 18); ],
          description [;
              if (children(self) == 0) "Forlorn and empty-handed.";
              "Your possessions don't inspire much confidence.";
              ],
          ...
    has   animate concealed proper transparent;

  [ Initialise;
          player = mySelfobj;
          ...
          ];

More information in the DM:
§A3

In the Initialise() routine, it's safe to assign object addresses directly to the location and player variables. Everywhere else, you should use the Library routines PlayerTo() and ChangePlayer() respectively.

Why does my game crash when I use move in an objectloop?

More information in the DM:
§3.4

Usually, it doesn't nowadays, because many errors are caught by Strict checking. However, you need to be aware of the special-case handling of objectloop. If you use one of the three special forms (especially #1; the others are rarely seen), then your loop runs a lot faster, because the number of objects being tested is much smaller. However, this optimisation is achieved by using the sibling() function to navigate the linked object tree, rather than simply iterating through all of the defined objects. And if you move or remove an object in the middle of an optimised loop, you'll screw up the linkage, and the results will be... interesting.

objectloop formats

 

Generated code is equivalent to:

Standard

  objectloop (condition) {
      statement;
      statement;
      ...
  }
  for (all objects in game) if (condition) {
      statement;
      statement;
      ...
  }

Special case #1

The direct children
(but not grandchildren)
of object

  objectloop (i in object) {  
      statement;
      statement;
      ...
  }
  for (i = child(object) : i : i = sibling(i)) {  
      statement;
      statement;
      ...
  }

Special case #2 (rare)

The children of object's
parent (including object
itself)

  objectloop (i near object) {  
      statement;
      statement;
      ...
  }
  for (i = child(parent(object)) : i : i = sibling(i)) {  
      statement;
      statement;
      ...
  }

Special case #3 (rare)

object and its
younger siblings

  objectloop (i from object) {  
      statement;
      statement;
      ...
  }
  for (i = object : i : i = sibling(i)) {  
      statement;
      statement;
      ...
  }

Using move and remove in 'standard' objectloops is fine. Also, the (i in object) form is 'special' only in that exact form -- if you add another condition like (i in object && i has attribute) or (i && i in object), it becomes safely 'standard'. Note: you can't add extra conditions to the other two special forms, which is probably why they're not often encountered.

Can I loop through all of an object's dependents?

You'll see from the previous topic that objectloop (i in object) selects the direct children of object, but not any other dependent objects -- grandchildren, great-grandchildren and so on -- lower down the hierarchy. Since that's quite a useful thing to be able to do, we'll discuss some ways that you can go about it. First of all, for reasons that will hopefully become clear in a minute, we'll encapsulate the actual processing in a separate routine: this simple example merely displays the name of each object as we loop through it:

  [ ProcessObject obj;
      print (name) obj, "^";
  ];

With that in place, here are three alternative definitions of a routine which applies ProcessObject() to all of the dependents of a specified parent object par:

  [ R1 par   o;
      objectloop (o ~= par && IndirectlyContains(par, o))
          ProcessObject(o);
  ];

  [ R2 par   o;
      for (o=child(par) : o : ) {
          ProcessObject(o);
          if (child(o)) o = child(o);
          else
              while (o) {
                  if (sibling(o)) { o = sibling(o); break; }
                  o = parent(o);
                  if (o == par) return;
              }
      }
  ];

  [ R3 par   o;
      objectloop (o in par) {
          ProcessObject(o);
          if (child(o)) R3(o);
      }
  ];

The R1() example is the easiest to write and understand: unfortunately it's also hopelessly inefficient because of the amount of unnecessary testing that it performs. The much better R2() example calls the low-level child(), sibling() and parent() functions to move directly between the various dependents of par. And R3() is a nice compromise: it uses recursion -- that is, it calls itself -- to navigate through par's dependents, which makes it appear simpler than it actually is.

So far, so good: you could use our little ProcessObject() routine with any of R1(player), R2(player) or R3(player) to print a list of the player's possessions. Or in fact, not so good, because ProcessObject() is being called for all of par's dependents, even if they're not visible to the outside world. For example, if the player is carrying a locked box, then you quite possibly want to bypass any objects in that box, rather than call ProcessObject() for each of them. This is quite tricky to do using the R1() technique, but is very straightforward for R2() and R3(). First of all, we extend ProcessObject() so that it returns true if its contents, if any, are also to be processed, or false if any contents are to be skipped. Here's one test that you might find useful:

  [ ProcessObject obj;
      print (name) obj, "^";
      if ((obj has supporter or transparent) ||
          (obj has container && obj has open)) rtrue;
      rfalse;
  ];

And these are revised versions of R2() and R3() which test the value returned by ProcessObject() and act accordingly:

  [ R2 par   o;
      for (o=child(par) : o : ) {
          if (ProcessObject(o) && child(o)) o = child(o);
          else
              while (o) {
                  if (sibling(o)) { o = sibling(o); break; }
                  o = parent(o);
                  if (o == par) return;
              }
      }
  ];

  [ R3 par   o;
      objectloop (o in par)
          if (ProcessObject(o) && child(o)) R3(o);
  ];

Into
the Intro

Setting
the scene

Preparing
to program

Learning
the lingo

Dabbling
in data

Operating
on objects

Verbal
versatility

Bothered
by bugs

History and
hereafter

Worldly
woes

Inside
information

Tips and
techniques