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