! ------------------------------------------------------------------------- ! $Id: surface.inf,v 1.1 2000/08/20 17:30:21 neilc Exp $ ! surface.inf -- A component of the Inform 6 port of Ditch Day Drifter ! ! This file contains the source code for all the areas of the CalTech ! campus that are above ground except for the maze. ! ------------------------------------------------------------------------- ! ------------------------------------------------------------------------- ! -- Table of Contents -- ! ! THE DORM BUILDING (1) ! Room Three (1.1) ! small wooden desk (1.1.1) ! desk drawer (1.1.1.2) ! ! Crawlable class (C) ! ! food item (1.1.2) ! waste basket (1.1.3) ! plastic bottle (1.1.3.1) ! attributes, name, description (1.1.3.1a) ! invent (1.1.3.1b) ! poured_into (1.1.3.1c) ! before (1.1.3.1d) ! number, daemon (1.1.3.1e) ! after (1.1.3.1f) ! bottle cap (1.1.3.1.1) ! bed (1.1.4) ! one-dollar bill (1.1.5) ! Alley One (1.2) ! alley one door (1.2-3.1) ! ! Treasure class (D) ! ! treasure slot (1.2.1.1) ! welcome sign (1.2.1.2) ! Room Four (1.3) ! win note (1.3.1) ! warp motivator (1.3.2) ! Alley One North (1.4) ! Computer Room (1.5) ! computer (1.5.1) ! students (1.5.2) ! attributes, name, description, describe, life (1.5.2a) ! orders, greet, react_before, number (1.5.2b) ! each_turn (1.5.2c) ! Breezeway (1.6) ! Courtyard (1.7) ! Lounge (1.8) ! Dining Room (1.9) ! wooden table (1.9.1) ! fish protein module (1.9.1.1) ! coffee cup (1.9.1.2) ! Kitchen (1.10) ! ToxiCola(tm) machine (1.10.1) ! ToxiCola(tm) button (1.10.1.1) ! ToxiCola(tm) (1.10.1.2) ! ! THE CAMPUS (2) ! Orange Walk 1 (2.1) ! Orange Walk 2 (2.2) ! orange trees (2.1-2.1) ! Quad (2.3) ! ! Crowd class (E) ! ! leak students (2.3.1) ! reporters (2.3.2) ! flask (2.3.3) ! ! LiquidNitrogen class (F) ! ! original liquid nitrogen (2.3.3.1) ! bottled liquid nitrogen (2.3.3.2) ! B&G (2.4) ! B&G memo (2.4.1) ! Health Center (2.5) ! ! SimpleDesk class (G) ! ! health desk (2.5.1) ! health memo (2.5.1.1) ! Walkway 1 (2.6) ! Walkway 2 (2.7) ! Biology Building (2.8) ! biology notebook (2.8.1) ! Explosive Lab (2.9) ! explosives thesis (2.9.1) ! Bookstore (2.10) ! battery (2.10.1) ! ! buy_obj global (H) ! ! clerk (2.10.2) ! attributes, name, description, describe, react_before (2.10.2a) ! orders, life (2.10.2b) ! Behavior Lab (2.11) ! bahavior door south (2.11.1) ! Maze Viewing Room (2.12) ! maze window (2.12.1) ! maze plaque (2.12.2) ! Security Office (2.13) ! security desk (2.13.1) ! security memo (2.13.1.1) ! flashlight (2.13.1.2) ! ! ------------------------------------------------------------------------- ! (1) THE DORM BUILDING ! (1.1) Room Three ! There are lots of good ways to lay out an object definition. I like the ! one I use because it emphasizes the conceptual and syntactic differences ! between attributes, properties, and class inheritance. ! ! Here's a prototype. Everything in the prototype is optional except for ! the word "Object" and the closing ";". I seldom use the "->" arrow ! notation. ! ! Object <"textual name"> ! ! classes from which this object inherits ! ! attributes ! ! ; Object RoomThree "Room 3" has light with description "This is your room. You live a fairly austere life, being a poor college student. The only notable features are the bed (unmade, of course) and a small wooden desk. An exit is west.", w_to AlleyOne, out_to AlleyOne, ; ! (1.1.1) small wooden desk ! It is not possible for an object to be both a supporter and a container, ! so the drawer must be a separate object in the same location as the desk. ! The desk simply re-routes open and close action to the drawer. Object room_three_desk "small wooden desk" RoomThree has scenery supporter with name 'small' 'wooden' 'wood' 'desk' 'desktop', ! A description property (and almost all properties) can be a routine. ! This one will describe the desk drawer and list objects on the desk. description [; print "It's the small desk that comes with all of the rooms in the house. The desktop is pitifully small; especially considering that you often need to have several physics texts and tables of integrals open simultaneously. The desk has a small drawer ("; if (drawer has open) { print "open). "; if (children(drawer) > 0) ShowCont(drawer); ! "misc.inf":12.4 } else print "closed). "; if (children(self) > 0) ShowCont(self); new_line; rtrue; ], ! Redirect attempts to open or close the desk to the drawer. before [; Open: <>; Close: <>; ], ; ! (1.1.1.2) desk drawer Object drawer "drawer" RoomThree has scenery container ~open openable with ! See the code for the Toxicola(tm) Machine [1.10.1] for a discussion ! of parse_name routines. This one restricts the words "small" and "desk" ! so that they don't all by themself refer to the drawer. parse_name [; switch (NextWord()) { 'small', 'desk': if (NextWord() == 'drawer') return 2; 'drawer': return 1; } return 0; ], ! It should seem like the drawer is part of the desk. before [; Take: "You can't remove the drawer from the desk."; ], after [; ! Only crawlable (small) items fit in the drawer. Receive: if (~~ noun ofclass Crawlable) "That's too big to fit in the drawer."; ], ; ! (C) Crawlable class ! The Crawlable class signifies items which are small enough to be carried ! through the tight passage ["gue.inf":4.7.1], will fit in the desk ! drawer, and will make no sound when dropped down pits ! ["gue.inf":4.15.1] or chutes ["gue.inf":4.11.1]. Class Crawlable; ! (1.1.2) food item Object food_item "food item" drawer ! I eschew the Inform syntax which allows declaration of an instance of a ! class using the class name. While concise, the syntax doesn't allow for ! objects which belong to more than one class. class Crawlable has edible with name 'food' 'item', description "It's a food item of the type the Food Service typically prepares.", ; ! (1.1.3) waste basket Object waste_basket "waste basket" RoomThree has container open with name 'waste' 'basket' 'waste-basket' 'waste_basket', ! An initial routine is run in place of an item's normal listing, until ! the object is first moved. In this case, it initially hides the waste ! basket's contents. initial "You see a waste basket here.", before [; Wear: "This isn't a party, and you aren't the life of it."; ], ; ! (1.1.3.1) plastic bottle Object bottle "two-liter plastic bottle" waste_basket ! (1.1.3.1a) has ~open openable container transparent with name 'plastic' 'two' 'liter' 'two-liter' '2-liter' 'bottle', description [; print "The bottle is "; if (bottled_ln in self) print "full of liquid nitrogen. "; else print "empty. "; print "It's "; if (self has open) print "open. "; else print "closed. "; if (funnel in self) print "There's a funnel in the bottle's mouth."; new_line; rtrue; ], ! (1.1.3.1b) ! Inventory listings for the bottle should match the description. invent [; ! At inventory state 2, the objects short name has been printed. if (inventory_stage == 2) { print " (which is "; if (self has open) print "open"; else print "closed"; print " and "; if (bottled_ln in self) print "full"; else print "empty"; if (funnel in self) print ", in which is a funnel"; print ")"; ! Returning true tells the listing routine to print nothing further ! about the bottle. rtrue; } ], ! (1.1.3.1c) ! poured_into reacts to messages from the ##PourInto ! ["verbs.inf":10.14.1] action. poured_into [; if (noun == original_ln) { ! (the liquid nitrogen housed in the flask) if (funnel in self) { if (bottled_ln in self) "The bottle is already full."; move bottled_ln to self; "You manage to get some liquid nitrogen into the bottle. "; } else { "The opening of the bottle is too small, and your pouring is not precise enough."; } } ], ! (1.1.3.1d) before [; ! The bottle accepts only the funnel. Receive: if (self hasnt open) "It might help to open the bottle first."; if (noun == funnel) { move funnel to self; "A perfect fit."; } else "That won't fit in the bottle."; Close: if (funnel in self) "You'll have to take the funnel out first."; if (IsNotHeldOrTaken(bottlecap)) ! "misc.inf":12.3 "You need the bottle cap."; give bottlecap concealed; move bottlecap to self; if (bottled_ln in self) { StartDaemon(self); give self ~open; "It takes some time to close the bottle, since the rapidly evaporating nitrogen occupies much more volume as a gas than as a liquid. However, you manage to close it."; } Search: <>; PourInto: ! If the bottle is full, convert: ! >POUR BOTTLE INTO FLASK ! to ! >POUR LIQUID NITROGEN INTO FLASK if (original_ln in self) <>; ], ! (1.1.3.1e) number 7, ! used as a counter by the daemon ! A daemon is run every turn beginning on and including the turn that it ! is started by the StartDaemon(obj) routine. It runs every turn until ! stopped by the StopDaemon(obj) routine. This daemon runs a countdown, ! prints a warning message, and explodes the bottle (possibly opening the ! safe). daemon [; self.number--; ! and counting... ! if the bottle is opened, stop the daemon. if (self has open) { StopDaemon(self); self.number=7; ! reset the counter return; } switch (self.number) { 3: ! If the player is in scope of the bottle he/she will get a ! warning notice on 3. if (TestScope(player, self)) { print "^The bottle is starting to make lots of noise, as though the plastic were being stretched to its limit.^"; return; } 0: ! Being in scope of the explosion is deadly. if (TestScope(player, self)) { deadflag=1; print "^The bottle explodes with a deafening boom and a huge cloud of water vapor. As with most explosions, standing in such close proximity was not advisable. It was, in fact, fatal."; lloyd.act(bottle); ! "lloyd.inf":7.1h StopDaemon(self); return; } ! The explosion will do something useful if it happens in the bank ! safe. if (self in bank_safe) { give bank_safe general open; remove self; if (player notin BankVault) print "^You hear a distant, muffled explosion.^"; ! if the player hangs around to watch, she sees it happen else { print "^There is a terrible explosion from within the safe. The door blasts open with a clang and a huge cloud of water vapor."; ! Lloyd has something to say about explosive devices if (lloyd in BankVault) lloyd.act(bank_safe); } StopDaemon(self); new_line; return; } else { print "^You hear a distant explosion.^"; StopDaemon(self); return; } default: return; } ], ! (1.1.3.1f) after [; Open: give bottlecap ~concealed; move bottlecap to player; ], ; ! (1.1.3.1.1) bottle cap Object bottlecap "bottle cap" bottle class Crawlable has concealed with ! Recognize the phrase "bottle cap," but not "bottle," which will always ! refer to the plastic bottle. parse_name [; switch(NextWord()) { 'bottlecap', 'cap': return 1; 'bottle': if (NextWord() == 'cap') return 2; default: return 0; } ], before [; Take: if (self in bottle) <>; PutOn: if (second == bottle) <>; Turn: if (self in bottle) <>; else if (~~ IsNotHeldOrTaken(bottle)) ! "misc.inf":12.3 <>; ], ; ! (1.1.4) bed Object bed "bed" RoomThree has enterable supporter scenery with name 'bed', description "It's a perfectly ordinary bed. It's particularly ordinary (for around here, anyway) in that it hasn't been made in a very long time.", before [; LookUnder,Search: ! The bill starts off in Room 3. I give it 'concealed' ! until it is first manipulated. 'concealed' prevents it from ! being listed in room descriptions. if (one_dollar has concealed) { give one_dollar ~concealed; print "You find a dollar bill! You pocket the bill. "; if (one_dollar hasnt moved) print "(Okay, so it's an obvious adventure game puzzle, but I'm sure you would have been disappointed if nothing had been there.)"; ! This message is for players who put the bill back under the bed ! and then find it again. else print "(Fun, huh?)"; move one_dollar to player; new_line; rtrue; } "You don't find anything."; ! It is irritating to create a whole new action ["verbs.inf":10.12.1] ! just for a throw-away joke, but this one's worth it. Make: "It was a nice thought, but you suddenly realize that you never learned how."; GoUnder: "Hiding won't solve anything."; JumpInto, JumpOn: print "The bed isn't as bouncy as you might have hoped. "; if (player notin self) <>; else { new_line; rtrue; } JumpOver: print "You don't make it all the way over. "; if (player in self) <>; else <>; ], react_before [; ! ##Jump takes no noun or second, so use react_before to intercept it. Jump: if (player in self) <>; ], after [; Enter: "Okay, you're now sitting on the bed."; ], put_under [; if (noun == one_dollar) { give one_dollar concealed; move one_dollar to location; "Okay, if you really want to."; } "That's not the way to keep your room tidy."; ], ; ! (1.1.5) one-dollar bill Object one_dollar "one-dollar bill" RoomThree class Crawlable has concealed with name '1//' 'dollar' 'one-dollar' '1-dollar' 'one' 'bill' 'money', ! 'x//' means the one-character dictionary word, 'x'. react_before [; default: ! The dollar is in scope and can be manipulated before it is "found". ! Any action which concerns the dollar is therefore intercepted here ! and makes the dollar not concealed. if (self has concealed && self == noun or second) { print "(", (the) self, " under the bed)^"; give self ~concealed; rfalse; } ], ; ! (1.2) Alley One Object AlleyOne "Alley One" has light with description [; print "You are in the eternal twilight of Alley One, one of the twisty little passages (all different) making up the student house in which you live. Your room (room 3) is to the east. To the west is a door ("; if (alley_one_door hasnt open) print "closed"; else print "open"; "), affixed to which is a large sign. An exit is south, and the hallway continues north."; ], ! A before routine on a location object functions like a react_before ! routine. before [; Enter: ! Given the action <>, the standard library ! would eventually generate <>, circumventing the ! w_to routine. I want "w_to" to run every time the player ! attempts to pass through the door, so I cut it off at the pass. ! ("w_obj" is one of the objects that represent directions, i.e., ! n_obj, u_obj, in_obj, etc..) if (noun == alley_one_door) <>; ], w_to [ just_checking; ! Direction properties will be called with "just_checking" set to 1 ! when I'm interested in only the return value. if (just_checking) return alley_one_door; if (alley_one_door hasnt open) { print "The door is closed and locked. "; ! Prompt players to read the sign if they haven't yet. if (sign hasnt general) print "You might read the sign on the door for more information."; new_line; rtrue; } else return alley_one_door; ], e_to RoomThree, n_to AlleyOneNorth, s_to Breezeway, ! w_to RoomFour out_to Breezeway, ; ! (1.2-3.1) alley one door ! This is a standard two-way door as exemplified in the _Inform_Designer's_ ! _Manual_(IDM). Object alley_one_door "door" has door scenery openable locked with name 'door', description [; if (self has open) "It's open."; if (real_location == AlleyOne) "The door is closed and locked. There is a slot in the door, and above that, a large sign is affixed to the door."; else "It's closed."; ], before [; Unlock: print "There's no keyhole"; if (real_location == AlleyOne) print ", only that strange slot in the door"; "."; ], ! This program must be compiled using library 6/10 or higher, wherein ! real_location always holds the current location. In older libraries, ! it held the current location only if the player was in a dark room. door_to [; if (real_location == AlleyOne) return RoomFour; else return AlleyOne; ], door_dir [; if (real_location == AlleyOne) return w_to; else return e_to; ], found_in AlleyOne RoomFour, ; ! (D) Class Treasure Class Treasure ! Grabbing scored items increments the score by OBJECT_SCORE. has scored with ! 'x//p' creates a plural dictionary word. The parser will assume I mean ! "more than one" whenever I use it. name "treasure" "treasures//p", list_together "treasures", ; ! (1.2.1.1) treasure slot Object slot "slot" AlleyOne has scenery container open with name 'slot', number 0, ! treasures received so far poured_into "The slot will only accept items on the treasure list.", before [; Receive: if (~~ noun ofclass Treasure) "The slot will only accept items on the treasure list."; else { print (The) noun, " disappears into the slot. "; self.number++; remove noun; score=score+5; if (self.number == 4) { ! A seldom used feature of the "give" statement is that ! it can set several attributes at once. give alley_one_door ~locked open; print "As the treasure disappears into the slot, you hear a klaxon from the other side of the door. An elaborate series of clicks and clanks follows, then the door swings open."; } new_line; rtrue; } LookUnder: "You are unable to."; ], ; ! (1.2.1.2) welcome sign Object sign "sign" AlleyOne ! It's a good idea, if you are going to use the multi-purpose attribute ! "general", to make a note to yourself in the attribute declaration. has scenery ! general if player has already examined it with name 'sign', ! The vertical white-space in a string is ignored by Inform, but I ! use it in this description to make it easier to see what the code ! intends. description "The sign says: ^^ Welcome to Ditch Day!^^ This stack is a treasure hunt. Gather all the treasures and you break the stack. To satisfy the requirements of this stack, you must find the items listed below and deposit them in the slot in the door. When all items have been put in the slot, the stack will be solved and the door will open automatically. The items to find are: ^^ The Great Seal of the Omega ^ Mister Happy Gear ^ A Million Random Digits ^ A DarbCard^^ These items are hidden amongst the expanses of the Great Undergraduate Excavation project. Happy hunting!^^ For first-time participants, please note that this is a ~finesse stack.~ You are not permitted to attempt to break the stack by brute force. Instead, you must follow the rules above.", before [; Examine: ! You won't be nagged to read the sign after you read it. give self general; Take: "The sign is firmly attached to the door."; LookUnder: "You are unable to."; ], ; ! (1.3) Room Four Object RoomFour "Room 4" has light with description "This is room 4, where the weird senior across the hall lives. An exit is to the east, and a strange passage leads down.", e_to alley_one_door, out_to alley_one_door, ! d_to ShipRoom, d_to [ just_checking; if (just_checking) return ShipRoom; print "The passage takes you down a winding stairway to a previously unseen entrance to...^"; return ShipRoom; ], ; ! (1.3.1) win note Object win_note "note" RoomFour class Crawlable with description "Congratulations! You've broken the stack! Please take this fine WarpMaster 2000(tm) warp motivator, with my compliments. I'll see you in ~Deep Space Drifter~!", name 'note', ; ! (1.3.2) warp motivator Object motivator "warp motivator" RoomFour with name 'warp' 'motivator' 'warpmaster', description "It's a WarpMaster 2000(tm), the top of the line model.", before [; Take: if (self hasnt moved) score=score+20; ], ; ! (1.4) Alley One North Object AlleyOneNorth "Alley One North" has light with description "You are at the north end of Alley One. A small room is to the west.", s_to AlleyOne, w_to ComputerRoom, ; ! (1.5) Computer Room Object ComputerRoom "Computer Room" has light with description "You are in a small computer room. Not surprisingly, the room contains a personal computer. The exit is east.", e_to AlleyOneNorth ; ! (1.5.1) computer Object computer "personal computer" ComputerRoom has scenery with name 'personal' 'computer' 'pc' 'screen' 'monitor' 'keyboard' 'text' 'game', description "The computer is in use by a couple of your fellow undergraduates. Closer inspection of the screen shows that they seem to be playing a text adventure. You've never really understood the appeal of those games yourself, but you quickly surmise that the game is part of one of the seniors' stacks.", before [; Take: "It's not a portable."; ], ; ! (1.5.2) students Object students "students" ComputerRoom ! (1.5.2a) has animate pluralname with ! Putting 'of' in the name property of an object can needs to be done ! carefully. If more than one object with 'of' in their names are in ! scope at the same time, it can lead to the following stupid transcript. ! ! You see a group of students and the Eye of Argon here. ! >TAKE OF ! Which do you mean, the group of students or the Eye of Argon? ! ! As a result, portable objects that need to include the word 'of' in their ! name property must use a parse_name routine instead. These students ! cannot be moved, so no other objects with 'of' in their name will be in ! scope at the same time -- as long as I follow the above rule. name 'couple' 'students' 'pair' 'of' 'undergraduates' 'drifters', description "The students are busy using the computer.", describe "^A couple of your fellow undergraduates are here, using the computer. They seem quite absorbed in what they're doing.", life [; Ask: "They're too engrossed to listen to you."; Answer: if (noun == 'hi' or 'hello' or 'greetings' or 'salutations') return self.greet(); Attack: "You are about to attack, but a random morality enforcing code fragment prevents it."; Kiss: "You might consider it if they washed."; Give: if (noun == one_dollar) if (self.number >= 3) "They seem much more interested in their ~virtual~ dollar than in the real thing."; else "They don't seem to want your money."; Show: if (noun == one_dollar) "They pretend not to see."; ThrowAt: "That's no help."; ], ! (1.5.2b) ! The students are not cooperative. orders [; Hello: return self.greet(); NotUnderstood: rfalse; default: "The students don't seem to want any suggestions from you."; ], ! See "lloyd.inf" for the rationale behind "greet". greet [; "The students ignore you and huddle closer to the computer screen."; ], ! The students will prevent players from doing a few annoying things. ! react_before routines have to be more careful than before routines ! because they are called for every action. react_before [; SwitchOff: if (noun == computer) "The students won't let you, since they're busy using the computer."; TypeOn: if (second == computer) "The computer is already in use. Courtesy demands that you wait your turn."; Hello: return self.greet(); ], number 0, ! counter for the student blurbs ! (1.5.2c) ! each_turn is basically the same as a daemon, but it is only run when ! the object is in scope. It is often more convenient than a daemon ! routine, since it does not need to be started and stopped and will not ! run when not in scope. each_turn [; if (self.number < 32) self.number++; ! to prevent overflow new_line; switch(self.number) { 1: "~Where are we going to find the dollar bill?~ one of the students asks the other. They sit back and stare at the screen, lost in thought."; 2: "~Hey!~ says one of the students. ~Did you look under the bed?~^^The other student shakes his head. ~No way, that would be a stupid puzzle!~"; 3: "One of the students using the computer types a long string of commands, and finally types, ~Look under bed.~^^~Wow! The dollar bill actually was under the bed! How lame!~"; 9: "~What's a liter?~ demands one of the students."; 20: "~This maze sure is hard,~ moans one of the students. ~How are we supposed to get through it?~^^~I dunno,~ says the other, scratching his head. ~Let's try going in random directions until we find the exit.~"; 25: "~This maze doesn't make any damn sense!~ a student bemoans."; 27: "~Hey! Check this out! You can type 'w' as an abbreviation for 'enter the west wall'.~^^The other student huddles even closer to the screen, ~Cool!~"; 30: "~What are we supposed to do now?~ asks a perplexed student. With brow furrowed, the student types ~i~, then taps the enter key."; 31: "The students stare at the screen as if expecting a revelation."; ! my favorite joke from _Enchanter_. default: "The students continue playing with the computer."; } ], ; ! (1.6) Breezeway Object Breezeway "Breezeway" has light with description "You are in a short passage that connects a courtyard, to the east, to the outside of the building, which lies to the west. A hallway leads north.", n_to AlleyOne, e_to Courtyard, w_to OrangeWalk1, ; ! (1.7) Courtyard Object Courtyard "Courtyard" has light with description "You are in a large outdoor courtyard. An arched passage is to the west. A passage leads east, and a stairway leads down.", w_to Breezeway, e_to Lounge, d_to Hall1, ; ! (1.8) Lounge Object Lounge "Lounge" has light with description "You are in the lounge. A passage leads west, and a dining room lies to the north.", w_to Courtyard, out_to Courtyard, n_to DiningRoom, ; ! (1.9) Dining Room Object DiningRoom "Dining Room" has light with description "You are in the dining room. There is a wooden table in the center of the room. The lounge lies to the south, and a passage to the east leads into the kitchen.", e_to Kitchen, s_to Lounge, ; ! (1.9.1) wooden table Object wooden_table "wooden table" DiningRoom has scenery supporter with name 'wooden' 'table', ! This is much more edifying than, "You see nothing special about the ! wooden table." before [; Examine: <>; ], ; ! (1.9.1.1) fish protein module Object fish_food "fish protein module" wooden_table has edible with name 'fish' 'protein' 'module', description "It's a small pyramid-shaped white object, which is widely considered to consist primarily of fish protein. The food service typically resorts to such unappetizing fare toward the end of the year.", ; ! (1.9.1.2) coffee cup Object cup "coffee cup" wooden_table has container open with name 'coffee' 'cup', description [; ! You don't need to include new_lines at the start of description ! routines. The Inform library, knowing that all description routines ! must print something, prints a new_line before calling them. if (toxicola in self) "It's full of a viscous brown fluid."; else "It's empty."; ], poured_into [; ! It's best to limit the number of containers that can hold liquid ! nitrogen, because every time it splits a new liquid nitrogen object ! must be created. The coffee cup isn't allowed to hold liquid nitrogen ! for this reason. In Ditch Day, only the bottle and the flask are ! allowed to hold liquid nitrogen, requiring only two liquid nitrogen ! objects. if (noun ofclass LiquidNitrogen) { if (toxicola in self) "The cup is already full of ToxiCola(tm), and that's bad enough already without adding any other chemicals to it."; else "You manage to get a bit of liquid nitrogen into the cup, but the liquid quickly evaporates."; } ], before [; ! The cup can hold only ToxiCola(tm). Receive: if (noun has pluralname) print "They "; else print "It "; "won't fit in the cup."; ! Attempts to pour the cup into things is redirected to pouring the ! ToxiCola (tm). EmptyT, PourInto: if (toxicola in self) <>; ], ; ! (1.10) Kitchen Object Kitchen "Kitchen" has light with description "You are in the kitchen. A ToxiCola(tm) machine is here. A passage leads into the dining room to the west.", w_to DiningRoom, out_to DiningRoom, ; ! (1.10.1) ToxiCola(tm) machine Object cola_machine "ToxiCola(tm) machine" Kitchen has container open scenery with ! A parse_name routine is a substitute for the name property when a name ! property isn't precise enough. In this case, there is a ToxiCola ! machine, a Toxicola machine button, and ToxiCola in the game, so the ! game must be taught some new rules: for example, decide that the word ! ToxiCola alone refers to the cola. The toxicola machine is trained to ! accept 'toxicola', but only if the word 'machine' comes afterwards. ! This prevents some annoying disambiguation problems. ! parse_name routines don't take any arguments. Use the NextWord routine ! to get words one at a time for inspection. You then return the number ! of words that you accept as referring to the object. ! I find it interesting that every author whose code I have seen has ! their own style of parse_name routines. I lean toward restrictive ones. parse_name [ wd adj_count noun_count; wd=NextWord(); if (wd == 'toxicola' or 'cola' or 'pop' or 'coke' or 'soda' or 'bubbly' or 'toxicola(tm)') { adj_count++; wd=NextWord(); } ! This object doubles as its own compartment. while (wd == 'machine' or 'compartment') { noun_count++; wd=NextWord(); } ! This routine returns 0 unless at least one "noun" appeared. if (noun_count > 0) return adj_count + noun_count; else return 0; ], description [; print "The machine dispenses ToxiCola(tm), one of the big losers in the Cola Wars. But hey, it's cheap, so the food service installed it. The machine consists of a compartment large enough for a cup and a button for dispensing ToxiCola(tm) into the cup."; if (cup in self) print "The compartment contains a cup."; new_line; rtrue; ], before [; Receive: if (noun ~= cup) "The compartment will fit only cups."; ], ; ! (1.10.1.1) ToxiCola(tm) button Object cola_button "button" Kitchen has scenery with ! This is similar to the ToxiCola(tm) Machine parse_name above, and is ! used for similar reasons. However, the button might conceivably be ! referred to as the "toxicola machine button", so it is slightly more ! complicated (and restrictive). parse_name [ wd adj_count button_wd; wd=NextWord(); if (wd == 'toxicola' or 'cola' or 'soda' or 'coke' or 'pop' or 'bubbly' or 'toxicola(tm)') { adj_count++; wd=NextWord(); } if (wd == 'machine') { adj_count++; wd=NextWord(); } if (wd == 'button') button_wd++; if (button_wd) return adj_count + button_wd; else return 0; ], before [; Push: ! A lot of functionality is contained in button objects in this game. if (cup in cola_machine) { if (toxicola in cup) "ToxiCola(tm) spills over the already full cup and drains away."; move toxicola to cup; "The horrible brown viscous fluid you have come to know as ToxiCola(tm) fills the cup."; } "Horrible viscous brown fluid spills into the empty compartment and drains away."; ], ; ! (1.10.1.2) ToxiCola(tm) Object toxicola "ToxiCola(tm)" with name 'thick' 'flat' 'viscous' 'brown' 'fluid' 'toxicola' 'cola' 'pop' 'soda' 'coke' 'bubbly' 'toxicola(tm)', article "some", description "It's a thick brown fluid. It appears to be quite flat.", before [; ! The toxicola has to remain in the cup to be carried. Take: ! onotheld_mode is a global variable used by the parser to indicate ! that an "implicit take" is taking place. The player will get very ! confused if we translate an implicit take of the cola to 'take ! cup', so just refuse. ! ! 'Take cola' results in: ! (taking the coffee cup) ! Taken. ! ! while, 'Give cola to guard' results in: ! (first taking the ToxiCola(tm)) ! You'll have to carry the ToxiCola(tm) in the cup. ! ! It would be nice to translate "give cola to guard" to "give cup to ! guard", but it is too much trouble. Trust me. if (cup notin player && onotheld_mode==0) { print "(taking ", (the) cup, ")^"; <>; } print "You'll have to carry ", (the) self, " in the cup."; if (onotheld_mode == 1 && action_to_be == ##Give) print " To give the Toxicola(tm) to someone, try: ~give cup ...~."; new_line; rtrue; Drink: if (IsNotHeldOrTaken(cup)) rtrue; ! "misc.inf":12.3 remove self; print "You drink the ToxiCola(tm), despite your better judgment. It initially sparks a sugar and caffeine rush. But it rapidly fades, and is replaced by a strange dull throbbing."; ! This instantly runs out the player's sleep timer, causing him or ! her to fall asleep at the end of this turn ["misc.inf":12.1b]. player.awake_time=SLEEP_LIMIT+35; new_line; rtrue; ], ; ! (2) THE CAMPUS ! (2.1) Orange Walk 1 Object OrangeWalk1 "Orange Walk" has light with description "You are on a walkway lined with orange trees. The walkway continues to the north, and an arched passage leads into a building to the east.", e_to Breezeway, n_to OrangeWalk2, ; ! (2.2) Orange Walk 2 Object OrangeWalk2 "Orange Walk" has light with description "You are on a walkway lined with orange trees. The walkway continues to the south, and leads into a large grassy square to the north.", n_to Quad, s_to OrangeWalk1, ; ! (2.1-2.1) orange trees ! This is a simple example of an object that exists in more than one ! location. For more complex examples, see the 2-sided doors ! ["surface.inf":1.2-3.1, "gue.inf":3.8.3] and the steam pipes ! ["gue.inf":4.*]. Object orange_trees "orange trees" has scenery pluralname with description "The orange trees are perfectly ordinary.", name 'orange' 'tree' 'trees', found_in OrangeWalk1 OrangeWalk2, before [; Climb, ClimbUp: "You climb into one of the orange trees and quickly find the view from the few feet higher to be highly uninteresting. You soon climb back down."; Enter: <>; ClimbDown: "You aren't in the tree."; ], ; ! (2.3) Quad Object Quad "Quad" has light ! has general if Lloyd has visited here. with ! Dictionary words that appear in the name property of a room will generate ! the response, "You don't need to refer to that in the course of this ! game," if the player refers to them. name 'huge' 'clouds' 'water' 'vapor', description "You are on the quad, a large grassy square in the center of campus. The bookstore lies to the northwest; the health center lies to the northeast; Buildings and Grounds lies to the north; and walkways lead west and south.^^Some students dressed in radiation suits are staging a bogus toxic leak, undoubtedly to fulfill the requirements of one of the stacks. They are wandering around, looking very busy. Many reporters are standing at a safe distance, looking terrified. The supposed clean-up crew is pouring lots of liquid nitrogen onto the ground, resulting in huge clouds of water vapor.", s_to OrangeWalk2, nw_to Bookstore, w_to Walkway1, ne_to HealthCenter, n_to BandG, ; ! (E) Crowd class ! The groups of reporters and students aren't important, but the player can ! still refer to them. Class Crowd has scenery animate with article "the", ! The following routines restrict the actions you can take on a ! Crowd class object to 'Examine'. before [; Examine: rfalse; default: print_ret (The) self, " aren't important."; ], life [; self.before(); rtrue; ], orders [; self.before(); rtrue; ], ; ! (2.3.1) leak students Object leak_students "students" Quad class Crowd with name 'students' 'student' 'radiation' 'suits' 'badges', description "The students are making quite a good show of the simulated nuclear waste spill. They're all wearing white clean-room suits with official-looking ~Radiation Control District~ badges. They're scampering about purposefully, keeping the reporters back at a safe distance.", ; ! (2.3.2) reporters Object reporters "reporters" Quad class Crowd with name 'reporters' 'reporter', description "They're not important.", ; ! (2.3.3) flask Object flask "flask" Quad has container open with name 'flask' 'vapor' 'clouds' 'cloud', description "The flask appears to have lots of liquid nitrogen in it. It's hard to tell just how much since the opening is perpetually clouded over with thick plumes of water vapor.", poured_into [; ! The flask can only be poured into from the bottle, so this part is ! quite simple. if (noun == bottled_ln) { if (funnel in bottle) "You'll have to take the funnel out first."; remove bottled_ln; "You pour the liquid nitrogen back into the flask."; } ], before [; Receive: "You know from experience that it wouldn't be a good idea to put ", (the) noun, " into the liquid nitrogen, since the LN2 is really, really cold."; ! This traps, among other things, "look in the flask". Search: <>; PourInto: <>; ! The hard truth. Empty, EmptyT: "The flask cannot be emptied. There seems to be an unlimited supply of liquid nitrogen in it."; ], ; ! (F) LiquidNitrogen class Class LiquidNitrogen with article "some", name 'liquid' 'nitrogen' 'ln2', description "You can't see much thanks to the thick clouds of water vapor that inevitably form over such a cold substance.", before [ x; ! Trying to take the liquid nitrogen will be re-routed to the ! nitrogen's parent (unless the library is trying to implicitly take ! the liquid nitrogen -- see the comment on the ToxiCola(tm), above). ! ! This will cause a player who writes "take nitrogen" to end up taking ! the container instead; but we don't want that to happen if the ! container is already held. Take: x=parent(self); if (x notin player && onotheld_mode==0) { print "(taking ", (the) x, ")^"; <>; } "You're safer leaving the liquid nitrogen in ", (the) x, "."; Insert, Transfer: print "(pouring ", (the) self, " into ", (the) second, ")^"; <>; Touch, Rub: "You know enough about liquid nitrogen to know that touching it is a bad idea."; ], ; ! (2.3.3.1) original liquid nitrogen ! The two containers in the game that can hold liquid nitrogen are ! programmed so that the LiquidNitrogen can never be split three ways. This ! creates the happy circumstance that only 2 LiquidNitrogen Class objects ! need be defined: one for the flask, and one for the bottle. Object original_ln flask class LiquidNitrogen with name 'original', ! If both the bottled liquid nitrogen and the flask of liquid nitrogen ! are in scope, short_name is set up to show the player a way to ! distinguish between them. The extra name word is suppressed otherwise ! because it would look messy. short_name [; if (TestScope(self, bottled_ln)) print "original "; print "liquid nitrogen"; rtrue; ! Do not print newlines at the end of short_name routines. ], ; ! (2.3.3.2) bottled liquid nitrogen Object bottled_ln class LiquidNitrogen with name 'bottled', short_name [; if (TestScope(self, original_ln)) print "bottled "; print "liquid nitrogen"; rtrue; ], ; ! (2.4) B&G ! Yay! Lots of simple and boring objects in a row. Object BAndG "B&G" has light with description "You are in the Buildings and Grounds office. The exit is to the south.", s_to Quad, out_to Quad, ; ! (2.4.1) B&G memo Object b_and_g_memo "scrap of paper" BAndG with name 'scrap' 'of' 'paper', description [; print "Most of the paper is torn away. The part that remains seems to have a list of numerical codes of some kind on it:^^"; font off; print " 293 -- north tunnel lighting ^ 322 -- station 2 lighting ^ 612 -- behavior lab"; font on; "^^The rest of the paper is missing."; ], ; ! (2.5) Health Center Object HealthCenter "Health Center" has light with description "You are in the health center. Like the rest of campus, this place is deserted because of Ditch Day. The large desk would normally have a receptionist behind it, but today, no one is in sight.", sw_to Quad, out_to Quad, ; ! (G) SimpleDesk class Class SimpleDesk has scenery supporter with short_name "desk", name 'desk', before [; Open: "There's no drawer."; ], ; ! (2.5.1) health desk Object health_desk HealthCenter class SimpleDesk with name 'large', ; ! (2.5.1.1) health memo Object healthmemo "health memo" health_desk class Crawlable with name 'health' 'memo', description [; ! Certain interpreters allow non-fixed-width text. Calling font off ! forces those interpreters into a fixed-width font. font off; print "From: Director of the Health Center ^To: All Health Center Personnel ^Subject: ToxiCola(tm) toxicity"; font on; "^^Many students have visited the Health Center recently, complaining that the ToxiCola(tm) that is served in the student houses has not been properly caffeinated. The students are complaining of drowsiness, dizziness, and other symptoms, that are normally associated with an insufficient intake of caffeine.^^ Upon investigation, we have learned that the ToxiCola(tm) dispensers in the student houses have become contaminated with a substance that induces these effects. The substance has not yet been identified, but the concentration seems to be increasing. All Health Center personnel are urgently directed to advise students to avoid the ToxiCola(tm) if at all possible. Students should be informed that their student health insurance coverage will cover any purchases of other caffeinated beverages that they need for their studies."; ], ; ! (2.6) Walkway 1 Object Walkway1 "Walkway" has light with description "You are on a walkway. A large grassy square lies to the east. Buildings lie to the north and south. The walkway continues west.", e_to Quad, n_to BehaviorLab, s_to SecurityOffice, w_to Walkway2, ; ! (2.7) Walkway 2 Object Walkway2 "Walkway" has light with description "You are on a walkway, which continues to the east. Buildings are to the north and south.", e_to Walkway1, s_to ExplosiveLab, n_to BiologyBuilding, ; ! (2.8) Biology Building Object BiologyBuilding "Biology Building" has light with description "You are in the biology building. The exit is south.", s_to Walkway2, out_to Walkway2, ; ! (2.8.1) biology notebook Object biology_notebook "notebook" BiologyBuilding with name 'notebook' 'book', description "The notebook explains various lab techniques used in cloning organisms. Since the invention of the CloneMaster, which requires only a sample of genetic material from a subject (such as some blood, or a bit of skin, or the like) and the basic skills required to operate a household blender, most of the techniques are obsolete. Some of the data, however, are interesting. For example, the notebook outlines the procedure for reversing the sex of a clone. The introduction of chemicals, identified herein only as Genetic Factor XQ3, Polymerase Blue, and Compound T99, at the start of the cloning process, apparently does the trick. Most of the document is a discussion of the human immune system. The author comes to the conclusion that the human immune system, though a novel idea, is far too improbable to ever actually be implemented.", ; ! (2.9) Explosive Lab Object ExplosiveLab "Explosive Lab" has light with description "It's not that the lab itself is explosive (though it has blown up a couple times in the past). Rather, they study explosives here. Unfortunately, all the good stuff has been removed by other Ditch Day participants, who got up earlier than you did. The exit is north.", n_to Walkway2, out_to Walkway2, ; ! (2.9.1) explosives thesis Object thesis "thesis" ExplosiveLab with name 'thesis', description "The thesis is about Thermal Expansion Devices. It explains about a new class of explosives that are made possible by low-temperature fluid technology (i.e., liquid nitrogen) and high-tension polymer containment vessels (i.e., plastic bottles). A great deal of jargon and complicated theories are presented, presumably to fool the faculty advisor into thinking the author actually did something useful with his research funds. After wading through the nonsense, you find that the paper is merely talking about putting liquid nitrogen into a plastic soft-drink bottle, then closing the bottle, then letting nature take its course. Since the nitrogen will tend to evaporate at room temperature, but will have no place to go, the bottle will eventually explode.^^On the cover page, you notice this important warning: ~Kids! Don't try this at home! Liquid nitrogen is extremely cold and can cause severe injuries. It should only be handled by trained professionals. Never put liquid nitrogen in a closed container.~", ; ! (2.10) Bookstore Object Bookstore "Bookstore" has light with description "You are in the bookstore. The shelves are quite empty; No doubt everything has been bought up by seniors in attempts to build their stacks and underclassmen in attempts to break them. The exit is to the southeast.", se_to Quad, ; ! (2.10.1) battery Object battery "battery" Bookstore ! has general if it is paid for. with name 'battery', ; ! (H) buy_obj global ! This global is for holding the identity of the item being purchased ! during an attempted Pay action. See the AfterPrompt routine ! ["entrypts.inf":8.1], the Pay related grammar and actions ! ["verbs.inf":10.13], the orders property of Lloyd ["lloyd.inf":7.1f], ! and the orders property of the guard ["gue.inf":3.8.1e]. Global buy_obj; ! (2.10.2) clerk Object clerk "clerk" Bookstore ! (2.10.2a) has animate female with name 'clerk', description "The clerk is a kindly lady, to whom you have paid many hundreds of dollars for books and other college necessities.", describe "^A clerk is near the exit, prepared to ring up any purchases you might want to make (not that there's much left here to buy).", react_before [; ! The clerk prevents a player that is carrying the battery from ! leaving until the battery is paid for. The test must use ! "IndirectlyContains" instead of "battery in player" or the player ! could sneak the battery out in the waste-basket (or the flashlight). Go: if (noun == se_obj && IndirectlyContains(player, battery) && battery hasnt general) "The clerk saw you pick up the battery. ~That'll be five dollars,~ she says, waiting patiently."; PourInto, PourOnto: if (second == self) { if (noun ofclass LiquidNitrogen) <>; if (noun == toxicola) "That would totally ruin her kindly old hair-do."; } ], ! (2.10.2b) orders [; NotUnderstood: rfalse; Give: if (noun == battery) { if (battery hasnt general) "~That'll be five dollars please,~ she says."; else { if (IndirectlyContains(player, battery)) "~You have it already,~ she says, smiling to herself."; else if (InScope(battery)) "~It's right over there,~ she says, not moving to get it for you."; else "If you've lost it already I can't help you,~ she says."; } } "~If you work hard enough, I'm sure you'll find one of your own,~ she advises."; default: "She laughs and says, ~I don't have time to do everything for you.~"; ], life [; ! It is sometimes not worth the trouble to avoid redundant ! code in the life property. Here, ##Ask and ##Tell (about the ! battery) end up performing the same interaction as ##Show. Ask, Tell: if (second == 'battery') { if (battery hasnt general) "She says, ~Five dollars please.~"; else "~It's your's now,~ she says."; } else "The clerk is too busy being old and kindly to discuss it."; Show: switch(noun) { battery: if (battery hasnt general) "She says, ~Five dollars please.~"; "~It's yours now,~ she says."; five_dollars: "~My lands, a fortune!~ she says, in mock amazement."; one_dollar: "She looks at your dollar for a moment, and says, ~I'm sorry dear, there's nothing left to buy for only a dollar. But chin up. Perhaps you could find somewhere to invest it.~"; default: rfalse; } ! Buying something is always re-routed to <> by the ! Pay actions and grammar ["verbs.inf":10.13]. Give: switch (noun) { five_dollars: ! If indicated by the player, buy_obj will hold the object that ! the player is buying. Otherwise, the clerk assumes the battery ! is what is being bought if the player is holding it. if (buy_obj == self) "~Well I never!~ she exclaims, and then smacks her lips loudly several times."; if (buy_obj ~= 0 && buy_obj ~= battery) "~I'm not selling ", (ThatOrThose) buy_obj, ",~ she explains."; else if (IndirectlyContains(player, battery) ~= 1 && buy_obj ~= battery) "The clerk looks confused. ~I don't see what you're paying for,~ she says. She then looks amused, realizing that the students here sometimes get a little ahead of themselves."; else if (battery has general) "The clerk looks confused and says, ~You've already paid!~ She then looks amused, realizing that the students here can be a bit absent-minded at times."; else { give battery general; remove five_dollars; "The clerk accepts your money and says, ~Thank you. Have a nice day.~"; } one_dollar: if (buy_obj == battery || (buy_obj == 0 && IndirectlyContains(player, battery))) "The clerk reminds you that the battery costs five dollars. All you have is one dollar. She looks amused.^^~They can do calculus in their sleep but they can't add,~ she jokes."; print "~I'm not selling anything that costs one dollar,~ she "; if (buy_obj == self) print "primly "; else print "politely "; "explains."; darbcard: "The clerk shakes her head. ~Sorry,~ she says. ~We only accept cash.~"; cup: if (toxicola in cup) "~I never drink that stuff,~ the clerk says. ~And neither should you! Do you have any idea what's in there? I probably don't know half as much chemistry as you, but I know better than to drink that."; default: "She doesn't appear interested."; } Kiss: if (self has general) "She's still blushing from the last time."; else { give self general; "She blushes, and smiles. ~You're so sweet! I'm lowering the price of the battery to... five dollars,~ she says, chuckling."; } Attack: "She is just a bit too old, and far too kindly for you to ever be mad at her."; ThrowAt: if (noun == five_dollars or one_dollar) <>; <>; ], ; ! (2.11) Behavior Lab Object BehaviorLab "Behavior Lab" has light with description "You are in the behavior lab. The exit is to the south, and a closed door is to the north. The door is labeled: ~Maze - Experimental Subjects Only~. In addition, a passage labeled ~Viewing Room~ leads east.", before [; Enter: if (noun == behavior_door_s) <>; ], s_to Walkway1, out_to Walkway1, e_to MazeView, n_to behavior_door_s, in_to behavior_door_s, ; ! (2.11.1) behavior door south ! The south side of the behavior door. In this case, it is easier to have ! two objects because the north side of the door behaves differently from ! the south side of the door. The other side is behavior_door_n ! ["maze.inf":6.4.1]. Object behavior_door_s "behavior door" BehaviorLab has door scenery openable locked with parse_name [ wd wd_count; wd=NextWord(); while ((location == MazeStart && wd == 'exit' or 'maze') || wd == 'behavior' or 'door' or 'label' or 'entrance') { wd_count++; wd=NextWord(); } return wd_count; ], description [; if (MazeStart hasnt visited) "The door is closed and locked, and labeled: ~Experimental Subjects Only.~"; else "The door is closed and labeled: ~Experimental Subjects Only.~"; ], before [; Open: if (MazeStart has visited) "The door doesn't seem to open from this side."; else "The door seems to be closed and locked. Besides, do you really want to become an ~Experimental Subject~?"; Unlock: "There's no keyhole."; ], door_dir n_to, door_to MazeStart, ! Even though it's impossible to open from this side. ; ! (2.12) Maze Viewing Room Object MazeView "Maze Viewing Room" has light with description [; print "The entire north wall of this room is occupied by a window, overlooking a vast human-sized labyrinth. No experimental subjects (i.e., students) seem to be wandering through the maze at the moment, "; if (MazeStart hasnt visited) print "but you have the strange feeling that you will have to find your way through the maze some day. You read, with a sense of foreboding, the plaque affixed to the wall:^^"; else print "so your attention wanders to the plaque on the wall:^^"; ; "^The Psycho-Magnetic Maze, which is visible through the window, has been constructed to determine how the human directional sense interacts with strong electromagnetic and nuclear fields. Through careful tuning of these fields we have found that human subjects often become completely disoriented in the maze, resulting in hours of random and desperate wandering and much amusement to those of us in the observation room."; ], w_to BehaviorLab, ; ! (2.12.1) maze window Object maze_window "window" MazeView has scenery with name 'window' 'maze' 'labyrinth' 'behavior' 'lab', description [; print "The window looks out onto a vast human-sized labyrinth. The maze is currently devoid of experimental subjects"; if (MazeStart hasnt visited) { print ", but you have the strange feeling that you'll have to find your way through the maze some day.^"; rtrue; } ".^"; ], put_under [; <>; ], before [; Search: <>; Take: "Unfortunately, no."; LookUnder: "There's no space under this window."; Enter: "You can't get into the maze though the window."; ], ; ! (2.12.2) maze plaque Object maze_plaque "plaque" MazeView has scenery with name 'plaque', description "*** The Behavioral Biology Laboratory Psycho-Magnetic Maze ***", before [; Take, LookUnder: "The plaque is firmly attached to the wall."; ], ; ! (2.13) Security Office Object SecurityOffice "Security Office" has light with description "You are in the campus security office, the very nerve-center of the elite CalTech Cops. The officers all appear to be absent; undoubtedly, they are all scurrying hither and yon trying to deal with the Ditch-Day festivities. There is a desk in the center of the room. The exit is to the north.", n_to Walkway1, out_to Walkway1, ; ! (2.13.1) security desk Object security_desk SecurityOffice class SimpleDesk with name 'security', ; ! (2.13.1.1) security memo Object security_memo "security memo" security_desk class Crawlable with name 'security' 'memo' 'memos', description [; font off; print "From: Director of Security ^To: All Security Personnel ^Subject: Great Underground Excavation"; font on; "^^It has come to the attention of the CalTech Cops that the student activity in the steam tunnels, known as the ~Great Undergraduate Excavation~ project, has escalated vastly in recent years. Due to objections from city officials about noise from underground and the fear local residents have expressed that their property will be undermined, this office has taken action to halt all GUE activity. Effective immediately, a security officer will be posted at all known steam tunnel entrances and shall, under no circumstances, allow students to enter."; ], ; ! (2.13.1.2) flashlight Object flashlight "flashlight" security_desk has transparent switchable ~light with name 'flashlight' 'flash' 'light' 'torch', ! This flashlight can be turned on and off, even if the battery is not in ! it. It won't provide light unless the battery is in it. description [; if (self has on && battery in self) "It is providing a warm, reassuring beam of light."; else if (battery notin self) { print "It seems to be missing a battery"; if (self has on) ", so it is dark."; else "."; } ], ! This flashlight can be in four states: ! on, without battery (dark) ! on, with battery (light) ! off, without battery (dark) ! off, with battery (dark) ! ! This react_before routine is used to take care of the foor states by ! turning the light attribute on and off depending on movements of the ! battery. The actual move command and the movement messages had to be ! included here because you cannot make things happen or print commands ! after the default action messages have been printed by the library. react_before [; Insert, Transfer: if (second == self) { if (noun == battery) { move battery to self; print "You put the battery in the flashlight.^"; if (self has on) { give self light; print "^The flashlight flickers, then shines brightly.^"; } } else print "You can't put ", (thatorthose) noun, " into the flashlight.^"; rtrue; } Take: if (noun == battery && battery in self) { move battery to player; print "You take the battery out of the flashlight.^"; if (self has on) { give self ~light; print "^The flashlight flickers out.^"; } rtrue; } ], before [; Burn: if (self hasnt on) { print "You turn on the flashlight. "; <>; } else { if (self has light) "The flashlight is already lit."; else "You can't do that without the battery."; } Open, Close: if (TestScope(battery)) { "You don't need to ", (address) verb_word, " the flashlight. Just put the battery in, or take the battery out."; } else "There's no reason to ", (address) verb_word, " the flashlight right now."; ], after [; SwitchOn: ! The light only comes on if the battery is in the flashlight. if (battery in self) { give self light; "The flashlight is now shining brightly."; } "The flashlight remains stubbornly dark."; SwitchOff: if (battery in self) { give self ~light; "The flashlight obediently clicks off."; } else "The flashlight doesn't get any darker."; ], ;