.. epigraph::
- | *W was a watchman, and guarded the door;*
- | *X was expensive, and so became poor.*
+ | |CENTER| *W was a watchman, and guarded the door;*
+ | |CENTER| *X was expensive, and so became poor.*
.. only:: html
.. image:: /images/picW.png
:align: left
-.. raw:: latex
-
- \dropcap{w}
-
-e've given ourselves an interesting challenge by overusing that
-convenient word "toilet", and here we show you how we resolve the
-ambiguities that have been introduced. Also, it's time for the eponymous
+|W|\e've given ourselves an interesting challenge by overusing that
+convenient word "toilet", and here we show you how we resolve the
+ambiguities that have been introduced. Also, it's time for the eponymous
owner of Benny's café to be developed in full.
Too many toilets
================
-If you check the ``name`` properties of the toilet door, the toilet key
-and the toilet room, you’ll see that the dictionary word ``'toilet'``
-occurs in all of them. There won't be any problems if players mention
-the words DOOR or KEY, but we reach a strange impasse should they try to
-perform some action with just the word TOILET. The interpreter has to
-think fast: is the player talking about the key? About the door? Or
-about the toilet? Unable to decide, it asks: "Which do you mean, the
-door to the toilet, the toilet key or the toilet?"
-
-And guess what? Players will never be able to refer to the toilet object
-(unless they type BATH ROOM or REST ROOM, not an obvious choice since we
-haven't used those phrases anywhere visible). If the player answers
-TOILET the parser will still have three objects with that dictionary
-word as a possible name, so it will ask again, and again -- until we
-give it some dictionary word which is not ambiguous. A human reader
-would be able to understand that the word TOILET alone refers to the
-room, but the interpreter won't -- unless we help it a little.
-
-We could work around this problem in more than one way, but we'll take
-this opportunity of demonstrating the use of a third-party library
-package.
-
-When experienced designers find a problem which is not easily solvable,
-they may come up with a smart solution and then consider that others
-could benefit from the effort. The product of this generosity takes the
-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
-"``.../infocom``", "``.../compilers``", "``.../inform6``",
-"``.../library``", and "``.../contributions``". All of these files
-contain Inform code. To use a library extension (also known as a library
-contribution), you should download it and read the instructions (usually
-embedded as comments in the file, but occasionally supplied separately)
-to discover what to do next. Normally, you ``Include`` it (as we have
-already done with ``Parser``, ``VerbLib`` and ``Grammar``), but often
-there are rules about where exactly this Include should be placed in
-your source code. It is not unusual to find other suggestions and
-warnings.
-
-To help us out of the disambiguation problem with the word TOILET, we
-are going to use Neil Cerutti's extension ``pname.h``, which is designed
-for situations precisely like this. First, we follow the link to the IF
-archive and download the compressed file ``pname.zip``, which contains
-two more files: ``pname.h`` and ``pname.txt``. We place these files in
-the folder where we are currently developing our game or, if using the
-environment we proposed in "Tools of the trade" on page 17, in the
-``Inform\Lib\Contrib`` folder. The text file offers instructions about
-installation and usage. Here we find a warning:
-
- This version of pname.h is recommended for use only with version 6/10
- of the Inform Library.
-
-We're actually using a later version, but this doesn't seem to cause a
-problem. Most extensions aren't so fussy, but ``pname.h`` fiddles with
-some routines at the heart of the standard library; these may not be
+.. index::
+ single: ambiguous objects
+
+If you check the :prop:`name` properties of the toilet door, the toilet key
+and the toilet room, you’ll see that the dictionary word ``'toilet'``
+occurs in all of them. There won't be any problems if players mention the
+words DOOR or KEY, but we reach a strange impasse should they try to
+perform some action with just the word TOILET. The interpreter has to
+think fast: is the player talking about the key? About the door? Or about
+the toilet? Unable to decide, it asks: "Which do you mean, the door to the
+toilet, the toilet key or the toilet?"
+
+And guess what? Players will never be able to refer to the toilet object
+(unless they type BATH ROOM or REST ROOM, not an obvious choice since we
+haven't used those phrases anywhere visible). If the player answers TOILET
+the parser will still have three objects with that dictionary word as a
+possible name, so it will ask again, and again -- until we give it some
+dictionary word which is not ambiguous. A human reader would be able to
+understand that the word TOILET alone refers to the room, but the
+interpreter won't -- unless we help it a little.
+
+We could work around this problem in more than one way, but we'll take this
+opportunity of demonstrating the use of a third-party library package.
+
+.. |IFARCHIVE| replace:: http://mirror.ifarchive.org/indexes/if-archive.html
+
+.. Generated by autoindex
+.. index::
+ single: IF Archive
+
+When experienced designers find a problem which is not easily solvable,
+they may come up with a smart solution and then consider that others could
+benefit from the effort. The product of this generosity takes the 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 |IFARCHIVE| 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 contribution), you should
+download it and read the instructions (usually embedded as comments in the
+file, but occasionally supplied separately) to discover what to do next.
+Normally, you ``Include`` it (as we have already done with ``Parser``,
+``VerbLib`` and ``Grammar``), but often there are rules about where exactly
+this Include should be placed in your source code. It is not unusual to
+find other suggestions and warnings.
+
+To help us out of the disambiguation problem with the word TOILET, we are
+going to use Neil Cerutti's extension ``pname.h``, which is designed for
+situations precisely like this. First, we follow the link to the IF
+archive and download the compressed file ``pname.zip``, which contains two
+more files: ``pname.h`` and ``pname.txt``. We place these files in the
+folder where we are currently developing our game or, if using the
+environment we proposed in :doc:`02`, in the ``Inform\Lib\Contrib`` folder.
+The text file offers instructions about installation and usage. Here we
+find a warning:
+
+ This version of pname.h is recommended for use only with version 6/10 of
+ the Inform Library.
+
+We're actually using a later version, but this doesn't seem to cause a
+problem. Most extensions aren't so fussy, but ``pname.h`` fiddles with
+some routines at the heart of the standard library; these may not be
identical in other Inform versions.
-The introduction explains what ``pname.h`` does for you; namely, it lets
-you avoid using complicated ``parse_name`` routines to disambiguate the
-player's input when the same dictionary word refers to more than one
-item. A ``parse_name`` routine would have been the solution to our
-problem before the existence of this file, and it qualifies as an
-advanced programming topic, difficult to master on a first approach.
-Fortunately, we don't need to worry. Neil Cerutti explains:
-
- The ``pname.h`` package defines a new object property, ``pname``
- (short for phrase name), with a similar look and feel to the standard
- ``name`` property: both contain a list of dictionary words. However,
- in a ``pname`` property the order of the words is significant, and
- special operators ``'.p'`` ``'.or'`` and ``'.x'`` enable you to embed
- some intelligence into the list. In most cases where the standard
- ``name`` property isn't enough, you can now just replace it with a
- ``pname`` property, rather than write a ``parse_name`` property
+.. Generated by autoindex
+.. index::
+ pair: parse_name; library property
+
+The introduction explains what ``pname.h`` does for you; namely, it lets
+you avoid using complicated :prop:`parse_name` routines to disambiguate the
+player's input when the same dictionary word refers to more than one item.
+A :prop:`parse_name` routine would have been the solution to our problem
+before the existence of this file, and it qualifies as an advanced
+programming topic, difficult to master on a first approach. Fortunately,
+we don't need to worry. Neil Cerutti explains:
+
+ The ``pname.h`` package defines a new object property, ``pname`` (short
+ for phrase name), with a similar look and feel to the standard
+ :prop:`name` property: both contain a list of dictionary words. However,
+ in a ``pname`` property the order of the words is significant, and
+ special operators ``'.p'`` ``'.or'`` and ``'.x'`` enable you to embed
+ some intelligence into the list. In most cases where the standard
+ :prop:`name` property isn't enough, you can now just replace it with a
+ ``pname`` property, rather than write a :prop:`parse_name` property
routine.
-We'll soon see how it works. Let's take a look at the installation
+We'll soon see how it works. Let's take a look at the installation
instructions:
To incorporate this package into your program, do three things:
- #. Add four lines near the head of the program (before you include
+ #. 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.
-It seems simple enough. So, following steps one and two, we add those
-``Replace...`` lines before the inclusion of ``Parser``, and we include
-``pname.h`` right after it. ``Replace`` tells the compiler that we're
+It seems simple enough. So, following steps one and two, we add those
+``Replace...`` lines before the inclusion of ``Parser``, and we include
+``pname.h`` right after it. ``Replace`` tells the compiler that we're
providing replacements for some standard routines.
+.. include:: /config/typethis.rst
+
.. code-block:: inform
Constant Story "Captain Fate";
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
-be added to some of our objects, and which works pretty much like a
-``name`` property. In fact, it should be used *instead* of a ``name``
-property where we have a disambiguation problem. Let’s change the
-relevant lines for the toilet door and the toilet key:
+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 be
+added to some of our objects, and which works pretty much like a
+:prop:`name` property. In fact, it should be used *instead* of a
+:prop:`name` 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?
+.. include:: /config/typethis.rst
.. 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
+We are now using a new operator -- ``'.x'`` -- in our ``pname`` word lists.
+The text file explains
- The first dictionary word to the right of a ``'.x'`` operator is
+ The first dictionary word to the right of a ``'.x'`` operator is
interpreted as optional.
-and this makes the dictionary word ``'toilet'`` of lesser importance for
-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
-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
-the English language, we've effectively said that "TOILET" is an
-adjective in the phrases "TOILET DOOR" and "TOILET KEY", but a noun when
-used on its own to refer to the room.
-
-The ``pname.h`` package has additional functionality to deal with more
-complex phrases, but we don't need it in our example game. Feel free,
-however, to read ``pname.txt`` and discover what this fine library
-extension can do for you: it's an easy answer to many a disambiguation
+and this makes the dictionary word ``'toilet'`` of lesser importance for
+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
+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
+the English language, we've effectively said that "TOILET" is an adjective
+in the phrases "TOILET DOOR" and "TOILET KEY", but a noun when used on its
+own to refer to the room.
+
+The ``pname.h`` package has additional functionality to deal with more
+complex phrases, but we don't need it in our example game. Feel free,
+however, to read ``pname.txt`` and discover what this fine library
+extension can do for you: it's an easy answer to many a disambiguation
headache.
-
Don't shoot! I'm only the barman
================================
-A lot of the action of the game happens around Benny, and his definition
-needs a little care. Let's explain what we want to happen.
-
- So the door is locked and the player, after discovering what the note
- stuck on the toilet door said, will eventually ask Benny for the key.
- Sadly, Benny allows use of the toilet only to customers, a remark
- he'll make looking pointedly at the menu board behind him. The player
- will have to ask for a coffee first, thereby qualifying as a customer
- in Benny's eyes and thus entitled to make use of the toilet. At last!
- Rush inside, change into Captain Fate’s costume and fly away to save
- the day!
-
-Except that the player neither paid for the coffee, nor returned the
-toilet key. Benny will have to stop the player from leaving the café in
-these circumstances. To prevent unnecessary complication, there will be
-a coin near the lavatory, enough cash to pay for the coffee. And that
-about sums it all up; pretty simple to describe -- not so simple to
-code. Remember Benny's basic definition from the previous chapter:
+A lot of the action of the game happens around Benny, and his definition
+needs a little care. Let's explain what we want to happen.
+
+ So the door is locked and the player, after discovering what the note
+ stuck on the toilet door said, will eventually ask Benny for the key.
+ Sadly, Benny allows use of the toilet only to customers, a remark he'll
+ make looking pointedly at the menu board behind him. The player will
+ have to ask for a coffee first, thereby qualifying as a customer in
+ Benny's eyes and thus entitled to make use of the toilet. At last! Rush
+ inside, change into Captain Fate’s costume and fly away to save the day!
+
+Except that the player neither paid for the coffee, nor returned the toilet
+key. Benny will have to stop the player from leaving the café in these
+circumstances. To prevent unnecessary complication, there will be a coin
+near the lavatory, enough cash to pay for the coffee. And that about sums
+it all up; pretty simple to describe -- not so simple to code. Remember
+Benny's basic definition from the previous chapter:
.. code-block:: inform
strikes him.",
has scenery animate male proper transparent;
-We can now add some complexity, beginning with a ``life`` property. In
+We can now add some complexity, beginning with a :prop:`life` property. In
generic form:
.. code-block:: inform
Ask,Tell,Answer: !... code to handle conversation
],
-We have seen some of these actions before. We'll take care of the easier
+We have seen some of these actions before. We'll take care of the easier
ones:
+.. include:: /config/typethis.rst
+
.. code-block:: inform
Attack:
Ask,Tell,Answer:
"Benny is too busy for idle chit-chat.";
-Attacking Benny is not wise. If the player is still dressed as John
-Covarth, the game displays a message refusing to use violence by reason
-of staying in character as a worthless wimp. However, if Captain Fate
-attempts the action, we'll find that there is more to Benny than meets
-the eye, and the game is lost. Kissing and conversation are disallowed
-by a couple of tailored responses.
-
-The Give action is a bit more complicated, since Benny reacts to certain
-objects in a special and significant way. Bear in mind that Benny's
-definition needs to keep track of whether the player has asked for a
-coffee (thereby becoming a customer and thus worthy of the key), whether
-the coffee has been paid for, and whether the toilet key has been
-returned. The solution, yet again (this really is a most useful
-capability), is more local property variables:
+Attacking Benny is not wise. If the player is still dressed as John
+Covarth, the game displays a message refusing to use violence by reason of
+staying in character as a worthless wimp. However, if Captain Fate
+attempts the action, we'll find that there is more to Benny than meets the
+eye, and the game is lost. Kissing and conversation are disallowed by a
+couple of tailored responses.
+
+The Give action is a bit more complicated, since Benny reacts to certain
+objects in a special and significant way. Bear in mind that Benny's
+definition needs to keep track of whether the player has asked for a coffee
+(thereby becoming a customer and thus worthy of the key), whether the
+coffee has been paid for, and whether the toilet key has been returned.
+The solution, yet again (this really is a most useful capability), is more
+local property variables:
+
+.. include:: /config/typethis.rst
.. code-block:: inform
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 :act:`Give` action of the :prop:`life`
+property, which deals with commands like GIVE THE KEY TO BENNY (in a
+moment, we'll come to the :act:`Give` action of the :prop:`orders`
+property, which deals with commands like BENNY, GIVE ME THE KEY):
-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
-come to the ``Give`` action of the ``orders`` property, which deals with
-commands like BENNY, GIVE ME THE KEY):
+.. include:: /config/typethis.rst
.. code-block:: inform
back anytime,~ he says.";
}
-The Give action in the ``life`` property holds the variable ``noun`` as
-the object offered to the NPC. Remember that we can use the ``switch``
+The Give action in the :prop:`life` property holds the variable :var:`noun`
+as the object offered to the NPC. Remember that we can use the ``switch``
statement as shorthand for:
.. code-block:: inform
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
-successfully transferred. The property ``key_not_returned`` will be set
-to true when we receive the toilet key from Benny (we have not coded
-that bit yet), and now, when we give it back, it's reset to ``false``.
-The ``move`` statement is in charge of the actual transfer of the object
-from the player's inventory to Benny, and we finally display a
-confirmation message. With the coin, we find a new statement:
-``remove``. This extracts the object from the object tree, so that it
-now has no parent. The effect is to make it disappear from the game
-(though you are not destroying the object permanently -- and indeed you
-could return it to the object tree using the ``move`` statement); as far
-as the player is concerned, there isn’t a COIN to be found anywhere. The
-``coffee_not_paid`` property will be set to true when Benny serves us
-the cup of coffee (again, we’ll see that in a moment); now we reset it
-to ``false``, which liberates the player from debt. This culminates with
-the ``"..."`` print-and-return statement, telling the player that the
-action was successful. In passing, remember that in "A homely
-atmosphere" on page 131 we defined the counter such that PUT KEY ON
-COUNTER is automatically translated into GIVE KEY TO BENNY .
-
-Why move the key to Benny but remove the coin instead? Once players
-qualify as customers by ordering a coffee, they will be able to ask for
-the key and return it as many times as they like, so it seems sensible
-to keep the key around. The coin, however, will be a one-shot. We won't
-let players ask for more than one coffee, to prevent their debt from
-growing ad infinitum -- besides, they came in here to change, not to
-indulge in caffeine. Once the coin is paid, it disappears for good,
-supposedly into Benny's greedy pockets. No need to worry about it any
-more.
-
-The benny object needs also an ``orders`` property, just to take care of
-the player's requests for coffee and the key, and to fend off any other
-demands. The ``Give`` action in an ``orders`` property deals with inputs
-like ASK BENNY FOR THE KEY or BENNY, GIVE ME THE KEY. The syntax is
-similar to that of the ``life`` property:
+ ...
+
+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
+successfully transferred. The property ``key_not_returned`` will be set to
+true when we receive the toilet key from Benny (we have not coded that bit
+yet), and now, when we give it back, it's reset to :const:`false`. The
+``move`` statement is in charge of the actual transfer of the object from
+the player's inventory to Benny, and we finally display a confirmation
+message. With the coin, we find a new statement: ``remove``. This
+extracts the object from the object tree, so that it now has no parent.
+The effect is to make it disappear from the game (though you are not
+destroying the object permanently -- and indeed you could return it to the
+object tree using the ``move`` statement); as far as the player is
+concerned, there isn’t a COIN to be found anywhere. The
+``coffee_not_paid`` property will be set to true when Benny serves us the
+cup of coffee (again, we’ll see that in a moment); now we reset it to
+:const:`false`, which liberates the player from debt. This culminates with
+the ``"..."`` print-and-return statement, telling the player that the
+action was successful. In passing, remember that in :ref:`homely-atmos` we
+defined the counter such that PUT KEY ON COUNTER is automatically
+translated into GIVE KEY TO BENNY .
+
+Why move the key to Benny but remove the coin instead? Once players
+qualify as customers by ordering a coffee, they will be able to ask for the
+key and return it as many times as they like, so it seems sensible to keep
+the key around. The coin, however, will be a one-shot. We won't let
+players ask for more than one coffee, to prevent their debt from growing ad
+infinitum -- besides, they came in here to change, not to indulge in
+caffeine. Once the coin is paid, it disappears for good, supposedly into
+Benny's greedy pockets. No need to worry about it any more.
+
+.. Generated by autoindex
+.. index::
+ pair: life; library property
+
+The benny object needs also an :prop:`orders` property, just to take care
+of the player's requests for coffee and the key, and to fend off any other
+demands. The :act:`Give` action in an :prop:`orders` property deals with
+inputs like ASK BENNY FOR THE KEY or BENNY, GIVE ME THE KEY. The syntax is
+similar to that of the :prop:`life` property:
+
+.. include:: /config/typethis.rst
.. code-block:: inform
}
],
-* We test the value of ``second`` in order to trap over-generous
- gestures such as BENNY, GIVE COFFEE TO CUSTOMERS . Then we consider
+* We test the value of :var:`second` in order to trap over-generous
+ gestures such as BENNY, GIVE COFFEE TO CUSTOMERS. Then we consider
potential requests.
-* **Toilet key:** first, we check whether players already have the key
- or not, and complain if they do, stopping execution thanks to the
- implicit ``return true`` of the ``"..."`` statement. If players don’t
- have the key, we proceed to check whether they've asked for a coffee
- yet, by testing the ``coffee_asked_for`` property. If this is true ,
- we should also check if the key is actually one of Benny’s
- possessions -- a perverse player could get the key, then drop it
- somewhere and ask for it again; if this should happen, we indicate
- that Benny is nobody's fool with the message ``"~Last place I saw
- that key..."``. Once all these fitting conditions are ``true``,
- players will get the key, which means that they have to return it --
- the ``key_not_returned`` property becomes ``true`` -- and we display
- a suitable message. However, if the player didn't ask for a coffee,
- Benny refuses to oblige, mentioning for the first time the menu board
- where players will be able to see a picture of a cup of coffee when
- they EXAMINE it. Take care to see how all the ``else`` clauses pair
- up with the appropriate if statements, triggering responses for each
- of the conditions that wasn't met.
-
-* **Coffee:** we check whether players have already asked for a coffee,
- by testing the ``coffee_asked_for`` property, and refuse to serve
- another one if ``true``. If ``false``, we place the coffee on the
- counter, and set the properties ``coffee_asked_for`` and
- ``coffee_not_paid`` to ``true``. The message bit you know about.
-
-* **Food:** we'll provide an object to deal with all of the delicious
- comestibles to be found in the café, specifically those (such as
- "pastries and sandwiches") mentioned in our descriptions. Although
- that object is not yet defined, we code ahead to thwart player's
- gluttony in case they choose to ask Benny for food.
-
-* **Menu:** our default response -- "I don’t think that’s on the menu,
- sir" -- isn’t very appropriate if the player asks for a menu, so we
- provide a better one.
-
-* **Default:** this takes care of anything else that the player asks
- Benny for, displaying his curt response.
+* **Toilet key:** first, we check whether players already have the key or
+ not, and complain if they do, stopping execution thanks to the implicit
+ ``return true`` of the ``"..."`` statement. If players don’t have the
+ key, we proceed to check whether they've asked for a coffee yet, by
+ testing the ``coffee_asked_for`` property. If this is true , we should
+ also check if the key is actually one of Benny’s possessions -- a
+ perverse player could get the key, then drop it somewhere and ask for it
+ again; if this should happen, we indicate that Benny is nobody's fool
+ with the message ``"~Last place I saw that key..."``. Once all these
+ fitting conditions are :const:`true`, players will get the key, which
+ means that they have to return it -- the ``key_not_returned`` property
+ becomes :const:`true` -- and we display a suitable message. However, if
+ the player didn't ask for a coffee, Benny refuses to oblige, mentioning
+ for the first time the menu board where players will be able to see a
+ picture of a cup of coffee when they EXAMINE it. Take care to see how
+ all the ``else`` clauses pair up with the appropriate if statements,
+ triggering responses for each of the conditions that wasn't met.
+
+* **Coffee:** we check whether players have already asked for a coffee, by
+ testing the ``coffee_asked_for`` property, and refuse to serve another
+ one if :const:`true`. If :const:`false`, we place the coffee on the
+ counter, and set the properties ``coffee_asked_for`` and
+ ``coffee_not_paid`` to :const:`true`. The message bit you know about.
+
+* **Food:** we'll provide an object to deal with all of the delicious
+ comestibles to be found in the café, specifically those (such as
+ "pastries and sandwiches") mentioned in our descriptions. Although that
+ object is not yet defined, we code ahead to thwart player's gluttony in
+ case they choose to ask Benny for food.
+
+* **Menu:** our default response -- "I don’t think that’s on the menu, sir"
+ -- isn’t very appropriate if the player asks for a menu, so we provide a
+ better one.
+
+* **Default:** this takes care of anything else that the player asks Benny
+ for, displaying his curt response.
And before you know it, Benny's object is out of the way; however, don't
-celebrate too soon. There’s still some Benny-related behaviour that,
-curiously enough, doesn’t happen in Benny's object; we're talking about
-Benny's reaction if the player tries to leave without paying or
-returning the key. We promised you that Benny would stop the player, and
-indeed he will. But where?
+celebrate too soon. There’s still some Benny-related behaviour that,
+curiously enough, doesn’t happen in Benny's object; we're talking about
+Benny's reaction if the player tries to leave without paying or returning
+the key. We promised you that Benny would stop the player, and indeed he
+will. But where?
We must revisit the café room object:
+.. include:: /config/typethis.rst
+
.. code-block:: inform
Room cafe "Inside Benny's cafe"
s_to street,
n_to toilet_door;
-Once again, we find that the solution to a design problem is not
-necessarily unique. Remember what we saw when dealing with the player's
-description: we could have assigned a new value to the
-``player.description`` variable, but opted to use the
-``LibraryMessages`` object instead. This is a similar case. The code
-causing Benny to intercept the forgetful player could have been added,
-perhaps, to a ``daemon`` property in Benny’s definition. However, since
-the action to be intercepted is always the same one and happens to be a
-movement action when the player tries to leave the café room, it is also
-possible to code it by trapping the ``Go`` action of the room object.
+.. index::
+ pair: LibraryMessages; library object
+
+.. Generated by autoindex
+.. index::
+ pair: Go; library action
+ pair: LibraryMessages; library object
+ pair: daemon; library property
+
+Once again, we find that the solution to a design problem is not
+necessarily unique. Remember what we saw when dealing with the player's
+description: we could have assigned a new value to the
+``player.description`` variable, but opted to use the
+:obj:`LibraryMessages` object instead. This is a similar case. The code
+causing Benny to intercept the forgetful player could have been added,
+perhaps, to a :prop:`daemon` property in Benny’s definition. However,
+since the action to be intercepted is always the same one and happens to be
+a movement action when the player tries to leave the café room, it is also
+possible to code it by trapping the :act:`Go` action of the room object.
Both would have been right, but this is somewhat simpler.
-We have added a ``before`` property to the room object (albeit a longish
-one), just dealing with the ``Go`` action. As we mentioned in an earlier
-chapter, this technique lets you trap the player who is about to exit a
-room before the movement actually takes place, a good moment to
-interfere if we want to prevent escape. The first line:
+.. Generated by autoindex
+.. index::
+ pair: before; library property
+
+We have added a :prop:`before` property to the room object (albeit a
+longish one), just dealing with the :act:`Go` action. As we mentioned in
+an earlier chapter, this technique lets you trap the player who is about to
+exit a room before the movement actually takes place, a good moment to
+interfere if we want to prevent escape. The first line:
.. code-block:: inform
if (noun ~= s_obj) return false;
-is telling the interpreter that we want to tamper only with southwards
-movement, allowing the interpreter to apply normal rules for the other
+is telling the interpreter that we want to tamper only with southwards
+movement, allowing the interpreter to apply normal rules for the other
available directions.
-From here on, it's only conditions and more conditions. The player may
+From here on, it's only conditions and more conditions. The player may
attempt to leave:
* without paying for the coffee and without returning the key,
* having returned the key, but not paid for the coffee, or
-* free of sin and accountable for nothing in the eyes of all men (well,
- in the eye of Benny, at least).
+* free of sin and accountable for nothing in the eyes of all men (well, in
+ the eye of Benny, at least).
The first three are covered by the test:
if (benny.coffee_not_paid == true || benny.key_not_returned == true) ...
-that is, if either the coffee is not paid for *or* if the key is not
-returned. When this condition is ``false``, it means that both
-misdemeanours have been avoided and that the player is free to go.
-However, when this condition is ``true``, the hand of Benny falls on the
-player's shoulder and then the game displays a different message
+that is, if either the coffee is not paid for *or* if the key is not
+returned. When this condition is :const:`false`, it means that both
+misdemeanours have been avoided and that the player is free to go.
+However, when this condition is :const:`true`, the hand of Benny falls on
+the player's shoulder and then the game displays a different message
according to which fault or faults the player has committed.
If the player is free to go, and is wearing the crime-fighting costume,
-the game is won. We tell you how that's reported in the next chapter,
+the game is won. We tell you how that's reported in the next chapter,
where we finish off the design.