!       -*-mode: Fundamental; tab-width: 4; -*-

Constant Story "Bane of the Builders";
Constant Headline "^An Interactive Short Story^
       Copyright (c) 2001 by Bogdan Baliuc^";
Release 6;
Constant MAX_SCORE = 100;
Constant OBJECT_SCORE = 10;
Constant ROOM_SCORE = 10;

Include "Parser";
Include "VerbLib";

! Properties

Property left_to;
Property right_to;
Property forward_to;
Property back_to;

! Globals

Global fMazeCreated;
Array maze --> 25;
Array cellstack --> 25;
Array nblist --> 4;
Array cellvisited --> 25;
Global mazedir;
Global cityState;
Array MyName --> 50;
Array MySurname --> 50;
Array name_array -> 53;
Array parse_array -> 14;

! Classes

Class IrisDoor
       with name 'iris' 'door',
       description [;
               print "An iris shaped door, large enough for two people to
               pass through.";
               if(self has open)
                       " The iris is open and there's a small slot to its
                       side on the wall.";
               " The iris is closed and there's a small slot to its side
               on the wall.";
       ],
       before [;
               Open: if(self has open)
                               "The iris door is already open.";
                       else
                               "You push, pull and kick the door, but you fail to open it.";
               Close: if(self has open)
                       {
                               give labdoor ~open;
                               give prisondoor ~open;
                               "You insert the card into the slot and the iris door
                               closes.";
                       }
                       else
                               "The iris door is already closed.";
       ],
       has door openable scenery static;

Class MazeRoom(25)
   with openings (-1) (-1) (-1) (-1),
       short_name "Sewer",
       description [i d nbptr;
               print "You are in a small, almost cubical compartment, whose
                       corners and edges have been rounded. Round hatches, made from
                       some sort of plastic are placed on all four walls";
               if (self.u_to == CityE)
                       print " and faint light filters down from an opening above";
               print ". ";
               nbptr = 0;
               for(i = 0: i < 4: ++i)
                       if((self.&openings)-->i ~= -1)
                               nblist-->(nbptr++) = i;
               if(nbptr == 1)
                       print "The hatch ";
               else
                       print "Hatches ";
               for(i=0: i < nbptr-1: ++i)
               {
                       d = ((nblist-->i) - mazedir + 4)%4;
                       if(i>0)
                               print ", ";
                       switch(d)
                       {
                               0: print "forward";
                               1: print "to your right";
                               2: print "to your back";
                               3: print "to your left";
                       }
               }
               if(nbptr>1)
                       print " and ";
               d = ((nblist-->(nbptr-1)) - mazedir + 4)%4;
               switch(d)
               {
                       0: print "forward";
                       1: print "to your right";
                       2: print "to your back";
                       3: print "to your left";
               }
               if(nbptr == 1)
                       print " is ";
               else
                       print " are ";
               "open.";
       ],
       d_to "You can't go that way.",
       u_to "You can't go that way.",
       left_to [d o;
               d = (mazedir+3)%4;
               o = (self.&openings)-->d;
               if(o > -1)
               {
                       mazedir = d;
                       give self ~visited;
                       return(maze-->o);
               }
               else
                       "That hatch is closed.";
       ],
       right_to [d o;
               d = (mazedir+1)%4;
               o = (self.&openings)-->d;
               if(o > -1)
               {
                       mazedir = d;
                       give self ~visited;
                       return(maze-->o);
               }
               else
                       "That hatch is closed.";
       ],
       back_to [d o;
               d = (mazedir+2)%4;
               o = (self.&openings)-->d;
               if(o > -1)
               {
                       mazedir = d;
                       give self ~visited;
                       return(maze-->o);
               }
               else
                       "That hatch is closed.";
       ],
       forward_to [d o;
               d = mazedir;
               o = (self.&openings)-->d;
               if(o > -1)
               {
                       mazedir = d;
                       give self ~visited;
                       return(maze-->o);
               }
               else
                       "That hatch is closed.";
       ],
       cant_go "You don't know which direction is which in this maze of
               pipes. You can only try to go 'left', 'right', 'back' and 'forward'.";

Class Slot
       with number 0,
       description [;
               print "It's small square slot, ";
               if(child(self) == nothing)
                       "currently empty.";
               print "containing a ";
               if(child(self).square)
                       print "black";
               else
                       print "white";
               " square.";
       ],
       before [;
               Receive:
                               if(child(self) ~= nothing)
                                       "There's already something in ", (the) self, ".";
                               if(noun provides square)
                                       rfalse;
                               print_ret (The) noun, " doesn't fit in the slot.";
               Shoot: blaster.charges--;
                       remove panel;
                       move melted_panel to real_location;
                       "You shoot at the panel, melting all the circuitry.";
       ],
       has static container open;

Class WhiteSquare
       with name 'white' 'square' 'squares//p',
       short_name "white square",
       plural "white squares",
       square 0,
       description "A small white square, made from an unknown metal.",
       before [;
               Shoot:
                       remove self;
                       blaster.charges--;
                       "You shoot the small square, melting it.";
       ];

Class BlackSquare
       with name 'black' 'square' 'squares//p',
       short_name "black square",
       plural "black squares",
       square 1,
       description "A small black square, made from an unknown metal.",
       before [;
               Shoot:
                       remove self;
                       blaster.charges--;
                       "You shoot the small square, melting it.";
       ];

Class ElevatorButton
       with
       contact [a b c;
               a = panel.slots(self.number*2);
               b = panel.slots(self.number*2+1);
               c = 0;
               if(child(a) == nothing || child(b) == nothing)
                       return(-1);
               if(child(b).square)
                       c++;
               if(child(a).square)
                       c = c + 2;
               return(c);
       ],
       description [;
               print "A circular light, resembling a button. It's
                       glowing ";
               if(self.contact() == Elevator.number)
                       "dimly.";
               "brightly.";
       ],
       before [x;
               Shoot: blaster.charges--;
                       remove panel;
                       move melted_panel to real_location;
                       "You shoot at the panel, melting all the circuitry.";
               Push, Touch:
                       x = self.contact() - 1;
                       if(x < 0)
                               "You touch the button, but nothing happens.";
                       print "As you touch the button, you feel a slight tingle
                               in the tip of your finger. ";
                       if(x == Elevator.number)
                               "Nothing else happens.";
                       print "The circular wall suddenly grows, covering the
                               opening";
                       if(Elevator.number == 1)
                               print "s as if they";
                       else
                               print " as if it";
                       print " never existed. You feel like you're ";
                       if(x > Elevator.number)
                               print "descending";
                       else
                               print "ascending";
                       Elevator.number = x;
                       print " with great speed. Finally you lurch to a halt and ";
                       switch(x)
                       {
                               0:
                                       Elevator.n_to = Cave;
                                       Elevator.s_to = nothing;
                                       Elevator.e_to = nothing;
                                       Elevator.w_to = nothing;
                                       "a portion of the wall dissolves, revealing an
                                       opening to the north.";
                               1:
                                       Elevator.n_to = nothing;
                                       Elevator.s_to = nothing;
                                       Elevator.w_to = CityW;
                                       Elevator.e_to = CityE;
                                       "portions of the wall dissolve, revealing
                                       openings to the east and west.";
                               2:
                                       Elevator.n_to = nothing;
                                       Elevator.s_to = nothing;
                                       Elevator.w_to = ControlRoom;
                                       Elevator.e_to = nothing;
                                       "a portion of the wall dissolves, revealing an
                                       opening to the west.";
                       }
       ],
       has scenery;

! Compass

CompassDirection left_obj "left hatch" compass
       with name 'left' 'hatch' 'wall',
       parse_name [n;
               if ((real_location provides openings) || (real_location == Ship))
               {
                       while(NextWord() == 'left' or 'hatch' or 'wall') n++;
                       return(n);
               }
               return(0);
       ],
       description [;
               return(HatchDesc(3));
       ],
       before [;
               Close:
                       if(real_location == Ship)
                               "There's no need to close the hatch now.";
                       return(HatchClose(3));
               Open:
                       if(real_location == Ship)
                               "The exit hatch is already open.";
                       return(HatchOpen(3));
               Shoot:  return(ShootWall(3));
       ],
       door_dir left_to;

CompassDirection right_obj "right hatch" compass
       with name 'right' 'hatch' 'wall',
       parse_name [n;
               if (real_location provides openings)
               {
                       while(NextWord() == 'right' or 'hatch' or 'wall') n++;
                       return(n);
               }
               return(0);
       ],
       description [;
               return(HatchDesc(1));
       ],
       before [;
               Open:   return(HatchOpen(1));
               Close:  return(HatchClose(1));
               Shoot:  return(ShootWall(1));
       ],
       door_dir right_to;

CompassDirection back_obj "back hatch" compass
       with name 'back' 'aft' 'hatch' 'wall',
       parse_name [n;
               if (real_location provides openings)
               {
                       while(NextWord() == 'back' or 'aft' or 'hatch' or 'wall') n++;
                       return(n);
               }
               return(0);
       ],
       description [;
               return(HatchDesc(2));
       ],
       before [;
               Open:   return(HatchOpen(2));
               Close:  return(HatchClose(2));
               Shoot:  return(ShootWall(2));
       ],
       door_dir back_to;

