!\--------------------------------------------------------------------------- THE VAULT OF HUGO Hugo v2.5 Tutorial Game by Kent Tessman (c) 1995-1999 ---------------------------------------------------------------------------\! #version 2.5 #set DEBUG ! include HugoFix library and grammar #set VERBSTUBS ! include verb stub routines #set USE_VEHICLES ! from OBJLIB.H #set USE_PLURAL_OBJECTS ! #set USE_ATTACHABLES ! #set NO_AUX_MATH ! don't need advanced math routines #switches -ls ! print statistics to SAMPLE.LST #ifset DEBUG #switches -d #endif ! The following limit setting reserves 512 extra bytes of dictionary space ! so that the play can name the unnamed object. A maximum 512 bytes are ! required because the game needs to write the name, adjective, and misc ! properties of the object. $MAXDICTEXTEND = 512 !---------------------------------------------------------------------------- ! NEW GRAMMAR: verb "kick", "punt", "boot" * DoVague * object DoPunt verb "board" * (minecar) DoEnter verb "roll", "drive", "steer", "ride" * DoVague * object DoMoveinVehicle * "to" object DoMoveinVehicle ! In the grammar definitions below, STRING refers to any section of the ! player's input enclosed in quotation marks. verb "write", "scribble", "scrawl", "print" * DoVague * "on" object DoWriteOn * "on" object "with" held DoWriteOn * string DoWrite * string "on" object DoWrite * string "on" object "with" held DoWrite * string "with" held DoWrite verb "name", "call", "christen" * DoVague * (unnamedobject) DoNameWhat * (unnamedobject) string DoName verb "stick" * DoVague * (dart) DoAttachObject * (dart) "in"/"on" (dartboard) DoAttachObject #include "verblib.g" ! normal verb grammar !---------------------------------------------------------------------------- #ifset PRECOMPILED_LIBRARY #link "hugolib.hlb" #else #include "hugolib.h" ! standard library routines #endif ! Normally, the library's PrintScore routine uses a MAX_SCORE/score ! formula to determine a ranking (if rankings are provided); the following ! global is used in the replaced PrintScore routine to ensure that rank is ! set by the game, not approximated by the library. global rank routine init { MAX_SCORE = 50 ranking[0] = "Amateur Adventurer" ranking[1] = "Competent Door-Unlocker" ranking[2] = "Bomb-Meddling Adventurer" ranking[3] = "Master Magic Wand Finder" ranking[4] = "The Genuine Article Sample Game Solver" MAX_RANK = 4 counter = -1 ! 1 turn before turn 0 STATUSTYPE = 1 ! score/turns TEXTCOLOR = DEF_FOREGROUND BGCOLOR = DEF_BACKGROUND SL_TEXTCOLOR = DEF_SL_FOREGROUND SL_BGCOLOR = DEF_SL_BACKGROUND prompt = ">" color TEXTCOLOR, BGCOLOR DEFAULT_FONT = PROP_ON Font(DEFAULT_FONT) cls "You brace yourself, check your flashlight, and, with \ source code in hand, prepare to enter...\n" Font(BOLD_ON) "THE VAULT OF HUGO" Font(BOLD_OFF) "An Interactive Example" print BANNER player = you location = outsidevault old_location = location move player to location ! initialize player location FindLight(location) ! whether the player can see DescribePlace(location) ! the appropriate description location is visited CalculateHolding(player) ! total size of player contents Acquire(player, flashlight) ! give the player the flashlight flashlight is known Activate(key_daemon) ! set up initial daemons InitPluralObjects } #ifset PRECOMPILED_LIBRARY replace main { #else routine main { #endif counter = counter + 1 PrintStatusLine run location.each_turn runevents RunScripts if speaking not in location ! in case the character being spoken speaking = 0 ! to leaves } player_character you "you" {} ! flashlight ! ! The flashlight is an example of a light source. The rules for ! the FindLight routine in HUGOLIB.H check to see if any light sources ! are available (starting with the room itself, then working through ! the visible contents) before deciding if the player is able to see ! in any given location. object flashlight "flashlight" { in you nouns "flashlight", "light", "torch", "lamp" adjective "flash" article "your" short_desc { CArt(self) " is here, "; if self is switchedon "glowing brightly." else "turned off." } long_desc { "It's one of those disposable kinds. Built-in battery. \ $3.99 at the corner store. That sort of thing. At the moment, it is "; if self is switchedon "on." else "off." } before { ! The before property routine attempts to match the verb ! routine based on a given specifier. In the case below, ! if the verbroutine global is set to DoBurn (technically ! &DoBurn, the address of the DoBurn routine) and the ! object global is set to the flashlight object, the ! following routine is run before (in place of) the DoBurn ! routine. object DoBurn {Perform(&DoSwitchOn, self)} } after { ! The two routines below are similar to the before routine ! above, except that they are run after the verb routine. object DoSwitchOn { "A beam of serviceable light appears from your flashlight." self is light FindLight(location) if location is not visited {DescribePlace(location) location is visited} } object DoSwitchOff { "Your flashlight goes dark. "; self is not light if FindLight(location) print newline else "And so does everything else." } } is switchable } !---------------------------------------------------------------------------- ! OUTSIDE THE VAULT !---------------------------------------------------------------------------- room outsidevault "outside a vault" { long_desc {"Kind of that 1930s, Bela Lugosi, graveyardy motif at work here. It's a pretty creepy place. Directly in front of you is the giant door to an even more giant vault. Above the door hangs a rusty sign."} e_to {return vaultdoor.door_to} in_to {return vaultdoor.door_to} cant_go {"Vines, thorns, and bent, twisted trees bar travel in any direction away from the vault."} before { location DoDig { if object ~= bump "You can't dig in that." else Perform(&DoSearch, bump) } } } ! key_daemon ! ! This basic daemon is simply a trigger that checks every turn to see ! if 10 turns have passed. If so, it prints a brief section of prose ! before deactivating itself. (It is also deactivated if the player ! pre-emptively searches the bump in the ground.) daemon key_daemon {} event key_daemon { if counter = 10 { "\nAll this shuffling around outside the door has uncovered a little bump in the ground." event_flag = true Deactivate(key_daemon) } } scenery bump "little bump" { in outsidevault nouns "bump", "ground" adjective "little" article "a" long_desc { if key is not moved {"It looks like there might be something there." bump is moved} else {"You've already got the key. What more do you want?"} } before { ! More than one verb routine may be given as a potential ! match to a specifier in a before or after routine, as in: object DoSearch, DoDig { if key is moved "You already did. There's nothing else to find." else { bump is moved "You find a rusty iron key!\n(Taken.)" Acquire(player, key) score = score + 10 Deactivate(key_daemon) } } } } object key "rusty iron key" { noun "key" adjectives "rusty", "iron" article "a" size 20 long_desc {"A skeleton key. Rusty. Iron. And heavy, too. A perfect match for the vault door, no?"} before { xobject DoUnlock { if object = oakdoor "The rusty key doesn't work on this door." else return false ! library continues as usual } } } scenery sign "rusty sign" { in outsidevault noun "sign" article "a" adjective "rusty" long_desc {"\"Here lies Hugo.\""} is readable } ! vaultdoor ! ! Notice that the found_in property specifies the rooms on either side ! of the door; OBJLIB.H does the rest. The vault door's special attribute ! is set once the player scores points for opening it. door vaultdoor "vault door" { nouns "door", "doorway" adjective "vault", "giant" article "the" between outsidevault, insidevault key_object key after { object DoUnlock { if self is not special { self is special score = score + 10 rank = 1 } return false ! library continues as usual } } is not open, lockable, locked } scenery vault "vault" { in outsidevault noun "vault" article "the" long_desc {"Big, imposing, and complete with rusty sign."} door_to ! so a player can "go vault" {return vaultdoor.door_to} before { object DoEnter { object = vaultdoor ! change object before letting return false ! library continue normally } } } !---------------------------------------------------------------------------- ! INSIDE THE VAULT !---------------------------------------------------------------------------- room insidevault "inside the vault" { long_desc { "Standing in the middle of this dimly lit chamber, you realize that just maybe you should've splurged on a more expensive flashlight. You also realize that there are four ways you can go: a marble archway to the north, a muddy cave opening to the east, "; if oakdoor is not blown_open "an oak door set in a brick frame"; else "an empty brick frame where the oak door used to be"; " to the southeast, and west back outside where you came from." } w_to {return vaultdoor.door_to} out_to {return vaultdoor.door_to} se_to {return oakdoor.door_to} n_to objectroom e_to characterroom in_to {"You'll have to be a little more specific about which way you want to go."} is not light after { location DoGo ! changes the way the vault is refered to from ! "a vault" to "the vault"--a stylistic thing { outsidevault.name = "outside the vault" return false } } vehicle_path minecar ! i.e. the mine car can travel here } ! minecar ! ! This is an excellent example of a basic vehicle from OBJLIB.H. The ! vehicle_verbs property must mirror the valid words provided in the ! verb grammar at the start of this file. The vehicle_move property is ! checked before the vehicle is allowed to move. (This is where, for ! example, a car object would be checked to make sure that the ignition ! is turned on, or the tires aren't flat, etc.) Any room in which travel ! in the mine car is permitted must have minecar in its vehicle_path ! property. vehicle minecar "mine car" { in insidevault nouns "car", "cart" adjectives "mine", "my", "old" ! because: synonym "mine" for "my" ! in HUGOLIB.H article "a" vehicle_verbs "roll", "drive", "steer", "ride" vehicle_move { ! Here, the mine car will not roll until the big rock is ! removed from under it. Note that the rock is not actually ! under the car, but looking under the car moves it from ! the nothing object to the room object. if bigrock in nothing {"Something seems to be stopping the mine car from rolling." return false} } initial_desc {"An old mine car sits abandoned to one side."} long_desc {"It was probably used to haul rocks during the excavation of the original Hugo. You could probably get in it."} contains_desc {"The old mine car is loaded with";} before { object DoClimb {Perform(&DoEnter, self)} object DoLookUnder { ! The big rock initially begins the game in nothing; ! looking under the mine car moves it inside the ! vault. if bigrock not in nothing "You don't find anything else." else { "You find a big rock lodged between the wheels, which you manage to wrestle out of the way." move bigrock to insidevault } } } after { object DoEnter { pencil is known return false } } capacity 100 holding 0 reach minecar ! can't reach things outside the car is container, open, static ! Because the mine car has the quiet attribute set, its contents ! (i.e. the pencil) are not immediately obvious--they are not ! listed by WhatsIn until the player specifically looks inside. is quiet ! Also, it is mobile and therefore may be pulled by the rope. is mobile attach_immobile ! returns false if the car is mobile { if bigrock in nothing "Something seems to be stopping the mine car from rolling." else: return false } } object bigrock "big rock" { nouns "rock", "stone" adjectives "big", "large", "huge" article "a" after { object DoGet {"Oof. It's a struggle, but you manage to pick it up."} } size 50 } !---------------------------------------------------------------------------- ! THE OBJECT ROOM !---------------------------------------------------------------------------- room objectroom "Object Room" { article "the" prep "in" s_to insidevault out_to insidevault long_desc { "This room contains a collection of objects with different properties, attributes, and associated routines in order to give some idea of basic object design. In addition to the various furnishings, you notice a dartboard hanging on one wall." } vehicle_path minecar is not light } ! chair ! ! Try sitting in it. object chair "wooden chair" { in objectroom noun "chair" adjective "wooden" article "a" reach cardtable ! i.e. only the chair and the card table ! may be reached from the chair is enterable, static } ! cardtable ! ! Try sitting on it. (You can't--it's not enterable.) But it can hold ! things on its surface. object cardtable "card table" { in objectroom nouns "table", "cardtable" adjective "card" article "a" capacity 50 holding 0 is platform, static } ! deckofcards and playingcard ! ! A rather unimpressive example of how to extract a single object from ! a group of similar objects. Pick a card, any card. object deckofcards "playing cards" { in cardtable noun "cards" adjective "deck", "playing" article "some" initial_desc {"A deck of playing cards has been placed appropriately on the table."} size 10 is plural } object card "playing card" { found_in deckofcards noun "card" , "diamonds" adjective "playing", "nine" article "a" size 5 long_desc {"It's the nine of diamonds."} after { object DoGet { if object.found_in ~= false { object.found_in = false "You deal the nine of diamonds." object.name = "nine of diamonds" object.article = "the" } else return false } } } ! goldcoins ! ! A simple demonstration of identical_class from OBJLIB.H. The coins can ! be referred to individually, by number (i.e. "two coins"), or as a ! group ("the coins"). identical_class goldcoins "shiny gold coins" { article "some" nouns "coins" adjectives "shiny", "gold" single_noun "coin" long_desc "Shiny and gold: both admirable qualities in a coin." plural_of coin1, coin2, coin3 } object coin1 "shiny gold coin" { in cardtable article "a" noun "coin" adjectives "shiny", "gold" identical_to goldcoins } coin1 coin2 "shiny gold coin" ! copy coin1 to coin2 { in cardtable } coin1 coin3 "shiny gold coin" { in cardtable } ! mittens ! ! Try wearing them. Try writing when you're wearing them. object mittens "pair of mittens" { in transparentbox nouns "mitten", "mittens" adjective "pair" article "a" size 10 initial_desc {"A pair of mittens is inside the transparent box."} is clothing } ! box ! ! The basic box class is used by transparentbox and opaquebox. The boxes ! plural_class (from OBJLIB.H) exists only to allow the boxes to be referred ! to as a group. plural_class boxes "boxes" { article "some" noun "boxes" single_noun "box" plural_of transparentbox, opaquebox } class box "box" { noun "box" article "a" size 20 capacity 20 holding 0 long_desc { if self is open "It's open." else "It's closed." } after { ! This after routine replaces the normal library "Taken." ! response whenever a box object is the parent of the ! taken object. parent(object) DoGet { print "You take "; The(object); " out of "; \ The(self); "." } } plural_is boxes is openable, not open, container } ! transparentbox ! ! Try getting something out of it when it's closed, even if you can see ! the contents. Then try putting the flashlight in here and closing it. box transparentbox "transparent box" { in objectroom adjective "transparent", "clear" is transparent } ! opaquebox ! ! Now try putting the flashlight in here and closing it. The library does ! all the work of checking to see if the DoClose verb routine hides the ! light source in the room. box opaquebox "opaque box" { in objectroom adjective "opaque" article "an" } box largedrum "large drum" ! the special attribute is set once it has been opened { in objectroom nouns "drum", "can", "barrel" adjectives "large", "big", "larger" short_desc { "A large drum--not the musical kind--is here. "; if warningnote is hidden { "Attached to it is a warning note." warningnote is known warningnote is already_listed } print newline } long_desc {"It's one of those big barrels used for storing and shipping oil, chemicals, and other hazardous materials. Hint."} before { object DoGet {"It's much too heavy to take."} } after { object DoOpen { ! if drum hasn't been opened the first time if self is not special { "Ignoring all warnings to the contrary, you open the drum. Inside is another, smaller drum, as well as a second warning note." self is special smalldrum is known warningnote.name = "first warning note" } else return false } } } plural_class notes "notes" { nouns "notes", "paper" adjectives "warning", "pieces" single_noun "note" plural_of warningnote, secondnote } object warningnote "warning note" { in objectroom nouns "note", "paper" adjectives "warning", "first", "piece" article "a" long_desc {"\"Do not open this drum. Whatever you do, don't open this drum. Do not. Open. This drum.\""} before { object DoGet {self is not hidden return false} } plural_is notes is readable, hidden } box smalldrum "smaller drum" ! the special attribute is set once the bomb has been found { in largedrum nouns "drum", "can", "barrel" adjectives "small", "smaller", "little" long_desc { "It's a smaller version of the first drum"; if secondnote is hidden { " (with a second warning note attached, of course)"; secondnote is known secondnote is already_listed } print "." } before { object DoGet {"Small is a relative term here. It's still too big to pick up."} } after { object DoOpen { if self is not special ! if bomb hasn't been found { "You find a bomb. What luck." self is special bomb is known Activate(bomb_fuse, 10) score = score + 10 rank = 2 } else return false } } } object secondnote "second warning note" { in largedrum nouns "note", "paper" adjectives "warning", "second", "piece" article "a" long_desc {"\"You listen well. But this time we mean it. Don't open this drum.\""} before { object DoGet { self is not hidden return false } } plural_is notes is readable, hidden } object bomb "bomb" { in smalldrum nouns "bomb" article "a" long_desc {"Just your typical, garden-variety bomb."} } ! bomb_fuse ! ! This fuse begins running as soon as the player opens the small drum. ! It prints a message only when it is within earshot or view of the player, ! but keeps ticking regardless. fuse bomb_fuse {} event bomb_fuse { if bomb in player ! player is holding it {"\nThe bomb you're holding is ticking." event_flag = true} elseif FindObject(bomb, location) ! bomb is visible in the room {"\nThe bomb is ticking." event_flag = true} elseif Contains(location, bomb) ! bomb is otherwise in room {"\nYou hear a ticking noise." event_flag = true} if not self.tick ! when self.timer = 0 { if Contains(location, bomb) ! if in player's location { "\nKABOOM!\n\n\ (Right next to the bomb was not, as they say, such a great place to be as it went off. You're dead now.)" endflag = 2 ! when endflag is non-false, it ! immediately triggers the end of the ! game } else { "\nYou hear a muffled kaboom." event_flag = true if bomb in insidevault { oakdoor is blown_open oakdoor is not openable oakdoor is not hidden score = score + 10 ! The following activates the dwarf's ! script with eleven steps; the DwarfDropBall ! ensures that she drops whatever she was ! holding before going anywhere. setscript[script(dwarf,11)] = \ &CharMove, s_obj, &CharMove, w_obj, &CharWait, nothing, &CharShakeHead, oakdoor, &CharWait, nothing, &CharMove, n_obj, &CharWait, nothing, &CharShakeHead, largedrum, &CharMove, s_obj, &CharMove, e_obj, &CharMove, n_obj DwarfDropBall } remove bomb Deactivate(bomb_fuse) } } } attribute written alias special ! for the pad only array writing[65] ! up to 64 characters of writing ! pad ! ! Try: write "something" on paper. object pad "pad of paper" { in cardtable article "a" nouns "paper" adjective "pad", "regular", "writing" long_desc { "It's a regular pad of writing paper. "; if self is written { "Written on it is: \""; print StringPrint(writing); "\"." } else: "It's blank." print newline } is readable } object pencil "pencil" { in minecar article "a" noun "pencil" adjective "wooden" long_desc "Not just a wooden pencil, but a magical wooden pencil, which one might use, perhaps, to name a hitherto unnamed object." size 5 } ! unnamedobject ! ! The unnamed object can be given a name by the player--i.e. have a word ! written on it by which the object may be referred to--in order to ! demonstrate the DICT command. object unnamedobject "unnamed object" ! the special attribute is set once the player has given it a name { in objectroom article "an" noun "object" adjective "unnamed", "non-descript", "nondescript" misc 0 ! will eventually contain the non- ! case-altered version of the name initial_desc "Lying in the corner of the room is a non-descript, unnamed object." short_desc print "The "; self.name; " is here." long_desc { "Nothing special about it. You can't even tell what it might be for."; if self is special {" Written on the side of it is: \""; print object.misc; "\".";} print newline } is openable, clothing, switchable } scenery dartboard "old dartboard" { in objectroom article "a" noun "dartboard", "board" adjective "old", "dart" short_desc "Hanging on one wall is an old dartboard." is static } ! dart ! ! The dart can be attached to the dartboard either by sticking it in or ! throwing it. Since the attach_take property is true, the dart is released ! when attached and taken when detached. attachable dart "green dart" { in objectroom article "a" noun "dart" adjective "green" size 5 attach_verb "stick", "throw" detach_verb "get" attach_prep "in" attached_desc "sticking out of" attach_take true attach_drop true attached_to dartboard ! space for one attachment attachable_to dartboard before { object DoThrowAt { if xobject is living "Trying to start something, are we?" else Perform(&DoAttachObject, object, xobject) } } } ! rope ! ! The rope is another attachable--but unlike the dart, because attach_take ! is not set to true, it may still be carried after being attached to another ! object. Since the minecar has the mobile attribute set, it may be pulled ! around; the chair and cardtable, however, may not. attachable rope "heavy rope" { in objectroom article "a" nouns "rope", "twine" adjective "heavy", "thick" attach_verbs "tie", "attach" detach_verbs "untie", "detach" attached_to chair, 0 ! space for two attachments attachable_to chair, cardtable, minecar } !---------------------------------------------------------------------------- ! THE CHARACTER ROOM AND THE BALL ROOM !---------------------------------------------------------------------------- room characterroom "Character Room" { noun "room" adjective "character" article "the" prep "in" w_to insidevault out_to insidevault n_to ballroom in_to ballroom long_desc {"The Character Room provides a couple of good examples of character scripts and events. Exits are north and west."} vehicle_path minecar } ! guard ! ! Ask him about things in the game. Try: ! ! ask guard about the minecar ! guard, tell me about the minecar ! guard, what about the minecar? ! ! Or, once you've begun talking to him, simply: ! ! tell me about... ! what about... character guard "burly guard" { in characterroom noun "guard" adjective "burly" article "a" long_desc {"He's wearing a button that reads: \"Just ask me.\""} before { ! The guard is the object, since the question is asked as: ! "ask about ". object DoAsk { select xobject case minecar "\"You bring that in here, and you're asking for trouble.\"" case ballroom "\"Don't let me catch you taking none of them there balls out of the Ball Room.\"" case bomb "\"I don't know what kind of loopy nut would want to be carting a bomb in here.\"" case dwarf {"\"She's a short little one. Kinda strange, I have to say. Spends all her time in there just a-kickin' away. I think she's mad 'cause she lost her magic wand.\"" wand is known} case wand "\"Wish I had one.\"" case oakdoor "\"I have no idea how to get that thing open. The only way would be to blast it, if you had something to blast it with...\"" case you "The guard doesn't think too much of you." case guard "I wouldn't pry if I were you." case else return false } } } ! This object-linked event is checked only when the guard is in the player's ! location. event guard { if minecar in location { "\nThe guard lifts his big boot up to the mine car and gives you a firm shove back out the door. \"Not in that thing, you don't, pal!\"" if player in minecar { move minecar to insidevault location = insidevault PrintStatusLine } else {MovePlayer(insidevault) MoveAllAttachables(player, characterroom, insidevault, true) } } if Contains(player, bomb) { "\nThe guard grabs you and throws you back out the door. \ \"Get out of here with that bomb, pal!\" An unsubtle approach, yes, but one that works." MovePlayer(insidevault) } if Contains(player, soccerball) or Contains(player, basketball) { "\nThe guard grabs you and throws you back out the door. \ \"Read the sign, pal! They call it the Ball Room for a reason. Keep 'em in there!\"" MovePlayer(ballroom) } } room ballroom "Ball Room" { noun "room", "ballroom" adjective "ball" article "the" prep "in" s_to characterroom out_to characterroom } ! This event runs whenever the player is in the ballroom. event ballroom ! the dwarf plays with the balls { local a if dwarf in ballroom { a = random(6) ! 1 to 6 select a case 1 DwarfGetBall(soccerball) case 2 DwarfGetBall(basketball) case 3, 4 DwarfDropBall case else { if child(dwarf) { "\nThe dwarf winds up and gives the "; print child(dwarf).name; " a kick. It ricochets off the wall and bounces back to her." event_flag = true } } } } routine DwarfDropBall { if child(dwarf) { "\nThe dwarf drops the "; print child(dwarf).name; "." move child(dwarf) to ballroom event_flag = true } } routine DwarfGetBall(obj) { if obj in ballroom { DwarfDropBall move obj to dwarf "\nThe dwarf picks up the "; print obj.name; "." event_flag = true } else ! player must have ball obj { if obj = basketball ! so try to choose the other ball obj = soccerball else obj = basketball if obj not in ballroom ! player must have both balls "\nThe dwarf looks at you impatiently and more than a little accusingly, waiting for you to give her back her balls." } } plural_class balls "balls" { article "some" noun "balls" single_noun "ball" plural_of soccerball, basketball } object soccerball "checkered soccer ball" { type balls ! for identification as a ball in ballroom nouns "ball", "soccerball" adjective "soccer", "checkered" article "a" before { object DoGet { if self in dwarf ! if she's holding it {"The dwarf shakes a fist at you and mutters, \"Get your own, kid.\""} else return false } } plural_is balls } soccerball basketball "orange basketball" ! copy the other ball object { in ballroom nouns "ball", "basketball" adjective "basket", "orange" article "an" } female_character dwarf "little dwarf" { in ballroom noun "dwarf" adjective "little" article "a" order_response ! i.e. "dwarf, (do something)", such as { ! "dwarf, kick ball" if verbroutine = &DoPunt { if object.type ~= balls {"The dwarf looks at you like you're nuts." return true} if object in player {"(first giving the ball to her)" if child(dwarf) move child(dwarf) to location move object to dwarf} if object not in dwarf {"The dwarf shrugs. \"I would, but I don't have "; print The(object); ".\""} else {"The dwarf winds up and gives the "; print object.name; " a kick. It ricochets off the wall and bounces back to her."} } else return false } after { object DoAsk { if xobject = wand "\"I'd like to have it back.\"" else return false } object DoTell { if xobject = wand "\"I'd like to have it back.\"" else return false } ! In this case, the dwarf is the xobject, since the command ! is given as: "show to ". xobject DoShow { if object = wand "\"Give that to me!\"" else return false } xobject DoGive { if object = wand { "\"Thank you! I've been looking for that.\" The dwarf takes the wand and bonks you a little roughly on the head with it, transporting you back to your nice, warm bed." rank = 4 score = score + 10 endflag = 1 } else return false } } } routine CharShakeHead { local char, obj if char in location print CThe(char); " shakes her head at "; The(obj); "." } !---------------------------------------------------------------------------- ! BRICK ROOM !---------------------------------------------------------------------------- ! Special attribute for the oak door: attribute blown_open alias special object oakdoor "oak door" ! a little more complicated door object { in insidevault noun "door", "doorway" adjective "oak" article "an" short_desc {"Lying on the floor is the oak door."} door_to { if self is not blown_open "The oak door is locked up tight as a drum." else return brickroom } vehicle_path minecar ! Setting key_object to a non-zero value means the door is not ! openable without a key. In this case, the ! key is ! technically object 1, which doesn't exist in the game. So ! for all intents and purposes, the player can never unlock ! this door. (It has to be blown open.) key_object 1 is static, openable, not open, lockable, locked ! Since the door is hidden at the outset, its short_desc is ! not printed (until the door is blown open). is hidden } room brickroom "Brick Room" { noun "room" adjective "brick" article "the" prep "in" long_desc {"This room is finished entirely in brick masonry. Good, solid workmanship. You can head back out to the northwest."} nw_to insidevault out_to insidevault } object trophy "shining golden trophy" { in brickroom nouns "award", "trophy", "inscription" adjectives "shining", "golden" article "a" initial_desc {"A shining golden trophy--an award for your efforts--is here. It bears an inscription."} long_desc {"Congratulations for solving this sample game's one and only major puzzle. (Although it really wasn't that hard, was it? And you probably don't deserve such a nice shining golden trophy.)"} after { object DoGet { if parent(letter) = nothing {"As you pick up the trophy, a magic wand falls to the ground, and a small piece of paper flutters down after it." move wand to brickroom move letter to brickroom rank = 3} else return false } } is readable } object letter "handwritten letter" { nouns "paper", "letter" adjective "handwritten", "piece" article "a" long_desc {"It's a letter from the author of this sample game. Goes something like this:\n\n\"Give this to the dwarf to solve the game.\" Nothing fancy, but I'm sure it was late when he was writing this."} is readable } object wand "magic wand" { noun "wand" adjective "magic", "twinkling" article "a" short_desc {"A magic wand is twinkling on the floor here."} long_desc {"\"The official magic wand of social democrats everywhere.\""} before { object DoWave { "You wave the magic wand, a cloud of orange mist appears, and...\n\n...Aw, forget it. I'm just kidding. What makes you think you know what to do with a magic wand, anyway?" } } } !---------------------------------------------------------------------------- ! NEW VERB ROUTINES !---------------------------------------------------------------------------- routine DoPunt { if object is living "Oh, good. Real good. Pick a fight, now. That's really going to get you places." elseif object.type ~= balls "You won't get very far trying to kick that around." else { "You wind up and give "; The(object) " a good boot. "; if dwarf in ballroom "The dwarf nods approvingly." else print newline move object to ballroom player.holding = player.holding - object.size } return true } routine DoWriteOn ! response to an improperly phrased command { if xobject and xobject ~= pencil {"You can't write with "; print The(xobject); "!"} elseif object ~= pad and object ~= unnamedobject {"There's not much point in defacing "; print The(object); "."} else "You'll have to be a little more specific about exactly what you'd like to write. Try: 'write \"something\".'" } routine DoWrite { local len if not xobject { if pencil not in player {"You're not holding anything to write with." return false} else xobject = pencil } if not object { if FindObject(pad, location) ~= 1 {"Nothing to write on." return false} else object = pad } if xobject ~= pencil or (object ~= pad and object ~= unnamedobject) {DoWriteOn return} elseif mittens is worn "Good luck writing with those mittens on." elseif object = unnamedobject return Perform(&DoName, unnamedobject) else { if pad is written {"You scratch out \""; print StringPrint(writing); "\" and ";} else: "You "; ! Read the engine parse$ into the writing[] array, to a ! maximum of 64 characters len = string(writing, parse$, 64) print word[1]; " \""; StringPrint(writing); "\""; " on the pad." pad is written } return true } ! Notice that the DoName routine only allows the player to create one new ! entry in order to avoid overrunning MAXDICTEXTEND. array name_array[50] routine DoName { if object is special {"You already named it "; The(object) "--don't go changing your mind now."} elseif pencil not in player "Would help if you were holding something to write that on the object, so you'll remember it." else { local i, len len = string(name_array, parse$, 49) ! maximum 49 char. for (i=0; i 'z' or (name_array[i] > '9' and name_array[i] < 'A') or (name_array[i] > 'Z' and name_array[i] < 'a'): {"Better to keep the fancy punctuation out of it." return} } "You write \""; StringPrint(name_array) "\" on the object." ! The misc property contains the non-case-corrected version ! of the name. object.misc = dict(name_array, 49) ! The name is converted to '"" object': ! initial quote first... name_array[0] = '\"' ! then read parse$ into name_array (after the first quote)... len = string(name_array+1, parse$, 49) ! and append the last part to name_array... string(name_array+len+1, "\" object") ! ...before turning name_array into a dictionary entry object.name = dict(name_array, 49) ! Since the adjective will be referred to by the parser, ! it must be lowercase--name_array must also be reloaded ! with parse$ since it has been modified above. len = string(name_array, parse$, 49) for (i=0; i= 'A' and name_array[i] <= 'Z' name_array[i] = name_array[i] + ('a'-'A') } ! then write the word as a dictionary entry object.adjective #1 = dict(name_array, 49) object.article = "the" ! i.e. 'the "" object' object is special object is moved } } routine DoNameWhat { "Try: name object \"(something)\"." } !---------------------------------------------------------------------------- ! REPLACE LIBRARY ROUTINES: !---------------------------------------------------------------------------- global already_warned replace DarkWarning { if not already_warned ! player is only warned once... { "It's pitch black in here. Stumbling around in the dark isn't such a hot idea: you're liable to be eaten by a grue." already_warned = true } else ! ...and gets three safe moves before { ! becoming a snack for a grue already_warned = already_warned + 1 if already_warned > 4 {"You stumble around in the dark...and are eaten by a grue! Bad move. Should've used a light." endflag = 2} else "You stumble around in the dark." } } ! Below is the new PrintScore routine. Note that it differs from the ! library routine in that it uses the new global rank to print the ranking. replace PrintScore(end_of_game) { "You "; if not end_of_game "have "; "scored a total of "; print number score; " out of "; number max_score; print ", giving you the rank of "; ranking[rank]; "." }