Used by `invent` and `list_together` properties.
`keep_silent`
- Normally `false`; `true` makes most group 2 actions silent.
+ Normally `false`; `true` makes most :ref:`group 2 actions
+ <group-2-actions>` silent.
`location`
The player's current room; unless that's dark, when it contains
A scored task has been achieved.
`AfterRoutines()`
- In a group 2 action, controls output of "after" messages.
+ In a :ref:`group 2 action <group-2-actions>`, controls output of "after"
+ messages.
`AllowPushDir()`
An object can be pushed from one location to another.
`DrawStatusLine()`
Refreshes the status line; happens anyway at end of each turn.
-`GetGNAOfObject(obj_id)`
+`GetGNAOfObject({obj_id})`
Returns gender-number-animation 0..11 of the `{obj_id}`.
-`HasLightSource(obj_id)`
+`HasLightSource({obj_id})`
Returns `true` if the `{obj_id}` has light.
`IndirectlyContains({parnt_obj_id,obj_id})`
Returns `true` if `{obj_id}` is currently a child or grand-child or
great-grand-child... of the `{parent_object}`.
-`IsSeeThrough(obj_id)`
+`IsSeeThrough({obj_id})`
Returns `true` if light can pass through the `{obj_id}`.
`Locale({obj_id,"string1","string2"})`
Group 2 actions usually work, given the right circumstances.
+.. tabularcolumns:: |l|p{5in}|
+
============= =============================================================
`Close` "`CLOSE [UP]`", "`COVER [UP]`", "`SHUT [UP]`"
`Disrobe` "`DISROBE`", "`DOFF`", "`REMOVE`", "`SHED`", "`TAKE OFF`"
Group 3 actions are by default stubs which output a message and stop at the
"before" stage (so there is no "after" stage).
+.. tabularcolumns:: |l|p{5in}|
+
============= =============================================================
`Answer` "`ANSWER TO`", "`SAY TO`",
"`SHOUT TO`", "`SPEAK TO`"
Fake actions handle some special cases, or represent "real" actions from
the viewpoint of the second object.
+.. tabularcolumns:: |l|p{5in}|
+
================ ========================================================
`LetGo` Generated by `Remove`.
`ListMiscellany` Outputs a range of inventory messages.
.. note::
On the command line, you sometimes also see a compiler :term:`switch`
- such as ``-S``, used for controlling detailed aspects of how the
- compiler operates. Rather than do that here, we find it more
+ such as :option:`-S`, used for controlling detailed aspects of how
+ the compiler operates. Rather than do that here, we find it more
convenient to place any necessary switches at the very top of the
source file, as we'll explain in the next chapter.
.. note::
On the command line, you sometimes also see a compiler :term:`switch`
- such as ``-S``, used for controlling detailed aspects of how the
- compiler operates. Rather than do that here, we find it more
+ such as :option:`-S`, used for controlling detailed aspects of how
+ the compiler operates. Rather than do that here, we find it more
convenient to place any necessary switches at the very top of the
source file, as we'll explain in the next chapter.
.. note::
- Actually, the ``-S`` is redundant, since Strict mode is already on by
- default. We include it here as a reminder that (a) to turn Strict
- mode *off*, you change this setting to ``-~S``, and (b) alphabetic
- case matters here: ``-s`` causes a display of compiler statistics (and
- ``-~s`` does nothing at all).
+ Actually, the :option:`-S` is redundant, since Strict mode is already
+ on by default. We include it here as a reminder that (a) to turn
+ Strict mode *off*, you change this setting to :option:`-~S`, and (b)
+ alphabetic case matters here: :option:`-s` causes a display of
+ compiler statistics (and :option:`-~s` does nothing at all).
* Otherwise, when the compiler comes across an exclamation mark, it ignores
the rest of the line. If the ``!`` is at the start of a line, the whole
.. pull-quote::
- "Impersonating mild mannered John Covarth, assistant help boy at
- an Impersonating insignificant drugstore, you suddenly STOP
- when your acute hearing deciphers a stray radio call from the
- POLICE. There’s some MADMAN attacking the population in Granary
- Park! You must change into your Captain FATE costume fast...!"
+ "Impersonating mild mannered John Covarth, assistant help boy at an
+ insignificant drugstore, you suddenly STOP when your acute hearing
+ deciphers a stray radio call from the POLICE. There’s some MADMAN
+ attacking the population in Granary Park! You must change into your
+ Captain FATE costume fast...!"
which won't be so easy to do. In this short example, players will win
when they manage to change into their super-hero costume and fly away to
.. note::
- although the text of our guide calls Benny's establishment a "café"
+ Although the text of our guide calls Benny's establishment a "café"
-- note the acute "e" -- the game itself simplifies this to "cafe".
We do this for clarity, not because Inform doesn't support accented
characters. The *Inform Designer's Manual* explains in detail how to
.. todo::
- That "whatever new look" below needs to be italicized and bolded for LaTeX
+ That "whatever new look" below needs to be italicized and bolded for
+ LaTeX.
.. note::
- going back to our example, an alternative approach would be to set
+ Going back to our example, an alternative approach would be to set
the variable ``player.description`` in the ``Initialise`` routine (as we
did with "William Tell") to the "ordinary clothes" string, and then
later change it as the need arises. It is a variable, after all, and you
.. admonition:: Cultural Note
:class: admonition note
- not for the first time, this guide betrays its origins. In
+ Not for the first time, this guide betrays its origins. In
European countries the word "toilet" often refers not only to the
white porcelain artefact, but also to the room in which it can be
found (also, a "bathroom" is for taking a bath, a "restroom" for
],
has supporter;
-That ``before property``, superficially normal, actually conceals a
+That ``before`` property, superficially normal, actually conceals a
little surprise. By now you should be entirely comfortable with using an
object's ``before`` property to intercept an action directed at that
object; for example, if the player types HIT COUNTER then the counter's
.. note::
- in "William Tell" we defined the ``quiver``, way back in
+ In "William Tell" we defined the ``quiver``, way back in
:ref:`possessions`, as an ``open container``. As things stand, the player
can put *any* held object, however inappropriate, into it. We could have
trapped the Receive action to ensure that arrows are the only acceptable
the property is always an embedded routine.
#. However, daemons do nothing until you activate them. This is easily
- achieved with the call ``StartDaemon(obj_id)``, which may happen
+ achieved with the call :samp:`StartDaemon({obj_id})`, which may happen
anywhere (if you want some object's daemon to be active from the
beginning of the game,you can make the call in your Initialise
routine).
#. Once the daemon has finished its mission (if ever) you may stop it
- with the call ``StopDaemon(obj_id)``.
+ with the call :samp:`StopDaemon({obj_id})`.
How does our particular daemon work? The appearance of our hero in full
crime-fighting wear will make the customers stare at him and make snarky
Then we check whether the player character is wearing the costume, in
which case it starts the ``daemon`` of the ``customers`` object. The use
-of the local first_time_out property ensures that the condition is
+of the local ``first_time_out`` property ensures that the condition is
``true`` only once, so the statement block attached to it runs also
once.
short_name [;
if (location == cafe) print "door to the toilet";
else print "door to the cafe";
+ return true;
],
description
...
.. note::
- what's displayed if there isn't an external name in an object's header?
+ What's displayed if there isn't an external name in an object's header?
If you've read the section :ref:`compile-as-you-go`, you'll recall that
the interpreter simply uses the internal identifier within parentheses;
that is, with no external name and no ``short_name`` property, we might
- see:
-
- .. code-block:: inform
+ see::
You open the (toilet_door).
And the same principle applies if we were mistakenly to ``return
false`` from this short_name routine: we would get, first, the result
of our ``print`` statement, and then the standard rules would display
- the internal ID:
-
- .. code-block:: inform
+ the internal ID::
You open the door to the toilet(toilet_door).
In all processes there is a library variable called ``keep_silent``,
which can be either ``false`` (the normal state) or ``true``; when
``true``, the interpreter does not display the associated message of an
-action in progress, so we can avoid things like::
+action in progress, so we can avoid things like:
+
+.. code-block:: transcript
>OPEN DOOR
You open the door to the toilet.
form of a library extension: the solution neatly packaged as a file that
other designers can incorporate into their source code. These files can
be found in the IF Archive: go to
-``http://mirror.ifarchive.org/indexes/if-archive.html`` and then select
+http://mirror.ifarchive.org/indexes/if-archive.html and then select
"``.../infocom``", "``.../compilers``", "``.../inform6``",
"``.../library``", and "``.../contributions``". All of these files
contain Inform code. To use a library extension (also known as a library
#. Add four lines near the head of the program (before you include
``Parser.h``).
- ``Replace MakeMatch;``
- ``Replace Identical;``
- ``Replace NounDomain;``
- ``Replace TryGivenObject;``
+ .. code-block:: inform
+
+ Replace MakeMatch;
+ Replace Identical;
+ Replace NounDomain;
+ Replace TryGivenObject;
#. Include the ``pname.h`` header just after you include ``Parser.h``.
- ``Include "Parser";``
- ``Include "pname";``
+
+ .. code-block:: inform
+
+ Include "Parser";
+ Include "pname";
#. Add ``pname`` properties to those objects which require phrase
recognition.
Include "Parser";
Include "pname";
- !...
+ ...
Now our source code is ready to benefit from the library package. How
does it work? We have acquired a new property -- ``pname`` -- which can
property where we have a disambiguation problem. Let’s change the
relevant lines for the toilet door and the toilet key:
-.. todo::
-
- Maybe specially highlight the lines using pname?
-
.. code-block:: inform
Object toilet_door
with pname '.x' 'red' '.x' 'toilet' 'door',
short_name [;
- !...
+ ...
Object toilet_key "toilet key" benny
with pname '.x' 'toilet' 'key',
article "the",
- !...
+ ...
while leaving the ``outside_of_toilet`` unchanged:
Object outside_of_toilet "toilet" cafe
with name 'toilet' 'bath' 'rest' 'room' 'bathroom' 'restroom',
before [;
- !...
+ ...
We are now using a new operator -- ``'.x'`` -- in our ``pname`` word
lists. explains
these objects, so that at run-time players could refer to the DOOR or
TOILET DOOR or the KEY or TOILET KEY -- but not simply to the TOILET --
when referring to either the door or the key. And, by leaving unchanged
-the name property of the outside_of_toilet object – where there is also
+the name property of the ``outside_of_toilet`` object – where there is also
another ``'toilet'`` entry -- the ``pname`` properties will tell the
interpreter to discard the key and the door as possible objects to be
considered when players refer just to TOILET. Looking at it in terms of
coffee_not_paid false, ! is Benny waiting to be paid?
key_not_returned false, ! is Benny waiting for the key?
live [;
- !...
+ ...
Now we are ready to tackle the ``Give`` action of the ``life`` property,
which deals with commands like GIVE THE KEY TO BENNY (in a moment, we'll
if (noun == costume) { whatever };
if (noun == clothes) { whatever };
- !...
+ ...
We won't let players give away their clothes or their costume (yes, an
improbable action, but you never know). The toilet key and the coin are
Benny, it's not a noun that the player can ASK Benny FOR. By making it a
child of the barman (who has the ``transparent`` attribute set), the
coffee is still an object that players can refer to. We ensure that they
-don't get more cups thanks to Benny's ``coffee_asked_for property``,
+don't get more cups thanks to Benny's ``coffee_asked_for`` property,
which will remain ``true`` after the first time.
We also ensure that Benny doesn't ask for money from players who have
``on``. switchable enables the object to be turned on and off, and is
typical of lanterns, computers, television sets, radios, and so on. The
library automatically extends the description of these objects by
-indicating if they are currently on or off::
+indicating if they are currently on or off:
+
+.. code-block:: transcript
> X LIGHT SWITCH
A notorious ACHIEVEMENT of technological SCIENCE, elegant yet EASY to use.
Two new actions are ready to use, ``SwitchOn`` and ``SwitchOff``. Left
to themselves, they toggle the object's state between ON and OFF and
-display a message like::
+display a message like:
+
+.. code-block:: transcript
You switch the brass lantern on.
itself (though this is usually convenient).
After setting the ``light`` attribute, we display a customised message,
-to avoid the default::
+to avoid the default:
+
+.. code-block:: transcript
You switch the light switch on.
.. note::
- remember what we said about class inheritance? No matter what you
+ Remember what we said about class inheritance? No matter what you
define in the class, the object’s definition has priority. The class
``Appliance`` defines a response for the ``Push`` action, but we
override it here with a new behaviour.
.. note::
- now, could they? Well, if players could TAKE the light switch (which
+ Now, could they? Well, if players could TAKE the light switch (which
we have forbidden) and then did INVENTORY, the trick would be given
away, because all objects with the ``light`` attribute set are listed
as ``(providing light)`` .
return false;
];
-``InScope(actor_obj_id)`` is an entry point routine that can tamper with
-the scope rules for the given ``actor_obj_id`` (either the player
-character or a NPC). We define it with one variable (which we name as we
-please; it's also a good idea to name variables in an intuitive way to
-remind us of what they represent), ``person`` , and then we make a
-complex test to see if the player is actually in the toilet and in the
+:samp:`InScope({actor_obj_id})` is an entry point routine that can tamper
+with the scope rules for the given :samp:`{actor_obj_id}` (either the
+player character or a NPC). We define it with one variable (which we name
+as we please; it's also a good idea to name variables in an intuitive way
+to remind us of what they represent), ``person`` , and then we make a
+complex test to see if the player is actually in the toilet and in the
dark.
We have told you that the library variable ``location`` holds the
finds himself in the dark *and* he actually happens to be in the
toilet...
-Then we make a call to one of the library routines,
-``PlaceInScope(obj_id)``, which has a very descriptive name: it places
-in scope the given object. In our case, we want both the door and the
-light switch to be within reach of the player, hence both additional
-lines. Finally, we must ``return false``, because we want the normal
-scope rules for the defined actor -- the player -- to apply to the rest
-of the objects of the game (if we returned ``true``, players would find
-that they are able to interact with very little indeed). Now we get a
-friendlier and more logical response:
+Then we make a call to one of the library routines,
+:samp:`PlaceInScope({obj_id})`, which has a very descriptive name: it
+places in scope the given object. In our case, we want both the door and
+the light switch to be within reach of the player, hence both additional
+lines. Finally, we must ``return false``, because we want the normal scope
+rules for the defined actor -- the player -- to apply to the rest of the
+objects of the game (if we returned ``true``, players would find that they
+are able to interact with very little indeed). Now we get a friendlier and
+more logical response:
.. code-block:: transcript
thinks to turn on the light switch, thereby placing the key in scope
once more.
-Why don't we add a ``PlaceInScope(toilet_key)`` to the above routine?
-Well, for starters, the key can be moved around (as opposed to the door
-or the light switch, which are fixed items in the toilet room). Suppose
-the player opens the door of the toilet, but drops the key in the café,
-then enters the toilet and closes the door. The condition is met and the
-key is placed in scope, when it's in another room. Second, this is a
-simple game with just a few objects, so you can define a rule for each
-of them; but in any large game, you might like to be able to refer to
-objects in bunches, and make general rules that apply to all (or some)
-of them.
+Why don't we add a :samp:`PlaceInScope({toilet_key})` to the above routine?
+Well, for starters, the key can be moved around (as opposed to the door or
+the light switch, which are fixed items in the toilet room). Suppose the
+player opens the door of the toilet, but drops the key in the café, then
+enters the toilet and closes the door. The condition is met and the key is
+placed in scope, when it's in another room. Second, this is a simple game
+with just a few objects, so you can define a rule for each of them; but in
+any large game, you might like to be able to refer to objects in bunches,
+and make general rules that apply to all (or some) of them.
We need to add code to the ``InScope`` routine, telling the game to
place in scope all objects that we drop in the dark, so that we might
is a loop statement, one of the four defined in Inform. A loop statement is
a construct that allows you to run several times through a statement (or a
statement block). ``objectloop`` performs the :samp:`{statement}` once for
-every object defined in the (``variable``) . If we were to code:
+every object defined in the (:samp:`{variable}`) . If we were to code:
:samp:`objectloop (item) {statement};`
food: ! code for the food...
menu: ! code for the menu...
default:
- "~I don't
+ "~I don't think that's on the menu, sir.~";
}
],
Some last lousy points
========================
+.. highlight:: inform
+
+.. default-role:: samp
+
.. only:: html
.. image:: /images/picF.png
Expressions
===========
-In this guide we’ve used the placeholder ``expression`` a few times;
+In this guide we’ve used the placeholder `{expression}` a few times;
here's roughly what we mean.
-* An ``expression`` is a single ``value``, or several ``values``
- combined using ``operators`` and sometimes parentheses ``(...)``.
+* An `{expression}` is a single `{value}`, or several `{values}`
+ combined using `{operators}` and sometimes parentheses ``(...)``.
-* Possible ``values`` include:
+* Possible `{values}` include:
* a literal number (-32768 to 32767)
* (only in a run-time statement, not in a compile-time directive) the
contents of a variable, or the return value from a routine.
-* Possible ``operators`` include:
+* Possible `{operators}` include:
* an arithmetic operator: ``+ - * / % ++``
* a bitwise logical operator: ``& | ~``
* an object conditional operator: ``ofclass in notin provides has hasnt``
* a boolean combinational operator: ``&& || ~~``
-
Internal IDs
============
variables, routines, etc. -- need to be given a name so that other items
can refer to them. We call this name an item's internal identifier
(because it's used only within the source file and isn't visible to the
-player), and we use the placeholders ``obj_id``, ``var_id``,
-``routine_id``, etc. to represent where it's used. An internal ID
+player), and we use the placeholders `{obj_id}`, `{var_id}`,
+`{routine_id}`, etc. to represent where it's used. An internal ID
* can be up to thirty-two characters long
Statements
==========
+.. todo::
+
+ We might need some custom syntax highlighting here.
+
A :term:`statement` is an instruction intended for the interpreter, telling
it what to do at run-time. It *must* be given in lower-case, and always
ends with a semicolon.
Some statements, like ``if``, control one or more other statements. We
-use the placeholder ``statement_block`` to represent either a single
-``statement``, or any number of ``statements`` enclosed in braces:
-
-.. todo::
-
- We might need some custom syntax highlighting here
-
-.. code-block:: inform
+use the placeholder `{statement_block}` to represent either a single
+`{statement}`, or any number of `{statements}` enclosed in braces::
statement;
-------------------------
Our games have used these statements, about half of the Inform
-possibilities:
-
-.. code-block:: inform
+possibilities::
give obj_id attribute;
give obj_id attribute attribute ... attribute;
-----------------------------
Although our example games haven't needed to use them, these looping
-statements are sometimes useful:
-
-.. code-block:: inform
+statements are sometimes useful::
break;
continue;
On the other hand, we suggest that you put the following statements on
hold for now; they're not immediately relevant to everyday code and have
-mostly to do with printing and formatting:
-
-.. code-block:: inform
+mostly to do with printing and formatting::
box
font
Print rules
-----------
-In ``print`` and ``print_ret`` statements, each ``value`` can be:
+In ``print`` and ``print_ret`` statements, each `{value}` can be:
-* a numeric ``expression``, displayed as a signed decimal number,
+* a numeric `{expression}`, displayed as a signed decimal number,
-* a ``"string"``, displayed literally, or
+* a `"{string}"`, displayed literally, or
* a print rule. You can create your own, or use a standard one, including:
.. tabularcolumns:: ll
+-------------------------+---------------------------------------------------+
- | ``(a) obj_id`` | the object's name, preceded by "a", "an" or "some"|
+ | `(a) {obj_id}` | the object's name, preceded by "a", "an" or "some"|
+-------------------------+---------------------------------------------------+
- | ``(A) obj_id`` | as ``(a)`` but using "A", "An" or "Some" |
+ | `(A) {obj_id}` | as ``(a)`` but using "A", "An" or "Some" |
+-------------------------+---------------------------------------------------+
- | ``(the) obj_id`` | the object's name, preceded by "the" |
+ | `(the) {obj_id}` | the object's name, preceded by "the" |
+-------------------------+---------------------------------------------------+
- | ``(The) obj_id`` | as ``(the)`` but using "The" |
+ | `(The) {obj_id}` | as ``(the)`` but using "The" |
+-------------------------+---------------------------------------------------+
- | ``(number) expression`` | the numeric expression's value in words |
+ | `(number) {expression}` | the numeric expression's value in words |
+-------------------------+---------------------------------------------------+
-
Directives
==========
We've used all of these directives; note that for ``Class``, ``Extend``,
``Object`` and ``Verb`` the full supported syntax is more sophisticated
-than the basic form presented here:
-
-.. code-block:: inform
+than the basic form presented here::
Class class_id
with property value,
-----------------------------
There's only a handful of useful directives which we haven't needed to
-use:
-
-.. code-block:: inform
+use::
Attribute attribute;
Statusline score;
Statusline time;
-but there's a whole load which are of fairly low importance for now:
-
-.. code-block:: inform
+but there's a whole load which are of fairly low importance for now::
Abbreviate
Array
You can create and initialise a property in an object's ``with`` segment:
-.. code-block:: inform
-
property, ! set to zero / false
property value, ! set to a single value
property value value ... value, ! set to a list of values
-In each case, the ``value`` is either a compile-time ``expression``, or
-an embedded routine:
-
-.. code-block:: inform
+In each case, the `{value}` is either a compile-time `{expression}`, or
+an embedded routine::
property expression,
property [; statement; statement; ... statement; ],
-
-You can refer to the value of a property:
-
-.. code-block:: inform
+You can refer to the value of a property::
self.property ! only within that same object
obj_id.property ! everywhere
-and you can test whether an object definition includes a given property:
-
-.. code-block:: inform
+and you can test whether an object definition includes a given property::
(obj_id provides property) ! is true or false
Standalone routines
-------------------
-Standalone routines are defined like this:
-
-.. code-block:: inform
+Standalone routines are defined like this::
[ routine_id; statement; statement; ... statement; ];
-and called like this:
-
-.. code-block:: inform
+and called like this::
routine_id()
Embedded routines
-----------------
-These are embedded as the value of an object's property:
-
-.. code-block:: inform
+These are embedded as the value of an object's property::
property [; statement; statement; ... statement; ],
-and are usually called automatically by the library, or manually by:
-
-.. code-block:: inform
+and are usually called automatically by the library, or manually by::
self.property() ! only within that same object
Both types of routine support up to fifteen local variables -- variables
which can be used only by the statements within the routine, and which
are automatically initialised to zero every time that the routine is
-called:
-
-.. code-block:: inform
+called::
[ routine_id var_id var_id ... var_id; statement; statement; ... statement; ];
You can pass up to seven arguments to a routine, by listing those
arguments within the parentheses when you call the routine. The effect
is simply to initialise the matching local variables to the argument
-values rather than to zero:
-
-.. code-block:: inform
+values rather than to zero::
routine_id(expression, expression, ... expression)
-------------
Every routine returns a single value, which is supplied either
-explicitly by some form of return statement:
-
-.. code-block:: inform
+explicitly by some form of return statement::
[ routine_id; statement; statement; ... return expr; ]; ! returns expr
property [; statement; statement; ... return expr; ], ! returns expr
-or implicitly when the routine runs out of statements. If none of these
-``statements`` is one -- ``return``, ``print_ret``, ``"..."` or
-``<<...>>`` -- that causes an explicit return, then:
-
-.. code-block:: inform
+or implicitly when the routine runs out of statements. If none of these
+``statements`` is one -- ``return``, ``print_ret``, ``"..."`` or
+``<<...>>`` -- that causes an explicit return, then::
[ routine_id; statement; statement; ... statement; ];
-returns ``true`` and
-
-.. code-block:: inform
+returns ``true`` and ::
property [; statement; statement; ... statement; ]
return False.
Here's an example standalone routine which returns the larger of its two
-argument values:
-
-.. code-block:: inform
+argument values::
[ Max a b; if (a > b) return a; else return b; ];
and here are some examples of its use (note that the first example,
-though legal, does nothing useful whatsoever):
-
-.. code-block:: inform
+though legal, does nothing useful whatsoever)::
Max(x,y);
A library routine is a standard routine, included within the library
files, which you can optionally call from your source file if you
require the functionality which the routine provides. We've mentioned
-these library routines:
-
-.. code-block:: inform
+these library routines::
IndirectlyContains(parent_obj_id, obj_id)
By contrast, an entry point routine is a routine which you can provide
in your source file, in which case the library calls it at an
-appropriate time. We've mentioned these optional entry point routines:
-
-.. code-block:: inform
+appropriate time. We've mentioned these optional entry point routines::
DeathMessage()
InScope(actor_obj_id)
-And this, the only mandatory one:
-
-.. code-block:: inform
+And this, the only mandatory one::
Initialise()
This is doubly true if you ever contemplate sharing a library extension
with the rest of the community. This example, with the name changed, is
-from a file in the Archive:
-
-.. code-block:: inform
+from a file in the Archive::
[xxxx i j;
if (j==0) rtrue;
Here's the same routine after a few minutes spent purely on making it
more comprehensible; we haven't actually tested that it (still) works,
-though that second ``else`` looks suspicious:
-
-.. code-block:: inform
+though that second ``else`` looks suspicious::
[ xxxx i j;
if (i in player || i has static or scenery || j == nothing) return true;
There are a few statement shortcuts, some more useful than others, which
you'll come across.
-* These five lines all do the same thing:
-
- .. code-block:: inform
+* These five lines all do the same thing::
return true;
return 1;
rtrue;
]; ! at the end of a standalone routine
-* These four lines all do the same thing:
-
- .. code-block:: inform
+* These four lines all do the same thing::
return false;
return 0;
rfalse;
]; ! at the end of an embedded routine
-* These four lines all do the same thing:
-
- .. code-block:: inform
+* These four lines all do the same thing::
print "string"; new_line; return true;
print "string^"; return true;
print_ret "string";
"string";
-* These lines are the same:
-
- .. code-block:: inform
+* These lines are the same::
print value1; print value2; print value3;
print value1, value2, value3;
-* These lines are the same:
-
- .. code-block:: inform
+* These lines are the same::
<action noun second>; return true;
<<action noun second>>;
-* These lines are also the same:
-
- .. code-block:: inform
+* These lines are also the same::
print "^";
new_line;
-* These ``if`` statements are equivalent:
-
- .. code-block:: inform
+* These ``if`` statements are equivalent::
if (MyVar == 1 || MyVar == 3 || MyVar == 7) ...
if (MyVar == 1 or 3 or 7) ...
-* These ``if`` statements are equivalent as well:
-
- .. code-block:: inform
+* These ``if`` statements are equivalent as well::
if (MyVar ~= 1 && MyVar ~= 3 && MyVar ~= 7) ...
if (MyVar ~= 1 or 3 or 7) ...
* In an ``if`` statement, the thing in parentheses can be *any*
expression; all that matters is its value: zero (false) or anything
- else (true). For example, these statements are equivalent:
-
- .. code-block:: inform
+ else (true). For example, these statements are equivalent::
if (MyVar ~= false) ...
if (~~(MyVar == false)) ...
Note that the following statement specifically tests whether ``MyVar``
contains ``true`` (1), *not* whether its value is anything other than
- zero.
-
- .. code-block:: inform
+ zero. ::
if (MyVar == true) ...
* If ``MyVar`` is a variable, the statements ``MyVar++;`` and
``++MyVar;`` work the same as ``MyVar = MyVar + 1;`` For example,
- these lines are equivalent:
-
- .. code-block:: inform
+ these lines are equivalent::
MyVar = MyVar + 1; if (MyVar == 3) ...
if (++MyVar == 3) ...
value. In the example, if ``MyVar`` currently contains 2 then
``++MyVar`` returns 3 and ``MyVar++`` returns 2, even though in both
cases the value of ``MyVar`` afterwards is 3. As another example,
- this code (from Helga in "William Tell"):
-
- .. code-block:: inform
+ this code (from Helga in "William Tell")::
Talk: self.times_spoken_to = self.times_spoken_to + 1;
switch (self.times_spoken_to) {
}
],
- could have been written more succinctly like this:
-
- .. code-block:: inform
+ could have been written more succinctly like this::
Talk: switch (++self.times_spoken_to) {
1: score++;
],
* Similarly, the statements ``MyVar--;`` and ``--MyVar;`` work the same
- as ``MyVar = MyVar - 1;`` Again, these lines are equivalent:
-
- .. code-block:: inform
+ as ``MyVar = MyVar - 1;`` Again, these lines are equivalent::
MyVar = MyVar - 1; if (MyVar == 7) ...
if (--MyVar == 7) ...
confined to library extensions (for example, the ``pname.h`` extension
which we encountered in :doc:`12` gives every object a ``pname`` property
and a ``phrase_matched`` attribute). To create them, you would use these
-directives near the start of your source file:
-
-.. code-block:: inform
+directives near the start of your source file::
Attribute attribute;
``found_in`` properties. For example, in "William Tell" we defined
twenty-seven objects; omitting those which used ``found_in`` to define
their placement at the start of the game, we're left with object
-definitions starting like this:
-
-.. code-block:: inform
+definitions starting like this::
Room street "A street in Altdorf"
There's an alternative object syntax which is available to achieve the
same object tree, using "arrows". That is, we could have defined those
-parent-and-child objects as:
-
-.. code-block:: inform
+parent-and-child objects as::
Room below_square "Further along the street"
Furniture -> stall "fruit and vegetable stall"
``-> ->``, and so on. In "William Tell", that situation doesn't occur;
to illustrate how it works, imagine that at the start of the game the
potatoes and the other fruit and vegetables where actually *on* the
-stall. Then we might have used:
-
-.. code-block:: inform
+stall. Then we might have used::
Room below_square "Further along the street"
Furniture -> stall "fruit and vegetable stall"
the difference between double quotes ``"..."`` (strings to be output) and
single quotes ``'...'`` (input tokens -- dictionary words). Perhaps
somewhat unfortunately, Inform allows you to blur this clean distinction:
-you can use double quotes in name properties and Verb directives:
-
-.. code-block:: inform
+you can use double quotes in name properties and Verb directives::
NPC stallholder "Helga" below_square
with name "stallholder" "greengrocer" "monger" "shopkeeper" "merchant"
roughly the same as ``->``) and ``near`` conditions (roughly, having the
same parent), or with ``" \ "`` controlling line breaks in long
``print`` statements. Try to understand them; try *not* to use them.
-
-
Although the spell made by the compiler is always the same one, you can
indicate up to a point how you want the magic to happen. There are a few
options to affect the process of compilation; some you define in the
-source code, some with ``switches`` and certain commands when you run
+source code, some with *switches* and certain commands when you run
the program. The compiler will work with some default options if you
don’t define any, but you may change these if you need to. Many of these
options are provided "just in case" special conditions apply; others are
indicates), with a maximum size of 256 Kbytes. If your game is larger
than this, you’ll have to compile into Version 8 file (``.z8``), which
can grow up to 512 Kbytes (and you do this very simply by setting the
-``-v8`` switch; more on that in a minute). It takes a surprising amount
+:option:`-v8` switch; more on that in a minute). It takes a surprising amount
of code to exceed these limits; you won’t have to worry about game size
for the next few months, if ever.
-
.. rubric:: Non-fatal errors
Non-fatal errors are much more common. You'll learn to be friends with:
This is the standard way of reporting a punctuation or syntax mistake.
If you type a comma instead of a semicolon, Inform will be looking for
something in vain. The good news is that you are pointed to the
-offending line of code:
-
-.. code-block:: transcript
+offending line of code::
Tell.inf(76): Error: Expected directive, '[' or class name but found found_in
> found_in
Here's a rather misleading message which maybe suggests that things in
our source file are in the wrong order, or that some expected
-punctuation is missing:
-
-.. code-block:: transcript
+punctuation is missing::
Fate.inf(459): Error: Expected name for new object or its textual short name
but found door
happen. Inform detects the fault and warns you. Probably the designer's
intention was:
+.. code-block:: inform
+
+ if (steel_door has open) {
+ give match ~light;
+ print_ret "The breeze blows out your lit match.";
+ }
+
Compiling *à la carte*
======================
systems and machines. Specific usage of the compiler varies accordingly,
but some features should be in all environments. To obtain precise
information about any particular version, run the compiler with the
-``-h1`` switch -- see :ref:`switches`.
+:option:`-h1` switch -- see :ref:`switches`.
Often the compiler is run with the name of your source file as its only
parameter. This tells the compiler to "read this file using Strict mode and
.. note::
- on some machines, a library file is actually called -- for example --
+ On some machines, a library file is actually called -- for example --
``Parser.h``, on others just ``Parser``. The compiler automatically
deals with such differences; you can *always* type simply ``Include
"Parser";`` in your source file.
:samp:`inform {source_file story_file switches}`
-where "``inform``" is the name of the compiler, the
-:samp:`{story_file}` is optional (so that you can specify a different
-name from the
-:samp:`{source_file}`) and the switches are also optional. Note that
-switches must be preceded by a hyphen ``-``; if you want to set, for
-instance, Strict mode, you'd write ``-S`` , while if you want to
-deactivate it, you’d write ``-~S``. The tilde sign can, as elsewhere, be
-understood as "not". If you wish to set many switches, just write them
-one after another separated by spaces and each with its own hyphen, or
-merge them with one hyphen and no spaces:
+where "``inform``" is the name of the compiler, the :samp:`{story_file}` is
+optional (so that you can specify a different name from the
+:samp:`{source_file}`) and the switches are also optional. Note that
+switches must be preceded by a hyphen ``-``; if you want to set, for
+instance, Strict mode, you'd write :option:`-S` , while if you want to
+deactivate it, you’d write :option:`-~S`. The tilde sign can, as elsewhere,
+be understood as "not". If you wish to set many switches, just write them
+one after another separated by spaces and each with its own hyphen, or
+merge them with one hyphen and no spaces::
- :samp:`inform MyGame.inf -S -s -X`
+ inform MyGame.inf -S -s -X
- :samp:`inform MyGame.inf -Ssx`
+ inform MyGame.inf -Ssx
Although there's nothing wrong with this method, it isn't awfully
convenient should you need to change the switch settings. A more
flexible method is to define the switches at the very start of your
-source file, again in either format:
+source file, again in either format::
- :samp:`!% -S -s -X`
+ !% -S -s -X
- :samp:`!% -Ssx`
+ !% -Ssx
-Normally, all switches are off by default, except Strict mode (``-S``),
-which is on and checks the code for additional mistakes. It's well worth
-adding Debug mode (``-D``), thus making the debugging verbs available at
-run time. This is the ideal setting while coding, but you should turn
-Debug mode off (just remove the ``-D``) when you release your game to
-the public. This is fortunately very easy to check, since the game
-banner ends with the letter "D" if the game was compiled in Debug mode:
+Normally, all switches are off by default, except Strict mode
+(:option:`-S`), which is on and checks the code for additional
+mistakes. It's well worth adding Debug mode (:option:`-D`), thus making the
+debugging verbs available at run time. This is the ideal setting while
+coding, but you should turn Debug mode off (just remove the :option:`-D`)
+when you release your game to the public. This is fortunately very easy to
+check, since the game banner ends with the letter "D" if the game was
+compiled in Debug mode:
.. code-block:: transcript
Switches are case sensitive, so you get different effects from ``-x``
and ``-X``. Some of the more useful switches are:
-:samp:`-~S`
- Set compiler Strict mode off. This deactivates some additional error
- checking features when it reads your source file. Strict mode is on by
- default.
-
-:samp:`-v5 -v8`
- Compile to this version of story file. Versions 5 (on by default) and
- 8 are the only ones you should ever care about; they produce,
- respectively, story files with the extensions .z5 and .z8 . Version 5
- was the Advanced Infocom design, and is the default produced by
- Inform. This is the version you'll normally be using, which allows
- file sizes up to 256 Kbytes. If your game grows beyond that size,
- you'll need to compile to the Version 8 story file, which is very
- similar to Version 5 but allows a 512 Kbytes file size.
-
-:samp:`-D -X`
- Include respectively the debugging verbs and the Infix debugger in the
- story file (see :doc:`16`).
-
-:samp:`-h1 -h2`
- Display help information about the compiler. ``-h1`` produces
- information about file naming, and ``-h2`` about the available
- switches.
-
-:samp:`-n -j`
- ``-n`` displays the number of declared attributes, properties and
- actions. ``-j`` lists objects as they are being read and constructed
- in the story file.
-
-:samp:`-s`
- Offer game statistics. This provides a lot of information about your
- game, including the number of objects, verbs, dictionary entries,
- memory usage, etc., while at the same time indicating the maximum
- allowed for each entry. This can be useful to check whether you are
- nearing the limits of Inform.
-
-:samp:`-r`
- Record all the text of the game into a temporary file, useful to check
- all your descriptions and messages by running them through a spelling
- checker.
-
-If you run the compiler with the ``-h2`` switch, you’ll find that there
-are many more switches than these, offering mostly advanced or obscure
-features which we consider to be of little interest to beginners.
-However, feel free to try whatever switches catch your eye; nothing you
-try here will affect your source file, which is strictly read-only as
-far as the compiler is concerned.
+.. option:: -S
+.. option:: -~S
+
+ Set compiler Strict mode on or off, respectively. Strict mode activates
+ some additional error checking features when it reads your source file.
+ Strict mode is on by default.
+
+.. option:: -v5
+.. option:: -v8
+
+ Compile to this version of story file. Versions 5 (on by default) and
+ 8 are the only ones you should ever care about; they produce,
+ respectively, story files with the extensions .z5 and .z8. Version 5
+ was the Advanced Infocom design, and is the default produced by
+ Inform. This is the version you'll normally be using, which allows
+ file sizes up to 256 Kbytes. If your game grows beyond that size,
+ you'll need to compile to the Version 8 story file, which is very
+ similar to Version 5 but allows a 512 Kbytes file size.
+
+.. option:: -D
+.. option:: -X
+
+ Include respectively the debugging verbs and the Infix debugger in the
+ story file (see :doc:`16`).
+
+.. option:: -h1
+.. option:: -h2
+
+ Display help information about the compiler. :option:`-h1` produces
+ innformation about file naming, and :option:`-h2` about the available
+ switches.
+
+.. option:: -n
+.. option:: -j
+
+ :option:`-n` displays the number of declared attributes, properties and
+ actions. :option:`-j` lists objects as they are being read and constructed
+ in the story file.
+
+.. option:: -s
+.. option:: -~s
+
+ Offer game statistics (or not). This provides a lot of information about
+ your game, including the number of objects, verbs, dictionary entries,
+ memory usage, etc., while at the same time indicating the maximum
+ allowed for each entry. This can be useful to check whether you are
+ nearing the limits of Inform.
+
+.. option:: -r
+
+ Record all the text of the game into a temporary file, useful to check
+ all your descriptions and messages by running them through a spelling
+ checker.
+If you run the compiler with the :option:`-h2` switch, you’ll find that
+there are many more switches than these, offering mostly advanced or
+obscure features which we consider to be of little interest to beginners.
+However, feel free to try whatever switches catch your eye; nothing you try
+here will affect your source file, which is strictly read-only as far as
+the compiler is concerned.
-===================
-Debugging your game
-===================
+=====================
+ Debugging your game
+=====================
.. only:: html
To help you out in this daunting task, Inform has a stock of special
actions: the debugging verbs. They become available at run-time when the
-source file is compiled in :term:`Debug mode` (``-D switch``). When you are
-ready to release your game, you’ll have to recompile, switching off Debug
-to avoid allowing the players to benefit from the debugging verbs. We'll
-cover briefly a few of these actions, and tell you what they do.
-
+source file is compiled in :term:`Debug mode` (:option:`-D` switch). When
+you are ready to release your game, you’ll have to recompile, switching off
+Debug to avoid allowing the players to benefit from the debugging verbs.
+We'll cover briefly a few of these actions, and tell you what they do.
Command lists
=============
``container``, a ``supporter`` , or something ``animate``.
-Infix: the harlot's perogative
-==============================
+Infix: the harlot's prerogative
+===============================
-The basic debugging verbs are fairly versatile, easy to use, and don't
-consume a lot of memory. Occasionally though, you'll meet a bug which
-you simply can't catch using regular techniques, and that’s when you
-might want to investigate the Infix debugger. You'll need to compile
-using the ``-X`` switch, and you'll then be able to monitor and modify
-almost all of your game’s data and objects. For instance, you can use
-";" to inspect -- and change -- a variable:
+The basic debugging verbs are fairly versatile, easy to use, and don't
+consume a lot of memory. Occasionally though, you'll meet a bug which you
+simply can't catch using regular techniques, and that’s when you might want
+to investigate the Infix debugger. You'll need to compile using the
+:option:`-X` switch, and you'll then be able to monitor and modify almost
+all of your game’s data and objects. For instance, you can use ";" to
+inspect -- and change -- a variable:
.. code-block:: transcript
"OK, Herr Tell, now you're in real trouble.
...
-.. todo:: "Herr" above is italicized. Was that a mistake in the original text?
+.. todo::
+
+ "Herr" above is italicized. Was that a mistake in the original text?
+
+ Update: I don't think so. In 08.rst, lines 465 and 516, "Herr" is
+ explicitly underlined (which probably appears italicized on output).
Infix is quite complex -- there are more commands than those we have
shown you -- so while it's good to have available, it's not really a
You won't need it often, but Infix can sometimes provide quick answers
to tricky problems.
-
No matter what
==============
* Benny will force the player back into the cafe even when the key is
dropped in the café, or put on the counter (in Benny's plain sight!).
-Of course, the code we've offered you in this edition takes care of
+Of course, the code we've offered you in *this* edition takes care of
those embarrassing issues, but it might very well happen that a few more
undetected absurdities pop up from now on.
ask in RAIF for kind souls willing to have a go at your game. Remember
the golden rules:
- * **Expect no mercy**. Although it hurts, a merciless approach is what
- you need at this time; much better to discover your errors and
- oversights now, before you release the game more widely. And don't
- forget to acknowledge your testers' assistance somewhere within the
- game.
-
- * **Never say never**. If your testers suggest that the game should
- respond better to an attempted action, don't automatically respond
- with "No one's going to try that!" They already have, and will again
- -- be grateful for your testers' devious minds and twisted psyches.
- Although a normal player won't try all of those oddball things,
- every player is bound to try at least one, and their enjoyment will
- be greater, the reality enhanced, if the game "understands".
-
- * **Ask for more**. Don't treat your testers simply as validators of
- your programming skills, but rather as reviewers of your
- storytelling abilities. Encourage them to comment on how well the
- pieces fit together, and to make suggestions -- small or radical --
- for improvement; don't necessarily reject good ideas just because
- implementing them "will take too long". For example: "the scene in
- the Tower of London doesn't somehow seem to belong in an Arabian
- Nights game", or "having to solve three puzzles in a row just to
- discover the plate of sheep's eyes is a little over the top", or
- "this five-room trek across the desert really is a bit dull;
- perhaps you could add a quicksand or something to liven it up?", or
- "the character of the eunuch in the harem seems to be lacking in
- something". That is, view the testers collectively not as simple
- spell-checkers, but rather as collaborative editors on your latest
- novel.
+* **Expect no mercy**. Although it hurts, a merciless approach is what you
+ need at this time; much better to discover your errors and oversights
+ now, before you release the game more widely. And don't forget to
+ acknowledge your testers' assistance somewhere within the game.
+
+* **Never say never**. If your testers suggest that the game should
+ respond better to an attempted action, don't automatically respond with
+ "No one's going to try that!" They already have, and will again -- be
+ grateful for your testers' devious minds and twisted psyches. Although a
+ normal player won't try *all* of those oddball things, every player is
+ bound to try at least *one*, and their enjoyment will be greater, the
+ reality enhanced, if the game "understands".
+
+* **Ask for more**. Don't treat your testers simply as validators of your
+ programming skills, but rather as reviewers of your storytelling
+ abilities. Encourage them to comment on how well the pieces fit together,
+ and to make suggestions -- small or radical -- for improvement; don't
+ necessarily reject good ideas just because implementing them "will take
+ too long". For example: "the scene in the Tower of London doesn't somehow
+ seem to belong in an Arabian Nights game", or "having to solve three
+ puzzles in a row just to discover the plate of sheep's eyes is a little
+ over the top", or "this five-room trek across the desert really is a bit
+ dull; perhaps you could add a quicksand or something to liven it up?", or
+ "the character of the eunuch in the harem seems to be lacking in
+ something". That is, view the testers collectively not as simple
+ spell-checkers, but rather as collaborative editors on your latest novel.
-- The Continental Op in Dashiell Hammett's *Red Harvest*.
-
.. only:: html
.. image:: /images/picJ.png
And, who knows? It might be that next year we’ll all be smashed by
*your* entry.
-
.. todo:: This signoff should be aligned to the right side.
*Sonja and Roger*
# documentation root, use os.path.abspath to make it absolute, like shown here.
sys.path.insert(0, ".")
+import tools.sphinxpatch
+
from tools.inform import InformLexer
from tools.transcript import TranscriptLexer
+++ /dev/null
-====================
- About this version
-====================
-
-This version of the IBG is converted from the 3rd edition PDF file. It's a
-work-in-progress. Here's a partial list of stuff still to do, with
-references to their places in the text:
-
-.. todolist::
copyright
history
+ todo
.. toctree::
:maxdepth: 1
* :ref:`genindex`
* :ref:`search`
-
- .. toctree::
-
- endnotes
--- /dev/null
+============
+ TO-DO list
+============
+
+This version of the IBG is converted from the 3rd edition PDF file. It's
+currently a work-in-progress. Here's a partial list of things still to
+address, with references to their places in the text:
+
+.. todolist::
"time_left", "time_out", "when_closed", "when_open", "when_on",
"when_off", "with_key"]
-keywords = ["box", "break", "continue", "do", "else", "font off", "font on",
+extension_properties = ["pname"]
+
+keywords = ["box", "break", "continue", "do", "else", "font",
"for", "give", "has", "hasnt", "if", "in", "inversion", "jump",
"move", "new_line", "notin", "objectloop", "ofclass", "or",
"print", "print_ret", "provides", "quit", "read", "remove",
(r'\\', Text),
(r'=', Operator),
(r"[A-Za-z_,]+:", Name.Label),
- (r"<<\S+>>", Name.Label),
+ (r"<.+?>", Name.Label),
(wordlist(objects), Name.Class),
(wordlist(keywords), Token.Keyword.Reserved),
(wordlist(attributes), Name.Attribute),
(wordlist(constants), Name.Constant),
+ (wordlist(extension_properties), Name.Builtin),
+
(r'[a-zA-Z_][a-zA-Z0-9_.]*', Name),
(r'(\d+\.?\d*|\d*\.\d+)([eE][+-]?[0-9]+)?', Number.Float),
(r'\d+', Number.Integer),
--- /dev/null
+"""
+Various monkey-patches for sphinx.
+"""
+
+# Tweak Sphinx domain option regexp to add ~ for Inform options.
+import re
+import sphinx.domains.std as std
+
+std.option_desc_re = re.compile(r'((?:/|--|-|\+)?[-?@~#_a-zA-Z0-9]+)(=?\s*.*)')
+