!% -S !% -d2e !% +/Users/joelh/IF/Inform/Lib/Base,/Users/joelh/IF/Inform/Lib/Contrib !% $MAX_PROP_TABLE_SIZE=25000 !% $MAX_OBJECTS=700 !% -v8 !% -r ! -DkXv8 ! $Id: Flibnaub.inf,v 1.22 2005/03/14 02:35:37 joelh Exp $ ! This needs to go before the abbrevs so it's available there, but we ! put the actual CvsId after it. Include ">abbrevs"; Constant Story "Flat Feet"; Constant Headline "^A Farcical Interactive Mystery^"; Release 1; Constant TASKS_PROVIDED; ! Note that we only use tasks, not scored objects and rooms, so that ! everything is printed in the FULL command. ("Sundry items" is only ! good for Zork.) Constant NUMBER_TASKS = 17; Constant MAX_SCORE = 35; Array task_scores -> 2 1 2 ! Car 3 3 ! Cliff House 1 2 1 3 ! Curator 1 1 1 1 1 3 ! Alcatraz 4 5; ! Sausalito [ PrintTaskName num; switch (num) { ! These are arranged in chronological order. During forks, ! it's order of difficulty. The first group is worth 5 ! points total, the next is worth 6, etc. Clues are always ! worth 3 points. I spread the points around more than most ! games to give the players a feeling of accomplishment, since ! this game doesn't have much to lead you around. 0: "freeing the tire"; 1: "fixing your car"; 2: "getting a case"; 3: "getting past the waitress at the Cliff House"; 4: "finding the photograph clue"; 5: "talking to the curator"; 6: "learning to fly"; 7: "meeting the curator at the top of the Pyramid"; 8: "getting the calling card clue"; 9: "getting onto Pier 39"; 10: "creating a bird"; 11: "getting a worm"; 12: "getting a fish"; 13: "getting tickets to Alcatraz"; 14: "finding the map scrap clue"; 15: "getting onto the helicopter"; 16: "capturing Carla Sanantonio"; } ]; Replace MakeMatch; Replace Identical; Replace NounDomain; Replace TryGivenObject; Replace DoMenu; !Needed by domenu.h Replace LowKey_Menu; !Needed by domenu.h Constant DIALECT_US = 1; Include "Parser"; Include "pname"; Include "smartcantgo"; Include "VerbLib"; !======================================================================= ! Classes ! Class CvsId was defined above, but we put the rest of the handlers ! here. Class CvsId; CvsId "$Id: Flibnaub.inf,v 1.22 2005/03/14 02:35:37 joelh Exp $"; [ PrintCvsIds obj; objectloop (obj ofclass CvsId) print (object)obj, "^"; ]; Class Room with description "UNDER CONSTRUCTION", name 'here', cant_go [; SmartCantGo(); ], before [; Examine, Search: if (noun == self) << Look >>; ], has light; [ InScope; ! Let the player refer to 'here', for 'dig here', 'ask ralph about ! here', etc. if (scope_reason == PARSING_REASON or TALKING_REASON or REACT_BEFORE_REASON or REACT_AFTER_REASON) PlaceInScope(location); rfalse; ]; ! See car.inf for a description of Street and its purpose. Class Street class Room with ask_in_scope 1, each_turn [; ! Move the car here, if it isn't already. ! ! I can't put this on the car, since each_turn only runs ! on things in scope. I also can't make this a found_in, ! since that removes objects that aren't found_in ! location, and the car should remember where it was last ! (because our heroes sure can't). You're not allowed to ! move anything that's in scope, but the docs don't say ! anything's wrong with moving something into scope. If ! that's a problem, change this to a daemon on the car or ! something. if (parent(car) == self) return; print "^"; move car to self; if (TestScope(ralph, player)) print "~Say, Jacques, how are we going to going to get our car back?~^~Wait for it, Ralph.~^^"; if (car.seen_bruce) "From out of the sky, the car falls to the ground and lands on the street with a loud THUNK. Some parts may have fallen off; you quit keeping track some time ago."; car.seen_bruce = true; "A strange man falls from the sky, and it looks like he's holding a chainsaw. ~Zombies, zombies!~ he cries, and runs off into the distance.^A moment later, your car-- or one similar enough that you don't care-- falls onto the street next to you."; ], before [dest; Go: dest = self.(noun.door_dir); if (dest == nothing) return false; if (~~(dest ofclass Street)) return false; if (parent(actor) == car) return false; if (IndirectlyContains(self,actor) ! should always be true && car in self) { print (The)actor; move actor to car; if (actor == player) { move ralph to car; print " and Ralph"; } print " dive into the car.^"; return false; } "It's too far to walk; you'll have to enter the car first."; ]; Class Firearm with name 'weapon' 'firearm', before [; Receive: "The manufacturer clearly said to only use approved ammunition."; ], has container open; !======================================================================= ! Includes Include ">Sausalito"; Include ">SF_CliffHouse"; Include ">SF_GGP"; Include ">SF_Pier39"; Include ">SF_financial"; Include ">Peninsula"; Include ">PaloAlto"; Include ">Sunnyvale"; Include ">SantaCruz"; Include ">Monterey"; Include ">Sky"; ! Put Ralph before the car, so that he'll be around when the car falls ! onto the street for the dialogue. Include ">Ralph"; Include ">car"; Include ">menus"; !======================================================================= ! Objects Firearm gun "gun" with name 'gun' 'pistol' 'barrel' 'sight' 'sights', description "Your trusty .44 Automag. The stainless .44 AMP barrel sends a 240-grain bullet at just over 1500 fps. You checked the sights just last week, and your years of mindless violence have given you the ability to put round after round into even the most helpless fleeing perpetrator. The gun is currently empty.", before [; Smell: "The fresh oil has an invigorating odor."; Receive: "That might damage the precision-machined action of your favorite weapon."; ]; Object hat "hat" with name 'hat' 'hatband' 'fedora', description "This brown fedora has a standard black hatband. It was on sale from PIs-R-Us. The hat's a bit large for you, but it's the best you've got.", stunned false, before [; LookUnder: if (hat in player && hat has worn) "You find your head."; ], after [; Drop: if (location == office) { if (self.stunned) { "Your hat, still stunned, rests quietly."; } else { ! Scott asked if this means the hat is animate, ! and should therefore the "You can only do that ! to something animate" messages were bogus. self.stunned = true; "Your hat makes a fast break for the exit, but hits the desk on the way out and lies on the ground, stunned."; } } rfalse; ], has clothing container worn open; #IfDef NotDef; ! Used to test parser disambiguation Object redhat "red hat" with pname 'red' '.x' 'hat', has clothing worn; #EndIf; Object coat "coat" with name 'coat' 'trench' 'trenchcoat' 'heirloom', description "The tan trenchcoat is standard PI issue, and was handed down to you from your uncle. The buttons were all broken off during the Case of the Frumious Bandersnatch, but you couldn't bear to part with the heirloom.", has clothing container worn open; !======================================================================= ! Procedures [ Initialise; #Ifdef DEBUG; pname_verify(); ! suggested by pname.h print "^"; PrintCvsIds(); print "^"; #Endif; ! Set up the player location = office; move gun to player; move hat to player; move coat to player; move car to sunnyvale; player.description = "Your feline physique stands 5'8~ tall, with black fur and white socks. The years of your traditional PI diet have left you somewhat more wide around the middle than you were in your svelte youth, but you've kept your strength up by lifting deadweights-- usually Ralph."; "^^Guns fire and tires squeal not three feet from your nose. The robbers are getting away! Suddenly, they fly up towards the ceiling... again and again and again... ^^~Drats, Ralph! The vertical hold's gone again!~ ^^Your ferret buddy leaps behind you and peeks over your shoulder. ~No problem, Jacques. Just turn the color to green and pretend they're aliens going to the mothership!~ ^^~It's a black and white TV, Ralph.~ ^^~Why do we care? We're both color-blind.~ ^^~Good point. Aliens it is!~ ^^~Why don't we replace the TV?~ ^^~We can't afford it. We haven't had a case in weeks. I'm getting tired of eating cat food!~ ^^~You're a cat, Jacques.~ ^^~So?~ ^^~By gum, you're right! Aliens it is.~ ^^~Oh, we can't, the vertical hold is back.~ ^^Ralph grabs the TV and throws it out the window. ~No vertical hold anymore.~ ^^~What a stunning idea!~^"; ]; [ DeathMessage; switch (deadflag) { 3: print "You have let the villain escape"; } ]; [ ChooseObjects obj code; if (code == 2) ! Default in the library is 2 return 2; if (obj == ralph) return 2; return 0; ]; !======================================================================= ! Grammar Include "Grammar"; ! I got used to "LOOK COAT" when playing Scott Adams games as a ! synonym for examine. Inform uses the preposition to distinguish ! between examine and search (as well as lookunder, etc) but I'm more ! cavalier in my attitude. Extend 'look' * noun -> Examine; ! Dialogue is important in this game, so add this so that "TALK TO RALPH" ! tells you what to do. Verb meta 'talk' * talkable -> Talk * creature -> Talk * 'to' talkable -> Talk * 'to' creature -> Talk * 'about' topic -> Talk ! This last one is a catch-all, so the others are redundant, but I ! may use them some other time. * topic -> Talk; [TalkSub; "To speak with characters in this game, you can use phrases such as ASK RALPH ABOUT DESK (to learn information) or RALPH, DROP THE DESK (to give commands)."; ]; ! For the blanket [is_blanket; return (noun ofclass Blanket_C); ]; Extend 'take' * noun=is_blanket 'from'/'off' noun -> Remove * noun=is_blanket 'off' 'of' noun -> Remove; Extend 'remove' * noun=is_blanket 'from'/'off'/'of' noun -> Remove * noun=is_blanket 'off' 'of' noun -> Remove; Extend only 'cover' * 'up'/'over' noun 'with' noun=is_blanket -> PutOn reverse * noun 'with' noun=is_blanket -> PutOn reverse; Extend 'put' * noun=is_blanket 'over' noun -> PutOn * noun 'under'/'in' noun=is_blanket -> PutOn reverse; ! For the phone; note that the order of NOUN and SECOND are a bit ! different so I can easily use BEFORE. Verb 'call' * number -> Call reverse * number 'on'/'with'/'using' noun -> Call reverse * creature -> Talk * 'for' creature -> Talk * 'on' noun -> Call * topic 'on'/'with'/'using' noun -> Call reverse * topic -> Call reverse; [CallSub; ! Odd... "CALL 911" passes the number in as noun. if (noun == nothing || second == nothing) "What do you want to call on?"; "There doesn't seem to be any immediately obvious way to do that."; ]; ! Also for the phone (mostly) Verb 'dial' * noun -> Turn * number -> Call reverse * number 'on'/'with'/'using' noun -> Call reverse * topic 'on' noun -> Call * noun 'to' special -> SetTo * noun 'on' -> Switchon * noun 'off' -> Switchoff; ! To pick up Ralph Verb 'lift' 'hoist' 'elevate' * noun -> Take * noun 'up' -> Take * 'up' noun -> Take; ! Let Ralph respond to anything in the game that we've seen, and make ! it easier for us to associate his responses with objects, not ! just words. Extend 'ask' first * creature 'about' noun -> Ask * creature 'about' scope=all_ask_in_scope -> Ask; Extend 'tell' first * creature 'about' noun -> Tell * creature 'about' scope=all_ask_in_scope -> Tell; Extend only 'consult' first * creature 'about' noun -> Ask * creature 'about' scope=all_ask_in_scope -> Ask; ! For toilet Verb 'flush' * noun -> Flush; [FlushSub; "I'm not really sure how to do that to ", (the)noun; ]; ! For arcade games Verb 'play' * noun -> SwitchOn * 'with' noun -> SwitchOn; Verb 'use' * switchable -> SwitchOn * noun -> Use * noun 'on'/'with' noun -> Use; [UseSub; "You'll need to be more specific than 'use'."; ]; ! For getting the fish Verb 'catch' 'grab' * noun -> Take * noun 'from'/'off'/'out'/'of' -> Remove * multiexcept 'in'/'into'/'with' noun -> Insert; ! For the "swyche" in the mechanical museum Verb 'turne' = 'turn'; ! For the feather Verb 'dry' * noun -> Dry * 'off' noun -> Dry; [ DrySub; L__M(##Rub, 1, noun); ]; ! Why does 'dig' require an object? We make 'dig' default to down. Extend 'dig' first * -> DigDown * 'with' held -> DigDown; [ DigDownSub; << Dig d_obj noun >>; ]; ! Tie was always pretty lame, which is understandable since rope is a ! pain in the butt. Fortunately, it's only in the game briefly. Extend 'tie' * noun 'with' noun -> Tie reverse * 'up' noun -> Tie * 'up' noun 'with' noun -> Tie reverse; ! And untie isn't around at all. Verb 'untie' 'detach' 'unfasten' * noun -> Untie; [ UntieSub; if (ObjectIsUntouchable(noun)) return; "There isn't any immediately obvious way to do that."; ]; ! The player will do whatever they can with the gun (let them try! ! bwahaha) so give them some verbage to play with. Verb 'load' * -> Restore * noun 'with' multiexcept -> Insert reverse * multiexcept 'in'/'inside'/'into' noun -> Insert; Verb 'unload' * noun -> Empty * multiinside 'from' noun -> Remove; Verb 'fire' 'shoot' * -> FireAt * noun -> FireAt * 'at' noun -> FireAt * 'at' noun 'with' held -> FireAt * noun 'with' held -> FireAt * held 'at' noun -> FireAt reverse; Extend 'attack' * noun 'with' held -> FireAt; [ FireAtSub obj; if (ObjectIsUntouchable(noun)) return; if (second == ralph) << ThrowAt ralph noun >>; ! FIXME-4 This is to handle "shoot gun", but it also unfortunately ! handles "shoot at gun". if (noun == nothing || (noun ofclass Firearm && second == nothing)) "What, just fire off a round at random?"; if (second == nothing) { ! We could go over everything in scope, but we don't want to ! pick up something implictly on a guess. objectloop (obj in player) if (obj ofclass Firearm) { print "(with ", (the) obj, ")^"; << FireAt noun obj >>; } "With what?"; } if (~~(second ofclass Firearm)) { "Using some sort of firearm might be more appropriate, and certainly would be more fun."; } if (second has container && child(second) == nothing) { "It's not loaded."; } if (AfterRoutines()) rtrue; "Inasmuch as gratuitous violence is fun and exciting, there has to be a better way."; ]; ! FIXME-4 Make about and credits go to the appropriate menus if it's ! easy. Verb meta 'help' 'hint' 'about' 'credits' 'menu' * -> Help; [ HelpSub; main_menu.select(); ]; Verb meta 'exits' * -> Exits; [ ExitsSub; if (location provides cant_go) location.cant_go(); else SmartCantGo(); ]; Verb meta 'winning' 'winnable' * -> Winning; [ WinningSub; if (location == pacific_sky && (pacific_sky.dist_out + pacific_sky.comfort > 7)) "Your perilous flight will surely be lost over the sea."; if (sausalito has visited) { if (calling_card.place == nothing || photograph hasnt moved) "You have come to Sausalito on a wild goose chase, and the goose is lauging at you."; if (calling_card.place.u_to ~= mezzanine && ~~IndirectlyContains(player,photograph) && ~~IndirectlyContains(ralph,photograph)) "You seem to have forgotten something you would need to find the perp."; if (map_scrap hasnt moved) "You have overreached your bounds, and cannot complete your mission"; } print "Your mission is still viable.^"; rfalse; ]; Verb meta 'xyzzy' * -> Xyzzy; [ XyzzySub; print "A hollow voice says: "; if (~~(WinningSub())) return; print "Let's see if we can do something about that...^"; if (location == pacific_sky) { pacific_sky.dist_out = 0; pacific_sky.dist_north = 1; pacific_sky.comfort = 0; PlayerTo(over_santa_cruz); return; } if (sausalito has visited && roof hasnt visited) { give sausalito ~visited; PlayerTo(bridge); return; } "Nope, you're in too much trouble now."; ]; Verb meta 'ident' * -> Ident; [ IdentSub; < Version >; PrintCvsIds(); rtrue; ];