1
! ----------------------------------------------------------------------------
2
! Balances 961216 One of the standard Inform 6 example games
7
! translated to Inform 6: 8.5.96
8
! minor bugs fixed: 16.12.96
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.
15
! Needs Inform 6, library 6/1 or later to compile.
16
! ----------------------------------------------------------------------------
22
Constant Story "BALANCES";
23
Constant Headline "^An Interactive Short Story
24
^Copyright (c) 1994, 1995, 1996 by Graham Nelson.^";
26
Constant OBJECT_SCORE 5;
27
Constant MAX_SCORE 51;
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
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
! ----------------------------------------------------------------------------
42
Array cube_text_buffer -> 8;
43
Global the_named_word = 0;
44
Global from_char; Global to_char;
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.",
51
if (parser_action==##TheSame)
53
if ((parser_one.&number)->i
54
~= (parser_two.&number)->i) return -2;
58
{ j=NextWord(); flag=0;
59
if (j=='cube' or 'white' ||
60
(j=='featureless' or 'blank' &&
61
((self.&number)->0) == 0)) flag=1;
63
{ flag=1; parser_action=##PluralFound; }
64
if (flag==0 && ((self.&number)->0) ~= 0)
66
if (TextReader(0)==0) return i;
68
if ((self.&number)->j ~= cube_text_buffer->j)
72
if (flag==0) return i;
77
[ i; if (((self.&number)->0) == 0) print "featureless white cube";
80
while (((self.&number)->i) ~= 0)
81
print (char) (self.&number)->i++;
87
[; self.short_name(); print "s";
90
[ i; wn = the_named_word;
91
if (TextReader(1)==0) return i;
93
(self.&number)->i = cube_text_buffer->i;
95
print_ret "It is now called ", (the) self, ".";
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
102
[ TextReader flag point i j len;
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++;
109
for (:j<8:j++) cube_text_buffer->j = 0;
110
from_char=0; to_char=0;
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);
118
for (i=0:i<len && i<7:i++) cube_text_buffer->i = point->i;
123
Object burin "magic burin"
124
with name "magic" "magical" "burin" "pen",
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.",
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.";
140
if (second ofclass SpellBook)
141
"If a burin could write in a spell book, you wouldn't need
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.";
148
[ WriteOnSub; "Graffiti is banned."; ];
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
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.";
161
! ----------------------------------------------------------------------------
162
! Now the whole spell-casting system
163
! ----------------------------------------------------------------------------
165
Attribute known_about; ! Player has seen this spell somewhere
166
Attribute reversed; ! Effect of this known spell reversed
170
with name "spell" "spells", article "the",
173
[; print (address) (self.&name)-->0;
176
[; self.word_name(); print " spell"; give self known_about; rtrue;
179
[; self.short_name();
180
print ": ", (string) self.purpose;
183
[; Examine: self.specification(); ".";
192
objectloop (i in self) if (i.number==100) j++;
195
objectloop (i in self)
197
{ k++; i.word_name();
198
if (k==j-1) print " and ";
199
if (k<j-1) print ", ";
201
if (j==1) print " spell is"; else print " spells are";
202
print " yours forever. Other than that, y";
207
objectloop (i in self) if (i.number<100) j++;
210
objectloop (i in self)
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 ", ";
222
else print "no spells";
227
if (sp.number==100) "You always know that spell.";
228
print "Using your best study habits, you commit the ";
230
print " spell to memory";
231
if (sp notin self) sp.number=0;
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
247
if (sp notin self || sp.number==100) rtrue;
250
if (sp.number==0) remove sp;
254
Spell -> gnusto_spell
256
purpose "copy a scroll into your spell 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;
271
"Your spell fails, as you have no spell book.";
273
if (i==0 || ~~(i ofclass Spell))
274
{ print_ret "Your spell fails, as ", (the) second,
277
a_book.learn_spell(i); remove second;
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.";
288
with array_of_spells 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0,
292
p = self.&array_of_spells;
293
for (i=0:i<self.capacity && (p-->i)~=0:i++) ;
294
if (i==self.capacity) rtrue;
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.";
305
print_ret "When you are done, ", (the) self, " remains unmarred.";
309
p = self.&array_of_spells;
310
for (i=0:i<self.capacity && (p-->i)~=0:i++)
311
{ j=p-->i; <Examine j>;
319
if (self has general)
320
{ if (child(self)~=0 && child(self) ofclass Spell)
321
j=(child(self).&name)-->0; else j='illegible';
325
if (k=='scrolls') parser_action=##PluralFound;
326
if ((k=='scrolls' or 'scroll' or j) || k==(self.&name)-->0)
335
if (i==0 || ~~(i ofclass Spell))
336
"The scroll has faded, and you cannot read it.";
337
print "The scroll reads ~"; i.specification(); "~.";
340
[; if (inventory_stage==2 && self has general)
341
{ if (child(self)==0 || ~~(child(self) ofclass Spell))
342
print " (which is illegible)";
344
{ print " (of ", (the) child(self), ")"; }
348
[ ReadableSpell i j k;
350
{ if (action_to_be==##Examine) rfalse;
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);
362
! No need for scope_stage 3 (the error stage), because our
363
! ParserError routine handles that case instead
366
[ CopyableSpell i j k;
367
if (scope_stage==1) return 1;
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);
377
! No need for scope_stage 3 (the error stage), because our
378
! ParserError routine handles that case instead
381
[ SpellsSub; memory.describe_contents(); ];
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);
389
Global the_spell_was = gnusto_spell;
391
[ CastOneSub; <Cast the_spell_was noun>; ];
394
the_spell_was = noun; memory.forget_spell(noun);
396
if (noun has reversed)
397
{ give noun ~reversed;
398
if (noun.unmagic() ~= 0) return;
403
{ ResetVagueWords(second); ! Set "it", "him", "her"
404
if (second provides before
405
&& second.before() ~= 0) return; ! Run before routine(s)
407
if (noun.magic() ~= 0) return;
412
if (verb_word=='c,cast' or 'cast')
413
objectloop (i in memory) PlaceInScope(i);
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; }
425
wn=verb_wordnum; if (vb~=0) wn++;
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;
432
"You haven't got that spell committed to memory. [Type ~spells~
433
to see what you do remember.]";
435
"Your training is such that you can only memorise such a spell
436
with the aid of a spell book containing it.";
438
"You have no text of that spell to copy.";
441
"You haven't learned that spell, if indeed it is a spell.";
443
"You haven't access to that spell, if indeed it is a spell.";
448
[ ChooseObjects obj code;
450
if (action_to_be==##WriteOn && obj in player) return 9;
454
[ UnknownVerb word i;
455
objectloop (i in memory)
456
if (word==(i.&name)-->0) { the_spell_was = i; return 'c,cast'; }
461
if (v=='c,cast') { print "cast a spell at"; rtrue; }
465
! ----------------------------------------------------------------------------
466
! And now, on with the story. First, some global variables:
467
! ----------------------------------------------------------------------------
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
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
! ----------------------------------------------------------------------------
484
if (scope_stage==1) return 0;
486
{ objectloop (i ofclass Question) PlaceInScope(i);
489
"At the moment, even the simplest questions confuse you.";
494
with name "helistar" "my" "friend" "colleague",
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.";
501
with name "magical" "magic" "burin",
502
description "A burin is an engraving and writing tool.";
504
with name "change" "great",
506
"Something you had a lot to do with, but what exactly? No, it's gone.";
510
"A one-eyed giant, usually hostile. (Don't they teach anything at
511
adventurer school these days?)";
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
521
with name "grimoire",
523
"According to Chambers English Dictionary, a grimoire is ~a magician's
524
book for calling up spirits~.";
526
with name "spells" "work",
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.]";
541
! ----------------------------------------------------------------------------
542
! Some multiple objects, coins in fact, coded in deluxe fashion:
543
! ----------------------------------------------------------------------------
548
description "A round unstamped disc, presumably part of the local
552
if (parser_action==##TheSame)
553
{ if ((parser_one.&name)-->0 == (parser_two.&name)-->0) return -1;
559
if (j=='coins') parser_action=##PluralFound;
560
else if (j~='coin' or w) return i;
568
short_name "gold coin",
573
short_name "silver coin",
574
plural "silver coins";
578
short_name "bronze coin",
579
plural "bronze coins";
581
SilverCoin players_coin;
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.";
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
592
! ----------------------------------------------------------------------------
593
! The player's spell book, and three initial spells (to go with gnusto):
594
! ----------------------------------------------------------------------------
596
SpellBook players_book "spell book"
597
with name "spell" "book" "my" "spellbook",
598
description "My Spell Book^";
602
purpose "cause an object to give off light",
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.";
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.";
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.";
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.";
631
purpose "open even locked or enchanted objects",
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)
640
print_ret (The) second, " opens obediently.
641
Like swatting a fly with a sledge hammer, if you ask me.";
643
give second open ~locked;
644
print "Silently, ", (the) second, " swings open. ";
645
if (second has container) <<Search second>>; new_line; rtrue;
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.";
659
purpose "mind probe",
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 ",
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.";
674
! ----------------------------------------------------------------------------
675
! The first scene: the Hut and its (rather easy) secret
676
! ----------------------------------------------------------------------------
681
Place Hut "Ramshackle Hut"
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";
691
Object -> furniture "wooden furniture"
692
with name "furniture" "broken" "wood" "wooden",
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.";
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;
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:^",
715
! ----------------------------------------------------------------------------
716
! Grasslands and the valley
717
! ----------------------------------------------------------------------------
719
Place Grasslands "Grasslands, near Hut"
720
with name "grasslands" "grass" "hut" "path",
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
727
cant_go "You wander around for a while but end up back at the hut.";
729
Place Valley "Pocket Valley"
730
with name "valley" "trail",
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.",
740
[ RideSub; print_ret "You can hardly ride ", (a) noun, "."; ];
742
Object -> horse "horse"
744
[; if (self has general) print "winged horse";
745
else print "chestnut horse";
749
[ i j; if (self has general) j='winged'; else j=-1;
750
while (NextWord()==j or 'horse' or 'chestnut') i++;
755
"There is ", (a) self, " here, munching on a pile of oats.";
758
[; Cast: if (the_spell_was == bozbar_spell)
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.";
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.";
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;
784
Object -> oats "pile of oats"
785
with name "oats" "pile" "of",
787
[; Examine, Search, LookUnder:
789
move shiny_scroll to player; score=score+5;
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?";
798
Scroll shiny_scroll "shiny scroll"
801
Spell -> bozbar_spell
803
purpose "cause an animal to sprout wings",
805
[; if (second==0 || second hasnt animate)
806
"The spell dies away in vain.";
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.";
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.";
821
print_ret (The) second, " has no wings to lose.";
824
! ----------------------------------------------------------------------------
825
! The Chasm and the snake
826
! ----------------------------------------------------------------------------
828
Place Edge "Edge of Chasm"
829
with name "wide" "chasm" "road" "daffodils" "clump",
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
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.",
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
844
Object -> snake "hissing snake"
845
with name "hissing" "snake",
847
"Lying in a tight coil at the edge of the chasm is a hissing snake.",
849
"It has some V-markings, some scaly parts, colours from grey to
850
reddish-brown. Is that any help?",
852
[; "The snake hisses angrily!"; ],
855
switch(the_spell_was)
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.";
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.";
870
"Horrid reptilian thoughts insinuate their way into you.";
873
"The slipperiness of its skin is only one of many reasons
874
why this is ill-advised.";
878
FeaturelessCube -> snakes_cube "cube"
880
"The snake appears to be curled around a featureless white cube.",
882
[; if (snake notin nothing) "The snake won't let you near that cube!";
885
! ----------------------------------------------------------------------------
886
! The crest of the hill; Icarus the tortoise; the chewed scroll
887
! ----------------------------------------------------------------------------
889
Place Up_Road "Crest of Hill"
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;
895
Object -> tortoise "tortoise"
896
with name "tortoise" "turtle",
897
initial "A tortoise ambles along the road, extremely slowly.",
899
[; "The tortoise (slowly) turns its neck to look at you (stupidly).";
902
[; Cast: switch(the_spell_was)
904
"Just how safe do you want your surroundings to be?";
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.";
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
918
"Your parents always warned you not to pick up casual
919
acquaintances met on the road.";
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!";
929
{ 1: print "^High in the sky,";
930
2: print "^Far above you,";
931
3: print "^Tiny in the blue sky,";
933
" a tortoise flaps across the sun.";
937
Scroll torn_scroll "torn scroll"
942
purpose "sharpen hearing",
944
[; if (second==0 || second hasnt animate)
945
"There is a loud bang in your ear, but no other effect.";
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.";
952
print_ret (The) second,
953
" is no doubt grateful for the gift of sharper hearing.";
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.";
965
{ hearing_good = false;
966
"^Those wretched butterflies finally shut up.";
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.",
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.";
982
Eat: "~Eating your words~ is notoriously dangerous for a wizard.
983
Rearranged in the stomach, a spell might do anything!";
987
Object feather "tortoise feather"
988
with name "tortoise" "feather",
990
"Possibly your rarest, and also least valuable, possession.";
992
! ----------------------------------------------------------------------------
993
! The cave mouth and the perfect sapphire
994
! ----------------------------------------------------------------------------
996
Place Cave_Mouth "Cave Mouth"
997
with name "gorse" "footpath" "cave" "mouth",
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,
1005
Object -> Iron_Door "iron door"
1006
with name "iron" "door" "heavy",
1007
description "It just looks like an ordinary heavy iron door.",
1009
[; if (location==Cave_Mouth) return w_to; return e_to;
1012
[; if (location==Cave_Mouth) return In_Cave;
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.";
1020
found_in In_Cave Cave_Mouth
1021
has static door openable locked lockable;
1023
! Cf. T. S. Eliot, "Burnt Norton" II:
1024
! (but see also Mallarme's sonnet from which Eliot borrowed the image)
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.",
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
1043
purpose "cause perfection",
1045
[; if (second==0) "Trying to make everything perfect was a little
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.";
1053
! ----------------------------------------------------------------------------
1054
! Inside the Cave, the powerful urbzig spell and its consequences
1055
! ----------------------------------------------------------------------------
1057
Place In_Cave "Inside Cave"
1059
"A wide but shallow cave not far inside the hill. There is no
1060
obvious exit, except for the way you came in.",
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
1066
if (scales.number~=0) "Something bars your way, and you hear
1067
the scales jangle slightly with energy.";
1071
[; return self.out_to();
1073
cant_go "The only way is back ~out~ through the iron door.",
1075
[; Take: if (parent(noun)==left_pan or right_pan)
1076
print_ret "Taken from ", (the) parent(noun), ".";
1080
FeaturelessCube -> cave_cube "cube"
1081
with initial "Balanced on a rock formation is a featureless white cube.";
1083
Object -> scales "pair of scales"
1084
with name "pair" "of" "scales" "pans", number 0,
1086
[; print "^A fair-sized pair of scales hangs from a bracket in the
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.";
1093
[; "There are left and right hand pans, which you should refer to
1096
has static supporter;
1099
with name "pan" "side" "tray",
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
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);
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.";
1122
has supporter scenery;
1125
if (obj==bronze_coin) return 2;
1126
if (obj ofclass Scroll || obj==feather) return 1;
1131
objectloop (i in obj) if (i ofclass Coin) c++;
1135
ScalePan -> right_pan "right pan" with name "right";
1140
ScalePan -> left_pan "left pan" with name "left";
1141
BronzeCoin -> -> bronze_coin;
1145
Scroll -> -> crumpled_scroll "crumpled scroll"
1146
with name "crumpled";
1147
Spell -> -> -> urbzig_spell
1149
purpose "turn a dangerous object into a harmless one",
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!";
1161
print " turns into a moth and flutters away.^";
1164
print_ret "Nothing obvious happens. Perhaps ", (the) second,
1165
" isn't so very dangerous after all.";
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, ".";
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
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
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
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?)";
1204
life [; "He roars incoherently, swinging the mace!"; ],
1207
[; if (self notin location)
1208
{ remove self; rtrue;
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!";
1216
[ i; i=random(4); if (i==1) "^The cyclops leaps and bellows!";
1218
"^Whirling the mace, the cyclops jabbers at you incoherently.";
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.";
1225
has animate transparent;
1227
Object -> mace "mace"
1228
with name "heavy" "mace" "axe",
1229
description "It looks much too heavy for you to even lift.";
1231
FeaturelessCube -> eye_cube "cube"
1233
"A featureless white cube lies where the cyclops dropped it.";
1235
! ----------------------------------------------------------------------------
1236
! The Footpath and the carpet
1237
! ----------------------------------------------------------------------------
1239
Place Footpath "Gorse Bushes"
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
1247
Object -> carpet "beautiful red carpet"
1248
with name "beautiful" "magic" "red" "carpet",
1250
"Slung over one of the gorse bushes is a beautiful red carpet.",
1252
"This is a carpet of unusual design. It is red, beautifully woven
1253
and bears a pattern of cubes.",
1256
if (self notin location || self hasnt moved)
1257
"Not until the carpet's on the ground, you can't.";
1258
Ride: <<Enter self>>;
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
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...^";
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, ")^";
1280
has supporter enterable;
1282
! ----------------------------------------------------------------------------
1284
! ----------------------------------------------------------------------------
1286
Global last_called = 1;
1287
Global explicit_flag = 0;
1288
Global tickets_taken = 0;
1291
with number -1, name "ticket",
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!~";
1298
[; if (self.number==-1) rfalse;
1299
print "lottery ticket ", self.number; rtrue;
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;
1310
if (w==-1000) { explicit_flag = false; return i; }
1312
if (self.number==-1)
1313
{ objectloop(j ofclass Ticket)
1314
if (w == j.number) return 0;
1317
{ if (self.number~=w) return 0;
1319
i++; last_called = w; explicit_flag = true; return i;
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.";
1329
Place Bazaar "Crowded Bazaar"
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.",
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!~";
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
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.";
1355
Object -> board "lottery board"
1357
name "board" "lottery" "holes",
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.",
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!~";
1369
{ objectloop (i ofclass Ticket)
1370
if (last_called == i.number)
1371
"That ticket's already taken.";
1375
last_called = random(10000);
1376
objectloop (i ofclass Ticket)
1377
if (last_called == i.number)
1384
i = Ticket.create();
1386
"The barker looks metaphysically embarrassed. ~Um,
1387
Inform's object creation system seems not to have worked.~";
1389
i.number = last_called; itobj = i;
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 ";
1396
print_ret "take ", (the) i, " out of the board.";
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.~";
1405
"The barker is burly, and won't let you
1406
tamper with the board.";
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;
1413
Ticket -> -> ticket_in_board "rolled-up ticket from the board"
1416
Object -> barker "barker"
1417
with name "barker" "burly" "man",
1420
"A boxer gone to seed who failed as a magician all down the
1421
coast, that'd be your guess.",
1423
[; Attack, Kiss: "No way. He must weigh twice what you do.";
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.~";
1436
Order, Answer: "The barker glowers at you.";
1437
Give: if (noun ofclass Ticket)
1439
if (noun.number==2306)
1440
{ move elephant to player; give elephant moved;
1442
Bazaar.description =
1443
"This is a crowded, noisy bazaar. Directly in front of you is
1445
"With very bad grace, the barker shoves the
1446
cuddly toy elephant into your arms.";
1448
if (noun.number==5802)
1449
{ move barker_cube to player; give barker_cube moved;
1451
Bazaar.description =
1452
"This is a crowded, noisy bazaar. Directly in front of you is
1455
"With concealed relief, the barker shoves the
1456
featureless white cube into your hands.";
1458
"~Bad luck! You lose!~";
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.~";
1467
board.credit = board.credit + 3;
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.";
1476
[; Cast: switch(the_spell_was)
1478
"He's not that much of an animal.";
1480
"His problem is listening, not hearing.";
1482
"For a moment his hair seems to comb itself.
1483
Irritated, he ruffles it again, and the spell dies
1484
an ignominious death.";
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).";
1494
"~If that mark does win, hope it's only worthless
1495
old 5802,~ ponders the barker.";
1498
has animate scenery;
1500
Object -> prizes "prizes"
1501
with name "prize" "prizes",
1502
before [; "~Hands off those prizes!~"; ],
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!~"; ],
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!~"; ],
1517
Object elephant "cuddly toy elephant"
1518
with name "cuddly" "toy" "elephant",
1519
description "Pink, cuddly, toy, elephant. Says it all, really.",
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
1526
if (the_spell_was == yomin_spell) "Woolly.";
1529
FeaturelessCube barker_cube "cube";
1531
! ----------------------------------------------------------------------------
1532
! The spells in Helistar's grimoire
1533
! ----------------------------------------------------------------------------
1537
purpose "reverse effect of memorised spell",
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.";
1552
print_ret "Your mind wrenches as ", (the) second,
1553
" reverses itself.";
1556
[; return self.magic(); ! The reverse of "lleps" is "lleps"
1561
purpose "cause immediate death of caster",
1564
"You really can't fault Helistar on this one. Death is
1565
absolutely immediate, like a sudden blackout curtain...";
1568
[; prepared_flag = true;
1569
"Nothing quite happens... and yet you feel enormously more
1570
confident as you go about this dangerous world.";
1573
! ----------------------------------------------------------------------------
1574
! Death and the Boneyard
1575
! ----------------------------------------------------------------------------
1578
if (~~prepared_flag) rfalse;
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.";
1585
prepared_flag = false; deadflag = false; hearing_good = false;
1587
if (memory.capacity >= 2) memory.capacity--;
1589
while (child(player)~=0) move child(player) to parent(player);
1590
move players_book to player;
1592
print "^^With great foresight you prepared yourself for resurrection...
1593
Your mind feels a little weaker, but at least you're alive.^";
1597
Place Boneyard "Boneyard"
1598
with name "bones" "blades" "shoulder" "skulls",
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.",
1605
[; if (scales.number ~= 0) return In_Cave;
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.",
1612
if (noun==w_obj) "You can make out nothing to the west.";
1615
Scroll -> worthless_scroll "worthless scroll"
1616
with initial "You are almost treading on a worthless scroll.",
1619
Spell -> -> filfre_spell
1621
purpose "produce gratuitous fireworks",
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.";
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.";
1634
! ----------------------------------------------------------------------------
1635
! The Cubical Temple
1636
! ----------------------------------------------------------------------------
1638
Place Track "Track, outside Temple"
1640
"This is the end of a long track winding through desolate hills,
1641
which runs back west up to the ridge.",
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.";
1650
w_to Up_Road, u_to Up_Road;
1652
Object -> Temple "cubical Temple"
1653
with name "temple" "cubical" "cube" "enormous",
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)
1661
"The huge temple remains impassive at your relatively
1664
objectloop (i in player)
1665
if (i ofclass FeaturelessCube) j++;
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
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;
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.";
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.",
1693
! ----------------------------------------------------------------------------
1695
! ----------------------------------------------------------------------------
1697
Place Balance_Room "Balance Room"
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.";
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.",
1707
[; "It's only an image.";
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.",
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.";
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;
1738
Object -> sockets "two by two square"
1739
with name "square" "two" "by" "two",
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)
1746
if (child(i)==0) print " is empty.^";
1747
else { print " contains ", (a) child(i), ".^"; }
1754
with name "socket", article "the",
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.";
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
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.";
1789
"The sockets are all full now, but that doesn't mean
1790
anything's happened.";
1792
"The cube is a predictably perfect fit in the socket.";
1794
has static container open;
1796
Socket -> bl_socket "bottom left socket"
1797
with name "bottom" "left" "serpent",
1798
description "a serpent";
1800
Socket -> ul_socket "top left socket"
1801
with name "top" "left" "bazaar",
1802
description "a scene in a bazaar";
1804
Socket -> br_socket "bottom right socket"
1805
with name "bottom" "right" "cave",
1806
description "an engraving of a rocky cave";
1808
Socket -> ur_socket "top right socket"
1809
with name "top" "right" "eye",
1810
description "an eye";
1812
! ----------------------------------------------------------------------------
1813
! That's all of the object definitions: just a little code and grammar left
1814
! ----------------------------------------------------------------------------
1819
move burin to player;
1820
move players_coin to player;
1821
move players_book to player;
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.)
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);
1832
helistars_book.learn_spell(frotz_spell);
1833
helistars_book.learn_spell(lleps_spell);
1834
helistars_book.learn_spell(mortin_spell);
1836
give gnusto_spell known_about;
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.^^";
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.";
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.";
1864
"How many times have you died now? Your memory isn't what it was.";
1867
! ----------------------------------------------------------------------------
1868
! Grammar extensions needed by the spell-casting and cube-writing rules:
1869
! ----------------------------------------------------------------------------
1873
[ AnyWord; from_char=0; to_char=0; the_named_word=wn++; return burin; ];
1876
i = WordAddress(wn++); i=i-buffer;
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++;
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"
1899
Verb "learn" "memorise" "memorize"
1900
* scope=ReadableSpell -> Learn;
1901
Extend "examine" first
1902
* scope=ReadableSpell -> Examine;
1908
* is_spell "at" noun -> Cast
1909
* is_spell "on" noun -> Cast;
1910
Verb "diagnose" "health"
1913
! ----------------------------------------------------------------------------
1914
! And one for the game itself.
1915
! ----------------------------------------------------------------------------
1917
Verb "ride" "mount" "straddle"
1920
Verb "flip" "toss" * is_coin -> TossCoin;
1921
! ----------------------------------------------------------------------------