~ubuntu-branches/ubuntu/vivid/inform/vivid

« back to all changes in this revision

Viewing changes to info/inform-11

  • Committer: Bazaar Package Importer
  • Author(s): Jan Christoph Nordholz
  • Date: 2008-05-26 22:09:44 UTC
  • mfrom: (2.1.1 lenny)
  • Revision ID: james.westby@ubuntu.com-20080526220944-ba7phz0d1k4vo7wx
Tags: 6.31.1+dfsg-1
* Remove a considerable number of files from the package
  due to unacceptable licensing terms.
* Repair library symlinks.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
This is Info file inform.info, produced by Makeinfo-1.64 from the input
2
 
file inform.texi.
3
 
 
4
 
This is the Inform Designer's Manual, third edition, 4 September 1996,
5
 
as updated 16 May 1997.  It was converted to Info by Christopher J.
6
 
Madsen <ac608@yfn.ysu.edu>.
7
 
 
8
 
Copyright 1996,1997 Graham Nelson and Christopher J. Madsen
9
 
 
10
 
Permission is granted to make and distribute copies of this manual
11
 
provided that:
12
 
 (a) distributed copies are not substantially different from those
13
 
     archived by the author,
14
 
 (b) this and other copyright messages are always retained in full, and
15
 
 (c) no profit is involved.
16
 
 
17
 
 
18
 
File: inform,  Node: Answers,  Next: Index,  Prev: Appendix,  Up: Top
19
 
 
20
 
Answers to all the exercises
21
 
****************************
22
 
 
23
 
     World is crazier and more of it than we think,
24
 
     Incorrigibly plural.  I peel and portion
25
 
     A tangerine and spit the pips and feel
26
 
     The drunkenness of things being various.
27
 
     
28
 
     -- Louis MacNeice (1907-1963), Snow
29
 
 
30
 
* Menu:
31
 
 
32
 
* Answer 1::                    mushroom picking
33
 
* Answer 2::                    opening medicine bottle
34
 
* Answer 3::                    before on second noun
35
 
* Answer 4::                    action validation
36
 
* Answer 5::                    orange cloud surrounding player
37
 
* Answer 6::                    Mayan directions
38
 
* Answer 7::                    reflecting the map east-west
39
 
* Answer 8::                    exchanging "east"/"west"
40
 
* Answer 9::                    acquisitive bag
41
 
* Answer 10::                   television set
42
 
* Answer 11::                   glass and steel boxes
43
 
* Answer 12::                   macrame bag
44
 
* Answer 13::                   plank bridge
45
 
* Answer 14::                   cage to open and enter
46
 
* Answer 15::                   car that won't go east
47
 
* Answer 16::                   pushing pumice ball uphill
48
 
* Answer 17::                   Tyndale's Bible
49
 
* Answer 18::                   bearded psychiatrist
50
 
* Answer 19::                   removing conversation actions
51
 
* Answer 20::                   computer (voice-activated)
52
 
* Answer 21::                   Charlotte playing Simon Says
53
 
* Answer 22::                   Charlotte's clapping game
54
 
* Answer 23::                   Dyslexic Dan
55
 
* Answer 24::                   extensions for one actor only
56
 
* Answer 25::                   alarm clock
57
 
* Answer 26::                   tricorder
58
 
* Answer 27::                   replicator
59
 
* Answer 28::                   communications badge
60
 
* Answer 29::                   Zen flight computer
61
 
* Answer 30::                   Picard and Maharg
62
 
* Answer 31::                   Martha the telepath
63
 
* Answer 32::                   troll afraid of the dark
64
 
* Answer 33::                   pet moth escapes in the dark
65
 
* Answer 34::                   thief who wanders
66
 
* Answer 35::                   weight--watching daemon
67
 
* Answer 36::                   scuttling claws
68
 
* Answer 37::                   Answer to Exercise 37
69
 
* Answer 38::                   midnight
70
 
* Answer 39::                   nightfall and daybreak
71
 
* Answer 40::                   mid-air location
72
 
* Answer 41::                   long time-scale game
73
 
* Answer 42::                   player reacting before
74
 
* Answer 43::                   silencing player
75
 
* Answer 44::                   the player's wayhel
76
 
* Answer 45::                   Giant with conscience
77
 
* Answer 46::                   chessboard of rooms
78
 
* Answer 47::                   varying the prompt
79
 
* Answer 48::                   Answer to Exercise 48
80
 
* Answer 49::                   printing pronouns
81
 
* Answer 50::                   ornate box (inventory inside)
82
 
* Answer 51::                   very verbose mode
83
 
* Answer 52::                   double inventory
84
 
* Answer 53::                   Scrabble pieces
85
 
* Answer 54::                   three denominations of coin
86
 
* Answer 55::                   I Ching coins
87
 
* Answer 56::                   tomato in red or green
88
 
* Answer 57::                   the artiste formerly known as Princess
89
 
* Answer 58::                   drinks machine
90
 
* Answer 59::                   parsing adjectives
91
 
* Answer 60::                   referring to objects by number
92
 
* Answer 61::                   wild-card for a single object
93
 
* Answer 62::                   wild-card for multiple objects
94
 
* Answer 63::                   "fly in amber"
95
 
* Answer 64::                   cherubim plural
96
 
* Answer 65::                   Answer to Exercise 65
97
 
* Answer 66::                   moving to a room by typing its name
98
 
* Answer 67::                   genie muddling black and white
99
 
* Answer 68::                   footnotes
100
 
* Answer 69::                   low numbers in French
101
 
* Answer 70::                   floating-point numbers
102
 
* Answer 71::                   phone numbers
103
 
* Answer 72::                   parsing times of day
104
 
* Answer 73::                   spaceship control panel
105
 
* Answer 74::                   implementing parser primitives
106
 
* Answer 75::                   parsing any quoted text
107
 
* Answer 76::                   tokens which never match
108
 
* Answer 77::                   Answer to Exercise 77
109
 
* Answer 78::                   third noun for parser
110
 
* Answer 79::                   "scope" verb
111
 
* Answer 80::                   "megalook" verb
112
 
* Answer 81::                   putting everything in scope
113
 
* Answer 82::                   room divided by glass window
114
 
* Answer 83::                   dwarf breathing in dark
115
 
* Answer 84::                   nose attached to player
116
 
* Answer 85::                   sterilising machine
117
 
* Answer 86::                   red sticky label
118
 
* Answer 87::                   "lock" and "unlock" inferring keys
119
 
* Answer 88::                   quotations in boxes
120
 
* Answer 89::                   Invisiclues hints
121
 
* Answer 90::                   saving the character
122
 
* Answer 91::                   title page
123
 
* Answer 92::                   status line invisible
124
 
* Answer 93::                   status line showing treasure
125
 
* Answer 94::                   status line with compass rose
126
 
* Answer 95::                   status line with centred room
127
 
* Answer 96::                   printf routine
128
 
 
129
 
 
130
 
File: inform,  Node: Answer 1,  Next: Answer 2,  Prev: Answers,  Up: Answers
131
 
 
132
 
Answer to Exercise 1: mushroom picking
133
 
======================================
134
 
 
135
 
   Change the mushroom's after rule to:
136
 
 
137
 
       after
138
 
       [;  Take: if (self hasnt general)
139
 
                 {   give self general;
140
 
                    "You pick the mushroom, neatly cleaving its thin stalk.";
141
 
                 }
142
 
                 "You pick up the slowly-disintegrating mushroom.";
143
 
           Drop: "The mushroom drops to the ground, battered slightly.";
144
 
       ],
145
 
 
146
 
As mentioned above, general is a general-purpose attribute, free for the
147
 
