-======================
-Some last lousy points
-======================
+========================
+ Some last lousy points
+========================
+
+.. highlight:: inform
+
+.. default-role:: samp
.. only:: html
be ignored for the time being; when you become an accomplished designer,
you will decide what matters and what can be left on the shelf.
-We'll also talk, in "Reading other people's code" on page 181, about a
-few ways of doing things that we've chosen not to tell you about, but
-which you're quite likely to encounter if you look at Inform code
-written by other designers.
+We'll also talk, in :ref:`reading-other-code`, about a few ways of doing
+things that we've chosen not to tell you about, but which you're quite
+likely to encounter if you look at Inform code written by other designers.
The tone here is perhaps a little dry, but trust us: in walking this
dusty ground we touch on just about everything that is fundamental in
your overall understanding of Inform. And as always, the *Inform
Designer's Manual* provides rounder and more comprehensive coverage.
-
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
used (except that a routine's local variables are not visible outside
that routine).
+.. _statements:
Statements
==========
-A **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
+ We might need some custom syntax highlighting here.
-.. code-block:: inform6
+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::
statement;
{ statement; statement; ... statement; }
-.. rubric:: Statements that we've met
+Statements that we've met
+-------------------------
Our games have used these statements, about half of the Inform
-possibilities:
-
-.. code-block:: inform6
+possibilities::
give obj_id attribute;
give obj_id attribute attribute ... attribute;
<<action noun>>;
<<action noun second>>;
-
-.. rubric:: Statements that we've not met
+Statements that we've not met
+-----------------------------
Although our example games haven't needed to use them, these looping
-statements are sometimes useful:
-
-.. code-block:: inform6
+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:: inform6
+mostly to do with printing and formatting::
box
font
In particular, avoid using the deprecated jump statement if you possibly can.
-.. rubric:: Print rules
+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
==========
-A **directive** is an instruction intended for the compiler, telling it
-what to do at compile-time, while the source file is being translated
-into Z-code. By convention it's given an initial capital letter (though
-the compiler doesn't enforce this) and always ends with a semicolon.
+A :term:`directive` is an instruction intended for the compiler, telling it
+what to do at compile-time, while the source file is being translated into
+Z-code. By convention it's given an initial capital letter (though the
+compiler doesn't enforce this) and always ends with a semicolon.
-.. rubric:: Directives that we've met
+Directives that we've met
+-------------------------
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:: inform6
+than the basic form presented here::
Class class_id
with property value,
#Ifdef any_id; ... #Endif;
-.. rubric:: Directives that we've not met
+Directives that we've not met
+-----------------------------
There's only a handful of useful directives which we haven't needed to
-use:
-
-.. code-block:: inform6
+use::
Attribute attribute;
Statusline score;
Statusline time;
-but there's a whole load which are of fairly low importance for now:
-
-.. code-block:: inform6
+but there's a whole load which are of fairly low importance for now::
Abbreviate
Array
System_file
Zcharacter
+.. _objects:
+
Objects
=======
of the model world. Full variables are called properties; simpler
two-state variables are attributes.
-.. rubric:: Properties
+Properties
+----------
The library defines around forty-eight standard property variables (such
as ``before`` or ``name``), but you can readily create further ones just
You can create and initialise a property in an object's ``with`` segment:
-.. code-block:: inform6
-
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:: inform6
+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:: inform6
+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:: inform6
+and you can test whether an object definition includes a given property::
(obj_id provides property) ! is true or false
+.. _routines:
Routines
========
Inform provides standalone routines and embedded routines.
-.. rubric:: Standalone routines
+Standalone routines
+-------------------
-Standalone routines are defined like this:
-
-.. code-block:: inform6
+Standalone routines are defined like this::
[ routine_id; statement; statement; ... statement; ];
-and called like this:
-
-.. code-block:: inform6
+and called like this::
routine_id()
-.. rubric:: Embedded routines
+Embedded routines
+-----------------
-These are embedded as the value of an object's property:
-
-.. code-block:: inform6
+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:: inform6
+and are usually called automatically by the library, or manually by::
self.property() ! only within that same object
obj_id.property() ! everywhere
-.. rubric:: Arguments and local variables
+Arguments and local variables
+-----------------------------
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:: inform6
+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:: inform6
+values rather than to zero::
routine_id(expression, expression, ... expression)
because there is no mechanism for the library to supply argument values
when calling the routine.
-
-.. rubric:: Return values
+Return values
+-------------
Every routine returns a single value, which is supplied either
-explicitly by some form of return statement:
-
-.. code-block:: inform6
+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:: inform6
+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:: inform6
+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:: inform6
+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:: inform6
+though legal, does nothing useful whatsoever)::
Max(x,y);
switch (Max(3,y)) { ...
-
-.. rubric:: Library routines versus entry points
-
+Library routines versus entry points
+------------------------------------
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:: inform6
+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:: inform6
+appropriate time. We've mentioned these optional entry point routines::
DeathMessage()
InScope(actor_obj_id)
-And this, the only mandatory one:
-
-.. code-block:: inform6
+And this, the only mandatory one::
Initialise()
-There are full lists in "Library routines" on page 264 and "Optional
-entry points" on page 270.
+There are full lists in :ref:`library-routines` and :ref:`entry-points`.
+.. _reading-other-code:
Reading other people's code
===========================
*consistent* about its use. In this section, we highlight some of the
more obvious differences which you may encounter.
-.. rubric:: Code layout
+Code layout
+-----------
Every designer has his or her own style for laying out their source
code, and they're all worse than the one you adopt. Inform's flexibility
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:: inform6
+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:: inform6
+though that second ``else`` looks suspicious::
[ xxxx i j;
if (i in player || i has static or scenery || j == nothing) return true;
We hope you'll agree that the result was worth the tiny extra effort.
Code gets written once; it gets read dozens and dozens of times.
-.. rubric:: Shortcuts
+Shortcuts
+---------
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:: inform6
+* 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:: inform6
+* 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:: inform6
+* 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:: inform6
+* These lines are the same::
print value1; print value2; print value3;
print value1, value2, value3;
-* These lines are the same:
-
- .. code-block:: inform6
+* These lines are the same::
<action noun second>; return true;
<<action noun second>>;
-* These lines are also the same:
-
- .. code-block:: inform6
+* These lines are also the same::
print "^";
new_line;
-* These ``if`` statements are equivalent:
-
- .. code-block:: inform6
+* 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:: inform6
+* 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:: inform6
+ 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:: inform6
+ 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:: inform6
+ 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:: inform6
+ 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:: inform6
+ 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:: inform6
+ as ``MyVar = MyVar - 1;`` Again, these lines are equivalent::
MyVar = MyVar - 1; if (MyVar == 7) ...
if (--MyVar == 7) ...
if (MyVar-- == 8) ...
-.. rubric:: "number" property and "general" attribute
+"number" property and "general" attribute
+-----------------------------------------
The library defines a standard ``number`` property and a standard
``general`` attribute, whose roles are undefined: they are
instead create new property variables -- with appropriate names -- as
part of your ``Object`` and ``Class`` definitions.
-.. rubric:: Common properties and attributes
+.. _common-props:
-As an alternative to creating new individual properties which apply only
-to a single object (or class of objects), it's possible to devise
-properties and new attributes which, like those defined by the library,
-are available on *all* objects. The need to do this is actually quite
-rare, and is mostly confined to library extensions (for example, the
-``pname.h`` extension which we encountered in "Captain Fate: take 3" on
-page 147 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:
+Common properties and attributes
+--------------------------------
-.. code-block:: inform6
+As an alternative to creating new individual properties which apply only to
+a single object (or class of objects), it's possible to devise properties
+and new attributes which, like those defined by the library, are available
+on *all* objects. The need to do this is actually quite rare, and is mostly
+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::
Attribute attribute;
On the other hand, the number of individual properties which you can add
is virtually unlimited.
-.. rubric:: Setting up the object tree
+.. _setting-up-tree:
+
+Setting up the object tree
+--------------------------
Throughout this guide, we've defined the initial position of each object
within the overall object tree either by explicitly mentioning its
``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:: inform6
+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:: inform6
+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:: inform6
+stall. Then we might have used::
Room below_square "Further along the street"
Furniture -> stall "fruit and vegetable stall"
We prefer to explicitly name the parent, but you'll encounter both forms
very regularly.
-.. rubric:: Quotes in "name" properties
-
-We went to some lengths, way back in "Things in quotes" on page 55, to
-explain 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:
+Quotes in "name" properties
+---------------------------
-.. code-block:: inform6
+We went to some lengths, way back in :ref:`things-in-quotes`, to explain
+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::
NPC stallholder "Helga" below_square
with name "stallholder" "greengrocer" "monger" "shopkeeper" "merchant"
dictionary words, not strings; it's just as easy -- and far clearer --
to stick rigidly to the preferred punctuation.
-.. rubric:: Obsolete usages
+Obsolete usages
+---------------
Finally, remember that Inform has been evolving since 1993. Over that
time, Graham has taken considerable care to maintain as much
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.
-
-