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