designer to use.  The `neatly cleaving' message can only happen once,
148
 
because after that the mushroom object must have general.  Note that
149
 
the mushroom is allowed to call itself self instead of mushroom.
150
 
 
151
 
   *Note Exercise 1: Getting Started.
152
 
 
153
 
 
154
 
File: inform,  Node: Answer 2,  Next: Answer 3,  Prev: Answer 1,  Up: Answers
155
 
 
156
 
Answer to Exercise 2: opening medicine bottle
157
 
=============================================
158
 
 
159
 
Object medicine "guaranteed child-proof medicine bottle" cupboard
160
 
  with name "medicine" "bottle",
161
 
       description "~Antidote only: no preventative effect.~",
162
 
       openup
163
 
       [;  give self open ~locked; "The bottle cracks open!";
164
 
       ],
165
 
  has  container openable locked;
166
 
 
167
 
Any other code in the game can send the message medicine.openup() to
168
 
crack open the bottle.  For brevity, this solution assumes that the
169
 
bottle is always visible to the player when it is opened -- if not the
170
 
printed message will be incongruous.
171
 
 
172
 
   *Note Exercise 2: Messages and Classes.
173
 
 
174
 
 
175
 
File: inform,  Node: Answer 3,  Next: Answer 4,  Prev: Answer 2,  Up: Answers
176
 
 
177
 
Answer to Exercise 3: before on second noun
178
 
===========================================
179
 
 
180
 
   Briefly: provide a GamePreRoutine which tests to see if second is an
181
 
object, rather than nothing or a number.  If it is, check whether the
182
 
object has a second_before rule (i.e. test the condition (object
183
 
provides second_before)).  If it has, send the second_before message to
184
 
it, and return the reply as the return value from GamePreRoutine.
185
 
 
186
 
   *Note Exercise 3: Actions and Reactions.
187
 
 
188
 
 
189
 
File: inform,  Node: Answer 4,  Next: Answer 5,  Prev: Answer 3,  Up: Answers
190
 
 
191
 
Answer to Exercise 4: action validation
192
 
=======================================
193
 
 
194
 
   Put any validation rules desired into the GamePreRoutine.  For
195
 
example, the following will filter out any stray Drop actions for
196
 
unheld objects:
197
 
 
198
 
[ GamePreRoutine;
199
 
  if (action==Drop && noun notin player)
200
 
      "You aren't holding ", (the) noun, ".";
201
 
  rfalse;
202
 
];
203
 
 
204
 
   *Note Exercise 4: Actions and Reactions.
205
 
 
206
 
 
207
 
File: inform,  Node: Answer 5,  Next: Answer 6,  Prev: Answer 4,  Up: Answers
208
 
 
209
 
Answer to Exercise 5: orange cloud surrounding player
210
 
=====================================================
211
 
 
212
 
Object orange_cloud "orange cloud"
213
 
  with name "orange" "cloud",
214
 
       react_before
215
 
       [;  Look: "You can't see for the orange cloud surrounding you.";
216
 
           Go, Exit: "You wander round in circles, choking.";
217
 
           Smell: if (noun==0) "Cinnamon?  No, nutmeg.";
218
 
       ],
219
 
  has  scenery;
220
 
 
221
 
   *Note Exercise 5: Places.
222
 
 
223
 
 
224
 
File: inform,  Node: Answer 6,  Next: Answer 7,  Prev: Answer 5,  Up: Answers
225
 
 
226
 
Answer to Exercise 6: Mayan directions
227
 
======================================
228
 
 
229
 
   Define four objects along the lines of:
230
 
 
231
 
Object white_obj "white wall" compass
232
 
  with name "white" "sac" "wall", article "the", door_dir n_to
233
 
  has  scenery;
234
 
 
235
 
and add the following line to Initialise:
236
 
 
237
 
remove n_obj; remove e_obj; remove w_obj; remove s_obj;
238
 
 
239
 
(We could even alias a new Property called white_to to be n_to, and
240
 
then enter map directions in the source code using Mayan direction
241
 
names.) As a fine point of style, turquoise (`yax') is the world colour
242
 
for `here', so add a grammar line to make this cause a "look":
243
 
 
244
 
Verb "turquoise" "yax" * -> Look;
245
 
 
246
 
   *Note Exercise 6: Places.
247
 
 
248
 
 
249
 
File: inform,  Node: Answer 7,  Next: Answer 8,  Prev: Answer 6,  Up: Answers
250
 
 
251
 
Answer to Exercise 7: reflecting the map east-west
252
 
==================================================
253
 
 
254
 
[ SwapDirs o1 o2 x;
255
 
  x=o1.door_dir; o1.door_dir=o2.door_dir; o2.door_dir=x; ];
256
 
[ ReflectWorld;
257
 
  SwapDirs(e_obj,w_obj); SwapDirs(ne_obj,nw_obj); SwapDirs(se_obj,sw_obj);
258
 
];
259
 
 
260
 
   *Note Exercise 7: Places.
261
 
 
262
 
 
263
 
File: inform,  Node: Answer 8,  Next: Answer 9,  Prev: Answer 7,  Up: Answers
264
 
 
265
 
Answer to Exercise 8: exchanging "east"/"west"
266
 
==============================================
267
 
 
268
 
   This is a prime candidate for using variable strings @nn.  Briefly:
269
 
at the head of the source, define
270
 
 
271
 
Lowstring east_str "east"; Lowstring west_str "west";
272
 
 
273
 
and then add two more routines to the game,
274
 
 
275
 
[ NormalWorld; String 0 east_str; String 1 west_str; ];
276
 
[ ReversedWorld; String 0 west_str; String 1 east_str; ];
277
 
 
278
 
where NormalWorld is called in Initialise or to go back to normal, and
279
 
ReversedWorld when the reflection happens.  Write @00 in place of east
280
 
in any double-quoted printable string, and similarly @01 for west.  It
281
 
will be printed as whichever is currently set.  (Inform provides up to
282
 
32 such variable strings.)
283
 
 
284
 
   *Note Exercise 8: Places.
285
 
 
286
 
 
287
 
File: inform,  Node: Answer 9,  Next: Answer 10,  Prev: Answer 8,  Up: Answers
288
 
 
289
 
Answer to Exercise 9: acquisitive bag
290
 
=====================================
291
 
 
292
 
Object -> bag "toothed bag"
293
 
  with name "toothed" "bag",
294
 
       description "A capacious bag with a toothed mouth.",
295
 
       before
296
 
       [; LetGo: "The bag defiantly bites itself
297
 
                  shut on your hand until you desist.";
298
 
          Close: "The bag resists all attempts to close it.";
299
 
       ],
300
 
       after
301
 
       [; Receive:
302
 
                 "The bag wriggles hideously as it swallows ",
303
 
                 (the) noun, ".";
304
 
       ],
305
 
  has  container open;
306
 
 
307
 
   *Note Exercise 9: Containers.
308
 
 
309
 
 
310
 
File: inform,  Node: Answer 10,  Next: Answer 11,  Prev: Answer 9,  Up: Answers
311
 
 
312
 
Answer to Exercise 10: television set
313
 
=====================================
314
 
 
315
 
Object television "portable television set" lounge
316
 
  with name "tv" "television" "set" "portable",
317
 
       before
318
 
       [;  SwitchOn: <<SwitchOn power_button>>;
319
 
           SwitchOff: <<SwitchOff power_button>>;
320
 
           Examine: <<Examine screen>>;
321
 
       ],
322
 
  has  transparent;
323
 
Object -> power_button "power button"
324
 
  with name "power" "button" "switch",
325
 
       after
326
 
       [;  SwitchOn, SwitchOff: <<Examine screen>>;
327
 
       ],
328
 
  has  switchable;
329
 
Object -> screen "television screen"
330
 
  with name "screen",
331
 
       before
332
 
       [;  Examine: if (power_button hasnt on) "The screen is black.";
333
 
               "The screen writhes with a strange Japanese cartoon.";
334
 
       ];
335
 
 
336
 
   *Note Exercise 10: Containers.
337
 
 
338
 
 
339
 
File: inform,  Node: Answer 11,  Next: Answer 12,  Prev: Answer 10,  Up: Answers
340
 
 
341
 
Answer to Exercise 11: glass and steel boxes
342
 
============================================
343
 
 
344
 
Object -> glass_box "glass box with a lid"
345
 
  with name "glass" "box" "with" "lid"
346
 
  has  container transparent openable open;
347
 
Object -> steel_box "steel box with a lid"
348
 
  with name "steel" "box" "with" "lid"
349
 
  has  container openable open;
350
 
 
351
 
   *Note Exercise 11: Containers.
352
 
 
353
 
 
354
 
File: inform,  Node: Answer 12,  Next: Answer 13,  Prev: Answer 11,  Up: Answers
355
 
 
356
 
Answer to Exercise 12: macrame bag
357
 
==================================
358
 
 
359
 
   (The describe part of this answer but is only decoration.)  Note the
360
 
careful use of inp1 and inp2 rather than noun or second: see the note
361
 
at the end of *Note Actions and Reactions::.
362
 
 
363
 
Object -> macrame_bag "macrame bag"
364
 
  with name "macrame" "bag" "string" "net" "sack",
365
 
       react_before
366
 
       [;  Examine, Search, Listen, Smell: ;
367
 
           default:
368
 
               if (inp1>1 && inp1 in self)
369
 
                   print_ret (The) inp1, " is tucked away in the bag.";
370
 
               if (inp2>1 && inp2 in self)
371
 
                   print_ret (The) inp2, " is tucked away in the bag.";
372
 
       ],
373
 
       describe
374
 
       [;  print "^A macrame bag hangs from the ceiling, shut tight";
375
 
           if (child(self)==0) ".";
376
 
           print ".  Inside you can make out ";
377
 
           WriteListFrom(child(self), ENGLISH_BIT); ".";
378
 
       ],
379
 
  has  container transparent;
380
 
Object -> -> "gold watch"
381
 
  with name "gold" "watch",
382
 
       description "The watch has no hands, oddly.",
383
 
       react_before
384
 
       [;  Listen: if (noun==0 or self) "The watch ticks loudly."; ];
385
 
 
386
 
   *Note Exercise 12: Containers.
387
 
 
388
 
 
389
 
File: inform,  Node: Answer 13,  Next: Answer 14,  Prev: Answer 12,  Up: Answers
390
 
 
391
 
Answer to Exercise 13: plank bridge
392
 
===================================
393
 
 
394
 
   The "plank breaking" rule is implemented here in its door_to routine.
395
 
Note that this returns `true' after killing the player.
396
 
 
397
 
