statement is controlled by the ``if`` statement, and the ``if`` statement
is performing the test ``self hasnt visited``. In detail:
+.. Generated by autoindex
+.. index::
+ pair: visited; library attribute
+
* :attr:`visited` is an attribute, but not one that you'd normally give to an
object yourself. It's automatically applied to a room object by the
interpreter, but only after that room has been visited for the first
if object :samp:`{X}` currently does not have attribute :samp:`{Y}`,
false if it does.
+.. Generated by autoindex
+.. index::
+ pair: self; library variable
+
* :var:`self`, which we met in the previous chapter, is that useful variable
which, within an object, always refers to that object. Since we're using
it in the middle of the ``street`` object, that's what it refers to.
:samp:`{external_names}`, because these are used by the ``Prop`` class's
``print_ret ... (the) self`` statement.
+.. Generated by autoindex
+.. index::
+ pair: pluralname; library attribute
+
You'll see a couple of new attributes: :attr:`animate` marks an object as
being "alive", while :attr:`pluralname` specifies that its external name is
plural rather than singular. The interpreter uses these attributes to
approach is to play safe and always give an object the relevant set of
attributes, even when, as here, they probably won't be needed.
+.. Generated by autoindex
+.. index::
+ pair: found_in; library property
+
You'll also see a new :prop:`found_in` property, which specifies the rooms
-- and only the rooms; :prop:`found_in` shouldn't be used to place objects
inside containers or supporters -- where this object is to appear. The
],
has container open clothing;
-Both of these are straightforward objects, with the ``Drop``, ``Give`` and
-``ThrowAt`` actions being intercepted to ensure that Wilhelm is never
-without them. The :attr:`clothing` attribute makes its first appearance,
-marking both the quiver and the bow as capable of being worn (as the result
-of a WEAR BOW command, for instance); you'll remember that our
-``Initialise`` routine goes on to add a :attr:`worn` attribute to the
-quiver.
+Both of these are straightforward objects, with the :act:`Drop`,
+:act:`Give` and :act:`ThrowAt` actions being intercepted to ensure that
+Wilhelm is never without them. The :attr:`clothing` attribute makes its
+first appearance, marking both the quiver and the bow as capable of being
+worn (as the result of a WEAR BOW command, for instance); you'll remember
+that our ``Initialise`` routine goes on to add a :attr:`worn` attribute to
+the quiver.
An empty quiver is pretty useless, so here's the class used to define
Wilhelm's stock of arrows. This class has some unusual features::
description "Fine locally grown produce.",
has pluralname;
+.. Generated by autoindex
+.. index::
+ pair: before; library property
+
The only new thing here is the :prop:`before` property of the fruit'n'veg
stall. The stall's description -- lots of items on a table -- may suggest
to players that they can SEARCH through the produce, maybe finding a lucky
beetroot or something else interesting. No such luck -- and we might as
well trap the attempt.
-Having intercepted a ``Search`` action, our plan is to respond with the
+.. Generated by autoindex
+.. index::
+ pair: Examine; library action
+ pair: Search; library action
+
+Having intercepted a :act:`Search` action, our plan is to respond with the
stall's description, as though the player has typed EXAMINE THE STALL.
There isn't an easy way for us to stealthily slide those literal words into
the interpreter, but we *can* simulate the effect which they'd cause: an
-action of ``Examine`` applied to the object stall. This rather cryptic
+action of :act:`Examine` applied to the object stall. This rather cryptic
statement does the job::
<Examine stall>;
-Having diverted the ``Search`` action into an ``Examine`` action, we must
-tell the interpreter that it doesn't need to do anything else, because
+Having diverted the :act:`Search` action into an :act:`Examine` action, we
+must tell the interpreter that it doesn't need to do anything else, because
we've handled the action ourselves. We've done that before -- using
``return true`` -- and so a first stab at the :prop:`before` action looks
like this::
before [; Search: <Examine stall>; return true; ],
+.. Generated by autoindex
+.. index::
+ pair: self; library variable
+
The two-statement sequence ``<...>; return true`` is so common that there's
a single statement shortcut: ``<<...>>``. Also, for exactly the same
reason as before, our code is clearer if we use :var:`self` instead of
before [; Search: <<Examine self>>; ],
A couple of final observations before we leave this topic. The example
-here is of an action (``Examine``) applied to an object (:var:`self`,
+here is of an action (:act:`Examine`) applied to an object (:var:`self`,
though ``stall`` or :var:`noun` would also work at this point). You can
also use the ``<...>`` and ``<<...>>`` statements for actions which affect
no objects::
Introducing Helga
=================
+.. Generated by autoindex
+.. index::
+ single: NPC
+
One of the trickiest aspects of designing a good game is to provide
satisfying interaction with other characters. It's hard enough to code
inanimate objects which provoke appropriate responses to whatever actions
little differently -- for example, TAKE HELGA results in "I don't suppose
Helga would care for that".
+.. Generated by autoindex
+.. index::
+ pair: Ask; library action
+ pair: Attack; library action
+ pair: Kiss; library action
+ pair: Order; library action
+ pair: Show; library action
+ pair: Tell; library action
+ pair: ThrowAt; library action
+ pair: WakeOther; library action
+ pair: life; library property
+
The :attr:`animate` attribute also brings into play nine extra actions
-which can be applied only to animate objects: ``Answer``, ``Ask``,
-``Order`` and ``Tell`` are all associated with speech, and ``Attack``,
-``Kiss``, ``Show``, ``ThrowAt`` and ``WakeOther`` are associated with
-non-verbal interaction. Additionally, a new :prop:`life` property -- very
-similar to :prop:`before` -- can be defined to intercept them. Here we use
-it to trap speech-related commands such as ASK HELGA ABOUT APPLE and TELL
-WALTER ABOUT BABIES, telling players that in this game we've implemented
-only a simpler TALK verb (which we describe in :ref:`verbs`).
+which can be applied only to animate objects: :act:`Answer`, :act:`Ask`,
+:act:`Order` and :act:`Tell` are all associated with speech, and
+:act:`Attack`, :act:`Kiss`, :act:`Show`, :act:`ThrowAt` and
+:act:`WakeOther` are associated with non-verbal interaction. Additionally,
+a new :prop:`life` property -- very similar to :prop:`before` -- can be
+defined to intercept them. Here we use it to trap speech-related commands
+such as ASK HELGA ABOUT APPLE and TELL WALTER ABOUT BABIES, telling players
+that in this game we've implemented only a simpler TALK verb (which we
+describe in :ref:`verbs`).
Based on the NPC class we've created, here's Helga::
scored; when it changes like this, the interpreter tells the player that
"Your score has just gone up by one point".
+.. Generated by autoindex
+.. index::
+ pair: initial; library property
+ pair: times_spoken_to; library property
+
There are also :prop:`life` and :prop:`times_spoken_to` properties (which
we'll talk about in :doc:`09`) and an :prop:`initial` property.