
+-----------------------------------------------------------------------------+
|                 Plain text of the Inform Designer's Manual                  |
+-----------------------------------------------------------------------------+




 This plain text version was generated automatically from the TeX
 source, and is an approximate version of the typeset version.  In case
 of garbled passages, consult that edition!



+-----------------------------------------------------------------------------+
|                                 Introduction                                |
+-----------------------------------------------------------------------------+




     I will build myself a copper tower
     With four ways out and no way in
     But mine the glory, mine the power...
     
         - Louis MacNeice (1907-1963),  Flight of the Heart



Inform is an Adventure-game compiler, and this is the book to read about it.

Infocom format 'story files' (Adventure games, that is) can be played on
almost any computer, ancient or modern, and interpreters which run them are
widely available, from personal organisers to mainframes.  They represent
probably the most portable form in which games can ever be written, as no
alteration whatever is required to move a game from one model of computer to
another.

Inform is not just a compiler but an 'operating system' too: its library (a
suite of standard game routines) allows designers to begin coding at once. 
An Inform source file need not contain any of the parser code, or the
running of the 'game universe', only descriptions and exceptions to the
usual rules.  This world is quite rich already, having over 80 verbs and an
extensive grammar: the library understands rooms, objects, duplicates,
containers, doors, things on top of other things, light, scoring, switching
things on and off, opening, closing and locking things, entering things,
travelling about in them and so forth.  The parser it uses (which can be
entirely invisible to the designer, but is programmable and very flexible)
is sophisticated enough to handle ambiguities, clarify its input by asking
questions and to cope properly with plurals, vagueness, conversation,
pronouns and the player becoming someone else in mid-game.

