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

« back to all changes in this revision

Viewing changes to inform-6.31.1/demos/balances.inf

  • 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
! ----------------------------------------------------------------------------
 
2
!   Balances 961216                 One of the standard Inform 6 example games
 
3
!
 
4
!                                                             created: 25.9.94
 
5
!                                                             updated: 6.10.94
 
6
!                                                         modernised: 11.12.95
 
7
!                                               translated to Inform 6: 8.5.96
 
8
!                                                   minor bugs fixed: 16.12.96
 
9
!
 
10
!   This short story was written to demonstrate large-scale programming of
 
11
!   the parser, and features multiple objects, complicated plurals, variable
 
12
!   verbs, objects named by the player and questions.  The spell-casting
 
13
!   system is written in a "safe" way so that it could easily be transplanted.
 
14
!
 
15
!   Needs Inform 6, library 6/1 or later to compile.
 
16
! ----------------------------------------------------------------------------
 
17
 
 
18
Release 5;
 
19
Serial "961216";
 
20
Switches d;
 
21
 
 
22
Constant Story "BALANCES";
 
23
Constant Headline "^An Interactive Short Story
 
24
                   ^Copyright (c) 1994, 1995, 1996 by Graham Nelson.^";
 
25
 
 
26
Constant OBJECT_SCORE 5;
 
27
Constant MAX_SCORE 51;
 
28
 
 
29
Include "Parser";
 
30
Include "VerbLib";
 
31
 
 
32
! ----------------------------------------------------------------------------
 
33
!   The white featureless cubes from "Spellbreaker", which can be identified
 
34
!   by being written on with the magic burin, so that their names are given
 
35
!   by the player in the course of play
 
36
!
 
37
!   A particularly witty thing to do is to give several of them the same name,
 
38
!   or to frotz some of them to distinguish them from the others...
 
39
!   And the game will have no problem with this.
 
40
! ----------------------------------------------------------------------------
 
41
 
 
42
Array cube_text_buffer -> 8;
 
43
Global the_named_word = 0;
 
44
Global from_char; Global to_char;
 
45
 
 
46
Class  FeaturelessCube
 
47
  with number 0 0 0 0,   ! There's room for 8 bytes of text in these 4 entries
 
48
       description "A perfect white cube, four inches on a side.",
 
49
       parse_name
 