Object -> PlankBridge "plank bridge"
398
 
  with description "Extremely fragile and precarious.",
399
 
       name "precarious" "fragile" "wooden" "plank" "bridge",
400
 
       when_open
401
 
           "A precarious plank bridge spans the chasm.",
402
 
       door_to
403
 
       [;  if (children(player)~=0)
404
 
           {   deadflag=1;
405
 
              "You step gingerly across the plank, which bows under
406
 
               your weight. But your meagre possessions are the straw
407
 
               which breaks the camel's back! There is a horrid crack...";
408
 
           }
409
 
           print "You step gingerly across the plank, grateful that
410
 
                  you're not burdened.^";
411
 
           if (location==NearSide) return FarSide; return NearSide;
412
 
       ],
413
 
       door_dir
414
 
       [;  if (location==NearSide) return s_to; return n_to;
415
 
       ],
416
 
       found_in NearSide FarSide,
417
 
  has  static door open;
418
 
 
419
 
There might be a problem with this solution if your game also contained
420
 
a character who wandered about, and whose code was clever enough to run
421
 
door_to routines for any doors it ran into.  If so, door_to could
422
 
perhaps be modified to check that the actor is the player.
423
 
 
424
 
   *Note Exercise 13: Doors.
425
 
 
426
 
 
427
 
File: inform,  Node: Answer 14,  Next: Answer 15,  Prev: Answer 13,  Up: Answers
428
 
 
429
 
Answer to Exercise 14: cage to open and enter
430
 
=============================================
431
 
 
432
 
Object -> cage "iron cage"
433
 
  with name "iron" "cage" "bars" "barred" "iron-barred",
434
 
       when_open
435
 
          "An iron-barred cage, large enough to stoop over inside,
436
 
           looms ominously here.",
437
 
       when_closed "The iron cage is closed.",
438
 
       inside_description "You stare out through the bars.",
439
 
  has  enterable container openable open transparent static;
440
 
 
441
 
   *Note Exercise 14: Things to Enter.
442
 
 
443
 
 
444
 
File: inform,  Node: Answer 15,  Next: Answer 16,  Prev: Answer 14,  Up: Answers
445
 
 
446
 
Answer to Exercise 15: car that won't go east
447
 
=============================================
448
 
 
449
 
   Change the car's before to
450
 
 
451
 
    before
452
 
    [; Go: if (noun==e_obj)
453
 
           {   print "The car will never fit through your front door.^";
454
 
               return 2;
455
 
           }
456
 
           if (car has on) "Brmm!  Brmm!";
457
 
           print "(The ignition is off at the moment.)^";
458
 
    ],
459
 
 
460
 
   *Note Exercise 15: Things to Enter.
461
 
 
462
 
 
463
 
File: inform,  Node: Answer 16,  Next: Answer 17,  Prev: Answer 15,  Up: Answers
464
 
 
465
 
Answer to Exercise 16: pushing pumice ball uphill
466
 
=================================================
467
 
 
468
 
   Insert these lines into the before rule for PushDir:
469
 
 
470
 
               if (second==u_obj) <<PushDir self n_obj>>;
471
 
               if (second==d_obj) <<PushDir self s_obj>>;
472
 
 
473
 
   *Note Exercise 16: Things to Enter.
474
 
 
475
 
 
476
 
File: inform,  Node: Answer 17,  Next: Answer 18,  Prev: Answer 16,  Up: Answers
477
 
 
478
 
Answer to Exercise 17: Tyndale's Bible
479
 
======================================
480
 
 
481
 
Object -> bible "black Tyndale Bible"
482
 
  with name "bible" "black" "book",
483
 
       initial "A black Bible rests on a spread-eagle lectern.",
484
 
       description "A splendid foot-high Bible, which must have survived
485
 
           the burnings of 1520.",
486
 
       before
487
 
       [ w x; Consult:
488
 
               wn = consult_from; w = NextWord();
489
 
               switch(w)
490
 
               {   'matthew': x="Gospel of St Matthew";
491
 
                   'mark': x="Gospel of St Mark";
492
 
                   'luke': x="Gospel of St Luke";
493
 
                   'john': x="Gospel of St John";
494
 
                   default: "There are only the four Gospels.";
495
 
               }
496
 
               if (consult_words==1)
497
 
                   "You read the ", (string) x, " right through.";
498
 
               w = TryNumber(wn);
499
 
               if (w==-1000)
500
 
                   "I was expecting a chapter number in the ",
501
 
                             (string) x, ".";
502
 
               "Chapter ", (number) w, " of the ", (string) x,
503
 
                     " is too sacred for you to understand now.";
504
 
       ];
505
 
 
506
 
   *Note Exercise 17: Reading Matter.
507
 
 
508
 
 
509
 
File: inform,  Node: Answer 18,  Next: Answer 19,  Prev: Answer 17,  Up: Answers
510
 
 
511
 
Answer to Exercise 18: bearded psychiatrist
512
 
===========================================
513
 
 
514
 
   Note that whether reacting before or after, the psychiatrist does
515
 
not cut any actions short, because react_before and react_after both
516
 
return false.
517
 
 
518
 
Object -> psychiatrist "bearded psychiatrist"
519
 
  with name "bearded" "doctor" "psychiatrist" "psychologist" "shrink",
520
 
       initial "A bearded psychiatrist has you under observation.",
521
 
       life
522
 
       [;  "He is fascinated by your behaviour, but makes no attempt to
523
 
            interfere with it.";
524
 
       ],
525
 
       react_after
526
 
       [;  Insert: print "~Subject puts ", (name) noun, " in ",
527
 
                       (name) second, ". Interesting.~^^";
528
 
           Look: print "~Pretend I'm not here,~ says the psychiatrist.^";
529
 
       ],
530
 
       react_before
531
 
       [;  Take, Remove: print "~Subject feels lack of ", (the) noun,
532
 
               ". Suppressed Oedipal complex? Mmm.~^";
533
 
       ],
