.. epigraph::
- | *U was a usurer, a miserable elf;*
- | *V was a vintner, who drank all himself.*
+ | |CENTER| *U was a usurer, a miserable elf;*
+ | |CENTER| *V was a vintner, who drank all himself.*
.. only:: html
.. image:: /images/picV.png
:align: left
-.. raw:: latex
-
- \dropcap{v}
-
-iewed from the inside, Benny's café is warm and welcoming, and packed
-with lunchtime customers. We'll try to conjure up some appropriate
-images, but the main focus of the room isn't the decor: it's the door
-leading to the toilet -- and, perhaps, privacy?
+|V|\iewed from the inside, Benny's café is warm and welcoming, and packed
+with lunchtime customers. We'll try to conjure up some appropriate images,
+but the main focus of the room isn't the decor: it's the door leading to
+the toilet -- and, perhaps, privacy?
.. _homely-atmos:
A homely atmosphere
===================
-Benny's café is populated with customers enjoying their lunch, so it
-won't be a good place to change identities. However, the toilet to the
-north looks promising, though Benny has strict rules about its use and
-the door seems to be locked.
+Benny's café is populated with customers enjoying their lunch, so it won't
+be a good place to change identities. However, the toilet to the north
+looks promising, though Benny has strict rules about its use and the door
+seems to be locked.
.. admonition:: Cultural Note
:class: admonition note
- 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
- taking a rest). Bear with us on this; the dual usage becomes
- important a little later on.
+ 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 taking a rest). Bear
+ with us on this; the dual usage becomes important a little later on.
We define the café room in simple form:
s_to street,
n_to toilet_door;
-We'll elaborate on the last line (``n_to toilet_door``) later, when we
+We'll elaborate on the last line (``n_to toilet_door``) later, when we
define the door object which lies between the café and the toilet.
We've mentioned a counter:
+.. include:: /config/typethis.rst
+
.. code-block:: inform
Appliance counter "counter" cafe
],
has supporter;
-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
-``before`` property is potentially able to intercept the resulting
-Attack action. However, the command PUT KEY ON COUNTER generates *two*
-actions. First, a PutOn action is offered to the key (effectively
-saying, do you want to be placed on top of the counter?); that’s the
-normal bit. And then the surprise: a Receive action is offered to the
-counter (effectively saying, are you happy to have the key placed on
-you?) Both actions have the same opportunity of returning ``false`` to
-let the action continue, ``true`` to prevent it.
-
-.. todo::
-
- There are a lot of actions here that are rendered in a typewriter font
- and others that are not. Should these ones that are not be promoted
- to having a typewriter font?
-
-The Receive action is generated by the library in the PutOnSub action
-handler, and also in InsertSub (so a command like PUT BIRD IN NEST sends a
-Receive to the nest object). There’s a matching LetGo, generated by the
-library from commands like TAKE KEY OFF COUNTER and REMOVE BIRD FROM
-NEST. Receive and LetGo are examples of what’s called a :term:`fake
-action`.
+That :prop:`before` property, superficially normal, actually conceals a
+little surprise. By now you should be entirely comfortable with using an
+object's :prop:`before` property to intercept an action directed at that
+object; for example, if the player types HIT COUNTER then the counter's
+:prop:`before` property is potentially able to intercept the resulting
+:act:`Attack` action. However, the command PUT KEY ON COUNTER generates
+*two* actions. First, a :act:`PutOn` action is offered to the key
+(effectively saying, do you want to be placed on top of the counter?);
+that’s the normal bit. And then the surprise: a :act:`Receive` action is
+offered to the counter (effectively saying, are you happy to have the key
+placed on you?) Both actions have the same opportunity of returning
+:const:`false` to let the action continue, :const:`true` to prevent it.
+
+.. Generated by autoindex
+.. index::
+ pair: LetGo; library action
+ pair: Receive; library action
+
+The :act:`Receive` action is generated by the library in the ``PutOnSub``
+action handler, and also in ``InsertSub`` (so a command like PUT BIRD IN
+NEST sends a Receive to the nest object). There’s a matching :act:`LetGo`,
+generated by the library from commands like TAKE KEY OFF COUNTER and REMOVE
+BIRD FROM NEST. :act:`Receive` and :act:`LetGo` are examples of what’s
+called a :term:`fake action`.
.. note::
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
- contents (recollect that ``~~``, to be read as "not", turns true into
- false and vice versa):
+ :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 :act:`Receive` action to ensure that arrows are
+ the only acceptable contents (recollect that ``~~``, to be read as "not",
+ turns true into false and vice versa):
.. code-block:: inform
print_ret "Only arrows -- clean arrows -- go in your quiver.";
],
-Here, we intercept any attempt to place an item on the counter, and
-translate it into an attempt to give that item to Benny. Part of the
-game's plot depends on the player returning the toilet key to Benny, and
-also paying him for his delicious cup of world-famous Cappuccino.
-Putting the key and the money on the counter is a reasonable alternative
-way for the player to accomplish this.
+Here, we intercept any attempt to place an item on the counter, and
+translate it into an attempt to give that item to Benny. Part of the
+game's plot depends on the player returning the toilet key to Benny, and
+also paying him for his delicious cup of world-famous Cappuccino. Putting
+the key and the money on the counter is a reasonable alternative way for
+the player to accomplish this.
-We've also mentioned some customers. These are treated as NPCs, reacting
+We've also mentioned some customers. These are treated as NPCs, reacting
to our hero’s performance.
+.. include:: /config/typethis.rst
+
.. code-block:: inform
Object customers "customers" cafe
],
has scenery animate pluralname;
-Let's go step by step. Our hero enters the café dressed as John Covarth,
-but will eventually manage to change clothes in the toilet, and he'll
-have to cross back through the café to reach the street and win the
-game. The customers' ``description`` takes into consideration which
-outfit the player character is wearing.
-
-In "William Tell" we’ve seen a brief manifestation of the ``life``
-property, but here we'll extend it a little. As we explained, ``life``
-lets you intercept those actions particular to animate objects. Here we
-trap ``Attack`` and ``Kiss`` to offer some customised messages for these
-actions when applied to the customers. Also, we avoid conversation by
-intercepting ``Ask``, ``Tell`` and ``Answer`` in order just to produce a
-message which depends on the player character's attire.
-
-One other feature of ``animate`` objects is the possibility of giving
-them orders: BILL, SHAKE THE SPEAR or ANNIE, GET YOUR GUN . These
-actions are dealt with in the ``orders`` property and, as with the
-``life`` property, the embedded routine can become quite complex if you
-want your NPCs to behave in an interesting way. In this case, we don't
-need the customers to perform tasks for us, so instead we provide a
-simple rejection message, just in case the player tries to order people
-around.
-
-Which leaves us with the ``daemon`` bit. A daemon is a property normally
-used to perform some timed or repetitive action without the need of the
-player’s direct interaction; for example, machines which work by
-themselves, animals that move on their own, or people going about their
-business. More powerfully, a daemon may take notice of the player’s
-decisions at a particular moment, allowing for some interactive
-behaviour; this is, however, an advanced feature that we won't use in
-this example. A daemon gets a chance of doing something at the end of
-every turn, typically to (or with) the object to which it’s associated.
-In our example, the daemon triggers some sneers and nasty comments from
-the customers once our hero comes out of the toilet dressed in Captain
-Fate’s costume.
+Let's go step by step. Our hero enters the café dressed as John Covarth,
+but will eventually manage to change clothes in the toilet, and he'll have
+to cross back through the café to reach the street and win the game. The
+customers' :prop:`description` takes into consideration which outfit the
+player character is wearing.
+
+.. Generated by autoindex
+.. index::
+ pair: Answer; library action
+ pair: Ask; library action
+ pair: Attack; library action
+ pair: Kiss; library action
+ pair: Tell; library action
+ pair: life; library property
+
+In "William Tell" we’ve seen a brief manifestation of the :prop:`life`
+property, but here we'll extend it a little. As we explained, :prop:`life`
+lets you intercept those actions particular to animate objects. Here we
+trap :act:`Attack` and :act:`Kiss` to offer some customised messages for
+these actions when applied to the customers. Also, we avoid conversation
+by intercepting :act:`Ask`, :act:`Tell` and :act:`Answer` in order just to
+produce a message which depends on the player character's attire.
+
+.. Generated by autoindex
+.. index::
+ pair: animate; library attribute
+ pair: orders; library property
+
+One other feature of :attr:`animate` objects is the possibility of giving
+them orders: BILL, SHAKE THE SPEAR or ANNIE, GET YOUR GUN . These actions
+are dealt with in the :prop:`orders` property and, as with the :prop:`life`
+property, the embedded routine can become quite complex if you want your
+NPCs to behave in an interesting way. In this case, we don't need the
+customers to perform tasks for us, so instead we provide a simple rejection
+message, just in case the player tries to order people around.
+
+.. Generated by autoindex
+.. index::
+ pair: daemon; library property
+
+Which leaves us with the :prop:`daemon` bit. A daemon is a property
+normally used to perform some timed or repetitive action without the need
+of the player’s direct interaction; for example, machines which work by
+themselves, animals that move on their own, or people going about their
+business. More powerfully, a daemon may take notice of the player’s
+decisions at a particular moment, allowing for some interactive behaviour;
+this is, however, an advanced feature that we won't use in this example. A
+daemon gets a chance of doing something at the end of every turn, typically
+to (or with) the object to which it’s associated. In our example, the
+daemon triggers some sneers and nasty comments from the customers once our
+hero comes out of the toilet dressed in Captain Fate’s costume.
To code a daemon, you need to do three things:
-#. First, define a daemon property in the object’s body; the value of
- the property is always an embedded routine.
+#. First, define a daemon property in the object’s body; the value of the
+ property is always an embedded routine.
-#. However, daemons do nothing until you activate them. This is easily
- 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).
+#. However, daemons do nothing until you activate them. This is easily
+ 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 :samp:`StopDaemon({obj_id})`.
+#. Once the daemon has finished its mission (if ever) you may stop it 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
-remarks. This must happen in the café room – the place where the
-customers are -- so we need to make certain that the daemon does
-something interesting only while the player stays in the right place
-(and hasn’t wandered, say, back into the toilet):
+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
+remarks. This must happen in the café room – the place where the customers
+are -- so we need to make certain that the daemon does something
+interesting only while the player stays in the right place (and hasn’t
+wandered, say, back into the toilet):
.. code-block:: inform
if (location ~= cafe) return;
-So if the location is not the café room (remember ~= means "not equal
-to"), return without doing anything else; on this turn, there’s nothing
-for the daemon to do. We use a plain ``return`` statement because the
-value returned from a daemon doesn’t matter.
+So if the location is not the café room (remember ~= means "not equal to"),
+return without doing anything else; on this turn, there’s nothing for the
+daemon to do. We use a plain ``return`` statement because the value
+returned from a daemon doesn’t matter.
-We have defined a customised local property, ``number_of_comments``, to
-control the sequence of customers' remarks. When the Captain enters the
-café room from the toilet for the first time, the value of the property
+We have defined a customised local property, ``number_of_comments``, to
+control the sequence of customers' remarks. When the Captain enters the
+café room from the toilet for the first time, the value of the property
should be zero, so the statement block under the test:
.. code-block:: inform
curiosity.^";
}
-will happen only this once. What we intend is to output the text "Nearby
-customers..." right after the startling entrance of our hero, setting up
-the scene for the comments which are about to happen. Since we assign a
-value of 1 to the property, the message will not be printed again.
-Notice how we use an explicit ``print`` statement; the execution of the
-daemon will continue normally to the next line.
+will happen only this once. What we intend is to output the text "Nearby
+customers..." right after the startling entrance of our hero, setting up
+the scene for the comments which are about to happen. Since we assign a
+value of 1 to the property, the message will not be printed again. Notice
+how we use an explicit ``print`` statement; the execution of the daemon
+will continue normally to the next line.
-We want the customers to indulge in witticisms once they see the
-costumed Captain, but not on a completely predictable basis.
+We want the customers to indulge in witticisms once they see the costumed
+Captain, but not on a completely predictable basis.
.. code-block:: inform
if (random(2) == 1) ...
-``random`` is an Inform routine used to generate random numbers or to
-choose randomly between given choices; in the form
-:samp:`random({expression})` it returns a random number between 1 and
-``expression`` inclusive. So our condition is actually stating: if a
-random choice between 1 and 2 happens to be 1 then perform some action.
-Remember that a daemon is run once at the end of every turn, so the
-condition is trying to squeeze a comment from a customer roughly once
-every other turn.
-
-Next, we proceed as we have already seen in "William Tell", with a
-switch statement to order the comments in a controlled sequence by
-cunning use of our tailored local property, ``number_of_comments``. We
-have written just five messages (could have been one or a hundred) and
-then we reach the default case, which is a good place to stop the
-daemon, since we have no more customers’ remarks to display.
-
-Ah, but when does the daemon *start* functioning? Well, as soon as our
-protagonist comes out of the toilet dressed in his multicoloured
-super-hero pyjamas. Since we want to minimise the possible game states,
-we’ll make some general rules to avoid trouble: (a) players will be able
-to change only in the toilet; (b) we won’t let players change back into
-street clothes; and (c) once players manage to step into the street thus
-dressed, the game is won. So, we can safely assume that if players enter
-the café in their Captain’s outfit, they’ll be coming from the toilet.
-As a consequence of all this, we add an ``after`` property to the café
-room object:
+``random`` is an Inform routine used to generate random numbers or to
+choose randomly between given choices; in the form
+:samp:`random({expression})` it returns a random number between 1 and
+``expression`` inclusive. So our condition is actually stating: if a
+random choice between 1 and 2 happens to be 1 then perform some action.
+Remember that a daemon is run once at the end of every turn, so the
+condition is trying to squeeze a comment from a customer roughly once every
+other turn.
+
+Next, we proceed as we have already seen in "William Tell", with a switch
+statement to order the comments in a controlled sequence by cunning use of
+our tailored local property, ``number_of_comments``. We have written just
+five messages (could have been one or a hundred) and then we reach the
+default case, which is a good place to stop the daemon, since we have no
+more customers’ remarks to display.
+
+.. Generated by autoindex
+.. index::
+ pair: after; library property
+
+Ah, but when does the daemon *start* functioning? Well, as soon as our
+protagonist comes out of the toilet dressed in his multicoloured super-hero
+pyjamas. Since we want to minimise the possible game states, we’ll make
+some general rules to avoid trouble: (a) players will be able to change
+only in the toilet; (b) we won’t let players change back into street
+clothes; and (c) once players manage to step into the street thus dressed,
+the game is won. So, we can safely assume that if players enter the café
+in their Captain’s outfit, they’ll be coming from the toilet. As a
+consequence of all this, we add an :prop:`after` property to the café room
+object:
+
+.. include:: /config/typethis.rst
.. code-block:: inform
s_to street,
n_to toilet_door
-There are two useful techniques to detect when the player is entering or
-leaving a room. We'll later see in detail how to deal with a player
-trying to go away and how to avoid it if need be. For now, let’s just
-mention that, in both cases, you have to intercept the ``Go`` action in
-a room object; if you trap it in a ``before`` property, you’re checking
-for departure from the room; if you trap it in an ``after`` property,
-you’re checking for arrivals into the room. Right now we wish to know if
-the player just came from the toilet, so we use an ``after`` property.
+There are two useful techniques to detect when the player is entering or
+leaving a room. We'll later see in detail how to deal with a player trying
+to go away and how to avoid it if need be. For now, let’s just mention
+that, in both cases, you have to intercept the :act:`Go` action in a room
+object; if you trap it in a :prop:`before` property, you’re checking for
+departure from the room; if you trap it in an :prop:`after` property,
+you’re checking for arrivals into the room. Right now we wish to know if
+the player just came from the toilet, so we use an :prop:`after` property.
The first line:
if (noun ~= s_obj) return false;
-is telling the interpreter that we want to do something if the player
-entered the room by typing a GO SOUTH command (this would normally mean
-"coming from the north", but remember that nothing stops you from
-connecting rooms without cardinal logic); the interpreter will apply
-normal rules for the other available directions.
-
-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
-``true`` only once, so the statement block attached to it runs also
+is telling the interpreter that we want to do something if the player
+entered the room by typing a GO SOUTH command (this would normally mean
+"coming from the north", but remember that nothing stops you from
+connecting rooms without cardinal logic); the interpreter will apply normal
+rules for the other available directions.
+
+.. Generated by autoindex
+.. index::
+ pair: daemon; library property
+ pair: true; library constant
+
+Then we check whether the player character is wearing the costume, in which
+case it starts the :prop:`daemon` of the ``customers`` object. The use of
+the local ``first_time_out`` property ensures that the condition is
+:const:`true` only once, so the statement block attached to it runs also
once.
-We've finished with the customers in the café. Now, we have the toilet
-to the north which, for reasons of gameplay *and* decency, is protected
-by a door.
+We've finished with the customers in the café. Now, we have the toilet to
+the north which, for reasons of gameplay *and* decency, is protected by a
+door.
A door to adore
===============
-Door objects require some specific properties and attributes. Let's
-first code a simple door:
+Door objects require some specific properties and attributes. Let's first
+code a simple door:
.. code-block:: inform
with_key toilet_key,
has scenery door openable lockable locked;
-We find this door in the café. We must specify the direction in which
-the door leads and, as we have mentioned in the café's description, that
-would be to the north. That’s what the ``door_dir`` property is for, and
-in this case it takes the value of the north direction property
-``n_to``. Then we must tell Inform the identity of the room to be found
-behind the door, hence the ``door_to`` property, which takes the value
-of the toilet room -- to be defined later. Remember the café's
-connection to the north, ``n_to toilet_door``? Thanks to it, Inform will
-know that the door is in the way, and thanks to the ``door_to``
-property, what lies beyond.
-
-Doors *must* have the attribute ``door``, but beyond that we have a
-stock of options to help us define exactly what kind of door we are
-dealing with. As for containers, doors can be ``openable`` (which
-activates the verbs OPEN and CLOSE so that they can be applied to this
-object) and, since by default they are closed, you can give them the
-attribute ``open`` if you wish otherwise. Additionally, doors can be
-``lockable`` (which sets up the LOCK/UNLOCK verbs) and you can make them
-``locked`` to override their default unlocked status. The verbs LOCK
-and UNLOCK are expecting some kind of key object to operate the door.
-This must be defined using the ``with_key`` property, whose value should
-be the internal ID of the key; in our example, the soon-to-be-defined
-``toilet_key`` . If you don't supply this property, players won't be
-able to lock or unlock the door.
-
-This simple door definition has one problem, namely, that it exists only
-in the café room. If you wish the door to be present also from the
-toilet side, you can either (a) define another door to be found in the
-``toilet room``, or (b) make this one a two-sided door.
-
-Solution (a) seems superficially straightforward, but then you have the
-problem of keeping the states of the two doors – open/closed,
-locked/unlocked -- in synch. In this scenario, where you can access the
-toilet only through this door, that wouldn't be too complicated, since
-you could leave the door object in the café room opened all the time,
-regardless of what players do with the door object in the toilet room
-and vice versa -- they are never going to see them at the same time. In
-general terms, though, such inconsistencies lead to problems; solution
+We find this door in the café. We must specify the direction in which the
+door leads and, as we have mentioned in the café's description, that would
+be to the north. That’s what the :prop:`door_dir` property is for, and in
+this case it takes the value of the north direction property :prop:`n_to`.
+Then we must tell Inform the identity of the room to be found behind the
+door, hence the :prop:`door_to` property, which takes the value of the
+toilet room -- to be defined later. Remember the café's connection to the
+north, ``n_to toilet_door``? Thanks to it, Inform will know that the door
+is in the way, and thanks to the :prop:`door_to` property, what lies
+beyond.
+
+.. Generated by autoindex
+.. index::
+ pair: door; library attribute
+ pair: lockable; library attribute
+ pair: locked; library attribute
+ pair: open; library attribute
+ pair: openable; library attribute
+ pair: with_key; library property
+
+Doors *must* have the attribute :attr:`door`, but beyond that we have a
+stock of options to help us define exactly what kind of door we are dealing
+with. As for containers, doors can be :attr:`openable` (which activates
+the verbs OPEN and CLOSE so that they can be applied to this object) and,
+since by default they are closed, you can give them the attribute
+:attr:`open` if you wish otherwise. Additionally, doors can be
+:attr:`lockable` (which sets up the LOCK/UNLOCK verbs) and you can make
+them :attr:`locked` to override their default unlocked status. The verbs
+LOCK and UNLOCK are expecting some kind of key object to operate the door.
+This must be defined using the :prop:`with_key` property, whose value
+should be the internal ID of the key; in our example, the
+soon-to-be-defined ``toilet_key`` . If you don't supply this property,
+players won't be able to lock or unlock the door.
+
+This simple door definition has one problem, namely, that it exists only in
+the café room. If you wish the door to be present also from the toilet
+side, you can either (a) define another door to be found in the ``toilet
+room``, or (b) make this one a two-sided door.
+
+Solution (a) seems superficially straightforward, but then you have the
+problem of keeping the states of the two doors – open/closed,
+locked/unlocked -- in synch. In this scenario, where you can access the
+toilet only through this door, that wouldn't be too complicated, since you
+could leave the door object in the café room opened all the time,
+regardless of what players do with the door object in the toilet room and
+vice versa -- they are never going to see them at the same time. In
+general terms, though, such inconsistencies lead to problems; solution
(a) is best ignored for most purposes.
-Solution (b) is better, since you have only one door object to deal with
-and its possible states affect both sides. However, the coding gets a
-little bit complicated and you''ll have to define routines for most
+Solution (b) is better, since you have only one door object to deal with
+and its possible states affect both sides. However, the coding gets a
+little bit complicated and you''ll have to define routines for most
properties:
+.. include:: /config/typethis.rst
+
.. code-block:: inform
Object toilet_door "toilet door"
with_key toilet_key,
has scenery door openable lockable locked;
-First of all, the door now needs a ``found_in`` property, since it's
-going to be located both in the café and the toilet. The ``description``
-checks which side of the door we are looking at – testing the current
-value of the variable ``location``, which holds the room the player is
-in -- because we have a scribbled note stuck on one side, but not on the
-other. And the ``door_dir`` and ``door_to`` properties must use the same
-trick, because we travel north from the café into the toilet, but south
-from the toilet into the café.
-
-Right now, the game will display "the toilet door" every time it needs
-to refer to this object. It would be nice if we could somehow get the
-game to distinguish between "the door to the toilet" and "the door to
-the cafe", depending on the side we are facing. For this, a ``short_name
-property`` is the thing. We have already talked about the external name
-defined as part of an object's header information:
+First of all, the door now needs a :prop:`found_in` property, since it's
+going to be located both in the café and the toilet. The
+:prop:`description` checks which side of the door we are looking at –
+testing the current value of the variable :var:`location`, which holds the
+room the player is in -- because we have a scribbled note stuck on one
+side, but not on the other. And the :prop:`door_dir` and :prop:`door_to`
+properties must use the same trick, because we travel north from the café
+into the toilet, but south from the toilet into the café.
+
+Right now, the game will display "the toilet door" every time it needs to
+refer to this object. It would be nice if we could somehow get the game to
+distinguish between "the door to the toilet" and "the door to the cafe",
+depending on the side we are facing. For this, a ``short_name property``
+is the thing. We have already talked about the external name defined as
+part of an object's header information:
.. code-block:: inform
Object toilet_door "toilet door"
-That ``toilet door`` will be the name displayed by the game at run-time
-to refer to the door. With identical effect, this could also have been
-coded thus:
+That ``toilet door`` will be the name displayed by the game at run-time to
+refer to the door. With identical effect, this could also have been coded
+thus:
.. code-block:: inform
Object toilet_door
with short_name "toilet door",
-``short_name`` is a property that supplies the external name of an
-object, either as a string or an embedded routine. Normally, objects
-retain the same external name throughout the game -- and the header
-information method is perfect in that case -- but if it needs to change,
-it's easy to write a routine as the value of ``short_name``:
+:prop:`short_name` is a property that supplies the external name of an
+object, either as a string or an embedded routine. Normally, objects
+retain the same external name throughout the game -- and the header
+information method is perfect in that case -- but if it needs to change,
+it's easy to write a routine as the value of :prop:`short_name`:
+
+.. include:: /config/typethis.rst
.. code-block:: inform
description
...
-Notice the ``return true`` at the end of the routine. You''ll recall
-that the standard rule says "return false to carry on, true to take over
-and stop normal execution”. In the case of ``short_name``, "carry on"
-means "and now display the external name from the header information",
-which is sometimes handy; for instance, you could write a ``short_name``
-routine to prefix an object's external name with one of a range of
-adjectives -- perhaps a shining/flickering/fading/useless lantern.
+Notice the ``return true`` at the end of the routine. You''ll recall that
+the standard rule says "return false to carry on, true to take over and
+stop normal execution". In the case of :prop:`short_name`, "carry on"
+means "and now display the external name from the header information",
+which is sometimes handy; for instance, you could write a
+:prop:`short_name` routine to prefix an object's external name with one of
+a range of adjectives -- perhaps a shining/flickering/fading/useless
+lantern.
.. note::
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::
+ that is, with no external name and no :prop:`short_name` property, we
+ might 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::
+ 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::
You open the door to the toilet(toilet_door).
-Doors can get more complicated than this (no, please, don't throw our
-guide out of the window). Here comes some optional deluxe coding to make
-the door object a bit friendlier in game play, so you can skip it if you
+Doors can get more complicated than this (no, please, don't throw our guide
+out of the window). Here comes some optional deluxe coding to make the
+door object a bit friendlier in game play, so you can skip it if you
foresee headaches.
-Our door now behaves nicely at run-time. It can be locked and unlocked
-if the player character has the right key; it can be opened and closed.
-A sequence of commands to go into the toilet and lock the door behind
-you would be: UNLOCK DOOR WITH KEY, OPEN DOOR, GO NORTH, CLOSE DOOR,
-LOCK DOOR WITH KEY. After we are finished, let's go back to the café:
-UNLOCK DOOR WITH KEY, OPEN DOOR, SOUTH. If the player is of the
-fastidious kind: CLOSE DOOR, LOCK DOOR WITH KEY. This game features only
-one door, but if it had three or four of them, players would grow
-restless (at the very least) if they needed to type so many commands
-just to go through a door. This is the kind of thing reportedly
-considered as poor design, because the game is suddenly slowed down to
-get over a simple action which involves no secrets or surprises. How
-exciting can the crossing of an ordinary door be, after all?
-
-If a few lines of code can make the life of the player easier, it's
-worth a shot. Let's provide a few improvements to our toilet door in
-``before`` and ``after`` properties:
+Our door now behaves nicely at run-time. It can be locked and unlocked if
+the player character has the right key; it can be opened and closed. A
+sequence of commands to go into the toilet and lock the door behind you
+would be: UNLOCK DOOR WITH KEY, OPEN DOOR, GO NORTH, CLOSE DOOR, LOCK DOOR
+WITH KEY. After we are finished, let's go back to the café: UNLOCK DOOR
+WITH KEY, OPEN DOOR, SOUTH. If the player is of the fastidious kind: CLOSE
+DOOR, LOCK DOOR WITH KEY. This game features only one door, but if it had
+three or four of them, players would grow restless (at the very least) if
+they needed to type so many commands just to go through a door. This is
+the kind of thing reportedly considered as poor design, because the game is
+suddenly slowed down to get over a simple action which involves no secrets
+or surprises. How exciting can the crossing of an ordinary door be, after
+all?
+
+.. Generated by autoindex
+.. index::
+ pair: after; library property
+ pair: before; library property
+
+If a few lines of code can make the life of the player easier, it's worth a
+shot. Let's provide a few improvements to our toilet door in
+:prop:`before` and :prop:`after` properties:
+
+.. include:: /config/typethis.rst
.. code-block:: inform
return true;
],
-The basic idea here is to let the player who holds the key perform just
-one action to both unlock *and* open the door (and, conversely, to close
-*and* lock it). The relevant actions are ``Unlock`` and ``Open``, and
-``Lock`` ( ``Close`` is not necessary; if players just close the door we
-shouldn’t assume that they want to lock it as well).
-
-* **Open**: if the door isn't locked or the player doesn't hold the key,
- keep going with the default ``Open`` action defined by the library.
- That leaves a locked door and a player holding the key, so we
- redirect processing to the ``Unlock`` action, giving as arguments the
- door (self) and the toilet key. Since we are using single
- angle-brackets ``<...>``, the action resumes after the unlocking is
- done (note that the ``Unlock`` action also takes care of opening the
- door). Finally, we ``return true`` to stop the library from trying to
- open the door by itself.
-
-* **Lock**: if the door is already closed, keep going with the standard
- library ``Lock`` action. If not, tell players that we are closing the
- door for them, redirect the action briefly to actually close it, and
- then ``return false`` to let the ``Lock`` action proceed as before.
-
-* **Unlock**: we place this action in the after property, so (let's
- hope) the ``Unlock`` action has already happened. If the door is still
- locked, something went wrong, so we ``return false`` to display the
- standard message for an unsuccessful unlocking. Otherwise, the door is
- now unlocked, so we inform the player that we are opening the door and
- redirect the action to actually open it, returning ``true`` to
+The basic idea here is to let the player who holds the key perform just one
+action to both unlock *and* open the door (and, conversely, to close *and*
+lock it). The relevant actions are :act:`Unlock` and :act:`Open`, and
+:act:`Lock` (:act:`Close` is not necessary; if players just close the door
+we shouldn’t assume that they want to lock it as well).
+
+* **Open**: if the door isn't locked or the player doesn't hold the key,
+ keep going with the default :act:`Open` action defined by the library.
+ That leaves a locked door and a player holding the key, so we redirect
+ processing to the :act:`Unlock` action, giving as arguments the door
+ (self) and the toilet key. Since we are using single angle-brackets
+ ``<...>``, the action resumes after the unlocking is done (note that the
+ :act:`Unlock` action also takes care of opening the door). Finally, we
+ ``return true`` to stop the library from trying to open the door by
+ itself.
+
+* **Lock**: if the door is already closed, keep going with the standard
+ library :act:`Lock` action. If not, tell players that we are closing the
+ door for them, redirect the action briefly to actually close it, and then
+ ``return false`` to let the :act:`Lock` action proceed as before.
+
+.. Generated by autoindex
+.. index::
+ pair: true; library constant
+
+* **Unlock**: we place this action in the after property, so (let's hope)
+ the :act:`Unlock` action has already happened. If the door is still
+ locked, something went wrong, so we ``return false`` to display the
+ standard message for an unsuccessful unlocking. Otherwise, the door is
+ now unlocked, so we inform the player that we are opening the door and
+ redirect the action to actually open it, returning :const:`true` to
suppress the standard message.
-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:
+.. Generated by autoindex
+.. index::
+ pair: false; library constant
+ pair: keep_silent; library variable
+
+In all processes there is a library variable called :var:`keep_silent`,
+which can be either :const:`false` (the normal state) or :const:`true`;
+when :const:`true`, the interpreter does not display the associated message
+of an action in progress, so we can avoid things like:
.. code-block:: transcript
You open the door to the toilet.
You unlock the door to the toilet and open it.
-Although we want to set ``keep_silent`` to ``true`` for the duration of
-our extra processing, we need to reset it afterwards. In a case like
-this, good design practice is to preserve its initial value (which was
-probably ``false``, but you should avoid risky assumptions); we use a
-local variable ``ks`` to remember that initial setting so that we can
-safely restore it afterwards. You’ll remember that a local variable in a
-standalone routine is declared between the routine’s name and the
-semicolon:
+Although we want to set :var:`keep_silent` to :const:`true` for the
+duration of our extra processing, we need to reset it afterwards. In a
+case like this, good design practice is to preserve its initial value
+(which was probably :const:`false`, but you should avoid risky
+assumptions); we use a local variable ``ks`` to remember that initial
+setting so that we can safely restore it afterwards. You’ll remember that
+a local variable in a standalone routine is declared between the routine’s
+name and the semicolon:
.. code-block:: inform
[ BeenToBefore this_room;
-In exactly the same way, a local variable in an embedded routine is
-declared between the ``[`` starting marker of the routine and the
+In exactly the same way, a local variable in an embedded routine is
+declared between the ``[`` starting marker of the routine and the
semicolon:
.. code-block:: inform
before [ ks;
-You can declare up to fifteen variables this way -- just separated by
-spaces -- which are usable only within the embedded routine. When we
+You can declare up to fifteen variables this way -- just separated by
+spaces -- which are usable only within the embedded routine. When we
assign it thus:
.. code-block:: inform
ks = keep_silent;
-we are actually making ``ks`` equal to whatever value ``keep_silent``
-has (either ``true`` or ``false``; we actually don't care). We then set
-``keep_silent`` to ``true``, make the desired silent actions, and we
-assign:
+we are actually making ``ks`` equal to whatever value :var:`keep_silent`
+has (either :const:`true` or :const:`false`; we actually don't care). We
+then set :var:`keep_silent` to :const:`true`, make the desired silent
+actions, and we assign:
.. code-block:: inform
keep_silent = ks;
-which restores the value originally stored in ``ks`` to ``keep_silent``.
-The effect is that we manage to leave it as it was before we tampered
-with it.
+which restores the value originally stored in ``ks`` to :var:`keep_silent`.
+The effect is that we manage to leave it as it was before we tampered with
+it.
-Well, that's about everything about doors. Everything? Well, no, not
+Well, that's about everything about doors. Everything? Well, no, not
really; any object can grow as complex as your imagination allows, but
-we’ll drop the subject here. If you care to see more sophisticated doors,
+we’ll drop the subject here. If you care to see more sophisticated doors,
check Exercises :dm4:`3 and 4 <s6.html#ex3>` in the |DM4|, where an
obliging door opens and unlocks by itself if the player simply walks in its
direction.
-So far, we have the player in front of a locked door leading to the
-toilet. A dead end? No, the description mentions a scribbled note on its
-surface. This one should offer no problem:
+So far, we have the player in front of a locked door leading to the toilet.
+A dead end? No, the description mentions a scribbled note on its surface.
+This one should offer no problem:
+
+.. include:: /config/typethis.rst
.. code-block:: inform
],
has scenery;
-Just notice how we change the description after the first time the
-player examines the note, using the local property ``read_once`` created
-just for this purpose. We don’t want the player to walk off with the
-note, so we intercept the ``Take`` action and display something more in
-character than the default message for scenery objects: "That's hardly
-portable".
-
-We've talked a lot about the toilet key; it seems about time to code it.
-Originally, the key is in Benny's possession, and the player will have
-to ask for it, just as the note explains. Although we'll define Benny in
-detail throughout the next chapter, here we present a basic definition,
+Just notice how we change the description after the first time the player
+examines the note, using the local property ``read_once`` created just for
+this purpose. We don’t want the player to walk off with the note, so we
+intercept the :act:`Take` action and display something more in character
+than the default message for scenery objects: "That's hardly portable".
+
+We've talked a lot about the toilet key; it seems about time to code it.
+Originally, the key is in Benny's possession, and the player will have to
+ask for it, just as the note explains. Although we'll define Benny in
+detail throughout the next chapter, here we present a basic definition,
largely so that the key has a parent object.
+.. include:: /config/typethis.rst
+
.. code-block:: inform
Object benny "Benny" cafe
"Benny is trusting you to look after that key.";
];
-While Benny has the key, there's logically no way to examine it (or
-perform any other action involving it), but we want to prevent the
-interpreter from objecting that ``You can't see any such thing``. We've
-made the ``toilet_key`` a child of the ``benny`` object, and you can see
-that Benny's got a ``transparent`` attribute; this means that the key is
-in scope, and enables the player to refer to it without the interpreter
-complaining. Because Benny also has an ``animate`` attribute, the
-interpreter would normally intercept a TAKE KEY action with "That seems
-to belong to Benny"; however, the same wouldn't apply to other commands
-like TOUCH KEY and TASTE KEY . So, to prevent any interaction with the
-key while it’s in Benny’s pockets, we define a ``before`` property.
+While Benny has the key, there's logically no way to examine it (or perform
+any other action involving it), but we want to prevent the interpreter from
+objecting that ``You can't see any such thing``. We've made the
+``toilet_key`` a child of the ``benny`` object, and you can see that
+Benny's got a :attr:`transparent` attribute; this means that the key is in
+scope, and enables the player to refer to it without the interpreter
+complaining. Because Benny also has an :attr:`animate` attribute, the
+interpreter would normally intercept a TAKE KEY action with "That seems to
+belong to Benny"; however, the same wouldn't apply to other commands like
+TOUCH KEY and TASTE KEY. So, to prevent any interaction with the key while
+it’s in Benny’s pockets, we define a :prop:`before` property.
.. code-block:: inform
"Benny is trusting you to look after that key.";
];
-All of the ``before`` properties that we've so far created have contained
-one or more labels specifying the actions which they are to intercept;
-you'll remember that in "William Tell" we introduced the ``default`` action
-(see :ref:`props-class`) to mean "any value not already catered
-for". There's one of those labels here, for the Drop action, but that's
-preceded by a piece of code that will be executed at the start of *every*
-action directed at the key. If it’s still in Benny’s possession, we display
-a polite refusal; if the player has it then we prevent careless disposal;
-otherwise, the action continues unhindered.
+All of the :prop:`before` properties that we've so far created have
+contained one or more labels specifying the actions which they are to
+intercept; you'll remember that in "William Tell" we introduced the
+``default`` action (see :ref:`props-class`) to mean "any value not already
+catered for". There's one of those labels here, for the Drop action, but
+that's preceded by a piece of code that will be executed at the start of
+*every* action directed at the key. If it's still in Benny’s possession,
+we display a polite refusal; if the player has it then we prevent careless
+disposal; otherwise, the action continues unhindered.
(In fact, the hat-on-a-pole ``Prop`` introduced in :ref:`south-side` had
-this all-exclusive ``before`` property:
+this all-exclusive :prop:`before` property:
.. code-block:: inform
print_ret "You're too far away at the moment.";
],
-It would have behaved exactly the same if we'd omitted the ``default``
+It would have behaved exactly the same if we'd omitted the ``default``
label, as we do here for Benny's key.)
-Another small innovation here: the ``invent`` library property (we
-didn’t make it up) which enables you to control how objects appear in
-inventory listings, overriding the default. Left to itself, the
-interpreter simply displays the object’s external name, preceded either
-by a standard article like "a" or "some", or one specifically defined in
-the object's ``article`` property. Here we replace "the toilet key" with
-one of two more helpful descriptions, making it a most valuable object
-in the eyes of John Covarth, and something to be despised haughtily by
-Captain Fate once it's of no further use to him.
-
-When we had players in the street, we faced the problem that they might
-choose to examine the café from the outside. While it's unlikely that
-they'll try to examine the toilet room from the outside, it takes very
+.. Generated by autoindex
+.. index::
+ pair: article; library property
+
+Another small innovation here: the :prop:`invent` library property (we
+didn’t make it up) which enables you to control how objects appear in
+inventory listings, overriding the default. Left to itself, the
+interpreter simply displays the object's external name, preceded either by
+a standard article like "a" or "some", or one specifically defined in the
+object's :prop:`article` property. Here we replace "the toilet key" with
+one of two more helpful descriptions, making it a most valuable object in
+the eyes of John Covarth, and something to be despised haughtily by Captain
+Fate once it's of no further use to him.
+
+When we had players in the street, we faced the problem that they might
+choose to examine the café from the outside. While it's unlikely that
+they'll try to examine the toilet room from the outside, it takes very
little effort to offer a sensible output just in case:
+.. include:: /config/typethis.rst
+
.. code-block:: inform
Object outside_of_toilet "toilet" cafe
],
has scenery openable enterable;
-As with the ``outside_of_cafe`` object, we intercept an ``Enter``
-action, to teleport players into the toilet room if they type ENTER
-TOILET (or to display a refusal if the toilet door is closed). Players
-may try to EXAMINE TOILET; they'll get a different message if the door
-is open -- we invite them to enter it -- or if it's closed. OPEN TOILET
-and CLOSE TOILET inputs are redirected to ``Open`` and ``Close`` actions
-for the toilet door; remember that the double angle-brackets imply a
-``return true``, so that the action stops there and the interpreter does
-not attempt to ``Open`` or ``Close`` the ``outside_of_toilet`` object
-itself after it has dealt with the door.
-
-You're right: the toilet looms large in this game (we blame it on early
-maternal influences). We’ve introduced an ambiguity problem with the
+As with the ``outside_of_cafe`` object, we intercept an :act:`Enter`
+action, to teleport players into the toilet room if they type ENTER TOILET
+(or to display a refusal if the toilet door is closed). Players may try to
+EXAMINE TOILET; they'll get a different message if the door is open -- we
+invite them to enter it -- or if it's closed. OPEN TOILET and CLOSE TOILET
+inputs are redirected to :act:`Open` and :act:`Close` actions for the
+toilet door; remember that the double angle-brackets imply a ``return
+true``, so that the action stops there and the interpreter does not attempt
+to :act:`Open` or :act:`Close` the ``outside_of_toilet`` object itself
+after it has dealt with the door.
+
+You're right: the toilet looms large in this game (we blame it on early
+maternal influences). We’ve introduced an ambiguity problem with the
``outside_of_toilet`` object, and we'll need some help in fixing it.