



Inventory This is the complete source code of the example game Balances.inf.
Back to List
Complete
Browsing Balances.inf
0001 ! ----------------------------------------------------------------------------
0002 ! Balances 961216 One of the standard Inform 6 example games
0003 !
0004 ! created: 25.9.94
0005 ! updated: 6.10.94
0006 ! modernised: 11.12.95
0007 ! translated to Inform 6: 8.5.96
0008 ! minor bugs fixed: 16.12.96
0009 !
0010 ! This short story was written to demonstrate large-scale programming of
0011 ! the parser, and features multiple objects, complicated plurals, variable
0012 ! verbs, objects named by the player and questions. The spell-casting
0013 ! system is written in a "safe" way so that it could easily be transplanted.
0014 !
0015 ! Needs Inform 6, library 6/1 or later to compile.
0016 ! ----------------------------------------------------------------------------
0017
0018 Release 5;
0019 Serial "961216";
0020 Switches d;
0021
0022 Constant Story "BALANCES";
0023 Constant Headline "^An Interactive Short Story
0024 ^Copyright (c) 1994, 1995, 1996 by Graham Nelson.^";
0025
0026 Constant OBJECT_SCORE 5;
0027 Constant MAX_SCORE 51;
0028
0029 Include "Parser";
0030 Include "VerbLib";
0031
0032 ! ----------------------------------------------------------------------------
0033 ! The white featureless cubes from "Spellbreaker", which can be identified
0034 ! by being written on with the magic burin, so that their names are given
0035 ! by the player in the course of play
0036 !
0037 ! A particularly witty thing to do is to give several of them the same name,
0038 ! or to frotz some of them to distinguish them from the others...
0039 ! And the game will have no problem with this.
0040 ! ----------------------------------------------------------------------------
0041
0042 Array cube_text_buffer -> 8;
0043 Global the_named_word = 0;
0044 Global from_char; Global to_char;
0045
0046 Class FeaturelessCube
0047 with number 0 0 0 0, ! There's room for 8 bytes of text in these 4 entries
0048 description "A perfect white cube, four inches on a side.",
0049 parse_name
0050 [ i j flag;
0051 if (parser_action==##TheSame)
0052 { for (i=0:i<8:i++)
0053 if ((parser_one.&number)->i
0054 ~= (parser_two.&number)->i) return -2;
0055 return -1;
0056 }
0057 for (::i++)
0058 { j=NextWord(); flag=0;
0059 if (j=='cube' or 'white' ||
0060 (j=='featureless' or 'blank' &&
0061 ((self.&number)->0) == 0)) flag=1;
0062 if (j=='cubes')
0063 { flag=1; parser_action=##PluralFound; }
0064 if (flag==0 && ((self.&number)->0) ~= 0)
0065 { wn--;
0066 if (TextReader(0)==0) return i;
0067 for (j=0: j<8: j++)
0068 if ((self.&number)->j ~= cube_text_buffer->j)
0069 return i;
0070 flag=1;
0071 }
0072 if (flag==0) return i;
0073 }
0074 ],
0075 article "a",
0076 short_name
0077 [ i; if (((self.&number)->0) == 0) print "featureless white cube";
0078 else
0079 { print "~";
0080 while (((self.&number)->i) ~= 0)
0081 print (char) (self.&number)->i++;
0082 print "~ cube";
0083 }
0084 rtrue;
0085 ],
0086 plural
0087 [; self.short_name(); print "s";
0088 ],
0089 baptise
0090 [ i; wn = the_named_word;
0091 if (TextReader(1)==0) return i;
0092 for (i=0: i<8: i++)
0093 (self.&number)->i = cube_text_buffer->i;
0094 self.article="the";
0095 print_ret "It is now called ", (the) self, ".";
0096 ],
0097 has scored;
0098
0099 ! Copies word "wn" from what the player most recently typed, putting it as
0100 ! plain text into cube_text_buffer, returning false if no such word is there
0101
0102 [ TextReader flag point i j len;
0103
0104 if (flag==1 && from_char~=to_char)
0105 { for (i=from_char, j=0:i<=to_char && j<7:i++)
0106 { cube_text_buffer->j = buffer->i;
0107 if (buffer->i ~= ' ' or ',' or '.') j++;
0108 }
0109 for (:j<8:j++) cube_text_buffer->j = 0;
0110 from_char=0; to_char=0;
0111 rtrue;
0112 }
0113
0114 for (i=0:i<8:i++) cube_text_buffer->i = 0;
0115 if (wn > parse->1) { wn++; rfalse; }
0116 i=wn*4+1; j=parse->i; point=j+buffer; len=parse->(i-1);
0117
0118 for (i=0:i<len && i<7:i++) cube_text_buffer->i = point->i;
0119
0120 wn++; rtrue;
0121 ];
0122
0123 Object burin "magic burin"
0124 with name "magic" "magical" "burin" "pen",
0125 description
0126 "This is a magical burin, used for inscribing objects with words
0127 or runes of magical import. Such a burin also gives you the
0128 ability to write spell scrolls.",
0129 before
0130 [; WriteOn:
0131 if (second ofclass FeaturelessCube)
0132 { if (second notin player)
0133 "Writing on a cube is such a fiddly process that you
0134 need to be holding it in your hand first.";
0135 if (burin notin player)
0136 "You would need some powerful implement for that.";
0137 second.baptise();
0138 rtrue;
0139 }
0140 if (second ofclass SpellBook)
0141 "If a burin could write in a spell book, you wouldn't need
0142 the gnusto spell!";
0143 if (second ofclass Scroll)
0144 "You cannot write just anything on the magic parchment of
0145 a scroll: you can only ~copy~ a spell to it.";
0146 ];
0147
0148 [ WriteOnSub; "Graffiti is banned."; ];
0149
0150 [ CopyToSub;
0151 if (burin notin player) "You need to be holding the burin to copy a spell.";
0152 if (second ofclass SpellBook)
0153 "If a burin could write in a spell book, you wouldn't need
0154 the gnusto spell!";
0155 if (~~(second ofclass Scroll)) "You can only copy spells to scrolls.";
0156 if (child(second)~=0)
0157 "The scroll is already full of incantation.";
0158 "The scroll is not blank, only illegible.";
0159 ];
0160
0161 ! ----------------------------------------------------------------------------
0162 ! Now the whole spell-casting system
0163 ! ----------------------------------------------------------------------------
0164
0165 Attribute known_about; ! Player has seen this spell somewhere
0166 Attribute reversed; ! Effect of this known spell reversed
0167
0168 Attribute is_spell;
0169 Class Spell
0170 with name "spell" "spells", article "the",
0171 number 0,
0172 word_name
0173 [; print (address) (self.&name)-->0;
0174 ],
0175 short_name
0176 [; self.word_name(); print " spell"; give self known_about; rtrue;
0177 ],
0178 specification
0179 [; self.short_name();
0180 print ": ", (string) self.purpose;
0181 ],
0182 before
0183 [; Examine: self.specification(); ".";
0184 ],
0185 has is_spell;
0186
0187 Object memory
0188 with capacity 5,
0189 number_known 1,
0190 describe_contents
0191 [ i j k;
0192 objectloop (i in self) if (i.number==100) j++;
0193 if (j>0)
0194 { print "The ";
0195 objectloop (i in self)
0196 if (i.number==100)
0197 { k++; i.word_name();
0198 if (k==j-1) print " and ";
0199 if (k<j-1) print ", ";
0200 }
0201 if (j==1) print " spell is"; else print " spells are";
0202 print " yours forever. Other than that, y";
0203 }
0204 else print "Y";
0205 print "ou have ";
0206 j=0; k=0;
0207 objectloop (i in self) if (i.number<100) j++;
0208 if (j>0)
0209 { print "the ";
0210 objectloop (i in self)
0211 if (i.number<100)
0212 { k++;
0213 print (name) i;
0214 if (i.number==2) print " (twice)";
0215 if (i.number==3) print " (thrice)";
0216 if (i.number==4) print " (four times)";
0217 if (i.number>=5) print " (many times)";
0218 if (k==j-1) print " and ";
0219 if (k<j-1) print ", ";
0220 }
0221 }
0222 else print "no spells";
0223 " memorised.";
0224 ],
0225 learn_spell
0226 [ sp;
0227 if (sp.number==100) "You always know that spell.";
0228 print "Using your best study habits, you commit the ";
0229 sp.word_name();
0230 print " spell to memory";
0231 if (sp notin self) sp.number=0;
0232 move sp to self;
0233 self.number_known++;
0234 sp.number++;
0235 if (sp.number==1) print ".";
0236 if (sp.number==2) print " once again.";
0237 if (sp.number==3) print " a third time.";
0238 if (sp.number>3) print " yet another time.";
0239 if (self.number_known <= self.capacity) { new_line; rtrue; }
0240 self.forget_spell(sibling(child(self)));
0241 " You have so much buzzing around in your head, though,
0242 that it's likely something may have been forgotten
0243 in the shuffle.";
0244 ],
0245 forget_spell
0246 [ sp;
0247 if (sp notin self || sp.number==100) rtrue;
0248 self.number_known--;
0249 sp.number--;
0250 if (sp.number==0) remove sp;
0251 rtrue;
0252 ];
0253
0254 Spell -> gnusto_spell
0255 with name "gnusto",
0256 purpose "copy a scroll into your spell book",
0257 number 100,
0258 magic
0259 [ i a_book;
0260 if (second ofclass SpellBook)
0261 "Unlike scrolls, spell books are magically guarded against
0262 the 'theft' of their lore.";
0263 if (second==0 || ~~(second ofclass Scroll))
0264 "Your spell fizzles vaguely out.";
0265 if (second notin player)
0266 "A gnusto spell would require close scrutiny of the scroll
0267 it is to copy: which you do not seem to be holding.";
0268 objectloop (i in player)
0269 if (i ofclass SpellBook) a_book=i;
0270 if (a_book==0)
0271 "Your spell fails, as you have no spell book.";
0272 i=child(second);
0273 if (i==0 || ~~(i ofclass Spell))
0274 { print_ret "Your spell fails, as ", (the) second,
0275 " is illegible.";
0276 }
0277 a_book.learn_spell(i); remove second;
0278 print_ret
0279 "Your spell book begins to glow softly. Slowly, ornately,
0280 the words of ", (the) i, " are inscribed,
0281 glowing even more brightly then the book itself.
0282 The book's brightness fades, but the spell remains!
0283 However, the scroll on which it was written vanishes as
0284 the last word is copied.";
0285 ];
0286
0287 Class SpellBook
0288 with array_of_spells 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0,
0289 capacity 16,
0290 learn_spell
0291 [ sp p i;
0292 p = self.&array_of_spells;
0293 for (i=0:i<self.capacity && (p-->i)~=0:i++) ;
0294 if (i==self.capacity) rtrue;
0295 p-->i = sp;
0296 ],
0297 before
0298 [; Open, Close:
0299 print_ret
0300 (The) self, " is always open to the right place, but it
0301 is also always closed. This eliminates tedious leafing and
0302 hunting for spells. Many lives have been saved by this
0303 magical innovation.";
0304 Attack:
0305 print_ret "When you are done, ", (the) self, " remains unmarred.";
0306 ],
0307 after
0308 [ p i j; Examine:
0309 p = self.&array_of_spells;
0310 for (i=0:i<self.capacity && (p-->i)~=0:i++)
0311 { j=p-->i; <Examine j>;
0312 }
0313 rtrue;
0314 ];
0315
0316 Class Scroll
0317 with parse_name
0318 [ i j k; j=-1;
0319 if (self has general)
0320 { if (child(self)~=0 && child(self) ofclass Spell)
0321 j=(child(self).&name)-->0; else j='illegible';
0322 }
0323 for (::)
0324 { k=NextWord();
0325 if (k=='scrolls') parser_action=##PluralFound;
0326 if ((k=='scrolls' or 'scroll' or j) || k==(self.&name)-->0)
0327 i++;
0328 else return i;
0329 }
0330 ],
0331 before
0332 [ i; Examine:
0333 i=child(self);
0334 give self general;
0335 if (i==0 || ~~(i ofclass Spell))
0336 "The scroll has faded, and you cannot read it.";
0337 print "The scroll reads ~"; i.specification(); "~.";
0338 ],
0339 invent
0340 [; if (inventory_stage==2 && self has general)
0341 { if (child(self)==0 || ~~(child(self) ofclass Spell))
0342 print " (which is illegible)";
0343 else
0344 { print " (of ", (the) child(self), ")"; }
0345 }
0346 ];
0347
0348 [ ReadableSpell i j k;
0349 if (scope_stage==1)
0350 { if (action_to_be==##Examine) rfalse;
0351 rtrue;
0352 }
0353 if (scope_stage==2)
0354 { objectloop (i in player)
0355 if (i ofclass SpellBook)
0356 { for (k=0:k<i.capacity && (i.&array_of_spells)-->k~=0:k++)
0357 { j=(i.&array_of_spells)-->k; PlaceInScope(j);
0358 }
0359 }
0360 rtrue;
0361 }
0362 ! No need for scope_stage 3 (the error stage), because our
0363 ! ParserError routine handles that case instead
0364 ];
0365
0366 [ CopyableSpell i j k;
0367 if (scope_stage==1) return 1;
0368 if (scope_stage==2)
0369 { objectloop (i in player)
0370 if (i ofclass SpellBook)
0371 { for (k=0:k<i.capacity && (i.&array_of_spells)-->k~=0:k++)
0372 { j=(i.&array_of_spells)-->k; PlaceInScope(j);
0373 }
0374 }
0375 rfalse;
0376 }
0377 ! No need for scope_stage 3 (the error stage), because our
0378 ! ParserError routine handles that case instead
0379 ];
0380
0381 [ SpellsSub; memory.describe_contents(); ];
0382
0383 [ LearnSub; if (location==thedark)
0384 print "(The magic writing of the spells casts enough light
0385 that you can read them.)^";
0386 memory.learn_spell(noun);
0387 ];
0388
0389 Global the_spell_was = gnusto_spell;
0390
0391 [ CastOneSub; <Cast the_spell_was noun>; ];
0392
0393 [ CastSub;
0394 the_spell_was = noun; memory.forget_spell(noun);
0395
0396 if (noun has reversed)
0397 { give noun ~reversed;
0398 if (noun.unmagic() ~= 0) return;
0399 "Nothing happens.";
0400 }
0401
0402 if (second ~= 0)
0403 { ResetVagueWords(second); ! Set "it", "him", "her"
0404 if (second provides before
0405 && second.before() ~= 0) return; ! Run before routine(s)
0406 }
0407 if (noun.magic() ~= 0) return;
0408 "Nothing happens.";
0409 ];
0410
0411 [ InScope i;
0412 if (verb_word=='c,cast' or 'cast')
0413 objectloop (i in memory) PlaceInScope(i);
0414 rfalse;
0415 ];
0416
0417 [ ParserError x i flag vb;
0418 if (etype==VERB_PE or ASKSCOPE_PE)
0419 { if (etype==ASKSCOPE_PE)
0420 { if (verb_word=='cast') vb=1;
0421 if (verb_word=='learn' or 'memorise' or 'memorize') vb=2;
0422 if (verb_word=='copy') vb=3;
0423 if (vb==0) { etype=CANTSEE_PE; rfalse; }
0424 }
0425 wn=verb_wordnum; if (vb~=0) wn++;
0426 x=NextWordStopped();
0427 for (i=player+1:i<=top_object:i++)
0428 if (i ofclass Spell && Refers(i,x)==1
0429 && i has known_about) flag=1;
0430 if (flag==1)
0431 { if (vb==0 or 1)
0432 "You haven't got that spell committed to memory. [Type ~spells~
0433 to see what you do remember.]";
0434 if (vb==2)
0435 "Your training is such that you can only memorise such a spell
0436 with the aid of a spell book containing it.";
0437 if (vb==3)
0438 "You have no text of that spell to copy.";
0439 }
0440 if (vb==1)
0441 "You haven't learned that spell, if indeed it is a spell.";
0442 if (vb==2 or 3)
0443 "You haven't access to that spell, if indeed it is a spell.";
0444 }
0445 rfalse;
0446 ];
0447
0448 [ ChooseObjects obj code;
0449 if (code<2) rfalse;
0450 if (action_to_be==##WriteOn && obj in player) return 9;
0451 return 0;
0452 ];
0453
0454 [ UnknownVerb word i;
0455 objectloop (i in memory)
0456 if (word==(i.&name)-->0) { the_spell_was = i; return 'c,cast'; }
0457 rfalse;
0458 ];
0459
0460 [ PrintVerb v;
0461 if (v=='c,cast') { print "cast a spell at"; rtrue; }
0462 rfalse;
0463 ];
0464
0465 ! ----------------------------------------------------------------------------
0466 ! And now, on with the story. First, some global variables:
0467 ! ----------------------------------------------------------------------------
0468
0469 Global prepared_flag = false; ! Prepared for resurrection?
0470 Global hearing_good = false; ! Sharp hearing?
0471 Global number_filled = 0; ! Sockets in the temple filled
0472
0473 ! ----------------------------------------------------------------------------
0474 ! A "questions" verb. Thus,
0475 ! "who is my friend helistar"
0476 ! "what was the great change"
0477 ! and so on are recognised.
0478 ! ----------------------------------------------------------------------------
0479
0480 [ QuerySub;
0481 noun.description();
0482 ];
0483 [ Topic i;
0484 if (scope_stage==1) return 0;
0485 if (scope_stage==2)
0486 { objectloop (i ofclass Question) PlaceInScope(i);
0487 rtrue;
0488 }
0489 "At the moment, even the simplest questions confuse you.";
0490 ];
0491
0492 Class Question;
0493 Question
0494 with name "helistar" "my" "friend" "colleague",
0495 description
0496 "Helistar is your colleague, an Enchanter like you who has been much
0497 on your mind lately. She has been investigating some very dark
0498 magic indeed, and seems not to be around any more. You feel rather
0499 vague about the details.";
0500 Question
0501 with name "magical" "magic" "burin",
0502 description "A burin is an engraving and writing tool.";
0503 Question
0504 with name "change" "great",
0505 description
0506 "Something you had a lot to do with, but what exactly? No, it's gone.";
0507 Question
0508 with name "cyclops",
0509 description
0510 "A one-eyed giant, usually hostile. (Don't they teach anything at
0511 adventurer school these days?)";
0512 Question
0513 with name "grue",
0514 description
0515 "The grue is a sinister, lurking presence in the dark places of the
0516 earth. Its favorite diet is adventurers, but its insatiable appetite
0517 is tempered by its fear of light. No grue has ever been seen by the
0518 light of day, and few have survived its fearsome jaws to
0519 tell the tale.";
0520 Question
0521 with name "grimoire",
0522 description
0523 "According to Chambers English Dictionary, a grimoire is ~a magician's
0524 book for calling up spirits~.";
0525 Question
0526 with name "spells" "work",
0527 description
0528 "Your memory is still dream-hazed, but it's coming back. As a trained
0529 Enchanter, you have the ability to cast spells like ~frotz~, provided
0530 you have learned them in advance. Some of these spells can be cast
0531 at something; others can be cast alone.
0532 ^^Spells are very complicated. Each time you cast one, you forget it
0533 (though you can get around this by learning it several times, so as
0534 to have several uses up your sleeve). The only way to hang on to
0535 a spell is to have it written down, on a scroll or in a spell book.
0536 Scrolls are not ideal for this, and you can only learn a spell from
0537 your spell book. (But you can add spells to your book.)
0538 ^^[Type ~learn frotz~ and then ~frotz coin~ for an example. You can
0539 also type ~spells~ to see what you currently have memorised.]";
0540
0541 ! ----------------------------------------------------------------------------
0542 ! Some multiple objects, coins in fact, coded in deluxe fashion:
0543 ! ----------------------------------------------------------------------------
0544
0545 Attribute is_coin;
0546 Class Coin
0547 with name "coin",
0548 description "A round unstamped disc, presumably part of the local
0549 currency.",
0550 parse_name
0551 [ i j w;
0552 if (parser_action==##TheSame)
0553 { if ((parser_one.&name)-->0 == (parser_two.&name)-->0) return -1;
0554 return -2;
0555 }
0556 w=(self.&name)-->0;
0557 for (::i++)
0558 { j=NextWord();
0559 if (j=='coins') parser_action=##PluralFound;
0560 else if (j~='coin' or w) return i;
0561 }
0562 ],
0563 has is_coin;
0564
0565 Class GoldCoin
0566 class Coin,
0567 with name "gold",
0568 short_name "gold coin",
0569 plural "gold coins";
0570 Class SilverCoin
0571 class Coin,
0572 with name "silver",
0573 short_name "silver coin",
0574 plural "silver coins";
0575 Class BronzeCoin
0576 class Coin,
0577 with name "bronze",
0578 short_name "bronze coin",
0579 plural "bronze coins";
0580
0581 SilverCoin players_coin;
0582
0583 [ TossCoinSub; if (noun notin player) "You need to be holding the coin first.";
0584 move noun to parent(player);
0585 if (location==thedark) "You throw it away into the darkness.";
0586 if (random(20)==1)
0587 "You toss the coin, and it lands... on its edge, amazingly.";
0588 "You toss the coin, and it comes up... blank, since neither side is
0589 marked.";
0590 ];
0591
0592 ! ----------------------------------------------------------------------------
0593 ! The player's spell book, and three initial spells (to go with gnusto):
0594 ! ----------------------------------------------------------------------------
0595
0596 SpellBook players_book "spell book"
0597 with name "spell" "book" "my" "spellbook",
0598 description "My Spell Book^";
0599
0600 Spell frotz_spell
0601 with name "frotz",
0602 purpose "cause an object to give off light",
0603 magic
0604 [; if (second==0) "There is a brief, blinding flash of light.";
0605 if (second has animate)
0606 "The spell, not designed for living creatures, goes sour.";
0607 if (second in compass)
0608 "The spell dissipates vaguely.";
0609 give second light;
0610 print_ret
0611 "There is an almost blinding flash of light as ", (the) second,
0612 " begins to glow! It slowly fades to a less painful level, but ",
0613 (the) second, " is now quite usable as a light source.";
0614 ],
0615 unmagic
0616 [; if (second==0) "There is a brief moment of deep darkness.";
0617 if (second has animate)
0618 "The spell, not designed for living creatures, goes sour.";
0619 if (second in compass)
0620 "The spell dissipates vaguely.";
0621 if (second hasnt light)
0622 print_ret (The) second, " isn't producing light as it is.";
0623 give second ~light;
0624 print_ret "A pool of darkness coagulates around ", (the) second,
0625 " but slowly fades back to normality. Still, ",
0626 (the) second, " is no longer any kind of light source.";
0627 ];
0628
0629 Spell rezrov_spell
0630 with name "rezrov",
0631 purpose "open even locked or enchanted objects",
0632 magic
0633 [; if (second==0) "The world is open already.";
0634 if (second has animate)
0635 "It might be a boon to surgeons if it worked, but it doesn't.";
0636 if (second has open || second hasnt openable)
0637 "It doesn't need opening.";
0638 if (second hasnt locked)
0639 { give second open;
0640 print_ret (The) second, " opens obediently.
0641 Like swatting a fly with a sledge hammer, if you ask me.";
0642 }
0643 give second open ~locked;
0644 print "Silently, ", (the) second, " swings open. ";
0645 if (second has container) <<Search second>>; new_line; rtrue;
0646 ],
0647 unmagic
0648 [; if (second==0) "The world is closed already.";
0649 if (second has animate)
0650 "Happily, that is unnecessary.";
0651 if (second has locked || second hasnt lockable)
0652 "It doesn't need locking.";
0653 give second ~open locked;
0654 "Silently, ", (the) second, " swings shut and locks.";
0655 ];
0656
0657 Spell yomin_spell
0658 with name "yomin",
0659 purpose "mind probe",
0660 magic
0661 [; if (second==0 || second hasnt animate)
0662 "That must be either vegetable or mineral.";
0663 if (second==player) "You give yourself a mild headache.";
0664 print_ret "You look into the rather ordinary thoughts of ",
0665 (the) second, ".";
0666 ],
0667 unmagic
0668 [; if (second==0 || second hasnt animate)
0669 "That must be either vegetable or mineral.";
0670 if (second==player) "You give yourself a mild headache.";
0671 print_ret (The) second, " is rather shocked, for some reason.";
0672 ];
0673
0674 ! ----------------------------------------------------------------------------
0675 ! The first scene: the Hut and its (rather easy) secret
0676 ! ----------------------------------------------------------------------------
0677
0678 Class Place
0679 has light;
0680
0681 Place Hut "Ramshackle Hut"
0682 with description
0683 "Until quite recently, someone lived here, you feel sure.
0684 Now the furniture is matchwood and
0685 the windows are glassless. Outside, it is a warm, sunny day,
0686 and grasslands extend to the low hills on the horizon.",
0687 out_to Grasslands, w_to Grasslands,
0688 cant_go "There's only the one room: better go ~out~.",
0689 name "windows" "grasslands" "grass" "hills";
0690
0691 Object -> furniture "wooden furniture"
0692 with name "furniture" "broken" "wood" "wooden",
0693 before
0694 [; Examine, Search, LookUnder:
0695 self.before=0; score=score+5;
0696 move h_box to player;
0697 "Searching through the furniture, which is good for nothing
0698 but firewood now, you come across an old cedarwood box,
0699 which you pick up for a closer look.";
0700 ],
0701 has scenery;
0702
0703 Object h_box "cedarwood box"
0704 with name "cedar" "cedarwood" "wooden" "box",
0705 description "The box bears the calligraphed initial H."
0706 has container openable lockable locked;
0707
0708 SpellBook -> helistars_book "Helistar's grimoire"
0709 with name "grimoire" "helistar" "helistars",
0710 description "This must be the grimoire of dangerous spells kept by
0711 your irresponsible friend Helistar. Many pages are
0712 missing, but a few spells remain:^",
0713 has proper;
0714
0715 ! ----------------------------------------------------------------------------
0716 ! Grasslands and the valley
0717 ! ----------------------------------------------------------------------------
0718
0719 Place Grasslands "Grasslands, near Hut"
0720 with name "grasslands" "grass" "hut" "path",
0721 description
0722 "The grasslands sway over low hills in all directions: it is a
0723 peaceful wilderness, broken only by this hut and a faint path
0724 to the north.",
0725 in_to Hut, e_to Hut,
0726 n_to Valley,
0727 cant_go "You wander around for a while but end up back at the hut.";
0728
0729 Place Valley "Pocket Valley"
0730 with name "valley" "trail",
0731 description
0732 "A pleasant pocket valley in the grassy hills, through which a
0733 trail runs north-to-south.",
0734 n_to "The trail runs out to nothing, and you retreat for fear of
0735 getting so lost you couldn't find the hut again by nightfall.",
0736 cant_go "You wander around the pleasant valley, but are afraid to
0737 lose sight of the trail.",
0738 s_to Grasslands;
0739
0740 [ RideSub; print_ret "You can hardly ride ", (a) noun, "."; ];
0741
0742 Object -> horse "horse"
0743 with short_name
0744 [; if (self has general) print "winged horse";
0745 else print "chestnut horse";
0746 rtrue;
0747 ],
0748 parse_name
0749 [ i j; if (self has general) j='winged'; else j=-1;
0750 while (NextWord()==j or 'horse' or 'chestnut') i++;
0751 return i;
0752 ],
0753 describe
0754 [; print_ret
0755 "There is ", (a) self, " here, munching on a pile of oats.";
0756 ],
0757 before
0758 [; Cast: if (the_spell_was == bozbar_spell)
0759 { give self general;
0760 "A pair of handsome brown wings suddenly appears on
0761 the horse's powerful shoulders. The horse turns in a
0762 complete circle, a look of puzzlement on his face.";
0763 }
0764 if (the_spell_was == yomin_spell)
0765 "He is mainly thinking about oats. Partly who you are
0766 and what you're up to, but mainly oats.";
0767 Enter: <<Ride self>>;
0768 Ride: if (horse hasnt general)
0769 "You ride around for a while, exercising the horse, but
0770 soon enough he tires of this and pointedly brings you
0771 back to the oats. Obligingly you dismount and he
0772 begins grazing again.";
0773
0774 print "You begin to ride north. Then, slowly at first but with
0775 increasing sureness, the horse begins beating its powerful
0776 wings. You rise majestically through the air, sailing
0777 gracefully across a chasm where the hills fall away.
0778 The horse lands gently on the far side and deposits you,
0779 taking to the skies again.^";
0780 PlayerTo(Edge); rtrue;
0781 ],
0782 has animate;
0783
0784 Object -> oats "pile of oats"
0785 with name "oats" "pile" "of",
0786 before
0787 [; Examine, Search, LookUnder:
0788 self.before=NULL;
0789 move shiny_scroll to player; score=score+5;
0790 itobj=shiny_scroll;
0791 "Sifting through the oats, you find a shiny scroll! Lucky
0792 you got to it before the horse did. As you turn it over
0793 in your hands, it seems undamaged.";
0794 Take: "What would you want with all those oats?";
0795 ],
0796 has scenery;
0797
0798 Scroll shiny_scroll "shiny scroll"
0799 with name "shiny";
0800
0801 Spell -> bozbar_spell
0802 with name "bozbar",
0803 purpose "cause an animal to spro