534
 
  has  animate;
535
 
 
536
 
   *Note Exercise 18: Living Creatures.
537
 
 
538
 
 
539
 
File: inform,  Node: Answer 19,  Next: Answer 20,  Prev: Answer 18,  Up: Answers
540
 
 
541
 
Answer to Exercise 19: removing conversation actions
542
 
====================================================
543
 
 
544
 
   Add the following lines, after the inclusion of Grammar:
545
 
 
546
 
[ SayInsteadSub; "[To talk to someone, please type ~someone, something~
547
 
or else ~ask someone about something~.]"; ];
548
 
Extend "answer" replace * topic -> SayInstead;
549
 
Extend "tell"   replace * topic -> SayInstead;
550
 
 
551
 
A slight snag is that this will throw out "nigel, tell me about the
552
 
grunfeld defence" (which the library will normally convert to an Ask
553
 
action, but can't if the grammar for "tell" is missing).  To avoid
554
 
this, you could (instead of making the above directives) Replace the
555
 
TellSub routine (*note Extending the Library::.) by the SayInsteadSub
556
 
one.
557
 
 
558
 
   *Note Exercise 19: Living Creatures.
559
 
 
560
 
 
561
 
File: inform,  Node: Answer 20,  Next: Answer 21,  Prev: Answer 19,  Up: Answers
562
 
 
563
 
Answer to Exercise 20: computer (voice-activated)
564
 
=================================================
565
 
 
566
 
   There are several ways to do this.  The easiest is to add more
567
 
grammar to the parser and let it do the hard work:
568
 
 
569
 
Object -> computer "computer"
570
 
  with name "computer",
571
 
       orders
572
 
       [;  Theta: print_ret "~Theta now set to ", noun, ".~";
573
 
           default: print_ret "~Please rephrase.~";
574
 
       ],
575
 
  has  talkable;
576
 
...
577
 
[ ThetaSub; "You must tell your computer so."; ];
578
 
Verb "theta" * "is" number -> Theta;
579
 
 
580
 
   *Note Exercise 20: Living Creatures.
581
 
 
582
 
 
583
 
File: inform,  Node: Answer 21,  Next: Answer 22,  Prev: Answer 20,  Up: Answers
584
 
 
585
 
Answer to Exercise 21: Charlotte playing Simon Says
586
 
===================================================
587
 
 
588
 
   Obviously, a slightly wider repertoire of actions might be a good
589
 
idea, but:
590
 
 
591
 
Object -> Charlotte "Charlotte"
592
 
  with name "charlotte" "charlie" "chas",
593
 
       grammar
594
 
       [;  give self ~general;
595
 
           wn=verb_wordnum;
596
 
           if (NextWord()=='simon' && NextWord()=='says')
597
 
           {   give self general;
598
 
               verb_wordnum=verb_wordnum+2;
599
 
           }
600
 
       ],
601
 
       orders
602
 
       [ i;  if (self hasnt general) "Charlotte sticks her tongue out.";
603
 
           WaveHands: "Charlotte waves energetically.";
604
 
           default: "~Don't know how,~ says Charlotte.";
605
 
       ],
606
 
       initial "Charlotte wants to play Simon Says.",
607
 
  has  animate female proper;
608
 
 
609
 
(The variable i isn't needed yet, but will be used by the code added in
610
 
the answer to the next exercise.)
611
 
 
612
 
   *Note Exercise 21: Living Creatures.
613
 
 
614
 
 
615
 
File: inform,  Node: Answer 22,  Next: Answer 23,  Prev: Answer 21,  Up: Answers
616
 
 
617
 
Answer to Exercise 22: Charlotte's clapping game
618
 
================================================
619
 
 
620
 
   First add a Clap verb (this is easy).  Then give Charlotte a number
621
 
property (initially 0, say) and add these three lines to the end of
622
 
Charlotte's grammar routine:
623
 
 
624
 
           self.number=TryNumber(verb_wordnum);
625
 
           if (self.number~=-1000)
626
 
           {    action=##Clap; noun=0; second=0; rtrue; }
627
 
 
628
 
Her orders routine now needs a local variable called i, and the new
629
 
clause:
630
 
 
631
 
           Clap: if (self.number==0) "Charlotte folds her arms.";
632
 
                 for (i=0:i<self.number:i++)
633
 
                 {   print "Clap! ";
634
 
                     if (i==100)
635
 
                         print "(You must be regretting this by now.) ";
636
 
                     if (i==200)
637
 
                         print "(What a determined girl she is.) ";
638
 
                 }
639
 
                 if (self.number>100)
640
 
                    "^^Charlotte is a bit out of breath now.";
641
 
                "^^~Easy!~ says Charlotte.";
642
 
 
643
 
   *Note Exercise 22: Living Creatures.
644
 
 
645
 
 
646
 
File: inform,  Node: Answer 23,  Next: Answer 24,  Prev: Answer 22,  Up: Answers
647
 
 
648
 
Answer to Exercise 23: Dyslexic Dan
649
 
===================================
650
 
 
651
 
   The interesting point here is that when the grammar property finds
652
 
the word "take", it accepts it and has to move verb_wordnum on by one
653
 
to signal that a word has been parsed succesfully.
654
 
 
655
 
Object -> Dan "Dyslexic Dan"
656
 
  with name "dan" "dyslexic",
657
 
       grammar
658
 
       [;  if (verb_word == 'take') { verb_wordnum++; return 'drop'; }
659
 
           if (verb_word == 'drop') { verb_wordnum++; return 'take'; }
660
 
       ],
661
 
       orders
662
 
       [ i;
663
 
           Take: "~What,~ says Dan, ~ you want me to take ",
664
 
                     (the) noun, "?~";
665
 
           Drop: "~What,~ says Dan, ~ you want me to drop ",
666
 
                     (the) noun, "?~";
667
 
           Inv: "~That I can do,~ says Dan. ~I'm empty-handed.~";
668
 
           No: "~Right you be then.~";
669
 
           Yes: "~I'll be having to think about that.~";
670
 
           default: "~Don't know how,~ says Dan.";
671
 
       ],
672
 
       initial "Dyslexic Dan is here.",
673
 
  has  animate proper;
674
 
 
675
 
   *Note Exercise 23: Living Creatures.
676
 
 
677
 
 
678
 
File: inform,  Node: Answer 24,  Next: Answer 25,  Prev: Answer 23,  Up: Answers
679
 
 
680
 
Answer to Exercise 24: extensions for one actor only
681
 
====================================================
682
 
 
683
 
   Suppose Dan's grammar (but nobody else's) for the "examine" verb is
684
 
to be extended.  His grammar routine should also contain:
685
 
 
686
 
           if (verb_word == 'examine' or 'x')
687
 
           {   verb_wordnum++; return -'danx,'; }
688
 
 
689
 
(Note the crudity of this: it looks at the actual verb word, so you
690
 
have to check any synonyms yourself.)  The verb "danx," must be
691
 
declared later:
692
 
 
693
 
Verb "danx," * "conscience" -> Inv;
694
 
 
695
 
and now "Dan, examine conscience" will send him an Inv order: but "Dan,
696
 
examine cow pie" will still send Examine cow_pie as usual.
697
 
 
698
 
   *Note Exercise 24: Living Creatures.
699
 
 
700
 
 
701
 
File: inform,  Node: Answer 25,  Next: Answer 26,  Prev: Answer 24,  Up: Answers
702
 
 
703
 
Answer to Exercise 25: alarm clock
704
 
==================================
705
 
 
706
 
[ PrintTime x; print (x/60), ":", (x%60)/10, (x%60)%10; ];
707
 
Object -> alarm_clock "alarm clock"
708
 
  with name "alarm" "clock",
709
 
       number 480,
710
 
       description
711
 
       [;  print "The alarm is ";
712
 
           if (self has general) print "on, "; else print "off, but ";
713
 
           "the clock reads ", (PrintTime) the_time,
714
 
           " and the alarm is set for ", (PrintTime) self.number, ".";
715
 
       ],
