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

« back to all changes in this revision

Viewing changes to 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
 
! ----------------------------------------------------------------------------