This manual makes occasional reference to the example games provided with
Inform, at present 'Advent' (a full version of the original mainframe
Adventure, which contains a good deal of 'everyday Inform'), 'Toyshop'
(a collection of unusual objects to play with) and 'Balances' (a short story
consisting of puzzles making great use of the parser's flexibility).  Try
to get hold of these programs and preferably print them out.  There is also
a 'Shell' game consisting of the minimum code to get going, but all 14
lines of it are given in section 1 anyway.





The text of this book has evolved from five earlier editions.  The old
manual was in places rather technical, with a makeshift and sometimes
defensive tone ('Inform is an easel, not a painting').  There were
specifications of the run-time code format and literary critiques of games
gone by: like an oven manual padded out with both a cookery book and a
detailed plan of the gas mains.  This book contains just the instructions
for the oven.

So there are three 'companion volumes'.   The Craft of Adventure is
an essay on the design of adventure games;   The Specification of the
Z-Machine covers the run-time format and Inform assembly language, its
lowest level; and  The Inform Technical Manual documents chiefly
internals, for compiler maintenance and porting.

In trying to be both a tutorial and reference work in a budget of about
100 pages of A4, this book aims itself in style halfway
between the two extremes of manual, Tedium and Gnawfinger's ''Elements of
Batch Processing in COBOL-66'', third edition, and Mr Blobby's ''Blobby Book
of Computer Fun''.  (This makes some sections both leaden  and
patronising.)  I have tried to make every passage tell the truth, so that
even early sections are reliable for reference purposes.  Passages which
divert the main story, usually to tell the unexpurgated truth when this may
just confuse the newcomer, are marked with a warning triangle $**$ or
two, and set in smaller type.  Lengthy examples are left as exercises, with
answers in the Appendix; which also contains a language specification, some
reference lists, definitions of attributes and properties, and a large index.





The copyright on Inform, the program and its source code, its example games
and documentation (including this book) is retained by Graham Nelson, who
asserts the moral right to be identified as its author.  Having said this, I
am happy for it to be freely distributed to anybody who wants a copy,
provided that: (a) distributed copies are not substantially different from
those archived by the author, (b) this and other copyright messages are
always retained in full, and (c) no profit is involved.  However, a story
file produced with the Inform compiler (and libraries) then belongs to its
author, and may be sold for profit if desired, provided that its game banner
contains the information that it was compiled by Inform, and the Inform
version number.

At present, the best source for Inform material (executables of the compiler
for different machines, source code, the library files and example games) is
the anonymous ftp site ftp.gmd.de, and its home directory is:

     if-archive/infocom/compilers/inform
     

Some of the ideas of Inform came from an incremental multi-player
game called Tera, on the Cambridge University mainframe, written by
Dilip Sequeira and the author in 1990 (whose compiler was called Teraform);
in turn, this stole a little from David Seal and Jonathan Thackray's
game assembler; which dates back to the late 1970s and was written for
'Acheton', perhaps the first worthwhile game written outside America.
Still, much of the Inform kernel derives ultimately from the  IEEE Computer
article ''Zork: A Computerized Fantasy Simulation Game'' by P. David Lebling,
Marc S. Blank and Timothy A. Anderson; and more was suggested by
Richard Tucker, among others.

With the advent of Inform 5 in mid-1994, I feel that the underlying language
came to a satisfactory state.  The library files, however, may well go on
being improved, since users can update these much more easily than the
compiler (changes to which mean work for many people).  The present
library files (release 5/4) are greatly enhanced from the Inform 5.2 files,
but compatible with them (except in handling plural nouns and that the
obselete attribute autosearch has been withdrawn).

The list of those who have helped the project along is legion: I should like
to thank them all, porters, users and critics alike, but especially Volker
Blasius, Paul David Doherty, Mark Howell, Bob Newell, Robert Pelak, Gareth
Rees, Joe rund Rian, Dilip Sequeira, Richard Tucker and Christopher Wichura.

One final word.  I should like to dedicate this book, impertinently perhaps,
to our illustrious predecessors: Willie Crowther, Don Woods and
the authors of Infocom, Inc.



                                                      Graham Nelson
                                                      Magdalen College, Oxford
                                                      September 1994








+-----------------------------------------------------------------------------+
|                             1  Getting started                              |
+-----------------------------------------------------------------------------+


The first thing to try is to compile the 'Hello Cruel World' game, a very
short test file supplied with Inform.  If that compiles and runs properly
(producing a short page of text, then finishing), try the following:

     Constant Story "SHELL";
     Constant Headline "^An Interactive Skeleton^\
                  Copyright (c) 1994 by (your name here).^";
     
     Include "Parser";
     Include "VerbLib";
     
     Object Blank_Room "Blank Room"
       with description "An empty room."
       has  light;
     
     [ Initialise;
       location=Blank_Room;
       "^^^^^Welcome to the shell...^^";
     ];
     
     Include "Grammar";
     end;
     
If this compiles, Inform is probably set up and working properly. It takes a
short while to compile, because it 'includes' three large standard files,
containing a large amount of code.  (Include lines are also sometimes
written #include to make C programmers feel more at home.)  The library
files are:




      Parser        The core of the game, and a full parser
      VerbLib       Routines for many game verbs, like ''take''
      Grammar       A grammar table to decode the player's input from



Together, they make up the 'library'.  They can certainly be modified by
designers, but great effort has gone into making sure the need hardly ever
arises.

 Apart from that, the code contains:

 (a)    strings giving the name of the game, and a copyright message, to be
printed out at the appropriate moments;

 (b)    a routine, called Initialise, which is run when the game begins,
and simply sets where the player starts (in the obvious place!) and prints a
welcoming message;

 (c)    an object, to be the only room of the game.

 The 'Shell' game is very boring: there is nothing for the player
to do but wait and quit.




In Inform, everything is an object: rooms and things to be picked up,
scenery, intangible things like mist and even some abstract ideas (like
the direction 'north').  More about this later: for now, here's a new
object, to go under the Blank_Room definition:

     Nearby cone "green cone"
       with name "green" "cone";
     
(Nearby just means it's an object inside the last thing declared as an
Object, in this case the Blank Room.)  A green cone now appears in the
Blank Room.  The player can call it either ''green cone", ''cone" or even
''green".  It can be taken, dropped, looked at, looked under and so on.

This is still rather plain.  Examining the cone sees ''nothing special about
the green cone", for instance.  So we might extend the definition by:

     Nearby cone "green cone"
       with name "green" "cone" "emerald",
            initial "Nearby is an emerald green cone, one foot high.";
     
The initial message now appears when we arrive in the Empty Room.  Taking
things a little further...

     Nearby cone "green cone"
       with name "green" "cone" "emerald" "marzipan",
            initial "Nearby is an emerald green cone, one foot high.",
            description "The cone seems to be made of emerald-coloured \ 
                         marzipan."
       has  edible;
     
(Note that the description is split across two lines: the \
makes the message
come out as one sentence without a huge space.)  Now if we examine the
cone, we get its surprising description: and the player is allowed to
eat the cone.



  **   name, description and initial are examples of 'properties',
while edible is an 'attribute': the difference is that the former have
values, whereas the latter are just on or off.

So far, we're just filling in a form, and we could go much further
doing this, but that wouldn't be much of an example.  Instead, some
honest programming:

     Nearby cone "green cone"
       with name "green" "cone" "emerald" "marzipan",
            initial "Nearby is an emerald green cone, one foot high.",
            description "The cone seems to be made of emerald-coloured \ 
                         marzipan.",
            after
            [; Take: "Taken.  (Your hands are smeared with marzipan.)";
               Drop: "The cone drops to the floor and sags a little.";
            ],
       has  edible;
     
The property after doesn't just have a string for a value: it has a
routine of its own.  Now what happens is that when an action happens
to the cone, the after routine is called to apply any special rules
about the cone.  In this case, Take and Drop are the only actions
tampered with: and the only effect is that the usual messages
(''Taken.'' ''Dropped.'') are replaced.



  **   There's no real difference between routines like Initialise,
which are defined outside objects at the 'top level', and routines
inside objects like this after routine: except that outside routines
have to have names, since they aren't identified by belonging to
any particular object.

Still, the cone doesn't actually do anything!  So here it is with a
(completely unfair) puzzle added:

     Nearby cone "green cone"
       with name "green" "cone" "emerald" "marzipan",
            initial "Nearby is an emerald green cone, one foot high.",
            description "The cone seems to be made of emerald-coloured \ 
                         marzipan.",
            before
            [; Eat: if (random(100) <= 30)
                    {   deadflag = 1;
                        "Unfortunately, you seem to be allergic to almonds.";
                    }
                    "You nibble at a corner of the cone.";
            ],
            after
            [; Take: "Taken.  (Your hands are smeared with marzipan.)";
               Drop: "The cone drops to the floor and sags a little.";
            ],
       has  edible;
     
The before routine is called before the player's intended action takes
place.  So when the player tries typing, say, ''eat the cone", what happens
is: in 30% of cases, she dies of almond poisoning; and in the other 70%,
she simply nibbles a corner of the cone (without actually consuming it
completely).



  **   Like many programming languages, Inform braces together blocks of
code.  deadflag is a global variable, whose value does not belong to any
particular object (or routine).  It is defined somewhere in the depths of
the library: it's usually 0; setting it to 1 causes the game to be lost,
and setting it to 2 causes a win.

In either case, the usual rule for the Eat action is never applied.  This is
because, although it isn't obvious from the code, the routine actually
returns a value, true or false.  And the command

     "Unfortunately, you seem to be allergic to almonds.";
     
not only prints the message (together with a carriage return), but also
returns true from the before routine.  Since the routine normally returns
false, the library knows that something has happened to interrupt the usual
rules of the game.



Exercise:    Extend the green cone so that it is described as sagging after
it has been dropped back on the ground.  (You need a few more properties for
this.)



Answer:  
     Nearby cone "green cone"
       with name "green" "cone" "emerald" "marzipan",
            describe
            [; if (cone has moved)
                   "A misshapen cone of green marzipan sits here.";
               "Nearby is an emerald green cone, one foot high.";
            ],
            description "The cone seems to be made of emerald-coloured \ 
                         marzipan.",
            before
            [; Eat: if (random(100) <= 30)
                    {   deadflag = 1;
                        "Unfortunately, you seem to be allergic to almonds.";
                    }
                    "You nibble at a corner of the cone.";
            ],
            after
            [; Take: "Taken.  (Your hands are smeared with marzipan.)";
               Drop: cone.description = "The cone is a vague green mess.";
                     "The cone drops to the floor and sags a little.";
            ],
       has  edible;
     
The old initial message has gone.  Instead, we have provided a
describe routine.  Whenever the game has to describe the cone in the
description of a place, it will call this routine.  The moved attribute
is held only by an object which has at some time in the past been taken.  So
the cone is now perfect and untouched until taken and dropped, whereupon
it becomes misshapen.  Also, the act of dropping the cone now changes the
description which appears when a player examines it.



+-----------------------------------------------------------------------------+
|                         2  Ingredients and lexicon                          |
+-----------------------------------------------------------------------------+


Properly speaking, 'Inform' means the compiler and its language: whereas this
book is chiefly about the 'library' of code which comes with it.  For
most practical purposes this makes no difference - but it's worth remembering
that in the last resort you can change almost anything about how the library
works.

The basic ingredients of an Inform game are:

      Objects,     Routines,     Actions     and     Grammar.
     
We have already seen examples of Objects and Routines.  Actions happen in the
course of play.  The main loop of a game looks like this:




 1.   Ask the player to type something

 2.   Parse this (i.e. decide what it means) and generate any actions it
calls for

 3.   Work out the consequences of these actions and tell the player

 4.   Worry about time passing by, and other things happening



a process which ends only in victory or death.  (In this respect it is unlike
life.)

Probably the most complicated programming in any adventure game goes into the
parser.  Inform's parser is fairly advanced, and is designed with the intention
of being highly programmable at all levels to suit your game: so this manual
will be returning to features of the parser again and again.  It isn't perfect
by any means, but it does understand things like:

     throw three of the coins into the fountain
     write funny on the lighted cube
     take the sword and all the crowns
     what is a grue
     dwarf, give me the battleaxe
     
It also asks questions when it needs to, makes inferences from partial requests
and tries to make good guesses when faced with ambiguous requests.  You can
teach it new verbs and new forms of old ones: this is Grammar.  (The library
starts with about 85 verbs, not counting synonyms.)

Until you need to start programming it, the parser sits in the background, and
you need to know nothing about it.  But the parser is where Actions come from.
An Action can have up to two objects attached to it, and represents something
which the player is trying to do.  For instance,

     Inv        Take sword       Insert gold_coin cloth_bag
     
are all actions.  (By this stage the game has reduced them to three numbers
each, the action number and two object numbers: there's no text floating about.)



  **   Actions are also sometimes produced as a knock-on effect by other
actions, and they can also be produced by your own code: you can even create
new actions altogether, which are treated no differently from the standard ones.



Exercise:   Compile one of the supplied example games, say 'Toyshop', with
the DEBUG option defined (see the section on debugging) so that you can use
the special ''actions'' verb to see exactly what all the actions are as they
happen.



Answer:  You may be surprised how many actions take place: often more than one
per turn.







  **   Inform can produce two kinds of game: ''Standard'' and ''Advanced''.

Code is in almost every case portable between these two forms, so that you
can easily make a version each way from the same program.  The latter is
better, but just in case you have a small computer (such as a personal
organiser) or a very bad run-time interpreter, you might prefer the former.
Occasionally this manual will mention a difference between these forms.



  ** **   At this point, we should describe the imaginary machine, sometimes
called the Z-machine (Z is for 'Zork') which Inform compiles games for.
An 'interpreter' is a program which simulates this imaginary machine, so that
it can run the game files that Inform produces: the same files will work
on any interpreter on any machine.  Interpreters are available for very many
machines indeed.  The Z-machine is, except in a few corners, a beautiful
design and is described in great detail in the  Specification of the
Z-Machine.  For now, a few words about the memory map.  The memory of
this imaginary computer is 128K long for Standard games and 256K long for
advanced ones: the format is extremely well compressed, so this is actually
quite a large memory.



  ** **   Numbers are stored in 16-bit words (2 bytes long), and are signed
in the usual way, so they hold values
$$ -32768  <=  n <=  32767 $$
with the hexadecimal value $ffff being the same as $-1$.  The sign doesn't
mean anything for addresses, of course, but there's a catch: given that a
2-byte number can only hold a value $0 <=  n <=  65535$, how can an address
in a 128K or 256K memory map be held?  The answer is that there are two
kinds of address: a 'packed address' and a 'byte address'.  A byte address is
just an address in the bottom 64K of memory, and the Z-machine is arranged
so that everything which could ever change is there: so these are the only
addresses which matter very much.  Packed addresses are addresses divided
by 2 (or by 4 in Advanced games), so they can only refer to even (divisible
by four) locations in memory.  They hold the addresses of long strings and
routines, which Inform is careful always to put at even (divisible by four)
locations.








+-----------------------------------------------------------------------------+
|                    3  Objects, properties and attributes                    |
+-----------------------------------------------------------------------------+




     Objects make up the substance of the world.  That is why
     they cannot be composite.
     
         - Ludwig Wittgenstein (1889-1951),  Tractatus





     ...making philosophical sense of change runs up against what
     seem to be impossible philosophical difficulties.  Aristotle...
     focuses on the central case of an object coming to have a
     property that it formerly lacked.
     
         - Julia Annas,  Classical Greek Philosophy




The objects of the game form what is sometimes called a 'tree', though
a better analogy would be a forest, and anyway one usually draws the whole
thing upside down and uses the language of 'families' - calling them 'children'
and 'parents' of each other.  Anyway, here's an example:

    Meadow
      |
    Mailbox  ->  Player
      |            |
     Note        Sceptre   ->   Cucumber  ->   Torch  ->   Magic Rod
                                                 |
                                               Battery

This is a family tree, then: each object has a parent, a sibling and a child,
though that object may be the special nothing object.  (The Cucumber has
child nothing, for instance.)

As the game goes on, objects move around: when an object moves, all its
possessions (that is, children) go with it.  The Inform command to move an
object is

     move object to new-owner;
     
and it must be emphasized that this prints nothing on the screen, and indeed
does nothing except to change the tree above.

Inform provides special functions for reading this tree.

     parent,    sibling    and    child
     
all do the obvious things, and in addition there's a function called children
which counts up how many children an object has (only children: grandchildren
aren't counted).  For instance,

      parent ( Mailbox ) = Meadow
      children ( Player ) = 4
      child ( Sceptre ) = 0
      sibling ( Torch ) = Magic Rod
     


  **   nothing isn't really an object: it's just a convenient name for the
number 0, which is the object number meaning 'no such object'.  It isn't a good
idea to meddle with nothing, or to apply functions like parent to it,
but then there's never any need.



  ** **   When an object is added to the possessions held by another, it appears
at the end of the list.  Thus, the eldest child is first in the list and the
youngest is last.  Inform also provides functions


     youngest      end of list of possessions
     eldest        same as child
     younger       same as sibling, i.e. rightwards in the picture
     elder         reverse of sibling, i.e. leftwards in the picture


Objects have more to them than just where they are in the tree.  They
also have collections of variables attached to them.

Firstly, there are flags, called ''attributes'', which can be either set or
clear.  These might be such conditions as ''giving light", ''currently worn"
or ''is one of the featureless white cubes".  Attributes all have names,
which are a single word: like light, for instance, which indicates that
something is giving off light.  There are about 30 defined by the library.
They can be tested with a condition like

     if (obj has locked) "But it's locked!";
     
and can be set with the give command.  So, for instance,

     give brass_lantern light;
     give iron_door locked;
     
and they can be taken away with

     give brass_lantern ~light;
     give fake_coin ~scored;
     
the ~ sign (or tilde) standing for negation.  In fact you can give or take
many at one go, so for instance

     give wooden_door open openable ~locked;
     


  **   You can make your own attributes

with a directive like

     Attribute offered_to_ogre;
     
at the start of the program.  (A 'directive' is a command to Inform directly,
and happens at compile-time: not something in a routine which is to happen in
the course of play.)



  ** **   In Standard games there are few spare attributes available because
th library takes most of them.  To get around this limit
there's a convenient dodge.  It sometimes happens that an attribute is only
meaningful for a particular kind of object: for instance, ''spell has been
read" might only be meaningful for a ''scroll".  With care, therefore, one
may re-use the same attribute to have different meanings for different kinds
of object. The syntax to declare that an attribute is being reused is


     Attribute <new> alias <old>;
     
Thereafter Inform will treat the new and old attribute names as
referring to the same attribute: it's up to the programmer to make sure this
does not lead to inconsistencies.  (The library already indulges in a certain
amount of this chicanery.)




Secondly, there are ''properties''.  These are far more elaborate, and not
every object has every property.  For instance: not every object has the
door_to property (it holds the place a door leads to, so things other
than doors don't usually have it).  The current value of a property is
got at by constructions like:

     iron_door.door_to
     crystal_bridge.door_to
     green_cone.before
     diamond.initial
     
You can read the value of door_to for something like the diamond,
and you'll just get a dull value like nothing, but you can't write to it:
that is, you can't change diamond.door_to unless you declared a door_to
property for it.



  **   You can also define your own properties (again, subject to
availability, because the library claims many of them).

     Property door_to;
     Property article "a";
     Property blorple_routine $ffff;
     
are all examples of the Property directive.  In the case of article,
we are saying that the value "a" should be the default value for any
object which doesn't declare an article.



  ** **   Properties can also alias.  They can also be declared as
long or additive, which is a complicated matter: basically, we'll
come to additive when discussing classes, and properties which might
start as small numbers (less than 256) and be changed into large ones
in play, ought to be declared as long.

As will be seen from examples, a property value can be many things:
a string like "frog", a number such as $ffff (this is the Inform
way of writing numbers in hexadecimal), an object or a routine.  You
can change the current value by something like

     location.door_to = hall_of_mists;
     brass_lantern.short_name = "dimly lit brass lantern";
     grenade.time_left = 45;
     



  !!   The game may crash at run-time if you attempt to write to a property
field which an object hasn't got.  So although you can read an undeclared
property (you just get the default value), you can't write to one.
(Also, you can't extend a property beyond its length: see below.)



  **   The Inform language does not have types as such, and strings
and routines are stored as numbers: as their addresses inside the virtual
machine, in fact.  This means that Inform thinks

     "Hello there" + 45 + 'a'
     
is a perfectly sensible calculation.  It's up to you to be careful.




  ** **   A property can hold more than just one number (be it interpreted
as a string, a routine or whatever): it can hold a small array of numbers.
In Standard games it can have four numbers (8 bytes' worth), and in
Advanced games 32 (64 bytes).  For instance, an entry in an object
definition might read

      found_in  Marble_Hall  Arched_Passage  Stone_Stairs,
     
storing a sequence of three values (all objects) in the found_in

property.
To read or write to this array, you need to know its (byte) address and its
length.  The operators

     object.&property    and    object.#property
     
tell you these.  (Be warned: object.#property tells you the number of bytes,
not the number of words.)
If you give a property more than 8 bytes of data in a Standard game,
Inform warns you and takes only the first 8, but does not cause an
error: this is so that, say,

     Object ...
     with name "radio" "wireless" "transistor" "portable" "stereo" "tranny",
          ...
     
will compile either way (but the last two synonyms for "radio" will not
enter the dictionary if it's being compiled in Standard form, since a name
takes two bytes).




** ** Exercise:   Use the object.&property construction to find out whether
the object in variable obj has the door_to property defined or not.



Answer:  if (obj.&door_to == 0) { ... }





Time to make some object definitions.  A typical object definition looks
something like:

     Object trapdoor "hinged trapdoor" attic
       with name "hinged" "trap" "door" "trapdoor",
            when_open "A hinged trapdoor in the floor stands open, and light \
                       streams in from below.",
            when_closed "There is a closed trapdoor in the middle of the floor.",
            door_to house,
            door_dir d_to,
       has  door static open light openable;
     
This is the conventional way to lay out an Object declaration: with the
header first, then with a list of properties and their starting values,
finishing up with the attributes it initially has.

trapdoor is the name given to the object in the program, and it becomes
a constant from then on (whose value is the number of the object).  The
attic is the object which the trapdoor starts out belonging to (as
any player of 'Curses' will know).  Some objects start out not
belonging to anything (rooms, for example, or treasures which only appear
half-way through).  You can declare these as belonging to nothing, but
it's better just to miss this out altogether:

     Object trapdoor "hinged trapdoor"
       with ...
     
If you do declare an object already belonging to another, as above,
then the other object must already have been defined.  (This is no real
restriction, and ensures that you can't set up a 'loop' - one in another
in a third in the first, for instance.)

Objects can also be declared, in an identical way, by the Nearby directive.
The only difference is that no initial-owner object can be given; it starts
out belonging to the last thing declared as an Object.  For example, in

     Object hillside "Panoramic Hillside"
       with ...
     
     Nearby scenery "scenery"
       with ...
     
the hillside is a room to which the scenery will belong.  Otherwise,
Nearby is the same as Object, and this is just a convenience to make
it easier to move things around in Inform code by cutting definitions out
and pasting them in elsewhere.

Some properties of objects should be routines.  For instance,
an object can have a describe property which is a routine to print out
a description of it.

These could just be listed as names of routines, but usually the actual
routine is written out then and there as the property value.
For instance, in the classic Adventure object

     Nearby tasty_food "tasty food"
           with description "Sure looks yummy!",
                    initial "There is tasty food here.",
                name "food" "ration" "rations" "tripe"
                     "yummy" "tasty" "delicious" "scrumptious",
                after
                [; Eat: "Delicious!"; ],
                article "some"
           has  edible;
     
the after property does not name a routine but instead defines it.  No
name is needed or given for the routine.  (The semicolon after the [ is
needed to show that the routine has no local variables.)

The routine must end with either ], or ];.  If ], the object definition
can resume where it left off, with further properties.  (If it ends with
];, then the object definition ends where the routine finishes.)



  **   The rules for embedded routines are not quite the same as those
for ordimary routines.  By default, embedded routines return ''false", or 0
(instead of ''true", or 1, which other routines return by default).  Also,
the handy shorthand:

     Action [, Action2 ...] : ...some code...
     
is provided, which executes the code only if the action being considered
is the one named.



  ** **   It actually does this by setting a special variable called
sw__var

to the action number: when it compiles Action1: it just
compiles an if statement which sees whether sw__var has value Action1.



  **   Properly speaking, the full syntax of the header is

     Object <obj-name-1> <obj-name-2> ... <obj-name-$n$> "short name"
     [<parent-obj>]
      or    Nearby <obj-name-1> <obj-name-2> ... <obj-name-$n$>
     "short name"
      or    Class <class-name>
     
and the parent object must have already been defined.
A Class definition is very like an object definition, and will be discussed
later on.  The syntax for an object, then, is

     <Header> [,]
         class <class-1> <class-2> ... <class-$n$> [,]
         with  <property-name-1> <value-1> ... <value-$n$>,
                   <property-name-2> <value-1> ... <value-$n$>,
                   ...
                   <property-name-$n$> <value-1> ... <value-$n$> [,]
         has  <att-1> <att-2> ... <att-$n$>
     
Although it's conventional to write class, with and has in this order,
actually they can be in any order and any or all can be omitted altogether:
and the commas in square brackets [,] are optional in between these fields.
(The classes listed under class are those which the object inherits from.)



  **   One property is treated differently from the others, and this
is the special property name.  Its data must be a list of English words
in double-quotes, as in all the above examples.  (Probably the most
annoying restriction of Standard games is that this means only 4 names
at most can be accommodated in that format: you get up to 32 in Advanced
games.)  It will probably confuse the parser if any of these names is
something like "my", "the", "all", "except" or "this".  Numbers
can safely be used, however.



  ** **   In fact, name contains a list of byte addresses of dictionary
words.  A quick way to print out the first word in the name list is
therefore

     print_addr obj.name;
     



  ** **   The attributes <att-1> and so on can be taken away as well as
added, thus:

       ...
       has  light ~scored;
     
which is sometimes useful to over-ride an inheritance from a class definition.



  ** **   A final curiosity of the Object syntax is that objects can be given
more than one name.  This is a hangover from much earlier days of Inform,
to do with re-using the same physical object in different logical ways,
something which the author does not commend to anyone.


+-----------------------------------------------------------------------------+
|                       4  Places, scenery and the map                        |
+-----------------------------------------------------------------------------+




     It was a long cylinder of parchment, which he unrolled and spread out
     on the floor, putting a stone on one end and holding the other.
     I saw a drawing on it, but it made no sense.
     
         - John Christopher,  The White Mountains





     And if no piece of chronicle we prove,
     We'll build in sonnets pretty rooms;
     As well a well wrought urn becomes
     The greatest ashes, as half-acre tombs.
     
         - John Donne (1571?-1631),  The Canonization



Back to our example.  Throw away the old ''blank room" and replace it by...

     Object Square_Room "Square Room"
       with description
            "A broad, square room, ten yards on a side, floored \
            with black and white chequered tiles."
       has  light;
     

(We also have to change the Initialise routine to make this the place
where the player begins, since the Blank Room no longer exists.)

Like the blank room, this one has light.  (If it didn't, the player
would never see it, since it would be dark, and the player hasn't yet
been given a lamp or torch of some kind.)  So where is the light coming
from?

     Nearby chandelier "crystal chandelier"
       with name "crystal" "chandelier",
            initial "A crystal chandelier hangs from far above, casting \
                     light in little rainbows across the floor.",
            description "The crystal is beautiful cut-glass."
       has  static;
     

This is part of the fittings, hence the static attribute (which means it
can't be taken or moved).  But what about the rainbows?

     Nearby rainbows "rainbows"
       with name "rainbow" "rainbows",
            description "Caused by diffraction, or something like that - \
                         you were never very good at physics."
       has  scenery;
     

Being scenery makes the object not only static but also not described
by the game unless actually examined by the player.  A true perfectionist
might alter it to:

     Nearby rainbows "rainbows"
       with name "rainbow" "rainbows",
            description "Caused by diffraction, or something like that - \
                         you were never very good at physics.",
            before
            [; Take, Push, Pull, Turn: "But the rainbows are made of light.";
            ],
       has  scenery;
     
Let us now add a second room:

     Object Corridor "Sloping Corridor"
       with description
                "This corridor slopes upward and out of the square room.",
            d_to Square_Room, s_to Square_Room,
            u_to "The slope becomes impossibly steep, and you retreat.",
            cant_go "The corridor runs up and down."
       has  light;
     

and extend the Square Room to:

     Object Square_Room "Square Room"
       with description
               "A broad, square room, ten yards on a side, floored \
                with black and white chequered tiles.  A doorway in the \
                centre of the north side opens onto a rising corridor.",
            u_to Corridor,
            n_to Corridor
       has  light;
     
The player can now go from one to the other.  The properties u_to, d_to,
n_to (and so on) declare what lies in the
directions ''up", ''down", ''north"
(and so on).  If they aren't declared, one cannot go that way.  Notice that
they can be either a room or a message which is printed if the player tries
to go in the given direction.


In the Square Room, if the player tries to go, say, east, she gets a message
along the lines of ''You can't go that way.", which is not very helpful.  In
the Corridor, the cant_go

message is printed instead.  (In fact, as is often the case with properties,
instead of giving an actual message you can instead give a routine to print
one out, so that what is printed varies with circumstances.)

Map connections are all one-way, in themselves: they just happen to be
defined here so that they appear two-way.





Rooms also have rules of their own.  We might write:

     Object Corridor "Sloping Corridor"
       with description
               "This corridor slopes upward and out of the square room:  \
                the floor underfoot is a little sticky.",
            d_to Square_Room, s_to Square_Room,
            u_to "The slope becomes impossibly steep, and you retreat.",
            cant_go "The corridor runs up and down.",
            before
            [; Take: if (noun == cone)
                        "The cone seems to be stuck to the floor here.";
            ],
       has  light;
     
and now the cone (if dropped there) cannot be taken from the floor of
the Sloping Corridor.  The variables noun and second hold the first
and second nouns supplied with an action.  Rooms have before and after
routines just as objects do.



  ** **   Sometimes the room may be a different one after the action has
taken place.  The Go action, for instance, is offered to the before
routine of the room which is being left, and the after routine of the
room being arrived in.  For example:

            after
            [; Go: if (noun==in_obj)
                   print "How grateful you are to get out of the rain...^";
            ],
     
will print the message when the room is entered via the ''in" direction.
(Note that the message is printed with the print command.  This means
that it does not automatically return true: in fact, it returns false,
so the game knows that the usual rules still apply.  Also, no new-line
is printed automatically: but the ^ symbol means ''print a new-line",
so one is actually printed.)



  **   Directions (such as ''north") are objects called n_obj, s_obj
and so on: in this case, in_obj.  (They are not to be confused with the
property names n_to and so on.)  Moreover, you can change these
directions (as far as Inform is concerned, only things in the special
object compass can be directions).



** Exercise:   In the first millenium A.D., the Mayan peoples of the
Yucat'an Peninsula had 'world colours' white ( sac), red ( chac),
yellow ( kan) and black ( chikin) for what we call the compass
bearings north, east, south, west (for instance west is associated
with 'sunset', hence black, the colour of night). Implement this.



Answer:  Define four objects along the lines of:

     Object white_obj "white wall" compass
       with name "white" "sac" "wall", article "the", door_dir n_to
       has  direction scenery;
     
and add the following line to Initialise:

     remove n_obj; remove e_obj; remove w_obj; remove s_obj;
     
(We could even alias a new property white_to to be n_to, and then
enter map directions in the source code using Mayan property names.)
As a fine point of style, turquoise ( yax) is the world colour for
'here', so add a grammar line to make this cause a ''look'':

     Verb "turquoise" "yax" * -> Look;
     



** Exercise:   (Cf. 'Trinity'.)  How can the entire game map
be suddenly east-west reflected?



Answer:  
     [ SwapDirs o1 o2 x;
       x=o1.door_dir; o1.door_dir=o2.door_dir; o2.door_dir=x; ];
     [ ReflectWorld;
       SwapDirs(e_obj,w_obj); SwapDirs(ne_obj,nw_obj); SwapDirs(se_obj,sw_obj);
     ];
     



** ** Exercise:    Even when the map is reflected, there may be many
room descriptions referring to ''east'' and ''west'' by name.  Reflect
these too.



Answer:  This is a prime candidate for using variable strings
@nn, a topic properly covered in the  Inform Technical Manual,
but briefly: at the head of the source, define

     Lowstring east_str "east"; Lowstring west_str "west";
     
and then add two more routines to the game,

     [ NormalWorld; String 0 #east_str; String 1 #west_str; ];
     [ ReversedWorld; String 0 #west_str; String 1 #east_str; ];
     
where NormalWorld is called in Initialise or to go back to
normal, and ReversedWorld when the reflection happens.  Write
@00 in place of east in any double-quoted printable string,
and similarly @01 for west.  It will be printed as whichever
is currently set.  (Inform provides up to 32 such variable strings.)


+-----------------------------------------------------------------------------+
|                   5  Causing actions and making new ones                    |
+-----------------------------------------------------------------------------+




     Only the actions of the just
     Smell sweet and blossom in their dust.
     
         - James Shirley (1594-1666),  The Contention of Ajax and Ulysses




     ...a language obsessed with action, and with the joy of seeing
     action multiply from action, action marching relentlessly ahead
     and with yet more actions filing in from either side to fall into
     neat step at the rear, in a long straight rank of cause and
     effect, to what will be inevitable, the only possible end.
     
         - Donna Tartt,  The Secret History



One often wants to simulate the effect of a player typing something.
For instance, in the Pepper Room the air is full of pepper and every turn
the player sneezes and drops something at random.  If the code to do this simply
removes an object and puts it on the floor, then it might accidentally
provide a solution to a problem like ''the toffee apple sticks to your hands
so you can't drop it".

This can at least be coded like this:

     You sneeze convulsively, and lose your grip on the toffee apple...
     The toffee apple sticks to your hand!
     
which (though not ideal) is much better.  As an example, here is another
piece of scenery to clutter up the tiny map so far:

     Object low_mist "low mist"
       with name "low" "swirling" "mist", article "the",
            initial "A low mist swirls about your feet.",
            description "It carries the unmistakable odour of cinnamon.",
            found_in  Square_Room  Corridor,
            before
            [; Smell: <<Examine self>>;
            ],
       has  static;
     

This mist is found in both the Square Room and the Corridor: note that the
found_in property has a list of places as its value.



 
The player will find that smelling the mist produces the same message as
looking at it.  The command

     <<Examine self>>;
     
causes the game to behave exactly as if the player had typed ''examine the
mist" at the keyboard: that is, the Examine action happens, applied to
the low_mist object.  (self always means the object whose routine this
is.  In this case, it's really a bit pointless since

     <<Examine low_mist>>;
     
does just the same thing.)  After going through the business of examining
the mist, the routine then returns 'true', or 1 (in this case, so that the
normal rules for smelling something are stopped in their tracks).

If instead

     <Examine self>;
     
had been used, the same would have happened, but the routine would not have
been returned from.  So the mist would be examined; and then the routine for
Smell would resume, and since there's nothing more to it, it would return
false; whereupon the library's usual rules would make it say something like
''You smell nothing unusual.".

All actions can be written this way:

     <Look>;  <<ThrowAt cone chandelier>>;
     
will, for instance, look around, then behave as if the player had asked
to throw the cone at the chandelier, then return true.






  **   Internally, actions like Look, ThrowAt and Take are stored
as numbers, and the number associated with an action can be got at by
x = ##Take; for instance.  The variable action holds the current action number
and sometimes it's convenient to use this directly.  For instance, imagine
a mirror hung very far above the player.  Given:

     before
     [; if (action==##Examine) rfalse;
        "The mirror is too high up, out of reach.";
     ]
     

the player will only be able to examine the mirror, and nothing else.
This prevents the library from ever saying something like ''You push the
mirror but nothing happens.", which would be misleading.



  **  
An action corresponds to a routine somewhere which actually carries out
the looking, throwing at, taking and so forth.  (Well, in fact there are
also some special actions called ''fake actions" which don't correspond to
such routines, as we shall come to later.)  These have the same name as the
action with Sub (short for ''subroutine") on the end: so, TakeSub for
instance.



  **  
The actions implemented by the library are in three groups.  The useful ones
are in groups 2 and 3:

     1. Quit, Restart, Restore, Verify, Save, ScriptOn, ScriptOff, Pronouns,
        Score, Fullscore, LMode1, LMode2, LMode3, NotifyOn, NotifyOff;
       
     2. Inv, InvTall, InvWide, Take, Drop, Remove, PutOn, Insert, Transfer,
        Empty, Enter, Exit, GetOff, Go, GoIn, Look, Examine, Give, Show,
        Unlock, Lock, SwitchOn, SwitchOff, Open, Close, Disrobe, Wear, Eat;
     
     3. Yes, No, Burn, Pray, Wake, WakeOther [person],
        Kiss, Think, Smell, Listen, Taste, Touch, TouchThing, Dig,
        Cut, Jump [jump on the spot], JumpOver, Tie, Drink,
        Fill, Sorry, Strong [swear word], Mild [swear word], Attack, Swim,
        Swing [something], Blow, Rub, Set, WaveHands [ie, just "wave"],
        Wave [something], Pull, Push, PushDir [push something in a direction],
        Turn, Squeeze, LookUnder [look underneath something], Search,
        ThrowAt, Answer, Buy, Ask, Sing, Climb, Wait, Sleep
     
Of course, the player can type all manner of things to get these.  For
instance, ''take off shirt" and ''remove the shirt" both cause the Disrobe
action.  Your code can ignore this complication.



  ** **   Group 1 actions are called meta - they are outside the game proper,
and your code is unable to interfere with them.  (If you want a room where the
game can't be saved, as for instance 'Spellbreaker' cunningly does, you'll
have to tamper with SaveSub directly, using a Replaced routine.)

Although all actions call the before routines, not all of them bother to
check after routines.  For instance, since the built-in SmellSub routine
just says ''You smell nothing out of the ordinary", there would be no point
calling after routines - nothing, after all, has been done.  (These are
the group 3 actions above.)



  **   The ones which actually do something, and call after, are:

     Inv, Take, Drop, Remove, PutOn, Insert, Exit, Go, Look, Examine, Unlock,
     Lock, SwitchOn, SwitchOff, Open, Close, Disrobe, Wear, Eat, Search.
     


  ** **   Some other group 2 actions use these after routines indirectly
- if the player empties a sack out onto the floor, this is deemed to be
a sequence of Drop actions, for instance, and if a sack is emptied into
a packing case this is considered a multiple insertion.



  ** **   Search (the searching or looking-inside-something action) is a
slightly special case between groups 2 and 3.  It never actually does anything
beyond printing messages.  What happens is that if it would be sensible to
look inside the object (i.e. if it's an open or transparent container and
there is light), after is called beforehand.  In this way you can use
before to trap searching of random scenery, and after to alter rules
for listing contents of containers.




The library's actions are easily added to.  For instance, add the routine:

     [ BlorpleSub;
       "You speak the magic word ~Blorple~.  Nothing happens.";
     ];
     
(somewhere after the Initialise routine, say, to be tidy).  There is now
an action Blorple (though it doesn't do anything very interesting).  One
can use the command <Blorple>; to make it happen, and could change the
before routine of, say, the Corridor, to make Blorple do something
exciting in that one place.  In other words, Blorple is now an action just
like any other.

But the player can't yet type ''blorple" and get this response, because
although the action exists, it hasn't been written into the grammar of
the game.  The grammar is a large table (mostly written out in the Grammar
library file).  It can easily be added to, and in this case we simply add
the lines

     Verb "blorple"
                *                                -> Blorple;
     
immediately after the inclusion of the Grammar file.  (The spacing is
just a matter of convention.)  This is about as simple as grammar lines
come, and means that only the word ''blorple" can be used as a verb, and
it can't apply to any noun or nouns.  (Far more about grammar later.)




  **  
It is time to be more precise about the exact sequence of events.  Suppose
the player is in the Bedquilt Room, and types ''drop oyster".  Once it has
checked that this is a reasonable command, the normal rules can be
interrupted at eight different stages:

 1.    Call GamePreRoutine (if there is one).  If this returns true,
stop here.

 2.    Call the before of the player.  If this returns true, stop here.

 3.    Call the before of Bedquilt Room.  If this returns true, stop here.

 4.    Then the before of the oyster.  If this returns true, stop here.

 5.    Actually drop the object.

 6.    Call the after of the player. If this returns true, stop here.

 7.    Call the after of Bedquilt Room. If this returns true, stop here.

 8.    Then the after of the oyster. If this returns true, stop here.

 9.    Call GamePostRoutine (if there is one).  If this returns true,
stop here.

 10.    Print ''Dropped.''




  ** **  
GamePreRoutine and GamePostRoutine are examples of 'entry points', like
Initialise: routines you can provide to make global rule changes.  Their
use is a drastic measure to be avoided if possible.  The player's own
before and after will be discussed in section 11.




  ** **   ''Fake actions'' are just like real actions, except that they don't
occur in any game grammar, so they're never generated by the parser.  They're
a neat way to pass 'messages' from one object to another one.  Because they
aren't defined implicitly in the grammar, they have to be explicitly declared
before use, by the directive:

     Fake_Action <Action-name>
     



** ** Exercise:   How can you make a medicine bottle, which can be opened
in a variety of ways in the game, so that the opening-code only occurs in
the bottle definition?



Answer:  Declare a fake action called, say, OpenUp.  Then:

     Object medicine "guaranteed child-proof medicine bottle" cupboard
       with name "medicine" "bottle",
            description "~Antidote only: no preventative effect.~",
            before
            [;  Open, Unlock: "It's adult-proof too.";
                Openup: give self open ~locked; "The bottle cracks open!";
            ],
       has  container openable locked;
     
Any other code in the game can execute <OpenUp medicine> to crack open
the bottle.


+-----------------------------------------------------------------------------+
|                  6  Containers, supporters and sub-objects                  |
+-----------------------------------------------------------------------------+




     The concept of a surface is implemented as a special kind of containment.
     Objects which have surfaces on which other objects may sit are actually
     containers with an additional property of ''surfaceness".
     
         - P. David Lebling,  Zork and the Future



Objects can be inside or on top of one another.  An object which has the
container attribute can contain things, like a box: one which has
supporter can hold them up, like a table.  (An object can't have both at
once.)  It can hold up to 100 items, by default: this is set by the capacity
property.

However, one can only put things inside a container when it has open.
If it has openable, the player can open and close it at will.  (Unless
it also has locked.)

To complicate matters, some containers are transparent (so that the
player can see inside them even when they are closed) and some are not.



Exercise:   Make a glass box and a steel box, which behave differently
when the lamp is shut up inside them.



Answer:  
     Nearby glass_box "glass box with a lid"
       with name "glass" "box" "with" "lid"
       has  container transparent openable open;
     Nearby steel_box "steel box with a lid"
       with name "steel" "box" "with" "lid"
       has  container openable open;
     

Containers (and supporters) are able to react to things being put inside
them, or removed from them, by acting on the Receive and LetGo actions.



Exercise:   Make the following, rather acquisitive bag:

     >put fish in bag
     The bag wriggles hideously as it swallows the fish.
     >get fish
     The bag defiantly bites itself shut on your hand until you desist.
     



Answer:  

     Object bag "toothed bag" room
       with name "toothed" "bag",
            description "A capacious bag with a toothed mouth.",
            before
            [; LetGo: "The bag defiantly bites itself \
                       shut on your hand until you desist.";
               Close: "The bag resists all attempts to close it.";
            ],
            after
            [; Receive:
                      print "The bag wriggles hideously as it swallows ";
                      DefArt(inp1); ".";
            ],
       has  container open;
     



  **   LetGo and Receive are actually two of the fake actions:
they are the actions Insert and Remove looked at from the container's
point of view.

Objects which have locked cannot be opened, be they doors or containers
(or both).  But objects which have lockable can be locked or unlocked
with the appropriate key, which is declared in the with_key property.
(If it is undeclared, then no key will fit.)

As a final example of a container, this is a fairly typical locked
cupboard:

     Nearby cupboard "bolted cupboard"
       with name "bolted" "cupboard",
            describe
            [; if (self hasnt open)
                   "^A shut cupboard is bolted to one wall.";
               "^Bolted up on one wall is an open cupboard.";
            ],
            with_key key
       has  locked container openable lockable static;
     

Now suppose you want to make a portable television set which has four
different buttons on it.  Obviously when the television moves, its buttons
should move with it, and the sensible way to arrange this is to make the
four buttons possessions of the television object.

However, the television isn't a container, and the player can't normally
''see'' (that is, refer to) the possessions of an
object.  So how do we bring the buttons into the player's ''view'' without
making them removable, or allowing anyone to put extra things ''into''
the television?

This is what the transparent attribute is for: it is an extremely useful
device to allow the player to ''see'' (i.e. talk about) the contents of
an object.



Exercise:   Implement a television set with attached power button and
screen.



Answer:  
     Object television "portable television set" lounge
       with name "tv" "television" "set" "portable",
            before
            [;  SwitchOn: <<SwitchOn power_button>>;
                SwitchOff: <<SwitchOff power_button>>;
                Examine: <<Examine screen>>;
            ],
       has  transparent;
     Nearby power_button "power button"
       with name "power" "button" "switch",
            after
            [;  SwitchOn, SwitchOff: <<Examine screen>>;
            ],
       has  switchable;
     Nearby screen "television screen"
       with name "screen",
            before
            [;  Examine: if (power_button hasnt on) "The screen is black.";
                    "The screen writhes with a strange Japanese cartoon.";
            ];
     


+-----------------------------------------------------------------------------+
|                                  7  Doors                                   |
+-----------------------------------------------------------------------------+




     Standing in front of you to the north, however, is a door surpassing
     anything you could have imagined. For starters, its massive lock is
     wrapped in a dozen six-inch thick iron chains. In addition, a certain
     five-headed monster...
     
         - Marc Blank and P. David Lebling,  'Enchanter'




     O for doors to be open and an invite with gilded edges
     To dine with Lord Lobcock and Count Asthma.
     
         - W. H. Auden (1907-1973),  Song



A useful kind of object is a door.  This need not literally be a door:
it might be a rope-bridge or a ladder, for instance.  To set up a door:

 (a)    give the object the door attribute;

 (b)    set the door_to property to the destination;

 (c)    set the door_dir property to the direction which that would be,
such as n_to;

 (d)    make the room's map connection in that direction point to the
door itself.


 For example, here is a closed and locked door:

     Object In_Immense_N_S_Passage "Immense N/S Passage"
       with description "One end of an immense north/south passage.",
            s_to In_Giant_Room,
            n_to RustyDoor;
     Nearby RustyDoor "rusty door"
       with description "It's just a big iron door.",
            name "door" "hinge" "hinges" "massive" "rusty" "iron",
            when_closed
                "The way north is barred by a massive, rusty, iron door.",
            when_open
                "The way north leads through a massive, rusty, iron door.",
            door_to In_Cavern_With_Waterfall,
            door_dir n_to,
            with_key set_of_keys
       has  static door openable lockable locked;
     
(Note that the door is static - otherwise the player could pick it up and
walk away with it!)  The properties when_closed and when_open give
descriptions appropriate for the door in these two states.


Doors are rather one-way: they are only really present on one side.  If
a door needs to be accessible (openable and lockable from either side),
a neat trick is to make it present in both locations and to fix the
door_to and door_dir to the right way round for whichever side the player
is on.  Here, then, is a two-way door:

     Object Grate "steel grate"
       with name "grate" "lock" "gate" "grille" "metal"
                 "strong" "steel" "grating",
            description "It just looks like an ordinary grate \
                mounted in concrete.",
            with_key set_of_keys,
            door_dir
            [; if (location==Below_The_Grate) return u_to; return d_to; ],
            door_to
            [; if (location==Below_The_Grate) return Outside_Grate;
               return Below_The_Grate; ],
            describe
            [; if (self has open) "^The grate stands open.";
               if (self hasnt locked) "^The grate is unlocked but shut.";
               rtrue; ],
            found_in  Below_The_Grate  Outside_Grate
       has  static door openable lockable locked;
     
where Below_The_Grate has u_to set to Grate, and Outside_Grate has
d_to set to Grate.  The grate can now be opened, closed, entered and
locked from either above or below.



  **    At first sight, it isn't obvious why doors have the door_dir

property.  Why does a door need to know which way it faces?  The idea is
that if there's an open door in the south wall, a player can go through it
either by typing ''south'' or ''enter door".  So what the Enter action
does (provided the door is actually open) is to cause the Go action with
the given direction.



  **   This has one practical consequence: if you put before and after
routines on the Enter action for the Grate, they only apply to a player
typing ''enter grate" and not to one just typing ''down".  The way to trap
both at once is to write a routine for the d_to property of Outside_Grate.



+-----------------------------------------------------------------------------+
|                            8  Switchable objects                            |
+-----------------------------------------------------------------------------+




     In one corner there is a machine which is reminiscent of a clothes dryer.
     On its face is a switch which is labelled ''START". The switch does not
     appear to be manipulable by any human hand (unless the fingers are about
     1/16 by 1/4 inch)...
     
         - \sl Zork



Objects can also be switchable.  This means they can be turned off or
on, as if they had some kind of switch on them.  The object has the
attribute on if it's on.  For example:

     Object searchlight "Gotham City searchlight" skyscraper
       with name "search" "light" "template", article "the",
            description "It has some kind of template on it.",
            when_on "The old city searchlight shines out a bat against \
                     the feather-clouds of the darkening sky.",
            when_off "The old city searchlight, neglected but still \
                      functional, sits here."
       has  switchable static;
     
Here is a lamp which provides for batteries which will some day run down,
though the code to actually deplete these batteries (by decrementing time_left
every turn it's switched on) is omitted:

     Nearby brass_lantern "brass lantern"
       with name "lamp" "lantern" "shiny" "brass",
            when_off  "There is a shiny brass lamp nearby.",
            when_on   "Your lamp is here, gleaming brightly.",
            time_left 330,
            before
            [; Examine: print "It is a shiny brass lamp";
                     if (brass_lantern hasnt on)
                         ".  It is not currently lit.";
                     if (brass_lantern.time_left < 30)
                         ", glowing dimly.";
                     ", glowing brightly.";
               Burn: <<SwitchOn brass_lantern>>;
               Rub:  "Rubbing the electric lamp is not particularly \
                      rewarding.  Anyway, nothing exciting happens.";
               SwitchOn: if (brass_lantern.time_left <= 0)
                     "Unfortunately, the batteries seem to be dead.";
            ],
            after
            [; SwitchOn: give brass_lantern light;
               SwitchOff: give brass_lantern ~light;
            ],
       has  switchable;
     


+-----------------------------------------------------------------------------+
|                9  Things to enter, travel in and push around                |
+-----------------------------------------------------------------------------+




     ...the need to navigate a newly added river prompted the invention
     of vehicles (specifically, a boat).
     
         - P. David Lebling, Marc Blank and Timothy Anderson



Some objects in a game are enterable, which means that a player can
get inside them.  The idea of ''inside" here is that the player is only
half-in, as with a car or a psychiatrist's couch.  (If it's more like a
prison cell, then it should be a separate place.)  In practice one often
wants to make an enterable thing also a container, or, as in this
example, a supporter:

     Object chair "dentist's chair" surgery
       with name "dentists" "chair" "couch",
       has  enterable supporter;
     




All the classic games have vehicles (like boats, or fork lift trucks, or
hot air balloons) which the player can journey in, so Inform makes this
easy.  Here is a simple case:

     Object car "little red car" cave
       with name "little" "red" "car",
            longdesc "Large enough to sit inside.  Among the controls is a \
                      prominent on/off switch.  The numberplate is KAR 1.",
            initpos "The red car sits here, its engine still running.",
            closedpos "A little red car is parked here.",
            before
            [; Go: if (car has on) "Brmm!  Brmm!";
                   print "(The ignition is off at the moment.)^";
            ],
       has  switchable enterable static container open;
     
Actually, this demonstrates a special rule.  If a player is inside an
enterable object and tries to move, say ''north", the before routine
for the object is called with the action Go, and n_obj as the noun.
If it returns false, the game disallows the attempt to move (as usual).
If it returns true, then the vehicle and player move together via the
game's usual map.



  **   Because you might want to drive the car ''out'' of a garage,
the ''out'' verb does not make the player get out of the car.  Usually
the player has to type something like ''get out'' to make this happen,
though of course the rules can be changed.



Exercise:   Alter the car so that it won't go up or down stairs.



Answer:  Change the car's before to
         before
         [; Go: if (noun==d_obj or u_obj)
                {   print "(The car will never get over those stairs.)^";
                    rfalse;
                }
                if (car has on) "Brmm!  Brmm!";
                print "(The ignition is off at the moment.)^";
         ],
     



  **  
Objects like the car (if the hand brake is off) or, say, an antiquated
wireless on casters, are obviously too heavy to pick up but the player
should at least be able to push them from place to place.  When the
player tries to do this, the PushDir action is generated.  Now, if
the before routine returns false, the game will just say that the
player can't; and if it returns true, the game will do nothing at all,
guessing that the before routine has already printed something more
interesting.  So how does one actually tell Inform that the push
should be allowed?  The answer is that one has to do two things:
call the AllowPushDir() routine (a library routine), and then
return true.  So, for example,

     Nearby huge_ball "huge plaster-of-paris ball"
       with name "huge" "plaster" "ball",
            description "A good eight feet across, though fairly lightweight.",
            initial
                "A huge plaster-of-paris ball rests here, eight feet wide.",
            before
            [; PushDir: AllowPushDir(); rtrue;
               Take, Remove: "There's a lot of plaster in an eight-foot sphere.";
            ],
            after
            [; PushDir:
                   "The ball rattles about and is hard to stop once underway.";
            ],
       has  static;
     



+-----------------------------------------------------------------------------+
|                    10  Living creatures and conversation                    |
+-----------------------------------------------------------------------------+




     To know how to live is my trade and my art.
     
         - Michel de Montaigne (1533-1592),  Essays





     Everything that can be said can be said clearly.
     
         - Ludwig Wittgenstein (1889-1951),  Tractatus



This rummage through special kinds of objects finishes up with the most
sophisticated kind: living ones.
Animate objects (such as sea monsters, mad aunts or nasty little dwarves)
have a property called life, containing their rules.  This behaves just
like a before or after routine, but only the following actions apply:



 Attack
       The player is making hostile advances...



 Kiss
       ...or excessively friendly ones.



 ThrowAt
       The player asked to throw noun at the creature.



 Give
       The player asked to give noun to the creature...



 Show
       ...or just to show it.



 Ask
       The player asked the creature about something: noun holds the
word.



 Answer
       The player tried either of:

     ''answer <word> to troll"
     ''troll, <something not understood>"
     
In either case the variable
special_word

is set to the dictionary entry of the first word, or
0 if it isn't in the dictionary, and special_number

is set to an attempt to read it as a number.  (For instance,
''computer, 143" will cause special_number to be set to 143.)



 Order
       On the other hand, an Order happens when the parser does understand
what the player wants the creature to do: e.g., ''troll, go south".
action, noun and second are set up
as usual: in this case action=##Go and noun=s_obj, while second=0.





If the routine doesn't exist, or returns false, events will take their
usual course.  Here is a full example:

     Object snake "sullen snake" mists
       with name "sullen" "snake",
            description "Perhaps a boa constrictor.  Perhaps not.",
            life
            [; Order:   if (action==##Go)
                            "The snake wasn't born yesterday.";
               Attack:  "Lazily, the snake dodges your attack.";
               Kiss:    "What a repulsive idea.";
               ThrowAt: print "Effortlessly, the snake dodges ";
                        DefArt(inp1); ".";
               Answer, Show:  "The snake disdains to comment.";
               Ask:     if (noun == 'mists')
                            "~Healthy and good for the skin, mists.~";
                        "~I'm only the obligatory monster.~";
               Give:    if (noun has edible)
                        {   remove noun;
                            "~Mmm!  Thanks!  I still hate you, though.~";
                        }
                        "~Bleurghh!  Are you trying to poison me?~";
            ],
       has  animate;
     
Of course an animate still has before and after routines like any
other, so you can trap many other kinds of behaviour.  (The library
understands that, for example, an animate creature cannot be taken.)



  **   DefArt is a routine which prints the short name of an object
along with its definite article, usually ''the".

Sometimes creatures should be transparent, sometimes not.  Consider these
two cases of animate characters, for instance:

    (o)       an urchin with something bulging inside his jacket pocket;

    (o)       a hacker who has a bunch of keys hanging off his belt.


The hacker is transparent, the urchin not.  That way the parser prevents
the player from referring to whatever the urchin is hiding (even if the
player has played the game before, and knows what is in there and what it's
called).  But the player can look at and be tantalised by the hacker's
keys.



  **   Another way to trap some of these actions (those which do not
involve conversation, i.e. other than Order, Answer or Ask) is to
use before in the ordinary way.  This lets you change rules about, say,
giving things to people in particular places.  The ThrowAt action is
also an ordinary one (for coconut shies, greenhouse windows and the like)
but is given to life as well because most creatures react to it, and
it's a convenience to have all the rules for a creature in one place.



  **   A footnote about Order: this is another ''fake action".

The before and after routines of a room can't detect the player having
given a request to another character.  Also, if you want the snake to
obey when the player tells it to take something, you have to write the code
to do the actual taking yourself.  This isn't any problem in practice.  (Try
looking at the code for Christopher in the ''Toyshop" example game.)



+-----------------------------------------------------------------------------+
|            11  Starting, moving, changing and killing the player            |
+-----------------------------------------------------------------------------+




     There are only three events in a man's life; birth, life and death;
     he is not conscious of being born, he dies in pain and he forgets
     to live.
     
         - Jean de la Bruy\'ere (1645-1696)




     That is the road we all have to take - over
     the Bridge of Sighs into eternity.
     
         - S\o ren Kierkegaard (1813-1855)




The player normally begins in the room which location is set to, and
setting location is the only absolute obligation on a game's Initialise
routine.  (The room may be initially dark if you so choose, or rather
if you provide no light source.)  In fact location could be set to a
chair or bed just as easily if the player is to start seated or lying
down.
If you would like to give the player some items to begin with, Initialise
should also move them to player.




To move the player about (for teleportation of some kind), two things
must be done: to move the player object, by

     move player to newroom;
     
and also to change the location variable, which says which room to
display on the status line:

     location = newroom;
     
The cleanest way to move the player is call PlayerTo(place); which also
sorts out things like only printing the new room's description if there's
enough light there to see by.



  **  
In general location can be different from parent(player) in two ways:
it can be ''Darkness" (that is, the special object thedark, which behaves
somewhat like a room), or it can be the actual room while parent(player)
is something the player sits inside, like (say) a jeep.



  **   Calling PlayerTo(place, 1); will move the player without printing
anything, and in particular without printing any room description.




The player's whole persona can easily be changed, by setting

     player.before = #r$MyNewRule;
     
where MyNewRule is a new before rule to be applied to every action of
the player's (or similarly for an after rule).  For instance, if a cannon
goes right next to the player, a period of deafness might ensue, and this
rule could stop the Listen action from taking its normal course.



  **   In fact a much more powerful trick is available: the player can
actually become a different character in the game, allowing the real player
at the keyboard to act through someone else.
Calling ChangePlayer(obj) will transform the player to obj.  There's
no need for obj to have names like ''me'' or ''myself''; the
parser understands these words automatically to refer to the
currently-inhabited player object.  However, it must provide a number
property (which the library will use for workspace).  The maximum number
of items the player can carry as that object will be its capacity.  Finally,
since ChangePlayer prints nothing, you may want to conclude with a <<Look>>;

 ChangePlayer has many possible applications.  The player
who tampers with Dr Frankenstein's brain transference machine may
suddenly become the Monster strapped to the table.  A player who drinks
too much wine could become a 'drunk player object' to whom many different
rules apply.  The ''snavig'' spell of 'Spellbreaker', which transforms
the player to an animal like the one cast upon, could be implemented thus.
More ambitiously, a game could have a stock of half a dozen main characters,
and the focus of play can switch between them.  A player might have a team
of four adventurers to explore a dungeon, and be able to switch the one
being controlled by typing the name.  (In this case, an AfterLife routine
-- see below -- may be needed to switch the focus back to a still-living
member of the team after one has met a sticky end.)




** Exercise:   In Central American legend, a sorceror can transform himself
into a  nagual, a familiar such as a spider-monkey; indeed, each
individual has an animal self or  wayhel, living in a volcanic land
over which the king, as a jaguar, rules.  Turn the player into his
 wayhel.



Answer:  The common man's  wayhel was a lowly mouse.  Since we think
much more highly of the player:

     Object hog "Warthog" Caldera
       with name "wart" "hog" "warthog", description "Muddy and grunting.",
            number 0,
            initial "A warthog snuffles and grunts about in the ash.",
            before
            [; if (player==self && action~=##Go or ##Look or ##Examine)
                   "Warthogs can't do anything as tricky as that!";
            ],
       has  animate proper;
     
and we just ChangePlayer(warthog);.  Note that this before rule is
carefully written only to affect actions of the player-as-warthog.
If the player-as-human should find and try to ''take warthog'', this
before routine won't interfere.



  **   Calling ChangePlayer(object,1); will do the same but make the
game print ''(as Whoever)'' during room descriptions.




The player is still alive for as long as the variable deadflag is zero.
When set to 1, the player dies; when set to 2, the player wins; and all higher
values are taken as more exotic forms of death.  Now Inform does not know
what to call these exotica: so if they should arise, it calls the
DeathMessage routine, which is expected to look at deadflag and
can then print something like ''You have changed''.

Many games allow reincarnation (or, as David M. Baggett points out, in
fact resurrection).  You too can allow this, by providing an AfterLife.
This routine gets the chance to do as it pleases before any ''You are
dead'' type message appears, including resetting deadflag back to 0 -
which causes the game to proceed in the normal way, rather than end.
AfterLife routines can be tricky to write, though, because the game
has to be set to a state which convincingly reflects what has happened.
(For instance, try collapsing the bridge in 'Advent' by leading the
bear across it, then being reincarnated and returning to the scene.)



+-----------------------------------------------------------------------------+
|                      12  Printing out names of objects                      |
+-----------------------------------------------------------------------------+




     And we were angry and poor and happy,
     And proud of seeing our names in print.
     
         - G. K. Chesterton (1874-1936),  A Song of Defeat



Inform has a special form of print command for this, print object, but
 do not use it.  Instead, call one of the following library routines:


     DefArt(obj)                      Print the object with its definite article
     CDefArt(obj)                     The same, but capitalised
     InDefArt(obj)                    Print the object with indefinite article
     PrintShortName(obj)              Print the object's short name alone





The indefinite article for an object is held in the property article
and is assumed to be 'a' if none is declared.  That means that if the
short name starts with a vowel, you need to set it to 'an'.  But article
offers much more amusement:

     a platinum bar, an orange balloon, your Aunt Jemima,
     some bundles of reeds, far too many marbles
     
are all examples of articles.

Definite articles are always ''the'' unless an object is given the
attribute proper, which makes it a proper noun and so not take a
definite article at all.  Thus

     the platinum bar, Aunt Jemima, Elbereth
     
are all printed by DefArt, the latter two being proper.

As we shall later see, changing the short name is easy.



** Exercise:   Why does

     print CDefArt(obj), " falls to the floor.^";
     
seem to work, but mysteriously print the number 1 after the name of the
object?



Answer:  Because CDefArt(obj) is a function call which, as it happens,
returns the value true, or 1 (not that this signifies anything), and
print thinks it is printing out a number.



  ** **   The reason print object is unsafe is that it prints the real,
''hardware and unchangeable'' short name, whereas we want everything to
work nicely when the user changes the short name of an object in play:
so the library routines almost all indirect through PrintShortName
(except in two cases to do with ChangePlayer, since the current
player's short name is always ''yourself'').


+-----------------------------------------------------------------------------+
|                           13  Classes of objects                            |
+-----------------------------------------------------------------------------+


In most games there are groups of objects with certain rules in common.
As well as individual objects, Inform allows one to define
classes in almost exactly the same way.  The only
difference between the layout of a class and object definition is that
a class has no short name or initial location (since it does not correspond
to a single real item).  For example:

      Class Treasure
       with depositpoints 10,
            after
            [; Take: if (location==Inside_Building)
                          score=score-self.depositpoints;
                     score=score+5;
                     "Taken!";
               Drop: score=score-5;
                     if (location==Inside_Building)
                     {   score=score+self.depositpoints;
                         "Safely deposited.";
                     }               
            ],
       has  valuable;
     
An object of this class inherits the properties and attributes it defines:
in this case, an object of class Treasure picks up the given score and
rules automatically.  So

     Nearby bars_of_silver "bars of silver"
      class Treasure
       with description "They're probably worth a fortune!",
            initial "There are bars of silver here!",
            article "some",
            name "silver" "bars";
     
inherits the depositpoints value of 10 and the rules about taking
and dropping.  If the silver bars had themselves set depositpoints
to 15, say, then the value would be 15: i.e., the class would be
over-ridden.



  **   depositpoints isn't a library property: it's one defined in the
game this example is drawn from, the 'Advent' example game.

We could also, for instance, have:

     Nearby cake "valuable cake"
      class Treasure
       with description "Exquisite!",
            initial "There's a valuable cake here!",
            after
            [; Eat: "Your most expensive meal in ages, but worth it.";
            ],
            name "valuable" "cake"
       has  edible;
     
Now the cake has two after rules.  Both apply, but the rule in the cake
itself takes precedence, i.e., happens first.



  **   
An object can inherit from several classes at once.  Moreover, a class can
itself inherit from other classes, so one can easily make a class for
''like Treasure but with only 8 depositpoints''.



  ** **  
The class field of an object definition contains a list of classes,

     class $C_1$ ... $C_n$
     
in which case the object inherits first from $C_1$, then from $C_2$
and so on.  $C_2$ over-rides $C_1$ and so on along the line.  These
classes may well disagree with each other, so the order matters.  If $C_1$
says depositpoints is 5, $C_3$ says it is 10 but the object
definition itself says 15 then the answer is 15.



  ** **  
With some properties, the value is not replaced but added to: this
is what happened with after above.  These
properties are those which were declared as additive, e.g. by

     Property additive before $ffff;
     
For instance, the standard Inform properties name and before are
both additive.  So we could add name "treasure", to the properties
in the class definition for Treasure, and then all objects of that
class would respond to the word ''treasure'', as well as their own
particular names.



+-----------------------------------------------------------------------------+
|                     14  Daemons and the passing of time                     |
+-----------------------------------------------------------------------------+




     Some, such as Sleep and Love, were never human.  From this
     class an individual daemon is allotted to each human being
     as his 'witness and guardian' through life.
     
         - C. S. Lewis (1898-1963),  The Discarded Image




     Some daemon stole my pen (forgive th' offence)
     And once betrayed me into common sense.
     
         - Alexander Pope (1688-1744),  The Dunciad



By tradition, a daemon is an event which happens each turn while it
is 'active'.  The classic example is of a dwarf which appears in the
cave: it has a daemon routine attached for moving about, throwing
knives at the player and other pleasantries.

Each object can have a daemon of its own.  This is set going, and stopped
again, by calling the (library) routines

     StartDaemon(the-object);
     StopDaemon(the-object);
     
Once active, the daemon property of the object is called as a routine
each turn.  Daemons are often started by a game's Initialise routine,
and active throughout.



  **   Be warned: this continues to happen even if the daemon is
associated with a room or item which has been left behind by the player.
Actually this is very useful, as it means daemons can be used for
'tidying-up operations', or for the consequences of the player's actions
to catch up with him.

Daemons often run a fair amount of code.  (There are plenty of good
examples in 'Toyshop' and 'Advent'.)  They shouldn't be ridiculously
slow if they will run more than once.  And some daemons so sit in
the background for enormously long times: for instance, the daemon in
''Advent'' which hides until the player has managed to get all the
treasures, then pounces.  Such daemons ought to
check their condition and return as quickly as possible if it fails.



Exercise:    Many games contain 'wandering monsters', characters who walk
around the map (usually hand-coded and not moving far abroad).  Use a daemon
to implement one who wanders as freely as the player, like the
thief in 'Zork I'.



Answer:  This is a crude implementation, for brevity (the real Zork I
thief has an enormous stock of attached messages).

     Object thief "thief" Danger_Zone
       with name "thief",
            each_turn "^The thief growls menacingly.",
            daemon
            [ i p j n k;
                if (random(3)~=1) rfalse;
                p=parent(thief);
                objectloop (i in compass)
                {   j=p.(i.door_dir);
                    if (j>player && j<=top_object && j hasnt door) n++;
                }
                if (n==0) rfalse;
                k=random(n); n=0;
                objectloop (i in compass)
                {   j=p.(i.door_dir);
                    if (j>player && j<=top_object && j hasnt door) n++;
                    if (n==k)
                    {   move self to j;
                        if (p==location) "^The thief stalks away!";
                        if (j==location) "^The thief stalks in!";
                        rfalse;
                    }
                }
            ];
     
This thief walks at random and cannot pass through doors, bridges and the like
(because these may be locked or have rules attached); it's only a first
approximation, and in a good game one should occasionally see the thief do
something surprising, such as open a secret door.



Exercise:  
Use a background daemon to implement a system of weights, so
that the player can only carry a certain weight before her strength gives
out and she is obliged to drop something.  It should allow for feathers to
be lighter than lawn-mowers.



Answer:  First define a new property for object weight:

     Property weight 10;
     
(10 being an average sort of weight).  Containers weigh more when
they hold things, so we will need:

     [ WeightOf obj t i;
        t = obj.weight;
        objectloop (i in obj) t=t+WeightOf(i);
        return t;
     ];
     
Now for the daemon which monitors the player's fatigue:

     Object weigher "weigher"
       with number 500,
            time_left 5,
            daemon
            [ w s b bw;
                 w=WeightOf(player)-100-player.weight;
                 s=self.number; s=s-w; if (s<0) s=0; if (s>500) s=500;
                 self.number = s;
                 if (s==0)
                 {   bw=-1;
                     objectloop(b in player)
                         if (WeightOf(b)>bw) { bw=WeightOf(b); w=b; }
                     print "^Exhausted with carrying so much, you decide \
                         to discard "; DefArt(w); print ": "; <<Drop w>>;
                 }
                 w=s/100; if (w==self.time_left) rfalse;
                 if (w==3) print "^You are feeling a little tired.^";
                 if (w==2) print "^You possessions are weighing you down.^";
                 if (w==1) print "^Carrying so much weight is wearing you out.^";
                 self.time_left = w;
            ];
     
Notice that items are actually dropped with Drop actions: one of them
might be, say, a wild boar, which would bolt away into the forest when
released.  The daemon tries to drop the heaviest item.  (Obviously a little
improvement would be needed if the game contained, say, an un-droppable
but very heavy ball and chain.)  Now the daemon is going to run every turn
forever, but needs to be started: so put StartDaemon(weigher); into the
game's Initialise routine.




A ''timer" (these are traditionally called ''fuses" but the author can stand
only so much tradition) can alternatively be attached to an object.
(An object can't have both a timer and a daemon going at the same time.)
A timer is started with

     StartTimer(the-object, time);
     
in which case it will ''go off" (alarm clock-style) in the given number of
turns.  This means that its time_out

property will be called (as a routine), once and once only, when the time comes.

It can be deactivated (so that it will never go off) by calling

     StopTimer(the-object);
     

A timer is  required to provide a time_left property, to hold the
amount of time left.  If it doesn't, the library will print an error message
at run-time.  You can alter time_left yourself, but setting it to 0 does
not stop the timer: use the routine StopTimer for that.



  **   In early releases of the library, a daemon needed a time_left
as well, which was illogical and a nuisance: anyway, it's no longer the case.



  **   Normally, you can only have 32 timers or daemons active at the same
time as each other (there may be any number of inactive ones).  But this
limit is easily raised: just define the constant MAX_TIMERS

to some larger value, putting the definition in your code before the
Parser file is included.




There is yet a third form of timed event.  If a room provides an each_turn
routine, then this will be called in each turn when the player is in it;
if an object provides each_turn, this is called whenever the object is
nearby.  For instance, a radio might blare out music
whenever it is nearby; a sword might glow whenever monsters are nearby;
or a stream running through several forest locations might occasionally
float objects by.

'Each turn' is entirely separate from daemons and timers.  Although an object
can't have both a timer and a daemon at the same time, it can have an each_turn
at the same time, and this is quite useful, especially to run creatures.
An ogre with limited patience can therefore have an each_turn routine
which worries the player (''The ogre stamps his feet angrily!'', etc.)
while also having a timer set to go off when his patience runs out.



  **    'Nearby' actually means 'in scope', a term which will be properly
explained later.  The idea is based on line of sight, which works well
in most cases.



  ** **    But it does mean that the radio will be inaudible when shut up
inside most containers - which is arguably fair enough - yet audible when
shut up inside transparent, say glass, ones.  You can always change the
scope rules using an InScope routine to get around this.  In case you
want to tell whether scope is being worked out for ordinary parsing reasons
or instead for each_turn processing, look at the et_flag variable
(0 in the former case, 1 in the latter).  Powerful effects are available
this way - you could put the radio in scope within all nearby rooms so as
to allow sound to travel.  Or you could make a thief audible throughout
the maze he is wandering around in, as in 'Zork I'.






The library also has the (limited) ability to keep track of time of day
as the game goes on.

If you're writing a game with the time instead of the score and turns on the
status line, you can set the time by

     SetTime( 60$\times$<hours>$+$<minutes>, rate );
     
The current time is held in the variable the_time

and runs on a 24-hour clock.  The rate controls how rapidly time is moving:
a rate of 0 means it is standing still (that is, that the library doesn't
change it: your routines still can).  A positive rate means that that many
minutes pass between each turn; and negative rate means that many turns
pass between each minute.

The time still won't appear on the game's status line unless you set

     Statusline time;
     
as a directive somewhere in your code.  And remember to start off the clock
by calling SetTime in your Initialise routine, if you're going to use
it.



Exercise:    How could you make your game take notice of the time passing
midnight, so that the day of the week could be nudged on?
                                                         


Answer:  Either set a daemon to watch for the_time suddenly dropping, or
put such a watch in the game's TimePasses routine.




  **    Exactly what happens at the end of each turn is:

 1.    The turns counter is incremented.

 2.    The 24-clock is moved on.

 3.    Daemons and timers are run (in no guaranteed order).

 4.    each_turn takes place for the current room, and then for
everything nearby (that is, in scope).

 5.    The game's global TimePasses() routine is called.

 6.    Light is re-considered (it may have changed as a result
of events since this time last turn).


The sequence is abandoned if at any stage the player
dies or wins.



** Exercise:    Suppose the player is magically suspended in mid-air,
but that anything let go of will fall out of sight.  The natural way
to code this is to use a daemon which gets rid of anything it finds
on the floor (this is better than just trapping Drop actions because
objects might end up on the floor in many different ways).  Why is
using each_turn better?



Answer:  Because you don't know what order daemons will run in.  A
'fatigue' daemon which makes the player drop something might come
after the 'mid-air' daemon has run for this turn.  Whereas each_turn
happens after daemons and timers have run their course, and can fairly
assume no further movements will take place this
turn.



Exercise:   How would a game work if it involved a month-long
archaeological dig, where anything from days to minutes pass between
successive game turns?



Answer:  It would have to provide its own code to keep track of time,
and it can do this by providing a TimePasses() routine.  Providing
''time'' or even ''date'' verbs to tell the player would also be a
good idea.


+-----------------------------------------------------------------------------+
|                 15  Adding verbs and grammar to the parser                  |
+-----------------------------------------------------------------------------+




     Grammar, which can govern even kings.
     
         - Moli\'ere (1622-1673),  Les Femmes savantes




     Language disguises thought... The tacit conventions on which
     the understanding of everyday language depends are enormously
     complicated.
     
         - Ludwig Wittgenstein,  Tractatus



The next few sections will delve deep into the parser.  Inform goes to
a great deal of trouble to make the parser as ''open-access'' as possible,
because a parser cannot ever be general enough for every game without
being extremely modifiable.  So there are very many ways to customise
the Inform parser, hopefully without the user needing to understand much
about how it works (because this is quite a long story).

The first essential requirement of any parser is to accept the addition of
the grammar for a new verb.  In Inform code, grammar should appear at the end
of the source code for a game, and of course most of it is written out
in the Grammar header file, which all games using the library include.
After this inclusion, you can add extras.

The directive for this is called Verb, and here's a typical example: some
of the library's grammar for ''take":

     Verb "take" "get" "pick" "lift"
                     * "out"                          -> Exit
                     * multi                          -> Take
                     * multiinside "from" noun        -> Remove
                     * "in" noun                      -> Enter
                     * multiinside "off" noun         -> Remove
                     * "off" held                     -> Disrobe
                     * "inventory"                    -> Inv;
     
This declares a verb, for which ''take", ''get" and so on are synonyms, and
which can take seven different courses.



  **   It should be noted that these really are synonyms: the parser thinks
''take" and ''get" are exactly the same.  Sometimes this has odd results,
so that although ''get in bed" is correctly understood as a request to enter
the bed, ''take in washing" is misunderstood as a request to enter the
washing.  You could either get around this by writing separate grammars for
the two nearly-synonyms, or can cheat and see if the variable
verb_word=='take' or 'get'.  Mostly, though, you don't mind if a few
odd things are accepted by the parser: what matters more is that sensible
things are not rejected by it.

When it ploughs through what the player has typed, the parser tries to match
each line in turn, starting at the top.  The first line will only be matched
if the player has typed something like ''get out".  The second line is more
interesting: it allows the player to type a single object or a list of
objects.  So the second line could be matched by

     take the banana
     get all the fruit except the apple
     
There need be no grammar at all after the verb: for example, a grammar for
''inventory" could be as simple as

     Verb "invent" "inv" "i"
                     *                                -> Inv;
     
After the -> in each line is the name of an action.  This is how actions
are defined: they are the names which appear in grammar lines like this
one.  Remember that if you do create an action this way, you also have
to write a routine to execute the action, even if it's one which doesn't
do very much.  For instance:

     [ XyzzySub; "Nothing happens."; ];
     Verb "xyzzy"    *                                -> Xyzzy;
     
will make a new magic-word verb ''xyzzy'', which always says ''Nothing
happens'' - always, that is, unless some before rule gets there first,
as it might do in certain magic places.  (The name of the routine is
always the name of the action with Sub appended.)

The new action Xyzzy is treated exactly like all the standard Inform
actions: ##Xyzzy gives its action number, and you can write before
and after rules for it in Xyzzy: fields just as you would for, say,
Take.

The individual words in the grammar (after the * and before the ->) are
called ''tokens".  In increasing order of complexity, this is the complete
list:


     "<word>"               that literal word only
     [noun]                      any object in scope
     [held]                      object held by the player
     [creature]                  an object in scope which is animate
     [multi]                     one or more objects in scope
     [multiheld]                 one or more held objects
     [multiexcept]               one or more in scope, except the other
     [multiinside]               one or more in scope, inside the other
     <attribute>                      any object in scope which has the attribute
     noun = <Routine>               any object in scope passing the given test
     scope = <Routine>              an object in this definition of scope
     [special]                    any single word or number
     [number]                    a number only
       <Routine>                      any text accepted by the given routine


(Tokens like [noun] are so written here to avoid confusion: there is
a variable called noun too, which is quite different.)


In the case of noun = <Routine>, the parser applies the following test:
the variable noun is set to the object in question, and the routine is
called.  If it returns true, the parser accepts the object, and otherwise
it rejects it.

 [number] matches any decimal number from 0 upwards (though it
rounds off large numbers to 10000), and also matches the numbers ''one''
to ''twenty'' written in English.

 The token [special] is now obselete.

 For now, we shall take ''in scope" to mean ''visible to the player".  It
is quite important in some cases to know exactly what this means, so
a better definition will be given later.



The [held] token is convenient for two reasons.  Firstly, many actions
only sensibly apply to things being held (such as Eat or Wear), and
using this token in the grammar you can make sure that the action is
never generated by the parser unless the object is being held.  That
saves on always having to write ''You can't eat what you're not holding"
code.  Secondly, suppose we have grammar

     Verb "eat"
                     * held                           -> Eat;
     
and the player types

     eat the banana
     
while the banana is plainly in view, on a shelf, say.  It would be
rather petty of the game to refuse on the grounds that the banana is
not being held.  So the parser will generate a Take action for the
banana and then, if the Take action succeeds, an Eat action.  (Notice
that the parser does not just pick up the object, but issues an action
in the proper way - so if the banana had rules making it too slippery
to pick up, it won't be picked up.)

The [multi-] tokens indicate that a list of one or more objects can
go here.  (The parser works out all the things the player has asked
for, sorting out plural nouns and words like ''except" by itself, and
then generates actions for each one.)  [multiexcept] is provided
to make commands like

     put everything in the rucksack
     
parsable: the ''everything" is matched by all of the player's
possessions except the rucksack (this stops the parser from generating
an action to put the rucksack inside itself).  Similarly
[multiinside] handles:

     remove everything from the cupboard
     
A restriction here is that a single grammar line can only contain
one [multi-] token: so ''hit everything with everything" can't be
parsed (straightforwardly: you can parse anything with a little more
effort).  On the whole, this is no bad thing.

The reason not all nouns can be multiple in the first place is that
too helpful a parser makes too easy a game.  You probably don't want
to allow something like

     unlock the mystery door with all the keys
     
- you want the player to suffer having to try them one at a time,
or else to be thinking.  (Of course if you do want to allow this it
is easy enough to change the grammar: the point is that you have the
option.)




We can also sort out objects according to attributes that they have:

     Verb "use" "employ" "utilise"
                     * edible                    -> Eat
                     * clothing                  -> Wear
           ...and so on...
                     * enterable                 -> Enter;
     
and this is how attributes are used as tokens.  (The library grammar
does not contain such an appallingly convenient verb!)

Since you can define your own attributes, it is therefore easy to
make a grammar line which matches only your own class of object.



  **   A footnote: the [creature] token is thus equivalent to
writing animate; but it dates back to the earliest days of Inform,
and does no harm.

Sometimes even that isn't flexible enough.  Here is a verb, ''free",
which should only apply to animal kept in a cage:

     [ CagedCreature;
         if (noun in wicker_cage) rtrue; rfalse;
     ];
     Verb "free" "release"
                     * noun=CagedCreature        -> FreeAnimal;
     
So that only nouns which pass the CagedCreature test are allowed.
(The CagedCreature routine can appear anywhere in the code, though
it's tidier to keep it nearby.)




So far, all the tokens were to tell the parser which of the objects in scope
were acceptable.  Exactly what 'in scope' means will be gone into later,
and so will the powerful scope=... token.  Here we next want the parser to
match things other than names of objects and prepositions like ''into".
The simplest useful case is of numbers, for example:

     Verb "type"
                     * number                    -> TypeNum;
     
so that the TypeNum action will happen if the player types ''type 504''
or ''type seventeen''.



Exercise:    (A beautiful feature stolen from David M. Baggett's game
'The Legend Lives', which uses it to great effect.)  Some games produce
footnotes every now and then.  Arrange matters so that these are
numbered [1], [2] and so on in order of appearance, to be read by the
player when ''footnote 1'' is typed.



Answer:  

     Constant MAX_FOOTNOTES 10;
     global footnotes_seen data MAX_FOOTNOTES;
     global footnote_count;
     [ Note n i pn;
         for (i=0:i<footnote_count:i++)
             if (n==footnotes_seen->i) pn=i;
         if (footnote_count==MAX_FOOTNOTES) "** MAX_FOOTNOTES exceeded! **";
         if (pn==0) { pn=footnote_count++; footnotes_seen->pn=n; }
         print " [",pn+1,"]";
     ];
     [ FootnoteSub n;
         if (noun>footnote_count)
         {   print "No footnote [",noun,"] has been mentioned.^"; rtrue; }
         if (noun==0) "Footnotes count upward from 1.";
         n=footnotes_seen->(noun-1);
         print "[",noun,"]  ";
         if (n==0) "This is a footnote.";
         if (n==1) "D.G.REG.F.D is inscribed around English coins.";
         if (n==2) "~Jackdaws love my big sphinx of quartz~, for example.";
     ];
     
     Verb "footnote" "note" * number              -> Footnote;
     
And then call, for instance, Note(1); to refer in the game to
the ''English coins'' footnote.



  **   
In fact, you're allowed to provide your own number-parsing routine, so
many sneaky possibilities are open here - Roman numerals, coordinates
like ''J4", long telephone numbers (which would be too large to fit into
integer variables in Inform), understanding English numbers and so on.
This takes the form

     [ ParseNumber buffer length;
       ...returning 0 if no match is made, or the number otherwise...
     ];
     
and examines the supposed ''number" held at the byte address buffer,
which is a row of ASCII characters of the given length.  If you declare
a ParseNumber routine, then the parser will always try this first when
trying to decode something as a number (and if it fails will fall back
on its own number-parsing routine).






  ** **   For not-very-good internal reasons, ParseNumber can't return
0 to mean the number zero.  Probably ''zero'' won't be needed too often,
but if it is you can always return some value like 1000 and code the
verb in question to understand this as 0.



  ** **   You can give a routine to parse anything:

     [ French w n; w=NextWord();
         if (w=='un' or 'une') n=1;
         if (w=='deux')        n=2;
         if (w=='trois')       n=3;
         if (w=='quatre')      n=4;
         if (w=='cinq')        n=5;
         if (n==0) return -1;
         parsed_number = n; return 1;
     ];
     
will detect low numbers in French, and could be used by something like:

     Verb "type"
                     * French                    -> TypeFrenchNum
                     * number                    -> TypeNum;
     
The specification for such a routine is as follows: it is to use NextWord
(possibly several times) to look at the appropriate words which
the user has typed.  The variable wn (current word number) may also be
helpful.  The routine must return

     -1    if the user's input isn't understood,
     1    if there is a numerical value resulting, or
     $n$    if object $n$ is understood.
     
In the case of a number, the actual value should be put into the variable
parsed_number.
On an unsuccessful match (returning -1) it doesn't matter what the final
value of wn is.  On a successful one it should be left pointing to the next
thing  after what the routine understood.  (Since NextWord moves
wn on by one each time it is called, this happens automatically unless
the routine has read too far.)




That's all about tokens: back to verb definition commands, because
some of the above examples are slightly contrived - they create wholly
new and unlikely verbs.  More often, one would want, say, a big array of
labelled buttons, any of which could be pushed.  So the verb for ''push"
ought to be extended, and for this the Extend directive is provided:

     Extend "push"
                     * Button                    -> PushButton;   
     
A routine called Button could then be written to accept things like

     ''button j16",    ''d11",    ''a5 button".
     
The point of Extend is that it is against the spirit of the library to
alter the standard library files - including the grammar table - unless
absolutely necessary.



  ** **   Actually, there's a better way to provide these buttons, so that
they work with any verb automatically, and that's to make a button object
with a parse_name routine which cunningly extracts the button number
as it parses: see the game 'Balances' for an example of this.

Normally, extra lines of grammar are added at the bottom of those already
there.  This may not be what you want.  For instance, ''take" has a grammar
line

                     * multi                     -> Take
     
quite early on.  So if you want to add a grammar line which diverts
''take something-edible" to a different action, like so:

                     * edible                    -> Eat
     
then it's no good adding this at the bottom of the Take grammar, because
the earlier line will always be matched first.  Thus, you really want
to insert your line at the top, not the bottom, in this case.  The right
command is

     Extend "take" first
                     * edible                    -> Eat;
     
You might even want to actually replace the old grammar completely, not
just add a line or two.  For this, use

     Extend "push" replace
                     * Button                    -> PushButton;
     
and now ''push" can be used only in this way.  To sum up, Extend can take
three keywords:

     replace          completely replace the old grammar with this one
     first            insert the new grammar at the top of the old one
     last             insert the new grammar at the bottom of the old one


with last being the default (which doesn't need to be said explicitly).



  **    Another convenience is to define meta verbs - verbs which are not
really part of the game, such as ''save'', ''score'' and ''quit''.
(You probably want to add your own debugging commands as meta-verbs: if you
make them ordinary verbs, then they may work most of the time, but might be
interfered with by game rules, and will take up ''game time".)
To declare a verb as meta, just add the word after the command.
For instance, the library defines

     Verb meta "score"
                     *                           -> Score;
     
The parser will match the grammar exactly in the normal way, but treats
the resulting action as outside the game - taking no time up, and
possible at any moment.



  ** **   There are (a few) times when verb definition commands are not
enough.  For example, in the original 'Advent' (or 'Colossal Cave'),
the player could type the name of a not-too-distant place which had
previously been visited, and be taken there.  There are several ways to code
this - say, with 60 rather similar verb definitions, or with a single
''travel" verb which has 60 synonyms, whose action routine looks at the
parser's verb_word variable to see which one was typed - but here's
another.  The library will call the UnknownVerb routine (if you provide one)
when the parser can't even get past the first word.  This has two options:
it can return false, in which case the parser just goes on to complain as it
would have done anyway.  Otherwise, it can return a verb word which is
substituted for what the player actually typed.  Here is a foolish example:

     [ UnknownVerb w;
       if (w=='shazam') { print "Shazam!^"; return 'inventory'; }
       rfalse;
     ];
     
which responds to the magic word ''shazam" by printing Shazam! and then,
rather disappointingly, taking the player's inventory.  But in the example
above, it could be used to look for the word w through the locations of
the game, store the place away in some global variable, and then return 'go'.
The GoSub routine could then be fixed to look at this variable.



** ** Exercise:    Why is it usually a bad idea to print text out in an
UnknownVerb routine?



Answer:  Because the parser might go on to reject the line it's working on:
for instance, if the player typed ''inventory splurge'' then the message
''Shazam!'' followed by a parser complaint will be somewhat unedifying.



  ** **   If you allow a flexible collection of verbs (say, names of
spells or places) then you may want a single 'dummy' verb to stand for
whichever is being typed.  This may make the parser produce strange
questions because it is unable to sensibly print the verb back at the
player, but you can fix this using the PrintVerb entry point (see
the Appendix).  See the exercise below.



** Exercise:    A tricky one: code a spaceship whose control panel has five
sliding controls, each of which can be set to a numerical value, so that
the game looks like:

     >look
     Machine Room
     There is a control panel here, with five slides, each of which can be
     set to a numerical value.
     
     >push slide one to 5
     You set slide number 1 to the value 5.
     
     >examine the first slide
     Slide number 1 currently stands at 5.
     
     >set four to six
     You set slide number 4 to the value 6.
     



Answer:  Here goes: we could implement the buttons with five
separate objects, essentially duplicates of each other.  (And by using a
class definition, this wouldn't look too bad.)  But if there were
500 slides this would be less reasonable.

     [ ASlide w n;
        if (location~=Machine_Room)            !  Slides only make sense in
            return -1;                         !  the Machine Room
        w=NextWord();
        if (w=='slide') w=NextWord();
        n=0;
        if (w=='first' or 'one')   n=1;
        if (w=='second' or 'two')  n=2;
        if (w=='third' or 'three') n=3;
        if (w=='fourth' or 'four') n=4;
        if (w=='fifth' or 'five')  n=5;
        if (n==0) return -1;                   !  Failure!
        w=NextWord();
        if (w~='slide') wn--;                  !  Move word counter back to
                                               !  first misunderstood word
        parsed_number=n;
        return 1;                              !  Success!
     ];
     
     Global slide_settings data 10;            !  Ten bytes of data to hold
                                               !  five words for the settings
                                               !  (all initially zero)
     
     !  An interesting point here is that "noun" and "second" contain the
     !  appropriate numbers, and not objects: this all happens automatically
     
     [ SetSlideSub;
        slide_settings-->(noun-1) = second;
        print_ret "You set slide number ", noun,
                  " to the value ", second, ".";
     ];
     
     [ XSlideSub;
        print_ret "Slide number ", noun, " currently stands at ",
            slide_settings-->(noun-1), ".";
     ];
     
     Extend "set" first
                * ASlide "to" number                  -> SetSlide;
     Extend "push" first
                * ASlide "to" number                  -> SetSlide;
     Extend "examine" first
                * ASlide                              -> XSlide;
     



** ** Exercise:    An even trickier one: write a parsing routine which will
accept any amount of text (including spaces, full stops and commas)
between double-quotes as a single token.



Answer:  
The blackboard code in 'Toyshop' contains just such a routine:

     Global from_char; Global to_char;
     [ QuotedText i j f;
        i = parse->((++wn)*4-3);
        if (buffer->i=='"')
        {   for (j=i+1:j<=(buffer->1)+1:j++)
                if (buffer->j=='"') f=j;
            if (f==0) return -1;
            from_char = i+1; to_char=f-1;
            if (from_char>to_char) return -1;
            while (f> (parse->(wn*4-3))) wn++; wn++;
            return 1;
        }
        return -1;
     ];
     
Note that in the case of success, the word marker wn is moved beyond the
last word accepted (since the Z-machine automatically tokenises
a double-quote as a single word).  The routine then tells the parser it
has parsed a number, which is a white lie.  What it actually does is to
record the byte positions where the quoted text starts and finishes in
the raw text buffer so that an action routine can easily extract the
text and use it later.  (Note that "" with no text inside is not
matched by this routine but only because the last if statement throws
out that one case.)



** ** Exercise:    And another: implement the Crowther and Woods feature
of moving from one room to another by typing its name, discussed above,
using a dummy verb and without using Replace to change any library
routines.



Answer:  
Define two properties:

     Property place_name;
     Property long to_places;
     
The scheme will work like this: a named room should have the place_name
property set to a single dictionary word; say, the Bedquilt cave could
be called 'bedquilt'.  Then in any room, a list of those other rooms
which can be moved to in this way should appear in the to_places entry.
For instance,

     to_places Bedquilt Slab_Room Twopit_Room;
     
Now the code: see if a not-understood verb is a place name of a nearby room,
and if so store that room's object number in goto_room, converting
the verb to a dummy.

     Global goto_room = 0;
     [ UnknownVerb word p i;
         p = location.&to_places; if (p==0) rfalse;
         for (i=0:(2*i)<location.#to_places:i++)
             if (word==(p-->i).place_name)
             {   goto_room = p-->i; return 'go#room';
             }
         rfalse;
     ];
     [ PrintVerb word;
         if (word=='go#room')
         { print "go to "; PrintShortName(goto_room); rtrue; }
         rfalse;
     ];
     
(The supplied PrintVerb is icing on the cake: so the parser can
say something like ''I only understood you as far as wanting to go to
Bedquilt.'' if need be.)  It remains only to put in code
and grammar for the dummy verb:

     [ GoRoomSub;
         if (goto_room hasnt visited) "But you have never been there.";
         PlayerTo(goto_room);
     ];
     Verb "go#room"  *                                -> GoRoom;
     
Note that if you don't know the way, you can't go there!  A purist might
prefer instead to not recognise the name of an unvisited room, back at
the UnknownVerb stage, to avoid the player being able to deduce names
of nearby rooms from this 'error message'.



+-----------------------------------------------------------------------------+
|                       16  Scope and what you can see                        |
+-----------------------------------------------------------------------------+




     He cannot see beyond his own nose.  Even the fingers he outstretches
     from it to the world are (as I shall suggest) often invisible to him.
     
         - Max Beerbohm (1872-1956), of George Bernard Shaw




     Wherefore are these things hid?
     
         - William Shakespeare (1564-1616),  Twelfth Night



Time to say what ''in scope" means.  This definition is one of the most
important algorithms in the game, although it is buried inside the parser,
because it decides what the player is allowed to refer to: so here it is
in full.  The following are in scope:

     the player's immediate possessions;
     the 12 compass directions;
      if there is light, the objects in the same place as the player.
     

\narrower In addition, if an object is in scope then its immediate
possessions are in scope,  if it is 'see-through', which means that:

     the object has supporter,  or
     the object has transparent,  or
     the object is an open container.
     

The definition of when there is light will be gone into in the next section.



  **   Many things are still in scope in a dark room - so the player can
still turn a lamp on if it's being carried.  On the other hand, a player who
puts the lamp on the ground and turns it off then loses the ability to
turn it back on again, because it is out of scope.  (This can be changed;
see below.)



  **   The compass direction objects make sense as objects.  The player can
always type something like

     attack the south wall
     
(and a before rule for the room in question could make something
unusual happen as a result).  The compass directions are visible in the
dark, as otherwise the player could not still walk around.



  **   The parser applies scope rules to other people too, not just the
player.  Thus ''dwarf, drop sword'' will be accepted even if the sword is
invisible to the player provided it is visible to the dwarf.



  **   Items with the concealed attribute may be concealed from
ordinary descriptions - but the parser still sees them: they are still in
scope.  (If you want things to be both concealed and unreferrable-to,
put them somewhere else!)



  ** **   Actually, the above definition is not quite right, because
the compass directions are not in scope when the player asks for a plural
number of things, like ''take all the knives".  (This makes some of the
parser's plural algorithms run faster.)  Also, for a [multiexcept]
token, the other object is not in scope; and for a [multiinside] token,
only objects in the other object are in scope.  This makes ''take everything
from the cupboard'' work in the natural way.




The rest of this section is about how to change the scope rules.  As usual
with Inform, you can change them globally, but it's more efficient and
safer to do so only locally.

A typical example: how do we allow the player to ask questions like
the traditional
''what is a grue''?
The ''grue'' part ought to be parsed as if it were a noun, so that
we could distinguish between, say, a ''garden grue'' and a ''wild grue''.
So it isn't good enough to look only at a single word.  Here is one
solution:

     Object questions "qs";
     [ QuerySub;
       print_paddr noun.description; new_line;
     ];
     [ Topic i;
       if (scope_stage==1) rfalse;
       if (scope_stage==2)
       {   objectloop (i in questions) PlaceInScope(i);
           rtrue;
       }
       "At the moment, even the simplest questions confuse you.";
     ];
     
where the actual questions are themselves objects which belong to
the questions object, like so:

     Object q1 "long count" questions
       with name "long" "count",
            description "The Long Count is the great Mayan cycle of time, \
                which began in 3114 BC and will finish with the world's end \
                in 2012 AD.";
     
and we also have a grammar line:

     Verb "what"
                     * "is"  scope=Topic              -> Query
                     * "was" scope=Topic              -> Query;
     
(Note that the questions and q1 objects are out of the game for every
other purpose.  The name ''qs'' doesn't matter; the individual questions
are named so that the parser might be able to say ''Which do you mean,
the long count or the short count?'' if the player just asked ''what
is the count''.)  Here's what happens: when the parser reaches
scope=Topic, it calls the Topic routine with the variable scope_stage
set to 1.  The routine should return 1 (true) if it is prepared to allow
multiple objects to be accepted here, and 0 (false) otherwise: as we don't
want ''what is everything'' to list all the questions and answers in the
game, we return false.

A little later on in its machinations, the parser again calls Topic
with scope_stage now set to 2.  Topic is now under an obligation to
tell the parser which objects are to be in scope.  It can call two
parser routines to do this.

     ScopeWithin(object)
     
puts everything inside the object into scope, though not the object itself;

     PlaceInScope(object)
     
puts just a single object into scope.  It is perfectly legal to declare
something in scope that ''would have been in scope anyway": or even something
which is in a different room altogether from the actor concerned, say at the
other end of a telephone line.  Our scope routine Topic should then return

 0    (false) to carry on with the usual scope rules, so that everything
that would usually be in scope still is, and

 1    (true) to tell the parser not to put any more objects into scope.


(So at scope_stage 2 it is quite permissible to do nothing but return false,
whereupon the usual rules apply.)  Topic returns true because it wants
only question topics to be in scope, not question topics together with
everything near the player.

If the player had typed ''what is the long count'', that would be all that
happens and all would be well.  On the other hand, if the player typed
''what is the lgon cnout'' owing to a bout of dyslexia, the error message
which the parser would usually produce (''You can't see any such thing'')
would be unsatisfactory.  So if parsing failed at this token, then
Topic is called at scope_stage 3 to print out a suitable error
message.  (It must provide one.)



  **   The scope= notation is available only under Inform 5.4 and later.



  **   Note that ScopeWithin(object) extends the scope down through
its possessions according to the usual rules (i.e. depending on their
transparency, whether they're containers and so in).  The definition of
Topic above shows how to put just the direct possessions into scope.



Exercise:   Write a token which puts everything in scope, so that you could
have a debugging ''purloin'' verb which could take anything (regardless
of where it was and the rules applying to it).



Answer:  A slight refinement of such a ''purloin'' verb is already defined
in the library (if the constant DEBUG is defined), so there's no need.
Here's how it could be done:

     [ Anything i;
       if (scope_stage==1) rfalse;
       if (scope_stage==2)
       {   for (i=1:i<=top_object:i++) PlaceInScope(i); rtrue; }
       "No such in game.";
     ];
     
(This disallows multiple matches for efficiency reasons - the parser has
enough work to do with such a huge scope definition as it is.)  Now
the token scope=Anything will match anything at all, even things like
the abstract concept of 'east'.





Changing the global definition of scope should be done cautiously
(there may be unanticipated side effects); bear in mind that scope decisions
need to be taken often - every time an object token is parsed, so perhaps
five to ten times in every game turn - and hence moderately
quickly.

To do this one provides a routine called

     InScope(actor)
     
where the actor is the person whom the parser is working out scope for;
usually, then, actor=player, but this should not be assumed to be always
the case.  If the routine decides that a particular object should be in
scope for the actor, it should execute InScope and ScopeWithin just
as above, and return true or false (as if it were at scope_stage 2).
Thus, it is vital to return false in circumstances when you don't want
to intervene.



  **   In the case of a token scope=Routine, the Routine gets first
crack at scope-changing, and InScope will only be reached if it returns
false to signify 'carry on'.

Here are some examples.  Firstly, as promised above, how to change the
rule that ''things you've just dropped disappear in the dark":

     [ InScope person i;
       if (person==player && location==thedark)
           objectloop (i near player)
               if (i has moved)
                   PlaceInScope(i);
       rfalse;
     ];
     
With this routine added, the objects in the dark room the player
is in are in scope only if they have moved (that is, have been held by
the player in the past); and even then, are in scope only to the player.



** Exercise:   Code the following puzzle, which has nasty scope
complications.  In an initially dark room there is a light switch.
Provided you've seen the switch at some time in the past, you can turn
it on and off - but before you've ever seen it, you can't.  Inside the
room is nothing you can see, but you can hear a dwarf breathing.  If you
tell the dwarf to turn the light on, he will.



Answer:  For good measure, we'll combine this with the previous rule
about moved objects being in scope in the dark.  The following
can be inserted into the 'Shell' game:

     Object coal "dull coal" Blank_Room
       with name "dull" "coal";
     
     Object Dark_Room "Dark Room"
       with description "An empty room with a west exit.",
            each_turn
            [; if (self has general) self.each_turn=0;
               else "^You hear the breathing of a dwarf.";
            ],
            w_to Blank_Room;
     
     Nearby light_switch "light switch"
       with name "light" "switch",
            initial "On one wall is the light switch.",
            after
            [; SwitchOn: give Dark_Room light;
               SwitchOff: give Dark_Room ~light;
            ],
       has  switchable static;
     
     Nearby diamond "shiny diamond"
       with name "shiny" "diamond"
       has  scored;
     
     Nearby dwarf "dwarf"
       with name "voice" "dwarf",
            life
            [; Order: if (action==##SwitchOn && noun==light_switch)
                      {   give Dark_Room light general;
                          give light_switch on; "~Right you are, squire.~";
                      }
            ],
       has  animate;     
     
     [ InScope person i;
       if (parent(person)==Dark_Room)
       {   if (person==dwarf  Dark_Room has general)
               PlaceInScope(light_switch);
       }
       if (person==player && location==thedark)
           objectloop (i near player)
               if (i has moved  i==dwarf)
                   PlaceInScope(i);
       rfalse;
     ];
     
Note that the routine puts the light switch in scope for the dwarf -
if it didn't, the dwarf would not be able to understand
''dwarf, turn light on", and that was the whole point.
     



  **   By combining an InScope routine with token-parsing routines
in grammar, dramatic effects are possible.  See the example game
'Balances', for instance.



  ** **   Once you begin programming the parser on a large scale, you soon
reach the point where the parser's ordinary error messages no longer appear
sensible.  So that you can change the rules even at this last hurdle,
the parser calls your ParserError routine (if you provide one): the
argument is the error type, and you return true
to tell the parser to shut up (as you have already printed a better error
message than it would have done).  The error types are all defined as
constants:



      STUCK_PE                I didn't understand that sentence.
      UPTO_PE                 I only understood you as far as...
      CANTSEE_PE              You can't see any such thing.
      TOOLIT_PE               You seem to have said too little!
      NOTHELD_PE              You aren't holding that!
      MULTI_PE                You can't use multiple objects with that verb.
      MMULTI_PE               You can only use multiple objects once on a line.
      VAGUE_PE                I'm not sure what ~it~ refers to.
      EXCEPT_PE               You excepted something not included anyway!
      ANIMA_PE                You can only do that to something animate.
      VERB_PE                 That's not a verb I recognise.
      SCENERY_PE              That's not something you need to refer to...
      ITGONE_PE               You can't see ~it~ (the spell book) at the moment.
      JUNKAFTER_PE            I didn't understand the way that finished.
      TOOFEW_PE               Only five of those are available.
      NOTHING_PE              Nothing to do!
      NUMBER_PE               I didn't understand that number.
      ASKSCOPE_PE              whatever the scope routine prints


Each time the parser gives up on a line of grammar, it has hit one of these
conditions.  A verb may have many lines of grammar; so by the time the
parser wants to print an error, all of them must have failed.  The error
message it prints is the most 'interesting' one (meaning, lowest down this
list).



+-----------------------------------------------------------------------------+
|                         17  The light and the dark                          |
+-----------------------------------------------------------------------------+



The library maintains light by itself, and copes with events like:

     a total eclipse of the Sun;
     fusing all the lights in the house;
     your lamp going out;
     a dwarf stealing it and running away;
     dropping a lit match which you were seeing by;
     putting your lamp into an opaque box and shutting the lid;
     black smoke filling up the glass jar that the lamp is in;
     the dwarf with your lamp running back into your now-dark room.
     
The point of this list is to demonstrate that light v. darkness is
tricky to get right, and that it is best left to the library.  Your code
needs only to do something like

     give lamp light;
     remove match;
     give glass_jar ~transparent;
     move dwarf to Dark_Room;
     
and can leave the library to sort out the consequences.  As the above
suggests, the light attribute means that an object is giving off light,
or that a room is currently lit (e.g. by being out of doors in day-time).

If you simply never want to have darkness, and some games never do, a
sneaky way of doing it is to put the line

     give player light;
     
in Initialise.  The game works as if the player herself were glowing
enough to provide light to see by.  So there's never darkness near the
player.




The definition of ''when there is light" is complicated, involving
recursion both up and down.  Remember that the parent of the player
object may not be a room; it may be, say, a red car whose parent is a
room.

There is light exactly when the parent of the player 'offers light'.
An object 'offers light' if:

     it itself has the light attribute set,  or
     any of its immediate possessions 'have light',  or
     it is see-through and its parent offers light,  or
     it is enterable and its parent offers light;
     
while an object 'has light' if:

     it currently has the light attribute set,  or
     it is see-through and one of its immediate possessions has light.
     
The process of checking this stops as soon as light is discovered.  The
routines

     OffersLight(object) and HasLightSource(object)
     
which return true or false and have no side effects (that is, they merely
report on the current state without changing anything), are available and
might occasionally be useful.



  **   So light is cast up and down the tree of objects.  In certain
contrived circumstances this might be troublesome: perhaps an opaque box,
whose outside is fluorescent but whose interior is dark, and which contains
an actor who needs not to have other contents of the box in scope...
'contrived' being the word.  The dilemma could be solved by putting an inner
box in the outer one.



Exercise:    How would you code a troll who is afraid of the dark, and needs
to be bribed but will only accept a light source... so that the troll will
be as happy with a goldfish bowl containing a fluorescent jellyfish as he
would be with a lamp?



Answer:  Just test if HasLightSource(gift)==1.

Each turn, light is reconsidered.  The presence or absence of light affects
the Look, Search, LookUnder and Examine actions, and
(since this is a common puzzle) also the Go action: you can provide
a routine called

     DarkToDark()
     
and if you do then it will be called when the player goes from one dark
room into another dark one.  If you want, you can take the opportunity to
kill the player off or extract some other forfeit.  If you provide no such
routine, then the player can move about freely (subject to any rules which
apply in the places concerned).



+-----------------------------------------------------------------------------+
|                        18  On inventories and lists                         |
+-----------------------------------------------------------------------------+




     As some day it may happen that a victim must be found
     I've got a little list - I've got a little list
     Of society offenders who might well be underground,
     And who never would be missed
     Who never would be missed!
     
         - W. S. Gilbert (1836-1911),  The Mikado



The library often needs to reel off a list of objects: when an Inv
(inventory) action takes place, for instance, or when describing the
contents of a container or a room.  Lists are difficult to print out
correctly 'by hand', because there are many cases to get right (especially
when taking plurals into account).  Fortunately, the library's list-maker is
open to the public.  The routine to call is:

     WriteListFrom(object, style);
     
where the list will start from the given object and go along its siblings.
(Thus, to list all the objects inside X, list from child(X).)  What the
list looks like depends on the style, which is a bitmap you can make by
adding up some of the following constants:


      NEWLINE_BIT            New-line after each entry
      INDENT_BIT             Indent each entry by depth
      FULLINV_BIT            Full inventory information after entry
      ENGLISH_BIT            English sentence style, with commas and 'and'
      RECURSE_BIT            Recurse downwards with usual rules
      ALWAYS_BIT             Always recurse downwards
      TERSE_BIT              More terse English style
      PARTINV_BIT            Only brief inventory information after entry
      DEFART_BIT             Use the definite article in list
      WORKFLAG_BIT           At top level (only), only list objects
                               which have the workflag attribute

 The best way to use this is to experiment.   For example, a 'tall'
inventory is produced by:

     WriteListFrom( child(player),
                    FULLINV_BIT + INDENT_BIT + NEWLINE_BIT + RECURSE_BIT );
     
and a 'wide' one by:

     WriteListFrom( child(player),
                    FULLINV_BIT + ENGLISH_BIT + RECURSE_BIT );
     
which produce effects like:

     >inventory tall
     You are carrying:
       a bag (which is open)
         three gold coins
         two silver coins
         a bronze coin
       four featureless white cubes
       a magic burin
       a spell book
     
     >inventory wide
     You are carrying a bag (which is open), inside which are three gold
     coins, two silver coins and a bronze coin, four featureless white
     cubes, a magic burin and a spell book.
     
(except that the 'You are carrying' part is not done by the list-maker,
and nor is the final full stop in the second example).




The workflag is an attribute which the library scribbles over from time
to time as temporary storage, but you can use it with care.  In this case
it makes it possible to specify any reasonable list.



Exercise:   Write a DoubleInvSub action routine to produce an inventory
like so:

     You are carrying four featureless white cubes, a magic burin and a
     spell book.  In addition, you are wearing a purple cloak and a miner's
     helmet.
     



Answer:  
     [ DoubleInvSub i count1 count2;
       print "You are carrying ";
       objectloop (i in player)
       {   if (i hasnt worn) { give i workflag; count1++; }
           else { give i ~workflag; count2++; }
       }
       if (count1==0) print "nothing.";
       else
       WriteListFrom(child(player),
           FULLINV_BIT + ENGLISH_BIT + RECURSE_BIT + WORKFLAG_BIT);
     
       if (count2==0) ".";
       print ".  In addition, you are wearing ";
       objectloop (i in player)
       {   if (i hasnt worn) give i ~workflag; else give i workflag;
       }
       WriteListFrom(child(player),
           ENGLISH_BIT + RECURSE_BIT + WORKFLAG_BIT);
       ".";
     ];
     

Some objects ought to print something different when they appear in
inventory lists: a wine bottle should say how much wine is left, for
instance.  By giving an object an invent routine, you can alter the
usual rules.

A typical inventory list looks like:

     >i
     You are carrying:
       a green cone
       a pair of hiking boots
       your satchel (which is open)
         a green cube
     
and each line goes through two stages.  Firstly, the object's indefinite
article and name are printed.  Secondly, little informative messages like
''(which is open)" are printed, and inventories are given for the contents
of open containers.

An object's invent routine gets two chances to interfere with this,
one before each stage.  So what happens is this:

 1.     The global variable inventory_stage is set to 1.

 2.     The invent routine is called (if there is one).
If it returns true, stop here.

 3.     The indefinite article and short name are printed.

 4.     The global variable inventory_stage is set to 2.

 5.     The invent routine is called (if there is one).
If it returns true, go to step 8.

 6.     One or more of the following are printed, as appropriate:

         (providing light)
         (being worn)
         (which is open)
         (which is closed)
     

 7.     If it is an open container, its contents are inventoried.

 8.     Linking text (such as a new-line or a comma) is printed,
according to the current style.

 Note that if an invent routine does return true,
then the contents are never reached.

For example, here is an invent routine for a matchbook:

     invent
     [ i; if (inventory_stage==2)
          {   i=self.number;
              if (i==0) print " (empty)";
              if (i==1) print " (1 match left)";
              if (i>1)  print " (",i," matches left)";
          }
     ],
     
(The rest of the matchbook definition is given in the 'Toyshop' example
game.)



  ** **   Changing the rules at inventory_stage 1 is kept on for more
peculiar effects (and is not really recommended).



+-----------------------------------------------------------------------------+
|                           19  The naming of names                           |
+-----------------------------------------------------------------------------+




     The Naming of Cats is a difficult matter,
     It isn't just one of your holiday games;
     You may think at first I'm as mad as a hatter
     When I tell you, a cat must have THREE DIFFERENT NAMES.
     
         - T. S. Eliot (1888-1965),  The Naming of Cats





     Bulldust, coolamon, dashiki, fizgig, grungy, jirble, pachinko,
     poodle-faker, sharny, taghairm
     
         - Catachrestic words from Chambers English Dictionary



Providing an invent routine doesn't work quite so well for the match
as for the matchbook.  You might try:

     invent
     [;   if (inventory_stage==2)
          {   if (self has light) print " (burning away)"; rtrue;
          }
     ],
     


  **   Returning true here is a trick to stop ''(providing light)"
from appearing as well - after all, that's redundant.

This does work but there's a better way, which is to change the object's
short name itself, from ''unlit match" to ''lit match" say.  So
another property, called short_name, is available.
  Normally, the short name of an object
is given in the header of the object definition.
But if a short_name routine is given, then whenever the game wants to
write out the name of the object, the following happens:

 1.    If the short_name is a string, it's printed and that's all.

 2.    If it is a routine, then it is called.  If it returns true,
that's all.

 3.    The 'real' short name (the one in the object header) is printed.

 So, as promised, here's the better way to code the match:

     short_name
     [;   if (self has light) print "burning match";
                         else print "unlit match";
          rtrue;
     ],
     
Note that rooms can also be given a short_name routine, which might be
useful to code, say, a grid of four hundred almost exactly similar
locations, called ''Area 1" up to ''Area 400".






  **   Now, though, the player is going to want to type ''drop the
burning match", or ''light the unlit match".  (Indeed, there might be two 
matches, only one of which can be called ''unlit".)  It's perfectly
straightforward to alter the name property of an object (provided one
remembers what it is: a list of (machine) words, being the byte addresses in
memory of words in the dictionary) but, again, there is a better and more
powerful way. This is to give the match object a parse_name routine.


A parse_name routine is expected to try to match the text which the user
has typed (available one word at a time from the NextWord() routine), and
to return how many words it managed to match.  It is required to go as far
as it can, i.e., not to stop if the first word makes sense, but to keep
reading and find out how many words in a row make sense.

It should return:

     0       if the text didn't make any sense at all,
     $k$     if $k$ words in a row of the text seem to refer to the object, or
     -1      to make the parser just do what it would normally do.
     
For example:

     Nearby thing "weird thing"
       with parse_name
            [ i; while (NextWord()=='weird' or 'thing') i++;
                 return i;
            ];
     
This definition duplicates (very nearly) what the parser would have done
if the weird thing had been defined as:

     Nearby thing "weird thing"
       with name "weird" "thing";
     
Which isn't very useful.  But the match can now be coded up with

     parse_name
     [ i j;   if (self has light) j='burning'; else j='unlit';
              while (NextWord()=='match' or j) i++;
              return i;
     ],
            
so that ''burning" only applies when it is, and similarly ''unlit".
(Actually the parser automatically recognises ''unlit" and ''lit", so this
last part was unnecessary.)




+-----------------------------------------------------------------------------+
|               20  Plural names and groups of similar objects                |
+-----------------------------------------------------------------------------+




     Abiit ad plures.
     
         - Petronius (?-c. 66),  Cena Trimalchionis



A notorious problem for adventure game parsers is to handle a collection of,
say, ten gold coins, allowing the player to use them independently of each
other, while gathering them together into groups in descriptions and
inventories.  This is relatively easy in Inform, and only in really hard
cases do you have to provide code.

There are two problems to be overcome: firstly, the game has to be able
to talk to the player in plurals, and secondly vice versa.  First, then,
game to player:

     Class  gold_coin_class
       with name "gold" "coin",
            plural "gold coins";
     
 (and similar silver and bronze coin classes here)

     Object bag "bag"
       with name "bag"
       has  container open openable;
     
     Nearby co1 "gold coin"   class gold_coin_class;
     Nearby co2 "gold coin"   class gold_coin_class;
     Nearby co3 "gold coin"   class gold_coin_class;
     Nearby co4 "silver coin" class silver_coin_class;
     Nearby co5 "silver coin" class silver_coin_class;
     Nearby co6 "bronze coin" class bronze_coin_class;
     
 Now we have a bag of six coins.  The player looking inside
the bag will get

     >look inside bag
     In the bag are three gold coins, two silver coins and a bronze coin.
     
How does the library know that the three gold coins are the same as each
other, but the others different?  It doesn't look at the classes but the
names.  It will only group together things which:

 (a)     have a plural set,

 (b)     are 'indistinguishable' from each other.

 Indistinguishable means they have the same name words as each other
(possibly in a different order), so that nothing the player can type
will separate the two.



  **   Actually, the library is cleverer than this.  What it groups
together depends slightly on the context of the list it's writing out.  When
it's writing a list which prints out details of which objects are providing
light, for instance (like an inventory), it won't group together two objects
if one is lit and the other isn't.  Similarly for objects with visible
possessions or which can be worn.




  ** **   This all gets even more complicated when the objects have a
parse_name routine supplied, because then the library can't use the name
fields to tell them apart.  If they have different parse_name routines, it
decides that they're different.  But if they have the same parse_name
routine, there is no alternative but to ask them.  What happens is that

     1.    A variable called parser_action is set to ##TheSame;
     2.    Two variables, called parser_one and parser_two are set to
           the two objects in question;
     3.    Their parse_name routine is called.  If it returns:
            -1     the objects are declared ''indistinguishable",
            -2     they are declared different.
     4.    Otherwise, the usual rules apply and the library looks at
            the ordinary name fields of the objects.
     
(##TheSame is a fake action.)

  The implementation of the
'Spellbreaker cubes' in the 'Balances' game
is an example of such a routine (so that if
the player writes the same name on several of the cubes, they become
grouped together).  Note that this whole set-up is such that if the
author of the parse_name routine has never read this paragraph, it doesn't
matter and the usual rules take their course.



  ** **   You may even want to provide a parse_name routine just to speed
up the process of telling two objects apart - if there were 30 gold coins
the parser will be doing a lot of work comparing all their names, but you
can make the decision much faster.





Secondly, the player talking to the computer.  This goes a little further
than just copies of the same object: many games involve collecting a number
of similar items, say a set of nine crowns in different colours. Then you'd
want the parser to recognise things like:

     > drop all of the crowns except green
     > drop the three other crowns
     
even though the crowns are not identical.  The simple way to do this is just
to put "crowns" in their name fields, and this works perfectly well most of
the time.



  ** **   But it isn't ideal, because then the parser will think

     > drop crowns
     
refers to a single object, and won't deduce that the player wants to pick
up all the sensibly available crowns.
So the complicated (but better way) is to make
the parse_name routine tell the parser that yes, there was a match, but
that it was a plural.  The way to do this is to set parser_action to
##PluralFound (another fake action).  So, for example:

     Class  crown_class
       with parse_name
            [ i j;
              for (::)
              {   j=NextWord();
                  if (j=='crown' or j==self.name) i++;
                  else
                  {   if (j=='crowns')
                      {   parser_action=##PluralFound; i++; }
                      else return i;
                  }
            ];
     



Exercise:    Write a 'cherub' class so that if the player tries to call them
''cherubs", a message like ''I'll let this go by for now, but the plural of
cherub is cherubim" appears.



Answer:   
     Global c_warned = 0;
     Class  cherub_class
       with parse_name
            [ i j flag;
              for (flag=1:flag==1:flag=0)
              {   j=NextWord();
                  if (j=='cherub' or j==self.name) flag=1;
                  if (j=='cherubs' && c_warned==0)
                  {   c_warned=1;
                      parser_action=##PluralFound; flag=1;
      print "(I'll let this go once, but the plural of cherub is cherubim.)^";
                  }
                  if (j=='cherubim')
                  {   parser_action=##PluralFound; flag=1; }
                  i++;
              }
              return i-1;
            ];
     
Then again, Shakespeare even writes ''cherubins'' in  Twelfth Night,
so who are we to censure?



+-----------------------------------------------------------------------------+
|                   21  Miscellaneous constants and scoring                   |
+-----------------------------------------------------------------------------+


Some game rules can be altered by defining 'constants' at the start of
the program, before the library files are included.  Two constants
it  must provide are the strings Story and Headline:

     Constant Story "ZORK II";
     Constant Headline "^An Interactive Plagiarism^\
                  Copyright (c) 1993 by Ivan O. Ideas.^";
     
All the rest are optional.



 
The library won't allow the player to carry an indefinite number of
objects: the limit allowed is the constant MAX_CARRIED, which you
may define if you wish.  If you don't define it, it's 100, which
roughly removes the rule.  (In fact you can change this 'live',
in that it is actually player.capacity which is consulted; the
only use of MAX_CARRIED is to set this up to an initial
value.)

If you define SACK_OBJECT to be some container, then the player will
automatically put old, least-used objects away in it as the game
progresses, provided it is being carried.  This is a feature which
endears the designer greatly to players.




Another constant is AMUSING_PROVIDED.  If you define this, the library
knows to put an ''amusing" option on the menu after the game is won.
It will then call Amusing() from your code when needed.  You can
use this to roll closing credits, or tell the player various strange
things about the game, now that there's no surprise left to spoil.





The other constants you are allowed to define help the score routines
along.  There are two scoring systems provided by the library, side by
side: you can use both or neither.  (You can always do what you like to
the score variable in any case.)  One scores points for getting certain
items or reaching certain places; the other for completing certain
actions.  The constants are:


     MAX_SCORE          The maximum game score (by default 0)
     NUMBER_TASKS          Number of individual ''tasks" to perform (1)
     OBJECT_SCORE          Bonus for first picking up a scored object (4)
     ROOM_SCORE          Bonus for first entering a scored room (5)

 and then the individual tasks have scores, as follows:

     Global task_scores initial t1 t2 ... tn;
     
Within your code, when a player achieves something, call Achieved(task)
to mark that the task has been completed.  It will only award points if
this task has not been completed before.

There do not have to be any ''tasks": there's no need to use the scoring
system provided.  Tasks (and the verb ''full" for full score) will only
work at all if you define the constant TASKS_PROVIDED.

A routine called PrintRank, which you can provide if you want, gets the
chance to print something additional to the score, such as rankings.  For
instance:

     [ PrintRank;
       print ", earning you the rank of ";
       if (score >= 348) "Grandmaster Adventurer!";
       if (score >= 330) "Master, first class.";
       if (score >= 300) "Master, second class.";
       if (score >= 200) "Junior Master.";
       if (score >= 130) "Seasoned Adventurer.";
       if (score >= 100) "Experienced Adventurer.";
       if (score >= 35) "Adventurer.";
       if (score >= 10) "Novice.";
       "Amateur.";
     ];
     

PrintTaskName prints the name of a game task (such as ''driving the car").
Of course, this is only ever called in a game with TASKS_PROVIDED defined.
For instance,

     [ PrintTaskName ach;
       if (ach==0) "eating a sweet";
       if (ach==1) "driving the car";
       if (ach==2) "shutting out the draught";
       if (ach==3) "building a tower of four";
       if (ach==4) "seeing which way the mantelpiece leans";
     ];
     





Normally, an Inform game will print messages like

     [Your score has gone up by three points.]
     
when the score changes (by whatever means).  The player can turn this on and
off with the ''notify'' verb; by default it is on.  You can alter the flag
notify_mode yourself to control this.








Sometimes you want to ask the player a yes/no question.  If so, call
YesOrNo(), a library routine: it returns true/false accordingly (and
doesn't print any question, which is up to you).  This saves a lot of
bother programming the parser.



  ** **   Occasionally you need to rewrite one of the library routines.
But the danger of doing so is that it is then necessary to keep a copy
of the library for every game, which is clearly unsatisfactory.  So:
for example, if the directive

     REPLACE BurnSub;
     
is placed in your file  before the library files are included,
Inform ignores the definition of BurnSub in the library files.
(You then have to define a routine called BurnSub yourself, or Inform
will complain that the program refers to a routine which isn't there.)
And this is the very last resort, and so the end of the manual proper.



+-----------------------------------------------------------------------------+
|                       22  Debugging verbs and tracing                       |
+-----------------------------------------------------------------------------+




     If builders built buildings the way programmers write programs,
     the first woodpecker that came along would destroy civilisation.
     
         - old computing adage



The two problems with debugging a game are working out exactly what it's
doing, and making things happen which wouldn't normally be allowed (such
as giving yourself the trident now rather than playing for two hours to
find it).

Inform provides a small suite of debugging verbs to help with this, but
only if the game defines the constant DEBUG before including the library
files.  (Just in case you forget to take this out again, the letter D
appears in the game banner to indicate this.)

You then get the following verbs, which can be used at any time in play:

     purloin <anything>
     abstract <anything> to <anything>
     tree       tree <thing>
     goto <number>
     actions    actions on    actions off
     routines   routines on   routines off
     timers     timers on     timers off
     trace      trace on      trace off    trace <1 to 5>
     
You can ''purloin" any item or items in your game at any time, wherever
you are.  You can likewise ''abstract" any item to any other item (meaning:
move it to the other item).  To get a listing of the objects in the game
and how they contain each other, use ''tree", and to see the possessions of
one of them alone, use ''tree <that>".  Finally, you can go to any object:
but since rooms don't have names understood by the parser, you have to give
the object number of the place you want to go to.  (The ''tree" listing will
tell you these numbers.)


Turning on ''actions" gives a trace of all the actions which take place in
the game (the parser's, the library's or yours); turning on ''routines"
traces every object routine (such as before or life) that is ever
called, except for short_name (as this would look chaotic, especially on
the status line).  Turning on ''timers'' shows the state of all active timers
and daemons each turn.





Infix, Dilip Sequeira's source-level debugger for Inform, is currently
in an advanced state of preparation: it is an enhanced form of Mark Howell's
Zip interpreter providing for breakpoints, tracing and so forth.  It
should fairly soon be publically archived with the rest of the Inform project.



  **   For Infix's benefit, Inform (if compiling with the option set) produces
a file of ''debugging information'' (cross-references of the game file with
the source code), and anyone interested in writing an Inform utility program
may want to know the format of this file: see the short C program Infact
which prints out the debugging information file in English.

On most interpreters, though, run-time crashes are mysterious (because they
were written on the assumption that all existing Infocom game files were free
from error).  Zip is rather more generous and will usually tell you why and
where the problem is; given a game file address you can work back to the
problem point in the source either with Mark Howell's txd (disassembler)
or by running Inform with the assembler trace option on.

Here are all the ways I know to crash an interpreter at run-time (with
high-level Inform code, that is; if you insist on using
assembly language or the indirect function you're raising the stakes),
arranged in decreasing order of likelihood:


    (o)       Writing to a property of an object which it hasn't got;

    (o)       Dividing by zero, possibly by calling random(0);

    (o)       Giving a string or numerical value for a property which can
only legally hold a routine, such as before, after or life;

    (o)       Applying parent, child or children to the nothing
object;

    (o)       Using print object on the nothing object, or for some
object which doesn't exist (always use the routines DefArt, CDefArt or
PrintShortName as appropriate, which are safeguarded and anyway
implement higher-level features);

    (o)       Using print_addr or print_paddr to print from an address
outside the memory map of the game file, or an address at which no string
is present (this will result in random text appearing, possibly including
unprintable characters, which may conceivably crash your terminal);


    (o)       Setting the location variable to zero, or some non-existent
object, since the interpreter prints the name of this object on the
status line;
in any case it is safer to use PlayerTo than to meddle directly with this;

    (o)       Running out of stack space in a recursive loop (though this
has never actually happened to anyone I know of).



  **  
There are times when it's hard to work out what the parser is up to and why
(actually, most times are like this).  The parser is written in levels, the
lower levels of which are murky indeed.  Most of the interesting things
happen in the middle levels, and these are the ones for which tracing is
available.  The levels which can be traced are:


      Level 1             Grammar lines
      Level 2             Individual tokens
      Level 3             Object list parsing
      Level 4             Resolving ambiguities and making choices of object(s)
      Level 5             Comparing text against an individual object

''trace" or ''trace on" give only level 1 tracing.  Be warned: ''trace five"
can produce reams of text when you try anything at all complicated: but you
do sometimes want to see it, to get a list of exactly everything that is in
scope and when.  There are two levels lower than that but they're too busy
doing dull spade-work to waste time on looking at parser_trace.  (There's
also a level 0, but it consists mostly of making arrangements for level 1,
and isn't very interesting.)



  ** **  
Finally, though this is a drastic measure, you can always compile your game
-g ('debugging code') which gives a listing of every routine ever
called and their parameters.  This produces an enormous mel'ee of output. 
(In Inform 5.3, though not earlier versions, you can declare a routine with
an asterisk * as its first local variable, which produces such tracing only
for that one routine.)



+-----------------------------------------------------------------------------+
|                   23  Limitations on the run-time format                    |
+-----------------------------------------------------------------------------+




     How wide the limits stand
     Between a splendid and an happy land.
     
         - Oliver Goldsmith (1728-1774),  The Deserted Village




The Infocom run-time format is well-designed, and has three major
advantages: it is compact, widely portable and can be quickly executed.
Nevertheless, like any rigidly defined
format (which it clearly must be), it imposes limitations.  These are not
by any means pressing.  Inform itself has a flexible enough memory-management
system not to impose artificial limits on numbers of objects and the like.

There are two sizes of game available: Standard (or version 3) and Advanced
(or version 5).  Always use the latter if you can; it is very much to be
preferred.  (There are very slight risks associated with exotic
assembly-language coding in Advanced games: but unless you deviate far
from normal Inform practice, and code on a very low level, these will never
trouble you.)  There are still 8-bit computers in use which are too small
for Advanced games, but most people should have no problem.




 Memory.    The total size of a Standard game is at most 128K; of an
Advanced game, 256K.  Because games are encoded in a very compressed form,
and because the centralised library of Inform makes the compiler fairly
efficient in terms of not duplicating code, even 128K allows for a game
at least half as large again as a typical old-style Infocom game.  No game
yet written under Inform has reached the 256K mark, not even the final
version of 'Curses' (at 224K, already substantially bigger and denser than
any Infocom game).




 Vocabulary.    There is no theoretical limit, and vocabularies
in excess of 2000 are quite sensibly possible.  (A typical large game will
muster 1000.)




 Dictionary resolution.    In Standard games, dictionary words are
truncated to their first 6 letters, which can be a nuisance; in Advanced,
9 letters, which never is.




 Attributes, properties, names.    Standard games only provide
32 attributes, 30 properties and at most 8 bytes of data per property:
the library consumes most of this ration, and the 8 bytes restriction
means that an object can only have four words in its name.  This is
perfectly manageable, if unsatisfactory.  Advanced games, which provide 48
attributes, 62 properties and 64 bytes of data (hence 32 names), effectively
make none of these restrictions serious.




 Special effects.    Standard games cannot have special effects such
as bold face and underlining.  (See the next two sections.)




 Objects.    Standard games can have at most 255 objects, enough for
a large Infocom-size game but not much more.  Advanced games have no such
restriction, the number being in principle unlimited.  Objects cannot
dynamically be created or destroyed, but this is imitated easily enough.




 Global variables.    There can only be 240 of these, and the Inform
compiler uses 5 as scratch space, while the library uses slightly over 100;
but since a typical game uses only a dozen of its own, code being almost
always object-oriented, the restriction is never even nearly felt.  (Recall
that arrays take only one global each.)




 ''Undo''.    Standard games do not provide an ''undo'' verb,
but Advanced ones (or rather, the Inform library when compiled on such)
do.








  **   There is a yet larger Infocom format, version 6, which lifts even the mild
restrictions of version 5 games, with memory maps of up to
600K or so: version 6 has only recently been fully deciphered, but Inform is
already capable of producing such files, and Mark Howell's ''Zip''
interpreter is (at time of writing) making good progress in running them.
A 600K Inform game would be gargantuan: by the time one comes along, there
should be no problem in running it.



  ** **    Having said all this, if memory does become short, there is a
standard mechanism for saving about 8-10% of the memory.  Inform does
not usually trouble to, since there's very seldom the need, and it makes
the compiler run about 10% slower.  What you need to do is define
abbreviations.  For instance, the directive

     Abbreviate " the ";
     
(placed before any text appears) will cause the string '' the '' to be
internally stored as a single 'letter', saving memory every time it occurs
(about 2500 times in 'Curses', for instance).  You can have up to 64
abbreviations.  A good list of abbreviations can be found in the
 Technical Manual: basically, avoid proper nouns and instead pick on short
combinations of a space and common two- or three-letter blocks.  You can
even get Inform to work out by itself what a good stock of abbreviations
would be: but be warned, this makes the compiler run about 29000% slower.



+-----------------------------------------------------------------------------+
|                  24  A very few, not very special effects                   |
+-----------------------------------------------------------------------------+




     Yes, all right, I won't do the menu... I don't think you realise
     how long it takes to do the menu, but no, it doesn't matter, I'll
     hang the picture now.  If the menus are late for lunch it doesn't
     matter, the guests can all come and look at the picture till they
     are ready, right?
     
         - John Cleese and Connie Booth,  Fawlty Towers



As the previous section suggested, some special effects are not to be
encouraged: they reduce portability a little, and anyway Inform is for
text games.

The status line is perhaps the most distinctive feature of Infocom games in
play.  This is the (usually highlighted) bar across the top of the screen. 
Usually, the game automatically prints the current game location, and either
the time or the score and number of turns taken.  It has the score/turns
format unless the directive

     Statusline time;
     
is present, in which case it shows the game's 24-hour clock.



  ** **   If you  really want to change this, then Replace the parser's
private DrawStatusLine routine.  But be sure to test the result on more
than one interpreter, in case you've made a mistake which doesn't show up on
one quirky implementation.  (In any case, you can only change it at all on
Advanced games.)



** ** Exercise:    Alter the 'Advent' example game to display the number
of treasures found instead of the score and turns on the status line.



Answer:  First put the directive Replace DrawStatusLine; before including
the library.  Then add the following routine anywhere after treasures_found,
an 'Advent' variable, is defined:

     [ DrawStatusLine;
        @split_window 1; @set_window 1; @set_cursor 1 1; style reverse;
        spaces (0->33)-1;
        @set_cursor 1 2;  PrintShortName(location);
        if (treasures_found > 0)
        {   @set_cursor 1 50; print "Treasure: ", treasures_found;
        }
        @set_cursor 1 1; style roman; @set_window 0;
     ];
     

About character graphic drawings: on some machines, text will by default
be displayed in a proportional font (i.e. one in which the width of a letter
depends on what it is, so that for example an 'i' will be narrower than an
'm').  If you want to display a diagram made up of letters, such as a map,
you will have to turn this off, for which the font command is provided.
Write font off before printing character graphics, and remember to
write font on again afterwards.



  !!   Don't turn the font on and off in the middle of a line; this
doesn't look right on some machines.

A distinctive feature of later Infocom games was their use of epigrams.
Inform can do this, too, but only for Advanced games.  The
assembly language required is easy but a nuisance, so there is a command
to do it, box.  For example,

     box "Beware of the Dog";
     
or

     box "I might repeat to myself, slowly and soothingly,"
         "a list of quotations beautiful from minds profound;"
         "if I can remember any of the damn things."
         ""
         "-- Dorothy Parker";
     
Note that a string of lines is given (without intervening commas) and
that a blank line is given by a null string.  Remember that the text
cannot be too wide or it will look awful on a small screen.

The author takes the view that this device is amusing for irrelevant
quotations but irritating when it conveys vital information (such as,
''Beware of the Dog", for instance).  Also, some people might be running
your game on a laptop with a vertically challenged screen, so it is
polite to provide a ''quotes off'' verb.




Sometimes one would like to provide a menu of text options (for instance,
when producing instructions which have several topics, or when giving
clues).  This can be done with the DoMenu routine, which imitates
the traditional ''Invisiclues'' style.  However, it only looks good
for Advanced games; for Standard games, it's simply textual.  (In an
Advanced game, by setting pretty_flag=0 you can get this simple text
version instead; which is a good idea for machines with very small
screens.)

Here is a typical call to DoMenu:

     DoMenu("There is information provided on the following:^\
             ^     Instructions for playing\
             ^     The history of this game\
             ^     Credits^",
             #r$HelpMenu, #r$HelpInfo);
     
Note the layout, and especially the carriage returns.  The second and
third arguments are themselves routines: the notation #r$, seldom
seen in high-level Inform, allows routine names to become ordinary
numerical values.  The first routine, in this case called HelpMenu,
is supposed to look at the variable menu_item.  In the case when this
is zero, it should return the number of entries in the menu (3 in the
example).  In any case it should set item_name to the title for the
page of information for that item; and item_width to half its length
in characters (this is used to centre titles on the screen: it is
unfortunately tricky for the game to compute the length of a static
string, so you have to tell it).
In the case of item 0, the title should be that for the whole menu.

The second routine, HelpInfo above, should simply look at menu_item
(1 to 3 above) and print the text for that selection.  After this returns,
normally the game prints ''Press [Space] to return to menu'' but if
the value 2 is returned it doesn't wait.

Menu items can safely launch whole new menus, and it is easy to make
a tree of these (which will be needed when it comes to providing hints
across any size of game).



Exercise:   Code an ''Invisiclues''-style sequence of hints for a puzzle,
revealed one at a time, as a menu item.



Answer:  Note the magic line of assembly code here, which only works for
Advanced games:

     [ GiveHint hint keypress;
       print_paddr hint; new_line; new_line;
       @read_char 1 0 0 keypress;
       if (keypress == 'H' or 'h') rfalse;
       rtrue;
     ];
     
And a typical menu item using it:

      if (menu_item==1)
      {   print "(Press ENTER to return to menu, or H for another hint.)^^";
          if (GiveHint("(1/3)  What kind of bird is it, exactly?")==1) return 2;
          if (GiveHint("(2/3)  Magpies are attracted by shiny items.")==1) return 2;
          "(3/3)  Wave at the magpie with the kitchen foil.";
      }
     





Finally, though it should only be used sparingly (and again is restricted
to Advanced games), one can change the text style.  The command for
this is style and its effects are loosely modelled on the VT100
(design of terminal).  The style can be style roman, style bold,
style reverse or style underline.  Again, remember that poor terminals
may not be able to display these, so you shouldn't hide crucial information
in them.



+-----------------------------------------------------------------------------+
|                              25  Dirty tricks                               |
+-----------------------------------------------------------------------------+





  ** **   The dirtiest tricks of all are those which bypass Inform's higher
levels and program the Z-machine directly.  There is an element of danger in
assembly language programming, in that some combinations of unusual opcodes
can look ugly on some incomplete or wrongly-written interpreters: so if you're
doing anything complicated, test it as widely as possible.
Note that none of the interesting effects work at all on Standard games,
only Advanced games.



The best-researched and most reliable interpreter available by far is Mark
Howell's Zip; as it's also the fastest, it will hopefully 'take over' entirely.
Next comes the InfoTaskForce, which is thorough and should give no serious
trouble, but was written when the format was a little less well understood,
and so (in some ports) gets some (rare) screen effects wrong.  (It also lacks
an ''undo'' feature, so the ''undo'' verb automatically provided by the library
routines won't work under ITF.)  The other two publically-available
interpreters are pinfocom and zterp, but these are unable to run Advanced
games.  In the last resort, sometimes it's possible to use one of Infocom's
own supplied interpreters with a different game from that it came with; but only
sometimes, as they may have inconvenient filenames 'wired into them'.  The
author recommends that anyone using assembly-language features get hold of
both ITF and Zip, and test on both.

This all sounds rather unportable, though actually the core described below
is pretty reliable.  But remember that the unportability does have some genuine
cause.  Your game may be running on a screen which is anything from a 64 by 9
pocket organiser up to a 132 by 48 X-window.

Anyone wanting to really push the outer limits (say, by implementing
Space Invaders or NetHack) will need to refer to  The Specification
of the Z-Machine, which also documents Inform assembly language format.





Screen tricks are the commonest.  An upper-level screen (which usually holds
the status line) can be split off from the main screen:

     split_window n;
     
creates one which is $n$ lines tall.  (This doesn't change the display, and
it can be resized at any time: but it needs to be tall enough to include all
the lines you want to write to, as otherwise the interpreter may flounder:
some will scroll the upper window, others won't.)  The
main screen is numbered 0, and the upper one 1; text output is switched between
them by

     set_window n;
     
The lower window is just a text stream whose cursor position cannot be set: on
the other hand, when it is returned to, the cursor will be where it was before
it was left.  Within the upper window, the cursor can be moved by

     set_cursor line column;
     
where $(1,1)$ is the top left character.  Printing on the upper window
overlies printing on the lower, is always done in a fixed-space font
and does not appear in a printed transcript of the game.
However, before printing to the upper window, it is essential to
change the printing format - that is, the buffer_mode opcode.  Before
printing, execute

     buffer_mode 0;
     
and when returning to the normal screen,

     buffer_mode 1;
     
Otherwise, dodgy interpreters (like ITF) may continue trying to split
lines at word breaks, and make a horrid mess.




A convenient way to clear the screen is

     erase_window $ffff;
     
but don't chance this in reverse video mode!  (And don't assume that erase_window
can erase individual windows - it should, but may not on bad interpreters.)




Players can be gratuitously annoyed (on most machines, anyway) by the beep opcode.
This is the only remotely portable sound effect.




The keyboard can be read in remarkably flexible ways, using the aread and
read_char opcodes.

     aread text parse time function;
     
will read from the keyboard, putting text into the text buffer, tokenising
it onto the end of the parse buffer (unless this is zero), and calling

     function(time);
     
every time seconds that the user is thinking: the process ends if ever this
function returns true.  Thus (by Replaceing the Keyboard routine in the
library files) you could, say, move around all the characters every ten seconds
of real time.

     read_char 1 time function <result>;
     
where <result> is a variable, will store in that variable the ASCII value
of a single keypress.  Once again, the function is called every time seconds
and may stop this process early.  Function keys return special values from 129
onwards, in the order: cursor up, down, left, right, function key f1, ..., f12,
keypad digit 0, ..., 9.




Leafing through the dictionary of opcodes will reveal a few other interesting
features.  It's possible to change the input and output streams which, although
only Zip gets this right, may be convenient for debugging purposes (creating
scripts of all typed commands, for example).  Finally, there are opcodes which
tokenise (that is, simply compare dictionary entries against) arbitrary
strings from arbitrary dictionaries, and which translate small doses of ASCII
to internal Z-machine string format.  Actually, one can avoid the need for this
in many cases, by programming the parser correctly: see, for instance,
the 'Balances' game which manages without these features.





+-----------------------------------------------------------------------------+
|                           A1  The Inform language                           |
+-----------------------------------------------------------------------------+


This is going to be a long appendix, full of lists and tables: but it has
to appear somewhere, if only for reference.  (Some technical commands
for internal use only are skipped over: see the  Technical Manual for
details of these.)



File format

When Inform reads in a file, it treats a few characters in special ways.
The character ! means the rest of the line (up to the next new-line) is
a comment, and Inform throws it away.  Tab characters are treated as
spaces.  Backslashes \ fold strings together, so that the new-line and
all subsequent spaces are ignored.  New-lines have no significance;
statements (and directives) are separated by semicolons ;.



Directives

These are commands directly to the Inform compiler, like Object.  They
can, but need not, be prefaced by a hash character, #.  The directives
which Inform understands are:


     Abbreviate <string>              Declare an abbreviation
     Attribute <name>              Make a new attribute
     Class ...              Define a new class
     Constant <name> <value>               Define a named constant
     End               End compilation here
     Endif               End of conditional compilation
     Extend ...              Extend the grammar for an existing verb
     Fake_action <name>               Make a new ''fake action''
     Global <name> ...               Declare a global variable
     Ifdef <name>              Compile only if constant is defined
     Ifndef <name>              Compile only if constant is undefined
     Ifnot              Compile only if previous If... failed
     Ifv3              Compile only for Standard games
     Ifv5              Compile only for Advanced games
     Include <filename>               Include that file here
     Nearby              Make an object inside the last Object
     Object              Make an object
     Property <name> ...              Make a new property
     Replace <routine>              Don't compile this library routine
     Release <number>              Set the game's Release Number
     Serial <string>              Set the game's Serial Number
     Statusline ...              Make the status line show score or time
     Switches <switches>              Set default compilation switches
     Verb ...              Declare the grammar for a new verb


The release number of a game (by default 1) is generally an edition
number; the serial number is the compilation date in the form
940924, that is, yymmdd.  Inform sets this automatically on machines
where the date is accessible, so the Serial directive is provided
only for use on machines without such an internal clock.



  **   Conditional compilation allows code for routines which need only
exist in some ''versions" of your games.  For instance,


       print "Welcome to the ";
       #IFV3; print "Standard"; #IFNOT; print "Advanced"; #ENDIF;
       print " version of Zork LVI.";
     
(The #IFNOT clause is optional.)  Note the trailing semicolon: Inform
is not C!  Such clauses may be nested up to 32 deep, and may contain whole
routines.  They may not, however, conditionally give  part of a
statement.  Thus, for instance,

       print #IFV3; "Standard"; #IFNOT; "Advanced"; #ENDIF;
     
is  not legal.



  ** **   The following directives are recondite and not for public use:

     Default Dictionary Listsymbols Listdict Listverbs Lowstring Stub System_file
     Trace Btrace Etrace Ltrace Notrace Nobtrace Noetrace Noltrace
     


Variables and arrays

There are two kinds of variable, global and local (plus one special one).
Variables are all two-byte integers, which are treated as signed when it
makes sense to do so (e.g. in asking whether one is positive or not) but
not when it doesn't (e.g. when it is used as an address).
Global variables must be declared before use, by the Global directive:


     Global <varname> = <initial-value>
                         data <size>
                         string <size>
                         initial <value-1> ... <value-$n$>
                         initstr <text>
     
For instance:

     Global turns = 1;
     Global buffer string 120;   ! text buffer holding 120 characters
     Global task_scores initial 4 5 9 1 2 3 0;  ! a 7-byte array
     Global players_name initstr "Graham";  ! an array of 6 chars
     
When you declare a variable as an array (by data, string, initial
or initstr)
what actually happens is that Inform allocates as much space as you ask
for, somewhere inside the machine, and stores the address of this array
in the variable.  You can get at entries of the array by

     buffer->entry    buffer-->entry
     
which read (or write to) the entry-th byte (in the case of ->) or
word (for -->).  A data array is initially full of zeros, while an
initial array contains the given (byte) values, which all have to be
constants for obvious reasons.  A string array is a special kind of
data array: the first byte contains its length (in bytes), and the
rest are initially zero.  initstr is the same but initialised to
the given string.  The text here is plain ASCII, and is not encrypted
as constant strings tend to be.  (This string format is used by the
parser.)

In addition, a routine can have from none up to 15 local variables.



  !!   There is also a stack, but it should be tampered with only
carefully in times of dire need.  Never call a variable sp, as this is the
stack pointer, and if you must use the stack at all, be careful not to
leave values on it: or your game may crash 1000 turns later, serving you
right.


Constants

Inform constants can take many forms.  The obvious ones are numbers,

     123   $ee05   $$11011001
     
being examples in decimal, hexadecimal and binary respectively.  There
are also


     ##Action           (The number of) the given action
     "some text"           (The packed address of) the given string
     'c'           (The ASCII code for) the given character
     'word'           (The byte address of) its dictionary entry


There is slight potential for confusion here: 'A' evaluates to 65,
but 'an' to the dictionary address of the word 'an'.  Note that
the construction 'sponge' actually enters the word 'sponge' into
the dictionary if it wasn't already there.  These are all legal
constants:

     31415  -1  $ff  $$1001001  'lantern'  ##Look  'X'
     "an emerald the size of a plover's egg"
     "~Hello,~ said Peter.^~Hello, Peter,~ said Jane.^"
     


Quoted strings

Inside the text of a string, the character ^ is replaced by a new-line
character, and the character ~ by a double-quote mark: these both make
strings much easier to type.

Inside a string (under Inform 5.3 or later) @@<number> produces the
character whose ASCII value is $n$, and you can use this to get untypeable
characters from foreign character sets.  (Or, for example, a literal
backslash, by @@92.)

For the @ string escape and other obscure constant forms such as
#r$, see the  Technical Manual.


Routines

Routines start with a [ and end with a ].  That is, they open with

     [ <Routine-name> <local-var-1> ... <local-var-$n$>;
     
giving the names of local variables for the routine ($0 <=  n <=  15$).
The routine ends with just ];.  (Routines embedded in object definitions
are the same, except that no routine-name is given, and they may end in
], if the object definition continues.)

The first few local variables also hold the arguments passed to the
routine when the function is called.  That is, if you have a routine

       [ Look from i j; ...some code...; ];
     

and it is called by Look(attic); then the local variable from will
initially have the value attic.  The rest all start out at zero.

From Inform 5.3, if the first variable is given as * then
tracing code is compiled to print details each time the routine
is called.

Function calls (that is, calls to routines) are legal with between 0
and 3 arguments, and every routine always returns a value.  If execution
runs into the ]; at the bottom, that value is 'true' (or 1) for an
ordinary routine, or 'false' (or 0) for an embedded one.


Labels


In case you want to jump around inside a routine, you can define labels
with a statement starting with a full stop, like .labelname;.  It is
legal, though ill-advised, to jump out of one routine and into another.
Label names are global, so the same label name can't be used in two
different routines.


Operators

Arithmetic (and other) expressions can contain the following:


  +  -           plus, minus
  * / % & |      times, divide, remainder, bitwise and, bitwise or
  ->  -->        byte array, word array entry
  .  .&  .#      property, property address, property length
  -              unary minus
  ++  --         incrementing and decrementing variables (as in C)


The order of precedence is as shown: i.e. those on each line are equally
potent, more potent than those above but less than those beneath.
Expressions are not allowed to contain conditions, nor assignments:
2+(i=3/j) is not a legal expression.  Some legal examples:

     4*(x+3/y)   Fish(x)+Fowl(y)  lamp.time   buffer->5
     
Note that ++ and -- can only be applied to variables, not to
properties or array entries.


Assignments

There are four forms allowed are:

     <variable> = <value>;
     <byte-array>-><entry> = <value>;
     <word-array>--><entry> = <value>;
     <object>.<property> = <value>;
     
For example:

     i=-15-j;   i=j-->1;   albatross.weight = albatross.weight + 1;
     (paintpot.&roomlist)-->i = location;   turns++;
     
One can also inc or dec (increment or decrement) a variable,
with inc score; being equivalent to the more modern score++;

Although these look logical, they are not allowed:

     paintpot.#roomlist = 5;
     paintpot.&roomlist = array;
     
because one cannot change the size or address of a property in play.



  !!   A division by zero error (such as $n$/0 or $n$%0)
may crash the game at run time.



  !!   Attempting to write to a property which an object does not
have may crash the game at run time.


Conditions

A simple condition is

     <a>   <relation>   <b>
     
where the relation is one of


     ==          a equals b
     ~=          a doesn't equal b
     < > >= <=          numeric (signed) comparisons
     has          object a has attribute b
     hasnt          object a hasnt attribute b
     in          object a is currently held by object b
     notin          ...is not...

With == (and ~=) only, one may also write the useful construction

     <something> == <v1> [or <v2> [or <v3>]]
     
which is true if the first something is any of the values given.  (An
idiosyncracy of Inform, for 'hardware reasons', is that you can only have
three).  Conditions can be combined by the && and || operators:

     <condition1> && <condition2>
     <condition1> ||  <condition2>
     
true if both, or either (respectively) are true.  These are always tested
left to right until the outcome is known.  So, for instance,

     i==1  ||  Explode(2)==2
     
does not call Explode if i is 2.  Examples of legal conditions are:

     i==1 or 2 or 3
     door has open || (door has locked && key in player)
     


Built-in functions

A very few functions are built into the language of Inform itself
(rather than written out longhand in the library files), but they
behave like any other routines.  They are:


     parent(obj)          parent of object
     sibling(obj)          sibling of object
     child(obj)          eldest child of object
     children(obj)          number of (direct) children of object
     eldest(obj)          same as child
     youngest(obj)          youngest child of object
     elder(obj)          elder sibling of object
     younger(obj)          same as sibling
     random(x)          uniformly random number between 1 and $x$
     indirect(addr)          call routine with address addr





  !!   random(0) may cause a division by zero error.


Printing commands

A string on its own, such as

     "The world explodes in a puff of garlic.";
     
is printed, with a new-line, and the current routine is returned from with
return value 'true', i.e., 1.  In addition:


     new_line          prints a new-line
     print ...          prints the given things
     print_ret ...          prints, new-lines and returns 1
     spaces n          prints $n$ spaces
     print_addr a          print string at byte address a
     print_paddr a          print string at packed address a
     font on/off          turns proportional fonts on/off
     style ...          in Advanced games, sets text style
     box "s1" ... "sn"          in Advanced games, puts up quotation box
     inversion          prints out the current Inform version number


print and print_ret take a comma-separated list of things to print out,
which can be: "strings", char n (print the character with this ASCII
value) or variable (print out the variable as a signed number).  The
text style can be any of

     roman  reverse  bold  underline
     


Manipulating objects



     remove obj          removes object from the tree
     move o1 to o2          moves o1 to become youngest child of o2
     give obj a1 ... an          gives attributes to obj


Attributes beginning with a ~ are taken away rather than given.


Returning from routines



     return          Return true, i.e. 1
     return x          Return value $x$
     rtrue          Return true, i.e. 1
     rfalse          Return false, i.e. 0



Blocks of code

A block of code may be a single instruction or a series of several, in which
case it must be enclosed in braces { and }.  Thus, for instance, in

     if (i==1) print "The water rises!";
     if (i==2) { print "The water rises further...";
                 water++;
               }
     
the if statements contain a block of code each.  Blocks can be nested
inside each other up to 32 deep.  An if statement (for example) is a
single statement even when it contains a great deal of code in its
block: so, for example,

     if (i>1) if (water<10) "The water is beginning to worry you.";
     
is legal.  (One small exception: an if followed by an else
counts as two statements, and this means Inform handles hanging elses
rather poorly: so it's wise to brace so that else is clearly unambiguous.)


Control constructs
 Inform provides:

     if <condition> <block1> [else <block2>]
     while <condition> <block>
     do <block> until <condition>
     for (<initialise>:<test>:<each time>)
     objectloop (<variable> in <object>)
     objectloop (<variable> from <object>)
     objectloop (<variable> near <object>)
     break
     jump <label>
     
Some of these will be familiar to most.  The for construct is essentially
the same as that in C, except for the colons : (which in C would be
semicolons).  Its carries out the initial assignment(s), then executes the
code for as long as the condition holds, executing the end assignment after
each pass through the code.  For instance,

     for (i=1:i<=10:i++) print i, " ";
     
counts to 10.  All three clauses are optional, and the empty condition is
always true; multiple assignments can be made.  For instance:

     for (i=0,j=10:i<10:i++,j--) print i, " + ", j, " = ", i+j, "^";
     for (::) print "Ha!^";
     
the latter laughing maniacally forever.

break breaks out of the current loop (not quite the same as breaking out
the current block of code: if statements don't count as loops in this
regard).

objectloop goes through the object tree, and is extremely useful.  from
means from the given object through its siblings; in means through all
children of the given object, and near means through all children of the
parent of the object.  For instance, the following do the same thing:

     objectloop (x in lamp) { ... }
     for (x=child(lamp): x~=0: x=sibling(x)) { ... }
     
Note that the library creates a variable called top_object holding the
highest existing object number: so a way to loop over every object
defined in your own code is

     for (i=player+1: i<=top_object: i++) ...
     
since player is always set to selfobj, which is the last object created
by the library.



  !!   When looping through the object tree, be careful if you are altering
it at the same time.  For instance,

     objectloop (x in rucksack) remove x;
     
is likely to go horribly wrong - it's safer not to cut down a tree
while actually climbing it.  The safe way is to keep lopping branches off,

     while (child(x)~=0) remove child(x);
     



Exercise:   Write a routine to print out prime factorisations of numbers from
2 to 100.



Answer:  Primes(100), where:
     [ Primes i j k l;
       for (j=2:j<=i:j++)
       {   print j, " : "; l=j;
           while (l > 1)
           for (k=2:k<=l:k++)
               if (l%k == 0) { l=l/k; print k, " "; break; }
           new_line;
       }
     ];
     
(which was the first algorithm ever compiled by Inform).


Actions

The commands

     < <Action> [<first-object> [<second-object>]] >
     << <Action> [<first-object> [<second-object>]] >>
      
cause the given actions to take place.  In the latter case, the current
routine then returns 1, or true.








+-----------------------------------------------------------------------------+
|               A2  Library objects, properties and attributes                |
+-----------------------------------------------------------------------------+




     A Model must be built which will get everything in without
     a clash; and it can do this only by becoming intricate,
     by mediating its unity through a great, and finely ordered,
     multiplicity.
     
         - C. S. Lewis (1898-1963),  The Discarded Image



The library defines the following
special objects:



 compass    To contain the directions.  A direction
object provides a door_dir property, and should have the
direction attribute.  A compass direction with enterable, if
there is one (which there usually isn't), will have an
Enter action converted to Go.

 n_obj    Both the object signifying the
abstract concept of 'northness', and the 'north wall' of
the current room.  (Thus, if a player types ''examine the north wall''
then the action Examine n_obj will be generated.)  Its
door_dir property holds the direction property it corresponds
to (n_to).


 s_obj, e_obj, w_obj, ne_obj, nw_obj, se_obj,
sw_obj    Similar.

 u_obj, d_obj, in_obj, out_obj     Similar:
the parser uses these if the player refers to ''ceiling'',
''floor''.  (in_obj and out_obj differ slightly, because
''in'' and ''out'' are verbs with other effects in some cases.)

 thedark    A pseudo-room representing 'being in
darkness'.  location is then set to this room, but the player
object is not moved to it.  Its description can be changed to
whatever ''It is dark here'' message is desired.

 selfobj    The player object.  However, do not
refer to selfobj directly: always refer to player, a variable
whose value is usually indeed selfobj but which might become
green_frog if the player is transformed into one.




Here is a concise account of all the normal rules concerning
all the library's attributes.  (Except that: rules about how
the parser sorts out ambiguities are far too complicated to
include here, but should not concern designers anyway; and the
definitions of ''scope'' and ''darkness'' are given in the
main text.)  Of course these rules are all modifiable using
suitable before and after rules.  But a good deal of
pragmatism has gone into their design, or rather evolution.





 absent    A 'floating object' (one with a
found_in property, which can appear in many different rooms)
which is absent will no longer appear in the game.

 animate    'Is alive (human or animal)'.  Can be
spoken to in ''richard, hello'' style; matches the creature
token in grammar; picks up ''him'' or ''her'' (according to
gender) rather than ''it'', likewise ''his''; an object the
player is changed into becomes animate; some messages read
''on whom'', etc., instead of ''on which''; can't be taken;
its subobjects ''belong to'' it rather than ''are part of'' it;
messages don't assume it can be ''touched'' or ''squeezed'' as
an ordinary object can; the actions Attack, ThrowAt are
diverted to life rather than rejected as being 'futile
violence'.

 clothing    Can be worn.

 concealed    'Concealed from view but present'.
The player's object has this; an object which was the player until
ChangePlayer happened, loses this property; a concealed
door can't be entered; does not appear in room descriptions.

 container    Affects scope and light (see definitions
in the main text); object lists recurse through it if open (or
transparent); may be described as closed, open, locked, empty;
a possession will give it a LetGo action if the player tries to
remove it, or a Receive if something is put in;
things can be taken or removed from it, or inserted into it,
but only if it is open; likewise for ''transfer'' and ''empty'';
room descriptions describe using when_open or when_closed if
given; if there is no defined description, an Examine causes the
contents to be searched (i.e. written out) rather than a message
''You see nothing special about...''; Search only reveals the
contents of containers, otherwise saying ''You find nothing''.

 direction    If the player tries to walk this way
or enter it, a Go rather than Enter action is generated.
(Used only in one line of grammar, but a crucial one.)

 door    'Is a door or bridge'.  Room descriptions
describe using when_open or when_closed if given; and an Enter
action becomes a Go action.  If a Go has to go through this
object, then: if concealed, the player 'can't go that way';
if not open, then the player is told either that this cannot
be ascended or descended (if the player tried ''up'' or ''down''
which went through it), or that it is in the way (otherwise);
but if neither, then its door_to property is consulted to
see where it leads; finally, if this is zero, then it is said
to 'lead nowhere' (a safety precaution) and otherwise the player
actually moves to the location.

 edible    Can be eaten (and thus removed from game).

 enterable    Affects scope and light (see definitions
in the main text); only an enterable on the floor can be entered.

 female    Only applies to animates (and cannot have
a found_in list for arcane reasons), and only affects the parser's
use of pronouns: it says ''her'' is appropriate but ''him'' and ''his''
are not.

 general    A general-purpose attribute, defined by
the library but never looked at or altered by it.  This is left
free to mean something different for each object: often used by
programmers for something like ''the puzzle for this object has been
solved''.

 light    'Is giving off light.'  (See definition of
'when there is light' in main text.)  Also: the parser understands
''lit'', ''lighted'', ''unlit'' using this; inventories will
say ''(providing light)'' of it, and so will room descriptions if the
current location is ordinarily dark; it will never be automatically
put away into the player's SACK_OBJECT (as it might plausibly be
inflammable or the main light source).

 lockable    Can be locked or unlocked by a player
holding its key object, which is in the property with_key;
if a container and also locked, may be called ''locked'' in
inventories.

 locked    Can't be opened.   If a container
and also locked, may be called ''locked'' in inventories.

 moved    'Has once been held by the player'.  Objects
(immediately) owned by the player after Initialise has run are given
it; at the end of each turn, if an item is newly held by the player
and is scored, it is given moved and OBJECT_SCORE points are
awarded; an object's initial message only appears in room
descriptions if it is unmoved.

 on      'Switched on.'  A switchable object with this
is described by with_on in room descriptions; it will be called
''switched on'' by Examine.


 open    'Open door or container'.  Affects scope and
light (see definitions in the main text), and: lists (such as inventories)
recurse through an open container; if a container, called open by some
descriptions; things can be taken or removed from an open container;
similarly inserted, transferred or emptied.  An open door can be
entered.  Described by when_open in room descriptions.

 openable    Can be opened or closed, unless locked.

 proper    Its short name is a proper noun, and never preceded
by ''the'' or ''The''.  The player's object must have this (so something
changed into will be given it).

 scenery    Not listed (by the library) in room descriptions, 
''not portable'' to be taken; ''you are unable to'' pull, push, or turn it.

 scored    The player gets OBJECT_SCORE points for picking
it up for the first time; or, if a room, ROOM_SCORE points for visiting
it for the first time.

 static    ''Fixed in place'' if player tries to take, remove,
pull, push or turn.

 supporter    'Things can be put on top of it'.
Affects scope and light (see definitions in the main text);
object lists recurse through it; a possession will give it a
LetGo action if the player tries to remove it, or a Receive
if something is put in; things can be taken or removed from it,
or put on it; likewise for transfers; a player inside it is said
to be ''on'' rather than ''in'' it; room descriptions list
its contents in separate paragraphs if it is itself listed.

 switchable    Can be switched on or off; listed
as such by Examine; described using when_on or when_off
in room descriptions.

 talkable    Player can talk to this object in
''thing, do this'' style.  (This is useful for microphones and
the like.)

 transparent    Affects scope and light
(see definitions in the main text: it roughly means 'contents
always visible').  A transparent container is treated as if
it were open for printing of contents.

 visited    Given to a room when a Look first
happens there: if this room is scored then ROOM_SCORE points
are awarded.  Affects whether room descriptions are abbreviated
or not.

 workflag    Temporary flag used by Inform internals,
also available to outside routines; can be used to select items
for some lists printed by WriteListFrom.

 worn    'Item of clothing being worn'.  Should
only be held by an object being immediately carried by player.
Affects inventories; doesn't count towards the limit of
MAX_CARRIED; won't be automatically put away into the
SACK_OBJECT; a Drop action will cause a Disrobe action first;
so will PutOn or Insert; you can't insert or remove something
from a worn container.





Note that very few attributes sensibly apply to rooms: only really
light, scored and visited, together with general if you
choose to use it.  Note also that an object cannot be both a
container and a supporter; and that the old attribute autosearch,
which was in earlier releases, has been withdrawn as obselete.





Next, definitions of properties which sensibly apply to ''objects''
(meaning, things which are not rooms):


 after     List of rule routines to be applied in sequence
after an action takes place.  (For a room, receives all actions in that
room; for a player-object, all actions by the player as that object.)

 article     Indefinite article for object (defaults to 'a').

 before     List of rule routines to be applied in sequence
before an action takes place.  (For a room, receives all actions in that
room; for a player-object, all actions by the player as that object.)

 cant_go     Message to print (or routine to print one) when
a player tries to go in an impossible direction from this room (defaults to
''You can't go that way.")


 capacity     Number of objects a container or supporter
can hold (defaults to 100); number of things the player can carry (when
the player is this object), initially set to MAX_CARRIED for the standard
player object.

 daemon     Routine to run each turn (once activated by a
StartDaemon and until stopped by a StopDaemon).  Note: the same object
cannot have both a daemon and a time_out.

 describe     Routine (only) to describe object: over-rides a
room's description to give main room description, if set; over-rides an
object's usual listing when it appears in a room description.

 description     Examine message, or routine to print one out,
for an object; main room description, or routine to print one, for a room.

 door_dir     Direction (that is, direction property, such as
n_to, not direction object) that a door goes via, or a routine
which returns this information; also used for direction objects, see
the compass notes above.


 door_to     Room that a door connects to, or routine
returning this; a value of 0 means 'leads nowhere' (but this is not the
ideal way to implement such a door).


 each_turn     String to print, or list of routines to
run, each turn that the object is in scope, after all timers and daemons
have run.


 found_in     List of rooms in which a ''floating object''
(that is, one present in multiple rooms) is found, unless it has absent,
in which case it is nowhere to be found.


 initial     Initial description of object not yet picked up,
or routine to print one.

 invent     Routine to change its inventory listing: see
main text.

 life     List of rule routines to be applied in sequence
after an action making sense for an animate object takes place.

 name     List of dictionary words referring to an object
(note: uniquely, these dictionary words are given in double quotes "thus",
whereas in all other circumstances they would be 'thus'; part tradition,
part defence against 'a' single-letter ambiguity).  For
a room, lists dictionary words which ''do not need to be referred to in
this game''.

 number     A general purpose property left free: conventionally
holding a number like ''number of turns' battery power left''.  (Except:
an object to be used as a player-object must provide one, and it isn't left
free.)

 parse_name     Routine (only) to parse object's name
(this overrides the name and is also used in determining if two objects
are describably identical): see main text.


 plural     The plural name of an object (when in the presence
of others like it), or routine to print it.

 short_name     The short name of an object (like ''brass lamp"),
or routine to print it.


 time_left     Number of turns left until timer (if set,
which must be done using StartTimer) goes off.


 time_out     Routine to run when timer goes off (having been
set by StartTimer and not in the mean time stopped by StopTimer).  Note:
the same object cannot have both a daemon and a time_out.


 when_closed     Look description of something closed
(door or container), or routine to print one.


 when_open     Look description of something open
(door or container), or routine to print one.


 when_off     Look description of a switchable which isn't
on, or routine to print one.

 when_on     Look description of a switchable which is on,
or routine to print one.

 with_key     Key object needed to lock/unlock a lockable object;
player must explicitly name it as the key being used and be holding it at the
time to use it.  May be 0, in which case no key fits.



 together with the properties

     n_to   s_to    ne_to   se_to    u_to    d_to
     e_to   w_to    nw_to   sw_to    in_to   out_to
     
each of which can be map connections to other routines, or strings
(in which case they are printed if the player tries to go that way,
but the move is not allowed and no further action is taken),
or routines (in which case they are called to decide whether the
map connection exists or not, and if so where it leads).



  !!    Do not confuse n_to and so on with the 12 direction
objects, n_obj et al.



+-----------------------------------------------------------------------------+
|          A3  All the entry points, library routines and constants           |
+-----------------------------------------------------------------------------+


Entry points are routines which you can provide, if you choose to,
and which are called by the library routines to give you the option of
changing the rules.  All games  must define an Initialise
routine, which is obliged to set the location variable to a room;
the rest are optional.


 AfterLife     When the player has died (a condition signalled
by the variable deadflag being set to a non-zero value other than
2, which indicates winning), this routine is called: by setting
deadflag=0 again it can resurrect the player.

 Amusing     Called to provide an ''afterword" for players who
have won (for instance, it might advertise some features which a successful
player might never have noticed).  (But only if you have defined the
constant AMUSING_PROVIDED in your own code.)

 DarkToDark     Called when a player goes from one dark room
into another one; a good excuse to kill the player off in anyone's book.

 DeathMessage     Prints up ''You have died" style messages, for
deadflag values of 3 or more.  (If you choose ever to set deadflag
to such.)

 GamePostRoutine     A kind of super-after rule, which
applies to all actions in the game, whatever they are:
use only in the last resort.

 GamePreRoutine     A kind of super-before rule, which
applies to all actions in the game, whatever they are: use only in the last
resort.

 Initialise     A compulsory routine, which must set location
and is convenient for miscellaneous initialising, perhaps for random settings.

 InScope     An opportunity to place extra items in scope during
parsing, or to change the scope altogether.  (If et_flag is 1 when this is
called, the scope is being worked out for each_turn reasons; otherwise for
everyday parsing.)

 LookRoutine     Called at the end of every Look description.

 NewRoom     Called when the room changes, before any
description of it is printed.
(This happens no matter how the change of room occurred.)

 ParseNumber     An opportunity to parse numbers in a different
(or additional) way.

 ParserError     The chance to print different parser error
messages (like ''I don't understand that sentence'').

 PrintRank     Completes the printing of the score.
(You might want to change this, so as to make the ranks something like
''junior astronaut" or ''master catburglar" or whatever suits your game.)

 PrintVerb     A chance to change the verb printed out in a
parser question (like ''What do you want to (whatever)?'') in case an unusual
verb via UnknownVerb has been constructed.  Returns true (or 1) if it has
printed something.

 PrintTaskName     Prints the name of a game task
(such as ''driving the car").

 TimePasses     Called after every turn (but not, for instance,
after a command like ''score" or ''save").  It's much more elegant to use timers
and daemons, or each_turn routines for individual rooms - using this
is a last resort.

 UnknownVerb   
Called by the parser when it hits an unknown verb,
so that you can transform it into a known one.






Library routines which are ''open to the public":






 Achieved(task)    Indicate the task is achieved (which only
awards score the first time).

 AllowPushDir()    Signal that an attempt to push an object from
one place to another should be allowed.

 CDefArt(object)    Print the capitalised definite article and
short name of object.

 ChangePlayer(object, flag)    Cause the player at the keyboard to
play as the given object, which must have a number property supplied.  If
the flag is set to 1, then subsequently print messages like ''(as Ford
Prefect)'' in room description headers.  This routine, however, prints nothing
itself.

 DefArt(object)    Print the definite article and short name of
object.

 DoMenu(text,routine,routine)    Produce a menu.

 EnglishNumber(x)    Prints out x in English (e.g.,
''two hundred and seventy-seven").

 HasLightSource(object)    Returns true if object ''has light''.

 InDefArt(object)    Print the indefinite article and short name
of object.

 NextWord()    Returns the next dictionary word in the player's
input, moving the word number wn on by one.  Returns -1 if the player's input
has run out, and 0 if the word is not in the dictionary.

 OffersLight(object)    Returns true if object ''offers light''.

 PlaceInScope(object)    Puts object into scope for the parser.

 PlayerTo(place, flag)    Move the player to place.  Unless
flag is given and is 1, describe the player's surroundings.

 PrintShortName(object)    Print the short name of object.
(This is protected against object having a meaningless value.)

 ScopeWithin(object)    Puts the contents of object into scope,
recursing downward according to the usual scope rules.

 SetTime(time,rate)    Set the game clock (a 24-hour clock) to the
given time (in seconds since the start of the day), to run at the given rate
$r$: $r=0$ means it does not run, if $r>0$ then $r$ seconds pass every turn,
if $r<0$ then $-r$ turns pass every second.

 ScopeWithin(object)    Puts the contents of object, recursing
downward according to the usual scope rules.

 StartDaemon(object)    Makes the daemon of object active, so
that its daemon routine will be called every turn.

 StartTimer(object, time)    Starts the timer of object, set
to go off in time turns, at which time its time_out routine will be called
(it must provide a time_left property).

 StopDaemon(object)    Makes the daemon of object inactive, so
that its daemon routine is no longer called.

 StopTimer(object)    Stops the timer of object, so that
it won't go off after all.

 TryNumber(wordnum)    Tries to parse the word at wordnum as a
number (recognising decimal numbers and English ones from ''one'' to
''twenty''), returning -1000 if it fails altogether, or the number.
Values exceeding 10000 are rounded down to 10000.

 WriteListFrom(object, style)    Write a list of object and its
siblings, with style a bitmap of options.

 YesOrNo()    Assuming that a question has already been printed,
wait for the player to type ''yes'' or ''no'', returning true or false
accordingly.






And, finally, the constants:






 AMUSING_PROVIDED    To indicate that an Amusing routine
is provided.

 DEBUG    To include the special ''debugging" verbs.

 Headline    Style of game and copyright message.

 MAX_CARRIED    Maximum number of (direct) possessions
the player can carry.

 MAX_SCORE    Maximum game score.

 MAX_TIMERS    Maximum number of timers or daemons active
at any one time (defaults to 32).

 NUMBER_TASKS    Number of ''tasks'' to perform.

 OBJECT_SCORE    Score for picking up a scored object
for the first time.

 ROOM_SCORE    Score for visiting up a scored room
for the first time.

 SACK_OBJECT    Object which acts as a ''rucksack'',
into which the game automatically tidies away things for the player.

 Story    Story name, conventionally in CAPITAL LETTERS.

 TASKS_PROVIDED    To indicate that ''tasks'' are provided.









+-----------------------------------------------------------------------------+
|                      A4  All the Inform error messages                      |
+-----------------------------------------------------------------------------+



Inform can produce about 230 different error messages.  The error messages
were tidied-up and made more consistent in Inform 5.4, which the text here
comes from, but earlier editions were similar.  Since interpreters can in
some cases crash horribly when given incorrect files, Inform never writes a
file which caused an error, though it will permit files which incurred only
warnings.


Fatal errors



To begin with, fatal errors (which stop Inform in its tracks) come in three
kinds, the first containing only this one:

     Too many errors: giving up
     
After 100 errors, Inform stops (in case it has been given the wrong source file
altogether).  Secondly, file input/output can go wrong.  Most commonly, Inform
has the wrong filename:

     Couldn't open input file <filename>
     Couldn't open output file <filename>
     Couldn't open transcript file <filename>
     Couldn't open debugging information file <filename>
     Couldn't open temporary file 1 <filename>
     Couldn't open temporary file 2 <filename>
     Too many files have included each other: increase #define MAX_INCLUSION_DEPTH
     
(Temporary files are used (on most machines) for temporary storage space
during compilation.  They are removed afterwards.)
The last error only occurs if 5 files all include each other.  Increasing this
#define means re-compiling Inform from its C source, a drastic measure.
The remaining file-handling errors usually mean that the disc is full:
something has gone wrong with an already-open file.

     I/O failure: couldn't read from source file
     I/O failure: couldn't write to temporary file 1
     I/O failure: couldn't reopen temporary file 1
     I/O failure: couldn't read from temporary file 1
     I/O failure: couldn't write to temporary file 2
     I/O failure: couldn't reopen temporary file 2
     I/O failure: couldn't read from temporary file 2
     I/O failure: couldn't write to story file
     I/O failure: couldn't write to transcript file
     I/O failure: can't write to debugging information file
     
The third class of fatal error is Inform running out of memory.  It might
fail drastically, having not enough memory to get started, as follows...

     Couldn't allocate memory
     Couldn't allocate memory for an array
     
(There are four similar hallocate errors unique to the PC 'Quick C' port.)
More often it will run out in the course of compilation, like so:

     The memory setting <setting> (which is <value> at present) has been exceeded.
     Try running Inform again with $<setting>=<some-larger-number> on the command line.
     
For details of the memory settings, see the next section.


Errors



There are a few conventions.  Anything in double-quotes is a quotation from
your source code; other strings are in single-quotes.  A message like

     Expected ... but found "..."
     
means that Inform expected something different from what it found; if it
doesn't say what it found, this usually means it found nothing (i.e. the
statement was incomplete).  Messages in the form

     No such ... as "..."
     Not a ...: "..."
     
mean that a name is unrecognised in the former case (say, a typing error
might produce this), or is recognised but means something else in the latter
case (an attempt to use a routine where a property is expected would give
such an error).

To begin with, the source-code format may go awry:

     Too many tokens on line (note: to increase the maximum, set
         $MAX_TOKENS=some-bigger-number on the Inform command line)
     Line too long (note: to increase the maximum length, set
         $BUFFER_LENGTH=some-bigger-number on the Inform command line)
     Too much text for one pair of "s to hold
     Too much text for one pair of 's to hold
     Open quotes " expected for text but found <text>
     Close quotes " expected for text but found <text>
     
(Usually BUFFER_LENGTH allows about 2000 characters per line.)
When giving something (such as an object) an internal name, there are
rules to be obeyed; for instance, you can't give an object the same name
as a property already declared:

     Symbol name expected
     Symbol names are not permitted to start with an '_'
     Symbol name is too long: <text>
     Duplicated symbol name: <text>
     
At the top level, the most common ''no such command'' error is

     Expected an assignment, command, directive or opcode but found <text>
     
which means Inform didn't even understand the first word of the command.
Directives to Inform can produce the following errors:

     All 32 attributes already declared (compile as Advanced game to get an extra 16)
     All 48 attributes already declared
     All 30 properties already declared (compile as Advanced game to get an extra 32)
     All 62 properties already declared
     Expected an attribute name after 'alias'
     Expected a property name after 'alias'
     'alias' incompatible with 'long'
     'alias' incompatible with 'additive'
     'alias' refers to undefined attribute <text>
     'alias' refers to undefined property <text>
     All 235 global variables already declared
     Expected 'string', 'data', 'initial', 'initstr' or '=' but found <text>
     
Use of alias is rare (except inside the library files).  The last of these
errors means that a global variable has been wrongly initialised, and a
common cause of this is typing, say, global trolls 5; instead of
global trolls = 5;.

     '*' divider expected, but found <text>
     No such token as <text>
     Expected '=' after 'scope' but found <text>
     Expected routine after 'scope=' but found <text>
     Expected routine after 'noun=' but found <text>
     '=' is only legal here as 'noun=Routine'
     '->' clause missing
     No such action routine as <text>
     Not an action: <text>
     Too many lines of grammar for verb: increase #define MAX_LINES_PER_VERB
     There is no previous grammar for the verb <text>
     Two different verb definitions refer to <text>
     Expected 'replace', 'last' or 'first' but found <text>
     
These are the grammatical errors, the last three concerning extended
verb definitions.  
Normally one gets 16 grammar lines per verb.  It's probably better to write
grammar more carefully (using routines to parse adjectives more carefully,
for instance) than to exceed this, as the game parser will otherwise slow
down.  The object/class definition errors are largely self-explanatory:

     Object/class definition finishes with ','
     Two commas ',' in a row in object/class definition
     No such attribute as <text>
     No such class as <text>
     Expected 'with', 'has' or 'class' in object/class definition but found <text>
     Expected an (internal) name for object but found the string <text>
     An object must be defined after the one which contains it: (so far)
         there is no such object as <text>
     Not an object: <text>
     No such property as <text>
     Not a property: <text>
     
Miscellaneous errors complete the list produced by mostly-uncommon directives:

     Expected ';' after 'include <file>' but found <text>
     A 'switches' directive must come before constant definitions
     Expected 'score' or 'time' after 'statusline' but found <text>
     The serial number must be a 6-digit date in double-quotes
     The version number must be 3 to 6: 3 for Standard games and 5 for Advanced
     Expected 'on' or 'off' after 'font' but found <text>
     Defaulted constants can't be strings
     Must specify 0 to 3 variables in 'stub' routine
     Expected 'full' or nothing after 'etrace' but found <text>
     Too many abbreviations declared
     All abbreviations must be declared together
     It's not worth abbreviating <text>
     Expected a 'string' value
     No such directive as <text>
     
Conditional compilation happens as a result of one of #IFDEF, #IFV3 or
#IFV5.  (The former tests whether a constant is defined; the latter test
for version-3 (Standard) games or version-5 (Advanced) games.)  An #IFNOT
section is optional but the closing #ENDIF is compulsory.  In these error
messages #IF... means any of the three opening clauses.

     '#IF...' nested too deeply: increase #define MAX_IFDEF_DEPTH
     '#ENDIF' without matching '#IF...'
     '#IFNOT' without matching '#IF...'
     Two '#IFNOT's in the same '#IF...'
     End of file reached inside '#IF...'
     
Routines begin with a [ and some local variables and end with ]:

     Routine has more than 15 local variables
     The earliest-defined routine is not allowed to have local variables
     Expected local variable but found ',' or ':' (probably the ';' after the
         '[ ...' line was forgotten)
     Misplaced ']'
     Comma ',' after ']' can only be used inside object/class definitions
     Expected ',' or ';' after ']' but found <text>
     Expected ';' after ']' but found <text>
     
The error messages for expressions are fairly simple.  Note, however, that
one is not allowed to type, say, lamp.number++; but must instead write
lamp.number = lamp.number + 1; (the ++ and -- operators
can only be applied to variables, not properties).

     Expected condition but found expression
     Unexpected condition
     Expected an assignment but found <text>
     Expected an assignment but found an expression
     Attempt to use void as a value
     Attempt to use an assignment as a value
     Attempt to use a condition as a value
     Operator has too few arguments
     Operator has too many arguments
     '++' and '--' can only apply directly to variables
     At most three values can be separated by 'or'
     'or' can only be used with the conditions '==' and '~='
     Too many brackets '(' in expression
     Brackets '(' too deeply nested
     Missing bracket ')' in function call
     Spurious comma ','
     Misplaced comma ','
     Wrong number of arguments to system function
     'children' takes a single argument
     'youngest' takes a single argument
     'elder' takes a single argument
     'indirect' takes at least one argument
     Type mismatch in argument <text>
     A function may be called with at most 3 arguments
     Malformed statement 'Function(...);'
     Spurious terms after function call
     Spurious terms after assignment
     Spurious terms after expression
     
Next, constants.  Note that dictionary words cannot start with a
non-alphabetic character, which means that Infocom-style ''debugging verbs''
which traditionally begin with a # are not allowed.

     No such variable as <text>
     No such constant as <text>
     Not a constant: <text>
     Reserved word as constant: <text>
     No such routine as <text>
     Dictionary words must begin with a letter of the alphabet
     Dictionary word not found for constant <text>
     
Loop constructs: note that 'old-style' for loops are a rather obselete
form (e.g. for i 1 to 10), and the more flexible style for (i=1:i<=10:i++)
is now preferred.

     'if' statement with more than one 'else'
     'else' attached to a loop block
     'for' loops too deeply nested
     ':' expected in 'for' loop
     Second ':' expected in 'for' loop
     Concluding ')' expected in 'for' loop
     'to' missing in old-style 'for' loop
     'to' expected in old-style 'for' loop
     Final value missing in old-style 'for' loop
     '{' required after an old-style 'for' loop
     Old-style 'for' loops must have simple final values
     Open bracket '(' expected in 'objectloop'
     'objectloop' must be 'from', 'near' or 'in' something
     Close bracket ')' expected in 'objectloop'
     Braces '{' are compulsory unless the condition is bracketed
     Unmatched '}' found
     Brace mismatch in previous routine
     
Inform checks the level of braces when a routine closes so that it can
recover as quickly as possible from a mismatch; this last error means at
least one brace is still open when the routine finishes.

     The object to 'give' to must be a variable or constant
     Expected some attributes to 'give'
     Expected 'to <object>' in 'move'
     Expected 'to' in 'move' but found <text>
     Expected ',' in 'print' list but found <text>
     Expected 'style' to be 'roman', 'bold', 'underline' or 'reverse' but found <text>
     Expected a parse buffer for 'read'
     Expected some properties to 'write'
     The object to 'write' must be a variable or constant
     Expected property value to 'write'
     Expected 'byte' or 'word' in 'put'
     Expected 'byte' or 'word' in 'put' but found <text>
     
These are miscellaneous commands and put and write are quite obselete.
Only action commands like <Take brass_lantern> remain:

     Action name too long or a string: perhaps a statement accidentally ended
         with a comma?
     Action commands must take the form '< Action ... >'
     The longest action command allowed is '<Action noun second>'
     Angle brackets do not match
     Action given in constant does not exist
     Action name over 60 characters long: <text>
     Expected ':' (after action) but found <text>
     
The first of these may be caused by something like:

          "You load the crossbow bolt.",
        Drop:  "The bolt falls to the floor with a thump.";
     
where a comma has been typed instead of a semicolon after the first string,
so that Inform thinks you are giving a rule for two actions, one being Drop
and the other apparently called "You load the crossbow bolt.".


Internal and assembler errors



By now we have descended to the ninth circle of Inform: the assembler.
These errors are fairly unmysterious (if only because they seldom happen),
but sometimes one is told something odd like

     No such label as _f456
     
which is caused by Inform failing to recover properly from a previous
brace mismatch error.  Just ignore this and fix the earlier error (which will
also have been reported).  The ''no such variable'' error is occasionally
seen when an unknown variable is first referred to by being written to.

     No such assembly opcode as <text>
     Too many arguments
     Can't store to that (no such variable)
     Branch too far forward: use '?'
     No such return condition for branch
     Can't branch to a routine, only to a label
     No such label as <text>
     Not a label: <text>
     
To conclude with, there are a few internal error messages:

     A label has moved between passes because of a low-level error just before
         (perhaps an improper use of a routine address as a constant)
     Object has altered in memory usage between passes: perhaps an attempt to
         use a routine name as value of a small property
     Duplicated system symbol name <text>
     Internal error - unknown directive code
     Internal error - unknown compiler code
     
The last three should not happen.  The first two occasionally do, and cause
some confusion.  Inform performs two tests regularly as a safeguard to make
sure that code has not come out substantially different in its two passes.
The first failure occurs in code, the second for object/class definitions.
Whatever caused this should be something unusual, low-level and just
before the error occurred: if you get these errors with innocent high-level
code, then probably Inform should provide a suitable error message, so
please email the author with a sample of offending code.


Warnings



Inform can produce any number of warnings without shutting down.  Note
that Inform tries to give only warnings when it hits Advanced-game features
in what is to be a Standard game, for the sake of portability.  Nevertheless
it is probably better to use #IFV3 and #IFV5 clauses around any pieces
of code which are to be different in these two versions (if, indeed, you
want two different versions).

     Local variable unused: <text>
     Since it is defined before inclusion of the library, game-play will begin
         not at 'Main' but at the routine <text>
     Ignoring Advanced-game status routine
     Ignoring this Advanced-game command
     Missing ','?  Property data seems to contain the property name <text>
     Standard-game limit of 8 bytes per property exceeded (use Advanced to get
         64), so truncating property <text>
     Ignoring Advanced-game opcode <text>
     Ignoring Standard-game opcode <text>
     



+-----------------------------------------------------------------------------+
|                  A5  Compiler options and memory settings                   |
+-----------------------------------------------------------------------------+




     I was promised a horse, but what I got instead
     was a tail, with a horse hung from it almost dead.
     
         - Palladas of Alexandria, translated by Tony Harrison




 
The reader is warned that some details in this section are slightly
different on different machines.




On most machines, Inform is run from the command line, by a command like

     inform -xv5 balances
     
and simply typing inform will produce a good deal of help information
about the command line options available.  The command line syntax is

     inform <switches> <settings> <source file> <output file>
     
where only the <source file> is mandatory.  (By default, the full names to
give the source and output files are derived in a way suitable for the machine
Inform is running on: on a PC, for instance, advent may be understood as
asking to compile advent.inf to advent.z5.)



The switches are given in one or more groups, preceded by a minus sign -
in the usual Unix command-line style.  The current list of legal switches is:

       a   list assembly-level instructions compiled
       b   give statistics and/or line/object list in both passes
       c   more concise error messages
       d   contract double spaces after full stops in text
       e   economy mode (slower): make use of declared abbreviations
       f   frequencies mode: show how useful abbreviations are
       g   with debugging code: traces all function calls
       h   print this information
       i   ignore default switches set within the file
       j   list objects as constructed
       k   output Infix debugging information to "Game_Debug"
       l   list all assembly lines
       m   say how much memory has been allocated
       n   print numbers of properties and attributes
       o   print offset addresses
       p   give percentage breakdown of story file
       r   record all the text to "Game_Text"
       s   give statistics
       t   trace Z-code assembly
       u   work out most useful abbreviations
       v3  compile to version-3 (Standard) story file
       v4  compile to version-4 (Plus) story file
       v5  compile to version-5 (Advanced) story file
       v6  compile to version-6 (graphical) story file
       w   disable warning messages
       x   print # for every 100 lines compiled (in both passes)
       z   print memory map of the Z-machine
       T   enable throwback of errors in the DDE
     
(Thus, as long as your name doesn't have a 'q' or 'y' in it, you can
amuse yourself typing your name in as a switch and see what it does.)
Note that these switches can also be selected by putting a switches
directive into the source code before anything else, such as

         Switches xdv5s;
     
The most useful switches are v3 and v5, which choose between Standard
and Advanced games.  For example, the above line is
from the example game 'Advent', which is consequently compiled to an
Advanced game.  (If no choice is stated, a Standard game results.)  The
options v4 and v6 are provided for completeness but their use is not
recommended.

Many of the remaining switches make Inform produce extra output, but do
not affect its compilation:




 a b l m n t    are tracing options to help with maintaining
Inform, or for debugging assembly language programs

 o p s z    will print out information about the final game file,
the s (statistics) option being particularly useful to keep track of how
large the game is growing

 c w T    in c mode, Inform does not quote whole source lines
together with error messages; in w mode it suppresses warnings; in T
mode, which is only present on the Acorn Archimedes, error throwback
will occur in the 'Desktop Development Environment'

 f    indicates roughly how many bytes the abbreviations saved

 h    prints out the help information (and is equivalent to
just typing inform)

 j x    make Inform print out steady text to prove that it's
still awake: on very slow machines this may be a convenience

 k    writes a ''debugging information'' file for the use of
the Infix debugger (similarly, the filename is something suitable for
the machine)

 r    is intended to help with proof-reading the text of a game,
and transcribes all of the text in double-quotes to the given file (whose
name is something suitable for the machine)

 u    will try to work out a good set of abbreviations to
declare for your game, but  extremely slowly (a matter of hours) and
 consuming very much memory (perhaps a megabyte)



This leaves three more switches which actually alter the game file which
Inform would compile:



 d    converts text like

     "...with a mango.  You applaud..."
     
into the same with only a single space after the full stop, which will
prevent an interpreter from displaying a spurious space at the beginning
of a line when a line break happens to occur exactly after the full stop;
this is to help typists who habitually double-space


 e    only in 'economy' mode does Inform actually process
abbreviations, because this is seldom needed and slows the compiler by
10% or so; the game file should not play any differently if compiled
this way, but will probably be shorter, if your choice of abbreviations
was sensible

 g    will make Inform automatically compile trace-printing
code on every function call; in play this will produce reams of text (several
pages between each chance to type commands) but is sometimes useful.  Note
that in Inform 5.3 or later, this can be set on an individual command by
writing * as its first local variable, without use of the g switch

 i    overrides any switches set by switches directives in
the source code; so that the game can be compiled with different options
without having to alter that source code.





Inform's memory management is about as flexible as it can be given that it
has to run in some quite hostile environments.  In particular, it is unable
to increase the size of any stretch of memory once allocated, so if it runs
out of anything it has to give up.  If it does run out, it will produce an
error message saying what it has run out of and how to provide more.

There are two main choices: $small and $large.  (Which one is the default
depends on the computer you use.)  Even $small is large enough to compile
all the example games, including 'Advent'.  $large is large enough to
compile almost anything (including the largest version of 'Curses' which
ever existed, a draft very close to 256K long).

A typical game, compiled with $large, will cause Inform to allocate about
336K of memory: and the same game about 100K less under $small.  (These
values will be rather lower if the computer Inform runs on has 16-bit
integers.)  In addition, Inform physically occupies about 170K (on my
computer).  Thus, the total memory consumption of the compiler at work
will be between 4 to 500K.

Running

         inform $list
     
will list the various settings which can be changed, and their current
values.  Thus one can compare small and large with:

         inform $small $list
         inform $large $list
     
If Inform runs out of allocation for something, it will generally print an
error message like:

        "Game", line 1320: Fatal error: The memory setting MAX_OBJECTS (which
        is 200 at present) has been exceeded.  Try running Inform again with
        $MAX_OBJECTS=<some-larger-number> on the command line.
     
and indeed

         inform $MAX_OBJECTS=250 game
     
(say) will tell Inform to try again, reserving more memory for objects this
time.  Note that settings are made from left to right, so that for instance

         inform $small $MAX_ACTIONS=200 ...
     
will work, but

         inform $MAX_ACTIONS=200 $small ...
     
will not because the $small changes MAX_ACTIONS again.

Changing some settings has hardly any effect on memory usage, whereas others
are expensive to increase.  To find out about, say, MAX_VERBS, run

         inform $?MAX_VERBS
     
(note the question mark) which will print some very brief comments.



+-----------------------------------------------------------------------------+
|                                end of manual                                |
+-----------------------------------------------------------------------------+