716
 
       react_after
717
 
       [;  Inv:  if (self in player)   { new_line; <<Examine self>>; }
718
 
           Look: if (self in location) { new_line; <<Examine self>>; }
719
 
       ],
720
 
       daemon
721
 
       [;  if (the_time >= self.number && the_time <= self.number+3
722
 
               && self has general) "^Beep! Beep! The alarm goes off.";
723
 
       ],
724
 
       grammar [; return 'alarm,'; ],
725
 
       orders
726
 
       [;  SwitchOn:  give self general; StartDaemon(self); "~Alarm set.~";
727
 
           SwitchOff: give self ~general; StopDaemon(self); "~Alarm off.~";
728
 
           SetTo:     self.number=noun; <<Examine self>>;
729
 
           default: "~Commands are on, off or a time of day only, pliz.~";
730
 
       ],
731
 
       life
732
 
       [;  Ask, Answer, Tell:
733
 
              "[Try ~clock, something~ to address the clock.]";
734
 
       ],
735
 
  has  talkable;
736
 
 
737
 
and add a new verb to the grammar:
738
 
 
739
 
Verb "alarm," * "on"      -> SwitchOn
740
 
              * "off"     -> SwitchOff
741
 
              * TimeOfDay -> SetTo;
742
 
 
743
 
