! -------------------------------------------------------------------------
! surface.inf -- A component of the Inform 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 <arrows> <name> <"textual name"> <parent>
!  <class ... ...>  ! classes from which this object inherits
!  <has ... ...>    ! attributes
!  <with
!    ... ,           ! properties
!    ... ,>
! ;
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: <<Open drawer>>;
     Close: <<Close drawer>>;
  ],
;

! (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:
      <<Examine self>>;
    PourInto:
      ! If the bottle is full, convert:
      !   >POUR BOTTLE INTO FLASK 
      ! to
      !   >POUR LIQUID NITROGEN INTO FLASK
      if (original_ln in self) <<PourInto original_ln second>>;
  ],
  ! (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) <<Open bottle>>;
   PutOn:
     if (second == bottle) <<Close bottle>>;
   Turn:
     if (self in bottle) <<Open bottle>>;
     else if (~~ IsNotHeldOrTaken(bottle)) ! "misc.inf":12.3
       <<Close bottle>>;
 ],
;

! (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) <<Enter self>>;
       else { new_line; rtrue; }
     JumpOver:
       print "You don't make it all the way over. ";
       if (player in self) <<Jump>>;
       else <<JumpInto self>>;
  ],
  react_before [;
    ! ##Jump takes no noun or second, so use react_before to intercept it.
    Jump: if (player in self) <<JumpOn 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 <<Enter alley_one_door>>, the standard library
      ! would eventually generate <<Go alley_one_door>>, 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) <<Go w_obj>>;
  ],
  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)
  ! 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.
 has animate pluralname
 with 
  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: <<Search self>>; ],
;

! (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) <<PourInto toxicola second>>; 
  ],
;

! (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, ")^";
        <<Take 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:
      <<Climb self>>;
    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 referr 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:
       <<Examine self>>;
     PourInto:
       <<PourInto original_ln second>>;
     ! 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, ")^"; 
        <<Take x>>; 
      }
      "You're safer leaving the liquid nitrogen in ", (the) x, "."; 
    Insert, Transfer:
      print "(pouring ", (the) self, " into ", (the) second, ")^";
      <<PourInto self 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) <<Attack self>>;
         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 <<Give money_obj>> 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) <<Give noun self>>;
       <<Attack self>>;
  ],
;

! (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) <<Go n_obj>>;
  ],
  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:^^";
    <Examine maze_plaque>;
    "^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 [;
    <<LookUnder self>>;
  ],
  before [; 
    Search: 
      <<Examine self>>;
    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 one of four possible 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 four states by
  ! turning the light attribute on and off based 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.^";
        }
      }
  ],
  before [; 
     Burn:
       if (self hasnt on) {
         print "You turn on the flashlight. ";
         <<SwitchOn self>>;
       }
       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.";
  ],
;