CompassDirection forward_obj "forward hatch" compass
       with name 'forward' 'fore' 'ahead' 'hatch' 'wall',
       parse_name [n;
               if (real_location provides openings)
               {
                       while(NextWord() == 'forward' or 'fore' or 'ahead' or 'hatch' or 'wall') n++;
                       return(n);
               }
               return(0);
       ],
       description [;
               return(HatchDesc(0));
       ],
       before [;
               Open:   return(HatchOpen(0));
               Close:  return(HatchClose(0));
               Shoot:  return(ShootWall(0));
       ],
       door_dir forward_to;

! Object tree

Object City "City Daemon Object"
       with number 0,
       daemon [;
               if(cityState < 4)
               {
                       if(self.number > 4)
                       {
                               self.number = 0;
                               ChangeCity();
                       }
               }
               else
                       StopDaemon(self);
       ];

Object goggles "pair of goggles"
       with name 'pair' 'goggles' 'glasses',
       description "A pair of goggles, with dark lenses.",
       has clothing;

Object bluecloth "blue cloth"
       with name 'blue' 'cloth',
       initial "A piece of worn blue cloth is laying on the bottom of the pipe.",
       description
               "It's a piece of blue cloth, the color faded by time.",
       after [;
               Examine, Search:
                       if(keycard in self)
                       {
                               move keycard to real_location;
                               "As you search the blue cloth, something shiny drops
                               from it.";
                       }
               Shoot:
                       remove self;
                       blaster.charges--;
                       "You quickly reduce the piece of cloth to ashes.";
               Wear:
                       give bluecloth worn;
                       "You wrap the piece of cloth around your hand.";
       ],
       has clothing;

Object -> keycard "metal rectangle"
       with name 'metal' 'rectangle' 'card' 'keycard',
       initial "A shiny metal rectangle has fallen from the cloth.",
       description
               "It's a small metal rectangle, resembling a credit card.
               It has various indentations on both sides.",
       has scored;

Object Crater "Bottom of Crater"
       with description
               "While from orbit it looked like a meteor crater, once you've
               landed it became clear it's artificial in origin. Time and
               weather had left their imprints, but the crater still looks
       like a perfect bowl, the flat bottom curving smoothly upwards
       until it becomes almost vertical. The small shuttle that
       brought you here from orbit is standing in the middle of the
       crater, waiting for you.^To the south, a black rectangle
               marks the entrance to the tunnel the Professor vanished in
               hours ago.",
       in_to Ship, n_to Ship,
       s_to entrance, d_to entrance,
   out_to "You are already outside!",
   cant_go "The walls of the crater are too smooth to climb.",
       after [;
               Go: ! Create the maze here, instead of Initialise,
                       ! giving the player a chance to type 'random' first
                       if(~~fMazeCreated)
                       {
                               fMazeCreated = 1;
                               CreateMaze();
                       }
       ],
       has light;

Object -> shuttleView "shuttle"
       with name 'shuttle' 'ship' 'spaceship',
       description "It's your shuttle. You know every dent on the hull and
               circuit inside her by heart.",
       has scenery static;

Object -> entrance "entrance"
       with name 'entrance' 'black' 'rectangle' 'dark' 'doorway',
       description
               "It's a dark doorway cut into the smooth stone of the crater.
               Sensors scan from orbit show that behind it is a tunnel that
               descends steeply.",
       door_to Tunnel,
       door_dir d_to,
       has scenery static door open;

Object Ship "Shuttle"
   with name 'array' 'controls' 'hatch',
       description
               "It's a standard G-12 model shuttle, able to carry two
               people and their equipment from orbit to the surface of a
               planet and back. On the left side, the pilot seat in front
               and the passenger behind it take up most of the space. On the
               right side, a storage bin leaves only a narrow lane on the center,
               allowing access to the seats. The exit hatch is to your left,
               facing south.",
   out_to Crater,
       s_to Crater,
       left_to Crater,
       has light;

Object -> pilotseat "pilot seat"
       with name 'pilot' 'front' 'seat' 'seats' 'chair' 'chairs',
       description
               "That's the place where you spent endless hours during the
               flight. An array of controls is lined up in front of it.",
       before [;
               Shoot: "Careful, you don't want to start a fire in the
                       shuttle";
       ],
       has scenery static supporter enterable;

Object -> passengerseat "passenger seat"
       with name 'passenger' 'back' 'rear' 'seat' 'seats' 'chair' 'chairs',
       description
               "This is where your cargo usually sits. In this case, the
               Professor, if you manage to find him in one piece.",
       before [;
               Shoot: "Careful, you don't want to start a fire in the
                       shuttle";
       ],
       after [;
               Examine:
                       if (blaster has concealed)
                       {
                               print "The professor seems to have forgotten
                                       his blaster.";
                               give blaster ~concealed;
                       }
               Enter:
                       if (blaster has concealed)
                       {
                               print "You hit something hard as you sit. The
                                       Professor has forgotten his blaster.";
                               give blaster ~concealed;
                               rtrue;
                       }
       ],
       has scenery static supporter enterable;

Object -> blaster "blaster"
       with name 'gun' 'plasma' 'blaster',
       charges 25,
       setting 1,
       initial
               "A blaster lies on the passenger seat.",
       description [;
               print "It's a military blaster, a gun that shoots
                       a thin stream of hot plasma. While not powerful
                       enough to melt metal, it's still a devastating
                       weapon at close range. The blaster is currently
                       set to ";
               if(self.setting)
                       print "kill";
               else
                       print "stun";
               print " and the power meter is ";
               if(self.charges>10) "green.";
               if(self.charges>3) "yellow.";
               if(self.charges>0) "red.";
               "dark.";
       ],
       before [;
               Shoot: "That's an interesting idea...";
               SetTo:
                       switch(second)
                       {
                               'stun':
                                       self.setting = 0;
                                       "You adjust the blaster power level to ~stun~.";
                               'kill':
                                       self.setting = 1;
                                       "You adjust the blaster power level to ~kill~.";
                               default:
                                       "You can only set your blaster to ~stun~ or
                                       ~kill~.";
                       }
       ],
       has concealed scored;

Object -> storagebin "storage bin"
       with name 'storage' 'bin' 'container',
       description [;
               print "This is where you store everything that's not
                       bolted down during the flight. The Professor removed
                       all the scientific equipment before he left. The bin
                       is ";
               if(self has open)
                       "open.";
               "closed.";
       ],
       before [;
               Shoot: "You don't really want to start a fire in the
                       shuttle.";
       ],
       has scenery container openable;

Object -> -> flashlight "atomic flashlight"
       with name 'flashlight' 'atomic',
   description
                "A standard issue atomic flashlight. It will
               still provide light long after you've turned to dust.",
       before [;
               Shoot: print "The flashlight is Navy issue. The blaster
                       can't melt it";
                       if(flashlight in player)
                       {
                               move flashlight to real_location;
                               move blaster to real_location;
                               ", but it burns your hand and you drop both.";
                       }
                       print ".";
                       rfalse;
       ],
       after [;
               SwitchOn:
                       give self light;
               SwitchOff:
                       give self ~light;
               Take:
                       give self ~concealed;
       ],
       has switchable;

Object Tunnel "Tunnel"
       with description
               "You're in a dark tunnel that steadily descends for several
               hundred meters in a straight line. The walls are made from
               the same grayish smooth stone as the crater. To the north,
               you can see a faint light marking the exit to the surface.
               The tunnel continues toward the south and deeper into the
               ground.",
       n_to Crater,
       s_to Tunnel2,
       u_to Crater,
       d_to Tunnel2;

Object -> walls "walls"
       with name 'wall' 'walls' 'floor' 'ceiling',
       description
               "The tunnel is made from the same gray stone as the crater.",
       before [;
               Shoot: blaster.charges--;
                       "You shoot randomly at the tunnel walls but nothing happens.";
       ],
       has scenery static;

Object Tunnel2 "Window"
       with description
               "The tunnel continues its steep descent, but it's no longer
               dark. The west wall is made from some sort of transparent
               material that lets in a glow from the cave beyond. The cave
               is huge, its walls stretching out of sight. Three disks seem
               suspended in the center, stacked one above the other, each a
               few hundred meters in diameter.",
       n_to Tunnel,
       u_to Tunnel,
       s_to Cave,
       d_to Cave,
       cant_go "The tunnel stretches in a north-south direction.",
       has light;

Object -> window "window"
       with name 'west' 'wall' 'window' 'cave' 'disk'
       'disks' 'top' 'bottom' 'middle',
       description
               "Through the window you can see three disks of the same size
               suspended in the middle of a huge cave. A metallic bridge
               leads away from the topmost disk, out of sight and you can see
               some colors shifting on the top of the second one. The third
               disk is almost entirely covered by the second, so you can't
               make out anything about it.",
       before [;
               Attack: "You hit the window until you get tired, but you can't
                       even see a scratch on it after your efforts.";
               Shoot: blaster.charges--;
                       "As the plasma arc touches the window, it reflects,
                       sizzling on the wall near you. That was close!";
       ],
       has scenery static;

