c730e1be39966294a4157d6e85987e5ec1f2ec2a
[ibg.git] / chapters / 05.rst
1 =================
2  Heidi revisited
3 =================
4
5 .. epigraph::
6
7    | *I was an innkeeper, who loved to carouse;*
8    | *J was a joiner, and built up a house.*
9
10 .. only:: html
11
12   .. image:: /images/picI.png
13      :align: left
14
15 .. raw:: latex
16
17     \dropcap{i}
18
19 n even the simplest story, there's bound to be scope for the player to
20 attempt activities that you hadn't anticipated.  Sometimes there may be
21 alternative ways of approaching a problem: if you can't be sure which
22 approach the player will take, you really ought to allow for all
23 possibilities.  Sometimes the objects you create and the descriptions you
24 provide may suggest to the player that doing such-and-such should be
25 possible, and, within reason, you ought to allow for that also.  The basic
26 game design is easy: what takes the time, and makes a game large and
27 complex, is taking care of all the *other* things that the player may think
28 of trying.
29
30 Here, we try to illustrate what this means by addressing a few of the more
31 glaring deficiencies in our first game.
32
33 Listening to the bird
34 =====================
35
36 Here's a fragment of the game being played:
37
38 .. code-block:: transcript
39
40    Deep in the forest
41    Through the dense foliage, you glimpse a building to the west. A track heads
42    to the northeast.
43
44    You can see a baby bird here.
45
46    >EXAMINE THE BIRD
47    Too young to fly, the nestling tweets helplessly.
48
49    >LISTEN TO BIRD
50    You hear nothing unexpected.
51
52    >
53
54 That's not too smart, is it?  Our description specifically calls the
55 player's attention to the sound of the bird -- and then she finds out that
56 we've got nothing special to say about its helpless tweeting.
57
58 The library has a stock of actions and responses for each of the game's
59 defined verbs, so it can handle most of the player's input with a default,
60 standard behaviour instead of remaining impertinently silent or saying that
61 it doesn't understand what the player intends.  "You hear nothing
62 unexpected" is the library's standard LISTEN response, good enough after
63 LISTEN TO NEST or LISTEN TO TREE, but fairly inappropriate here; we really
64 need to substitute a more relevant response after LISTEN TO BIRD.  Here's
65 how we do it:
66
67 .. code-block:: inform
68
69    Object   bird "baby bird" forest
70      with   description "Too young to fly, the nestling tweets helplessly.",
71             name 'baby' 'bird' 'nestling',
72             before [;
73                   Listen:
74                     print "It sounds scared and in need of assistance.^";
75                     return true;
76             ],
77       has   ;
78
79 We'll go through this a step at a time:
80
81 #. We've added a new ``before`` property to our bird object.  The
82    interpreter looks at the property *before* attempting to perform any
83    action which is directed specifically at this object::
84
85       before [; ... ],
86
87 #. The value of the property is an embedded routine, containing a label and
88    two statements::
89
90        Listen:
91          print "It sounds scared and in need of assistance.^";
92          return true;
93
94 #. The label is the name of an action, in this case ``Listen``.  What we're
95    telling the interpreter is: if the action that you're about to perform
96    on the bird is a ``Listen``, execute these statements first; if it's any
97    other action, carry on as normal.  So, if the player types EXAMINE BIRD,
98    PICK UP BIRD, PUT BIRD IN NEST, HIT BIRD or FONDLE BIRD, then she'll get
99    the standard response.  If she types LISTEN TO BIRD, then our two
100    statements get executed before anything else happens.  We call this
101    "trapping" or "intercepting" the action of Listening to the bird.
102
103 #. The two statements that we execute are, first::
104
105        print "It sounds scared and in need of assistance.^";
106
107    which causes the interpreter to display the string given in double
108    quotes; remember that a ``^`` character in a string appears as a
109    newline.  Second, we execute::
110
111        return true;
112
113    which tells the interpreter that it doesn't need to do anything else,
114    because we've handled the ``Listen`` action ourselves.  And the game now
115    behaves like this -- perfect:
116
117    .. code-block:: transcript
118
119       >LISTEN TO BIRD
120       It sounds scared and in need of assistance.
121
122       >
123
124 The use of the ``return true`` statement probably needs a bit more
125 explanation.  An object's ``before`` property traps an action aimed at that
126 object right at the start, before the interpreter has started to do
127 anything.  That's the point at which the statements in the embedded routine
128 are executed.  If the last of those statements is ``return true`` then the
129 interpreter assumes that the action has been dealt with by those
130 statements, and so there's nothing left to do: no action, no message;
131 nothing.  On the other hand, if the last of the statements is ``return
132 false`` then the interpreter carries on to perform the default action as
133 though it hadn't been intercepted.  Sometimes that's what you want it to
134 do, but not here: if instead we'd written this:
135
136 .. code-block:: inform
137
138    Object    bird "baby bird" forest
139      with    description "Too young to fly, the nestling tweets helplessly.",
140              name 'baby' 'bird' 'nestling',
141              before [;
142                 Listen:
143                   print "It sounds scared and in need of assistance.^";
144                   return false;
145              ],
146        has   ;
147
148 then the interpreter would first have displayed our string, and then
149 carried on with its normal response, which is to display the standard
150 message:
151
152 .. code-block:: transcript
153
154    >LISTEN TO BIRD
155    It sounds scared and in need of assistance.
156    You hear nothing unexpected.
157
158    >
159
160 This technique -- intercepting an action aimed at a particular object in
161 order to do something appropriate for that object -- is one that we'll use
162 again and again.
163
164 Entering the cottage
165 ====================
166
167 At the start of the game the player character stands "outside a cottage", which
168 might lead her to believe that she can go inside:
169
170 .. code-block:: transcript
171
172    In front of a cottage
173    You stand outside a cottage. The forest stretches east.
174
175    >IN
176    You can't go that way.
177
178    >
179
180 Again, that isn't perhaps the most appropriate response, but it's easy to
181 change:
182
183 .. code-block:: inform
184
185    Object    before_cottage "In front of a cottage"
186      with    description
187                  "You stand outside a cottage. The forest stretches east.",
188              e_to forest,
189              in_to "It's such a lovely day -- much too nice to go inside.",
190              cant_go "The only path lies to the east.",
191        has   light;
192
193 The ``in_to`` property would normally link to another room, in the same way
194 as the ``e_to`` property contain the internal ID of the ``forest`` object.
195 However, if instead you set its value to be a string, the interpreter
196 displays that string when the player tries the IN direction.  Other --
197 unspecified -- directions like NORTH and UP still elicit the standard "You
198 can't go that way" response, but we can change that too, by supplying a
199 ``cant_go`` property whose value is a suitable string.  We then get this
200 friendlier behaviour:
201
202 .. code-block:: transcript
203
204    In front of a cottage
205    You stand outside a cottage. The forest stretches east.
206
207    >IN
208    It's such a lovely day -- much too nice to go inside.
209
210    >NORTH
211    The only path lies to the east.
212
213    >EAST
214
215    Deep in the forest
216    ...
217
218 There's another issue here; since we haven't actually implemented an object
219 to represent the cottage, a perfectly reasonable EXAMINE COTTAGE command
220 receives the obviously nonsensical reply "You can't see any such thing".
221 That's easy to fix; we can add a new ``cottage`` object, making it a piece
222 of ``scenery`` just like the ``tree``:
223
224 .. code-block:: inform
225
226    Object   cottage "tiny cottage" before_cottage
227      with   description "It's small and simple, but you're very happy here.",
228             name 'tiny' 'cottage' 'home' 'house' 'hut' 'shed' 'hovel',
229       has   scenery;
230
231 This solves the problem, but promptly gives us another unreasonable
232 response:
233
234 .. code-block:: transcript
235
236    In front of a cottage
237    You stand outside a cottage. The forest stretches east.
238
239    >ENTER COTTAGE
240    That's not something you can enter.
241
242    >
243
244 The situation here is similar to our LISTEN TO BIRD problem, and the
245 solution we adopt is similar as well:
246
247 .. code-block:: inform
248
249    Object   cottage "tiny cottage" before_cottage
250      with   description "It's small and simple, but you're very happy here.",
251             name 'tiny' 'cottage' 'home' 'house' 'hut' 'shed' 'hovel',
252             before [;
253                Enter:
254                  print_ret "It's such a lovely day -- much too nice to go inside.";
255             ],
256       has   scenery;
257
258 We use a ``before`` property to intercept the ``Enter`` action applied to
259 the cottage object, so that we can display a more appropriate message.
260 This time, however, we've done it using one statement rather than two.  It
261 turns out that the sequence "``print`` a string which ends with a newline
262 character, and then ``return true``" is so frequently needed that there's a
263 special statement which does it all.  That is, this single statement (where
264 you'll note that the string *doesn't* need to end in ``^``)::
265
266      print_ret "It's such a lovely day -- much too nice to go inside.";
267
268 works exactly the same as this pair of statements::
269
270      print "It's such a lovely day -- much too nice to go inside.^";
271      return true;
272
273 We could have used the shorter form when handling LISTEN TO BIRD, and we
274 *will* use it from now on.
275
276 Climbing the tree
277 =================
278
279 In the clearing, holding the nest and looking at the tree, the player is
280 meant to type UP.  Just as likely, though, she'll try CLIMB TREE (which
281 currently gives the completely misleading response "I don't think much is
282 to be achieved by that").  Yet another opportunity to use a ``before``
283 property, but now with a difference.
284
285 .. code-block:: inform
286
287    Object   tree "tall sycamore tree" clearing
288      with   description
289                  "Standing proud in the middle of the clearing,
290                   the stout tree looks easy to climb.",
291             name 'tall' 'sycamore' 'tree' 'stout' 'proud',
292             before [;
293                Climb:
294                  PlayerTo(top_of_tree);
295                  return true;
296             ],
297      has    scenery;
298
299 This time, when we intercept the ``Climb`` action applied to the ``tree``
300 object, it's not in order to display a better message; it's because we want
301 to move the player character to another room, just as if she'd typed UP.
302 Relocating the player character is actually quite a complex business, but
303 fortunately all of that complexity is hidden: there's a standard
304 :term:`library routine` to do the job, not one that we've written, but one
305 that's provided as part of the Inform system.
306
307 You'll remember that, when we first mentioned routines (see
308 :ref:`standalone-routines`), we used the example of ``Initialise()`` and
309 said that "the routine's name followed by opening and closing parentheses
310 is all that it takes to call a routine".  That was true for
311 ``Initialise()``, but not quite the whole story.  To move the player
312 character, we've got to specify where we want her to go, and we do that by
313 supplying the internal ID of the destination room within the opening and
314 closing parentheses.  That is, instead of just ``PlayerTo()`` we call
315 ``PlayerTo(top_of_tree)``, and we describe ``top_of_tree`` as the routine's
316 :term:`argument`.
317
318 Although we've moved the player character to another room, we're still in
319 the middle of the intercepted ``Climb`` action.  As previously, we need to
320 tell the interpreter that we've dealt with the action, and so we don't want
321 the standard rejection message to be displayed.  The ``return true``
322 statement does that, as usual.
323
324 Dropping objects from the tree
325 ==============================
326
327 In a normal room like the ``forest`` or the ``clearing``, the player can
328 DROP something she's carrying and it'll effectively fall to the ground at
329 her feet.  Simple, convenient, predictable -- except when the player is at
330 the top of the tree.  Should she DROP something from up there, having it
331 land nearby might seem a bit improbable; much more likely that it would
332 fall to the clearing below.
333
334 It looks like we might want to intercept the ``Drop`` action, but not quite
335 in the way we've been doing up until now.  For one thing, we don't want to
336 complicate the definitions of the ``bird`` and the ``nest`` and any other
337 objects we may introduce: much better to find a general solution that will
338 work for all objects.  And second, we need to recognise that not all
339 objects are droppable; the player can't, for example, DROP THE BRANCH.
340
341 The best approach to the second problem is to intercept the ``Drop`` action
342 *after* it has occurred, rather than beforehand.  That way, we let the
343 library take care of objects which aren't being held or which can't be
344 dropped, and only become involved once a ``Drop`` has been successful.  And
345 the best approach to the first problem is to do this particular
346 interception not on an object-by-object basis, as we have been doing so
347 far, but instead for every ``Drop`` which takes place in our troublesome
348 ``top_of_tree`` room.  This is what we have to write:
349
350 .. code-block:: inform
351
352    Object   top_of_tree "At the top of the tree"
353      with   description "You cling precariously to the trunk.",
354             d_to clearing,
355             after [;
356                Drop:
357                  move noun to clearing;
358                  return false;
359             ],
360       has   light;
361
362 Let's again take it a step at a time:
363
364 #. We've added a new ``after`` property to our ``top_of_tree`` object.  The
365    interpreter looks at the property *subsequent to* performing any action in
366    this room::
367
368        after [; ... ],
369
370 #. The value of the property is an embedded routine, containing a label and
371    two statements::
372
373        Drop:
374          move noun to clearing;
375          return false;
376
377 #. The label is the name of an action, in this case ``Drop``.  What we're
378    telling the interpreter is: if the action that you've just performed
379    here is a ``Drop``, execute these statements before telling the player
380    what you've done; if it's any other action, carry on as normal.
381
382 #. The two statements that we execute are first::
383
384        move noun to clearing;
385
386    which takes the object which has just been moved from the ``player``
387    object to the ``top_of_tree`` object (by the successful ``Drop`` action)
388    and moves it again so that its parent becomes the ``clearing`` object.
389    That ``noun`` is a library variable that always contains the internal ID
390    of the object which is the target of the current action.  If the player
391    types DROP NEST, ``noun`` contains the internal ID of the ``nest``
392    object; if she types DROP NESTLING then ``noun`` contains the internal
393    ID of the ``bird`` object.  Second, we execute::
394
395        return false;
396
397    which tells the interpreter that it should now let the player know
398    what's happened.  Here's the result of all this:
399
400    .. code-block:: transcript
401
402       At the top of the tree
403       You cling precariously to the trunk.
404
405       You can see a wide firm bough here.
406
407       >DROP NEST
408       Dropped.
409
410       >LOOK
411
412       At the top of the tree
413       You cling precariously to the trunk.
414
415       You can see a wide firm bough here.
416
417       >DOWN
418
419       A forest clearing
420       A tall sycamore stands in the middle of this clearing. The path winds
421       southwest through the trees.
422
423       You can see a bird's nest (in which is a baby bird) here.
424
425       >
426
427 Of course, you might think that the standard message "Dropped" is slightly
428 unhelpful in these non-standard circumstances.  If you prefer to hint at
429 what's just happened, you could use this alternative solution:
430
431 .. code-block:: inform
432
433    Object   top_of_tree "At the top of the tree"
434      with   description "You cling precariously to the trunk.",
435             d_to clearing,
436             after [;
437                Drop:
438                  move noun to clearing;
439                  print_ret "Dropped... to the ground far below.";
440             ],
441      has    light;
442
443 The ``print_ret`` statement does two things for us: displays a more
444 informative message, and returns ``true`` to tell the interpreter that
445 there's no need to let the player know what's happened -- we've handled
446 that ourselves.
447
448 Is the bird in the nest?
449 ========================
450
451 The game ends when the player character puts the nest onto the branch.  Our
452 assumption here is that the bird is inside the nest, but this might not be
453 so; the player may have first taken up the bird and then gone back for the
454 nest, or vice versa.  It would be better not to end the game until we'd
455 checked for the bird actually being in the nest; fortunately, that's easy
456 to do:
457
458 .. code-block:: inform
459
460    Object   branch "wide firm bough" top_of_tree
461      with   description "It's flat enough to support a small object.",
462             name 'wide' 'firm' 'flat' 'bough' 'branch',
463             each_turn [; if (bird in nest && nest in branch) deadflag = 2; ],
464       has   static supporter;
465
466 The extended ``if`` statement::
467
468     if (bird in nest && nest in branch) deadflag = 2;
469
470 should now be read as: "Test whether the ``bird`` is currently in (or on)
471 the ``nest``, *and* whether the ``nest`` is currently on (or in) the
472 ``branch``; if both parts are ``true``, set the value of ``deadflag`` to 2;
473 otherwise, do nothing".
474
475 Summing up
476 ==========
477
478 You should by now have some appreciation of the need not only to handle the
479 obvious actions which were at the forefront of your mind when designing the
480 game, but also as many as you can of the other possible ways that a player
481 may choose to interact with the objects presented to her.  Some of those
482 ways will be highly intelligent, some downright dumb; in either case you
483 should try to ensure that the game's response is at least sensible, even
484 when you're telling the player "sorry, you can't do that".
485
486 The new topics that we've encountered here include these:
487
488 Object properties
489 -----------------
490
491 Objects can have a ``before`` property -- if there is one, the interpreter
492 looks at it *before* performing an action which in some way involves that
493 object.  Similarly, you can provide an ``after`` property, which the
494 interpreter looks at *after* performing an action but before telling the
495 player what's happened.  Both ``before`` and ``after`` properties can be
496 used not only with tangible objects like the ``bird``, ``cottage`` and
497 ``tree`` (when they intercept actions aimed at that particular object) but
498 also with rooms (when they intercept actions aimed at any object in that
499 room).
500
501 The value of each ``before`` and ``after`` property is an embedded routine.
502 If such a routine ends with ``return false``, the interpreter then carries
503 on with the next stage of the action which has been intercepted; if it ends
504 with ``return true``, the interpreter does nothing further for that action.
505 By combining these possibilities, you can supplement the work done by a
506 standard action with statements of your own, or you can replace a standard
507 action completely.
508
509 Previously, we've seen connection properties used with the internal ID of
510 the room to which they lead.  In this chapter, we showed that the value
511 could also be a string (explaining why movement in that direction isn't
512 possible).  Here are examples of both, and also of the ``cant_go`` property
513 which provides just such an explanation for *all* connections that aren't
514 explicitly listed::
515
516     e_to forest,
517     in_to "It's such a lovely day -- much too nice to go inside.",
518     cant_go "The only path lies to the east.",
519
520 .. _routines-args:
521
522 Routines and arguments
523 ----------------------
524
525 The library includes a number of useful routines, available to perform
526 certain common tasks if you require them; there's a list in
527 :ref:`library-routines`.  We used the ``PlayerTo`` routine, which moves the
528 player character from her current room to another one -- not necessarily
529 adjacent to the first room.
530
531 When calling ``PlayerTo``, we had to tell the library which room is the
532 destination.  We did this by supplying that room's internal ID within
533 parentheses, thus::
534
535     PlayerTo(clearing);
536
537 A value given in parentheses like that is called an :term:`argument` of the
538 routine.  In fact, a routine can have more than one argument; if so,
539 they're separated by commas.  For example, to move the player character to
540 a room *without* displaying that room's description, we could have supplied
541 a second argument::
542
543     PlayerTo(clearing,1);
544
545 In this example, the effect of the ``1`` is to prevent the description
546 being displayed.
547
548 Statements
549 ----------
550
551 We encountered several new statements:
552
553 ``return true;``
554
555 ``return false;``
556     We used these at the end of embedded routines to control what the
557     interpreter did next.
558
559 ``print "string";``
560
561 ``print_ret "string";``
562     The ``print`` statement simply displays the string of characters
563     represented here by *string*.  The ``print_ret`` statement also does
564     that, then outputs a newline character, and finally executes a ``return
565     true;``
566
567 ``if (condition && condition ) ...``
568     We extended the simple ``if`` statement that we met before.  The ``&&``
569     (to be read as "and") is an operator commonly used when testing for
570     more than one condition at the same time.  It means "if this condition
571     is true *and* this condition is also true *and* ..."  There's also a
572     ``||`` operator, to be read as "or", and a "not" operator ``~~``, which
573     turns true into false and vice versa.
574
575     .. note::
576
577        In addition, there are ``&``, ``|`` and ``~`` operators, but they do
578        a rather different job and are much less common.  Take care not to
579        get them confused.
580
581 ``move obj_id to parent_obj_id;``
582      The ``move`` statement rearranges the object tree, by making the first
583      ``obj_id`` a child of the ``parent_obj_id``.
584
585 .. rubric:: Actions
586
587 We've talked a lot about intercepting actions like ``Listen``, ``Enter``,
588 ``Climb`` and ``Drop``.  An action is a generalised representation of
589 something to be done, determined by the verb which the player types.  For
590 example, the verbs HEAR and LISTEN are ways of saying much the same thing,
591 and so both result in the same action: ``Listen``.  Similarly, verbs like
592 ENTER, GET INTO, SIT ON and WALK INSIDE all lead to an action of ``Enter``,
593 CLIMB and SCALE lead to Climb, and DISCARD, DROP, PUT DOWN and THROW all
594 lead to ``Drop``.  This makes life much easier for the designer; although
595 Inform defines quite a lot of actions, there are many fewer than there are
596 ways of expressing those same actions using English verbs.
597
598 Each action is represented internally by a number, and the value of the
599 current action is stored in a library variable called, erm, ``action``.
600 Two more variables are also useful here: ``noun`` holds the internal ID of
601 the object which is the focus of the action, and ``second`` holds the
602 internal ID of the secondary object (if there is one).  Here are some
603 examples of these:
604
605 ===============================    ======     =======   =======
606 Player types                       action     noun      second
607 -------------------------------    ------     -------   -------
608 LISTEN                             Listen     nothing   nothing
609 LISTEN TO THE BIRD                 Listen     bird      nothing
610 PICK UP THE BIRD                   Take       bird      nothing
611 PUT BIRD IN NEST                   Insert     bird      nest
612 DROP THE NEST                      Drop       nest      nothing
613 PUT NEST ON BRANCH                 PutOn      nest      branch
614 ===============================    ======     =======   =======
615
616 The value ``nothing`` is a built-in constant (like ``true`` and ``false``)
617 which means, well, there isn't any object to refer to.  There's a list of
618 standard library actions in :ref:`group-1-actions`, :ref:`group-2-actions`
619 and :ref:`group-3-actions`.
620
621 We've now reached the end of our first game.  In these three chapters we've
622 shown you the basic principles on which almost all games are based, and
623 introduced you to many of the components that you'll need when creating
624 more interesting IF.  We suggest that you take one last look at the source
625 code (see :doc:`/appendices/b`), and then move on to the next stage.