home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format 103 / af103sub.adf / Hugo.LZX / Hugo / Examples / sample.hug < prev    next >
Text File  |  1997-08-22  |  40KB  |  1,778 lines

  1. !\---------------------------------------------------------------------------
  2.     
  3.     THE VAULT OF HUGO
  4.     Hugo v2.3 Tutorial Game
  5.  
  6.     by Kent Tessman (c) 1995-1997
  7.  
  8. ---------------------------------------------------------------------------\!
  9.  
  10. #version 2.3
  11.  
  12. #set DEBUG                              ! include HugoFix library and grammar
  13. #set VERBSTUBS                          ! include verb stub routines
  14.  
  15. #set USE_VEHICLES                       ! from OBJLIB.H
  16. #set USE_PLURAL_OBJECTS                 !
  17. #set USE_ATTACHABLES                    !
  18.  
  19. #set NO_AUX_MATH                        ! don't need advanced math routines
  20.  
  21. #switches -ls                           ! print statistics to SAMPLE.LST
  22.  
  23.  
  24. ! The following limit setting reserves 512 extra bytes of dictionary space
  25. ! so that the play can name the unnamed object.  A maximum 512 bytes are
  26. ! required because the game needs to write the name, adjective, and misc
  27. ! properties of the object.
  28.  
  29. $MAXDICTEXTEND = 512
  30.  
  31.  
  32. !----------------------------------------------------------------------------
  33. ! NEW GRAMMAR:
  34.  
  35. verb "kick", "punt", "boot"
  36.     *                                               DoVague
  37.     * object                                        DoPunt
  38.  
  39. verb "board"
  40.     * (minecar)                                     DoEnter
  41.  
  42. verb "roll", "drive", "steer", "ride"
  43.     *                                               DoVague
  44.     * object                                        DoMoveinVehicle
  45.     * "to" object                                   DoMoveinVehicle
  46.  
  47. ! In the grammar definitions below, STRING refers to any section of the
  48. ! player's input enclosed in quotation marks.
  49.  
  50. verb "write", "scribble", "scrawl", "print"
  51.     *                                               DoVague
  52.     * "on" object                                   DoWriteOn
  53.     * "on" object "with" held                       DoWriteOn
  54.     * string                                        DoWrite
  55.     * string "on" object                            DoWrite
  56.     * string "on" object "with" held                DoWrite
  57.     * string "with" held                            DoWrite
  58.  
  59. verb "name", "call", "christen"
  60.     *                                               DoVague
  61.     * (unnamedobject)                               DoNameWhat
  62.     * (unnamedobject) string                        DoName
  63.  
  64. verb "stick"
  65.     *                                               DoVague
  66.     * (dart)                                        DoAttachObject
  67.     * (dart) "in"/"on" (dartboard)                  DoAttachObject
  68.  
  69.  
  70. #include "grammar.g"                    ! normal game grammar
  71.  
  72. !----------------------------------------------------------------------------
  73.  
  74. #ifset PRECOMPILED_LIBRARY
  75. #link "hugolib.hlb"
  76. #endif
  77. #ifclear PRECOMPILED_LIBRARY
  78. #include "hugolib.h"                    ! standard library routines
  79. #endif
  80.  
  81. ! Normally, the library's PrintScore routine uses a MAX_SCORE/score
  82. ! formula to determine a ranking (if rankings are provided); the following
  83. ! global is used in the replaced PrintScore routine to ensure that rank is
  84. ! set by the game, not approximated by the library.
  85.  
  86. global rank
  87.  
  88. routine init
  89. {
  90.     MAX_SCORE = 50
  91.     ranking[0] = "Amateur Adventurer"
  92.     ranking[1] = "Competent Door-Unlocker"
  93.     ranking[2] = "Bomb-Meddling Adventurer"
  94.     ranking[3] = "Master Magic Wand Finder"
  95.     ranking[4] = "The Genuine Article Sample Game Solver"
  96.     MAX_RANK = 4
  97.  
  98.     counter = -1                    ! 1 turn before turn 0
  99.  
  100.     STATUSTYPE = 1                  ! score/turns
  101.     TEXTCOLOR = DEF_FOREGROUND
  102.     BGCOLOR = DEF_BACKGROUND
  103.     SL_TEXTCOLOR = BRIGHT_WHITE
  104.     SL_BGCOLOR = BLUE
  105.  
  106.     prompt = ">"
  107.     color TEXTCOLOR, BGCOLOR
  108.  
  109.     cls
  110.     "You brace yourself, check your flashlight, and, with \
  111.     source code in hand, prepare to enter...\n"
  112.     
  113.     Font(BOLD_ON | DEFAULT_FONT)
  114.     "THE VAULT OF HUGO"
  115.     Font(BOLD_OFF)
  116.     "An Interactive Example"
  117.     print BANNER
  118.  
  119.     player = you
  120.     location = outsidevault
  121.     old_location = location
  122.  
  123.     move player to location         ! initialize player location
  124.     FindLight(location)             ! whether the player can see
  125.     DescribePlace(location)         ! the appropriate description
  126.     location is visited
  127.     CalculateHolding(player)        ! total size of player contents
  128.  
  129.     Acquire(player, flashlight)     ! give the player the flashlight
  130.     flashlight is known
  131.     
  132.     Activate(key_daemon)            ! set up initial daemons
  133.  
  134.     InitPluralObjects
  135. }
  136.  
  137. #ifset PRECOMPILED_LIBRARY
  138. replace main
  139. {
  140. #endif
  141. #ifclear PRECOMPILED_LIBRARY
  142. routine main
  143. {
  144. #endif
  145.     counter = counter + 1
  146.     PrintStatusLine
  147.     run location.each_turn
  148.     runevents
  149.     RunScripts
  150.     if speaking not in location     ! in case the character being spoken
  151.         speaking = 0            ! to leaves
  152. }
  153.  
  154. character you "you"
  155. {
  156.     nouns "me", "myself"
  157.     pronouns "you", "you", "your", "yourself"
  158.     capacity 100
  159.     is plural                       ! for matching second-person verbs
  160.     is hidden                       ! for location descriptions
  161.     long_desc {"Looking good."}
  162. }
  163.  
  164.  
  165. ! flashlight
  166. !
  167. ! The flashlight is an example of a light source.  The rules for
  168. ! the FindLight routine in HUGOLIB.H check to see if any light sources
  169. ! are available (starting with the room itself, then working through
  170. ! the visible contents) before deciding if the player is able to see 
  171. ! in any given location.
  172.  
  173. object flashlight "flashlight"
  174. {
  175.     in you
  176.     nouns "flashlight", "light", "torch", "lamp"
  177.     adjective "flash"
  178.     article "your"
  179.     short_desc
  180.     {
  181.         CArt(self)
  182.         " is here, ";
  183.         if self is switchedon
  184.             "glowing brightly."
  185.         else
  186.             "turned off."
  187.     }
  188.     long_desc
  189.     {
  190.         "It's one of those disposable kinds.  Built-in battery.  \
  191.         $3.99 at the corner store.  That sort of thing.  At the 
  192.         moment, it is ";
  193.         if self is switchedon
  194.             "on."
  195.         else
  196.             "off."
  197.     }
  198.     before
  199.     {
  200.         ! The before property routine attempts to match the verb                
  201.         ! routine based on a given specifier.  In the case below,
  202.         ! if the verbroutine global is set to DoBurn (technically
  203.         ! &DoBurn, the address of the DoBurn routine) and the 
  204.         ! object global is set to the flashlight object, the
  205.         ! following routine is run before (in place of) the DoBurn
  206.         ! routine.
  207.  
  208.         object DoBurn
  209.             {Perform(&DoSwitchOn, self)}
  210.     }
  211.     after
  212.     {
  213.         ! The two routines below are similar to the before routine
  214.         ! above, except that they are run after the verb routine.
  215.  
  216.         object DoSwitchOn
  217.         {
  218.             "A beam of serviceable light appears from your 
  219.             flashlight."
  220.             self is light
  221.             FindLight(location)
  222.             if location is not visited
  223.                 {DescribePlace(location)
  224.                 location is visited}
  225.         }
  226.         object DoSwitchOff
  227.         {
  228.             "Your flashlight goes dark.  ";
  229.             self is not light
  230.             if FindLight(location)
  231.                 print newline
  232.             else
  233.                 "And so does everything else."
  234.         }
  235.     }
  236.     is switchable
  237. }
  238.  
  239. !----------------------------------------------------------------------------
  240. ! OUTSIDE THE VAULT
  241. !----------------------------------------------------------------------------
  242. room outsidevault "outside a vault"
  243. {
  244.     long_desc
  245.         {"Kind of that 1930s, Bela Lugosi, graveyardy motif at 
  246.         work here.  It's a pretty creepy place.  Directly in 
  247.         front of you is the giant door to an even more giant 
  248.         vault.  Above the door hangs a rusty sign."}
  249.     e_to {return vaultdoor.door_to}
  250.     in_to {return vaultdoor.door_to}
  251.     cant_go
  252.         {"Vines, thorns, and bent, twisted trees bar travel in any 
  253.         direction away from the vault."}
  254.     before
  255.     {
  256.         location DoDig
  257.         {
  258.             if object ~= bump
  259.                 "You can't dig in that."
  260.             else
  261.                 Perform(&DoSearch, bump)
  262.         }
  263.     }
  264. }
  265.  
  266.  
  267. ! key_daemon
  268. !
  269. ! This basic daemon is simply a trigger that checks every turn to see
  270. ! if 10 turns have passed.  If so, it prints a brief section of prose
  271. ! before deactivating itself.  (It is also deactivated if the player
  272. ! pre-emptively searches the bump in the ground.)
  273.  
  274. daemon key_daemon
  275. {}
  276.  
  277. event key_daemon
  278. {
  279.     if counter = 10
  280.     {
  281.         "\nAll this shuffling around outside the door has uncovered 
  282.         a little bump in the ground."
  283.         
  284.         event_flag = true
  285.         Deactivate(key_daemon)
  286.     }
  287. }
  288.  
  289. scenery bump "little bump"
  290. {
  291.     in outsidevault
  292.     nouns "bump", "ground"
  293.     adjective "little"
  294.     article "a"
  295.     long_desc
  296.     {
  297.         if key is not moved
  298.             {"It looks like there might be something there."
  299.             bump is moved}
  300.         else
  301.             {"You've already got the key.  What more do 
  302.             you want?"}
  303.     }
  304.     before
  305.     {
  306.         ! More than one verb routine may be given as a potential
  307.         ! match to a specifier in a before or after routine, as in:
  308.         
  309.         object DoSearch, DoDig
  310.         {
  311.             if key is moved
  312.                 "You already did.  There's nothing else 
  313.                 to find."
  314.             else
  315.             {
  316.                 bump is moved
  317.                 "You find a rusty iron key!\n(Taken.)"
  318.                 Acquire(player, key)
  319.                 score = score + 10
  320.                 Deactivate(key_daemon)
  321.             }
  322.         }
  323.     }
  324. }
  325.  
  326. object key "rusty iron key"
  327. {
  328.     noun "key"
  329.     adjectives "rusty", "iron"
  330.     article "a"
  331.     size 20
  332.     long_desc
  333.         {"A skeleton key.  Rusty.  Iron.  And heavy, too.  A perfect 
  334.         match for the vault door, no?"}
  335.     before
  336.     {
  337.         xobject DoUnlock
  338.         {
  339.             if object = oakdoor
  340.                 "The rusty key doesn't work on this door."
  341.             else
  342.                 return false    ! library continues as usual
  343.         }
  344.     }
  345. }
  346.  
  347. scenery sign "rusty sign"
  348. {
  349.     in outsidevault
  350.     noun "sign"
  351.     article "a"
  352.     adjective "rusty"
  353.     long_desc {"\"Here lies Hugo.\""}
  354.     is readable
  355. }
  356.  
  357.  
  358. ! vaultdoor
  359. !
  360. ! Notice that the found_in property specifies the rooms on either side
  361. ! of the door; OBJLIB.H does the rest.  The vault door's special attribute
  362. ! is set once the player scores points for opening it.
  363.  
  364. door vaultdoor "vault door"
  365. {
  366.     nouns "door", "doorway"
  367.     adjective "vault"
  368.     article "the"
  369.     between outsidevault, insidevault
  370.     key_object key
  371.     after
  372.     {
  373.         object DoUnlock
  374.         {
  375.             if self is not special
  376.             {
  377.                 self is special
  378.                 score = score + 10
  379.                 rank = 1
  380.             }
  381.             return false    ! library continues as usual
  382.         }
  383.     }
  384.     is not open, lockable, locked
  385. }
  386.  
  387. scenery vault "vault"
  388. {
  389.     in outsidevault
  390.     noun "vault"
  391.     article "the"
  392.     long_desc {"Big, imposing, and complete with rusty sign."}
  393.     door_to                         ! so a player can "go vault"
  394.         {return vaultdoor.door_to}
  395.     before
  396.     {
  397.         object DoEnter
  398.         {
  399.             object = vaultdoor      ! change object before letting
  400.             return false            ! library continue normally
  401.         }
  402.     }
  403. }
  404.  
  405. !----------------------------------------------------------------------------
  406. ! INSIDE THE VAULT
  407. !----------------------------------------------------------------------------
  408. room insidevault "inside the vault"
  409. {
  410.     long_desc
  411.     {
  412.         "Standing in the middle of this dimly lit chamber, you 
  413.         realize that just maybe you should've splurged on a 
  414.         more expensive flashlight.  You also realize that there 
  415.         are four ways you can go:  a marble archway to the north, 
  416.         a muddy cave opening to the east, ";
  417.         if oakdoor is not blown_open
  418.             "an oak door set in a brick frame";
  419.         else
  420.             "an empty brick frame where the oak door used to be";
  421.         " to the southeast, and west back outside where you came 
  422.         from."
  423.     }
  424.     w_to {return vaultdoor.door_to}
  425.     out_to {return vaultdoor.door_to}
  426.     se_to {return oakdoor.door_to}
  427.     n_to objectroom
  428.     e_to characterroom
  429.     in_to {"You'll have to be a little more specific about which way 
  430.         you want to go."}
  431.     is not light
  432.     after
  433.     {
  434.         location DoGo
  435.             
  436.             ! changes the way the vault is refered to from 
  437.             ! "a vault" to "the vault"--a stylistic thing
  438.  
  439.         {
  440.             outsidevault.name = "outside the vault"  
  441.             return false
  442.         }
  443.     }
  444.     vehicle_path minecar    ! i.e. the mine car can travel here
  445. }
  446.  
  447.  
  448. ! minecar
  449. !
  450. ! This is an excellent example of a basic vehicle from OBJLIB.H.  The 
  451. ! vehicle_verbs property must mirror the valid words provided in the 
  452. ! verb grammar at the start of this file.  The vehicle_move property is 
  453. ! checked before the vehicle is allowed to move.  (This is where, for 
  454. ! example, a car object would be checked to make sure that the ignition 
  455. ! is turned on, or the tires aren't flat, etc.)  Any room in which travel 
  456. ! in the mine car is permitted must have minecar in its vehicle_path 
  457. ! property.
  458.  
  459. vehicle minecar "mine car"
  460. {
  461.     in insidevault
  462.     nouns "car", "cart"
  463.     adjectives "mine", "my", "old"  ! because:  synonym "mine" for "my"
  464.                     ! in HUGOLIB.H
  465.     article "a"
  466.     vehicle_verbs "roll", "drive", "steer", "ride"
  467.     vehicle_move
  468.     {
  469.         ! Here, the mine car will not roll until the big rock is
  470.         ! removed from under it.  Note that the rock is not actually
  471.         ! under the car, but looking under the car moves it from
  472.         ! the nothing object to the room object.
  473.         
  474.         if bigrock in nothing
  475.             {"Something seems to be stopping the mine car 
  476.             from rolling."
  477.             return false}
  478.     }
  479.     initial_desc
  480.         {"An old mine car sits abandoned to one side."}
  481.     long_desc
  482.         {"It was probably used to haul rocks during the 
  483.         excavation of the original Hugo.  You could probably 
  484.         get in it."}
  485.     contains_desc
  486.         {"The old mine car is loaded with";}
  487.     before
  488.     {
  489.         object DoClimb
  490.             {Perform(&DoEnter, self)}
  491.         object DoLookUnder
  492.         {
  493.             ! The big rock initially begins the game in nothing;
  494.             ! looking under the mine car moves it inside the
  495.             ! vault.
  496.             
  497.             if bigrock not in nothing
  498.                 "You don't find anything else."
  499.             else
  500.             {
  501.                 "You find a big rock lodged between the 
  502.                 wheels, which you manage to wrestle out of 
  503.                 the way."
  504.                 move bigrock to insidevault
  505.             }
  506.         }
  507.     }
  508.     after
  509.     {
  510.         object DoEnter
  511.         {
  512.             pencil is known
  513.             return false
  514.         }
  515.     }
  516.     capacity 100
  517.     holding 0
  518.     reach minecar                   ! can't reach things outside the car
  519.     is container, open, static
  520.  
  521.     ! Because the mine car has the quiet attribute set, its contents
  522.     ! (i.e. the pencil) are not immediately obvious--they are not 
  523.     ! listed by WhatsIn until the player specifically looks inside.
  524.  
  525.     is quiet
  526.  
  527.     ! Also, it is mobile and therefore may be pulled by the rope. 
  528.  
  529.     is mobile
  530.     attach_immobile                 ! returns false if the car is mobile
  531.     {
  532.         if bigrock in nothing
  533.             "Something seems to be stopping the mine car 
  534.             from rolling."
  535.         else:  return false
  536.     }
  537. }
  538.  
  539. object bigrock "big rock"
  540. {
  541.     nouns "rock", "stone"
  542.     adjectives "big", "large", "huge"
  543.     article "a"
  544.     after
  545.     {
  546.         object DoGet
  547.             {"Oof.  It's a struggle, but you manage to 
  548.             pick it up."}
  549.     }
  550.     size 50
  551. }
  552.  
  553. !----------------------------------------------------------------------------
  554. ! THE OBJECT ROOM
  555. !----------------------------------------------------------------------------
  556. room objectroom "Object Room"
  557. {
  558.     article "the"
  559.     prep "in"
  560.     s_to insidevault
  561.     out_to insidevault
  562.     long_desc
  563.     {
  564.         "This room contains a collection of objects with different 
  565.         properties, attributes, and associated routines in order 
  566.         to give some idea of basic object design.  In addition to 
  567.         the various furnishings, you notice a dartboard hanging on 
  568.         one wall."
  569.     }
  570.     vehicle_path minecar
  571.     is not light
  572. }
  573.  
  574. ! chair
  575. !
  576. ! Try sitting in it.
  577.  
  578. object chair "wooden chair"
  579. {
  580.     in objectroom
  581.     noun "chair"
  582.     adjective "wooden"
  583.     article "a"
  584.     reach cardtable         ! i.e. only the chair and the card table
  585.                 ! may be reached from the chair
  586.     is enterable, static
  587. }
  588.  
  589.  
  590. ! cardtable
  591. !
  592. ! Try sitting on it.  (You can't--it's not enterable.)  But it can hold
  593. ! things on its surface.
  594.  
  595. object cardtable "card table"
  596. {
  597.     in objectroom
  598.     nouns "table", "cardtable"
  599.     adjective "card"
  600.     article "a"
  601.     capacity 50
  602.     holding 0
  603.     is platform, static
  604. }
  605.  
  606.  
  607. ! deckofcards and playingcard
  608. !
  609. ! A rather unimpressive example of how to extract a single object from
  610. ! a group of similar objects.  Pick a card, any card.
  611.  
  612. object deckofcards "playing cards"
  613. {
  614.     in cardtable
  615.     noun "cards"
  616.     adjective "deck", "playing"
  617.     article "some"
  618.     initial_desc
  619.         {"A deck of playing cards has been placed appropriately 
  620.         on the table."}
  621.     size 10
  622.     is plural
  623. }
  624.  
  625. object card "playing card"
  626. {
  627.     found_in deckofcards
  628.     noun "card" , "diamonds"
  629.     adjective "playing", "nine"
  630.     article "a"
  631.     size 5
  632.     long_desc {"It's the nine of diamonds."}
  633.     after
  634.     {
  635.         object DoGet
  636.         {
  637.             if object.found_in ~= false
  638.             {
  639.                 object.found_in = false
  640.                 "You deal the nine of diamonds."
  641.                 object.name = "nine of diamonds"
  642.                 object.article = "the"
  643.             }
  644.             else
  645.                 return false
  646.         }
  647.     }
  648. }
  649.  
  650.  
  651. ! goldcoins
  652. !
  653. ! A simple demonstration of identical_class from OBJLIB.H.  The coins can 
  654. ! be referred to individually, by number (i.e. "two coins"), or as a 
  655. ! group ("the coins").
  656.  
  657. identical_class goldcoins "shiny gold coins"
  658. {
  659.     article "some"
  660.     nouns "coins"
  661.     adjectives "shiny", "gold"
  662.     single_noun "coin"
  663.     long_desc
  664.         "Shiny and gold:  both admirable qualities in a coin."
  665.     plural_of coin1, coin2, coin3
  666. }
  667.  
  668. object coin1 "shiny gold coin"
  669. {
  670.     in cardtable
  671.     article "a"
  672.     noun "coin"
  673.     adjectives "shiny", "gold"
  674.     identical_to goldcoins
  675. }
  676.  
  677. coin1 coin2 "shiny gold coin"           ! copy coin1 to coin2
  678. {
  679.     in cardtable
  680. }
  681.  
  682. coin1 coin3 "shiny gold coin"
  683. {
  684.     in cardtable
  685. }
  686.  
  687.  
  688. ! mittens
  689. !
  690. ! Try wearing them.  Try writing when you're wearing them.
  691.  
  692. object mittens "pair of mittens"
  693. {
  694.     in transparentbox
  695.     nouns "mitten", "mittens"
  696.     adjective "pair"
  697.     article "a"
  698.     size 10
  699.     initial_desc
  700.         {"A pair of mittens is inside the transparent box."} 
  701.     is clothing
  702. }
  703.  
  704.  
  705. ! box
  706. !
  707. ! The basic box class is used by transparentbox and opaquebox.  The boxes
  708. ! plural_class (from OBJLIB.H) exists only to allow the boxes to be referred 
  709. ! to as a group.
  710.  
  711. plural_class boxes "boxes"
  712. {
  713.     article "some"
  714.     noun "boxes"
  715.     single_noun "box"
  716.     plural_of transparentbox, opaquebox
  717. }
  718.  
  719. class box "box"
  720. {
  721.     noun "box"
  722.     article "a"
  723.     size 20
  724.     capacity 20
  725.     holding 0
  726.     long_desc
  727.     {
  728.         if self is open
  729.             "It's open."
  730.         else
  731.             "It's closed."
  732.     }
  733.     after
  734.     {
  735.         ! This after routine replaces the normal library "Taken."
  736.         ! response whenever a box object is the parent of the
  737.         ! taken object.
  738.         
  739.         parent(object) DoGet
  740.         {
  741.             print "You take "; The(object); " out of "; \
  742.             The(self); "."
  743.         }
  744.     }
  745.     plural_is boxes
  746.     is openable, not open, container
  747. }
  748.  
  749.  
  750. ! transparentbox
  751. !
  752. ! Try getting something out of it when it's closed, even if you can see
  753. ! the contents.  Then try putting the flashlight in here and closing it.
  754.  
  755. box transparentbox "transparent box"
  756. {
  757.     in objectroom
  758.     adjective "transparent", "clear"
  759.     is transparent
  760. }
  761.  
  762.  
  763. ! opaquebox
  764. !
  765. ! Now try putting the flashlight in here and closing it.  The library does
  766. ! all the work of checking to see if the DoClose verb routine hides the
  767. ! light source in the room.
  768.  
  769. box opaquebox "opaque box"
  770. {
  771.     in objectroom
  772.     adjective "opaque"
  773.     article "an"
  774. }
  775.  
  776. box largedrum "large drum"
  777. ! the special attribute is set once it has been opened
  778. {
  779.     in objectroom
  780.     nouns "drum", "can", "barrel"
  781.     adjectives "large", "big", "larger"
  782.     short_desc
  783.     {
  784.         "A large drum--not the musical kind--is here.  ";
  785.         if warningnote is hidden
  786.         {
  787.             "Attached to it is a warning note."
  788.             warningnote is known
  789.             warningnote is already_listed
  790.         }
  791.         print newline
  792.     }
  793.     long_desc
  794.         {"It's one of those big barrels used for storing and shipping 
  795.         oil, chemicals, and other hazardous materials.  Hint."}
  796.     before
  797.     {
  798.         object DoGet
  799.             {"It's much too heavy to take."}
  800.     }
  801.     after
  802.     {
  803.         object DoOpen
  804.         {
  805.             ! if drum hasn't been opened the first time
  806.             if self is not special
  807.             {
  808.                 "Ignoring all warnings to the contrary, you 
  809.                 open the drum.  Inside is another, smaller 
  810.                 drum, as well as a second warning note."
  811.                 self is special
  812.                 smalldrum is known
  813.                 warningnote.name = "first warning note"
  814.             }
  815.             else
  816.                 return false
  817.         }
  818.     }
  819. }
  820.  
  821. plural_class notes "notes"
  822. {
  823.     nouns "notes", "paper"
  824.     adjectives "warning", "pieces"
  825.     single_noun "note"
  826. }
  827.  
  828. object warningnote "warning note"
  829. {
  830.     in objectroom
  831.     nouns "note", "paper"
  832.     adjectives "warning", "first", "piece"
  833.     article "a"
  834.     long_desc
  835.         {"\"Do not open this drum.  Whatever you do, don't open 
  836.         this drum.  Do not.  Open.  This drum.\""}
  837.     before
  838.     {
  839.         object DoGet
  840.             {self is not hidden
  841.             return false}
  842.     }
  843.     plural_is notes
  844.     is readable, hidden
  845. }
  846.  
  847. box smalldrum "smaller drum"
  848. ! the special attribute is set once the bomb has been found
  849. {
  850.     in largedrum
  851.     nouns "drum", "can", "barrel"
  852.     adjectives "small", "smaller", "little"
  853.     long_desc
  854.     {
  855.         "It's a smaller version of the first drum";
  856.         if secondnote is hidden
  857.         {
  858.             " (with a second warning note attached, of course)";
  859.             secondnote is known
  860.             secondnote is already_listed
  861.         }
  862.         print "."
  863.     }
  864.     before
  865.     {
  866.         object DoGet
  867.             {"Small is a relative term here.  It's still too 
  868.             big to pick up."}
  869.     }
  870.     after
  871.     {
  872.         object DoOpen
  873.         {
  874.             if self is not special   ! if bomb hasn't been found
  875.             {
  876.                 "You find a bomb.  What luck."
  877.                 self is special
  878.                 bomb is known
  879.                 Activate(bomb_fuse, 10)
  880.                 score = score + 10
  881.                 rank = 2
  882.             }
  883.             else
  884.                 return false
  885.         }
  886.     }
  887. }
  888.  
  889. object secondnote "second warning note"
  890. {
  891.     in largedrum
  892.     nouns "note", "paper"
  893.     adjectives "warning", "second", "piece"
  894.     article "a"
  895.     long_desc
  896.         {"\"You listen well.  But this time we mean it.  Don't open 
  897.         this drum.\""}
  898.     before
  899.     {
  900.         object DoGet
  901.         {
  902.             self is not hidden
  903.             return false
  904.         }
  905.     }
  906.     plural_is notes
  907.     is readable, hidden
  908. }
  909.  
  910. object bomb "bomb"
  911. {
  912.     in smalldrum
  913.     nouns "bomb"
  914.     article "a"
  915.     long_desc
  916.         {"Just your typical, garden-variety bomb."}
  917. }
  918.  
  919.  
  920. ! bomb_fuse
  921. !
  922. ! This fuse begins running as soon as the player opens the small drum.
  923. ! It prints a message only when it is within earshot or view of the player,
  924. ! but keeps ticking regardless.
  925.  
  926. fuse bomb_fuse
  927. {}
  928.  
  929. event bomb_fuse
  930. {
  931.     if bomb in player                       ! player is holding it
  932.         {"\nThe bomb you're holding is ticking."
  933.         event_flag = true}
  934.     elseif FindObject(bomb, location)       ! bomb is visible in the room
  935.         {"\nThe bomb is ticking."
  936.         event_flag = true}
  937.     elseif Contains(location, bomb)         ! bomb is otherwise in room
  938.         {"\nYou hear a ticking noise."
  939.         event_flag = true}
  940.  
  941.     if not self.tick                        ! when self.timer = 0
  942.     {
  943.         if Contains(location, bomb)     ! if in player's location
  944.         {
  945.             "\nKABOOM!\n\n\
  946.             (Right next to the bomb was not, as they say, such 
  947.             a great place to be as it went off.  You're dead now.)"
  948.             
  949.             endflag = 2     ! when endflag is non-false, it
  950.                     ! immediately triggers the end of the
  951.                     ! game
  952.         }
  953.         else
  954.         {
  955.             "\nYou hear a muffled kaboom."
  956.             event_flag = true
  957.             if bomb in insidevault
  958.             {
  959.                 oakdoor is blown_open
  960.                 oakdoor is not openable
  961.                 oakdoor is not hidden
  962.                 score = score + 10
  963.                 
  964.                 ! The following activates the dwarf's 
  965.                 ! script with eleven steps; the DwarfDropBall
  966.                 ! ensures that she drops whatever she was 
  967.                 ! holding before going anywhere.
  968.                 
  969.                 setscript[script(dwarf,11)] = \
  970.                     &CharMove, s_obj, 
  971.                     &CharMove, w_obj, 
  972.                     &CharWait, nothing, 
  973.                     &CharShakeHead, oakdoor, 
  974.                     &CharWait, nothing, 
  975.                     &CharMove, n_obj, 
  976.                     &CharWait, nothing, 
  977.                     &CharShakeHead, largedrum, 
  978.                     &CharMove, s_obj, 
  979.                     &CharMove, e_obj, 
  980.                     &CharMove, n_obj
  981.                 DwarfDropBall
  982.             }
  983.             remove bomb
  984.             Deactivate(bomb_fuse)
  985.         }
  986.     }
  987. }
  988.  
  989.  
  990. attribute written alias special         ! for the pad only
  991. array writing[65]                       ! up to 64 characters of writing
  992.  
  993. ! pad
  994. !
  995. ! Try:  write "something" on paper.
  996.  
  997. object pad "pad of paper"
  998. {
  999.     in cardtable
  1000.     article "a"
  1001.     nouns "paper"
  1002.     adjective "pad", "regular", "writing"
  1003.     long_desc
  1004.     {
  1005.         "It's a regular pad of writing paper.  ";
  1006.         if self is written
  1007.         {
  1008.             "Written on it is:  \"";
  1009.             print StringPrint(writing); "\"."
  1010.         }
  1011.         else:  "It's blank."
  1012.         print newline
  1013.     }
  1014.     is readable
  1015. }
  1016.  
  1017. object pencil "pencil"
  1018. {
  1019.     in minecar
  1020.     article "a"
  1021.     noun "pencil"
  1022.     adjective "wooden"
  1023.     long_desc
  1024.         "Not just a wooden pencil, but a magical wooden pencil, 
  1025.         which one might use, perhaps, to name a hitherto unnamed 
  1026.         object."
  1027.     size 5
  1028. }
  1029.  
  1030.  
  1031. ! unnamedobject
  1032. !
  1033. ! The unnamed object can be given a name by the player--i.e. have a word
  1034. ! written on it by which the object may be referred to--in order to
  1035. ! demonstrate the DICT command.
  1036.  
  1037. object unnamedobject "unnamed object"
  1038. ! the special attribute is set once the player has given it a name
  1039. {
  1040.     in objectroom
  1041.     article "an"
  1042.     noun "object"
  1043.     adjective "unnamed", "non-descript", "nondescript"
  1044.     misc 0                          ! will eventually contain the non-
  1045.                     ! case-altered version of the name
  1046.     initial_desc
  1047.         "Lying in the corner of the room is a non-descript, 
  1048.         unnamed object."
  1049.     short_desc
  1050.         print "The "; self.name; " is here."
  1051.     long_desc
  1052.     {
  1053.         "Nothing special about it.  You can't even tell what it 
  1054.         might be for.";
  1055.         if self is special
  1056.             {"  Written on the side of it is:  \"";
  1057.             print object.misc; "\".";}
  1058.         print newline
  1059.     }
  1060.     is openable, clothing, switchable
  1061. }
  1062.  
  1063. scenery dartboard "old dartboard"
  1064. {
  1065.     in objectroom
  1066.     article "a"
  1067.     noun "dartboard", "board"
  1068.     adjective "old", "dart"
  1069.     short_desc
  1070.         "Hanging on one wall is an old dartboard."
  1071.     is static
  1072. }
  1073.  
  1074.  
  1075. ! dart
  1076. !
  1077. ! The dart can be attached to the dartboard either by sticking it in or
  1078. ! throwing it.  Since the attach_take property is true, the dart is released
  1079. ! when attached and taken when detached.
  1080.  
  1081. attachable dart "green dart"
  1082. {
  1083.     in objectroom
  1084.     article "a"
  1085.     noun "dart"
  1086.     adjective "green"
  1087.     size 5
  1088.     attach_verb "stick", "throw"
  1089.     detach_verb "get"
  1090.     attach_prep "in"
  1091.     attached_desc "sticking out of"
  1092.     attach_take true
  1093.     attach_drop true
  1094.     attached_to dartboard           ! space for one attachment
  1095.     attachable_to dartboard
  1096.     before
  1097.     {
  1098.         object DoThrowAt
  1099.         {
  1100.             if xobject is living
  1101.                 "Trying to start something, are we?"
  1102.             else
  1103.                 Perform(&DoAttachObject, object, xobject)
  1104.         }
  1105.     }
  1106. }       
  1107.  
  1108.  
  1109. ! rope
  1110. !
  1111. ! The rope is another attachable--but unlike the dart, because attach_take
  1112. ! is not set to true, it may still be carried after being attached to another
  1113. ! object.  Since the minecar has the mobile attribute set, it may be pulled
  1114. ! around; the chair and cardtable, however, may not.
  1115.  
  1116. attachable rope "heavy rope"
  1117. {
  1118.     in objectroom
  1119.     article "a"
  1120.     nouns "rope", "twine"
  1121.     adjective "heavy", "thick"
  1122.     attach_verbs "tie", "attach"
  1123.     detach_verbs "untie", "detach"
  1124.     attached_to chair, 0            ! space for two attachments
  1125.     attachable_to chair, cardtable, minecar
  1126. }
  1127.  
  1128.  
  1129. !----------------------------------------------------------------------------
  1130. ! THE CHARACTER ROOM AND THE BALL ROOM
  1131. !----------------------------------------------------------------------------
  1132. room characterroom "Character Room"
  1133. {
  1134.     noun "room"
  1135.     adjective "character"
  1136.     article "the"
  1137.     prep "in"
  1138.     w_to insidevault
  1139.     out_to insidevault
  1140.     n_to ballroom
  1141.     in_to ballroom
  1142.     long_desc
  1143.         {"The Character Room provides a couple of good examples of 
  1144.         character scripts and events.  Exits are north and west."}
  1145.     vehicle_path minecar
  1146. }
  1147.  
  1148.  
  1149. ! guard
  1150. !
  1151. ! Ask him about things in the game.  Try:
  1152. !
  1153. !       ask guard about the minecar
  1154. !       guard, tell me about the minecar
  1155. !       guard, what about the minecar?
  1156. !
  1157. ! Or, once you've begun talking to him, simply:
  1158. !
  1159. !       tell me about...
  1160. !       what about...
  1161.  
  1162. character guard "burly guard"
  1163. {
  1164.     in characterroom
  1165.     noun "guard"
  1166.     adjective "burly"
  1167.     article "a"
  1168.     long_desc
  1169.         {"He's wearing a button that reads:  \"Just ask me.\""}
  1170.     before
  1171.     {
  1172.         ! The guard is the object, since the question is asked as:
  1173.         ! "ask <object> about <xobject>".
  1174.         
  1175.         object DoAsk
  1176.         {
  1177.             select xobject
  1178.             case minecar
  1179.                 "\"You bring that in here, and you're asking 
  1180.                 for trouble.\""
  1181.             case ballroom
  1182.                 "\"Don't let me catch you taking none of them 
  1183.                 there balls out of the Ball Room.\""
  1184.             case bomb
  1185.                 "\"I don't know what kind of loopy nut 
  1186.                 would want to be carting a bomb in here.\""
  1187.             case dwarf
  1188.                 {"\"She's a short little one.  Kinda strange, 
  1189.                 I have to say.  Spends all her time in there 
  1190.                 just a-kickin' away.  I think she's mad 
  1191.                 'cause she lost her magic wand.\""
  1192.                 wand is known}
  1193.             case wand
  1194.                 "\"Wish I had one.\""
  1195.             case oakdoor
  1196.                 "\"I have no idea how to get that thing 
  1197.                 open.  The only way would be to blast it, 
  1198.                 if you had something to blast it with...\""
  1199.             case you
  1200.                 "The guard doesn't think too much of you."
  1201.             case guard
  1202.                 "I wouldn't pry if I were you."
  1203.             case else
  1204.                 return false
  1205.         }
  1206.     }
  1207. }
  1208.  
  1209.  
  1210. ! This object-linked event is checked only when the guard is in the player's
  1211. ! location.
  1212.  
  1213. event guard
  1214. {
  1215.     if minecar in location
  1216.     {
  1217.         "\nThe guard lifts his big boot up to the mine car and gives 
  1218.         you a firm shove back out the door.  \"Not in that thing, 
  1219.         you don't, pal!\""
  1220.         if player in minecar
  1221.         {
  1222.             move minecar to insidevault
  1223.             location = insidevault
  1224.             PrintStatusLine
  1225.         }
  1226.         else
  1227.         {MovePlayer(insidevault)
  1228.         MoveAllAttachables(player, characterroom, insidevault, true)
  1229.         }
  1230.     }
  1231.     if Contains(player, bomb)
  1232.     {
  1233.         "\nThe guard grabs you and throws you back out the door.  \
  1234.         \"Get out of here with that bomb, pal!\"  An unsubtle 
  1235.         approach, yes, but one that works."
  1236.         MovePlayer(insidevault)
  1237.     }
  1238.     if Contains(player, soccerball) or Contains(player, basketball)
  1239.     {
  1240.         "\nThe guard grabs you and throws you back out the door.  \
  1241.         \"Read the sign, pal!  They call it the Ball Room for a 
  1242.         reason.  Keep 'em in there!\""
  1243.         MovePlayer(ballroom)
  1244.     }
  1245. }
  1246.  
  1247. room ballroom "Ball Room"
  1248. {
  1249.     noun "room", "ballroom"
  1250.     adjective "ball"
  1251.     article "the"
  1252.     prep "in"
  1253.     s_to characterroom
  1254.     out_to characterroom
  1255. }
  1256.  
  1257.  
  1258. ! This event runs whenever the player is in the ballroom.
  1259.  
  1260. event ballroom                          ! the dwarf plays with the balls
  1261. {
  1262.     local a
  1263.     
  1264.     if dwarf in ballroom
  1265.     {
  1266.         a = random(6)           ! 1 to 6
  1267.         select a
  1268.             case 1
  1269.                 DwarfGetBall(soccerball)
  1270.             case 2
  1271.                 DwarfGetBall(basketball)
  1272.             case 3, 4
  1273.                 DwarfDropBall
  1274.             case else
  1275.             {
  1276.                 if child(dwarf)
  1277.                 {
  1278.                     "\nThe dwarf winds up and gives the ";
  1279.                     print child(dwarf).name;
  1280.                     " a kick.  It ricochets off the wall 
  1281.                     and bounces back to her."
  1282.                     event_flag = true
  1283.                 }
  1284.             }
  1285.     }               
  1286. }
  1287.  
  1288. routine DwarfDropBall
  1289. {
  1290.     if child(dwarf)
  1291.     {
  1292.         "\nThe dwarf drops the ";
  1293.         print child(dwarf).name; "."
  1294.         move child(dwarf) to ballroom
  1295.         event_flag = true
  1296.     }
  1297. }
  1298.  
  1299. routine DwarfGetBall(obj)
  1300. {
  1301.     if obj in ballroom
  1302.     {
  1303.         DwarfDropBall
  1304.         move obj to dwarf
  1305.         "\nThe dwarf picks up the ";
  1306.         print obj.name; "."
  1307.         event_flag = true
  1308.     }
  1309.     else                            ! player must have ball obj
  1310.     {
  1311.         if obj = basketball     ! so try to choose the other ball
  1312.             obj = soccerball
  1313.         else
  1314.             obj = basketball
  1315.  
  1316.         if obj not in ballroom  ! player must have both balls
  1317.             "\nThe dwarf looks at you impatiently and more than 
  1318.             a little accusingly, waiting for you to give her 
  1319.             back her balls."
  1320.     }
  1321. }
  1322.  
  1323. plural_class balls "balls"
  1324. {
  1325.     article "some"
  1326.     noun "balls"
  1327.     single_noun "ball"
  1328.     plural_of soccerball, basketball
  1329. }
  1330.  
  1331. object soccerball "checkered soccer ball"
  1332. {
  1333.     type balls                      ! for identification as a ball
  1334.     in ballroom
  1335.     nouns "ball", "soccerball"
  1336.     adjective "soccer", "checkered"
  1337.     article "a"
  1338.     before
  1339.     {
  1340.         object DoGet
  1341.         {
  1342.             if self in dwarf        ! if she's holding it
  1343.                 {"The dwarf shakes a fist at you and 
  1344.                 mutters, \"Get your own, kid.\""}
  1345.             else
  1346.                 return false
  1347.         }
  1348.     }
  1349.     plural_is balls
  1350. }
  1351.  
  1352. soccerball basketball "orange basketball"       ! copy the other ball object
  1353. {
  1354.     in ballroom
  1355.     nouns "ball", "basketball"
  1356.     adjective "basket", "orange"
  1357.     article "an"
  1358. }
  1359.  
  1360. female_character dwarf "little dwarf"
  1361. {
  1362.     in ballroom
  1363.     noun "dwarf"
  1364.     adjective "little"
  1365.     article "a"
  1366.     order_response          ! i.e. "dwarf, (do something)", such as
  1367.     {                       ! "dwarf, kick ball"
  1368.         
  1369.         if verbroutine = &DoPunt
  1370.         {
  1371.             if object.type ~= balls
  1372.                 {"The dwarf looks at you like you're nuts."
  1373.                 return true}
  1374.             if object in player
  1375.                 {"(first giving the ball to her)"
  1376.                 if child(dwarf)
  1377.                     move child(dwarf) to location
  1378.                 move object to dwarf}
  1379.             
  1380.             if object not in dwarf
  1381.                 {"The dwarf shrugs.  \"I would, but I don't 
  1382.                 have "; 
  1383.                 print The(object); ".\""}
  1384.             else
  1385.                 {"The dwarf winds up and gives the ";
  1386.                 print object.name;
  1387.                 " a kick.  It ricochets off the wall and 
  1388.                 bounces back to her."}
  1389.         }
  1390.         else
  1391.             return false
  1392.     }
  1393.     after
  1394.     {
  1395.         object DoAsk
  1396.         {
  1397.             if xobject = wand
  1398.                 "\"I'd like to have it back.\""
  1399.             else
  1400.                 return false
  1401.         }
  1402.         object DoTell
  1403.         {
  1404.             if xobject = wand
  1405.                 "\"I'd like to have it back.\""
  1406.             else
  1407.                 return false
  1408.         }
  1409.         
  1410.         ! In this case, the dwarf is the xobject, since the command
  1411.         ! is given as:  "show <object> to <xobject>". 
  1412.         
  1413.         xobject DoShow
  1414.         {
  1415.             if object = wand
  1416.                 "\"Give that to me!\""
  1417.             else
  1418.                 return false
  1419.         }
  1420.         xobject DoGive
  1421.         {
  1422.             if object = wand
  1423.             {
  1424.                 "\"Thank you!  I've been looking for 
  1425.                 that.\"  The dwarf takes the wand and bonks 
  1426.                 you a little roughly on the head with it, 
  1427.                 transporting you back to your nice, warm bed."
  1428.                 rank = 4
  1429.                 score = score + 10
  1430.                 endflag = 1     
  1431.             }
  1432.             else
  1433.                 return false
  1434.         }
  1435.     }
  1436. }
  1437.  
  1438. routine CharShakeHead
  1439. {
  1440.     local char, obj
  1441.     if char in location
  1442.         print CThe(char); " shakes her head at "; The(obj); "."
  1443. }
  1444.  
  1445. !----------------------------------------------------------------------------
  1446. ! BRICK ROOM
  1447. !----------------------------------------------------------------------------
  1448.  
  1449. ! Special attribute for the oak door:
  1450. attribute blown_open alias special
  1451.  
  1452. object oakdoor "oak door"       ! a little more complicated door object
  1453. {
  1454.     in insidevault
  1455.     noun "door", "doorway"
  1456.     adjective "oak"
  1457.     article "an"
  1458.     short_desc
  1459.         {"Lying on the floor is the oak door."}
  1460.     door_to
  1461.     {
  1462.         if self is not blown_open
  1463.             "The oak door is locked up tight as a drum."
  1464.         else
  1465.             return brickroom
  1466.     }
  1467.     vehicle_path minecar
  1468.                
  1469.     ! Setting key_object to a non-zero value means the door is not 
  1470.     ! openable without a key.  In this case, the ! key is 
  1471.     ! technically object 1, which doesn't exist in the game.  So 
  1472.     ! for all intents and purposes, the player can never unlock 
  1473.     ! this door.  (It has to be blown open.)
  1474.     
  1475.     key_object 1
  1476.  
  1477.     is static, openable, not open, lockable, locked
  1478.  
  1479.     ! Since the door is hidden at the outset, its short_desc is
  1480.     ! not printed (until the door is blown open).
  1481.  
  1482.     is hidden
  1483. }
  1484.  
  1485. room brickroom "Brick Room"
  1486. {
  1487.     noun "room"
  1488.     adjective "brick"
  1489.     article "the"
  1490.     prep "in"
  1491.     long_desc
  1492.         {"This room is finished entirely in brick masonry.  Good, 
  1493.         solid workmanship.  You can head back out to the northwest."}
  1494.     nw_to insidevault
  1495.     out_to insidevault
  1496. }
  1497.  
  1498. object trophy "shining golden trophy"
  1499. {
  1500.     in brickroom
  1501.     nouns "award", "trophy", "inscription"
  1502.     adjectives "shining", "golden"
  1503.     article "a"
  1504.     initial_desc
  1505.         {"A shining golden trophy--an award for your efforts--is 
  1506.         here.  It bears an inscription."}
  1507.     long_desc
  1508.         {"Congratulations for solving this sample game's one and 
  1509.         only major puzzle.  (Although it really wasn't that hard, 
  1510.         was it?  And you probably don't deserve such a nice shining
  1511.         golden trophy.)"}
  1512.     after
  1513.     {
  1514.         object DoGet
  1515.         {
  1516.             if parent(letter) = nothing
  1517.                 {"As you pick up the trophy, a magic wand 
  1518.                 falls to the ground, and a small piece of 
  1519.                 paper flutters down after it."
  1520.                 move wand to brickroom
  1521.                 move letter to brickroom
  1522.                 rank = 3}
  1523.  
  1524.             else
  1525.                 return false
  1526.         }
  1527.     }
  1528.     is readable
  1529. }
  1530.  
  1531. object letter "handwritten letter"
  1532. {
  1533.     nouns "paper", "letter"
  1534.     adjective "handwritten", "piece"
  1535.     article "a"
  1536.     long_desc
  1537.         {"It's a letter from the author of this sample game.  Goes 
  1538.         something like this:\n\n\"Give this to the dwarf to solve 
  1539.         the game.\"  Nothing fancy, but I'm sure it was late 
  1540.         when he was writing this."}
  1541.     is readable
  1542. }
  1543.  
  1544. object wand "magic wand"
  1545. {
  1546.     noun "wand"
  1547.     adjective "magic", "twinkling"
  1548.     article "a"
  1549.     short_desc {"A magic wand is twinkling on the floor here."}
  1550.     long_desc 
  1551.         {"\"The official magic wand of social democrats 
  1552.         everywhere.\""}
  1553.     before
  1554.     {
  1555.         object DoWave
  1556.         {
  1557.             "You wave the magic wand, a cloud of orange mist 
  1558.             appears, and...\n\n...Aw, forget it.  I'm just 
  1559.             kidding.  What makes you think you know what to 
  1560.             do with a magic wand, anyway?"
  1561.         }
  1562.     }
  1563. }
  1564.  
  1565. !----------------------------------------------------------------------------
  1566. ! NEW VERB ROUTINES
  1567. !----------------------------------------------------------------------------
  1568.  
  1569. routine DoPunt
  1570. {
  1571.     if object is living
  1572.         "Oh, good.  Real good.  Pick a fight, now.  That's really 
  1573.         going to get you places."
  1574.     elseif object.type ~= balls
  1575.         "You won't get very far trying to kick that around."
  1576.     else
  1577.     {
  1578.         "You wind up and give ";
  1579.         The(object)
  1580.         " a good boot.  ";
  1581.         if dwarf in ballroom
  1582.             "The dwarf nods approvingly."
  1583.         else
  1584.             print newline
  1585.         move object to ballroom
  1586.         player.holding = player.holding - object.size
  1587.     }
  1588.     return true
  1589. }
  1590.  
  1591. routine DoWriteOn       ! response to an improperly phrased command
  1592. {
  1593.     if xobject and xobject ~= pencil
  1594.         {"You can't write with ";
  1595.         print The(xobject); "!"}
  1596.     elseif object ~= pad and object ~= unnamedobject
  1597.         {"There's not much point in defacing ";
  1598.         print The(object); "."}
  1599.     else
  1600.         "You'll have to be a little more specific about exactly 
  1601.         what you'd like to write.  Try:  'write \"something\".'"
  1602. }
  1603.  
  1604. routine DoWrite
  1605. {
  1606.     local len
  1607.  
  1608.     if not xobject
  1609.     {
  1610.         if pencil not in player
  1611.             {"You're not holding anything to write with."
  1612.             return false}
  1613.         else
  1614.             xobject = pencil
  1615.     }
  1616.     if not object
  1617.     {
  1618.         if FindObject(pad, location) ~= 1
  1619.             {"Nothing to write on."
  1620.             return false}
  1621.         else
  1622.             object = pad
  1623.     }
  1624.  
  1625.     if xobject ~= pencil or (object ~= pad and object ~= unnamedobject)
  1626.         {DoWriteOn
  1627.         return}
  1628.     elseif mittens is worn
  1629.         "Good luck writing with those mittens on."
  1630.     elseif object = unnamedobject
  1631.         return Perform(&DoName, unnamedobject)
  1632.     else
  1633.     {
  1634.         if pad is written
  1635.             {"You scratch out \"";
  1636.             print StringPrint(writing); "\" and ";}
  1637.         else:  "You ";
  1638.         
  1639.         ! Read the engine parse$ into the writing[] array, to a
  1640.         ! maximum of 64 characters
  1641.  
  1642.         len = string(writing, parse$, 64)
  1643.         
  1644.         print word[1]; " \""; StringPrint(writing); "\"";
  1645.         " on the pad."
  1646.         pad is written
  1647.     }
  1648.     return true
  1649. }
  1650.  
  1651.  
  1652. ! Notice that the DoName routine only allows the player to create one new
  1653. ! entry in order to avoid overrunning MAXDICTEXTEND.
  1654.  
  1655. array name_array[50]
  1656.  
  1657. routine DoName
  1658. {
  1659.     if object is special
  1660.         {"You already named it ";
  1661.         The(object)
  1662.         "--don't go changing your mind now."}
  1663.     elseif pencil not in player
  1664.         "Would help if you were holding something to write that 
  1665.         on the object, so you'll remember it."
  1666.     else
  1667.     {
  1668.         local i, len
  1669.         
  1670.         len = string(name_array, parse$, 49)    ! maximum 49 char.
  1671.         for (i=0; i<len; i=i+1)
  1672.         {
  1673.             ! Because the parser cannot recognize multiple
  1674.             ! words...
  1675.             if name_array[i] = ' '          ! a space
  1676.                 {"Better keep it to one word."
  1677.                 return}
  1678.  
  1679.             ! ...or non-alphanumeric characters (a table of
  1680.             ! ASCII values will show why these are the 
  1681.             ! boundaries)
  1682.  
  1683.             if name_array[i] < '0' or name_array[i] > 'z' or
  1684.               (name_array[i] > '9' and name_array[i] < 'A') or
  1685.               (name_array[i] > 'Z' and name_array[i] < 'a'):
  1686.                 {"Better to keep the fancy punctuation 
  1687.                 out of it."
  1688.                 return}
  1689.         }
  1690.  
  1691.         "You write \"";
  1692.         StringPrint(name_array)
  1693.         "\" on the object."
  1694.         
  1695.         ! The misc property contains the non-case-corrected version
  1696.         ! of the name.
  1697.         
  1698.         object.misc = dict(name_array, 49)
  1699.         
  1700.         ! The name is converted to '"<string>" object':
  1701.         
  1702.         ! initial quote first...
  1703.         name_array[0] = '\"'
  1704.         
  1705.         ! then read parse$ into name_array (after the first quote)...
  1706.         len = string(name_array+1, parse$, 49)
  1707.         
  1708.         ! and append the last part to name_array...
  1709.         string(name_array+len+1, "\" object")
  1710.         
  1711.         ! ...before turning name_array into a dictionary entry
  1712.         object.name = dict(name_array, 49)
  1713.         
  1714.         ! Since the adjective will be referred to by the parser,
  1715.         ! it must be lowercase--name_array must also be reloaded
  1716.         ! with parse$ since it has been modified above.
  1717.         
  1718.         len = string(name_array, parse$, 49)
  1719.         for (i=0; i<len; i=i+1) ! the actual case-conversion loop
  1720.         {
  1721.             if name_array[i] >= 'A' and name_array[i] <= 'Z'
  1722.                 name_array[i] = name_array[i] + ('a'-'A')
  1723.         }
  1724.         
  1725.         ! then write the word as a dictionary entry
  1726.         object.adjective #1 = dict(name_array, 49)
  1727.  
  1728.         object.article = "the"  ! i.e. 'the "<string>" object'
  1729.         object is special
  1730.         object is moved
  1731.     }
  1732. }
  1733.  
  1734. routine DoNameWhat
  1735. {
  1736.     "Try:  name object \"(something)\"."
  1737. }
  1738.  
  1739. !----------------------------------------------------------------------------
  1740. ! REPLACE LIBRARY ROUTINES:
  1741. !----------------------------------------------------------------------------
  1742.  
  1743. global already_warned
  1744.  
  1745. replace DarkWarning
  1746. {
  1747.     if not already_warned           ! player is only warned once...
  1748.     {
  1749.         "It's pitch black in here.  Stumbling around in the dark 
  1750.         isn't such a hot idea:  you're liable to be eaten by a grue."
  1751.         already_warned = true
  1752.     }
  1753.     else                            ! ...and gets three safe moves before
  1754.     {                               ! becoming a snack for a grue
  1755.         already_warned = already_warned + 1
  1756.         if already_warned > 4
  1757.             {"You stumble around in the dark...and are eaten 
  1758.             by a grue!  Bad move.  Should've used a light."
  1759.             endflag = 2}
  1760.         else
  1761.             "You stumble around in the dark."
  1762.     }
  1763. }
  1764.  
  1765. ! Below is the new PrintScore routine.  Note that it differs from the
  1766. ! library routine in that it uses the new global rank to print the ranking.
  1767.  
  1768. replace PrintScore(end_of_game)
  1769. {
  1770.     "You ";
  1771.     if not end_of_game
  1772.         "have ";
  1773.     "scored a total of ";
  1774.     print number score; " out of "; number max_score; 
  1775.     print ", giving you the rank of "; ranking[rank]; "."
  1776. }
  1777.  
  1778.