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