Object Cave "Cave"
       with description
               "The tunnel ends abruptly here, leaving you on a narrow
               metal bridge that extends south above the topmost disk
               toward a shiny cylinder at its center. Bright white
               light escapes from under the disk, giving the cave an
               eerie glow.",
       n_to Tunnel2,
       u_to Tunnel2,
       s_to Elevator,
       d_to Elevator,
       has light;

Object -> bridge "bridge"
       with name 'metal' 'bridge' 'railing' 'railings',
       description
               "It's a narrow bridge, just wide enough for you to walk
               unhindered. It's made from some sort of metal and despite
               its apparent fragility it feels rock solid under your feet.
               Safety railings run across its length, on both sides,
               reaching up to your chest in height.",
       before [;
               Shoot:
                       blaster.charges--;
                       if(blaster.setting)
                       {
                               deadflag = 1;
                               "You aim at the bridge under your feet and squeeze the
                               trigger. Nothing happens at first, but then the metal
                               turns slowly red and with a terrible noise it breaks,
                               dropping you into the darkness below.";
                       }
                       "You aim at the bridge under your feet and squeeze the
                       trigger. The metal turns slightly red, where the discharge
                       hits the metal, but it has no other effect.";
       ],
       has scenery static;

Object -> disk2
       with name 'disk' 'top' 'topmost' 'cave',
       description
               "Looking down is not a good a idea, although the railings
               on the bridge prevent you from falling. The top disk obscures
               the others and is surrounded by a thin halo of light.",
       has scenery static;

Object Elevator "Cylinder"
       with number 0,
       description [;
               print "You're in a metallic cylinder, about ten meters tall
                       and thirty in diameter. ";
               if(panel in Elevator)
               {
                       if(panel has open)
                               print "A small panel on the wall is open and ";
                       else
                               print "A small panel with three lighted buttons is on
                               the wall and ";
                       switch(self.number)
                       {
                               0: "a rectangular opening to the north reveals a
                                       metallic bridge.";
                               1: "rectangular openings to the east and west lead
                                       to well-lighted areas.";
                               2: "a rectangular opening to the west leads into
                                       darkness.";
                               default: "you just found a bug!";
                       }
               }
               rtrue;
       ],
       n_to Cave,
       s_to nothing,
       e_to nothing,
       w_to nothing,
       has light;

Object -> buttons "buttons"
       with name 'lights' 'buttons',
       description "Three yellow glowing buttons, placed vertically.",
       has scenery static;

Object -> panel "panel"
       with name 'panel' 'controls' 'circuitry' 'slots',
       slots [nr;
               switch(nr)
               {
                       0: return(slot1);
                       1: return(slot2);
                       2: return(slot3);
                       3: return(slot4);
                       4: return(slot5);
               }
               return(slot6);
       ],
       description [i haveblack havewhite;
               if(self has open)
               {
                       print "Behind the panel you can see three contacts,
                               corresponding to the position of the three buttons.
                               Each contact leads to two slots to the right, in an
                               array of six slots. The slots ";
                       haveblack = 0;
                       havewhite = 0;
                       for(i = 0: i < 6: ++i)
                               if(child(self.slots(i)) ~= nothing)
                                       if(child(self.slots(i)).square)
                                               haveblack = 1;
                                       else
                                               havewhite = 1;
                       if((~~haveblack) && (~~havewhite))
                               print "are empty.";
                       else if(haveblack && havewhite)
                               print "contain white and black metal squares.";
                       else if(haveblack)
                               print "contain some black squares.";
                       else
                               print "contain some white squares.";
                       font off;
                       print "^^  +---+^";
                       for(i = 0: i < 6: ++i)
                       {
                               if(child(self.slots(i)) == nothing)
                                       print "  !   !^";
                               else if(child(self.slots(i)).square)
                                       print "  ! B !^";
                               else
                                       print "  ! W !^";
                               if(i % 2)
                                       print "  +---+^";
                       }
                       font on;
                       rtrue;
               }
               "It's a rectangular panel, etched in the surface of
               the cylinder. Three lights, resembling buttons,
               are placed vertically on it.";
       ],
       before [;
               Pull: <<Open self>>;
               Push: <<Close self>>;
               Shoot: blaster.charges--;
                       remove panel;
                       remove elButton1;
                       remove elButton2;
                       remove elButton3;
                       move melted_panel to location;
                       "You shoot at the panel, melting all the circuitry.";
               Receive: "In which slot do you want to insert ", (the) noun, "?";
       ],
       after [;
               Open: give self transparent;
                       remove elButton1;
                       remove elButton2;
                       remove elButton3;
                       remove buttons;
                       "You grip the edge of the panel firmly with your
                       fingers and pull. It opens to one side, revealing
                       the circuitry behind.";
               Close: give self ~transparent;
                       move buttons to location;
                       move elButton3 to location;
                       move elButton2 to location;
                       move elButton1 to location;
                       "You push the panel back in its place.";
       ],
       has scenery container openable;

Slot -> -> slot1 "first slot"
       with name 'first' 'slot' '1//' 'row' 'top';
WhiteSquare -> -> ->;

Slot -> -> slot2 "second slot"
       with name 'second' 'slot' '2//' 'row';
BlackSquare -> -> ->;

Slot -> -> slot3 "third slot"
       with name 'third' 'slot' '3//' 'row';
BlackSquare -> -> ->;

Slot -> -> slot4 "fourth slot"
       with name 'fourth' 'slot' '4//' 'row';
WhiteSquare -> -> ->;

Slot -> -> slot5 "fifth slot"
       with name 'fifth' 'slot' '5//' 'row';

Slot -> -> slot6 "sixth slot"
       with name 'sixth' 'slot' '6//' 'row';
BlackSquare -> -> ->;

ElevatorButton -> elButton1 "top button"
       with name 'first' 'top' 'topmost' 'button' 'light' '1//',
       number 0;

ElevatorButton -> elButton2 "middle button"
       with name 'second' 'middle' 'button' 'light' '2//',
       number 1;

ElevatorButton -> elButton3 "bottom button"
       with name 'third' 'bottom' 'button' 'light' '3//',
       number 2;

Object melted_panel "panel"
       with name 'panel' 'controls' 'circuitry' 'slots',
       initial "The melted remains of a control panel are on the wall.",
       description "It once was a control panel, but it's now melted
               beyond recognition.",
       before [;
               Open: "That's not something you can open anymore.";
               Close: "That's not something you can close anymore.";
               Shoot: "You've already caused enough damage to the panel.";
       ],
       has static;

Object alien "alien"
       with name 'being' 'beings' 'alien' 'aliens'
               'image' 'images' 'humanoid' 'humanoids',
       found_in CityN CityE CityS CityW Lab Library School,
       parse_name [ n;
               if(cityState == 0 or 1 or 2)
               {
                       while(NextWord() == 'alien' or 'aliens' or 'being'
                               or 'beings' or 'image' or 'images' or 'humanoid'
                               or 'humanoids') n++;
                       return(n);
               }
               return(0);
       ],
       description
               "Those must be the Builders! Humanoid in shape, their skin has
               a translucent quality and they have big black eyes without a
               visible iris. As you take a better look at them you realize
               that they are half-transparent.",
       before [;
               Push, Pull, Touch, Attack, Take, Search:
                       "You try to grab one of the passerby but your hand
                       passes through it as if it was just an illusion. The
                       alien ignores you.";
               Taste, Kiss:
                       "Spotting a particularly good looking alien you step in
                       front of it and open your mouth for a kiss. The alien
                       passes through you, unabashed.";
               Wave, WaveHands, Ask, Order:
                       "Despite your efforts to be noticed, the aliens
                       completely ignore you.";
               Shoot:
                       blaster.charges--;
                       "You point your blaster at an alien and shoot. The plasma
                       arc passes through it without any noticeable effect.";
       ],
       has scenery animate;

Object bodies "bodies"
       with name 'alien' 'aliens' 'being' 'beings' 'body' 'bodies',
       found_in CityW CityN CityE Library Lab School,
       parse_name [ n;
               if(cityState ~= 3)
                       return(0);
               if(real_location == CityE)
                       while(NextWord() == 'alien' or 'being' or 'body') n++;
               else
                       while(NextWord() == 'alien' or 'aliens' or 'being' or
                               'beings' or 'body' or 'bodies') n++;
               return(n);
       ],
       description [;
               if(real_location == CityE)
                       "The alien look dead.";
               "The alien bodies look dead.";
       ],
       before [;
               Push, Pull, Touch, Attack, Take, Search:
                       print "You kneel by ";
                       if(real_location == CityE)
                               print "the";
                       else
                               print "an";
                       " alien body and try to grab something, but your hand
                       passes through it.";
               Taste, Kiss:
                       "A dead alien body?";
               Wave, WaveHands, Ask, Order:
                       "Nobody alive seems to be here.";
               Shoot:
                       blaster.charges--;
                       "You point your blaster at a body and shoot. The plasma
                       arc passes through it without any noticeable effect.";
       ],
       has scenery static;