(using the `TimeOfDay' token from the exercises of *note Grammar
744
 
Tokens::.).  Note that since the word "alarm," can't be matched by
745
 
anything the player types, this verb is concealed from ordinary
746
 
grammar.  The orders we produce here are not used in the ordinary way
747
 
(for instance, the action SwitchOn with no noun or second would never
748
 
ordinarily be produced by the parser) but this doesn't matter: it only
749
 
matters that the grammar and the orders property agree with each other.
750
 
 
751
 
   *Note Exercise 25: Living Creatures.
752
 
 
753
 
 
754
 
File: inform,  Node: Answer 26,  Next: Answer 27,  Prev: Answer 25,  Up: Answers
755
 
 
756
 
Answer to Exercise 26: tricorder
757
 
================================
758
 
 
759
 
Object -> tricorder "tricorder"
760
 
  with name "tricorder",
761
 
       grammar [; return 'tc,'; ],
762
 
       orders
763
 
       [;  Examine: if (noun==player) "~You radiate life signs.~";
764
 
               print "~", (The) noun, " radiates ";
765
 
               if (noun hasnt animate) print "no ";
766
 
              "life signs.~";
767
 
           default: "The tricorder bleeps.";
768
 
       ],
769
 
       life
770
 
       [;  Ask, Answer, Tell: "The tricorder is too simple.";
771
 
       ],
772
 
  has  talkable;
773
 
...
774
 
Verb "tc,"    * noun      -> Examine;
775
 
 
776
 
   *Note Exercise 26: Living Creatures.
777
 
 
778
 
 
779
 
File: inform,  Node: Answer 27,  Next: Answer 28,  Prev: Answer 26,  Up: Answers
780
 
 
781
 
Answer to Exercise 27: replicator
782
 
=================================
783
 
 
784
 
Object replicator "replicator"
785
 
  with name "replicator",
786
 
       grammar [;  return 'rc,'; ],
787
 
       orders
788
 
       [;  Give:
789
 
               if (noun in self)
790
 
                   "The replicator serves up a cup of ",
791
 
                   (name) noun, " which you drink eagerly.";
792
 
               "~That is not something I can replicate.~";
793
 
           default: "The replicator is unable to oblige.";
794
 
       ],
795
 
       life
796
 
       [;  Ask, Answer, Tell: "The replicator has no conversation skill.";
797
 
       ],
798
 
  has  talkable;
799
 
Object -> "Earl Grey tea"    with name "earl" "grey" "tea";
800
 
Object -> "Aldebaran brandy" with name "aldebaran" "brandy";
801
 
Object -> "distilled water"  with name "distilled" "water";
802
 
...
803
 
Verb "rc,"    * held      -> Give;
804
 
 
805
 
The point to note here is that the `held' token means `held by the
806
 
replicator' here, as the actor is the replicator, so this is a neat way
807
 
of getting a `one of the following phrases' token into the grammar.
808
 
 
809
 
   *Note Exercise 27: Living Creatures.
810
 
 
811
 
 
812
 
File: inform,  Node: Answer 28,  Next: Answer 29,  Prev: Answer 27,  Up: Answers
813
 
 
814
 
Answer to Exercise 28: communications badge
815
 
===========================================
816
 
 
817
 
   This is similar to the previous exercises.  One creates an attribute
818
 
called crewmember and gives it to the crew objects: the orders property
819
 
is
820
 
 
821
 
       orders
822
 
       [;  Examine:
823
 
               if (parent(noun)==0)
824
 
                   "~", (name) noun,
825
 
                       " is no longer aboard this demonstration game.~";
826
 
               "~", (name) noun, " is in ", (name) parent(noun), ".~";
827
 
           default: "The computer's only really good for locating the crew.";
828
 
       ],
829
 
 
830
 
and the grammar simply returns 'stc,' which is defined as
831
 
 
832
 
[ Crew i;
833
 
  switch(scope_stage)
834
 
  {  1: rfalse;
835
 
     2: objectloop (i has crewmember) PlaceInScope(i); rtrue;
836
 
  }
837
 
];
838
 
Verb "stc,"   * "where" "is" scope=Crew -> Examine;
839
 
 
840
 
An interesting point is that the scope routine doesn't need to do
841
 
anything at stage 3 (usually used for printing out errors) because the
842
 
normal error-message printing system is never reached.  Something like
843
 
"computer, where is Comminder Doto" causes a ##NotUnderstood order.
844
 
 
845
 
   *Note Exercise 28: Living Creatures.
846
 
 
847
 
 
848
 
File: inform,  Node: Answer 29,  Next: Answer 30,  Prev: Answer 28,  Up: Answers
849
 
 
850
 
Answer to Exercise 29: Zen flight computer
851
 
==========================================
852
 
 
853
 
Object Zen "Zen" Flight_Deck
854
 
  with name "zen" "flight" "computer",
855
 
       initial "Square lights flicker unpredictably across a hexagonal
856
 
                fascia on one wall, indicating that Zen is on-line.",
857
 
       grammar [;  return -'zen,'; ],
858
 
       orders
859
 
       [;  Show: "The main screen shows a starfield,
860
 
                  turning through ", noun, " degrees.";
861
 
           Go:  "~Confirmed.~  The ship turns to a new bearing.";
862
 
           SetTo: if (noun==0) "~Confirmed.~  The ship comes to a stop.";
863
 
               if (noun>12) "~Standard by ", (number) noun,
864
 
                            " exceeds design tolerances.~";
865
 
               "~Confirmed.~  The ship's engines step to
866
 
                standard by ", (number) noun, ".";
867
 
           Take: if (noun~=force_wall) "~Please clarify.~";
868
 
                "~Force wall raised.~";
869
 
           Drop: if (noun~=blasters)   "~Please clarify.~";
870
 
              "~Battle-computers on line.
871
 
                Neutron blasters cleared for firing.~";
872
 
           NotUnderstood: "~Language banks unable to decode.~";
873
 
           default: "~Information. That function is unavailable.~";
874
 
       ],
875
 
  has  talkable proper static;
876
 
Object -> force_wall "force wall"     with name "force" "wall" "shields";
877
 
Object -> blasters "neutron blasters" with name "neutron" "blasters";
878
 
...
879
 
Verb "zen,"   * "scan" number "orbital"        -> Show
880
 
              * "set" "course" "for" Planet    -> Go
881
 
              * "speed" "standard" "by" number -> SetTo
882
 
              * "raise" held                   -> Take
883
 
              * "clear" held "for" "firing"    -> Drop;
884
 
 
885
 
Dealing with Ask, Answer and Tell are left to the reader.
886
 
 
887
 
   *Note Exercise 29: Living Creatures.
888
 
 
889
 
 
890
 
File: inform,  Node: Answer 30,  Next: Answer 31,  Prev: Answer 29,  Up: Answers
891
 
 
892
 
Answer to Exercise 30: Picard and Maharg
893
 
========================================
894
 
 
895
 
[ InScope;
896
 
   if (action_to_be == ##Examine or ##Show or ##ShowR)
897
 
       PlaceInScope(noslen_maharg);
898
 
   if (scope_reason == TALKING_REASON)
899
 
       PlaceInScope(noslen_maharg);
900
 
];
901
 
 
902
 
Note that ShowR is a variant form of Show in which the parameters are
903
 
`the other way round': thus "show maharg the phaser" generates ShowR
904
 
maharg phaser internally, which is then converted to the more usual
905
 
Show phaser maharg.
906
 
 
907
 
   *Note Exercise 30: Living Creatures.
908
 
 
909
 
 
910
 
File: inform,  Node: Answer 31,  Next: Answer 32,  Prev: Answer 30,  Up: Answers
911
 
 
912
 
Answer to Exercise 31: Martha the telepath
913
 
==========================================
914
 
 
915
 
   Martha and the sealed room are defined as follows:
916
 
 
917
 
Object sealed_room "Sealed Room"
918
 
  with description
919
 
          "I'm in a sealed room, like a squash court without a door,
920
 
           maybe six or seven yards across",
921
 
  has  light;
922
 
Object -> ball "red ball" with name "red" "ball";
923
 
Object -> martha "Martha"
924
 
  with name "martha",
925
 
       orders
926
 
       [ r; r=parent(self);
927
 
           Give:
928
 
               if (noun notin r) "~That's beyond my telekinesis.~";
929
 
               if (noun==self) "~Teleportation's too hard for me.~";
930
 
               move noun to player;
931
 
               "~Here goes...~ and Martha's telekinetic talents
932
 
                   magically bring ", (the) noun, " to your hands.";
933
 
           Look:
934
 
               print "~", (string) r.description;
935
 
               if (children(r)==1) ".  There's nothing here but me.~";
936
 
               print ".  I can see ";
937
 
               WriteListFrom(child(r),CONCEAL_BIT+ENGLISH_BIT);
938
 
              ".~";
939
 
           default: "~Afraid I can't help you there.~";
940
 
       ],
941
 
       life
942
 
       [;  Ask: "~You're on your own this time.~";
943
 
           Tell: "Martha clucks sympathetically.";
944
 
           Answer: "~I'll be darned,~ Martha replies.";
945
 
       ],
946
 
   has animate female concealed proper;
947
 
 
948
 
but the really interesting part is the InScope routine to fix things up:
949
 
 
950
 
[ InScope actor;
951
 
   if (actor==martha) PlaceInScope(player);
952
 
   if (actor==player && scope_reason==TALKING_REASON)
953
 
       PlaceInScope(martha);
954
 
   rfalse;
955
 
];
956
 
 
957
 
Note that since we want two-way communication, the player has to be in
958
 
scope to Martha too: otherwise Martha won't be able to follow the
959
 
command "martha, give me the fish", because "me" will refer to
960
 
something beyond her scope.
961
 
 
962
 
   *Note Exercise 31: Living Creatures.
963
 
 
964
 
 
965
 
File: inform,  Node: Answer 32,  Next: Answer 33,  Prev: Answer 31,  Up: Answers
966
 
 
967
 
Answer to Exercise 32: troll afraid of the dark
968
 
===============================================
969
 
 
970
 
   Just test if HasLightSource(gift)==1.
971
 
 
972
 
   *Note Exercise 32: Light and Dark.
973
 
 
974
 
 
975
 
File: inform,  Node: Answer 33,  Next: Answer 34,  Prev: Answer 32,  Up: Answers
976
 
 
977
 
Answer to Exercise 33: pet moth escapes in the dark
978
 
===================================================
979
 
 
980
 
   We could solve this using a daemon, but for the sake of
981
 
demonstrating a feature of thedark we won't.  In Initialise, write
982
 
thedark.initial = GoMothGo; and add the routine:
983
 
 
984
 
[ GoMothGo;
985
 
   if (moth in player)
986
 
   {   remove moth;
987
 
      "As your eyes try to adjust, you feel a ticklish sensation
988
 
       and hear a tiny fluttering sound.";
989
 
   }
990
 
];
991
 
 
992
 
   *Note Exercise 33: Light and Dark.
993
 
 
994
 
 
995
 
File: inform,  Node: Answer 34,  Next: Answer 35,  Prev: Answer 33,  Up: Answers
996
 
 
997
 
Answer to Exercise 34: thief who wanders
998
 
========================================
999
 
 
1000
 
   This is a crude implementation, for brevity (the real Zork thief has
1001
 
an enormous stock of attached messages).  A life routine is omitted,
1002
 
and of course this particular thief steals nothing.  See `The Thief'
1003
 
for a much fuller, annotated implementation.
1004
 
 
1005
 
Object -> thief "thief"
1006
 
  with name "thief" "gentleman" "mahu" "modo",
1007
 
       each_turn "^The thief growls menacingly.",
1008
 
       daemon
1009
 
       [ i p j n k;
1010
 
           if (random(3)~=1) rfalse;
1011
 
           p=parent(thief);
1012
 
           objectloop (i in compass)
1013
 
           {   j=p.(i.door_dir);
1014
 
               if (j ofclass Object && j hasnt door) n++;
1015
 
           }
1016
 
           if (n==0) rfalse;
1017
 
           k=random(n); n=0;
1018
 
           objectloop (i in compass)
1019
 
           {   j=p.(i.door_dir);
1020
 
               if (j ofclass Object && j hasnt door) n++;
1021
 
               if (n==k)
1022
 
               {   move self to j;
1023
 
                   if (p==location) "^The thief stalks away!";
1024
 
                   if (j==location) "^The thief stalks in!";
1025
 
                   rfalse;
1026
 
               }
1027
 
           }
1028
 
       ],
1029
 
  has  animate;
1030
 
 
1031
 
(Not forgetting to StartDaemon(thief) at some point, for instance in
1032
 
the game's Initialise routine.)  So the thief walks at random but never
1033
 
via doors, bridges and the like (because these may be locked or have
1034
 
rules attached); it's only a first approximation, and in a good game
1035
 
one should occasionally see the thief do something surprising, such as
1036
 
open a secret door.  As for the name, note that `The Prince of darkness
1037
 
is a gentleman. Modo he's called, and Mahu' (William Shakespeare, `King
1038
 
Lear' III iv).
1039
 
 
1040
 
   *Note Exercise 34: Daemons.
1041
 
 
1042
 
 
1043
 
File: inform,  Node: Answer 35,  Next: Answer 36,  Prev: Answer 34,  Up: Answers
1044
 
 
1045
 
Answer to Exercise 35: weight--watching daemon
1046
 
==============================================
1047
 
 
1048
 
   We shall use a new property called weight and decide that any object
1049
 
which doesn't provide any particular weight will weigh 10 units.
1050
 
Clearly, an object which contains other objects will carry their weight
1051
 
too, so:
1052
 
 
1053
 
[ WeightOf obj t i;
1054
 
   if (obj provides weight) t = obj.weight; else t = 10;
1055
 
   objectloop (i in obj) t = t + WeightOf(i);
1056
 
   return t;
1057
 
];
1058
 
 
1059
 
Once every turn we shall check how much the player is carrying and
1060
 
adjust a measure of the player's fatigue accordingly.  There are many
1061
 
ways we could choose to calculate this: for the sake of example we'll
1062
 
define two constants:
1063
 
 
1064
 
Constant CARRYING_STRENGTH = 500;
1065
 
Constant HEAVINESS_THRESHOLD = 100;
1066
 
 
1067
 
Initially the player's strength will be the maximum possible, which
1068
 
we'll set to 500.  Each turn the amount of weight being carried is
1069
 
substracted from this, but 100 is also added on (without exceeding the
1070
 
maximum value).  So if the player carries more than 100 units, then her
1071
 
strength declines, but by dropping things to get the weight below 100
1072
 
she can allow it to recover.  If she drops absolutely everything, her
1073
 
entire strength will recuperate in at most 5 turns.  Exhaustion sets in
1074
 
if her strength reaches 0, and at this point she is forced to drop
1075
 
something, which gives her strength a slight boost.  Anyway, here's an
1076
 
implementation of all this:
1077
 
 
1078
 
Object weight_monitor
1079
 
  with players_strength,
1080
 
       warning_level 5,
1081
 
       activate
1082
 
       [;  self.players_strength = CARRYING_STRENGTH; StartDaemon(self);
1083
 
       ],
1084
 
       daemon
1085
 
       [ w s b bw;
1086
 
            if (location ~= Weights_Room) { StopDaemon(self); return; }
1087
 
            s = self.players_strength
1088
 
                - WeightOf(player) + HEAVINESS_THRESHOLD;
1089
 
            if (s<0) s=0; if (s>CARRYING_STRENGTH) s=CARRYING_STRENGTH;
1090
 
            self.players_strength = s;
1091
 
            if (s==0)
1092
 
            {   bw=-1;
1093
 
                objectloop(b in player)
1094
 
                    if (WeightOf(b) > bw) { bw = WeightOf(b); w=b; }
1095
 
                self.players_strength = self.players_strength + bw;
1096
 
                print "^Exhausted with carrying so much, you decide
1097
 
                    to discard ", (the) w, ": "; <<Drop w>>;
1098
 
            }
1099
 
            w=s/100; if (w==self.warning_level) return;
1100
 
            self.warning_level = w;
1101
 
            switch(w)
1102
 
            {   3: "^You are feeling a little tired.";
1103
 
                2: "^You possessions are weighing you down.";
1104
 
                1: "^Carrying so much weight is wearing you out.";
1105
 
                0: "^You're nearly exhausted enough to drop everything
1106
 
                     at an inconvenient moment.";
1107
 
            }
1108
 
       ];
1109
 
 
1110
 
Notice that items are actually dropped with Drop actions: one of them
1111
 
might be, say, a wild boar, which would bolt away into the forest when
1112
 
released.  The daemon tries to drop the heaviest item.  (Obviously a
1113
 
little improvement would be needed if the game contained, say, an
1114
 
un-droppable but very heavy ball and chain.)  Finally, of course, at
1115
 
some point the weight monitor has to be sent an activate message to get
1116
 
things going.
1117
 
 
1118
 
   *Note Exercise 35: Daemons.
1119
 
 
1120
 
 
1121
 
File: inform,  Node: Answer 36,  Next: Answer 37,  Prev: Answer 35,  Up: Answers
1122
 
 
1123
 
Answer to Exercise 36: scuttling claws
1124
 
======================================
1125
 
 
1126
 
   See the next answer.
1127
 
 
1128
 
   *Note Exercise 36: Daemons.
1129
 
 
1130
 
 
1131
 
File: inform,  Node: Answer 37,  Next: Answer 38,  Prev: Answer 36,  Up: Answers
1132
 
 
1133
 
Answer to Exercise 37
1134
 
=====================
1135
 
 
1136
 
Object tiny_claws "sound of tiny claws" thedark
1137
 
  with article "the",
1138
 
       name "tiny" "claws" "sound" "of" "scuttling" "scuttle"
1139
 
            "things" "creatures" "monsters" "insects",
1140
 
       initial "Somewhere, tiny claws are scuttling.",
1141
 
       before
1142
 
       [;  Listen: "How intelligent they sound, for mere insects.";
1143
 
           Touch, Taste: "You wouldn't want to.  Really.";
1144
 
           Smell: "You can only smell your own fear.";
1145
 
           Attack: "They easily evade your flailing about in the dark.";
1146
 
           default: "The creatures evade you, chittering.";
1147
 
       ],
1148
 
       each_turn [; StartDaemon(self); ],
1149
 
       number 0,
1150
 
       daemon
1151
 
       [;  if (location~=thedark) { self.number=0; StopDaemon(self); rtrue; }
1152
 
           switch(++(self.number))
1153
 
           {   1: "^The scuttling draws a little nearer, and your breathing
1154
 
                    grows loud and hoarse.";
1155
 
               2: "^The perspiration of terror runs off your brow.  The
1156
 
                    creatures are almost here!";
1157
 
               3: "^You feel a tickling at your extremities and kick outward,
1158
 
                    shaking something chitinous off.  Their sound alone
1159
 
                    is a menacing rasp.";
1160
 
               4: deadflag=1;
1161
 
                  "^Suddenly there is a tiny pain, of a hypodermic-sharp fang
1162
 
                    at your calf.  Almost at once your limbs go into spasm,
1163
 
                    your shoulders and knee-joints lock, your tongue swells...";
1164
 
           }
1165
 
       ];
1166
 
 
1167
 
   *Note Exercise 37: Daemons.
1168
 
 
1169
 
 
1170
 
File: inform,  Node: Answer 38,  Next: Answer 39,  Prev: Answer 37,  Up: Answers
1171
 
 
1172
 
Answer to Exercise 38: midnight
1173
 
===============================
1174
 
 
1175
 
   Either set a daemon to watch for the_time suddenly dropping, or put
1176
 
such a watch in the game's TimePasses routine.
1177
 
 
1178
 
   *Note Exercise 38: Daemons.
1179
 
 
1180
 
 
1181
 
File: inform,  Node: Answer 39,  Next: Answer 40,  Prev: Answer 38,  Up: Answers
1182
 
 
1183
 
Answer to Exercise 39: nightfall and daybreak
1184
 
=============================================
1185
 
 
1186
 
   A minimal solution is as follows:
1187
 
 
1188
 
Constant SUNRISE  360;  ! i.e., 6 am
1189
 
Constant SUNSET  1140;  ! i.e., 7 pm
1190
 
Attribute outdoors;     ! Give this to external locations
1191
 
Attribute lit;          ! And this to artificially lit ones
1192
 
Global day_state = 2;
1193
 
[ TimePasses f obj;
1194
 
  if (the_time >= SUNRISE && the_time < SUNSET) f=1;
1195
 
  if (day_state == f) rfalse;
1196
 
  objectloop (obj)
1197
 
  {   if (obj has lit) give obj light;
1198
 
      if (obj has outdoors && obj hasnt lit)
1199
 
      {   if (f==0) give obj ~light; else give obj light;
1200
 
      }
1201
 
  }
1202
 
  if (day_state==2) { day_state = f; return; }
1203
 
  day_state = f; if (location hasnt outdoors) return;
1204
 
  if (f==1) "^The sun rises, illuminating the landscape!";
1205
 
 "^As the sun sets, the landscape is plunged into darkness.";
1206
 
];
1207
 
 
1208
 
In the Initialise routine, set the time (using SetTime) and then call
1209
 
TimePasses to set all the light attributes accordingly.  Note that with
1210
 
this system, there's no need to set light at all: that's automatic.
1211
 
 
1212
 
   *Note Exercise 39: Daemons.
1213
 
 
1214
 
 
1215
 
File: inform,  Node: Answer 40,  Next: Answer 41,  Prev: Answer 39,  Up: Answers
1216
 
 
1217
 
Answer to Exercise 40: mid-air location
1218
 
=======================================
1219
 
 
1220
 
   Because you don't know what order daemons will run in.  A `fatigue'
1221
 
daemon which makes the player drop something might come after the
1222
 
`mid-air' daemon has run for this turn.  Whereas each_turn happens
1223
 
after daemons and timers have run their course, and can fairly assume
1224
 
no further movements will take place this turn.
1225
 
 
1226
 
   *Note Exercise 40: Daemons.
1227
 
 
1228
 
 
1229
 
File: inform,  Node: Answer 41,  Next: Answer 42,  Prev: Answer 40,  Up: Answers
1230
 
 
1231
 
Answer to Exercise 41: long time-scale game
1232
 
===========================================
1233
 
 
1234
 
   It would have to provide its own code to keep track of time, and it
1235
 
can do this by providing a TimePasses() routine.  Providing "time" or
1236
 
even "date" verbs to tell the player would also be a good idea.
1237
 
 
1238
 
   *Note Exercise 41: Daemons.
1239
 
 
1240
 
 
1241
 
File: inform,  Node: Answer 42,  Next: Answer 43,  Prev: Answer 41,  Up: Answers
1242
 
 
1243
 
Answer to Exercise 42: player reacting before
1244
 
=============================================
1245
 
 
1246
 
   Two reasons.  Firstly, there are times when we want to be able to
1247
 
trap orders to other people, which react_before does not.  Secondly,
1248
 
the player's react_before rule is not necessarily the first to react.
1249
 
In the case of the player's deafness, a cuckoo may have already used
1250
 
react_before to sing.  But it would have been safe to use
1251
 
GamePreRoutine, if a little untidy (because a rule about the player
1252
 
would not be part of the player's definition, which makes for confusing
1253
 
source code).  See *Note Actions and Reactions:: for the exact sequence
1254
 
of events when actions are processed.
1255
 
 
1256
 
   *Note Exercise 42: Player.
1257
 
 
1258
 
 
1259
 
File: inform,  Node: Answer 43,  Next: Answer 44,  Prev: Answer 42,  Up: Answers
1260
 
 
1261
 
Answer to Exercise 43: silencing player
1262
 
=======================================
1263
 
 
1264
 
       orders
1265
 
       [;  if (gasmask hasnt worn) rfalse;
1266
 
           if (actor==self && action~=##Answer or ##Tell or ##Ask) rfalse;
1267
 
          "Your speech is muffled into silence by the gas mask.";
1268
 
       ],
1269
 
 
1270
 
   *Note Exercise 43: Player.
1271
 
 
1272
 
 
1273
 
File: inform,  Node: Answer 44,  Next: Answer 45,  Prev: Answer 43,  Up: Answers
1274
 
 
1275
 
Answer to Exercise 44: the player's wayhel
1276
 
==========================================
1277
 
 
1278
 
   The common man's `wayhel' was a lowly mouse.  Since we think much
1279
 
more highly of the player:
1280
 
 
1281
 
Object hog "Warthog" Caldera
1282
 
  with name "wart" "hog" "warthog", description "Muddy and grunting.",
1283
 
       number 0,
1284
 
       initial "A warthog snuffles and grunts about in the ash.",
1285
 
       orders
1286
 
       [;  Go, Look, Examine, Eat, Smell, Taste, Touch: rfalse;
1287
 
           default: "Warthogs can't do anything as tricky as that!";
1288
 
       ],
1289
 
  has  animate proper;
1290
 
 
1291
 
and we just ChangePlayer(warthog);.  Note that the same orders routine
1292
 
applies to the player-as-human typing "warthog, listen" as to the
1293
 
player-as-warthog typing just "listen".
1294
 
 
1295
 
   *Note Exercise 44: Player.
1296
 
 
1297
 
 
1298
 
File: inform,  Node: Answer 45,  Next: Answer 46,  Prev: Answer 44,  Up: Answers
1299
 
 
1300
 
Answer to Exercise 45: Giant with conscience
1301
 
============================================
1302
 
 
1303
 
      orders
1304
 
      [;  if (player==self)
1305
 
          {   if (actor~=self)
1306
 
                 "You only become tongue-tied and gabble.";
1307
 
              rfalse;
1308
 
          }
1309
 
          Attack: "The Giant looks at you with doleful eyes.
1310
 
                   ~Me not be so bad!~";
1311
 
          default: "The Giant is unable to comprehend your instructions.";
1312
 
      ],
1313
 
 
1314
 
   *Note Exercise 45: Player.
1315
 
 
1316
 
 
1317
 
File: inform,  Node: Answer 46,  Next: Answer 47,  Prev: Answer 45,  Up: Answers
1318
 
 
1319
 
Answer to Exercise 46: chessboard of rooms
1320
 
==========================================
1321
 
 
1322
 
   Give the "chessboard" room a short_name routine (it probably already
1323
 
has one, to print names like "Chessboard d6") and make it change the
1324
 
short name to "the gigantic Chessboard" if and only if action is
1325
 
currently set to ##Places.
1326
 
 
1327
 
   *Note Exercise 46: Constants and Scoring.
1328
 
 
1329
 
 
1330
 
File: inform,  Node: Answer 47,  Next: Answer 48,  Prev: Answer 46,  Up: Answers
1331
 
 
1332
 
Answer to Exercise 47: varying the prompt
1333
 
=========================================
1334
 
 
1335
 
   Put the following definition between inclusion of "Parser" and
1336
 
"Verblib":
1337
 
 
1338
 
     Object LibraryMessages
1339
 
       with before
1340
 
            [;  Prompt: if (turns==1)
1341
 
                        print "What should you, the detective, do now?^>";
1342
 
                    else
1343
 
                        print "What next?^>";
1344
 
                    rtrue;
1345
 
            ];
1346
 
 
1347
 
   *Note Exercise 47: Extending the Library.
1348
 
 
1349
 
 
1350
 
File: inform,  Node: Answer 48,  Next: Answer 49,  Prev: Answer 47,  Up: Answers
1351
 
 
1352
 
Answer to Exercise 48
1353
 
=====================
1354
 
 
1355
 
   See the `Inform Translator's Manual'.  One must provide a new
1356
 
grammar file (generating the same actions but from different syntax),
1357
 
tables showing how pronouns, possessives and articles work in the new
1358
 
language, a sheaf of translated library messages and so on.  But it can
1359
 
be done.
1360
 
 
1361
 
   *Note Exercise 48: Extending the Library.
1362
 
 
1363
 
 
1364
 
File: inform,  Node: Answer 49,  Next: Answer 50,  Prev: Answer 48,  Up: Answers
1365
 
 
1366
 
Answer to Exercise 49: printing pronouns
1367
 
========================================
1368
 
 
1369
 
   Simply define the following (for accusative, nominative and
1370
 
capitalised nominative pronouns, respectively):
1371
 
 
1372
 
[ PronounAcc i;
1373
 
    if (i hasnt animate) print "it";
1374
 
    else { if (i has female) print "her"; else print "him"; } ];
1375
 
[ PronounNom i;
1376
 
    if (i hasnt animate) print "it";
1377
 
    else { if (i has female) print "she"; else print "he"; } ];
1378
 
[ CPronounNom i;
1379
 
    if (i hasnt animate) print "It";
1380
 
    else { if (i has female) print "She"; else print "He"; } ];
1381
 
 
1382
 
   *Note Exercise 49: Describing Objects.
1383
 
 
1384
 
 
1385
 
File: inform,  Node: Answer 50,  Next: Answer 51,  Prev: Answer 49,  Up: Answers
1386
 
 
1387
 
Answer to Exercise 50: ornate box (inventory inside)
1388
 
====================================================
1389
 
 
1390
 
   Use the invent routine to signal to short_name and article routines
1391
 
to change their usual habits:
1392
 
 
1393
 
       invent
1394
 
       [;  if (inventory_stage==1) give self general;
1395
 
           else give self ~general;
1396
 
       ],
1397
 
       short_name
1398
 
       [;  if (self has general) { print "box"; rtrue; } ],
1399
 
       article
1400
 
       [;  if (self has general) { print "that hateful"; rtrue; }
1401
 
           else print "a"; ],
1402
 
 
1403
 
   *Note Exercise 50: Describing Objects.
1404
 
 
1405
 
 
1406
 
File: inform,  Node: Answer 51,  Next: Answer 52,  Prev: Answer 50,  Up: Answers
1407
 
 
1408
 
Answer to Exercise 51: very verbose mode
1409
 
========================================
1410
 
 
1411
 
   This answer is cheating, as it needs to know about the library's
1412
 
lookmode variable (set to 1 for normal, 2 for verbose or 3 for
1413
 
superbrief).  Simply include:
1414
 
 
1415
 
[ TimePasses;
1416
 
  if (action~=##Look && lookmode==2) <Look>;
1417
 
];
1418
 
 
1419
 
   *Note Exercise 51: Describing Objects.