!------------------------------------------------------------------------------ ! ! ! D E A D L I N E ! ! ! Inform Port ! ! ! This material contains elements based on the game Deadline. ! It is used with permission as instructive material. ! Original Deadline material is (c) 1982, 1999 Activision, Inc. ! Deadline and Activision are registered trademarks of Activision, Inc. ! All rights reserved. ! ! Inform Port written by Volker Lanz. Please do not distribute modified ! versions of these files. ! You can contact me via e-mail: volker.lanz@gmx.net ! ! Please note: Activision have kindly given their permission to ! release this source code for instructive purposes. They, however, ! haven't granted anyone the permission to play DEADLINE who has not ! purchased the original game. Please bear in mind that playing the ! compiled game without owning the original DEADLINE is still a ! violation of copyright. ! ! ! Missing features and bugs: ! ========================== ! - McNabb tries to show holes only once instead of twice ! - Baxter and Dunbar aren't talking in the living room when ! Dunbar gets nervous ! - When Dunbar goes outside after the player has shown her the ! lab report, she drops the stub on the front path instead ! of dropping it where she meets the player ! - When Rourke tries to bring the envelope to Mrs. Robner and the ! player has it, she doesn't let Mrs. Robner know about that. ! - Mrs. Robner's movement has to be started if the player enters ! the house via the ladder and balconies ! - Knocking at doors ("A muffled voice says ~Come in!~") ! ! ! Modifications for this release: ! =============================== ! CHANGED: modified to work with Library 6/10 (thanks to Chip ! Hayes for making the necessary changes). ! CHANGED: modified to work with NPC Engine release 8. ! CHANGED: the game now explicitly says that NPCs stop on their ! way when you call them while moving. ! CHANGED: "arrest" now works as in the original version: if ! two people are to be arrested, they need not be ! in scope (or, in the case of Baxter, not even on ! the grounds). ! CHANGED: the game now doesn't say where NPCs come from ! anymore when they enter a room. not sure if that's ! an improvement, but the original was like that. ! CHANGED: the way how asking McNabb to show the holes was ! implemented was more than ugly. Changed. ! CHANGED: modified the ladder so it doesn't need a dummy ! object anymore when leaning against one of the ! balconies. ! CHANGED: the Inform Library now prints initial() descriptions ! even for objects on supporters (still not for objects ! in open containers [Dunbar's medicine cabinet], though) ! CHANGED: game now distinguishes between "accuse " and ! "accuse of ". ! CHANGED: the way the hidden door was implemented was far ! from perfect; it still is, but it's a _little_ ! better now ;-)) ! CHANGED: will reading completely re-written. ! CHANGED: "show to " will stop NPCs in their movement ! as well as "give to " ! CHANGED: major modifications to the rules in ChooseObjects ! (Chip Hayes) ! ! FIXED: when Mrs. Robner went to her bedroom to call Steven, ! she didn't check if the player was in the bathroom. ! FIXED: when the player stopped an NPC moving, say, down ! the hall, he could interact with him as if he was ! in the same location (e.g. give things to him). ! FIXED: some bugs with weight and capacity (Chip Hayes). ! FIXED: a crash occured when the player trampled on the ! roses (Chip Hayes). ! FIXED: under certain circumstances, wrong messages were ! printed when the player tried to arrest Dunbar ! and Baxter. ! FIXED: when Baxter was on his way to kill Dunbar and Mrs. ! Robner was in the master bedroom, the game would crash. ! FIXED: to make Baxter take the blue pen out of his pocket, ! the player couldn't say "ask baxter for pen", but ! only "baxter, give me the pen". ! FIXED: "find " didn't always result in "You're the ! detective." when necessary. ! FIXED: asking Baxter or McNabb about something they can't ! say anything about did result in a programming error. ! FIXED: McNabb would stop moving completely under certain ! circumstances when the player trampled on the roses. ! FIXED: player could talk to Duffy. ! FIXED: "descend stairs" didn't work. ! FIXED: the book wasn't described when Baxter was in the ! living room and the player dropped it there. ! FIXED: George didn't complain about the player turning off ! the stereo. ! FIXED: when Duffy returned from analysing the ladder, the game ! said he held it in its hands, yet he claimed to have ! left it outside the house, if necessary. ! FIXED: player couldn't "read ending" when he had the book ! since read didn't work with scenery objects. Same was ! true for the cornerstone (Chip Hayes). ! FIXED: part of the description for the loblo bottle was ! missing. ! FIXED: little bug in the routine for Mrs. Robner welcoming ! the player. ! FIXED: programming error when trying to "smell air" ! FIXED: "answer phone" didn't work. ! FIXED: the game would stop NPCs in their movement although ! communication was disallowed because they were too ! far away, i.e. not in the location ! ! ADDED: the player can now say "find blue pen". ! ADDED: when the player tries to arrest Dunbar, but doesn't ! yet know she is dead, Duffy will come and tell him. ! ADDED: the suspects now reply "I don't know" if the player ! asks them where Steven is. ! ADDED: objects NPCs are holding are now described with them. ! ADDED: player can now "search for" any object in the ! game that isn't static or scenery. ! ADDED: game only ends with a 25% probability if player tries to ! break the china in the kitchen. ! ADDED: correct response to "find me" ! ADDED: correct response when player tries to clean the shed ! window or break any window. Also, a window class. ! ADDED: player can now look through the dining room window from ! garden path. ! ADDED: response to "break mirror" and a mirror class. ! ADDED: "climb stairs carefully" ! ADDED: "look in " feature. ! ADDED: "dig holes" works the same as "dig near holes" ! ! !------------------------------------------------------------------------------ !------------------------------------------------------------------------------ ! R E L E A S E, S T O R Y, H E A D L I N E, S E R I A L !------------------------------------------------------------------------------ Release 3; Constant Story "DEADLINE"; Constant Headline "^Interactive Fiction: A Mystery.^ Written by Marc Blank. Ported to Inform by Volker Lanz (volker.lanz@@64gmx.net).^ Copyright 1982, 1999 by Activision, Inc. All rights reserved.^ Deadline and Activision are registered trademarks of Activision, Inc.^"; Serial "000923"; !------------------------------------------------------------------------------ ! C O N S T A N T S A N D S E T T I N G S !------------------------------------------------------------------------------ Constant DEBUG; ! Is this a debugging version? ! Constant NOHINTS; ! Does this version feature InvisiClues? Constant DIALECT_US; Constant WITHOUT_DIRECTIONS; ! Telling the library we provide our own Constant MAX_WAIT 180; ! Maximum to wait Constant HINT_STYLE 2; ! We want InvisiClue-look hints. Constant ALTMENU_PROP_STUBS; ! New version of AltMenu.h wants this for some reason Constant SUBWAY_MOVE_TYPE; ! Setting type of movement to subway Statusline time; !------------------------------------------------------------------------------ ! A B B R E V I A T I O N S !------------------------------------------------------------------------------ Abbreviate "the " ". " ", " "and " "You " "The " "you " "Robner " "of " "that " "to " "is " "Baxter " "don't " "George " "can't " "I " "your " "with " "are " "about " "There " "have " "Dunbar " "from " "Marshall " "in " "for " "around " "which " "here" "was " "Robner" "He " "his " "would " "but " "This " "know " "through " "doesn't " "been " "Sergeant " "can " "balcony " "Mrs" "large " "think " "quite " "She " "not " "door " "seems " "Inspector" "really " "Mr" "I'm " "into " "on " "has " "Robner's " "toward " "be " "there "; !------------------------------------------------------------------------------ ! P R O P E R T I E S A N D A T T R I B U T E S !------------------------------------------------------------------------------ Property weight 1000; Property size 1000; Property space 0; Attribute legible; ! To be able to read stuff using "read" Attribute corridor; ! Is this room a corridor? Attribute baxter_shown; ! Mark items that were shown to Baxter Attribute dunbar_shown; ! Mark items that were shown to Dunbar Attribute george_shown; ! Mark items that were shown to George Attribute topic; ! Mark objects that can be asked about Attribute findable; ! Mark objects that can be found via "find" verb !------------------------------------------------------------------------------ ! S T R I N G S !------------------------------------------------------------------------------ Constant ContainMedicineOnly "It should contain the proper medicine only... Don't you think so?"; Constant CantGoLake "You can't go into the lake."; Constant CantGoHouse "You can't enter the house here."; Constant DuffyBusy "Sergeant Duffy is at the lab running an errand for you. You will have to wait for him to return."; Constant AllIKnow "~I told everything I know about it to the other detectives.~"; Constant KnockWall "Knocking on the walls reveals nothing unusual."; !------------------------------------------------------------------------------ ! R E P L A C I N G R O U T I N E S !------------------------------------------------------------------------------ Replace DoMenu; Replace LowKey_Menu; Replace ScoreSub; Replace JumpSub; Replace HelpSub; Replace Banner; Replace VersionSub; Replace DrawStatusLine; Replace LookSub; Replace Locale; Replace SayWhatsOn; Replace WriteListFrom; Replace ParseToken; Replace ParseToken__; Replace HelpOffSub; Replace BeforeParsing; Replace LMode1Sub; Replace LMode2Sub; Replace LMode3Sub; Replace ThrowAtSub; Replace ScriptOnSub; Replace ScriptOffSub; Replace FullScoreSub; Replace PushSub; Replace InsertSub; Replace TakeSub; Replace YesOrNo; Replace RestoreSub; Replace SaveSub; Replace VerifySub; Replace InvWideSub; Replace InvTallSub; Replace InvSub; Replace LanguageLM; Replace GoSub; Replace WaitSub; Replace SqueezeSub; Replace NPC_BeforeFollowing; Replace NPC_BeforeCheckVisible; Replace NPC_AfterPrintVisible; Replace NPC_Msg; Replace TryGivenObject; Replace AttemptToTakeObject; !------------------------------------------------------------------------------ ! F I R S T I N C L U D E S !------------------------------------------------------------------------------ Include "Parser.h"; Include "VerbLib.h"; Include "LibExt.h"; !------------------------------------------------------------------------------- ! P A R S E R E R R O R !------------------------------------------------------------------------------- ! ! These are slighly modified replies the parser gives when it cannot ! understand what the player meant with his input. ! !------------------------------------------------------------------------------- [ ParserError pe; switch (pe) { STUCK_PE: "[Sorry, I didn't understand that sentence at all.]"; UPTO_PE: print "[I only understood you as far as wanting to "; PrintCommand(); ".]"; NUMBER_PE: "[I didn't understand that number.]"; CANTSEE_PE: L__M(##Miscellany, 30); rtrue; TOOLIT_PE: "[You seem to have said too little!]"; NOTHELD_PE: "[You aren't holding that!]"; MULTI_PE: print "[You can't use multiple objects with '"; print (address) verb_word; "'.]"; MMULTI_PE: "[You can use multiple objects only once on a line.]"; VAGUE_PE: "[I'm not sure what '", (address) pronoun_word, "' refers to.]"; EXCEPT_PE: "[You excepted something not included anyway.]"; ANIMA_PE: "You can only do that to a human or living creature."; VERB_PE: L__M(##Miscellany, 38); rtrue; SCENERY_PE: "[You don't need to refer to this to complete the story.]"; ITGONE_PE: print "[You can't see '", (address) pronoun_word, "' "; if (pronoun_obj ~= NULL) print "(", (the) pronoun_obj, ") "; "at the moment.]"; JUNKAFTER_PE: "[I didn't understand the way that finished.]"; TOOFEW_PE: if (multi_had == 0) print "[None "; else print "[Only ", (number) multi_had; " of those are available.]"; NOTHING_PE: "[Nothing to do.]"; } rfalse; ]; !------------------------------------------------------------------------------- ! C H O O S E O B J E C T S !------------------------------------------------------------------------------- ! ! ChooseObjects deals with various situations where the parser cannot ! decide which object the player refers to in his input. ! !------------------------------------------------------------------------------- [ ChooseObjects obj code; ! Do we get called because an "all" list is created? if (code < 2) { ! Don't include scenery or animate objects in "all" lists! if (obj has scenery or animate) return 2; ! ...and don't include static objects in "take all" if (obj has static && action_to_be == ##Take) return 2; ! Don't include objects the player isn't holding in "put all in/on s.th." if (action_to_be == ##Insert or ##PutOn && obj notin player) return 2; ! Don't include objects in "take all" that are in open containers or ! on supporters which can themselves be taken. if (action_to_be == ##Take && (parent(obj) has container && parent(obj) has open || parent(obj) has supporter) && parent(obj) hasnt scenery or static) return 2; ! Force all other objects in scope to be considered in an "all" situation, ! except those concealed (prevents Duffy, NPC_Engine, etc. from being included) if (obj hasnt concealed) return 1; ! Do with the rest whatever you want return 0; } ! We want to prefer closed objects over open ones when opening if (action_to_be == ##Open && obj has openable && obj hasnt open) return 6; ! ... and open ones over closed ones when closing if (action_to_be == ##Close && obj has openable && obj has open) return 6; ! The rest has 3 return 3; ]; !------------------------------------------------------------------------------ ! G A M E P R E R O U T I N E !------------------------------------------------------------------------------ ! ! This one is used to make sure the player cannot interact with NPCs ! that are in scope (i.e. visible), but not in the same location ! as he is. Also see the player object's order property for dealing ! with orders to NPCs in scope. ! !------------------------------------------------------------------------------ [ GamePreRoutine; if (noun ofclass NPC_Engine && ScopeCeiling(noun) ~= location) { switch(action) { ##Hey, ##Examine, ##NPC_WaitFor, ##Find, ##Follow, ##Arrest, ##Answer: rfalse; ##Ask, ##AskFor, ##Tell, ##Order: print_ret (The) noun, " can't hear you."; default: print_ret (The) noun, " isn't here!"; } } if (second ofclass NPC_Engine && ScopeCeiling(second) ~= location && action ~= ##Ask or ##Answer) print_ret (The) second, " isn't here!"; rfalse; ]; !------------------------------------------------------------------------------ ! B E F O R E P A R S I N G !------------------------------------------------------------------------------ ! ! BeforeParsing() removes full stops after "Mr", "Ms", "Mrs", "Sgt" and ! all question and exclamation marks ! !------------------------------------------------------------------------------ [ BeforeParsing flag i p1 p2 p3; for(i=4: i <= buffer->1 + 1: i++) if (buffer->i == '.') { p3 = buffer->(i-1); p2 = buffer->(i-2); if (i > 4) p1 = buffer->(i-3); else p1 = 0; if ((p1 == 'm' && p2 == 'r' && p3 == 's') ! Mrs || (p2 == 'm' && p3 == 'r') ! Mr || (p2 == 'm' && p3 == 's') ! Ms || (p1 == 's' && p2 == 'g' && p3 == 't')) ! Sgt { buffer->i = ' '; flag = 1; } } else if (buffer->i == '!' or '?' or '"') { buffer->i = ' '; flag = 1; } if (flag) @tokenise buffer parse; ]; !------------------------------------------------------------------------------ ! P R I N T V E R B !------------------------------------------------------------------------------ ! ! This one prints out commands the player entered. ! !------------------------------------------------------------------------------ [ PrintVerb i; switch (i) { 'who': print "ask a ~who~-question"; 'what': print "ask a ~what~-question"; #n$q: print "quit"; #n$l: print "look"; #n$z: print "wait"; #n$x: print "examine"; #n$i, 'inv', 'inventory': print "take inventory"; #n$n, 'north': print "go north"; #n$e, 'east': print "go east"; #n$s, 'south': print "go south"; #n$w, 'west': print "go west"; 'ne', 'northeast': print "go north-east"; 'se', 'southeast': print "go south-east"; 'sw', 'southwest': print "go south-west"; 'nw', 'northwest': print "go north-west"; #n$d, 'down', 'ground', 'floor': print "go downwards"; #n$u, 'up', 'ceiling': print "go upwards"; 'in', 'inside': print "go inside"; 'out', 'outside': print "go outside"; 'yes', #n$y: print "say ~yes~"; 'no': print "say ~no~"; 'why': print "ask ~why~"; 'sorry': print "apologise"; #n$t, 'time': print "know the time"; default: rfalse; } rtrue; ]; !------------------------------------------------------------------------------- ! M O R E I N C L U D E S !------------------------------------------------------------------------------- Include "NPC_Engine.h"; Include "Grammar.h"; Include "NPC_Wait.h"; Include "Utility.h"; Include "DoMenu.h"; Include "AltMenu.h"; Include "Hints.h"; !------------------------------------------------------------------------------ ! C L A S S E S !------------------------------------------------------------------------------ !------------------------------------------------------------------------------ Class Outside class NPC_Room has light; !------------------------------------------------------------------------------ Class Groundfloor class NPC_Room has light; !------------------------------------------------------------------------------ Class Firstfloor class NPC_Room has light; !------------------------------------------------------------------------------ Class Bed_Class with name "bed", capacity 20, space 12, before [; LookUnder: "No doubt you are looking for the bogeyman, but you are out of luck."; ], has supporter scenery enterable; !------------------------------------------------------------------------------ Class Door_Class with npc_open [ npc; if (self has locked) rfalse; npc.npc_door_passed = self; give self open; rtrue; ], description [; print (The) self, " is "; if (self has open) "open, but you can't tell what's beyond it."; "closed."; ], before [; LookThrough: print (The) self, " is "; if (self has open) "open, but you can't tell what's beyond it."; "closed."; Knock: "There is no answer at the door."; ], has scenery door openable; !------------------------------------------------------------------------------ Class Window_Class with before [; Break: "Vandalism is not the answer! Think of your position. How would it look for a famous police inspector to be arrested?"; Open: "The window can't be opened."; ], has scenery; !------------------------------------------------------------------------------ Class Mirror_Class with before [; Break: "Don't you know it's bad luck to break mirrors?"; Search: "A weary Police Inspector looks back at you, with a look that seems to be saying ~Look what the cat dragged in.~"; ], has scenery; !------------------------------------------------------------------------------- ! C O M P A S S D I R E C T I O N S !------------------------------------------------------------------------------- #ifdef WITHOUT_DIRECTIONS; CompassDirection n_obj "north wall" Compass with name 'n//' 'north' 'wall', before [; Knock: if (location == Upstairs_Closet) "The wall to the north here sounds unusually hollow."; print_ret (string) KnockWall; ], door_dir n_to; CompassDirection s_obj "south wall" Compass with name 's//' 'south' 'wall', before [; Knock: print_ret (string) KnockWall; ], door_dir s_to; CompassDirection e_obj "east wall" Compass with name 'e//' 'east' 'wall', before [; Knock: print_ret (string) KnockWall; ], door_dir e_to; CompassDirection w_obj "west wall" Compass with name 'w//' 'west' 'wall', before [; Knock: print_ret (string) KnockWall; ], door_dir w_to; CompassDirection ne_obj "northeast wall" Compass with name 'ne' 'northeast' 'wall', before [; Knock: print_ret (string) KnockWall; ], door_dir ne_to; CompassDirection nw_obj "northwest wall" Compass with name 'nw' 'northwest' 'wall', before [; Knock: print_ret (string) KnockWall; ], door_dir nw_to; CompassDirection se_obj "southeast wall" Compass with name 'se' 'southeast' 'wall', before [; Knock: print_ret (string) KnockWall; ], door_dir se_to; CompassDirection sw_obj "southwest wall" Compass with name 'sw' 'southwest' 'wall', before [; Knock: print_ret (string) KnockWall; ], door_dir sw_to; CompassDirection u_obj "ceiling" Compass with name 'u//' 'up' 'ceiling' 'ascend', description [; if (location ofclass Outside) { if (location == Among_The_Roses or In_The_Orchard) "You can see a balcony directly above you."; "There is blue sky above you."; } "You can see the ceiling. It's not the Sistine Chapel, but it's nicely painted."; ], door_dir u_to; CompassDirection d_obj "floor" Compass with name 'd//' 'down' 'floor' 'ground', description [; if (location == Among_The_Roses || location == Garden_Path) "There are rows upon rows of roses here. It would take you the best part of a day to search the ground in great detail."; else if (location == Foyer) "The floor is marble."; else if (location == Rourke_Room) "The floor is hardwood."; else if (location ofclass Outside) "There's dirt there, mostly; and grass."; "Nothing's interesting about the floor."; ], before [; Search, Dig, DigNear: if (location == Among_The_Roses && Holes in Among_The_Roses) << SEARCH Holes >>; << EXAMINE self >>; ], door_dir d_to; #endif; !------------------------------------------------------------------------------ ! P L A Y E R O B J E C T !------------------------------------------------------------------------------ Object Detective "detective" with short_name [; print "yourself"; rtrue; ], description "You look just like you always did, if a little tired.", after NULL, life NULL, add_to_scope [npc; ! If the action is arrest and add_to_scope hasn't been invoked ! for TestScope reasons (i.e., it wasn't invoked as a result of ! ArrestSub() calling TestScope() ), add all NPCs to scope. if (action_to_be == ##Arrest && scope_reason ~= TESTSCOPE_REASON) { npc = npc_first_npc; while(npc) { PlaceInScope(npc); npc = npc.npc_next; } } ], each_turn [o i j; ! Checking if player carries too many things objectloop (o in player) if (o hasnt worn) { j = j + 1; i = i + ValueOrRun(o, weight); } if (i > ValueOrRun(player,capacity) || j > ValueOrRun(player, space)) { o = child(player); while (o has worn) o = sibling(o); ! In the following, we must first print the message before ! dropping the object because the before-Drop thing of ! an object might change the name print "^Oh no, you're having difficulties holding all these things and let go ", (the) o, " accidentally.^"; keep_silent = 1; < Drop o >; keep_silent = 0; rtrue; } ], time_out NULL, describe NULL, capacity 15, space 7, parse_name 0, orders [; ! Again, this one checks whether the NPC the player is trying ! to address with his orders is in the same location as ! he is. Also see GamePreRoutine(). if (actor ~= player && TestScope(actor) && ScopeCeiling(actor) ~= location && action ~= ##Hey) print_ret (The) actor, " can't hear you."; rfalse; ], before [; Molest: "What a (ahem!) strange idea!"; Find: if (actor == player) "You're around here somewhere..."; ], number 0, has concealed animate proper transparent; !------------------------------------------------------------------------------ ! D A E M O N S !------------------------------------------------------------------------------ !------------------------------------------------------------------------------ Object KillDunbar with stage 0, daemon [; ! While the player isn't in the house, nothing will happen if (location ofclass Outside && self.stage == 0) rfalse; ! While Dunbar isn't in her bedroom or Baxter isn't in the north lawn, nothing ! will happen, either. if ((Ms_Dunbar notin Dunbar_Bedroom || Mr_Baxter notin North_Lawn) && self.stage == 0) rfalse; switch(self.stage) { 0: ! We're moving the ladder to the Orchard and make sure there's no ! way getting to the Library Balcony anymore move Ladder to In_The_Orchard; Among_The_Roses.u_to = 0; Library_Balcony.d_to = 0; ! Baxter is moved to the Orchard Path and the next stage is initiated NPC_Move(Mr_Baxter, In_The_Orchard, ##Go, s_obj); self.stage = 1; 1: ! While the player is on the Bedroom balcony, Baxter won't move. if (location == Bedroom_Balcony) rfalse; ! Baxter can now move, since the player cannot see him. We put the ! ladder up to the balcony railing and move Baxter to the balcony. In_The_Orchard.u_to = Bedroom_Balcony; Bedroom_Balcony.d_to = In_The_Orchard; NPC_Move(Mr_Baxter, Bedroom_Balcony, ##Go, u_obj); self.stage = 2; 2: ! While the player is in the master bedroom, Baxter won't enter it. if (location == Master_Bedroom) rfalse; ! If Mrs. Robner is in the master bedroom, we make sure she's leaving ! soon. if (Mrs_Robner in Master_Bedroom) { if (Mrs_Robner.npc_time_left > 5) Mrs_Robner.npc_time_left = 5; rfalse; } ! Open the balcony door and move Baxter into the master bedroom. give Bedroom_Balcony_Door open; NPC_Move (Mr_Baxter, Master_Bedroom, ##Go, s_obj); self.stage = 3; 3: ! While the player is in the upstairs corridor or in Dunbar's ! room, Baxter won't move if ((location ofclass Firstfloor && location has corridor) || location == Dunbar_Bedroom) rfalse; ! Open the door to the master bedroom and move Baxter to the hallway. give Master_Bedroom_Door open; NPC_Move (Mr_Baxter, Hallway_1, ##Go, s_obj); self.stage = 4; 4: ! Killing Ms. Dunbar. NPC_Move (Ms_Dunbar, 0); ! Baxter is moved to the balcony. NPC_Move (Mr_Baxter, Bedroom_Balcony, ##Go, n_obj); ! Moving objects to the scene of the crime. ! Note that the order of the following statements is important due to their initial ! descriptions (i.e. Dunbar_Body must be moved after the gun and the note) move Smoking_Gun to Dunbar_Bedroom; move Suicide_Note to Dunbar_Bedroom; move Dunbar_Body to Dunbar_Bedroom; move Blue_Pen to Mr_Baxter; ! Saving the time of Dunbar's death; this is needed by the description ! property of Dunbar's body. Dunbar_Body.deathtime = the_time; self.stage = 5; ! See if we need to print a message, telling the player there was a ! pistol shot. if (location ofclass Firstfloor) "You hear a pistol shot close by."; else if(location ofclass Groundfloor) "From upstairs, you hear a single explosion like a pistol shot."; "You hear what sounds like a pistol shot from inside the house."; 5: ! Checking if the player can see Baxter running away from the murder self.stage = 6; if (location == End_Of_Hallway or Hallway_3) "As you enter the hallway, you catch a glimpse of someone running across the eastern end of the hallway from south to north."; if (location == Hallway_2 or Top_Of_Stairs) { Mr_Baxter.seen_escape = 1; "As you enter the hallway, you see Baxter running from Dunbar's room across the hall to the master bedroom."; } if (location == Master_Bedroom) { Mr_Baxter.seen_escape = 1; "As you walk into the bedroom, you see Baxter running past you to the balcony. He doesn't seem to have noticed you."; } 6: ! We move Baxter to In the Orchard and remove the ladder connection NPC_Move (Mr_Baxter, In_The_Orchard, ##Go, d_obj); In_The_Orchard.u_to = 0; Bedroom_Balcony.d_to = 0; ! Baxter will go to the scene of the murder after some time NPC_Schedule(Mr_Baxter, Dunbar_Bedroom, 5+random(5)); self.stage = 7; 7: ! Now we move George to Dunbar's Bedroom if he isn't nervous or busy ! with the new will. if (GeorgeNervous.active == 0 && (GeorgeNewWill.stage == 0 || GeorgeNewWill.stage == 6 || GeorgeNewWill.stage == 9)) NPC_Path(George, Dunbar_Bedroom); ! We can move Mrs. Robner in any case. NPC_Path(Mrs_Robner, Dunbar_Bedroom); ! And we move Rourke to Hallway_1 NPC_Path(Mrs_Rourke, Hallway_1); ! Setting stage to final value and stopping self. We're finished. self.stage = 8; StopDaemon(self); } ]; !------------------------------------------------------------------------------ Object Shed_Episode with stage 0, count 0, daemon [; if (DunbarNervous.stage < 3 || BaxterNervous.stage < 2) rfalse; if (self.stage == 0 && (location ofclass Outside && location ~= West_Lawn or West_Side_Of_House or Behind_The_Shed or Garden_Path or Among_The_Roses)) rfalse; switch(self.stage) { 0: NPC_StopSchedule(Ms_Dunbar); NPC_StopSchedule(Mr_Baxter); DunbarNervous.stage = 4; BaxterNervous.stage = 3; StopDaemon(DunbarNervous); StopDaemon(BaxterNervous); if (Mr_Baxter notin East_Lawn) NPC_Path(Mr_Baxter, East_Lawn); else if (Mr_Baxter in East_Lawn && Mr_Baxter.npc_move_type ~= 2) { Mr_Baxter.npc_move_type = 2; give Mr_Baxter ~concealed; } if (Ms_Dunbar notin East_Lawn && Ms_Dunbar notin Shed) NPC_Path(Ms_Dunbar, East_Lawn); else if (Ms_Dunbar in East_Lawn && Ms_Dunbar.npc_move_type ~= 2) { Ms_Dunbar.npc_move_type = 2; give Ms_Dunbar ~concealed; } self.stage = 1; 1: self.stage = 2; 2: ! If they can see the player, we go back to moving them around if (location ofclass Outside && location ~= West_Lawn or West_Side_Of_House or Behind_The_Shed or Garden_Path or Among_The_Roses) { self.stage = 0; if (Ms_Dunbar notin Shed) { DunbarNervous.stage = 3; StartDaemon(DunbarNervous); } BaxterNervous.stage = 2; StartDaemon(BaxterNervous); rfalse; } NPC_Schedule (Mr_Baxter, Shed, 4+random(2)); if (Ms_Dunbar notin Shed) NPC_Schedule (Ms_Dunbar, Shed, 1+random(2)); self.stage = 3; 3: if (Mr_Baxter notin Shed || Ms_Dunbar notin Shed) rfalse; if (self.count++ < 9) rfalse; self.stage = 4; 4: ! They're leaving NPC_Path(Ms_Dunbar, Dunbar_Bedroom); NPC_Path(Mr_Baxter, North_Lawn); if (Ms_Dunbar in Shed && Mr_Baxter in Shed) StartTimer(DescribeShedLeaving, 0); self.stage = 5; 5: StopDaemon(self); StartDaemon (KillDunbar); } ]; !------------------------------------------------------------------------------ Object DunbarNervous with stage 0, daemon [t; switch(self.stage) { 0: ! She is still in the Living Room if (player notin parent(Ms_Dunbar)) { NPC_Schedule(Ms_Dunbar, Front_Path, 5+random(5)); self.stage = 1; } 1: ! She's on her way to the Front Path ! NPC_arrived of Ms_Dunbar will deal with increasing stage 2: ! She's arrived at the Front Path move Ticket_Stub to parent(Ms_Dunbar); give Ticket_Stub ~concealed; give Ticket_Stub ~moved; StartDaemon(Shed_Episode); self.stage = 3; if (Ms_Dunbar in location) "Ms. Dunbar spots you. She reaches into her pocket and pulls out a cigarette. As she does so, what appears to be a ticket stub falls out of her pocket and floats to the ground. She checks her pocket again, apparently for a match, but finds none and puts the cigarette back in her pocket."; 3: ! She's walking around the garden waiting for the player to disappear if (Ms_Dunbar.npc_move_type ~= 2) ! If she's just moving, we're doing nothing rfalse; if (Ms_Dunbar.npc_dest ~= 0) ! If she already has a destination, we're also doing nothing here rfalse; do { t = random (East_Lawn, Orchard_Path, North_Lawn); } until (t ~= parent(Ms_Dunbar)); NPC_Schedule(Ms_Dunbar, t, 5+random(5)); } ]; !------------------------------------------------------------------------------ Object BaxterNervous with stage 0, daemon [ t; switch(self.stage) { 0: ! He is still in the Living Room if (Ms_Dunbar notin Front_Path) rfalse; NPC_Schedule(Mr_Baxter, East_Lawn, 3+random(3)); self.stage = 1; 1: ! He's on his way to the East Lawn 2: ! He's walking around the garden, waiting for the player to disappear if (Mr_Baxter.npc_move_type ~= 2) rfalse; if (Mr_Baxter.npc_dest ~= 0) rfalse; do { t = random (East_Lawn, Orchard_Path, North_Lawn); } until (t ~= parent(Mr_Baxter)); NPC_Schedule(Mr_Baxter, t, 7+random(7)); } ]; !------------------------------------------------------------------------------ Object LeaveMasterBedroom with no 0, daemon [; self.no++; if(self.no == 1) ! First time we don't do anything rfalse; if (self.no <= 3) "Mrs. Robner glares at you, holding the phone in one hand. ~Would you mind terribly?~, she asks."; NPC_Path(Mrs_Robner, Living_Room); Mrs_Robner.go_phone = 0; StopDaemon(self); "~I can't understand why you won't let me use the phone. Can't I talk to my best friend? Hummph...I suppose it can wait, since you are being so...uh...unhelpful.~ She puts down the receiver, rises from her bed, and starts to leave."; ]; !------------------------------------------------------------------------------ Object GeorgeNervous with follow 0, ! The player is following George! ==2 means, George has complained about that active 0, ! Is this daemon active right now? waitleave 0, ! How long has George waited for the detective to leave? delay 3, ! Used for a delay between George arriving at his room and his attempt to go to the Library daemon [; if (George in George_Bedroom && location == George_Bedroom) { if(George.npc_move_type == 2) { print "George paces around the room, awaiting your departure with ill-concealed impatience.^"; self.waitleave++; if (self.waitleave == 1 && self.follow < 2) "~I have business to attend to. Would you mind leaving?~"; else if (self.waitleave == 1 && self.follow == 2) "~I don't understand you, Inspector. I asked to be alone so I can take care of some business. I...I don't see why you have to snoop around here like I was some sort of suspect.~"; else if (self.waitleave == 12) { self.active = 2; ! George is on his way to the living room self.follow = 0; self.waitleave = 0; ! resetting these, since George will come back and the thing will start over NPC_Path(George, Living_Room); "~I can't take this. You get on my nerves. I'm leaving.~"; } } } else if (George in George_Bedroom && location ~= George_Bedroom && George_Bedroom_Door hasnt open) { if (self.delay > 0) self.delay--; else if (location == Hallway_1 or Hallway_2 or Top_Of_Stairs) { if (random (10) == 1) { George.npc_met = turns; "A door opens down the hall. George steps out, spots you, and looks briefly toward the window. After a moment he steps back into his room and shuts the door."; } else if (random(10) == 1) "You faintly hear a door open and then close near the end of the hall."; } else if (location == Hallway_3) { if (random(5) == 1) { George.npc_met = turns; "George opens his door and peeks out. He is startled by your presence, excuses himself, and closes the door sharply in your face before you can utter a word."; } } else if (location == End_Of_Hallway or Library) { if (random(5)==1) { print "You hear George's door open and "; if (random(2)==1) { George.npc_met = turns; "you catch a brief glimpse of his head darting back into the doorway. You watch as the door closes again."; } "close again immediately."; } } else { if(random(5) == 1) { give George_Bedroom_Door open; move George to Library; StartDaemon(GeorgeNewWill); GeorgeNewWill.stage = 1; self.active = 0; self.follow = 0; self.waitleave = 0; self.delay = 3; StopDaemon(self); if (location == Upstairs_Closet) { George.npc_met = turns; "You hear George's door open and you see his head poke out briefly, scanning the hallway. He apparently didn't see you, and darts across the hall to the library."; } if (location == Library_Balcony) { George.npc_met = turns; "You see George through the doorway, looking down the hallway, then darting into the library."; } } } } else if (George in George_Bedroom && location == Hallway_3 && George_Bedroom_Door has open) { if(random(5) == 1) { George.npc_met = turns; give George_Bedroom_Door ~open; "George walks up to his door and slams it in your face."; } } else if (George in George_Bedroom) give George_Bedroom_Door ~open; ]; !------------------------------------------------------------------------------ Object GeorgeNewWill with stage 0, count 0, ! Indicates how long George has been in the Hidden Closet daemon [; switch(self.stage) { 1: self.stage = 2; rfalse; 2: ! George is in the Library and will now open the hidden closet door and enter it give Black_Button general; move George to Hidden_Closet; self.stage = 3; if (location == Library_Balcony) { George.npc_met = turns; "George walks purposefully toward the bookshelves. He looks around, but you react before he can see you. When you peek out again, George is fiddling with the shelves. His right arm reaches into the shelf and, to your amazement, the unit of bookshelves on the left rotates away from the wall, revealing a darkened room behind. George enters it, trembling with barely controlled fear and excitement."; } 3: self.stage = 4; if (location == Library_Balcony or Library) { George.npc_met = turns; "A dim light in the hidden closet comes on. In the faint light, you can see George motioning with his right hand. All at once, the shelf swings shut!"; } 4: if(self.count++ == 16) { if (location == Library) { George.npc_met = turns; move George to Garden_Path; give New_Will concealed; NPC_Path(George, North_Lawn); self.stage = 5; "Suddenly, the bookshelves swing out, forming an opening to a dark area behind. George starts to emerge but stops suddenly as he notices you! With jack-rabbit reflexes, he darts back inside. Before you can act, the shelves close again."; } move George to Library; give New_Will concealed; NPC_Path(George, North_Lawn); self.stage = 5; if (location == Library_Balcony) { George.npc_met = turns; "Suddenly, the shelf swings out, and George emerges. He walks over to a special place in the shelves and reaches behind some books. The bookshelves silently assume their normal position."; } } 8: ! The player has caught George redhanded in the hidden closet if(self.count++ == 11) { StopDaemon(self); self.stage = 9; NPC_Schedule(George, George_Bedroom, 1); } } ]; !------------------------------------------------------------------------------ ! T I M E R S !------------------------------------------------------------------------------ !------------------------------------------------------------------------------ Object DescribeShedLeaving with time_left 0, time_out [; if (location == South_Lawn or East_Lawn or East_Side_Of_House) "Baxter and Dunbar both leave the shed, heading off in different directions."; if (location == Behind_The_Shed) "The voices stop and you hear sets of footsteps leaving the shed."; rfalse; ]; !------------------------------------------------------------------------------ Object TimeUp with time_left 0, time_out [; print "^Chief Inspector Klutz walks up to you, seemingly from out of nowhere. ~I'm sorry, Inspector, but your time is up here. I'm sorry that you didn't have any more time to investigate the case. Maybe next time...~ He escorts you to a waiting police car, in which you go off into the sunset.^"; EndOfGame(0); ]; !------------------------------------------------------------------------------ Object WillReading with time 0, ! saving the time will reading was daemon [; if (Mrs_Robner in location) { StopDaemon(self); "Mrs. Robner turns to you. ~I don't understand why you missed the will reading. You seem so interested in everything else that goes on around here.~"; } if (Mr_Coates in location) { StopDaemon(self); "Mr. Coates says, in passing, ~To tell you the truth, Inspector, my suspicions about this case are not quite allayed. I wish you had been at the will reading. Good day.~"; } ], time_left -1, time_out [; ! First of all, let's see if all NPCs that should hear the will reading are ! actually present in the living room. If not, Coates waits until ! 12:40 pm and then starts the will reading anyway. if (George notin Living_Room || Mrs_Robner notin Living_Room || Ms_Dunbar notin Living_Room || Mr_Baxter notin Living_Room) { if (the_time < 12*60+40) { StartTimer(self, 0); if (location == Living_Room) { ! Indicating that we're NOT waiting for the player. give self ~general; if (random(100) < 75 || the_time <= 12*60) rfalse; if (random (100) > 50) "Mr. Coates asks everyone to be patient, as not everyone is present."; else "Mr. Coates appears distracted, looking frequently toward the door."; } rfalse; } if (location == Living_Room) print "~It's late, so let's begin!~ Coates says.^"; } ! Either everybody's there or Coates wants to begin without someone. ! Now let's see if the player's also there. If not, Coates waits until 12:15 ! and starts the will reading then. if (location ~= Living_Room && the_time < 12*60+15) { StartTimer(self, 0); if (the_time > 12*60) give self general; rfalse; } ! Coates will read the will now. Before that, we have to check whether ! Mrs. Robner has to complain to the player that he wasn't there on time. if (location == Living_Room && self has general) print "The people present turn to look at you. Mrs. Robner glares at you. ~You might at least have the courtesy to be here on time! Haven't you caused enough disruption already? We should have started without you. Mr. Coates, please proceed.~^"; ! Finally, let's see if we were waiting for someone else... else if (the_time > 12*60+5) { if (location == Living_Room && Ms_Dunbar in Living_Room && Mr_Baxter in Living_Room && Mrs_Robner in Living_Room && George in Living_Room) print "~Ah!~ Mr. Coates says, ~Everybody's here now.~^"; } ! The following is all only printing that of course will only be executed ! if the player is actually present. if (location == Living_Room) { ! This one indicates that the player has attended the will reading. We need ! this for some reactions of NPCs to questions later on. give self visited; print "Mr. Coates begins: ~This is an awkward situation. Mr. Robner told me five days ago that he wanted to execute a new will, and promised to call me when it was completed. As I never heard from him, I must assume that he either changed his mind or did not complete the new will. Therefore, the one in my possession must be considered the most recent testament.~^"; if (George in Living_Room) { if (Calendar has george_shown) print "You notice that George, who was not initially paying close attention, now perks up and begins to look about anxiously.^"; else print "From the corner of your eye, you catch George nodding his head, as if in approval, and smiling broadly.^"; } print "Continuing, Mr. Coates says: ~Naturally, should a more recent will exist and be found within a reasonable period, the present one will be voided. I will proceed with reading the will here in my hands, which was executed three years ago last month.~ He reads the will, simply written and direct, leaving equal parts of the estate to his son, George Arthur Robner, and his wife, Mrs. Leslie Phillips Robner.^ There is some discussion, understated congratulations and overstated sympathy, which Mr. Coates cuts short by clearing his throat. ~I must leave now, I'm afraid. If you have any questions, I can be contacted tomorrow.~ He picks up the phone, dials his office, and asks to be picked up at the Robner estate.^"; if (Calendar has george_shown && George in Living_Room) print "George, now looking quite upset, starts for the door.^ ~I've...got to be going now. I'll see you later,~ George says. He starts to leave.^"; } else StartDaemon(self); ! We're taking note of the time the will has been read. self.time = the_time; ! Mr Coates is going to the South Lawn where a car will pick him up NPC_Path(Mr_Coates, South_Lawn); ! And if George has been shown the calendar, he is nervous and ! he'll go to his room; otherwise to East Lawn if(Calendar has george_shown) { NPC_Path(George, George_Bedroom); GeorgeNervous.active = 1; StartDaemon(GeorgeNervous); } else NPC_Schedule(George, East_Lawn, 40+random(10)); ! Mrs. Robner goes to the Master Bedroom NPC_Schedule(Mrs_Robner, Master_Bedroom, 40+random(20)); ! If the player was present, we need to return true, otherwise false. if (location == Living_Room) rtrue; rfalse; ]; !------------------------------------------------------------------------------ Object StevenCallEnds with time_left 0, time_out [; Mrs_Robner.go_phone = 0; NPC_Path(Mrs_Robner, Living_Room); ]; !------------------------------------------------------------------------------ Object PhoneRing with time_left 0, time_out [; StartDaemon(self); rfalse; ], daemon [; if(self hasnt general) { give self general; Mrs_Robner.go_phone = 1; NPC_Path(Mrs_Robner, Living_Room); if (location == Living_Room or Master_Bedroom or Library) "The telephone rings."; else if(location ofclass Groundfloor or Firstfloor) { print "You hear a phone ringing in a nearby room."; if (Mrs_Robner in Dining_Room && location == Dining_Room) print " Mrs. Robner says ~Pardon me~ and starts for the door."; new_line; rtrue; } else if (random(2) == 1) "You notice a very faint ringing sound coming from the house."; } else if (location ofclass Groundfloor or Firstfloor) "The phone rings again."; ]; !------------------------------------------------------------------------------ Object Mailman with time_left 0, time_out [; if(location == South_Lawn or West_Of_Front_Door or East_Of_Front_Door) { move Envelope to Marble_Table; "You notice a mailman stop by the house briefly and depart."; } else if (location == Foyer) { move Envelope to Foyer; Envelope.initial = "Partially exposed under the front door is an envelope."; "There is a short rap on the front door. A moment later, a thin envelope appears under the door."; } else if (location == Front_Path) { move Envelope to player; give Envelope moved; "A mailman walks briskly up to you, hands you an envelope, and departs."; } move Envelope to Marble_Table; rfalse; ]; !------------------------------------------------------------------------------ Object Paperboy with time_left 0, time_out [; move Newspaper to Front_Path; if(location == South_Lawn or Front_Path) "The local paperboy, in an amazing athletic feat, throws a newspaper toward the house from a distance of at least 100 feet. It even lands beside the front door, rather than in the bushes."; ]; !------------------------------------------------------------------------------ Object BaxterArrival with time_left 0, time_out [; move Mr_Baxter to South_Lawn; Mr_Baxter.npc_old_dir = n_obj; NPC_Path(Mr_Baxter, Living_Room); if(location == South_Lawn) "A limosine pulls up the drive. Mr. Baxter exits and the limo pulls away. Baxter takes a deep breath and looks around."; if(location == Front_Path or West_Of_Front_Door or East_Of_Front_Door or East_Lawn or West_Lawn) "A car pulls up the drive to the south, and Mr. Baxter steps out onto the lawn."; ]; !------------------------------------------------------------------------------ Object CoatesArrival with time_left 0, time_out [; move Mr_Coates to South_Lawn; Mr_Coates.npc_old_dir = n_obj; NPC_Path(Mr_Coates, Living_Room); if(location == South_Lawn) "A large automobile pulls up the drive. Mr. Coates, the lawyer, steps out of the car. ~Oh, hello! You must be the Inspector. I'll be reading the will at noon, you know. Don't be late!~ he says."; if(location == Front_Path or West_Of_Front_Door or East_Of_Front_Door or East_Lawn or West_Lawn) "A car pulls up the drive to the south, and Mr. Coates steps out onto the lawn."; ]; !------------------------------------------------------------------------------ Object MusicEnds with time_left 0, time_out [; if(Tapes.active == 0 && Records.active == 0) rtrue; if(location == George_Bedroom) { print "The "; Describe_Music(); print " has ended (and not soon enough)."; Records.active = 0; Tapes.active = 0; if(George in George_Bedroom) { print " George walks over to his stereo and returns the music to its proper place. He then chooses a "; if(random(2) == 1) { print "record"; Records.active = random(7); } else { print "tape"; Tapes.active = random(6); } print " from his large collection. Dear Lord! It's a "; Describe_Music(); print "."; StopTimer(self); StartTimer(self, 15+random(5)); } new_line; rtrue; } Records.active = 0; Tapes.active = 0; ]; !------------------------------------------------------------------------------ Object DuffyTimer with time_left -1, time_out [; print "Sergeant Duffy "; if (Duffy.anal == Ladder) print "comes onto the scene."; else switch(random(3)) { 1: print "appears before you, holding ", (the) Duffy.anal, " carefully in his hands. His quiet efficiency and youthful vigor impress you quite a bit."; 2: print "seems to arrive from nowhere, holding ", (the) Duffy.anal, " in his hands."; 3: print "returns with ", (the) Duffy.anal, ". For a moment you muse on his almost magical entrances."; } print " "; if (Duffy.anal_for == -1) { print "~The fingerprints,~ he begins, ~belong to "; if (Duffy.anal == Library_Teacup) ! Will apparently never reach this print "Mr. Robner."; else if (Duffy.anal == Bowl or Library_Saucer) print "Mr. Robner and Ms. Dunbar."; } else if (Duffy.anal_for) { if(Duffy.anal == Fragment && Duffy.anal_for == 'loblo') { print "~The fragment did contain LoBlo. Here is the full report.~ He hands you a slip of paper, and departs.^"; move Lab_Report to player; give Lab_Report moved; move Duffy.anal to player; self.time_left = -1; rtrue; } print "~The ", (name) Duffy.anal, " analysis yielded nothing useful."; } else switch(Duffy.anal) { Bowl: print "~The bowl,~ he begins, ~has the fingerprints of Mr. Robner and Ms. Dunbar. The bowl contains common table sugar only."; Library_Saucer: print "~The saucer,~ he begins, ~contains traces of tea and sugar. The fingerprints are those of Mr. Robner and Ms. Dunbar."; Library_Teacup: print "~The cup,~ he begins, ~contains a trace of tea. The fingerprints are those of Mr. Robner."; Fragment: print "~The fragment,~ he begins, ~contains traces of tea and sugar. In addition, there seems to be some other chemical present that is not a common medication. It could take weeks to determine exactly what it is. It is definitely not Amitraxin (Ebullion), though. There are no clear fingerprints."; default: print "~I am sorry,~ he begins, ~but the lab found nothing of interest."; } if (Duffy.anal == Ladder && ~(location ofclass Outside)) { print " In the interests of civility, I have left the ladder outside the house.~ He leaves.^"; move Ladder to Front_Path; self.time_left = -1; rtrue; } print "~ With that, he leaves, handing you ", (the) Duffy.anal, " as he whisks away.^"; move Duffy.anal to player; self.time_left = -1; rtrue; ]; !------------------------------------------------------------------------------ Object NewWillToLake with time_left 0, time_out [; remove New_Will; move Wet_Piece_Of_Paper to Lake; if (George in location) { New_Will.destruction_seen = 1; "You catch, out of the corner of one eye, George motioning with his arm toward the lake."; } ]; !------------------------------------------------------------------------------ Object FindHoles with time_left 0, time_out [; Mr_McNabb.holes_found = 1; ! He has found the holes move Holes to Mr_McNabb; if (Mr_McNabb in location) { Mr_McNabb.show_holes = 1; ! He's told the player about the holes "All of a sudden, Mr. McNabb starts talking to himself quite loudly about his poor roses being ruined. He walks up to you and says ~You canna believe the holes someone's made. Crushed my roses. It'll take me plenty a time to set it right. I just canna believe it!~ He shakes his head dejectedly."; } ]; !------------------------------------------------------------------------------ Object ShowHoles with from, ! Where was McNabb when player asked him to show the holes? dest, ! What was his next destination room at that point? time_save 0, time_left 0, time_out [; Mr_McNabb.show_holes = 3; NPC_Path(Mr_McNabb, self.from); if (location == Among_The_Roses) { move Holes to Among_The_Roses; give Holes ~concealed; "McNabb grabs your arm and leads you to a spot deep within the garden and near the house. You might never have found this place alone. He points at the ground, where you see two holes in the soft earth."; } ]; !------------------------------------------------------------------------------ ! S C O P E R O U T I N E S !------------------------------------------------------------------------------ [ TopicScope x; switch(scope_stage) { 1: rfalse; 2: objectloop (x has topic) PlaceInScope(x); rfalse; 3: L__M(##Miscellany, 30); } ]; !------------------------------------------------------------------------------ [ FindScope x; switch(scope_stage) { 1: rfalse; 2: objectloop (x has findable) PlaceInScope(x); rfalse; 3: L__M(##Miscellany, 30); } ]; !------------------------------------------------------------------------------ [ SearchForScope x; switch(scope_stage) { 1: rfalse; 2: objectloop(x hasnt scenery or static or animate && metaclass(x) == Object) PlaceInScope(x); 3: if (inputobjs-->2 && inputobjs-->2 has animate) print_ret (The) inputobjs-->2, " surely doesn't have that."; "[That's not something you can search for.]"; } ]; !------------------------------------------------------------------------------ [ AskForScope x; switch(scope_stage) { 1: rfalse; 2: objectloop(x hasnt scenery or static or animate && metaclass(x) == Object) PlaceInScope(x); 3: if (inputobjs-->2 && inputobjs-->2 has animate) print_ret (The) inputobjs-->2, " doesn't have that."; "[That's not something you can ask for.]"; } ]; !------------------------------------------------------------------------------ [ LookInRoomScope x; switch(scope_stage) { 1: rfalse; 2: objectloop(x ofclass NPC_Room) PlaceInScope(x); 3: "[That's not a room you can look in.]"; } ]; !------------------------------------------------------------------------------ ! T O K E N S !------------------------------------------------------------------------------ [ ReadToken; if (noun == Cornerstone or Ending) rtrue; rfalse; ]; !------------------------------------------------------------------------------ ! I N C L U D E G A M E F I L E S !------------------------------------------------------------------------------ Include ">Outside.inf"; Include ">Groundfloor.inf"; Include ">Firstfloor.inf"; Include ">NPC.inf"; Include ">OtherObj.inf"; Include ">EndOfGame.inf"; !------------------------------------------------------------------------------ ! V E R B R O U T I N E S !------------------------------------------------------------------------------ !------------------------------------------------------------------------------ [ LookInRoomSub current_compass dir check check2 save_loc; if (noun == location) "You are in the ", (name) noun, " right now."; objectloop (current_compass in Compass) { dir = ObjectOrRun(current_compass, door_dir); check = ObjectOrRun(location, dir); if (check && check has door) { check2 = NPC_GetOtherSide(location, check); if (check2 == noun) << LookThrough check >>; } if (check && check == noun) { print "You take a quick peek into the ", (name) noun; if (~~ WillPrintDescription(noun)) ", but you don't see anything special there."; print ":^"; save_loc = location; location = noun; if(Locale(noun, "You can see", "You can also see")) print ".^"; location = save_loc; rtrue; } } "You can't seem to find that room."; ]; !------------------------------------------------------------------------------ [ WillPrintDescription obj o k; objectloop (o in obj) { if (o hasnt concealed or scenery) k++; if (o has scenery && o has supporter) k = k + WillPrintDescription(o); } return k; ]; !------------------------------------------------------------------------------ [ ClimbCarefullySub; << Climb noun >>; ]; !------------------------------------------------------------------------------ [ ClimbDownCarefullySub; << ClimbDown noun >>; ]; !------------------------------------------------------------------------------ [ ThankSub; if (noun) { if (noun hasnt animate) "Your sanity is in question."; if (noun == player) "Your ego is big enough already."; print_ret (The) noun, " acknowledges your thanks."; } "Whatever do you have to be thankful for?"; ]; !------------------------------------------------------------------------------ [ ShakeSub; if (noun has container && child(noun)) { if (noun has open) { while(child(noun)) move child(noun) to location; "Everything in it spills to the floor."; } "It sounds as though there is something inside ", (the) noun, "."; } "Well, what did you expect to happen?"; ]; !------------------------------------------------------------------------------ [ BiteSub; if (noun == player) "Don't let your soft spot for masochism become too apparent."; if (noun has animate) "This sort of shabby behavior is disgusting."; << Eat noun >>; ]; !------------------------------------------------------------------------------ [ CurseSub; if (noun has animate && noun ~= player) "Insults of this nature won't help you."; "What a loony!"; ]; !------------------------------------------------------------------------------ [ ThrowAtSub; if (ObjectIsUntouchable(noun)) return; if (second>1) { action=##ThrownAt; if (RunRoutines(second,before)~=0) { action=##ThrowAt; rtrue; } action=##ThrowAt; } if (second hasnt animate) "Perhaps you aren't feeling well?"; if (RunLife(second,##ThrowAt)~=0) rfalse; move noun to location; print_ret (The) second, ", puzzled by your unorthodox methods, ducks as ", (the) noun, " flies by."; ]; !------------------------------------------------------------------------------ [ BreakSub; if (noun has animate) << KILL noun second >>; print "Trying to destroy ", (the) noun, " "; print_ret (string) random("isn't particularly useful.", "has no effect."); ]; !------------------------------------------------------------------------------ [ BugSub; "If there is a problem here, it is unintentional. You may report your problem to the address provided in your documentation."; ]; !------------------------------------------------------------------------------ [ WhySub; if (actor ~= player) << ASK actor noun >>; if (noun == player) "You're the inspector and, in case you forgot, you're here to find out about this case."; if (noun has animate) "Surely you have read the interviews."; if (noun ~= 0) "This question cannot be answered."; "Detectives are expected to know how to conduct an interrogation; please re-read your casebook for remedial instruction. Remember that the documentary evidence enclosed contains the answers to all of the important questions which cannot be asked directly."; ]; !------------------------------------------------------------------------------ [ SearchForSub; if (second in noun) { print "How observant you are! There "; if (second has pluralname) "they are."; "it is."; } "You don't find ", (the) second, " there."; ]; !------------------------------------------------------------------------------ [ ExamineRoomSub t; if (location ofclass Firstfloor or Groundfloor) t = 7; else t = 10; if (location has corridor) t = t - 4; print "An exhaustive search of even a single room would take hours. A more productive approach would be to examine or search various items of interest within the room. A cursory search would take on the order of ", t, " minutes, but it wouldn't reveal much.^Would you like to do it anyway? (Y/N) > "; if(YesOrNo()) { t = t - 2 + random(3); for (:(t>1)&&(deadflag==0)&&(tw_waiting hasnt on):t--) { InformLibrary.End_Turn_Sequence(); DisplayStatus(); DrawStatusLine(); } if ((tw_waiting has on)&&(t>1)&&(deadflag==0)) "You didn't get a chance to finish looking over the room."; "Your brief search revealed nothing that was not obvious before."; } "Ok."; ]; !------------------------------------------------------------------------------ [ CallUpSub; if (noun has animate && noun in location) print_ret (The) noun, " is in the same place as you are!"; if (location ~= Living_Room or Master_Bedroom or Library) "And how do you want to make a phone-call without a telephone?"; if (Mrs_Robner.go_phone == 3) { print "You pick up the phone to do your call. But you don't hear a dial tone. Apparently, you're the witness of a phonecall made on another extension in the house. "; < TAKE Telephone >; "Deep in thought about what you heard you hang up the phone. You completely forgot that you wanted to make a call yourself."; } if(DaemonRunning(PhoneRing)) "Any child knows that you can't call someone while the phone is ringing."; if (noun hasnt animate) "How, exactly, does one ring that?"; "There's no sense in phoning ", (the) noun, "."; ]; !------------------------------------------------------------------------------ [ MyAnswerSub; if (noun == 0) "Nobody seems to be awaiting your answer."; "It is hardly likely that ", (the) noun, " is interested."; ]; !------------------------------------------------------------------------------ [ TimeSub; print "It is now "; LanguageTimeOfDay((the_time+1)/60, (the_time+1)%60); "."; ]; !------------------------------------------------------------------------------ [ HelpSub; #IFDEF NOHINTS; "This release of DEADLINE doesn't feature InvisiClue hints."; #IFNOT; if (hint_menu has locked) "InvisiClues have been disabled for this session."; if (hint_menu hasnt general) { give hint_menu general; "[Warning: It is recognized that the temptation for help may at times be so exceedingly strong that you might fetch hints prematurely. Therefore, you may at any time during the story type HINTS OFF, and this will disallow the seeking out of help for the present session of the story. If you still want a hint now, indicate HINT.]"; } hint_menu.select(); new_line; < Look >; #ENDIF; ]; [ HelpOffSub; #IFDEF NOHINTS; << HELP >>; #IFNOT; print (string) HINTD__TX; give hint_menu locked; rtrue; #ENDIF; ]; !------------------------------------------------------------------------------ [ JumpSub; if (location == Bedroom_Balcony or Library_Balcony && location.d_to == 0) { print "For a brief moment, you feel the exhilaration of free fall. A thought hits you: the ground is moving toward me. It is your last thought.^"; EndOfGame(0); } "Wheeeeeeeeee!!!!!"; ]; !------------------------------------------------------------------------------ [ AccuseSub; if (noun == player) "Don't worry, your super ego will take care of that."; if (noun hasnt animate) { print "What a detective! Quick, Sergeant! Arrest "; if (noun hasnt proper) { if (noun has pluralname) print "those "; else print "that "; } print_ret (name) noun, "!"; } print_ret (The) noun, " shrugs off your suggestion."; ]; !------------------------------------------------------------------------------ [ AccuseOfSub; ! I have no idea why this one won't work with "if (second == 'murder')", just ! like it _does_ work in AnalyseSub(). If anyone can explain this to me, ! please let me know ;-)) if (consult_words == 1) { wn = consult_from; if (NextWord() == 'murder') << Accuse noun >>; } "What an accusation!"; ]; !------------------------------------------------------------------------------ [ HeySub; if (noun) { if (noun == player) "Are you trying to make yourself concentrate upon your work? Good!"; "~Hey, Inspector!~ replies ", (the) noun, ". ~Are your hallucinations any better today?~"; } "Hey yourself!"; ]; !------------------------------------------------------------------------------ [ KillSub; if (noun hasnt animate) { "No doubt you need a refresher course at the academy in the martial arts, but ", (the) noun, " is hardly a likely target."; } if (noun == player) "Looking at your achievements in this case so far, it's hardly surprising to see you come up with ideas like that."; if(random(100) < 75) "You rethink your planned action."; if (second == Smoking_Gun) print "A shot rings out and ", (the) noun, " falls to the ground, dead. Good shot. "; else print "With a lethal blow of your hand, ", (the) noun, " falls dead. "; BehavedBadly(); ]; !------------------------------------------------------------------------------ [ AnalyseSub; if(DuffyTimer.time_left >= 0) print_ret (string) DuffyBusy; if (noun has scenery or static or animate) "Sergeant Duffy appears with a puzzled look on his face. ~With all respect, I don't think I can take THAT to the laboratory! I'll be nearby if you need me.~ He leaves, shaking his head slowly."; if(second == 'fingerprints') << FINGERPRINT noun >>; StartAnalysis(noun, second, 0); rtrue; ]; !------------------------------------------------------------------------------ [ FingerprintSub; if(DuffyTimer.time_left >= 0) print_ret (string) DuffyBusy; if (noun == Library_Teacup) "There don't seem to be any fingerprints on the cup."; if (noun == Bowl or Library_Saucer) { print "You look at ", (the) noun, " closely. It appears to have good fingerprints on it, so you call for Sergeant Duffy.^"; StartAnalysis(noun, second, 1); rtrue; } "Upon looking over and dusting ", (the) noun, " you notice that there are no good fingerprints to be found."; ]; !------------------------------------------------------------------------------ [ StartAnalysis obj a_for fprint; Duffy.anal = obj; move Duffy.anal to Duffy; if (fprint == 1) Duffy.anal_for = -1; else if(a_for) Duffy.anal_for = a_for; else Duffy.anal_for = 0; StartTimer(DuffyTimer, 15+random(15)); "Sergeant Duffy walks up as quietly as a mouse. He takes ", (the) Duffy.anal, " from you. ~I'll return soon with the results,~ he says, and leaves as silently as he entered."; ]; !------------------------------------------------------------------------------ [ HelloSub; if (noun) "Only schizophrenics say ~hello~ to ", (a) noun, "."; "Good day."; ]; !------------------------------------------------------------------------------ [ GoodbyeSub; if (noun) "Only schizophrenics say ~goodbye~ to ", (a) noun, "."; << Hello >>; ]; !------------------------------------------------------------------------------ [ MyListenSub; if (noun has door) { if (noun hasnt open) "You can't hear anything through ", (the) noun, "."; else "It is wide open."; } print_ret (The) noun, " makes no sound."; ]; !------------------------------------------------------------------------------ [ TurnOnSub; if(noun has animate) "Ahem! You may or may not realize this, but you are on a case. You shouldn't be wasting your time attempting to flirt with the suspects. In any event, it's unlikely that you are person enough to do it."; "You can't turn that on."; ]; !------------------------------------------------------------------------------ [ TurnOffSub; if (noun has animate) "Your uncouth manner is certain to turn anyone off."; "You can't turn that off."; ]; !------------------------------------------------------------------------------ [ MolestSub; if (noun has animate && noun ~= player) { if (random(100) > 75) "Section 29A of the United States Criminal Code, whose provisions come to your unhealthy mind, tut-tuts this sort of thing. A pity."; else BehavedBadly(); } "What a (ahem!) strange idea!"; ]; !------------------------------------------------------------------------------ [ HideSub; switch(location) { East_Lawn: "You might hide behind the shed."; Library: "You might hide on the balcony."; } "There's no good hiding place here."; ]; !------------------------------------------------------------------------------ [ BatheSub; print "Swimming isn't possible "; if (noun) print "on ", (the) noun; else if (location ofclass Outside) print "on the ground"; else print "right on the floor, Sherlock"; "."; ]; !------------------------------------------------------------------------------ ! V E R B S T U B S !------------------------------------------------------------------------------ [ TurnToSub; << TURN noun >>; ]; [ ExamCareSub; << EXAMINE noun >>; ]; [ ClimbDownSub; L__M(##Go, 2); ]; [ TellWhatsWrongSub; << ASK actor Weather >>; ]; [ WhatsWrongSub; << ASK actor Weather >>; ]; [ AskWhatsWrongSub; << ASK noun Weather >>; ]; [ DigNearSub; << DIG noun second >>; ]; [ HideOnSub; "You hit your head against ", (the) noun, " as you attempt this feat."; ]; [ ReadSub; "You cannot read ", (the) noun, "."; ]; [ CountSub; "Unless you are drunk, one."; ]; [ KnockSub; "Why knock on ", (a) noun, "?"; ]; [ MyRubSub; "Fiddling with ", (the) noun, " produces no effect."; ]; [ LookAgainstSub; "That doesn't make much sense."; ]; [ RunOverSub; "That doesn't make much sense."; ]; [ TurnUpSub; "That is silly."; ]; [ TurnDownSub; "That is silly."; ]; [ PlaySub; "You are adept only at playing the fool."; ]; [ DiagnoseSub; "You're OK for now."; ]; [ ScoreSub; "You are an amateur inspector, at best."; ]; [ CleanSub; "Cleanliness is next to Godliness, although in this case it seems to be next to Uselessness."; ]; [ SighSub; "It has been a long day, hasn't it?"; ]; [ MyUnlockSub; "It doesn't seem to work."; ]; [ UseSub; "You should be more specific with what you want to do."; ]; [ FlushSub; "Whatever do you have in mind?"; ]; [ LeanSub; "You can't do that."; ]; [ EatMealSub; "Although rather hungry, you realize that the case is too important for you to be eating meals."; ]; [ LookThroughSub; "You cannot see through ", (the) noun, "."; ]; [ WriteSub; "You're nuts."; ]; !------------------------------------------------------------------------------ ! D E B U G V E R B !------------------------------------------------------------------------------ #ifdef DEBUG; [ dbVerbSub; StopTimer (PhoneRing); StopTimer (Mailman); StopTimer (Paperboy); StopTimer(BaxterArrival); StopTimer(CoatesArrival); if (parent(Mr_Baxter) == 0) StartTimer(BaxterArrival, 0); StopTimer(FindHoles); move Lab_Report to player; give Lab_Report moved; give Lab_Report dunbar_shown; give Lab_Report baxter_shown; move Stack_Of_Papers to player; give Stack_Of_Papers moved; give Stack_Of_Papers baxter_shown; give Pad general; move Ticket_Stub to player; give Ticket_Stub baxter_shown; give Ticket_Stub dunbar_shown; give Calendar george_shown; "Ok."; ]; #endif; !------------------------------------------------------------------------------ ! V A R I O U S G A M E R O U T I N E S !------------------------------------------------------------------------------ !------------------------------------------------------------------------------ [ NPC_Msg act n x1 x2; switch(act) { ##NPC_Goto: switch(n) { 1: "You're already there!"; 2: "You don't know how to get there right now."; 3: "You're moving closer towards ", (the) x1, "."; default: NPC_Error(26, n); rtrue; } ##Wait: switch(n) { 1: "That's too long to wait."; 2: "Time doesn't pass."; 3: "Time passes..."; 4: print "Do you want to keep waiting? (Y/N) >"; rtrue; 5: print "^It is now "; 6: "."; 7: "(tomorrow)"; 8: "Not a good idea. You might wait all day."; 9: print_ret (The) x1, " ", (isorare) x1, " already here!"; 10: "^", (The) x1, ", for whom you are waiting, ", (hasorhave) x1, " arrived."; 11: print (The) x1, " still ", (hasorhave) x1, "n't arrived. "; rtrue; 12: "Ok."; default: NPC_Error (18, n); rtrue; } ##Miscellany: switch(n) { 1: print (The) x1, " start"; if (x1 hasnt pluralname) print "s"; " to move about distractedly."; 2: "You're the detective."; 3: print_ret (The) x1, " ", (isorare) x1, " here."; 4: print (The) x1, " "; if(x1.npc_door_passed) { print "open"; if (x1 hasnt pluralname) print "s"; print " ", (the) x1.npc_door_passed, " and "; } if (x2 == u_obj or d_obj) print (isorare) x1, " going"; else { print "head"; if (x1 hasnt pluralname) print "s"; print " off to"; } " ", (LeaveToDir) x2, "."; 5: print (The) x1, " "; if(x1.npc_door_passed) { print "open"; if (x1 hasnt pluralname) print "s"; print " ", (the) x1.npc_door_passed, " and "; } if (ScopeCeiling(x1) == x1.npc_target) { print "step"; if (x1 hasnt pluralname) print "s"; print " into the room from ", (ComeFromDir) x2; } else if (x1.npc_move_type == 5) print (isorare) x1, " following you"; else print (isorare) x1, " walking past you"; "."; 6: print (The) x1, " "; if (x1 has pluralname) print "try"; else print "tries"; " to open ", (the) x2, ", but it seems to be locked."; 7: "Off to ", (LeaveToDir) x2, ", you can see that ", (the) x1, " can't open a door."; default: NPC_Error(14, n); rtrue; } ##NPC_PrintVisible: switch(n) { 1: print (The) x1, " ", (isorare) x1; if (ScopeCeiling(x1) has corridor && location has corridor && x2 ~= u_obj or d_obj) print " down the hall"; else if (x2 ~= u_obj or d_obj) print " off"; print " to"; if (x2 == u_obj or d_obj) print "ward"; " ", (LeaveToDir) x2, "."; 2: print "To"; if (x2 == u_obj or d_obj) print "ward"; print " ", (LeaveToDir) x2, ", ", (the) x1, " "; rtrue; 3: print "open"; if (x1 hasnt pluralname) print "s"; print " a door and "; rtrue; 4: if (x1.npc_old_loc == Shed) print "comes out of the shed"; else { if (x2 has corridor && x1.npc_old_loc hasnt corridor && x2 ~= NPC_Visible_Room) print "enters the hallway"; else print "comes into view"; print " from ", (ComeFromDir) x1.npc_old_dir; } "."; 5: print (The) x1, " "; if (ScopeCeiling(x1) == Bottom_Of_Stairs or Top_Of_Stairs && x1.npc_old_loc ~= Stairs) print "steps onto the stairs"; else { print (isorare) x1, " "; if (x1.npc_old_dir == d_obj) print "going downstairs"; else if (x1.npc_old_dir == u_obj) print "going upstairs"; else { print "to ", (LeaveToDir) x2, ", heading "; if ((x2 == n_obj && x1.npc_old_dir == s_obj) || (x2 == ne_obj && x1.npc_old_dir == sw_obj) || (x2 == e_obj && x1.npc_old_dir == w_obj) || (x2 == se_obj && x1.npc_old_dir == nw_obj) || (x2 == s_obj && x1.npc_old_dir == n_obj) || (x2 == sw_obj && x1.npc_old_dir == ne_obj) || (x2 == w_obj && x1.npc_old_dir == e_obj) || (x2 == nw_obj && x1.npc_old_dir == se_obj) || (x2 == u_obj && x1.npc_old_dir == d_obj) || (x2 == d_obj && x1.npc_old_dir == u_obj)) print "towards you"; else print "toward ", (LeaveToDir) x1.npc_old_dir; } } "."; 6: print (The) x1, ", off to ", (LeaveToDir) x2, ", "; rtrue; 7: if (ScopeCeiling(x1) == Shed) print "darts into the shed"; else { if (ScopeCeiling(x1) ofclass Outside) print "leaves your view"; else if (ScopeCeiling(x1) hasnt corridor) print "ducks into a room"; else print "disappears from sight"; print " "; if (x1.npc_old_dir == u_obj) print "up the stairs"; else if(x1.npc_old_dir == d_obj) print "down the stairs"; else print "to ", (LeaveToDir) x1.npc_old_dir; } "."; 8: print_ret (The) x1, " ", (string) x1.npc_walkon, " from ", (ComeFromDir) x1.npc_old_dir, "."; default: NPC_Error(10, n); rtrue; } ##Follow: switch(n) { 2: "You are always following yourself."; 3: "One cannot follow ", (a) x1, "."; 4: "You are in the same place as ", (the) x1, "!"; 5: "You haven't even seen ", (the) x1, " so far."; 6: "You seem to have lost track of ", (the) x1, "."; default: NPC_Error(11, n); rtrue; } ##Find: switch(n) { 1: switch(x1) { 1: print "a few hours"; 2: print "an hour or two"; 3: print "about an hour"; 4: print "about half an hour"; 5: print "about fifteen minutes"; 6: print "less than ten minutes"; 7: print "just a minute"; default: NPC_Error(3); rtrue; } print " ago."; rtrue; 2: if (x1 == player) print "You"; else print "~", (CIOrWe) x1; print " last saw"; print " ", (itorthem) x2, " "; rtrue; 3: print " ", (CIorWe) x1, " don't know where "; if (x2 has pluralname) print "they"; else if (x2 has female) print "she"; else print "he"; print " went, though.~"; rtrue; 4: if (x1 == player) "You're the detective."; "~", (CIOrWe) x1, " don't know.~"; 5: if (x1 == player) print "You"; else print "~", (CIOrWe) x1; print " haven't seen"; print " ", (itorthem) x2, " "; if (x1 == player) "yet."; "today.~"; 7: "That question cannot be answered."; 8: "~Ahem...~"; 9: if (x1 has animate) "Are you blind?"; if (x1 has pluralname) print "They're"; else print "It's"; " right here."; default: NPC_Error(1, n); rtrue; } default: NPC_Error(2, action); rtrue; } ]; !------------------------------------------------------------------------------ [ NPC_AfterPrintVisible npc loc; if (ScopeCeiling(npc) == Stairs && loc ~= NPC_Visible_Room && loc has corridor && ~~(loc == Bottom_Of_Stairs or Stairs or Top_Of_Stairs)) "You can hear footsteps on the staircase."; rfalse; ]; !------------------------------------------------------------------------------ [ NPC_BeforeCheckVisible loc test_loc; if (loc ofclass Outside && ~~(test_loc ofclass Outside)) rtrue; if (test_loc hasnt corridor && ~~(test_loc ofclass Outside)) rtrue; if (loc hasnt corridor && ~~(loc ofclass Outside)) rtrue; if (loc == Shed || test_loc == Shed) rtrue; if (loc == Behind_The_Shed || test_loc == Behind_The_Shed) rtrue; rfalse; ]; !------------------------------------------------------------------------------ [ NPC_BeforeFollowing item; if (item == player) "You are always following yourself."; if (~~(item ofclass NPC)) "How tragic to see a formerly great detective stalking ", (a) item, "."; if (parent(item) == location or player) "You are in the same place as ", (the) item, "!"; if (ScopeCeiling(item) == 0) { print (The) item; if (item.npc_met == 0) print " isn't on"; else print " has left"; " the grounds."; } if (item.npc_met == 0) "You haven't even seen ", (the) item, " so far."; if (turns - item.npc_met > 0) "You seem to have lost track of ", (the) item, "."; if (location == Library_Balcony or Bedroom_Balcony && ~~(ScopeCeiling(item) ofclass Firstfloor)) "You can't follow ", (the) item, " from here."; rfalse; ]; !------------------------------------------------------------------------------ [ DescribeChildren npc x y; if (child(npc) == 0) rfalse; objectloop (x in npc) { if (x has concealed) give x ~workflag; else { give x workflag; y = 1; } } if (~~ y) rfalse; print (The) npc, " is holding:^"; WriteListFrom(child(npc), WORKFLAG_BIT + INDENT_BIT + NEWLINE_BIT + RECURSE_BIT); rtrue; ]; !------------------------------------------------------------------------------ [ HelloMrsRobner; if(DaemonRunning(PhoneRing)) ! If the phone's ringing right now, stop it. This would confuse the StopDaemon(PhoneRing); ! movement for Mrs. Robner if (Mrs_Robner.go_phone ~= 0) ! If Mrs. Robner is on her way to the telephone, stop this Mrs_Robner.go_phone = 0; NPC_Move(Mrs_Robner, Foyer); Mrs_Robner.npc_old_loc = Foyer; Mrs_Robner.npc_met = turns; Mrs_Robner.start_time = turns; NPC_Path(Mrs_Robner, Kitchen); print "~Hello,~ she says, ~I'm Mrs. Robner. Please come in. I'm afraid I really can't help you much. This is surely a terrible waste of time, not to mention upsetting, having all these police marching around the house. This has been a trying time, as I suppose you can understand. As I told Mr. Coates and the other detective, you may look around but you must be out by 8 o'clock at the latest. Oh, I almost forgot... Mr. Coates will be reading my husband's will at noon in the living room. You may attend if you wish.~^"; give Front_Door ~open; if (location == Front_Path) { print "Mrs. Robner leads you into the house and closes the door behind you.^^"; PlayerTo (Foyer, 0); } print"~I'm going to make myself some breakfast now. I'll be around all day if you need anything. I'll do what I can to help. Good day!~^"; return; ]; !------------------------------------------------------------------------------ [ DoorStatus door; if (door has open) print "open"; else print "closed"; rtrue; ]; !------------------------------------------------------------------------------ [ DescribePad; give Pad general; print " reveals impressions left by writing on the previous sheet. The writer must borne down heavily, but only a few words come out clearly:"; print " ^"; print " ^"; print " Baxter, ^"; print " ^"; print " st time ^"; print " nsist op merg ^"; print " mnidy Oth ^"; print " forc ^"; print " ocumen y poss ^"; print " plica y Focus s ^"; print " recons ^"; print "late! ^"; print " rsha^"; print " ^"; rtrue; ]; !------------------------------------------------------------------------------ [ HowManyAreThere obj i j; j = 0; objectloop (i in obj) if (i has animate) j++; return j; ]; !------------------------------------------------------------------------------ [ PrintWhosIn obj i; objectloop (i in obj) if (i has animate) print (name) i, " is there.^"; ]; !------------------------------------------------------------------------------ Array TapesTable table [; "Navajo night chant"; "New Orleans jazz band"; "risque russian drinking song"; "simulated rain shower"; "Wagnerian opera"; "Bulgarian shepherdess song"; ]; Array RecordsTable table [; "march by Sir Edward Elgar"; "chorus of African tribal music"; "Pretenders concert"; "bluegrass tune"; "Hebrew prayer service"; "Hungarian rhapsody"; "cacophonous electronic jumble"; ]; [ Describe_Music; if(Tapes.active ~= 0) print (string) TapesTable-->Tapes.active; else if(Records.active ~= 0) print (string) RecordsTable-->Records.active; ]; !------------------------------------------------------------------------------ Array DoYourselfTable table [; "~Do it yourself!~"; "~Why not do it yourself?~"; "~You can do that yourself.~"; ]; [ DoYourself n; if (n == 0) n = random(DoYourselfTable-->0); print_ret (string) DoYourselfTable-->n; ]; !------------------------------------------------------------------------------ [ DontFollow; if(George.npc_move_type ~= 2) ! George is just moving around { if (GeorgeNervous.follow == 0) { GeorgeNervous.follow = 1; rfalse; } GeorgeNervous.follow = 2; if(random(2) == 1) "~Please stop following me around like this. Can I have no privacy? I'm simply trying to take care of something personal.~"; "~Stop following me. My business is private.~"; } ]; !------------------------------------------------------------------------------ [ DescribeWalkOn npc r; npc.npc_met = turns; r = parent(npc); print (The) npc, " "; if(npc.npc_door_passed) print "opens ", (the) npc.npc_door_passed, " and "; else if (npc.npc_old_loc == Shed) print "comes out of the shed and "; if (r == npc.npc_target) { if(r hasnt corridor && (r ofclass Groundfloor || r ofclass Firstfloor)) print "steps into the room"; else print "stops here"; } else print "is walking past you"; "."; ]; !------------------------------------------------------------------------------ [ DescribeWalkOff npc i; npc.npc_met = turns; print (The) npc, " "; if (npc in Shed) "darts into the shed."; if(npc.npc_door_passed) print "opens ", (the) npc.npc_door_passed, " and "; if (i == u_obj or d_obj) print "is going"; else print "heads off to"; print_ret " ", (LeaveToDir) i, "."; ]; !------------------------------------------------------------------------------ [ CheckWhisper x y; if (parent(x) ~= parent(y)) rfalse; print (The) x, " looks briefly toward ", (the) y, " and then speaks in a low whisper: "; rtrue; ]; !------------------------------------------------------------------------------ [ DisturbBaxDun; Shed_Episode.count = 7; if (Shed_Episode.count < 2 || Shed_Episode.count > 5) "You seem to have walked in on some sort of get-together, although from the look on Ms. Dunbar's face, you are not the guest of honor. She is aghast, and she continually looks back and forth between Mr. Baxter and yourself."; move Ms_Dunbar to East_Lawn; "As you enter the shed, Mr. Baxter and Ms. Dunbar, who were in the midst of a quiet but heated argument, stop at once. Ms. Dunbar is quite upset and clutches Mr. Baxter. Baxter, who has retained his composure throughout, attempts to comfort Dunbar. She pushes him away and runs out of the shed."; ]; !------------------------------------------------------------------------------ Array YouJestTable table [; "You can't be serious!"; "That sounds silly to me."; "You surely jest!"; "You must be joking."; "That's completely futile."; "Don't be ridiculous!"; "That's nonsense, if you want my opinion."; ]; [ SurelyYouJest n; if (n == 0) n = random(YouJestTable-->0); print_ret (string) YouJestTable-->n; ]; !------------------------------------------------------------------------------ Array NotInterestedTable table [; "doesn't appear interested."; "lets out a loud yawn."; "seems not to care."; "seems to be getting impatient."; ]; [ NotInterested npc n; if (n == 0) n = random(NotInterestedTable-->0); print_ret (The) npc, " ", (string) NotInterestedTable-->n; ]; !------------------------------------------------------------------------------ [ DoorSmell loc a b c; objectloop(a in Compass) { b = loc.(a.door_dir); if (b && b has door && b has open) { c = b.door_to(); if (c ofclass Outside || (c == Bedroom_Balcony or Library_Balcony)) "There is a pleasant breeze coming through ", (the) b, "."; } } rfalse; ]; !------------------------------------------------------------------------------ [ DontKnowWord n j; n = n*4; print "[The "; if (n == 4) print "verb"; else print "word"; print " '"; for (j = 0: j < parse->n: j++) print (char) buffer->(parse->(n+1)+j); "' isn't in your vocabulary.]"; ]; !------------------------------------------------------------------------------ ! V E R B D E F I N I T I O N S !------------------------------------------------------------------------------ !------------------------------------------------------------------------------ Verb meta 'diagnose' * -> Diagnose; Verb meta 'bug' * -> Bug * noun -> Bug; !------------------------------------------------------------------------------ Verb 'reply' * -> MyAnswer * noun -> MyAnswer; Verb 'analyse' 'analyze' 'test' * noun -> Analyse * noun 'for' topic -> Analyse; Verb 'fingerprint' * noun -> Fingerprint; Verb 'bathe' * -> Bathe * 'in'/'on' noun -> Bathe; Verb 'hide' * -> Hide * 'on'/'behind' noun -> HideOn; Verb 'molest' 'rape' * noun -> Molest; Verb 'count' * noun -> Count; Verb 'knock' * 'at'/'on' noun -> Knock * 'down' noun -> Kill; Verb 'shade' * noun -> MyRub * noun 'with' noun -> MyRub * noun 'over'/'on' noun -> MyRub reverse; Verb 'play' * noun -> Play; Verb 'hello' 'hi' * -> Hello * noun -> Hello; Verb 'goodbye' * -> Goodbye * noun -> Goodbye; Verb 'mumble' 'sigh' * -> Sigh; Verb 'dispatch' 'strangle' 'hurt' 'injure' * noun -> Kill * noun 'with' held -> Kill; Verb 'hey' 'call' * -> Hey * noun -> Hey * 'up' scope=TopicScope -> CallUp; Verb 'ring' * scope=TopicScope -> CallUp; Verb 'flush' * noun -> Flush; Verb 'use' * noun -> Use; Verb 'accuse' * noun -> Accuse * noun 'of' topic -> AccuseOf; Verb 'arrest' * multi -> Arrest; Verb 'lean' * noun 'against' noun -> Lean; Verb 'whats' 'what^s' * 'wrong' -> WhatsWrong; Verb 't//' 'time' * -> Time; Verb 'what' 'why' 'who' 'how' * -> Why * noun -> Why * scope = TopicScope -> Why * 'about' noun -> Why * 'about' scope = TopicScope -> Why * 'is' noun -> Why * 'is' scope = TopicScope -> Why; Verb 'write' * 'with' held -> Write; Verb 'curse' * -> Mild * noun -> Curse; Verb 'bite' * noun -> Bite; Verb 'shake' * held -> Shake; Verb 'thank' 'thanks' 'thank-you' * -> Thank * noun -> Thank; Verb 'descend' * noun -> ClimbDown; #ifdef DEBUG; Verb '$$' * -> dbVerb; #endif; !------------------------------------------------------------------------------ ! V E R B E X T E N S I O N S !------------------------------------------------------------------------------ Extend only 'look' * 'in'/'inside'/'into' scope=LookInRoomScope -> LookInRoom; Extend 'climb' first * noun 'carefully'/'slowly' -> ClimbCarefully * 'up' noun 'carefully'/'slowly' -> ClimbCarefully * 'down' noun 'carefully'/'slowly' -> ClimbDownCarefully; Extend 'find' first * scope=FindScope -> Find; Extend 'turn' replace * noun -> Turn * noun noun -> Turn * 'up' noun -> TurnUp * noun 'up' -> TurnUp * 'down' noun -> TurnDown * noun 'down' -> TurnDown * noun 'on' -> TurnOn * 'on' noun -> TurnOn * noun 'off' -> TurnOff * 'off' noun -> TurnOff * 'page' 'of' noun -> Turn * noun 'to' number -> TurnTo * noun number -> TurnTo; Extend 'run' * noun 'over' noun -> RunOver; Extend 'examine' * noun 'carefully'/'slowly' -> ExamCare; Extend 'listen' replace * noun -> MyListen * 'to'/'at' noun -> MyListen; Extend only 'kill' replace * noun -> Kill * noun 'with' held -> Kill; Extend 'read' replace * noun=ReadToken -> Read * held 'against' 'light' -> LookAgainst * held 'against' 'the' 'light' -> LookAgainst * held -> Read * 'in' held -> Read; Extend 'answer' replace * -> MyAnswer * noun -> MyAnswer * scope = TopicScope 'to' creature -> Answer; Extend only 'dust' replace * noun -> Analyse * noun 'for' topic -> Analyse; Extend only 'check' replace * noun -> Analyse * noun 'for' topic -> Analyse; Extend only 'clean' replace * noun -> Clean; Extend only 'wipe' replace * 'off' noun -> Clean * noun -> Clean; Extend 'attack' replace * noun 'with' held -> Kill; Extend 'unlock' replace * noun -> MyUnlock; Extend 'rub' replace * noun -> MyRub * noun 'with' noun -> MyRub * noun 'over'/'on' noun -> MyRub reverse; Extend 'dig' * 'near'/'around' noun -> DigNear * 'next' 'to' noun -> DigNear; Extend 'climb' * 'down' noun -> ClimbDown * noun 'down' -> ClimbDown; Extend 'ask' * creature 'whats' 'wrong' -> AskWhatsWrong * creature 'what^s' 'wrong' -> AskWhatsWrong; Extend 'tell' * creature 'whats' 'wrong' -> TellWhatsWrong * creature 'what^s' 'wrong' -> TellWhatsWrong; Extend 'ask' * creature 'for' scope=AskForScope -> AskFor; Extend 'eat' replace * 'meal'/'breakfast'/'supper'/'lunch' -> EatMeal * noun -> Eat; Extend 'ask' first * creature 'about' scope = TopicScope -> Ask; Extend 'tell' first * creature 'about' scope = TopicScope -> Tell; Extend 'examine' first * 'room' -> ExamineRoom * 'room' 'carefully'/'slowly' -> ExamineRoom; Extend 'search' * noun 'for' scope = SearchForScope -> SearchFor * 'room' -> ExamineRoom; Extend 'look' replace * -> Look * 'at' noun -> Examine * 'inside'/'in'/'into'/'behind' noun -> Search * 'under' noun -> LookUnder * 'through' noun -> LookThrough * 'up' topic 'in' noun -> Consult * 'at' noun 'against' 'light' -> LookAgainst * 'at' noun 'against' 'the' 'light' -> LookAgainst * 'out' 'of' noun -> LookThrough; Extend 'l//' replace * -> Look * 'at' noun -> Examine * 'inside'/'in'/'into'/'behind' noun -> Search * 'under' noun -> LookUnder * 'through' noun -> LookThrough * 'up' topic 'in' noun -> Consult * 'at' noun 'against' 'light' -> LookAgainst * 'at' noun 'against' 'the' 'light' -> LookAgainst * 'out' 'of' noun -> LookThrough; Extend only 'break' 'destroy' 'smash' 'wreck' 'crack' replace * noun -> Break * noun 'with' noun -> Break; Extend 'swim' replace * -> Bathe * 'in'/'on' noun -> Bathe; Extend 'find' * scope = TopicScope -> Find * 'is'/'are' scope = TopicScope -> Find; !------------------------------------------------------------------------------ ! S Y N O N Y M S !------------------------------------------------------------------------------ Verb 'apologise' 'apologize' = 'sorry'; Verb 'kindle' 'ignite' 'inflame' 'illuminate' 'char' 'combust' 'incinerate' 'scorch' = 'light'; Verb 'aye' 'ok' 'okay' 'positive' 'positively' 'sure' 'yup' 'yep' = 'yes'; Verb 'naw' 'nay' 'negative' 'nope' 'never' = 'no'; Verb 'browse' 'leaf' 'skim' = 'read'; Verb 'crumble' 'damage' 'demolish' 'erase' 'trash' 'assault' 'slay' 'stab' 'vanquish' 'wound'= 'break'; Verb 'leap' 'vault' 'burdle' 'bound' = 'jump'; Verb 'loiter' = 'wait'; Verb 'tug' 'yank' = 'pull'; Verb 'smooch' = 'kiss'; Verb 'stash' 'stuff' = 'insert'; Verb 'talk' 'utter' = 'say'; Verb 'catch' 'confiscate' 'grab' 'keep' 'seize' 'snatch' 'steal' = 'take'; Verb 'dislocate' 'roll' 'nudge' 'shove' 'thrust' = 'move'; Verb 'lick' = 'taste'; Verb 'pound' 'rap' = 'knock'; Verb 'strip' 'undress' = 'disrobe'; Verb 'crouch' 'settle' 'squat' = 'sit'; Verb 'gaze' 'peek' 'peer' 'stare' = 'look'; Verb 'dump' = 'drop'; Verb 'bestow' 'deliver' 'donate' 'hand' = 'offer'; Verb 'slap' 'strike' 'swat' 'whap' 'kick' = 'hit'; Verb '$ver' '$verify' = 'verify'; Verb '$version' '$v' '$id' = 'version'; Verb 'whiff' = 'smell'; Verb 'retort' = 'answer'; Verb 'rest' 'snooze' = 'sleep'; Verb 'guzzle' 'imbibe' 'quaff' 'swill' = 'drink'; Verb 'rouse' = 'wake'; Verb 'toggle' 'flip' = 'turn'; Verb 'slam' = 'shut'; Verb 'study' 'survey' = 'examine'; Verb 'consume' 'devour' 'gobble' 'ingest' 'nibble' = 'eat'; Verb 'crush' 'squish' 'crumple' = 'squeeze'; Verb 'interrogate' 'query' 'question' 'quiz' = 'ask'; Verb 'crawl' 'advance' 'hike' 'jog' 'proceed' 'saunter' 'step' 'stroll' 'tramp' 'trudge' 'flee' 'escape' = 'walk'; Verb 'cleave' 'gash' 'lacerate' 'saw' 'severe' 'slash' 'split' = 'cut'; Verb 'excavate' = 'dig'; Verb 'howl' 'scream' 'yell' = 'shout'; Verb 'brush' 'dry' 'wash' = 'clean'; Verb 'scram' 'depart' = 'exit'; Verb 'dress' = 'wear'; Verb 'inspect' = 'examine'; !------------------------------------------------------------------------------ ! I N I T I A L I S E !------------------------------------------------------------------------------ [ Initialise; ! Set the player player = Detective; ! Set the location to the South Lawn, where the game begins location = South_Lawn; #IFNDEF NOHINTS; ! We provide a menu with InvisiClues and have to say how it's called. hint_menu = InvisiClue; #ENDIF; ! Set the time to 8:00am (that is, 480 minutes since midnight) SetTime (480, 1); ! Set the end of the game to 8:00pm (that is, 719 minutes to play) StartTimer (TimeUp, 719); ! We don't want the player to be transparent give player ~transparent; ! Initialise the npc engine NPC_Initialise(); ! Plan first movements of some NPCs NPC_Schedule(Mr_McNabb, East_Lawn, 100+random(5)); NPC_Schedule(George, Kitchen, 30+random(15)); NPC_Schedule(Ms_Dunbar, Dunbar_Bathroom, 50+random(20)); NPC_Schedule(Mrs_Rourke, Dining_Room, 120+random(20)); ! Start a timer for the phone to ring StartTimer (PhoneRing, 61+random(10)); ! Start a timer for the mailman to come StartTimer (Mailman, 60+random(40)); ! Start a timer for the paperboy to come StartTimer (Paperboy, 160+random(30)); ! Start a timer for Baxter to arrive StartTimer(BaxterArrival, 100+random(20)); ! Start a timer for Coates to arrive StartTimer(CoatesArrival, 225+random(5)); ! Timer for McNabb finding the holes StartTimer(FindHoles, 190+random(30)); move Ticket_Stub to Ms_Dunbar; give Ticket_Stub concealed; move Holes to Mr_McNabb; give Holes concealed; "^"; ]; #ifndef NOHINTS; Include "invisi.h"; #endif; !------------------------------------------------------------------------------ ! E N D O F F I L E !------------------------------------------------------------------------------