Object vehicle "vehicle"
       with name 'vehicle' 'vehicles' 'car' 'cars',
       found_in CityN CityS CityW,
       parse_name [n;
               if(cityState < 3)
               {
                       while(NextWord() == 'vehicle' or 'vehicles' or 'car'
                               or 'cars') n++;
                       return(n);
               }
               if((cityState == 4) && (real_location == CityW))
               {
                       while(NextWord() == 'vehicle' or 'car' or 'wreckage') n++;
                       return(n);
               }
               return(0);
       ],
       description [;
               if(cityState < 3)
                       "The alien vehicles resemble small parallelepipeds,
                       floating above the ground.";
               "The vehicle might have once been parallelepipedical in shape,
               but it's now deformed and charred beyond recognition.";
       ],
       before [;
               Wave, WaveHands, Ask, Order:
                       "Despite your efforts to be noticed, the aliens
                       completely ignore you.";
               Shoot:
                       blaster.charges--;
                       "You point your blaster at a vehicle and shoot. The plasma
                       arc passes through it without any noticeable effect.";
       ],
       has scenery static;


Object archbridge "metal bridge"
       with name 'metal' 'bridge' 'bridges',
       found_in CityN CityE CityS CityW,
       description "Two wide metal bridges are leading toward other
               sections.",
       has scenery static;

Object bigscreen "big screen"
       with name 'big' 'screen' 'display' 'tv',
       found_in CityE CityS CityW,
       parse_name [n;
               if(cityState == 1)
               {
                       while(NextWord() == 'big' or 'screen' or 'display'
                               or 'tv') n++;
                       return(n);
               }
               return(0);
       ],
       description "On the big screen you can see a scene from a
               laboratory. Aliens dressed in blue suits, wearing protection
               goggles are scrambling in panic as a black mist pours out
               from a broken bell shaped transparent case. The scene
               is replayed again and again.",
       has scenery static;

Object cylinder "metallic cylinder"
       with name 'metallic' 'cylinder' 'elevator',
       found_in CityN CityE CityS CityW,
       description [;
               print "A smooth metallic cylinder raises from floor
                       straight up into the light above";
               if(location == CityN or CityS)
                   ", but there's no opening in it.";
               ". There's an opening in it.";
       ],
       has scenery static;

Object CityW "Square"
       with
       description [;
               switch(cityState)
               {
                       0: print "The scene in front of you vaguely resembles a
                               busy square on Earth at noon. You're sitting in a large
                               triangular area, bustling with activity. Tall, thin
                               beings, dressed in all the colors of the rainbow
                               walk around leisurely or in small floating vehicles.
                               Pastel pink, bright yellow, light green; there are as
                               many colors as people, shining brightly in the light
                               that comes from the disk above, giving the impression
                               that you're in a city on the surface of the
                               planet, not deep underground. The people walk, or run
                               or stand, they come and go from the building to the
                               west, they go over the bridges to northeast and
                               southeast, all without paying any attention to you.";
                       1: print "The scene in front of you vaguely resembles a
                               busy square on Earth at noon. You're sitting in a large
                               triangular area, delimited by a low building to the west
                               and bridges to northeast and southeast. Tall, thin beings,
                               dressed in a mix of bright colors are walking on foot or
                               traveling in small floating vehicles. Most of them,
                               though, are gathered outside the building where some sort
                               of screen or giant TV has been placed, watching intently.
                               As usual, nobody pays you any attention.";
                       2: print "The street in front of you is almost deserted. A few
                               tall, vaguely humanoid creatures are entering or leaving a
                               building to the west and a couple of small vehicles speed
                               by. Bridges are leaving this area to the northeast and
                               southeast. As you are watching, one of the aliens, dressed
                               in the same bright colors as the rest, but surrounded by
                               strange black aura starts hitting another until the second
                               drops to the ground.";
                               ChangeCity();
                               rtrue;
                       3: print "A few alien bodies are lining the floor in front of
                               a low building to the west. Their colorful clothes are torn
                               and covered with a green fluid that seems spread
                               everywhere. A blackened vehicle lies crushed against a
                               pillar of the northeast bridge. Nothing moves.";
                       default: print "You're standing on a metal platform, triangular
                               in shape, extending to the edge of the disk in west. Just
                               at the edge is a low white building and metal bridges link
                               it to other platforms, to northeast and southeast.";
               }
               "^To the east, there is a metallic cylinder, raising
               up out of sight into the light. There's an opening in it.";
       ],
       ne_to CityN,
       se_to CityS,
       e_to Elevator,
       w_to Library,
       has light;

Object -> buildingW "low building"
       with name 'low' 'building' 'entrance',
       description [;
               print "A long, low building occupies the western part of this
               section. It has no visible windows or other openings that you
               can see, except for an entrance in the middle that seems to be
               open.";
               if(cityState < 3)
                       print " Alien beings come and go, ignoring you.";
               rtrue;
       ],
       before [;
               Shoot: "Shooting at the building won't accomplish anything.";
               Enter: PlayerTo(Library);
                       rtrue;
       ],
       has scenery static;

Object CityE "Park"
       with
       description [;
               switch(cityState)
               {
                       0: print "A few steps away from you, the metal floor of
                               this large triangular platform becomes covered with grass.
                               Tall, thin beings, dressed in all the colors of the
                               rainbow, walk leisurely or sit around what looks like
                               a round pool. A couple of smaller aliens (children?)
                               stand in front of each other, throwing and catching
                               some colored disks. Metal bridges arch gracefully to
                               other areas to northwest and southwest. Nobody is
                               paying any attention to you.";
                       1: print "A few steps away from you, the metal floor of
                               this large triangular platform becomes covered with grass.
                               Tall, thin beings, dressed in a mix of colors are
                               sitting by a round pool watching intently a big
                               screen that has been erected on the other side of it.
                               As usual, you are completely ignored.";
                       2: print "A few steps away from you, the metal floor of
                               this large triangular platform becomes covered with grass.
                               A couple of small aliens seem to be playing by a round pool
                               and a bigger one is watching them. Suddenly, one of the
                               smaller beings is surrounded by a black aura, like a mist
                               and it rushes at the other, throwing it into the pool.";
                               ChangeCity();
                               rtrue;
                       3: print "A few steps away from you, the metal floor of
                               this large triangular platform becomes covered with grass.
                               A single alien body lies face down by a round pool, with
                               green fluid pouring from a torn limb. Everything is still.";
                       default: print "A few steps away from you, the metal floor
                               of this large triangular platform is lowered a few steps,
                               then continues toward the edge of the disk. The only
                               features are a round hole in the middle of the platform
                               and metal bridges to northwest and southwest, leading to
                               other platforms.";
               }
               "^To the west, there is a metallic cylinder, raising
               up out of sight into the light. There's an opening in it.";
       ],
       nw_to CityN,
       sw_to CityS,
       w_to Elevator,
       has light;

Object -> grass "grass"
       with name 'grass',
       description "Looks just like ordinary grass.",
       before [;
               Touch, Take, Eat:
                       "You bend down and try to pick a handful, but your
                       hand passes right through it.";
               Shoot:
                       blaster.charges--;
                       "You shoot at the grass, but it doesn't burn, it doesn't
                       sizzle. In fact, nothing happens to it";
       ],
       has scenery static;

Object -> pool "round pool"
       with name 'round' 'pool' 'water',
       description
               "It's a circular pool of water, about 20 meters across, in the
               middle of the park. When you look at it closer, the water
               shimmers oddly.",
       before [;
               Touch, Drink, Take:
                       "As you try to touch the water surface, it doesn't feel
                       wet at all. You cup your hand, but when you remove it from
                       the pool, it's empty. The pool is just an illusion.";
               Shoot: blaster.charges--;
                       "You shoot at the pool, but, oddly, the water doesn't boil.
                       In fact, nothing happens.";
               Enter: <<Dive>>;
       ],
       has scenery static;

Object hole "round hole"
       with name 'round' 'hole',
       description
               "It's a circular hole, about 20 meters in diameter and 2 meters
               deep. It's walls are slightly inclined, which would allow you to
               climb in or out with some difficulty.",
       before [;
               Enter: print "You lower yourself down into the hole and carefully
                       advance to the middle. Suddenly, the floor gives way under
                       your feet and you fall...^^";
                       PlayerTo(maze-->14);
                       rtrue;
       ],
       has scenery static;

Object CityN "Guarded Area"
       with
       description [;
               switch(cityState)
               {
                       0: print "Tall, thin, almost human, alien beings dressed in
                               all the colors of the rainbow walk from a bridge to the
                               southeast to another one to southwest or viceversa. Small
                               floating vehicles zip by. Nobody stops here, except a
                               group of four aliens, dressed in white, who seem to
                               guard the entrance into a building to the north. Everyone
                               is ignoring you.";
                       1: print "In front of a building at the north end of this
                               triangular area, alien beings have gathered. There are
                               two groups and they seem to be arguing. One group is
                               completely dressed in white and apparently tries to
                               prevent the other from entering the building. Nobody
                               pays you any attention.";
                       2: print "A group of alien beings dressed in white are
                               guarding the entrance to a building to the north. They
                               are carrying what look like hand weapons and are shooting
                               at another alien surrounded by a black aura. As the alien
                               falls to the ground, the black aura rises and wraps
                               itself around one of the guardians, who immediately starts
                               shooting at its colleagues.";
                               ChangeCity();
                               rtrue;
                       3: print "White clad alien bodies are laying near the entrance
                               of a building to the north. Metal bridges leave this
                               triangular area to southwest and southeast. Everything is
                               still.";
                       default: print "You are in a large triangular area, delimited by
                               metal bridges to the southeast and southwest and a low gray
                               building to the north.";
               }
               "^To the south, there is a metallic cylinder, raising
               up out of sight into the light, but you can't see any
               opening in it.";
       ],
       se_to CityE,
       sw_to CityW,
       n_to Lab,
       has light;

