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