50
       [ i j flag;
 
51
            if (parser_action==##TheSame)
 
52
            {   for (i=0:i<8:i++)
 
53
                    if ((parser_one.&number)->i
 
54
                        ~= (parser_two.&number)->i) return -2;
 
55
                return -1;
 
56
            }
 
57
            for (::i++)
 
58
            {   j=NextWord(); flag=0;
 
59
                if (j=='cube' or 'white' ||
 
60
                    (j=='featureless' or 'blank' &&
 
61
                           ((self.&number)->0) == 0)) flag=1;
 
62
                if (j=='cubes')
 
63
                {   flag=1; parser_action=##PluralFound; }
 
64
                if (flag==0 && ((self.&number)->0) ~= 0)
 
65
                {   wn--;
 
66
                    if (TextReader(0)==0) return i;
 
67
                    for (j=0: j<8: j++)
 
68
                        if ((self.&number)->j ~= cube_text_buffer->j)
 
69
                            return i;
 
70
                    flag=1;
 
71
                }
 
72
                if (flag==0) return i;
 
73
            }
 
74
       ],
 
75
       article "a",
 
76
       short_name
 
77
       [ i; if (((self.&number)->0) == 0) print "featureless white cube";
 
78
            else
 
79
            {   print "~";
 
80
                while (((self.&number)->i) ~= 0)
 
81
                    print (char) (self.&number)->i++;
 
82
                print "~ cube";
 
83
            }
 
84
            rtrue;
 
85
       ],
 
86
       plural
 
87
       [;   self.short_name(); print "s";
 
88
       ],
 
89
       baptise
 
90
       [ i; wn = the_named_word;
 
91
            if (TextReader(1)==0) return i;
 
92
            for (i=0: i<8: i++)
 
93
                (self.&number)->i = cube_text_buffer->i;
 
94
            self.article="the";
 
95
            print_ret "It is now called ", (the) self, ".";
 
96
       ],
 
97
  has  scored;
 
98
 
 
99
!  Copies word "wn" from what the player most recently typed, putting it as
 
100
!  plain text into cube_text_buffer, returning false if no such word is there
 
101
 
 
102
[ TextReader flag point i j len;
 
103
 
 
104
   if (flag==1 && from_char~=to_char)
 
105
   {   for (i=from_char, j=0:i<=to_char && j<7:i++)
 
106
       {   cube_text_buffer->j = buffer->i;
 
107
           if (buffer->i ~= ' ' or ',' or '.') j++;
 
108
       }
 
109
       for (:j<8:j++) cube_text_buffer->j = 0;
 
110
       from_char=0; to_char=0;
 
111
       rtrue;
 
112
   }
 
113
 
 
114
   for (i=0:i<8:i++) cube_text_buffer->i = 0;
 
115
   if (wn > parse->1) { wn++; rfalse; }
 
116
   i=wn*4+1; j=parse->i; point=j+buffer; len=parse->(i-1);
 
117
 
 
118
   for (i=0:i<len && i<7:i++) cube_text_buffer->i = point->i;
 
119
 
 
120
   wn++; rtrue;
 
121
];
 
122
 
 
123
Object burin "magic burin"
 
124
  with name "magic" "magical" "burin" "pen",
 
125
       description
 
126
          "This is a magical burin, used for inscribing objects with words
 
127
           or runes of magical import. Such a burin also gives you the
 
128
           ability to write spell scrolls.",
 
129
       before
 
130
       [; WriteOn:
 
131
             if (second ofclass FeaturelessCube)
 
132
             {   if (second notin player)
 
133
                     "Writing on a cube is such a fiddly process that you
 
134
                      need to be holding it in your hand first.";
 
135
                 if (burin notin player)
 
136
                     "You would need some powerful implement for that.";
 
137
                 second.baptise();
 
138
                 rtrue;
 
139
             }
 
140
             if (second ofclass SpellBook)
 
141
                 "If a burin could write in a spell book, you wouldn't need
 
142
                  the gnusto spell!";
 
143
             if (second ofclass Scroll)
 
144
                 "You cannot write just anything on the magic parchment of
 
145
                  a scroll: you can only ~copy~ a spell to it.";
 
146
       ];
 
147
 
 
148
[ WriteOnSub; "Graffiti is banned."; ];
 
149
 
 
150
[ CopyToSub;
 
151
  if (burin notin player) "You need to be holding the burin to copy a spell.";
 
152
  if (second ofclass SpellBook)
 
153
      "If a burin could write in a spell book, you wouldn't need
 
154
       the gnusto spell!";
 
155
  if (~~(second ofclass Scroll)) "You can only copy spells to scrolls.";
 
156
  if (child(second)~=0)
 
157
      "The scroll is already full of incantation.";
 
158
  "The scroll is not blank, only illegible.";
 
159
];
 
160
 
 
161
! ----------------------------------------------------------------------------
 
162
!   Now the whole spell-casting system
 
163
! ----------------------------------------------------------------------------
 
164
 
 
165
Attribute known_about;                 ! Player has seen this spell somewhere
 
166
Attribute reversed;                    ! Effect of this known spell reversed
 
167
 
 
168
Attribute is_spell;
 
169
Class  Spell
 
170
  with name "spell" "spells", article "the",
 
171
       number 0,
 
172
       word_name
 
173
       [;  print (address) (self.&name)-->0;
 
174
       ],
 
175
       short_name
 
176
       [;  self.word_name(); print " spell"; give self known_about; rtrue;
 
177
       ],
 
178
       specification
 
179
       [;  self.short_name();
 
180
           print ": ", (string) self.purpose;
 
181
       ],
 
182
       before
 
183
       [;  Examine: self.specification(); ".";
 
184
       ],
 
185
  has  is_spell;
 
186
 
 
187
Object memory
 
188
  with capacity 5,
 
189
       number_known 1,
 
190
       describe_contents
 
191
       [ i j k;
 
192
           objectloop (i in self) if (i.number==100) j++;
 
193
           if (j>0)
 
194
           {   print "The ";
 
195
               objectloop (i in self)
 
196
                   if (i.number==100)
 
197
                   {   k++; i.word_name();
 
198
                       if (k==j-1) print " and ";
 
199
                       if (k<j-1) print ", ";
 
200
                   }
 
201
               if (j==1) print " spell is"; else print " spells are";
 
202
               print " yours forever.  Other than that, y";
 
203
           }
 
204
           else print "Y";
 
205
           print "ou have ";
 
206
           j=0; k=0;
 
207
           objectloop (i in self) if (i.number<100) j++;
 
208
           if (j>0)
 
209
           {   print "the ";
 
210
               objectloop (i in self)
 
211
                   if (i.number<100)
 
212
                   {   k++;
 
213
                       print (name) i;
 
214
                       if (i.number==2) print " (twice)";
 
215
                       if (i.number==3) print " (thrice)";
 
216
                       if (i.number==4) print " (four times)";
 
217
                       if (i.number>=5) print " (many times)";
 
218
                       if (k==j-1) print " and ";
 
219
                       if (k<j-1) print ", ";
 
220
                   }
 
221
           }
 
222
           else print "no spells";
 
223
           " memorised.";
 
224
       ],
 
225
       learn_spell
 
226
       [ sp;
 
227
           if (sp.number==100) "You always know that spell.";
 
228
           print "Using your best study habits, you commit the ";
 
229
           sp.word_name();
 
230
           print " spell to memory";
 
231
           if (sp notin self) sp.number=0;
 
232
           move sp to self;
 
233
           self.number_known++;
 
234
           sp.number++;
 
235
           if (sp.number==1) print ".";
 
236
           if (sp.number==2) print " once again.";
 
237
           if (sp.number==3) print " a third time.";
 
238
           if (sp.number>3) print " yet another time.";
 
239
           if (self.number_known <= self.capacity) { new_line; rtrue; }
 
240
           self.forget_spell(sibling(child(self)));
 
241
           "  You have so much buzzing around in your head, though,
 
242
              that it's likely something may have been forgotten
 
243
              in the shuffle.";
 
244
       ],
 
245
       forget_spell
 
246
       [ sp;
 
247
           if (sp notin self || sp.number==100) rtrue;
 
248
           self.number_known--;
 
249
           sp.number--;
 
250
           if (sp.number==0) remove sp;
 
251
           rtrue;
 
252
       ];
 
253
 
 
254
Spell -> gnusto_spell
 
255
  with name "gnusto",
 
256
       purpose "copy a scroll into your spell book",
 
257
       number 100,
 
258
       magic
 
259
       [ i a_book;
 
260
            if (second ofclass SpellBook)
 
261
               "Unlike scrolls, spell books are magically guarded against
 
262
                the 'theft' of their lore.";
 
263
            if (second==0 || ~~(second ofclass Scroll))
 
264
               "Your spell fizzles vaguely out.";
 
265
            if (second notin player)
 
266
                "A gnusto spell would require close scrutiny of the scroll
 
267
                 it is to copy: which you do not seem to be holding.";
 
268
            objectloop (i in player)
 
269
                if (i ofclass SpellBook) a_book=i;
 
270
            if (a_book==0)
 
271
                "Your spell fails, as you have no spell book.";
 
272
            i=child(second);
 
273
            if (i==0 || ~~(i ofclass Spell))
 
274
            {   print_ret "Your spell fails, as ", (the) second,
 
275
                   " is illegible.";
 
276
            }
 
277
            a_book.learn_spell(i); remove second;
 
278
            print_ret
 
279
               "Your spell book begins to glow softly.  Slowly, ornately,
 
280
                the words of ", (the) i, " are inscribed,
 
281
                glowing even more brightly then the book itself. 
 
282
                The book's brightness fades, but the spell remains! 
 
283
                However, the scroll on which it was written vanishes as
 
284
                the last word is copied.";
 
285
       ];
 
286
 
 
287
Class SpellBook
 
288
  with array_of_spells 0 0 0 0  0 0 0 0  0 0 0 0  0 0 0 0,
 
289
       capacity 16,
 
290
       learn_spell
 
291
       [ sp p i;
 
292
              p = self.&array_of_spells;
 
293
              for (i=0:i<self.capacity && (p-->i)~=0:i++) ;
 
294
              if (i==self.capacity) rtrue;
 
295
              p-->i = sp;
 
296
       ],
 
297
       before
 
298
       [; Open, Close:
 
299
              print_ret
 
300
              (The) self, " is always open to the right place, but it
 
301
              is also always closed. This eliminates tedious leafing and
 
302
              hunting for spells.  Many lives have been saved by this
 
303
              magical innovation.";
 
304
          Attack:
 
305
              print_ret "When you are done, ", (the) self, " remains unmarred.";
 
306
       ],
 
307
       after
 
308
       [ p i j; Examine:
 
309
              p = self.&array_of_spells;
 
310
              for (i=0:i<self.capacity && (p-->i)~=0:i++)
 
311
              {   j=p-->i; <Examine j>;
 
312
              }
 
313
              rtrue;
 
314
       ];
 
315
 
 
316
Class Scroll
 
317
  with parse_name
 
318
       [ i j k; j=-1;
 
319
              if (self has general)
 
320
              {   if (child(self)~=0 && child(self) ofclass Spell)
 
321
                      j=(child(self).&name)-->0; else j='illegible';
 
322
              }
 
323
              for (::)
 
324
              {   k=NextWord();
 
325
                  if (k=='scrolls') parser_action=##PluralFound;
 
326
                  if ((k=='scrolls' or 'scroll' or j) || k==(self.&name)-->0)
 
327
                      i++;
 
328
                  else return i;
 
329
              }
 
330
       ],
 
331
       before
 
332
       [ i; Examine:
 
333
            i=child(self);
 
334
            give self general;
 
335
            if (i==0 || ~~(i ofclass Spell))
 
336
                "The scroll has faded, and you cannot read it.";
 
337
            print "The scroll reads ~"; i.specification(); "~.";
 
338
       ],
 
339
       invent
 
340
       [;   if (inventory_stage==2 && self has general)
 
341
            {   if (child(self)==0 || ~~(child(self) ofclass Spell))
 
342
                    print " (which is illegible)";
 
343
                else
 
344
                {   print " (of ", (the) child(self), ")"; }
 
345
            }
 
346
       ];
 
347
 
 
348
[ ReadableSpell i j k;
 
349
  if (scope_stage==1)
 
350
  {   if (action_to_be==##Examine) rfalse;
 
351
      rtrue;
 
352
  }
 
353
  if (scope_stage==2)
 
354
  {   objectloop (i in player)
 
355
          if (i ofclass SpellBook)
 
356
          {   for (k=0:k<i.capacity && (i.&array_of_spells)-->k~=0:k++)
 
357
              {   j=(i.&array_of_spells)-->k; PlaceInScope(j);
 
358
              }
 
359
          }
 
360
      rtrue;
 
361
  }
 
362
  ! No need for scope_stage 3 (the error stage), because our
 
363
  ! ParserError routine handles that case instead
 
364
];
 
365
 
 
366
[ CopyableSpell i j k;
 
367
  if (scope_stage==1) return 1;
 
368
  if (scope_stage==2)
 
369
  {   objectloop (i in player)
 
370
          if (i ofclass SpellBook)
 
371
          {   for (k=0:k<i.capacity && (i.&array_of_spells)-->k~=0:k++)
 
372
              {   j=(i.&array_of_spells)-->k; PlaceInScope(j);
 
373
              }
 
374
          }
 
375
      rfalse;
 
376
  }
 
377
  ! No need for scope_stage 3 (the error stage), because our
 
378
  ! ParserError routine handles that case instead
 
379
];
 
380
 
 
381
[ SpellsSub; memory.describe_contents(); ];
 
382
 
 
383
[ LearnSub; if (location==thedark)
 
384
                print "(The magic writing of the spells casts enough light
 
385
                        that you can read them.)^";
 
386
            memory.learn_spell(noun);
 
387
];
 
388
 
 
389
Global the_spell_was = gnusto_spell;
 
390
 
 
391
[ CastOneSub; <Cast the_spell_was noun>; ];
 
392
 
 
393
[ CastSub;
 
394
  the_spell_was = noun; memory.forget_spell(noun);
 
395
 
 
396
  if (noun has reversed)
 
397
  {   give noun ~reversed;
 
398
      if (noun.unmagic() ~= 0) return;
 
399
      "Nothing happens.";
 
400
  }
 
401
 
 
402
  if (second ~= 0)
 
403
  {   ResetVagueWords(second);                     ! Set "it", "him", "her"
 
404
      if (second provides before
 
405
          && second.before() ~= 0) return;         ! Run before routine(s)
 
406
  }
 
407
  if (noun.magic() ~= 0) return;
 
408
  "Nothing happens.";
 
409
];
 
410
 
 
411
[ InScope i;
 
412
  if (verb_word=='c,cast' or 'cast')
 
413
      objectloop (i in memory) PlaceInScope(i);
 
414
  rfalse;
 
415
];
 
416
 
 
417
[ ParserError x i flag vb;
 
418
  if (etype==VERB_PE or ASKSCOPE_PE)
 
419
  {   if (etype==ASKSCOPE_PE)
 
420
      {   if (verb_word=='cast') vb=1;
 
421
          if (verb_word=='learn' or 'memorise' or 'memorize') vb=2;
 
422
          if (verb_word=='copy') vb=3;
 
423
          if (vb==0) { etype=CANTSEE_PE; rfalse; }
 
424
      }
 
425
      wn=verb_wordnum; if (vb~=0) wn++;
 
426
      x=NextWordStopped();
 
427
      for (i=player+1:i<=top_object:i++)
 
428
          if (i ofclass Spell && Refers(i,x)==1
 
429
              && i has known_about) flag=1;
 
430
      if (flag==1)
 
431
      {   if (vb==0 or 1)
 
432
             "You haven't got that spell committed to memory.  [Type ~spells~
 
433
              to see what you do remember.]";
 
434
          if (vb==2)
 
435
             "Your training is such that you can only memorise such a spell
 
436
              with the aid of a spell book containing it.";
 
437
          if (vb==3)
 
438
             "You have no text of that spell to copy.";
 
439
      }
 
440
      if (vb==1)
 
441
         "You haven't learned that spell, if indeed it is a spell.";
 
442
      if (vb==2 or 3)
 
443
         "You haven't access to that spell, if indeed it is a spell.";
 
444
  }
 
445
  rfalse;
 
446
];
 
447
 
 
448
[ ChooseObjects obj code;
 
449
  if (code<2) rfalse;
 
450
  if (action_to_be==##WriteOn && obj in player) return 9;
 
451
  return 0;
 
452
];
 
453
 
 
454
[ UnknownVerb word i;
 
455
  objectloop (i in memory)
 
456
      if (word==(i.&name)-->0) { the_spell_was = i; return 'c,cast'; }
 
457
  rfalse;
 
458
];
 
459
 
 
460
[ PrintVerb v;
 
461
  if (v=='c,cast') { print "cast a spell at"; rtrue; }
 
462
  rfalse;
 
463
];
 
464
 
 
465
! ----------------------------------------------------------------------------
 
466
!   And now, on with the story.  First, some global variables:
 
467
! ----------------------------------------------------------------------------
 
468
 
 
469
Global prepared_flag = false;      !  Prepared for resurrection?
 
470
Global hearing_good  = false;      !  Sharp hearing?
 
471
Global number_filled = 0;          !  Sockets in the temple filled
 
472
 
 
473
! ----------------------------------------------------------------------------
 
474
!   A "questions" verb.  Thus,
 
475
!      "who is my friend helistar"
 
476
!      "what was the great change"
 
477
!   and so on are recognised.
 
478
! ----------------------------------------------------------------------------
 
479
 
 
480
[ QuerySub;
 
481
  noun.description();
 
482
];
 
483
[ Topic i;
 
484
  if (scope_stage==1) return 0;
 
485
  if (scope_stage==2)
 
486
  {   objectloop (i ofclass Question) PlaceInScope(i);
 
487
      rtrue;
 
488
  }
 
489
  "At the moment, even the simplest questions confuse you.";
 
490
];
 
491
 
 
492
Class Question;
 
493
Question
 
494
  with name "helistar" "my" "friend" "colleague",
 
495
       description
 
496
      "Helistar is your colleague, an Enchanter like you who has been much
 
497
       on your mind lately.  She has been investigating some very dark
 
498
       magic indeed, and seems not to be around any more.  You feel rather
 
499
       vague about the details.";
 
500
Question
 
501
  with name "magical" "magic" "burin",
 
502
       description "A burin is an engraving and writing tool.";
 
503
Question
 
504
  with name "change" "great",
 
505
       description
 
506
      "Something you had a lot to do with, but what exactly?  No, it's gone.";
 
507
Question
 
508
  with name "cyclops",
 
509
       description
 
510
      "A one-eyed giant, usually hostile.  (Don't they teach anything at
 
511
       adventurer school these days?)";
 
512
Question
 
513
  with name "grue",
 
514
       description
 
515
      "The grue is a sinister, lurking presence in the dark places of the
 
516
       earth. Its favorite diet is adventurers, but its insatiable appetite
 
517
       is tempered by its fear of light. No grue has ever been seen by the
 
518
       light of day, and few have survived its fearsome jaws to
 
519
       tell the tale.";
 
520
Question
 
521
  with name "grimoire",
 
522
       description
 
523
      "According to Chambers English Dictionary, a grimoire is ~a magician's
 
524
       book for calling up spirits~.";
 
525
Question
 
526
  with name "spells" "work",
 
527
       description
 
528
      "Your memory is still dream-hazed, but it's coming back. As a trained
 
529
       Enchanter, you have the ability to cast spells like ~frotz~, provided
 
530
       you have learned them in advance.  Some of these spells can be cast
 
531
       at something; others can be cast alone.
 
532
     ^^Spells are very complicated.  Each time you cast one, you forget it
 
533
       (though you can get around this by learning it several times, so as
 
534
       to have several uses up your sleeve).  The only way to hang on to
 
535
       a spell is to have it written down, on a scroll or in a spell book.
 
536
       Scrolls are not ideal for this, and you can only learn a spell from
 
537
       your spell book.  (But you can add spells to your book.)
 
538
     ^^[Type ~learn frotz~ and then ~frotz coin~ for an example.  You can
 
539
       also type ~spells~ to see what you currently have memorised.]";
 
540
 
 
541
! ----------------------------------------------------------------------------
 
542
!   Some multiple objects, coins in fact, coded in deluxe fashion:
 
543
! ----------------------------------------------------------------------------
 
544
 
 
545
Attribute is_coin;
 
546
Class Coin
 
547
  with name "coin",
 
548
       description "A round unstamped disc, presumably part of the local
 
549
           currency.",
 
550
       parse_name
 
551
       [ i j w;
 
552
         if (parser_action==##TheSame)
 
553
         {   if ((parser_one.&name)-->0 == (parser_two.&name)-->0) return -1;
 
554
             return -2;
 
555
         }
 
556
         w=(self.&name)-->0;
 
557
         for (::i++)
 
558
         {   j=NextWord();
 
559
             if (j=='coins') parser_action=##PluralFound;
 
560
             else if (j~='coin' or w) return i;
 
561
         }
 
562
       ],
 
563
  has  is_coin;
 
564
 
 
565
Class GoldCoin
 
566
 class Coin,
 
567
  with name "gold",
 
568
       short_name "gold coin",
 
569
       plural "gold coins";
 
570
Class SilverCoin
 
571
 class Coin,
 
572
  with name "silver",
 
573
       short_name "silver coin",
 
574
       plural "silver coins";
 
575
Class BronzeCoin
 
576
 class Coin,
 
577
  with name "bronze",
 
578
       short_name "bronze coin",
 
579
       plural "bronze coins";
 
580
 
 
581
SilverCoin players_coin;
 
582
 
 
583
[ TossCoinSub; if (noun notin player) "You need to be holding the coin first.";
 
584
  move noun to parent(player);
 
585
  if (location==thedark) "You throw it away into the darkness.";
 
586
  if (random(20)==1)
 
587
     "You toss the coin, and it lands... on its edge, amazingly.";
 
588
  "You toss the coin, and it comes up... blank, since neither side is
 
589
   marked.";
 
590
];
 
591
 
 
592
! ----------------------------------------------------------------------------
 
593
!   The player's spell book, and three initial spells (to go with gnusto):
 
594
! ----------------------------------------------------------------------------
 
595
 
 
596
SpellBook players_book "spell book"
 
597
  with name "spell" "book" "my" "spellbook",
 
598
       description "My Spell Book^";
 
599
 
 
600
Spell frotz_spell
 
601
  with name "frotz",
 
602
       purpose "cause an object to give off light",
 
603
       magic
 
604
       [;  if (second==0) "There is a brief, blinding flash of light.";
 
605
           if (second has animate)
 
606
               "The spell, not designed for living creatures, goes sour.";
 
607
           if (second in compass)
 
608
               "The spell dissipates vaguely.";
 
609
           give second light;
 
610
           print_ret
 
611
            "There is an almost blinding flash of light as ", (the) second,
 
612
            " begins to glow!  It slowly fades to a less painful level, but ",
 
613
            (the) second, " is now quite usable as a light source.";
 
614
       ],
 
615
       unmagic
 
616
       [;  if (second==0) "There is a brief moment of deep darkness.";
 
617
           if (second has animate)
 
618
               "The spell, not designed for living creatures, goes sour.";
 
619
           if (second in compass)
 
620
               "The spell dissipates vaguely.";
 
621
           if (second hasnt light)
 
622
               print_ret (The) second, " isn't producing light as it is.";
 
623
           give second ~light;
 
624
           print_ret "A pool of darkness coagulates around ", (the) second,
 
625
                 " but slowly fades back to normality.  Still, ",
 
626
                 (the) second, " is no longer any kind of light source.";
 
627
       ];
 
628
 
 
629
Spell rezrov_spell
 
630
  with name "rezrov",
 
631
       purpose "open even locked or enchanted objects",
 
632
       magic
 
633
       [;  if (second==0) "The world is open already.";
 
634
           if (second has animate)
 
635
               "It might be a boon to surgeons if it worked, but it doesn't.";
 
636
           if (second has open || second hasnt openable)
 
637
               "It doesn't need opening.";
 
638
           if (second hasnt locked)
 
639
           {   give second open;
 
640
               print_ret (The) second, " opens obediently. 
 
641
               Like swatting a fly with a sledge hammer, if you ask me.";
 
642
           }
 
643
           give second open ~locked;
 
644
           print "Silently, ", (the) second, " swings open. ";
 
645
           if (second has container) <<Search second>>; new_line; rtrue;
 
646
       ],
 
647
       unmagic
 
648
       [;  if (second==0) "The world is closed already.";
 
649
           if (second has animate)
 
650
               "Happily, that is unnecessary.";
 
651
           if (second has locked || second hasnt lockable)
 
652
               "It doesn't need locking.";
 
653
           give second ~open locked;
 
654
           "Silently, ", (the) second, " swings shut and locks.";
 
655
       ];
 
656
 
 
657
Spell yomin_spell
 
658
  with name "yomin",
 
659
       purpose "mind probe",
 
660
       magic
 
661
       [;  if (second==0 || second hasnt animate)
 
662
               "That must be either vegetable or mineral.";
 
663
           if (second==player) "You give yourself a mild headache.";
 
664
           print_ret "You look into the rather ordinary thoughts of ",
 
665
                     (the) second, ".";
 
666
       ],
 
667
       unmagic
 
668
       [;  if (second==0 || second hasnt animate)
 
669
               "That must be either vegetable or mineral.";
 
670
           if (second==player) "You give yourself a mild headache.";
 
671
           print_ret (The) second, " is rather shocked, for some reason.";
 
672
       ];
 
673
 
 
674
! ----------------------------------------------------------------------------
 
675
!   The first scene: the Hut and its (rather easy) secret 
 
676
! ----------------------------------------------------------------------------
 
677
 
 
678
Class Place
 
679
  has  light;
 
680
 
 
681
Place Hut "Ramshackle Hut"
 
682
  with description
 
683
          "Until quite recently, someone lived here, you feel sure. 
 
684
           Now the furniture is matchwood and
 
685
           the windows are glassless.  Outside, it is a warm, sunny day,
 
686
           and grasslands extend to the low hills on the horizon.",
 
687
       out_to Grasslands, w_to Grasslands,
 
688
       cant_go "There's only the one room: better go ~out~.",
 
689
       name "windows" "grasslands" "grass" "hills";
 
690
 
 
691
Object -> furniture "wooden furniture"
 
692
  with name "furniture" "broken" "wood" "wooden",
 
693
       before
 
694
       [;  Examine, Search, LookUnder:
 
695
               self.before=0; score=score+5;
 
696
               move h_box to player;
 
697
               "Searching through the furniture, which is good for nothing
 
698
                but firewood now, you come across an old cedarwood box,
 
699
                which you pick up for a closer look.";
 
700
       ],
 
701
  has  scenery;
 
702
 
 
703
Object h_box "cedarwood box"
 
704
  with name "cedar" "cedarwood" "wooden" "box",
 
705
       description "The box bears the calligraphed initial H."
 
706
  has  container openable lockable locked;
 
707
 
 
708
SpellBook -> helistars_book "Helistar's grimoire"
 
709
  with name "grimoire" "helistar" "helistars",
 
710
       description "This must be the grimoire of dangerous spells kept by
 
711
                    your irresponsible friend Helistar.  Many pages are
 
712
                    missing, but a few spells remain:^",
 
713
  has  proper;
 
714
 
 
715
! ----------------------------------------------------------------------------
 
716
!   Grasslands and the valley
 
717
! ----------------------------------------------------------------------------
 
718
 
 
719
Place Grasslands "Grasslands, near Hut"
 
720
  with name "grasslands" "grass" "hut" "path",
 
721
       description
 
722
          "The grasslands sway over low hills in all directions: it is a
 
723
           peaceful wilderness, broken only by this hut and a faint path
 
724
           to the north.",
 
725
       in_to Hut, e_to Hut,
 
726
       n_to Valley,
 
727
       cant_go "You wander around for a while but end up back at the hut.";
 
728
 
 
729
Place Valley "Pocket Valley"
 
730
  with name "valley" "trail",
 
731
       description
 
732
          "A pleasant pocket valley in the grassy hills, through which a
 
733
           trail runs north-to-south.",
 
734
       n_to "The trail runs out to nothing, and you retreat for fear of
 
735
             getting so lost you couldn't find the hut again by nightfall.",
 
736
       cant_go "You wander around the pleasant valley, but are afraid to
 
737
                lose sight of the trail.",
 
738
       s_to Grasslands;
 
739
 
 
740
[ RideSub; print_ret "You can hardly ride ", (a) noun, "."; ];
 
741
 
 
742
Object -> horse "horse"
 
743
  with short_name
 
744
       [; if (self has general) print "winged horse";
 
745
          else print "chestnut horse";
 
746
          rtrue;
 
747
       ],
 
748
       parse_name
 
749
       [ i j; if (self has general) j='winged'; else j=-1;
 
750
          while (NextWord()==j or 'horse' or 'chestnut') i++;
 
751
          return i;
 
752
       ],
 
753
       describe
 
754
       [;  print_ret
 
755
              "There is ", (a) self, " here, munching on a pile of oats.";
 
756
       ],
 
757
       before
 
758
       [;  Cast: if (the_spell_was == bozbar_spell)
 
759
                 {   give self general;
 
760
                    "A pair of handsome brown wings suddenly appears on
 
761
                     the horse's powerful shoulders.  The horse turns in a
 
762
                     complete circle, a look of puzzlement on his face.";
 
763
                 }
 
764
                 if (the_spell_was == yomin_spell)
 
765
                    "He is mainly thinking about oats.  Partly who you are
 
766
                     and what you're up to, but mainly oats.";
 
767
           Enter: <<Ride self>>;
 
768
           Ride: if (horse hasnt general)
 
769
                    "You ride around for a while, exercising the horse, but
 
770
                     soon enough he tires of this and pointedly brings you
 
771
                     back to the oats.  Obligingly you dismount and he
 
772
                     begins grazing again.";
 
773
 
 
774
           print "You begin to ride north.  Then, slowly at first but with
 
775
                  increasing sureness, the horse begins beating its powerful
 
776
                  wings.  You rise majestically through the air, sailing
 
777
                  gracefully across a chasm where the hills fall away. 
 
778
                  The horse lands gently on the far side and deposits you,
 
779
                  taking to the skies again.^";
 
780
           PlayerTo(Edge); rtrue;
 
781
       ],
 
782
  has  animate;
 
783
 
 
784
Object -> oats "pile of oats"
 
785
  with name "oats" "pile" "of",
 
786
       before
 
787
       [;  Examine, Search, LookUnder:
 
788
               self.before=NULL;
 
789
               move shiny_scroll to player; score=score+5;
 
790
               itobj=shiny_scroll;
 
791
               "Sifting through the oats, you find a shiny scroll!  Lucky
 
792
                you got to it before the horse did.  As you turn it over
 
793
                in your hands, it seems undamaged.";
 
794
           Take:  "What would you want with all those oats?";
 
795
       ],
 
796
  has  scenery;
 
797
 
 
798
Scroll shiny_scroll "shiny scroll"
 
799
  with name "shiny";
 
800
 
 
801
Spell -> bozbar_spell
 
802
  with name "bozbar",
 
803
       purpose "cause an animal to sprout wings",
 
804
       magic
 
805
       [;  if (second==0 || second hasnt animate)
 
806
               "The spell dies away in vain.";
 
807
           if (second==player)
 
808
               "Your elbows twitch, but there is no other effect.";
 
809
           print_ret "For a moment, ", (the) second,
 
810
               " looks highly discomforted, but the moment passes.";
 
811
       ],
 
812
       unmagic
 
813
       [;  if (second==0 || second hasnt animate)
 
814
               "The spell dies away in vain.";
 
815
           if (second==player) "What wings?";
 
816
           if (second==horse && horse has general)
 
817
           {   give horse ~general;
 
818
               "The Enchanter giveth, and the Enchanter taketh away. 
 
819
                The horse looks disconsolate but returns to the oats.";
 
820
           }
 
821
           print_ret (The) second, " has no wings to lose.";
 
822
       ];
 
823
 
 
824
! ----------------------------------------------------------------------------
 
825
!   The Chasm and the snake
 
826
! ----------------------------------------------------------------------------
 
827
 
 
828
Place Edge "Edge of Chasm"
 
829
  with name "wide" "chasm" "road" "daffodils" "clump",
 
830
       description
 
831
          "The road ends suddenly at a wide chasm.  The road leads upward
 
832
           to the north, and you can see it continuing on the southern side
 
833
           of the chasm.",
 
834
       u_to Up_Road, n_to Up_Road,
 
835
       cant_go "The chasm is too perilous to approach.  The only safe way is
 
836
               up and to the north.",
 
837
       before
 
838
       [;  Jump: deadflag = true;
 
839
              "You jump bravely into the chasm, and plunge...
 
840
               gracefully through the air.  (It gets a bit less noble and
 
841
               airy after that.)";
 
842
       ];
 
843
 
 
844
Object -> snake "hissing snake"
 
845
  with name "hissing" "snake",
 
846
       initial
 
847
         "Lying in a tight coil at the edge of the chasm is a hissing snake.",
 
848
       description
 
849
         "It has some V-markings, some scaly parts, colours from grey to
 
850
          reddish-brown. Is that any help?",
 
851
       life
 
852
       [; "The snake hisses angrily!"; ],
 
853
       before
 
854
       [;  Cast:
 
855
               switch(the_spell_was)
 
856
               {   urbzig_spell:
 
857
                       remove self;
 
858
                       snakes_cube.initial =
 
859
                    "Beside a clump of daffodils is a featureless white cube.";
 
860
                       "The snake is replaced by a clump of daffodils.";
 
861
                   bozbar_spell:
 
862
                       deadflag = true; remove self;
 
863
                       snakes_cube.initial =
 
864
                      "A featureless cube rests where the snake took off from.";
 
865
                      "The snake is transformed into a huge, winged serpent,
 
866
                       a dragon which bellows and leaps out into the chasm,
 
867
                       backwinging furiously... and knocking you over the
 
868
                       edge quite by accident.";
 
869
                   yomin_spell:
 
870
                      "Horrid reptilian thoughts insinuate their way into you.";
 
871
               }
 
872
           Take, Remove:
 
873
              "The slipperiness of its skin is only one of many reasons
 
874
               why this is ill-advised.";
 
875
       ],
 
876
  has  animate;
 
877
 
 
878
FeaturelessCube -> snakes_cube "cube"
 
879
  with initial
 
880
         "The snake appears to be curled around a featureless white cube.",
 
881
       before
 
882
       [; if (snake notin nothing) "The snake won't let you near that cube!";
 
883
       ];
 
884
 
 
885
! ----------------------------------------------------------------------------
 
886
!   The crest of the hill; Icarus the tortoise; the chewed scroll
 
887
! ----------------------------------------------------------------------------
 
888
 
 
889
Place Up_Road "Crest of Hill"
 
890
  with description
 
891
          "The road crosses the top of a ridge here, sloping downwards to
 
892
           the south and the northwest.  A track diverges to east.",
 
893
       nw_to Cave_Mouth, s_to Edge, d_to Edge, e_to Track;
 
894
 
 
895
Object -> tortoise "tortoise"
 
896
  with name "tortoise" "turtle",
 
897
       initial "A tortoise ambles along the road, extremely slowly.",
 
898
       life
 
899
       [; "The tortoise (slowly) turns its neck to look at you (stupidly).";
 
900
       ],
 
901
       before
 
902
       [; Cast: switch(the_spell_was)
 
903
                {   urbzig_spell:
 
904
                       "Just how safe do you want your surroundings to be?";
 
905
                    bozbar_spell:
 
906
                        move chewed_scroll to parent(self); remove self;
 
907
                        StartDaemon(self); score=score+5;
 
908
                       "The tortoise seems to be incapable of expressing
 
909
                        surprise, but is now soaring away high in the sky. 
 
910
                        Something rather grubby is left behind.";
 
911
                    yomin_spell:
 
912
                       "For a moment you think there is nothing there, as you
 
913
                        chew absentmindedly on a leaf.  But somewhere inside
 
914
                        the tortoise is a sense of wonder at the amazing blue
 
915
                        canopy of the sky.";
 
916
                }
 
917
          Take, Remove:
 
918
               "Your parents always warned you not to pick up casual
 
919
                acquaintances met on the road.";
 
920
       ],
 
921
       daemon
 
922
       [ i; if (location ~= Up_Road or Track || random(6)~=1) rfalse;
 
923
          if (random(4)==1 && self hasnt general)
 
924
          {   move feather to location; give self general;
 
925
              "^A tortoise-feather flutters to the ground before you!";
 
926
          }
 
927
          i=random(3);
 
928
          switch(i)
 
929
          {   1: print "^High in the sky,";
 
930
              2: print "^Far above you,";
 
931
              3: print "^Tiny in the blue sky,";
 
932
          }
 
933
          " a tortoise flaps across the sun.";
 
934
       ],
 
935
  has  animate;
 
936
 
 
937
Scroll torn_scroll "torn scroll"
 
938
  with name "torn";
 
939
 
 
940
Spell -> lobal_spell
 
941
  with name "lobal",
 
942
       purpose "sharpen hearing",
 
943
       magic
 
944
       [;  if (second==0 || second hasnt animate)
 
945
               "There is a loud bang in your ear, but no other effect.";
 
946
           if (second==player)
 
947
           {   if (hearing_good) "There is no further effect.";
 
948
               hearing_good=1; StartTimer(self, 5);
 
949
               "Nothing happens, possibly because those butterflies on the
 
950
                other side of the hill keep distracting you.";
 
951
           }
 
952
           print_ret (The) second,
 
953
              " is no doubt grateful for the gift of sharper hearing.";
 
954
       ],
 
955
       unmagic
 
956
       [;  if (second==0 || second hasnt animate)
 
957
               "There is a brief silence, but no other effect.";
 
958
           if (second==player) { StopTimer(self); hearing_good=0; "Pardon?"; }
 
959
           print_ret (The) second,
 
960
              " is no doubt grateful not to have to listen to you.";
 
961
       ],
 
962
       time_left 0,
 
963
       time_out
 
964
       [;  if (hearing_good)
 
965
           {   hearing_good = false;
 
966
               "^Those wretched butterflies finally shut up.";
 
967
           }
 
968
       ];
 
969
 
 
970
Scroll chewed_scroll "chewed scroll"
 
971
  with initial "It looks as if the tortoise was eating something - once
 
972
                it might have been a scroll, but now it lies there,
 
973
                chewed up like a lettuce leaf.",
 
974
       before
 
975
       [;  Cast: if (the_spell_was == caskly_spell)
 
976
                 {   move torn_scroll to parent(self);
 
977
                     remove self; score=score+5;
 
978
                     "Before your eyes, the scroll begins to repair itself,
 
979
                      failing only at the very last tear.  Not quite perfect
 
980
                      perhaps, but certainly a readable, if torn scroll.";
 
981
                 }
 
982
           Eat:  "~Eating your words~ is notoriously dangerous for a wizard.
 
983
                  Rearranged in the stomach, a spell might do anything!";
 
984
       ],
 
985
  with name "chewed";
 
986
 
 
987
Object feather "tortoise feather"
 
988
  with name "tortoise" "feather",
 
989
       description
 
990
          "Possibly your rarest, and also least valuable, possession.";
 
991
        
 
992
! ----------------------------------------------------------------------------
 
993
!   The cave mouth and the perfect sapphire
 
994
! ----------------------------------------------------------------------------
 
995
 
 
996
Place Cave_Mouth "Cave Mouth"
 
997
  with name "gorse" "footpath" "cave" "mouth",
 
998
       description
 
999
          "This is a cave mouth, at one end of a road which winds southeast
 
1000
           over rising ground.  The entrance west to the caves is a dark
 
1001
           tunnel, and only a footpath runs further north, into gorse.",
 
1002
       u_to Up_Road, se_to Up_Road, in_to Iron_Door, w_to Iron_Door,
 
1003
       n_to Footpath;
 
1004
 
 
1005
Object -> Iron_Door "iron door"
 
1006
  with name "iron" "door" "heavy",
 
1007
       description "It just looks like an ordinary heavy iron door.",
 
1008
       door_dir
 
1009
       [; if (location==Cave_Mouth) return w_to; return e_to;
 
1010
       ],
 
1011
       door_to
 
1012
       [; if (location==Cave_Mouth) return In_Cave;
 
1013
          return Cave_Mouth;
 
1014
       ],
 
1015
       describe
 
1016
       [; if (self has open) "^The iron door stands open.";
 
1017
          if (self hasnt locked) "^The iron door is unlocked but shut.";
 
1018
          "A heavy iron door bars the cave mouth.";
 
1019
       ],
 
1020
       found_in  In_Cave  Cave_Mouth
 
1021
  has  static door openable locked lockable;
 
1022
 
 
1023
!  Cf. T. S. Eliot, "Burnt Norton" II:
 
1024
!  (but see also Mallarme's sonnet from which Eliot borrowed the image)
 
1025
 
 
1026
Object -> sapphire "perfect sapphire"
 
1027
  with name "perfect" "sapphire" "gemstone" "gem",
 
1028
       initial "Clotted in the mud beside the door is a perfect sapphire.",
 
1029
       before
 
1030
       [;  Examine: remove self; move caskly_spell to memory;
 
1031
                    players_book.learn_spell(caskly_spell);
 
1032
                    caskly_spell.number=100;
 
1033
                    "As you gaze into the perfect blue of the sapphire,
 
1034
                     you feel your mind begin to reel.  Unable to bear
 
1035
                     the naked sight of perfection, you look away, ashamed. 
 
1036
                     As you do so, the sapphire cracks and wastes away to
 
1037
                     thin hot dust.  But something remains, something in your
 
1038
                     mind...";
 
1039
       ];
 
1040
 
 
1041
Spell caskly_spell
 
1042
  with name "caskly",
 
1043
       purpose "cause perfection",
 
1044
       magic
 
1045
       [;  if (second==0) "Trying to make everything perfect was a little
 
1046
                           too ambitious.";
 
1047
           if (second==player) "Oh, don't be too hard on yourself.";
 
1048
           if (second==helistars_book)
 
1049
               "Your spell is not powerful enough to restore the lost pages.";
 
1050
           print_ret (The) second, " looks pretty perfect as is.";
 
1051
       ];
 
1052
 
 
1053
! ----------------------------------------------------------------------------
 
1054
!   Inside the Cave, the powerful urbzig spell and its consequences
 
1055
! ----------------------------------------------------------------------------
 
1056
 
 
1057
Place In_Cave "Inside Cave"
 
1058
  with description
 
1059
          "A wide but shallow cave not far inside the hill.  There is no
 
1060
           obvious exit, except for the way you came in.",
 
1061
       out_to
 
1062
       [;  if (CoinsIn(left_pan)+CoinsIn(right_pan) < 6)
 
1063
               "Something bars your way, and you hear
 
1064
                the scales jangling militantly.  You were trying to
 
1065
                steal its coins!";
 
1066
           if (scales.number~=0) "Something bars your way, and you hear
 
1067
               the scales jangle slightly with energy.";
 
1068
           return Iron_Door;
 
1069
       ],
 
1070
       e_to
 
1071
       [;  return self.out_to();
 
1072
       ],
 
1073
       cant_go "The only way is back ~out~ through the iron door.",
 
1074
       after
 
1075
       [;  Take: if (parent(noun)==left_pan or right_pan)
 
1076
                     print_ret "Taken from ", (the) parent(noun), ".";
 
1077
       ],
 
1078
  has  ~light;
 
1079
 
 
1080
FeaturelessCube -> cave_cube "cube"
 
1081
  with initial "Balanced on a rock formation is a featureless white cube.";
 
1082
 
 
1083
Object -> scales "pair of scales"
 
1084
  with name "pair" "of" "scales" "pans", number 0,
 
1085
       describe
 
1086
       [;  print "^A fair-sized pair of scales hangs from a bracket in the
 
1087
                  cave wall.  ";
 
1088
           if (self.number==0)  "The scales are balanced.";
 
1089
           if (self.number==1)  "The left-hand side is higher.";
 
1090
           "The right-hand side is higher.";
 
1091
       ],
 
1092
       before
 
1093
       [;  "There are left and right hand pans, which you should refer to
 
1094
            individually.";
 
1095
       ],
 
1096
  has  static supporter;
 
1097
 
 
1098
Class  ScalePan
 
1099
  with name "pan" "side" "tray",
 
1100
       before
 
1101
       [;  Receive:
 
1102
           if (noun ofclass Scroll or Coin) rfalse;
 
1103
           if (noun==feather) rfalse;
 
1104
           "The pans gleam with what almost seems greed, and somehow they
 
1105
            contrive to nudge your hand past them with your worthless and
 
1106
            boring item.";
 
1107
       ],
 
1108
       after
 
1109
       [ i j d w1 w2;  Receive, LetGo: i=scales.number;
 
1110
           objectloop (j in left_pan) w1=w1 + WeightOf(j);
 
1111
           objectloop (j in right_pan) w2=w2 + WeightOf(j);
 
1112
           if (w1==w2) scales.number=0;
 
1113
           if (w1 > w2) scales.number=-1;
 
1114
           if (w1 < w2) scales.number=1;
 
1115
           j=scales.number; d=(w2-w1)*(scales.number);
 
1116
           if (j==i) rfalse;
 
1117
           if (j==0) "The scales come into balance.";
 
1118
           if (j==1) print "The left pan "; else print "The right pan ";
 
1119
           if (d==1) "very slowly rises up.";
 
1120
           "rises up.";
 
1121
       ],
 
1122
  has  supporter scenery;
 
1123
 
 
1124
[ WeightOf obj;
 
1125
  if (obj==bronze_coin) return 2;
 
1126
  if (obj ofclass Scroll || obj==feather) return 1;
 
1127
  return 3;
 
1128
];
 
1129
 
 
1130
[ CoinsIn obj i c;
 
1131
  objectloop (i in obj) if (i ofclass Coin) c++;
 
1132
  return c;
 
1133
];
 
1134
 
 
1135
ScalePan -> right_pan "right pan" with name "right";
 
1136
GoldCoin -> ->;
 
1137
GoldCoin -> ->;
 
1138
GoldCoin -> ->;
 
1139
 
 
1140
ScalePan -> left_pan "left pan" with name "left";
 
1141
BronzeCoin -> -> bronze_coin;
 
1142
GoldCoin -> ->;
 
1143
GoldCoin -> ->;
 
1144
 
 
1145
Scroll -> -> crumpled_scroll "crumpled scroll"
 
1146
  with name "crumpled";
 
1147
Spell  -> -> -> urbzig_spell
 
1148
  with name "urbzig",
 
1149
       purpose "turn a dangerous object into a harmless one",
 
1150
       magic
 
1151
       [;  if (second==0) "The spell fizzles away.";
 
1152
           if (second==player) "It's a matter of opinion, isn't it?";
 
1153
           if (second==helistars_book or mace || second ofclass FeaturelessCube)
 
1154
           {   CDefArt(second); remove second;
 
1155
               if (second==mace && cyclops in location)
 
1156
               {   remove cyclops; move eye_cube to location;
 
1157
                   " turns into a featureless white cube just as the cyclops
 
1158
                    was about to hit you with it.  Mightily embarrassed
 
1159
                    by this, he drops the cube and runs off!";
 
1160
               }
 
1161
               print " turns into a moth and flutters away.^";
 
1162
               rtrue;
 
1163
           }
 
1164
           print_ret "Nothing obvious happens.  Perhaps ", (the) second,
 
1165
                     " isn't so very dangerous after all.";
 
1166
       ],
 
1167
       unmagic
 
1168
       [;  if (second==0) "The spell fizzles away.";
 
1169
           if (second==player) "It's a matter of opinion, isn't it?";
 
1170
           if (second has static || second has scenery)
 
1171
           {   print_ret "Your spell is too weak for something quite as
 
1172
                          monumentally harmless as ", (the) second, ".";
 
1173
           }
 
1174
           if (second==helistars_book or snake or cyclops or mace
 
1175
               || second ofclass FeaturelessCube)
 
1176
               "Nothing obvious happens.";
 
1177
           if (second in player)
 
1178
           {   remove second; deadflag = true;
 
1179
               "Suddenly, a tarantula races up your arm to your throat! 
 
1180
                Perhaps it was unwise to gizbru something you were
 
1181
                actually holding.";
 
1182
           }
 
1183
           if (cyclops has general)
 
1184
               "Nothing happens.  Perhaps that's just as well,
 
1185
                after the last time.";
 
1186
           move cyclops to location;
 
1187
           remove second; give cyclops general; StartTimer(cyclops, 5);
 
1188
           print_ret (The) second, " is replaced by a buck-toothed cyclops
 
1189
                wielding a mace!";
 
1190
       ];
 
1191
 
 
1192
Object cyclops "buck-toothed cyclops"
 
1193
  with name "buck" "toothed" "buck-toothed" "cyclops",
 
1194
       initial "A huge buck-toothed cyclops menaces you, armed with a
 
1195
                heavy mace!",
 
1196
       before
 
1197
       [;  Cast: if (the_spell_was == bozbar_spell)
 
1198
                     "Does the term ~death wish~ mean anything to you?";
 
1199
                 if (the_spell_was == urbzig_spell)
 
1200
                     "The cyclops bellows with glee as your spell has
 
1201
                      no effect.  (After all, he wouldn't be ~dangerous~ if
 
1202
                      an urbzig spell worked on him, would he?)";
 
1203
       ],
 
1204
       life [; "He roars incoherently, swinging the mace!"; ],
 
1205
       time_left 0,
 
1206
       time_out
 
1207
       [;  if (self notin location)
 
1208
           {   remove self; rtrue;
 
1209
           }
 
1210
           deadflag = true; remove mace; remove cyclops;
 
1211
           "Feeling that he's given you quite long enough to explain why
 
1212
            you made such a mess of his life, he swings the great mace
 
1213
            maniacally down on you!";
 
1214
       ],
 
1215
       each_turn
 
1216
       [ i; i=random(4); if (i==1) "^The cyclops leaps and bellows!";
 
1217
            if (i==2)
 
1218
              "^Whirling the mace, the cyclops jabbers at you incoherently.";
 
1219
            if (i==3)
 
1220
              "^The cyclops is losing patience (the appropriate cyclops
 
1221
                word is untranslatable into English, but approximately means
 
1222
                ~forbearance in not smashing all nearby skulls~).";
 
1223
            "^The cyclops jabs you with the mace, almost breaking your rib.";
 
1224
       ],
 
1225
  has  animate transparent;
 
1226
 
 
1227
Object -> mace "mace"
 
1228
  with name "heavy" "mace" "axe",
 
1229
       description "It looks much too heavy for you to even lift.";
 
1230
 
 
1231
FeaturelessCube -> eye_cube "cube"
 
1232
  with initial
 
1233
         "A featureless white cube lies where the cyclops dropped it.";
 
1234
 
 
1235
! ----------------------------------------------------------------------------
 
1236
!   The Footpath and the carpet
 
1237
! ----------------------------------------------------------------------------
 
1238
 
 
1239
Place Footpath "Gorse Bushes"
 
1240
  with description
 
1241
           "The footpath from the cave mouth runs into dense, impenetrable
 
1242
            gorse bushes.  Perhaps it wasn't so much a footpath as a rill
 
1243
            in the earth where roots wouldn't take; anyway, there's no way
 
1244
            but back south.",
 
1245
       s_to Cave_Mouth;
 
1246
 
 
1247
Object -> carpet "beautiful red carpet"
 
1248
  with name "beautiful" "magic" "red" "carpet",
 
1249
       initial
 
1250
          "Slung over one of the gorse bushes is a beautiful red carpet.",
 
1251
       description
 
1252
          "This is a carpet of unusual design. It is red, beautifully woven
 
1253
           and bears a pattern of cubes.",
 
1254
       before
 
1255
       [ i;  Receive:
 
1256
                 if (self notin location || self hasnt moved)
 
1257
                     "Not until the carpet's on the ground, you can't.";
 
1258
           Ride: <<Enter self>>;
 
1259
           Enter:
 
1260
                 if (self notin location || self hasnt moved)
 
1261
                     "Not until the carpet's on the ground, you can't.";
 
1262
                 if (location==Balance_Room)
 
1263
                     "Mysteriously, the carpet rucks and pulls until you're
 
1264
                      thrown off.  It settles back on the white floor with a
 
1265
                      contented sigh.";
 
1266
                 if (location==In_Cave)
 
1267
                     "The carpet rises suddenly, crashing into the roof of
 
1268
                      the cave and throwing you back off again.  Painfully.";
 
1269
                 if (location==Bazaar) i=Up_Road; else i=Bazaar;
 
1270
                 print "The carpet rises suddenly into the fluffy white
 
1271
                        clouds, and after a headlong journey deposits you...^";
 
1272
                 move self to i;
 
1273
                 PlayerTo(i,1); move player to self; <<Look>>;
 
1274
           Take: if (player in self) "Not while you're on it!";
 
1275
                 for (i=child(self):i~=0:i=child(self))
 
1276
                 {   move i to location;
 
1277
                     print "(Dislodging ", (the) i, ")^";
 
1278
                 }
 
1279
       ],
 
1280
  has  supporter enterable;
 
1281
 
 
1282
! ----------------------------------------------------------------------------
 
1283
!   A Bazaar Lottery
 
1284
! ----------------------------------------------------------------------------
 
1285
 
 
1286
Global last_called = 1;
 
1287
Global explicit_flag = 0;
 
1288
Global tickets_taken = 0;
 
1289
 
 
1290
Class Ticket(6)
 
1291
  with number -1, name "ticket",
 
1292
       description
 
1293
       [;  if (self.number==2306) "It is labelled ~First Prize~!";
 
1294
           if (self.number==5802) "It is labelled ~Nineteenth Prize~.";
 
1295
           "~You lose,~ says the ticket, with a smily face.  ~Try again!~";
 
1296
       ],
 
1297
       short_name
 
1298
       [;  if (self.number==-1) rfalse;
 
1299
           print "lottery ticket ", self.number; rtrue;
 
1300
       ],
 
1301
       parse_name
 
1302
       [ i j w;
 
1303
           i=0;
 
1304
           if (NextWord()=='lottery') i++; else wn--;
 
1305
           if (NextWord()=='tickets')
 
1306
           {   parser_action=##PluralFound; return i+1; } else wn--;
 
1307
           if (NextWord()~='ticket') return 0;
 
1308
           i++;
 
1309
           w=TryNumber(wn);
 
1310
           if (w==-1000) { explicit_flag = false; return i; }
 
1311
           if (w==0) return 0;
 
1312
           if (self.number==-1)
 
1313
           {   objectloop(j ofclass Ticket)
 
1314
                   if (w == j.number) return 0;
 
1315
           }
 
1316
           else
 
1317
           {   if (self.number~=w) return 0;
 
1318
           }
 
1319
           i++; last_called = w; explicit_flag = true; return i;
 
1320
       ],
 
1321
       before
 
1322
       [;  Examine:
 
1323
               if (self in board)
 
1324
                  "It would be cheating to see what's written on the curled up
 
1325
                   tickets still in the board.";
 
1326
           Cast: "~Get outta here, bub!~, the barker says, disgusted.";
 
1327
       ];
 
1328
 
 
1329
Place Bazaar "Crowded Bazaar"
 
1330
  with description
 
1331
           "This is a crowded, noisy bazaar.  Directly in front of you is
 
1332
            a lottery!  But the contemptuous-looking barker is doing a
 
1333
            very poor trade: hardly anyone wants his first prize, the
 
1334
            big cuddly toy elephant, or even his nineteenth prize, a
 
1335
            featureless white cube.",
 
1336
       each_turn
 
1337
       [;   switch(random(4))
 
1338
            {   1: "^~Roll up!  Roll up!  One silver piece for three goes!~";
 
1339
                2: "^~Come on, then!  Just a silver coin gets you three!~";
 
1340
                3: "^~Think what you could win, all for one silver coin!~";
 
1341
                4: "^~This could be your lucky day!~";
 
1342
            }
 
1343
       ],
 
1344
       before
 
1345
       [;   Learn:
 
1346
                "~None of that!~ snaps the barker angrily, putting you off
 
1347
                 your study habits.  He mutters about ~Enchanter cheats~,
 
1348
                 but under the circumstances you decide to let the insult
 
1349
                 pass.";
 
1350
       ],
 
1351
       cant_go "Everywhere, the crowds of jabbering natives block your way
 
1352
           to all the good stalls.  In fact, the only one you can get at is
 
1353
           this dismal lottery.";
 
1354
 
 
1355
Object -> board "lottery board"
 
1356
  with credit 0,
 
1357
       name "board" "lottery" "holes",
 
1358
       description
 
1359
           "There are a hundred holes each way, making, um, let's see, yes,
 
1360
            ten thousand tickets in all. Still, there are nineteen prizes,
 
1361
            so your odds must be, oh, well, not too awful anyway.",
 
1362
       before
 
1363
       [ i; LetGo:
 
1364
                if (self.credit == 0)
 
1365
                   "The barker stabs you in the chest with
 
1366
                    his finger.  ~That's a silver coin to you, bub!~";
 
1367
 
 
1368
                if (explicit_flag)
 
1369
                {   objectloop (i ofclass Ticket)
 
1370
                        if (last_called == i.number)
 
1371
                            "That ticket's already taken.";
 
1372
                }
 
1373
                else
 
1374
                {   .RandomChoice;
 
1375
                    last_called = random(10000);
 
1376
                    objectloop (i ofclass Ticket)
 
1377
                        if (last_called == i.number)
 
1378
                            jump RandomChoice;
 
1379
                }
 
1380
 
 
1381
                tickets_taken++;
 
1382
                self.credit--;
 
1383
 
 
1384
                i = Ticket.create();
 
1385
                if (i == 0)
 
1386
                   "The barker looks metaphysically embarrassed. ~Um,
 
1387
                    Inform's object creation system seems not to have worked.~";
 
1388
 
 
1389
                i.number = last_called; itobj = i;
 
1390
 
 
1391
                move i to player; give i moved proper;
 
1392
                if (explicit_flag==0)
 
1393
                    print "Randomly picking from the ", 10001-tickets_taken,
 
1394
                          " numbered holes with tickets in, you ";
 
1395
                    else print "You ";
 
1396
                print_ret "take ", (the) i, " out of the board.";
 
1397
 
 
1398
            Examine: ;
 
1399
            Receive:
 
1400
                if (noun ofclass Ticket)
 
1401
                   "~No changes of mind, that's your ticket now!  Give it to
 
1402
                     me if you want to play it.~";
 
1403
                <<Push self>>;
 
1404
            default:
 
1405
                "The barker is burly, and won't let you
 
1406
                 tamper with the board.";
 
1407
       ],
 
1408
       initial
 
1409
           "Behind the barker is a huge drilled board, and inside each little
 
1410
            numbered hole is a rolled-up lottery ticket."
 
1411
  has  static container open;
 
1412
 
 
1413
Ticket -> -> ticket_in_board "rolled-up ticket from the board"
 
1414
  with article "a";
 
1415
 
 
1416
Object -> barker "barker"
 
1417
  with name "barker" "burly" "man",
 
1418
       number 0,
 
1419
       description
 
1420
           "A boxer gone to seed who failed as a magician all down the
 
1421
            coast, that'd be your guess.",
 
1422
       life
 
1423
       [;  Attack, Kiss: "No way.  He must weigh twice what you do.";
 
1424
           Ask:  switch(noun)
 
1425
                 {   'prize', 'prizes':
 
1426
                         "~Just one silver coin and a prize could be yours!~";
 
1427
                     'white', 'featureless', 'cube':
 
1428
                         "He blows the dust off it.  ~Genuine antique, that.~";
 
1429
                     'elephant', 'toy', 'cuddly':
 
1430
                         "~Good quality merchandise,~ he says, in a way that
 
1431
                          suggests he can only spell one of those three words.";
 
1432
                     'ticket', 'tickets', 'lottery':
 
1433
                         "~Three tickets for one silver coin!~";
 
1434
                     default: "~Just play the game, bub.~";
 
1435
                 }
 
1436
           Order, Answer: "The barker glowers at you.";
 
1437
           Give: if (noun ofclass Ticket)
 
1438
                 {   remove noun;
 
1439
                     if (noun.number==2306)
 
1440
                     {   move elephant to player; give elephant moved;
 
1441
                         remove pelephant;
 
1442
                         Bazaar.description =
 
1443
           "This is a crowded, noisy bazaar.  Directly in front of you is
 
1444
            the lottery!";
 
1445
                         "With very bad grace, the barker shoves the
 
1446
                          cuddly toy elephant into your arms.";
 
1447
                     }
 
1448
                     if (noun.number==5802)
 
1449
                     {   move barker_cube to player; give barker_cube moved;
 
1450
                         remove pcube;
 
1451
                         Bazaar.description =
 
1452
           "This is a crowded, noisy bazaar.  Directly in front of you is
 
1453
            the lottery!";
 
1454
                         score=score+5;
 
1455
                         "With concealed relief, the barker shoves the
 
1456
                          featureless white cube into your hands.";
 
1457
                     }
 
1458
                     "~Bad luck!  You lose!~";
 
1459
                 }
 
1460
                 if (self.number==2) "~You've had enough goes already!~ he
 
1461
                     growls.  No wonder trade is bad.";
 
1462
                 if (~~(noun ofclass Coin))
 
1463
                     "~What do you call that? One silver coin to play!~";
 
1464
                 if ((noun.&name)-->0 == 'bronze')
 
1465
                     "~Bronze!  Not a chance, sunshine.~";
 
1466
                 remove noun;
 
1467
                 board.credit = board.credit + 3;
 
1468
                 self.number++;
 
1469
                 if ((noun.&name)-->0 == 'gold')
 
1470
                     "Gleefully the barker snatches the gold coin. ~Sorry
 
1471
                      bub, no change. Business is slack today!~";
 
1472
                 "Grudgingly the barker takes the silver coin and stands
 
1473
                  back to let you at the board, arms folded.";
 
1474
       ],
 
1475
       before
 
1476
       [;  Cast: switch(the_spell_was)
 
1477
                 {   bozbar_spell:
 
1478
                        "He's not that much of an animal.";
 
1479
                     lobal_spell:
 
1480
                        "His problem is listening, not hearing.";
 
1481
                     caskly_spell:
 
1482
                        "For a moment his hair seems to comb itself. 
 
1483
                         Irritated, he ruffles it again, and the spell dies
 
1484
                         an ignominious death.";
 
1485
                     yomin_spell:
 
1486
                         if (elephant has moved || barker_cube has moved)
 
1487
                         "The barker's mind is a heap of grumbles about lost
 
1488
                          prizes and scrawny Enchanters.";
 
1489
                         if (self hasnt general)
 
1490
                         {   give self general;
 
1491
                            "~Hope that scrawny Enchanter doesn't pick 2306!~
 
1492
                             thinks the barker (slowly).";
 
1493
                         }
 
1494
                         "~If that mark does win, hope it's only worthless
 
1495
                          old 5802,~ ponders the barker.";
 
1496
                 }
 
1497
       ],
 
1498
  has  animate scenery;
 
1499
 
 
1500
Object -> prizes "prizes"
 
1501
  with name "prize" "prizes",
 
1502
       before [; "~Hands off those prizes!~"; ],
 
1503
  has  scenery;
 
1504
 
 
1505
Object -> pelephant "prize elephant"
 
1506
  with name "prize" "elephant" "cuddly" "toy",
 
1507
       description "Pink, cuddly, toy, elephant.  Says it all, really.",
 
1508
       before [; Examine: ; default: "~Hands off those prizes!~"; ],
 
1509
  has  scenery;
 
1510
       
 
1511
Object -> pcube "prize cube"
 
1512
  with name "prize" "featureless" "white" "cube",
 
1513
       description "Wouldn't you like to win it?",
 
1514
       before [; Examine: ; default: "~Hands off those prizes!~"; ],
 
1515
  has  scenery;
 
1516
 
 
1517
Object elephant "cuddly toy elephant"
 
1518
  with name "cuddly" "toy" "elephant",
 
1519
       description "Pink, cuddly, toy, elephant.  Says it all, really.",
 
1520
       before
 
1521
       [;  Cast: if (the_spell_was == bozbar_spell)
 
1522
                     "Let me get this straight.  You, the enchanter who
 
1523
                      defeated Krill, the head of the Borphee Guild
 
1524
                      himself...  are attempting to grow wings on a pink
 
1525
                      cuddly elephant?";
 
1526
                 if (the_spell_was == yomin_spell) "Woolly.";
 
1527
       ];
 
1528
 
 
1529
FeaturelessCube barker_cube "cube";
 
1530
 
 
1531
! ----------------------------------------------------------------------------
 
1532
!   The spells in Helistar's grimoire
 
1533
! ----------------------------------------------------------------------------
 
1534
 
 
1535
Spell lleps_spell
 
1536
  with name "lleps",
 
1537
       purpose "reverse effect of memorised spell",
 
1538
       magic
 
1539
       [;   if (second==0 || second notin memory)
 
1540
                "The spell backfires, painfully.";
 
1541
            if (second.number==100)
 
1542
                "You know that spell too well for your mind to be able
 
1543
                 to accept the change.";
 
1544
            if (second has reversed) give second ~reversed;
 
1545
            else give second reversed;
 
1546
            if (second==lleps_spell)
 
1547
            {    memory.forget_spell(second);
 
1548
                "Your mind wrenches as the two lleps spells
 
1549
                 cancel each other out, leaving only a sensation
 
1550
                 quite like a hangover.";
 
1551
            }
 
1552
            print_ret "Your mind wrenches as ", (the) second,
 
1553
                      " reverses itself.";
 
1554
       ],
 
1555
       unmagic
 
1556
       [;   return self.magic();         !  The reverse of "lleps" is "lleps"
 
1557
       ];
 
1558
 
 
1559
Spell mortin_spell
 
1560
  with name "mortin",
 
1561
       purpose "cause immediate death of caster",
 
1562
       magic
 
1563
       [;   deadflag = true;
 
1564
            "You really can't fault Helistar on this one.  Death is
 
1565
             absolutely immediate, like a sudden blackout curtain...";
 
1566
       ],
 
1567
       unmagic
 
1568
       [;   prepared_flag = true;
 
1569
            "Nothing quite happens... and yet you feel enormously more
 
1570
             confident as you go about this dangerous world.";
 
1571
       ];
 
1572
 
 
1573
! ----------------------------------------------------------------------------
 
1574
!   Death and the Boneyard
 
1575
! ----------------------------------------------------------------------------
 
1576
 
 
1577
[ AfterLife;
 
1578
  if (~~prepared_flag) rfalse;
 
1579
  
 
1580
  if (player in Balance_Room)
 
1581
      "^^Your foresight in preparing a resurrection was wasted.  The
 
1582
         tangled magic of the Balance Room coiled around your puny
 
1583
         enchantment like a constricting serpent.";
 
1584
 
 
1585
  prepared_flag = false; deadflag = false; hearing_good = false;
 
1586
 
 
1587
  if (memory.capacity >= 2) memory.capacity--;
 
1588
 
 
1589
  while (child(player)~=0) move child(player) to parent(player);
 
1590
  move players_book to player;
 
1591
 
 
1592
  print "^^With great foresight you prepared yourself for resurrection... 
 
1593
           Your mind feels a little weaker, but at least you're alive.^";
 
1594
  PlayerTo(Boneyard);
 
1595
];
 
1596
 
 
1597
Place Boneyard "Boneyard"
 
1598
  with name "bones" "blades" "shoulder" "skulls",
 
1599
       description
 
1600
          "This is a room of bones.  Shoulder blades make up the floor,
 
1601
           skulls the walls and leg-bones the door frames. The west exit
 
1602
           leads into darkness, but the doorway to the north opens onto a
 
1603
           seemingly normal scene.",
 
1604
       n_to
 
1605
       [;  if (scales.number ~= 0) return In_Cave;
 
1606
           return Grasslands;
 
1607
       ],
 
1608
       w_to "Some magical force blocks your way, as though that doorway
 
1609
             led into adventures from your past which you cannot rejoin now.",
 
1610
       before
 
1611
       [;  Examine, Search:
 
1612
               if (noun==w_obj) "You can make out nothing to the west.";
 
1613
       ];
 
1614
 
 
1615
Scroll -> worthless_scroll "worthless scroll"
 
1616
  with initial "You are almost treading on a worthless scroll.",
 
1617
       name "worthless";
 
1618
 
 
1619
Spell -> -> filfre_spell
 
1620
  with name "filfre",
 
1621
       purpose "produce gratuitous fireworks",
 
1622
       magic
 
1623
       [;    if (self hasnt scored) { score++; give self scored; }
 
1624
            "A brief shower of gratuitous fireworks spells out:
 
1625
           ^^The masterly Enchanter trilogy was written by Marc Blank,
 
1626
             Dave Lebling and Steve Meretzky.";
 
1627
       ],
 
1628
       unmagic
 
1629
       [;   "A lengthy shower of artistically justified fireworks spells out:
 
1630
           ^^The masterly Enchanter trilogy was written by Jane Austen,
 
1631
             Emily Bronte and Edgar Allen Poe.";
 
1632
       ];
 
1633
 
 
1634
! ----------------------------------------------------------------------------
 
1635
!   The Cubical Temple
 
1636
! ----------------------------------------------------------------------------
 
1637
 
 
1638
Place Track "Track, outside Temple"
 
1639
  with description
 
1640
          "This is the end of a long track winding through desolate hills,
 
1641
           which runs back west up to the ridge.",
 
1642
       before
 
1643
       [;   Listen:
 
1644
                if (~~hearing_good) "The chanting is too quiet to make out.";
 
1645
                "The endlessly repeating threnody of the monks tells of
 
1646
                 the legend of one who will some day enlighten their order,
 
1647
                 and so be taken up to a higher plane.  He (or she,
 
1648
                 presumably) is known as The Four-Cubed One.";
 
1649
       ],
 
1650
       w_to Up_Road, u_to Up_Road;
 
1651
 
 
1652
Object -> Temple "cubical Temple"
 
1653
  with name "temple" "cubical" "cube" "enormous",
 
1654
       before
 
1655
       [ i j;
 
1656
         Enter: "The Temple is featureless and unbroken.  Perhaps the top
 
1657
                 is open, because the sound must come from somewhere...
 
1658
                 but you wouldn't bet on it.";
 
1659
         Cast:   switch(the_spell_was)
 
1660
                 {   rezrov_spell:
 
1661
                        "The huge temple remains impassive at your relatively
 
1662
                         puny enchantment.";
 
1663
                     frotz_spell:
 
1664
                         objectloop (i in player)
 
1665
                             if (i ofclass FeaturelessCube) j++;
 
1666
                         if (j==0)
 
1667
                             "The temple shakes, but then is still again.";
 
1668
                         if (j<4) "The temple shakes!  White light plays
 
1669
                             over your hands and possessions, but then all is
 
1670
                             still again.";
 
1671
                         print "The temple shakes and white light bathes you. 
 
1672
                             Smoothly it unfolds itself in a four-dimensional
 
1673
                             way your senses can barely comprehend.  All you
 
1674
                             know is that when it is over,
 
1675
                             you find yourself in...^";
 
1676
                         hearing_good = false; score=score+5;
 
1677
                         PlayerTo(Balance_Room); rtrue;
 
1678
                 }
 
1679
       ],
 
1680
       describe
 
1681
       [;   print "^You stand outside an enormous temple in the shape of a
 
1682
                   perfect, featureless white cube, four hundred feet on a
 
1683
                   side.  From somewhere within you hear the ";
 
1684
            if (hearing_good) print "bellowing noise";
 
1685
            else print "tiny sound";
 
1686
            " of the monks chanting.";
 
1687
       ],
 
1688
       description
 
1689
           "It's much like every other gigantic temple in the shape of a
 
1690
            featureless white cube you've ever seen.  No obvious way in.",
 
1691
  has  static;
 
1692
 
 
1693
! ----------------------------------------------------------------------------
 
1694
!   Inside the Temple
 
1695
! ----------------------------------------------------------------------------
 
1696
 
 
1697
Place Balance_Room "Balance Room"
 
1698
  with description
 
1699
           "This seems to be the inside of a featureless white cube, forty
 
1700
            feet on a side.  The air is stale and there is no exit.";
 
1701
 
 
1702
Object -> balance_meter "image of the scales"
 
1703
  with name "image" "scales" "of" "pair", article "the",
 
1704
       initial "The image of a pair of scales hangs high in the air.  One
 
1705
                pan is much lower than the other.",
 
1706
       before
 
1707
       [; "It's only an image.";
 
1708
       ],
 
1709
  has  static;
 
1710
 
 
1711
Object -> dusty_podium "dusty podium"
 
1712
  with name "podium" "dusty" "cobwebs" "cobwebbed",
 
1713
       initial "Far below the scales, in the centre of the ~floor~, is a
 
1714
                predictably-shaped podium, but it is so dusty and
 
1715
                cobwebbed that you can't see what it once was.",
 
1716
       before
 
1717
       [;  Cast: if (the_spell_was == caskly_spell)
 
1718
                    "Nice try, but it is protected from enchantment.";
 
1719
                "However dusty it is, the podium is still protected from
 
1720
                 casual enchantment.";
 
1721
           Rub:  remove self; move balance_key to Balance_Room;
 
1722
                 itobj = balance_key;
 
1723
                "No substitute for old-fashioned hard work, sometimes,
 
1724
                 and after much patient (sneezy) scrubbing, the podium
 
1725
                 appears in its true white glory.  Set into it are four
 
1726
                 sockets, arranged in a two by two square.";
 
1727
       ],
 
1728
  has  static;
 
1729
 
 
1730
Object balance_key "podium"
 
1731
  with name "podium" "pedestal" "platform" "cubical",
 
1732
       description "As predicted, it is cubical.",
 
1733
       initial "Far below the scales, in the centre of the ~floor~, is a
 
1734
                predictably-shaped podium.  Set into it are four sockets,
 
1735
                arranged in a two by two square.",
 
1736
  has  static supporter;
 
1737
 
 
1738
Object -> sockets "two by two square"
 
1739
  with name "square" "two" "by" "two",
 
1740
       before
 
1741
       [ i;  if (action~=##Examine || number_filled==0)
 
1742
              "You'll have to say which socket you mean. 
 
1743
               (Let's call them ~top left~, ~bottom right~ and so on.)";
 
1744
           objectloop (i in self)
 
1745
           {   print (The) i;
 
1746
               if (child(i)==0) print " is empty.^";
 
1747
               else { print " contains ", (a) child(i), ".^"; }
 
1748
           }
 
1749
           rtrue;
 
1750
       ],
 
1751
  has  static;
 
1752
 
 
1753
Class Socket
 
1754
  with name "socket", article "the",
 
1755
       before
 
1756
       [;  Cast:  "The sockets are proof against magic.";
 
1757
           Examine: print (The) self, ", cubical and slightly more
 
1758
                    than four inches on a side, is decorated with ",
 
1759
                    (string) self.description;
 
1760
                    if (child(self) == nothing) ".";
 
1761
                    print_ret ", and contains ", (a) child(self), ".";
 
1762
           Receive: if (~~(noun ofclass FeaturelessCube))
 
1763
                       "The socket rejects that.";
 
1764
                    if (child(self) ~= nothing)
 
1765
                       "There is already a cube in that socket.";
 
1766
       ],
 
1767
       after
 
1768
       [;  LetGo:  number_filled--;
 
1769
                   "With much struggle, you manage to pull the cube away.";
 
1770
           Receive: number_filled++;
 
1771
           if (number_filled==4)
 
1772
           {   if (snakes_cube in bl_socket
 
1773
                   && barker_cube in ul_socket
 
1774
                   && cave_cube in br_socket
 
1775
                   && eye_cube in ur_socket)
 
1776
               {   deadflag=2; score=score+5;
 
1777
                  "As you place the final cube into the sockets, you feel
 
1778
                   imbued with celestial wisdom (more so than usually). 
 
1779
                   You find yourself growing to the height of the cube, so
 
1780
                   that you pull the balances back level by hand, and then
 
1781
                   you grow still further, out of the temple until it is but
 
1782
                   a cube in your hand, and you are a giant towering over
 
1783
                   the land.
 
1784
                 ^^Then, of course, you wake up, glumly realising it's time
 
1785
                   to go to your job at the new Borphee Laboratories and
 
1786
                   all those Wheatstone bridge experiments.  But at least
 
1787
                   you can dream about the old days.";
 
1788
               }
 
1789
              "The sockets are all full now, but that doesn't mean
 
1790
               anything's happened.";
 
1791
           }
 
1792
          "The cube is a predictably perfect fit in the socket.";
 
1793
       ],
 
1794
  has  static container open;
 
1795
 
 
1796
Socket -> bl_socket "bottom left socket"
 
1797
  with name "bottom" "left" "serpent",
 
1798
       description "a serpent";
 
1799
 
 
1800
Socket -> ul_socket "top left socket"
 
1801
  with name "top" "left" "bazaar",
 
1802
       description "a scene in a bazaar";
 
1803
 
 
1804
Socket -> br_socket "bottom right socket"
 
1805
  with name "bottom" "right" "cave",
 
1806
       description "an engraving of a rocky cave";
 
1807
 
 
1808
Socket -> ur_socket "top right socket"
 
1809
  with name "top" "right" "eye",
 
1810
       description "an eye";
 
1811
 
 
1812
! ----------------------------------------------------------------------------
 
1813
!   That's all of the object definitions: just a little code and grammar left
 
1814
! ----------------------------------------------------------------------------
 
1815
 
 
1816
[ Initialise;
 
1817
 
 
1818
  location = Hut;
 
1819
  move burin to player;
 
1820
  move players_coin to player;
 
1821
  move players_book to player;
 
1822
 
 
1823
  thedark.description =
 
1824
      "It is pitch black.  You are likely to be eaten by a grue.";
 
1825
  ! (In fact you are stone-cold certain not to be, but never mind.)
 
1826
 
 
1827
  players_book.learn_spell(gnusto_spell);
 
1828
  players_book.learn_spell(frotz_spell);
 
1829
  players_book.learn_spell(yomin_spell);
 
1830
  players_book.learn_spell(rezrov_spell);
 
1831
 
 
1832
  helistars_book.learn_spell(frotz_spell);
 
1833
  helistars_book.learn_spell(lleps_spell);
 
1834
  helistars_book.learn_spell(mortin_spell);
 
1835
 
 
1836
  give gnusto_spell known_about;
 
1837
 
 
1838
 "^^^^^[Welcome to a short story called ~Balances~, one of the example
 
1839
       games for the Inform design system. Some people may recognise the
 
1840
       setting, but others might like to type ~how do spells work~ -
 
1841
       the game responds to a few such questions.]
 
1842
     ^^You feel a little confused as to how you got here.  Something
 
1843
       to do with Helistar!  That's right, and how the world is so far
 
1844
       off balance nowadays, after the Great Change.^^";
 
1845
];
 
1846
 
 
1847
[ PrintRank;
 
1848
  print ", earning you the rank of ";
 
1849
  if (score >= 50)  "Scientist.";
 
1850
  if (score >= 40)  "Spellbreaker.";
 
1851
  if (score >= 30)  "Sorcerer.";
 
1852
  if (score >= 20)  "Enchanter.";
 
1853
  if (score >= 10)  "novice Enchanter.";
 
1854
  "lost dreamer.";
 
1855
];
 
1856
 
 
1857
[ DiagnoseSub;
 
1858
  switch(memory.capacity)
 
1859
  {   5: "You feel fine, and your memory is unimpaired.";
 
1860
      4: "You feel shaky after your brush with death, but your mental
 
1861
          faculties seem sound.";
 
1862
      3: "For someone who has died twice, you're in reasonable shape.";
 
1863
  }
 
1864
  "How many times have you died now?  Your memory isn't what it was.";
 
1865
];
 
1866
 
 
1867
! ----------------------------------------------------------------------------
 
1868
!   Grammar extensions needed by the spell-casting and cube-writing rules:
 
1869
! ----------------------------------------------------------------------------
 
1870
 
 
1871
Include "Grammar";
 
1872
 
 
1873
[ AnyWord; from_char=0; to_char=0; the_named_word=wn++; return burin; ];
 
1874
 
 
1875
[ QuotedText i j f;
 
1876
   i = WordAddress(wn++); i=i-buffer;
 
1877
   if (buffer->i=='"')
 
1878
   {   for (j=i+1:j<=(buffer->1)+1:j++)
 
1879
           if (buffer->j=='"') f=j;
 
1880
       if (f==0) return -1;
 
1881
       from_char = i+1; to_char=f-1;
 
1882
       if (from_char>to_char) return -1;
 
1883
       while (buffer+f > WordAddress(wn)) wn++; wn++;
 
1884
       return burin;
 
1885
   }
 
1886
   return -1;
 
1887
];
 
1888
 
 
1889
Verb "write" "scribe"
 
1890
                * AnyWord "on" held              -> WriteOn
 
1891
                * QuotedText "on" held           -> WriteOn;
 
1892
Verb "copy"     * scope=CopyableSpell "to" noun  -> CopyTo;
 
1893
Verb "who" "what" "how"
 
1894
                * "do"  scope=Topic              -> Query
 
1895
                * "is"  scope=Topic              -> Query
 
1896
                * "was" scope=Topic              -> Query;
 
1897
Verb "spells" "memory"
 
1898
                *                                -> Spells;
 
1899
Verb "learn" "memorise" "memorize"
 
1900
                * scope=ReadableSpell            -> Learn;
 
1901
Extend "examine" first
 
1902
                * scope=ReadableSpell            -> Examine;
 
1903
Verb "c,cast"
 
1904
                *                                -> CastOne
 
1905
                * noun                           -> CastOne;
 
1906
Verb "cast"
 
1907
                * is_spell                       -> Cast
 
1908
                * is_spell "at" noun             -> Cast
 
1909
                * is_spell "on" noun             -> Cast;
 
1910
Verb "diagnose" "health"
 
1911
                *                                -> Diagnose;
 
1912
 
 
1913
! ----------------------------------------------------------------------------
 
1914
!   And one for the game itself.
 
1915
! ----------------------------------------------------------------------------
 
1916
 
 
1917
Verb "ride" "mount" "straddle"
 
1918
                * creature                       -> Ride
 
1919
                * noun                           -> Enter;
 
1920
Verb "flip" "toss" * is_coin                     -> TossCoin;
 
1921
! ----------------------------------------------------------------------------