Object -> buildingN "low building"
       with name 'low' 'building' 'house',
       description "The building fills almost entirely the north side of
               the triangle. It has no windows, only a wide open doorway.",
       before [;
               Shoot: "Shooting at the building won't accomplish anything.";
               Enter: PlayerTo(Lab);
                       rtrue;
       ],
       has scenery static;

Object CityS "Quiet Area"
       with name 'pole',
       description [;
               switch(cityState)
               {
                       0: print "You are in a quiet triangular area, with metal
                               bridges leading to other triangles to the northeast
                               and northwest. Tall and thin, alien beings dressed in
                               all the colors of the rainbow lead smaller aliens,
                               presumably children toward a low building to the south.
                               Nobody pays you any attention.";
                       1: print "You are in a quiet triangular area, with metal
                               bridges leading to other triangles to the northeast
                               and northwest. Tall and thin, alien beings dressed in
                               all the colors of the rainbow are gathered around a
                               big screen affixed on a pole, discussing in low, musical
                               tones. You are completely ignored.";
                       2: print "Small alien beings are hurriedly leaving a low
                               building to the south, joining taller aliens that are
                               waiting for them. Large vehicles come and go and many
                               wounded aliens are carried inside a building to the
                               south.";
                               ChangeCity();
                               rtrue;
                       3: print "You are in a quiet triangular area, with metal
                               bridges leading to other triangles to the northeast
                               and northwest. A long, low building lines the south side.
                               Alien bodies are scattered on the ground and everything
                               is still.";
                       default: print "You are in a quiet triangular area, with metal
                               bridges leading to other triangles to the northeast
                               and northwest. A long, low building lines the south side.";
               }
               "^To the north, there is a metallic cylinder, raising
               up out of sight into the light, but you can't see any
               opening in it.";
       ],
       nw_to CityW,
       ne_to CityE,
       s_to School,
       has light;

Object -> buildingS "low building"
       with name 'low' 'building' 'house',
       description "The building fills almost entirely the south side of
               the triangle. It has no windows, only a wide open doorway.",
       before [;
               Shoot: "Shooting at the building won't accomplish anything.";
               Enter: PlayerTo(School);
                       rtrue;
       ],
       has scenery static;

Object Library "Library"
       with description [;
               switch(cityState)
               {
                       0:      print "This large room is divided into two sections. The
                               northern section contains countless rows of shelves,
                               delimiting aisles. Machines glide quietly in front of
                               the shelves, retrieving or returning small cartridges.
                               Alien beings are seated in the south section, manipulating
                               devices with small screens. Everybody seems to ignore your
                               presence.";
                       1:  print "This large room is divided into two sections. The
                               northern section countless rows of shelves,
                               delimiting aisles. Machines glide quietly in front of
                               the shelves, retrieving or returning small cartridges.
                               Alien beings are seated in the south section, talking
                               excitedly. Everybody ignores you.";
                       2:      print "This large room is divided into two sections. A few
                               aliens sit in the south side, intently studying the small
                               screens in front of them. From between two shelves in the
                               north area, another alien, surrounded by a black aura,
                               throws an object toward the others and rushes by you
                               toward the exit. A powerful explosion takes place in the
                               south area, covering it from your view.";
                               ChangeCity();
                               rtrue;
                       3:  print "Wrecked machinery and alien bodies are lining the
                               southern part of this room. In the northern part you can
                               see a lot of collapsed shelves.";
                       default: print "Wrecked machinery and alien bodies are lining
                               the southern part of this room. In the north part you can
                               see a lot of collapsed shelves.";
               }
               " You can leave the building through a door to the east.";
       ],
       e_to CityW,
       has light;

Object -> shelves
       with name 'shelf' 'shelves',
       description [;
               if(cityState <= 2)
                       "The shelves contain many cartridges, that are retrieved and
                       replaced by some machines.";
               else
                       "Most of the shelves have collapsed, burying some machinery
                       under them. They look very unstable.";
       ],
       before [;
               Shoot: "Your blaster isn't nearly powerful enough to melt all
                       that metal.";
       ],
       has scenery static;

Object -> device "device"
       with name 'machinery' 'device' 'machine' 'machines' 'reader'
               'slot' 'display' 'screen',
       description [;
               switch(cityState)
               {
                       0,1,2:
                               "The devices in the southern part of the room are some
                               sort of readers. Aliens insert small cartridges into them
                               then watch the attached display. One of the devices seems
                               unoccupied, its display dark.";
                       default: "Most of the devices have been torn apart. Only one
                               appears unharmed. It has a slot and a display. The display
                               is dark.";
               }
       ],
       before [;
               Shoot: "And destroy a priceless piece of alien technology?";
               Receive:
                       if(noun == cartridge)
                       {
                               PlayMovie();
                               rtrue;
                       }
                       print_ret (The) noun, " doesn't fit in the machine.";
               SwitchOn:
                       "There's no obvious way to turn the device on.";
               SwitchOff:
                       "Looks like it's already off. At least, the screen is dark.";
       ],
       has scenery static;

Object Lab "Lab"
       with description [;
               switch(cityState)
               {
                       0: print "Metal tables line the east and west walls of this room.
                               Aliens dressed in blue tunics swarm back and forth, taking,
                               showing things to each other, but mostly examining a tall
                               glass case in the center of the room, that contains a black
                               swirling mist. Two white-clad aliens are guarding a door to
                               the north. You are completely ignored.";
                       1: print "Metal tables line the east and west walls of this room.
                               Aliens dressed in blue tunics run back and forth in panic as
                               a black swirling mist spreads forth from a broken glass case
                               in the center of the room. Two white-clad aliens are guarding
                               a door to the north. Nobody is paying you any attention.";
                       2: print "Metal tables line the east and west walls of this room.
                               Aliens dressed in blue tunics run in panic around a broken
                               glass case in the middle of the room. As you watch, a black
                               shadow engulfs one of the two white clad aliens that were
                               guarding a door to the north. Immediately, it starts shooting
                               at the other aliens.";
                               ChangeCity();
                               rtrue;
                       3: print "Metal tables and alien bodies line the walls of this
                               room. Most of the bodies have blue tunics, but one, lying
                               in front of a door to the north, is dressed in white. A
                               broken glass case sits in the middle of the room.";
                       default: print "Metal tables line the walls of this room. A
                               broken glass case sits in the middle and a door leads north.";
               }
               " The exit is to the south.";
       ],
       after [;
               Go:     if(Prison.number==2)
                               "The Professor runs after you, catching up after a few
                               steps.";
       ],
       s_to CityN,
       n_to labdoor,
       has light;

Object -> mist "black mist"
       with parse_name [n;
               if(cityState == 1)
               {
                       while(NextWord() == 'black' or 'mist' or 'shadow') n++;
                       return(n);
               }
               return(0);
       ],
       description "A black mist pours out of the broken case. The aliens seem
       to be desperate not to be touched by it.",
       has scenery static;

IrisDoor -> labdoor "door"
       with door_to Prison,
       door_dir n_to;

Object -> case "glass case"
       with name 'glass' 'case' 'box' 'bell',
       description [;
               if(~~cityState)
                       "It's a bell-shaped, transparent case, almost as tall
                       as you. It contains some sort of black gas or mist that
                       swirls inside.";
               else
                       "Originally, it was probably bell-shaped, but the case is
                       now broken. Almost as tall as you, is made from a
                       transparent material.";
       ],
       before [;
               Shoot: blaster.charges--;
                       "You shoot the case and the beam reflects back, missing you
                       by an inch. That was close!";
       ],
       has scenery static;

Object -> doorslot "small slot"
       with name 'small' 'slot',
       description "Judging by its dimensions you could insert in it something
               about the size of a credit card.",
       found_in Lab Prison,
       before [;
               Receive:
                       if(noun == keycard)
                       {
                               print "As you insert the small rectangle into the slot, the
                                       iris door ";
                               if(labdoor has open)
                               {
                                       give labdoor ~open;
                                       give prisondoor ~open;
                                       "closes silently.";
                               }
                               else
                               {
                                       give labdoor open;
                                       give prisondoor open;
                                       "opens silently.";
                               }
                       }
                       print_ret (The) noun, " doesn't fit in the slot.";
       ],
       has container open scenery static;

Object -> cartridge "cylindrical cartridge"
       with name 'cylinder' 'cylindrical' 'cartridge',
       initial "A small cylindrical cartridge glitters under a table.",
       description "It's a metallic cylinder, about two inches long. It
               has a small inset at one end, but you can't see any way of
               opening it.";

Object Prison "Small Room"
       with number 0,
       description [;
                       print "You're in a small room, divided in two by a
                       transparent partition, made from the same material
                       as the case in the lab. On your side of the partition,
                       a switch is on the side wall and an iris shaped door
                       leads back south. ";
                       switch(self.number)
                       {
                               0: "On the other side of the partition, you can
                                       see the Professor sitting on the floor, with
                                       his head propped on his knees.";
                               1: "On the other side of the partition, you can
                                       see the Professor, looking at you hopefully.";
                               default: "A rectangular opening is in the middle
                                       of the partition.";
                       }
       ],
       daemon [;
               switch(self.number)
               {
                       0,1:
                               if(prisonwall has open)
                               {
                                       self.number = 2;
                                       if(goggles has worn)
                                               print "You see the black shadow crawling up the
                                               Professor's leg and wrapping around him. ";
                                       "As the wall slides open, the Professor pulls a long,
                                       gleaming knife out of somewhere and runs straight for
                                       you!";
                               }
                       2:
                               if(~~Professor.status)
                               {
                                       deadflag = 1;
                                       self.number = 4;
                                       "^^With a shout of triumph, the Professor plunges his
                                       knife deep in your chest. As you fall down, the last
                                       thing you notice is the black aura shifting around
                                       him.^The Bane that possesses him is finally free to
                                       destroy the mankind just as it destroyed the Builders.";
                               }
                               move shadow to location;
                               print "As the Professor falls, you can ";
                               if(goggles has worn)
                                       print "see a black mist";
                               else
                                       print "feel an alien presence";
                               print " raising from his body and wrapping itself around
                                       you. ";
                               if(belt has worn)
                               {
                                       self.number = 3;
                                       "Your belt suddenly radiates a bright white light and
                                       the alien presence recoils away from you.";
                               }
                               return(TakeOverMe());
                       3:
                               if((belt has worn) && (--belt.charges > 0))
                               {
                                       if(prisondoor has open)
                                       {
                                               self.number = 6;
                                               deadflag = 3;
                                               if(goggles has worn)
                                                       print "You can see the black shadow
                                                               seeping out through the open iris door.";
                                               else
                                                       print "You feel the alien presence leaving.";
                                               if(Professor.status == 1)
                                                       print "You wait until the Professor recovers";
                                               else
                                                       print "You gather the Professor's body";
                                               " and then proceed back to the surface. When you
                                               approach the mothership, nobody answers your hails.
                                               ^You dock, open the airlock and manage to get a
                                               glimpse of the docking bay covered in blood before
                                               a shot kills you. The Bane eventually conquers the
                                       ship and finds its way to Earth.";
                                       }
                                       if(shadow.position && (prisonwall hasnt open))
                                       {
                                               print "^You have trapped the Bane!^^^";
                                               score = score + 20;
                                               deadflag = 2;
                                               self.number = 7;
                                               WinBlurb(Professor.status);
                                               rtrue;
                                       }
                                       if(goggles has worn)
                                       {
                                               print "^The black shadow recoils, moving ";
                                               if(prisonwall has open)
                                                       shadow.position = ~~shadow.position;
                                               if(shadow.position)
                                                       "to the far side of the transparent wall.";
                                               "in circles by the iris door.";
                                       }
                                       "^You can feel the alien presence moving around you,
                                       but you can't locate it.";
                               }
                               if(goggles has worn)
                                       print "The alien presence";
                               else
                                       print "The black shadow";
                               print " wraps around you once again";
                               if(belt has worn)
                                       print " but this time the belt fails to create its
                                               protective shield.";
                               else
                                       print " and you no longer have the protection of
                                               the white belt.";
                               return(TakeOverMe());
               }
       ],
       s_to prisondoor,
       has light scored;

IrisDoor -> prisondoor "door"
       with door_dir s_to,
       door_to Lab;

Object -> prisonwall "transparent wall"
       with name 'transparent' 'wall' 'partition',
       description [;
               print "A transparent wall divides the room in two halves";
               if(self has open)
                       print ". It's currently open";
               ".";
       ],
       before [;
               Shoot:  blaster.charges--;
                       "You shoot at the wall and the discharge is reflected
                       back, passing you by a hair. That was close!";
       ],
       has scenery static;

Object -> switch "switch"
       with name 'switch' 'lever' 'button',
       description "A small switch is embedded into the wall, on your
               side of the transparent partition.",
       before [;
               Pull:
                       if(prisonwall has open)
                               "That's as far as it would go.";
                       give prisonwall open;
                       "You flip the switch and a portion of the transparent
                       wall slides to one side.";
               Push:
                       if(prisonwall has open)
                       {
                               give prisonwall ~open;
                               "You flip the switch and the transparent wall slides
                               back, covering the opening.";
                       }
                       "That's as far as it would go.";
               SwitchOn, SwitchOff:
                       if(prisonwall has open)
                       {
                               give prisonwall ~open;
                               "You flip the switch and the transparent wall slides
                               back, covering the opening.";
                       }
                       else
                       {
                               give prisonwall open;
                               "You flip the switch and a portion of the transparent
                               wall slides to one side.";
                       }
       ],
       has scenery static;

Object -> Professor "Professor"
       with name 'prof' 'professor',
       status 0,
       spoken 0,
       description [;
               print "The Professor is a short, plump man, with white hair
                       and bright blue eyes. He looks like he could use a good
                       night's sleep, but otherwise unharmed";
               if(goggles has worn)
                       print ". Some sort of black mist or shadow is coiling
                               by his feet";
               ".";
       ],
       before [;
               Attack, Give, Kiss, Touch, Take:
                       if(Prison.number == 0 or 1)
                               "You can't reach the Professor.";
                       if(~~self.status)
                               "The Professor overpowers you with ease. You never
                               thought he was that strong.";
                       "The Professor is already down. Don't bother with him.";
               Shoot:
                       if(Prison.number == 0 or 1)
                       {
                               blaster.charges--;
                               "You shoot at the wall and the discharge is reflected
                               back, missing you by a hair. That was close!";
                       }
                       if(self.status)
                               "He's no danger to you at the moment.";
                       blaster.charges--;
                       print "Quick as lightning, you reach for your blaster
                                and shoot at the Professor. ";
                       if(bluecloth has worn)
                               "Unfortunately, your aim is not as sure as usual
                               due to the cloth you have wrapped around your hand
                               and you miss him.";
                       if(blaster.setting)
                       {
                               self.status = 2;
                               "The blaster burns a gaping hole in his chest and he
                               crumples to the ground.";
                       }
                       self.status = 1;
                       score = score + 10;
                       "The discharge hits him squarely in the chest and knocks
                       him unconscious.";
       ],
       life [;
           Show:
                       if(self.status == 1)
                               "The Professor is out cold.";
                       if(self.status == 2)
                               "The Professor is dead.";
                       if(~~Prison.number)
                               "The Professor seems unaware of your presence.";
                       if(Prison.number ~= 1)
                               rfalse;
                       if(noun == blaster)
                               "The Professor shakes his head. ~I don't
                               think shooting it down is a good idea. I
                               might end up dead.~";
                       if(noun == keycard)
                               "~Hmm... if I can read the markings right, this
                               is the Builder equivalent of an access card.~";
                       if(noun == flashlight)
                               "~It's a flashlight. What about it?~";
                       if(noun provides square)
                               "~It's an electronic component of some sort. If you
                               open the wall, I'll gladly analyse it.~";
                       return(self.sayHurry());
               WakeOther:
                       switch(self.status)
                       {
                               1: "Better get the situation under control before
                                       risking to wake him up.";
                               2: "He'll never wake up again.";
                               default:
                                       if(~~Prison.number)
                                       {
                                               print "You knock on the wall. ";
                                               return(self.sayOpening());
                                       }
                                       "He seems alert enough.";
                       }
               Ask, Answer, Order, Tell:
                       if(self.status == 1)
                               "The Professor is out cold.";
                       if(self.status == 2)
                               "The Professor is dead.";
                       switch(Prison.number)
                       {
                               0: return(self.sayOpening());
                               1: return(self.sayHurry());
                               default:
                                       "The Professor ignores you.";
                       }
               Give:
                       switch(self.status)
                       {
                               1: "The Professor is out cold.";
                               2: "The Professor is dead.";
                               default:
                                       if(Prison.number == 0 or 1)
                                               "You can't give him anything through the wall.";
                                       "He only seems interested in giving /you/ that knife!";
                       }
       ],
       sayOpening [;
               Prison.number = 1;
               "The Professor raises his head. ~", (NameArray) MyName, ",
               thank Space you're here~. His voice is faint, but it carries
               through the wall. ~I got locked behind this transparent
               wall. Get me out of here, will you? We have to get back to
               the ship.~";
       ],
       sayHurry [;
               if(self.spoken)
                       "The Professor doesn't say anything, just taps his foot
                       impatiently, pointing at the switch on the wall.";
               self.spoken = 1;
               "The Professor waves his hand impatiently. ~We'll talk about
               this later, ", (NameArray) MyName, ". Now, please get me out
               of here. For one thing, I really need to find a bathroom.~";
       ],
       has scenery animate;

Object shadow "black shadow"
       with name 'black' 'mist' 'shadow' 'alien' 'presence',
       position 0,
       description [;
               if(goggles has worn)
                       "A black mist is curling above the floor, sending shivers
                       down your spine every time you look at it.";
               "You can feel an alien presence nearby, so cold that it makes
               your hair stand on end, but you can't see a thing.";
       ],
       before [;
               Attack, Take, Kiss, Touch, Shoot:
                       "The alien presence is not exactly solid.";
       ],
       has scenery static;

Object School
       with name 'screen' 'display',
       short_name "School",
       description [;
               switch(cityState)
               {
                       0: print "Twenty small alien beings are sitting on chairs,
                               watching a larger one in front of the room. The larger
                               alien is displaying some strange symbols on a screen
                               behind it, pointing to some of then, then turning
                               toward the smaller ones and apparently explaining
                               something, then returns to the screen and starts over.
                               Everybody ignores you.";
                       1: print "Twenty small alien beings are gathered in a circle
                               around a larger one, watching it with utmost attention.
                               The large alien seems to be explaining something,
                               frequently pointing toward the exit. As usual, you are
                               completely ignored.";
                       2: print "Rows upon rows of beds line this room. Alien beings,
                               with their clothes torn, dirty and wounded, are on the
                               beds, twitching restlessly. An alien dressed in blue is
                               moving from bed to bed, talking with the others, wiping
                               their heads and wounds. Nobody takes any notice of your
                               presence.";
                               ChangeCity();
                               rtrue;
                       3: print "Rows upon rows of beds line this room. Alien beings,
                               with their clothes torn, dirty and wounded are on the
                               beds, laying still.";
                       default: print "This room resembles a hospital or an army
                               barracks. Rows of beds fill the room, but they are all
                               empty.";
               }
               " The exit is to the north.";
       ],
       n_to CityS,
       has light;

Object -> bed "beds"
       with name 'bed' 'beds' 'bunk' 'bunks' 'table' 'tables',
       description "Flat metal surfaces propped on four legs. You could
               call them tables as well, but they're just the size and height
               that would allow you to lie down on one and rest.",
       before [;
               Enter: "It doesn't look especially comfortable and you have
                       work to do.";
               Shoot: "The blaster won't melt the metal.";
               Search, LookUnder:
                       if(parent(goggles) == nothing)
                       {
                               move goggles to player;
                               score = score + 10;
                               "You kneel on the floor and look under all beds. In a
                               corner you find a pair of goggles, which you take in
                               your hand.";
                       }
       ],
       has scenery static supporter;

Object ControlRoom "Control Room"
       with description "You're in a small room, whose walls are filled
               with multicolored lights. In the center there is a box, made
               from a transparent glass-like material. Near the box is a
               lever.",
       e_to Elevator,
       has scored;

Object -> lights "lights"
       with name 'light' 'lights' 'control' 'controls',
       description "The walls are covered with lights of all colors,
               but you can't figure out their meanings.",
       has scenery static;

Object -> glassbox "glass box"
       with name 'glass' 'transparent' 'box',
       description [;
               print "It's a transparent cube, made from a glass-like
               material";
               if(belt in glassbox)
                       print ". Inside the cube is a white belt";
               ".";
       ],
       before [;
               Open: "You don't know how to open the box.";
       ],
       has scenery static container transparent;

Object -> -> belt "white belt"
       with name 'white' 'belt',
       charges 5,
       description "A white belt, made from some rubbery material
               with a metallic white clasp.",
       after [;
               Wear: "As you close the metal clasp, you suddenly feel
                       very alert.";
               Remove: "As you remove the belt, you feel weak and dizzy
                       for a short moment.";
       ],
       has clothing scored;

Object -> lever "lever"
       with name 'lever' 'switch',
       description "A metal lever, sticking out of the floor.",
       before [;
               Touch:
                       if(~~(bluecloth has worn))
                               "As you touch the lever you feel an electric
                               discharge. That hurt!";
               Push:
                       if(~~(bluecloth has worn))
                               <<Touch self>>;
                       if(glassbox has open)
                               "The lever won't budge.";
                       "The lever is pushed as far as it would go.";
               Pull:
                       if(~~(bluecloth has worn))
                               <<Touch self>>;
                       if(glassbox has open)
                               "The lever won't go any further.";
                       give glassbox open;
                       "With your hand wrapped in the cloth, you pull the
                       lever toward you and the top of the box suddenly
                       disappears.";
       ],
       has scenery static;

! Library entry points

[ Initialise i;
       location = Ship;
       print "Do you want to restore a saved game? ";
       if(YesOrNo())
               <<Restore>>;
       print "New players can use the LICENSE or WARRANTY commands to
               see information about this program. At any point, type HELP
               for hints regarding your present location.^";
       for(i = 0: ~~i:)
       {
               print "Enter your name (<First> <Last>) [John Doe]: ";
               name_array->0 = 50;
               parse_array->0 = 3;
               read name_array parse_array;
               if(parse_array->1 == 2)
                       i = 1;
               if(name_array->1 == 0)
           break;
       }
       if(i == 1)
       {
       MyName->0 = parse_array->4;
               for(i=0: i<parse_array->4: ++i)
                       MyName->(i+1)=name_array->(parse_array->5 + i);
       MySurname->0 = parse_array->8;
               for(i=0: i<parse_array->8: ++i)
                       MySurname->(i+1)=name_array->(parse_array->9 + i);
       }
       else
       {
               MyName->0=4;
               MyName->1='j';
               MyName->2='o';
               MyName->3='h';
               MyName->4='n';
               MySurname->0=3;
               MySurname->1='d';
               MySurname->2='o';
               MySurname->3='e';
       }
       player.description = MyDesc;
       thedark.description = DarkDesc;
       notify_mode = 0;
       StartDaemon(Prison);
       StartDaemon(City);
       "^^^^^After years and years of moving from one lifeless planet to
       another, the Professor had finally seen his dream come true.
       The mysterious race known as the Builders had left many traces and
       artifacts throughout the galaxy, but mankind had never managed
   to find out why or how could a civilization that was spacefaring
       when we were still hiding in caves disappear. Now, on this planet,
       scans made from orbit detected the presence of an energy source.^
       The foremost expert on the Builders civilization, the Professor,
       had descended to investigate. Since you are the only officer aboard
   who became quite friendly with him during your long voyage, he had
       asked you to fly him down. Your Captain couldn't have been happier.
       ^^But the Professor has been gone for almost 24 standard hours
   now and you lost radio contact the moment he had entered that tunnel
       in the face of the mountain. It might be time for the Navy to
       come to rescue...^^^";
];

[ PrintRank;
       print ", earning you the rank of ";
       PrintRankName();
       ".";
];

[ DeathMessage;
       print "You have failed";
];

[ NewRoom;
       if(location == CityN or CityE or CityS or CityW
               or Lab or Library or School)
       {
               City.number = City.number + 1;
       }
];

[ DarkToDark l;
       l = random(25) - 1;
       real_location= maze-->l;
       mazedir = random(4) - 1;
       "You wander for a while in darkness.";
];

! Local functions

[ toupper c;
       if(c >= 'a' && c <= 'z')
               return(c - 'a' + 'A');
       return(c);
];

[ NameArray str_array i;
       if(~~str_array->0)
               rtrue;
       print (char) toupper(str_array->1);
       for(i = 2: i<=str_array->0: ++i) print (char) str_array->i;
];

[ MyDesc;
       print "The one you see every morning in the mirror.
               You're wearing a blue Navy jumpsuit, with rank pips
               on your collar and a golden tag above your left breast: ";
       PrintRankName();
       " ", (NameArray)MySurname, ".";
];

[ DarkDesc;
       if(real_location == Tunnel)
               "It is dark, the only light coming faintly from an
               opening to the north.";
       else if(real_location == maze-->14)
               "It is pitch dark, the only trace of light coming from
               an opening above.";
       "It is pitch dark and you can't see a thing.";
];

[ HatchDesc w d;
       if(real_location provides openings)
       {
               print "A round plastic hatch fixed in a metal frame on the
               wall. It looks just big enough for you to crawl through.
               The hatch is ";
               d = (mazedir+w)%4;
               if((real_location.&openings)-->d == -1)
                       "closed.";
               "open.";
       }
       if(location == Ship)
               "Your way in and out of the shuttle.";
       "You don't see any such thing here.";
];

[ HatchOpen w d;
       d = (mazedir+w)%4;
       if((real_location.&openings)-->d == -1)
               "The hatch doesn't budge.";
       "It's already open.";
];

[ HatchClose w d;
       d = (mazedir+w)%4;
       if((real_location.&openings)-->d == -1)
               "The hatch is already closed.";
       "There's no need to close it.";
];

[ PrintRankName;
       if(score == 100) print "Captain";
       else if(score >= 80) print "Commander";
       else if(score >= 60) print "Lieutenant Commander";
       else if(score >= 40) print "Lieutenant";
       else if(score >= 20) print "Lieutenant junior";
       else if(score >= 0) print "Ensign";
       else print "Bane of Mankind";
];

[ CreateMaze i ccell ncell nb cellptr nbptr total;

       for(i = 0: i < 25: ++i)
       {
               maze-->i = MazeRoom.create();
               cellvisited-->i = 0;
       }
       ccell = random(25) - 1;
       cellvisited-->ccell = 1;
       cellptr = 0;
       total = 1;
       while(total < 25)
       {
               ! find neighbours
               nbptr = 0;
               if(ccell>=5 && ~~(cellvisited-->(ccell-5)))
                       nblist-->(nbptr++) = ccell-5;
               if(ccell%5 < 4 && ~~(cellvisited-->(ccell+1)))
                       nblist-->(nbptr++) = ccell+1;
       if(ccell<20 && ~~(cellvisited-->(ccell+5)))
                       nblist-->(nbptr++) = ccell+5;
               if(ccell%5 > 0 && ~~(cellvisited-->(ccell-1)))
                       nblist-->(nbptr++) = ccell-1;
               if(nbptr > 0)
               {
                       nb = random(nbptr) - 1;
                       ncell = nblist-->nb;
                       if(ncell == ccell - 5)
                       {
                               ((maze-->ccell).&openings)-->0 = ncell;
                               ((maze-->ncell).&openings)-->2 = ccell;
                       }
                       else if(ncell == ccell + 5)
                       {
                               ((maze-->ccell).&openings)-->2 = ncell;
                               ((maze-->ncell).&openings)-->0 = ccell;
                       }
                       else if(ncell == ccell + 1)
                       {
                               ((maze-->ccell).&openings)-->1 = ncell;
                               ((maze-->ncell).&openings)-->3 = ccell;
                       }
                       else
                       {
                               ((maze-->ccell).&openings)-->3 = ncell;
                               ((maze-->ncell).&openings)-->1 = ccell;
                       }
                       cellvisited-->ncell = 1;
                       cellstack-->(cellptr++) = ccell;
                       ccell = ncell;
                       total++;
               }
               else
                       if(cellptr>0)
                               ccell = cellstack-->(--cellptr);
                       else
                               total = 100;
       }
       mazedir = random(4) - 1;
       (maze-->14).u_to = CityE;
       move bluecloth to maze-->2;
       give maze-->2 scored;
];

[ ChangeCity;
       if(cityState<4)
       {
               give cityN ~visited;
               give cityS ~visited;
               give cityW ~visited;
               give cityE ~visited;
               give Lab ~visited;
               give School ~visited;
               give Library ~visited;
               if(++cityState == 4)
               {
                       remove pool;
                       move hole to CityE;
               }
               if(cityState > 1)
                       School.short_name = "Hospital";
               print "^The world around you suddenly shimmers and changes...^^";
               PlayerTo(location);
       }
];

[ ShootWall w d i nc;
       for(i=0: i<25: ++i)
               if(real_location == maze-->i)
                       break;
       if(i >= 25)
               rfalse;
       d = (mazedir+w)%4;
       if((real_location.&openings)-->d == -1)
       {
               w = 1;
               switch(d)
               {
                       0:      nc = i - 5;
                               if(i<5)
                                       w = 0;
                       1:      nc = i + 1;
                               if(i%5 == 4)
                                       w = 0;
                       2:      nc = i + 5;
                               if(i>=20)
                                       w = 0;
                       3:      nc = i - 1;
                               if(i%5 == 0)
                                       w = 0;
               }
               blaster.charges--;
               if(w && blaster.setting)
               {
                       (real_location.&openings)-->d = nc;
                       ((maze-->nc).&openings)-->((d+2)%4) = i;
                       "You aim at the hatch and squeeze the trigger. Suddenly,
                       the hatch melts away, leaving an opening.";
               }
               else
                       "You aim at the hatch and squeeze the trigger. Stubbornly,
                       the hatch doesn't bulge.";
       }
       else
               "That hatch is already open.";
];

[ TakeOverMe;
       deadflag = 3;
       Prison.number = 5;
       score = -10;
       print "^^Something takes over your body, leaving only your mind
       free to watch. Through a haze you can see yourself ";
       if(Professor.status == 1)
               print "torching the Professor with your blaster, ";
       "leaving the underground complex and boarding your shuttle,
       returning to the mothership. Then the slaughter starts. You
       shoot your colleagues, destroy the communications equipment. When,
       mercifully, one of your comrades shoots you down, before you die
       you can see a black shadow raising from your body and engulfing his.";
];

[ PlayMovie;
       "The cartridge fits easily into the slot and the display lights up.^^^
       You see an alien, dressed in a blue tunic with a white belt, wearing
       a pair of goggles sitting in this very room in front of a machine. The
       alien stands and leaves the building, entering a desolate area, a large
       metal triangle with bridges leading away.^
       The scene changes, shows the alien carrying a transparent case filled
       with a black swirling mist. He enters a building that resembles a
       laboratory, unlocking an iris door in front of him with a keycard.
       He disappears through the door, returning a few moments later.^
       The scene changes again, showing the alien in some sort of a hospital,
       holding the hand of another alien who is lying on a bed. It removes
       its goggles and puts them on the bed, by the wounded alien.^
       The scene changes once more, again showing the desolate triangular
       area. The alien enters into a cylindrical elevator and the door closes
       after it. For a couple of minutes everything is still, then
       half-transparent images appear, become more solid and real, making
       the triangle look like a busy square.^^^
       The cartridge ejects and the display becomes black again.";
];

[ WinBlurb st;
       if(st == 1)
               "You wait until the Professor recovers from the stun and head
               together back to the mothership. A larger expedition heads down
               to study the black mist and discovers that it's an intelligent
               entity bent on destruction. More films are discovered in the
               city, proving without a doubt that the mist, named ~The Bane~ by
               the Builders was responsible for wiping out entire planets.^
               The city on this planet was a colony dedicated to finding means
               of protection against the Bane and they had in the end fulfilled
               their mission, but only one survivor ever made it out. What
               happened to it or the Builder planets that received the cure in
               time remains a mystery.^
               All in all, you managed to save the Professor, the Earth and help
               uncover part of the Builders' mystery. Not bad for a day's work.";
       "You carry the Professor's body back to the shuttle, then up to your
       ship. A larger expedition heads down to study the black mist and
       discovers that it's an intelligent entity bent on destruction. More
       films are discovered in the city, proving without a doubt that the
       mist, named ~The Bane~ by the Builders was responsible for wiping out
       entire planets.^
       The city on this planet was a colony dedicated to finding means
       of protection against the Bane and they had in the end fulfilled
       their mission, but only one survivor ever made it out. What
       happened to it or the Builder planets that received the cure in
       time remains a mystery.^
       All in all, you managed to save the Earth from the same fate and
       uncover part of the Builders' mystery. Too bad the Professor didn't
       make it. He would have been proud of you.";
];
Include "Grammar";

! Extra verbs & their stuff

[ ShootSub;
       if(noun == player)
               "You shoot yourself in the foot.";
       else
               "Shooting ", (the) noun, " won't help you.";
];

[ IsGun;
       if(blaster in player && noun == blaster)
               if(blaster.charges)
                       rtrue;
               else
               {
                       print "Your blaster is discharged.^";
               }
       rfalse;
];

Verb 'shoot'
       * noun 'with' noun=IsGun -> Shoot
       * 'at' noun 'with' noun=IsGun -> Shoot
       * 'with' noun=IsGun 'at' noun -> Shoot reverse;

[ DiveSub;
       if(pool in location)
       {
               print "You step into the pool, but it doesn't feel wet.
                       In fact, it doesn't feel like you're in water at all.
                       One more step, and the floor suddenly gives way,
                       sending you down...^^";
               PlayerTo(maze-->14);
       }
       else
               "There's not enough water nearby.";
];

Extend 'swim' replace * -> Dive;

Extend 'wave' * 'to' noun -> Wave;

[ HelpSub;
       if((location == Ship) && ~~(blaster in player))
               "The passenger seat looks comfy.";
       else if((location == Elevator) && (panel hasnt open))
               "When a car doesn't start, you look under the hood.";
       else if(location == Lab)
               "Did you check what's behind the iris door?";
       else if((location == School) && (cityState > 2))
               "Look under the bed.";
       else if((location == CityE) && (cityState < 4))
               "Nice weather for a swim.";
       else if(location provides openings)
               "How does a rat go through a maze? Taking only left (or only
               right) turns.";
       else if(location == ControlRoom)
               "Wrapping your hand in something might help here.";
       else if(location == thedark)
               "Are you sure you didn't forget anything in the shuttle?";
       "Try examining things.";
];

Verb 'help' * -> Help;

[ WrapSub;
       if(noun == bluecloth)
       {
               give bluecloth worn;
               "You wrap your hand in the blue cloth.";
       }
       "You can't wrap ", (the) noun, ".";
];

Verb 'wrap' 'bandage'
       * held 'on' 'hand' -> Wrap
       * 'hand' 'with' held -> Wrap
       * 'hand' 'in' held -> Wrap;

Verb 'flip'
       * noun -> SwitchOn;

[ LicenseSub;
       "~Bane of the Builders~ is free software; you can redistribute it
       and/or modify it under the terms of the GNU General Public License
       as published by the Free Software Foundation; either version 2 of
       the License, or (at your option) any later version.^^
   ~Bane of the Builders~ is distributed in the hope that it will be
       useful, but WITHOUT ANY WARRANTY; without even the implied warranty
       of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
   GNU General Public License for more details.^^
       You can find a copy of the GNU General Public License at
       http://www.gnu.org/licenses/gpl.txt; if you can not, write to the
       Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
       MA 02111-1307 USA";
];

Verb meta 'license' 'warranty' * -> License;

#ifndef DEBUG;

[ RandomizeSub n;
       n=random(-100);
       "[Randomized.]";
];

Verb meta 'random'
               *  -> Randomize;
#endif;