Switches xv8; Release 6; Constant AMUSING_PROVIDED; Constant AMUSING_WORD 'afterword'; Constant NO_PLACES; Constant INITIAL_DAEMONS; Constant DEATH_MENTION_UNDO; Constant ALLOW_INTERRUPT_MULTI; Constant ALLOW_HIDDEN_GENDER; Constant SKIP_DEXTERITY_CHECK; Constant ALTER_AMBIG_BEHAVIOR; !Constant ZDEBUG; !Constant SKIP_NONE; #ifdef ZDEBUG; #ifndef SKIP_NONE; Constant SKIP_THEATER; !Constant SKIP_NOVEMBER; Constant SKIP_SILENT; Constant SKIP_DRY; Constant SKIP_DARK; Constant SKIP_FROZEN; Constant SKIP_DOME; Constant SKIP_CLAUSTRO; Constant SKIP_MEANING; Constant SKIP_FORM; #endif; #endif; Constant Story "SO FAR"; Constant Headline "^An Interactive Catharsis^\ Copyright 1996 by Andrew Plotkin.^\ (First-time players should type ~about~.)^"; Replace DrawStatusLine; Replace ScoreSub; Replace InvWideSub; Replace StrongSub; Replace MildSub; Replace PronounsSub; Replace FullScoreSub; Replace BurnSub; Replace SmellSub; Replace ListenSub; Replace FillSub; Replace SingSub; Replace SwimSub; Replace WaveHandsSub; Include "Parser"; Attribute general2; ! used for various things, but no global meaning. Attribute outdoors; ! if set, the room is outdoors, and the sky is visible. Attribute winter; ! if set, the room is cold. should only be set for rooms. Property door_world; Fake_Action Ignite; Fake_Action AddFluid; Fake_Action ReceiveBehind; Constant world_None 0; Constant world_Home 1; Constant world_November 2; Constant world_Silent 3; Constant world_Dry 4; Constant world_Frozen 5; Constant world_Dome 6; Constant world_Dark 7; Constant world_Claustro 8; Constant world_Meaning 9; Constant world_Form 10; Global world = world_None; ! which are we in? Array WorldsVisitedList --> 11; ! 0..10, although 0 is unused Global WorldsVisited = 0; Global weather = 0; ! string Global statusprinting = 0; ! will be 1 if the library is printing in the status line Constant CantGoThatWay "You can't go that way."; Object LibraryMessages "lib_messages" with before [; Attack: "Such force seems unnecessary."; Go: if (lm_n == 5) { print "You can't; ", (the) lm_o, " isn't open.^"; rtrue; } Drop: if (lm_n == 1) "You haven't got that."; Miscellany: if (lm_n==5) { print "^Would you like to RESTART, RESTORE a saved game"; #IFDEF DEATH_MENTION_UNDO; if (undo_flag~=0 && deadflag~=2) ! --Z print ", UNDO your last move"; #ENDIF; if (TASKS_PROVIDED==0) print ", give the FULL score for that game"; if (deadflag==2 && AMUSING_PROVIDED==0) print ", see the AFTERWORD"; ", or QUIT?"; } if (lm_n == 9) { print "^It is now pitch dark."; if (world == world_Dark) { print " For a moment you are lost in pressing silence. \ Then sounds emerge, tentatively, all around you.^^"; ; } else { new_line; } rtrue; } Examine: if (lm_n == 1) "You can't see."; Drink: "That's plainly unpotable."; LMode1: " is now in its ~brief~ printing mode, which gives \ long descriptions of places the first time you visit, and short \ descriptions when you return."; LMode2: " is now in its normal ~verbose~ mode, which always gives long \ descriptions of locations (even if you've been there before)."; ]; Include "VerbLib"; ! ------------- Objects #ifdef ZDEBUG; Object wand "magic wand", with name "magic" "wand", description "It's your magic wand! [BUG]", before [; Wave: if (self hasnt light) { give self light; "The wand starts to glow."; } else { give self ~light; "The wand goes out."; } ]; #endif; ! ZDEBUG Object sky "sky" with name "sky" "weather" "sun" "moon" "moons" "amwal" "warel", found_in [; if (location has outdoors) rtrue; else rfalse; ], description [; switch (world) { world_Home: print "You lean out of the shade and look up. \ The sun scorches you from one side of a metal-blue sky."; world_November: print "The sky is a deep untouched blue, shaded with violet. The sun \ is low in the west."; world_Silent: print "Scraps of cloud drift along soft clear blue. The sun is low."; world_Dry: print "The sky is so wide as to seem flat, a plane of pure blue \ parallel with the grass. The sun nears the western horizon."; world_Frozen: print "The sky is a bowl of harsh bright blue, unforgiving and as cold \ as the ice here below."; switch (location) { FroCliffBottom: print " Beams of dark and light seem to radiate from the west, \ etched from the sunlight which slices across the ragged \ cliff-top above."; FroCliffShadow: print " Beams of dark and light seem to radiate from the west, \ etched from the sunlight which slices across the ragged \ cliff-top to the west."; FroOnSlope: print " Beams of dark and light seem to radiate from the west, \ etched from the sunlight which slices across the \ ridge-crest."; default: print " The sun is low in the west."; } world_Dome: print "The sun is a tiny glaring spot, low in the west, but the sky is \ dark and thick with stars."; default: "There's nothing up there but unpainted graphics. [BUG]"; } !print " [DEBUG] visited = ", WorldsVisited, "."; switch (WorldsVisited) { 1: ! Home print " The moons are also visible. Warel is already high; Amwal is just \ rising, but she will soon be catching up, approaching tonight's lunar event."; 2: ! first time in Nov print " The moons are also visible; Warel is high, Amwal a bit above the horizon."; 3: ! first time in either Frozen or Silent print " The moons are also visible; Warel is high, Amwal well above the horizon."; 4: print " The moons are also visible. Warel is close to the zenith; Amwal in the \ middle sky, to the east."; 5: print " The moons are also visible. Amwal is high; Warel nearly at zenith."; 6: ! first time in Dome print " The moon Warel is nearly at zenith; Amwal is a little lower, to the east."; 7: ! second time in Dome, and through the nonsky worlds to bottom. print " Both moons are approaching the zenith, and each other."; ! 8: Dark (if sequence is correct) (could be as little as 4 if wrong) ! 9: Claustro (if sequence is correct) (could be as little as 5 if wrong) default: print " The moons are swinging loose. [BUG]"; } new_line; rtrue; ], before [; Smell: <>; ! smell nothing -- ie, air. ], react_before [; ! I'm a little scared about this, but it seems to work. Examine: if (noun == u_obj) <>; ], number 0, ! your temperature. daemon [ oldnum curnum str; ! temperature maintainer -- always on. oldnum = self.number; if (location has winter) { if (world ~= world_Frozen) { print "^Elves are sunbathing here. [BUG]^"; } if (blanket has worn && blanket in player) { if (location == FroCliffTop) { self.number = self.number - 15; str = "^The gale tears at your blanket. "; } else { if (frowind in location) { self.number = self.number - 10; str = "^Your blanket only blunts the icy wind. "; } else { self.number = self.number - 5; str = "^The quiet chill still seeps through your blanket. "; } } } else { if (location == FroCliffTop) { self.number = self.number - 50; } else { self.number = self.number - 35; } str = "^"; } oldnum = safe_div(oldnum, 100); curnum = safe_div(self.number, 100); if (curnum < oldnum) { frowind.number = 0; ! suppress wind's each_turn switch (curnum) { -1: print (string) str, "You are shivering violently.^"; -2: print (string) str, "Your hands and feet are becoming numb.^"; -3: print (string) str, "The cold is a vague ache through your blood, and \ it is hard to move.^"; -4: print (string) str, "The world seems to crawl, sluggishly. You cannot muster the \ energy to shiver any more.^"; -5: deadflag = 1; ! just return "^The world dims and swirls. You must have fallen, for the snow \ is supporting your body, but it's too cold to hurt anymore."; } } } else { if (world == world_Frozen) { print "^Elves are snowboarding here. [BUG]^"; } if (self.number < 0) { if (blanket has worn && blanket in player) { self.number = self.number + 100; } else { self.number = self.number + 50; } } else { if (blanket has worn && blanket in player) { self.number = self.number + 25; } else { self.number = 0; } } oldnum = safe_div(oldnum, 100); curnum = safe_div(self.number, 100); if (curnum > oldnum) { switch (curnum) { -3: print "^Your hands and feet are prickling, painfully alive.^"; -1: print "^The chill is fading from your blood.^"; 2: print "^You're unpleasantly warm, muffled in that \ blanket.^"; self.number = 100; } } } if (parent(snow) ~= nothing) { MaintainSnowPhase(); } if (parent(icelump) ~= nothing) { MaintainIcePhase(); } if (jarwater in jar) { MaintainWaterPhase(); } ], has scenery; Object ears "your ears" with name "your" "my" "ear" "ears", description "Your ears are, fortunately, not within your field of view.", before [; Take, Close: if (world == world_Dark && location == thedark) "The sounds around you are barely diminished; you give up."; "This is unlikely to improve matters."; Listen: "Someone is confused."; Pull, Push: "They're attached."; Search, Rub: "Your ears are relatively clean."; Taste, Eat: print_ret "You should ", (emphstring) "be", " so lucky."; Receive: "Your parents warned you against this sort of behavior."; PutOn: <>; ], has proper; Object tongue "your tongue" with name "your" "my" "tongue", description [; if (self has general) "It'th a pink bwuw connecthing your thathe t'o the pole."; "Your tongue is not limber enough to manage this. If it were, well, mmm, never \ mind."; ], before [; Take: if (verb_word == 'hold') rtrue; ! heh heh if (self has general) "It'th thtuck."; "Any number of feeble jokes about cats come to mind."; Drop: if (self has general) "You wi'th."; "It's, well, attached."; Pull: if (self has general) "Owwww!^^No goodh."; "That would look astonishingly stupid."; Eat: ! bite, really "Oww!"; Attack: "Oww!"; Taste: if (self has general) "Yeah, wighth."; "By definition, you taste nothing unexpected."; Empty, EmptyT: "Your tongue can't contain things."; Untie: if (self has general) "You can'th!"; "You've never been tongue-tied."; Tie: "There's no need to get tongue-tied."; Search: <>; PutOn, Insert: <>; Receive: <>; ], has proper supporter; ! general mean'h it'h thtuck to a pole. Object newplay "yourself" with description "Just you, as usual.", number thedark, capacity 100, ! add_to_scope tongue ears, ! handled by InScope() has concealed animate proper transparent; Class shadowclass with name "dark" "darkness" "black" "blackness" "shadow" "shade", door_to theaterbench, ! this is safe; the door_to property is available for ~doors. door_world world_Home, before [; Touch: "You reach into the shadow, and in, in, and the farther you stretch the \ farther there is to go -- you pull back, shivering."; Search: <>; LookBehind: "You can't even see what's in the shadow."; Receive: ! this test is duplicated in _dark.inf, Object darkshadow if (noun == jarwater || noun == jaroil) { remove noun; rtrue; } move noun to self.door_to; rtrue; Enter: MoveToWorld(self.door_world); PlayerTo(self.door_to, 0); ! full look rtrue; ], has scenery container; Include "sofar_home.inf"; Include "sofar_nov.inf"; Include "sofar_silent.inf"; Include "sofar_dry.inf"; Include "sofar_froze.inf"; Include "sofar_dome.inf"; Include "sofar_dark.inf"; Include "sofar_claus.inf"; Include "sofar_meaning.inf"; Include "sofar_form.inf"; ! ------------- Verbs and helper routines ! see manual p.98 [ ChooseObjects obj code; if (code < 2) { if (obj has scenery) return 2; rfalse; } if (obj hasnt scenery) { if (obj == tricklewater or trickleoil) { !print "[DEBUG] Choose: ", (the) obj, " is a trickle: 1.^"; return 1; } !print "[DEBUG] Choose: ", (the) obj, " hasnt scenery: 2.^"; return 2; } else { !print "[DEBUG] Choose: ", (the) obj, " has scenery: 1.^"; return 1; } ]; [ InScope person; if (person == player) { PlaceInScope(ears); PlaceInScope(tongue); } rfalse; ]; [ PronounsSub; print "At the moment, ~it~ "; SayProS(itobj); print ", ~him~ "; SayProS(himobj); print " and"; print " ~her~ "; SayProS(herobj); "."; ]; [ ParserError errnum; switch (errnum) { SCENERY_PE: "That's not important here."; default: rfalse; } ]; [ PauseClear dummy; print "[Hit any key.] "; new_line; ! new_line; @read_char 1 dummy; @erase_window $ffff; new_line; ]; ! find num/denom, rounded towards zero. Works even if num is negative. [ safe_div num denom; if (num < 0) return -((-num) / denom); return num / denom; ]; ! find the outermost object that contains obj (generally a room, but if obj is in ! nothing, it will be returned itself.) [ locationof obj; if (parent(obj) == nothing) return obj; while (parent(obj) ~= nothing) { obj = parent(obj); } return obj; ]; ! returns TRUE if obj1 is anywhere inside (but not identical to) obj2 [ anywherein obj1 obj2; if (parent(obj1) == nothing) rfalse; while (parent(obj1) ~= nothing) { obj1 = parent(obj1); if (obj1 == obj2) rtrue; } rfalse; ]; [ emphstring str; style underline; print (string) str; style roman; ]; Global latchset = 0; Global latchstring = 0; ! If setnow is nonzero, set latchstring to str. ! Otherwise, if this is the first call since the setting, print str; else print latchstring. [ latch str setnow; if (setnow ~= 0) { latchstring = str; latchset = 0; } else { if (latchset == 0) { latchset = 1; if (str ~= 0) print (string) str; } else { if (latchstring ~= 0) print (string) latchstring; } } ]; ! If latch was ever called, print str2; else str1. [ unlatch str1 str2 str; if (latchset == 0) str = str1; else str = str2; if (str ~= 0) print (string) str; ]; [ DrawStatusLine width posa i; @split_window 1; @set_window 1; @set_cursor 1 1; style reverse; statusprinting = 1; width = 0->33; spaces (width); ! A pox upon buggy interpreters! @set_cursor 1 2; PrintShortName(location); i = parent(player); if (i ~= location && location ~= thedark) { if (i has supporter) { print ", on "; } else { print ", in "; } DefArt(i); } if (weather ~= 0) { posa = width-31; if (posa >= 34) { @set_cursor 1 posa; } print " (", (string) weather, ")"; } statusprinting = 0; @set_cursor 1 1; style roman; @set_window 0; ]; [ DeathMessage; switch (deadflag) { 3: print "You go home"; 4: print "You are beyond the scope of this story"; 5: print "All is loosed and undone"; } ]; [ MoveToWorld neww; if (neww == world) { "You reappear where you were. Boom. Yecch. [BUG]"; } ! swap out old stuff switch (world) { world_Home: if (theplay hasnt absent) { print "All the actors yell ~Hey! Come back here!~ [BUG]^"; } give porticocrowd absent; remove porticocrowd; world_November: StopDaemon(novpowerring); give novroadmoss absent; remove novroadmoss; give eastpillarfar absent; remove eastpillarfar; give westpillarfar absent; remove westpillarfar; give pillarladder absent; remove pillarladder; give novtrench absent; remove novtrench; world_Silent: StopDaemon(silmallboss); StopDaemon(thecircus); give silriver absent; remove silriver; give silparkcrowd absent; remove silparkcrowd; give silmallcrowd absent; remove silmallcrowd; give silmalltrees absent; remove silmalltrees; give silparktrees absent; remove silparktrees; give silparkbushes absent; remove silparkbushes; if (bloodstain.number ~= 0) { StopDaemon(bloodstain); bloodstain.number = 17; remove dashercorpse; } world_Dry: DryExit(); world_Frozen: FroExit(); world_Dome: DomExit(); world_Dark: DarkExit(); world_Claustro: CloExit(); world_Meaning: MeanExit(); world_Form: FormExit(); } world = neww; ! swap in new stuff if (world ~= world_None && WorldsVisitedList-->world == 0) { WorldsVisitedList-->world = 1; WorldsVisited = WorldsVisited + 1; } thedark.description = "It is too dark to see."; switch (world) { world_Home: weather = "hot, sticky"; world_November: weather = "autumn, cool, smoky"; player_suit = 0; StartDaemon(novpowerring); give novroadmoss ~absent; give eastpillarfar ~absent; give westpillarfar ~absent; give pillarladder ~absent; give novtrench ~absent; world_Silent: weather = "mild spring, quiet"; StartDaemon(thecircus); StartDaemon(silmallboss); give silriver ~absent; give silparkcrowd ~absent; give silmallcrowd ~absent; give silmalltrees ~absent; give silparktrees ~absent; give silparkbushes ~absent; world_Dry: weather = "warm, arid, dusty"; DryEnter(); world_Frozen: weather = "bright, bitter wind"; FroEnter(); world_Dome: weather = "bitter reek"; DomEnter(); world_Dark: weather = "dank black"; DarkEnter(); world_Claustro: weather = "cramped, crawling"; thedark.description = "It is too dark to see. The ceiling is still there, \ low and massively solid, nonetheless."; CloEnter(); world_Meaning: weather = "formless"; MeanEnter(); world_Form: weather = "meaningless"; FormEnter(); default: weather = "[BUGGY]"; } ]; [ AboutSub; print (emphstring) "So Far"; print " is copyright 1996 by Andrew Plotkin. It may be copied, distributed, \ and played freely.^^"; print "This is a shortish-to-medium-sized game. More than a short story, \ less than a full-length novel. Its rating is ~cruel.~ It is possible to \ make mistakes which will prevent you from winning. Sometimes common sense \ will serve to avoid such mistakes; sometimes insight is necessary; sometimes \ neither will help. Save often, and keep your old saved games.^^"; print "Do not expect ", (emphstring) "So Far", " to be anything like ", (emphstring) "A Change in the Weather.", " It's not.^^"; print "This game was created using the Inform adventure development system, \ which was created by Graham Nelson. You can get Inform, as well as other text \ adventures, from the Interactive Fiction archive:^"; font off; print " ftp://ftp.gmd.de/if-archive/"; font on; print "^^"; print "This game is free. But if you feel like sending me money, I won't refuse. \ If you feel like sending me comments or bug reports, I'll be ecstatic. As of the end \ of 1996, I am at^^"; font off; print " erkyrath@@64netcom.com"; font on; print "^^"; print " Andrew Plotkin^ 7529 Murray Hill Rd. #322^ Columbia, MD 21046^ USA^^"; print "Further acknowledgements:^^"; print " Beta testing: Michael ~The Inescapable~ Kinyon, C. E. Forman, \ Neil Demause, Jools Arnold, Magnus Olsson, Gareth Rees.^"; print " Omega testing: \ Kai Hesse, Lucian Smith, Jon Conrad, Mike Phillips, Matthew \ MacKenzie, Paul C. Trauth, David Auerbach, Michael \ Haralambous, Stephen Granade, Dylan Thurston, Dan Shiovitz, \ Admiral Jota, Mikko Vuorinen, Dylan O'Donnell, Robert \ Rendell, Joe Mason, Marnix Klooster, Avrom Faderman.^"; print " Extra ideas: My brain. (Honest, it comes up with stuff all on its own. \ Sometimes it doesn't tell me the reasons until days later. Then I scream.)^"; print " Dinners of some relevance: Nikki, Jen, Aleecia, Jody.^"; print " Surreal confidence: Tom.^"; print " DJ'ing folk music on the radio for five hours every \ Saturday night, thus providing me with prime working atmosphere: Mary Cliff.^"; print " Playing incredibly funny folk music, both on the radio and live: \ The Foremen.^"; print "^This game is dedicated. (For real.)^"; rtrue; ]; [ Amusing; print "Well, there's a story. Read it how you like. If you come to any conclusions, \ or even any interesting guesses, please email me. I'm curious to know how well \ it worked.^^"; print "A few details:^^"; print "I don't know what's behind any of the locked doors, either. Email me if \ you find out.^^"; print "The web-like towers in the autumn world are, of course, the ~Tensegrity~ \ structures invented by Bucky Fuller. They really do work -- rigid clouds of \ rods and cables, with no two rods touching. There's one on display in front \ of the Baltimore Science Center, should you be in that area; another is \ in the sculpture courtyard of the Hirshhorn Museum in Washington DC. Imagine \ that latter one arched over a trench, and you've got the castle bridge precisely.^^"; print "The creatures at the circus are loosely based on Dougal Dixon's ", (emphstring) "The New Dinosaurs,", " (Salem House, 1988.) It's a science fantasia \ about how life on Earth might look today, if it hadn't been for that nasty meteor, \ or plague, or alien hunting squad, \ or whatever it was that made such a mess 65 megayears \ back. In particular, look at his crested sprintosaur (a grazing herd animal \ descended from the ~duck-billed~ hadrosaur), and the northclaw (a hunting theropod, \ also from the grasslands.) I didn't try to describe exact copies of those animals, \ but I stayed fairly close.^^"; print "If you want a better idea of what the green rod smells like, find some \ cardamom. It really does smell blue. (A sort of greeny-blue, as opposed to \ fresh cilantro, which smells bright blue.) The rod tastes like cardamom, too, \ but the spicy aftereffects are much more like candied tamarind. (Recommended!)^^"; print "For those two or three of you who didn't recognize the poetry fragments behind \ the bells: it's Edgar Allen Poe. Phil Ochs did a great setting of that poem to \ music, and I had it stuck in my head the entire time I was programming that world. \ I figured I should inflict it on the rest of you, as revenge.^^"; print "~Who has seen her, following the wind?~ This is the first line of the poem \ ~The Ghost Lover,~ \ by Rosemary Kirstein, quoted in her book ", (emphstring) "The Outskirter's \ Secret.", " (Del Rey, 1992.) The book contains several verses; I don't \ know if a complete version exists.^^"; print "Although there is, of course, no real score in this game, it is possible to \ get one point. I'll be impressed if anyone does it, even with a story-file \ text dumper. (No fair actually disassembling.)^^"; print "And, finally, a proverb: ", (emphstring) "~The author should always write on the \ reader's nose.~", " I hope I've written on yours.^"; ]; [ InvWideSub; inventory_style = TERSE_BIT + FULLINV_BIT + ENGLISH_BIT + RECURSE_BIT; ; ]; [ ScoreSub; if (deadflag == 0) "That's not how life works."; ! otherwise, the game is over; no score. if (deadflag==2) { ! extra winning message? } rtrue; ]; [ FullScoreSub; <>; ]; [ StrongSub; "Much as you love curses, this is no time to practice your blasphemy."; ]; [ MildSub; <>; ]; [ TheatreSub; "A hollow voice says, ~Christminster.~"; ]; [ NoSuchVerbSub; "That's not a verb I recognise."; ]; [ LagachSub; NoSuchVerbSub(); rtrue; ]; [ LookBehindSub; if (location==thedark) "But it's dark."; if (noun==player) { "Let's not start feeling paranoid."; } if (noun has door && noun hasnt open) { "You can't."; } "You find nothing of interest."; ]; [ LookUpSub; <>; ]; [ LookDownSub; <>; ]; [ SwimSub; if (noun == nothing) "There's nowhere to swim here."; "That is not well-suited to swimming. (Nor are you.)"; ]; [ SingSub; print "You essay a few notes,"; if (noun ~= 0 && noun ~= player) { print " although ", (the) noun, " isn't likely to appreciate your talents.^"; rtrue; } " but music is not your forte."; ]; [ ShoutSub; "You vent your frustration."; ]; [ WaveHandsSub; if (glittering in player && glittering has worn) <>; "You wave, feeling foolish."; ]; [ ApplaudSub; "You give yourself a hearty round of self-congratulation. \ You feel better now, if slightly embarrassed."; ]; [ BowSub; if (noun == player) "Topologically implausible."; if (noun ~= nothing && noun has animate) print_ret (The) noun, " ignores you."; "Respectful, but useless."; ]; [ ListenSub; if (noun == nothing) { if (world == world_Dry) "Grasses rattle gently."; } "You hear nothing unexpected."; ]; [ SmellSub; if (noun == nothing) { switch (world) { world_Home: "The air is hot, close, and chokingly humid."; world_November: "The air is cool, brisk, and rich as pepper sauce."; world_Silent: "The air carries mild spring fragrances, with a hint of the \ distinctive reek of human civilization."; world_Dry: "The air is dry, without much smell."; world_Frozen: "Winter ice claws your nostrils."; world_Dome: ! already handled (by domdirt); world_Dark: "The air is damp; you smell mud, faintly."; world_Claustro: "The air is heavy with rust."; world_Meaning: "The air smells unlike anything."; world_Form: "The air smells unlike anything."; } } L__M(##Smell); ]; [ IsOilSource obj; if (obj == nothing) rfalse; if (obj == jaroil) return 2; if (IsOilPod(obj) ~= 0) return 3; rfalse; ]; [ IsWaterSource obj; if (obj == nothing) rfalse; if (obj == dryspring) rtrue; if (obj == silriver) rtrue; rfalse; ]; [ FillSub; if (second == nothing) { ! try to find one if (dryspring in location) { second = dryspring; } if (silriver in location) { second = silriver; } if (second ~= nothing) { print "(with water from ", (the) second, ")^"; } } if (noun == jar) { if (second == nothing) "I'm not sure what you want to fill it with."; if (IsWaterSource(second) ~= 0) { <>; } if (IsOilPod(second) ~= 0) { <>; } <>; } else { if (second == nothing) "I'm not sure what you want to fill it with."; if (IsWaterSource(second) ~= 0) { print_ret (The) noun, " can't hold water."; } <>; } ]; [ IsFireSource obj; if (obj == nothing) rfalse; if (obj == matchflame || (obj == match && matchflame in match)) rtrue; if (obj == trickleoil && trickleoil has light) rtrue; rfalse; ]; [ BurnSub; if (second == nothing) { ! try to find one if (match in player && matchflame in match) { second = matchflame; } else { if (jar in player && trickleoil in jar && trickleoil has light) second = trickleoil; } if (second ~= nothing) { print "(with ", (the) second, ")^"; } } if (IsFireSource(second) ~= 0) { action=##Ignite; if (RunRoutines(noun,before)~=0) { action=##Burn; rtrue; } action=##Burn; "Arson won't improve matters."; } if (second == nothing) "As they say, wishes don't light candles."; print (The) second, " won't ignite anything.^"; rtrue; ]; [ KnockOnSub; if (noun has animate) "Such force seems unnecessary."; "There is no response."; ]; [ AimSub; if (noun == second) "What a self-referential idea."; "Nothing happens."; ]; [ FollowSub; print (The) noun, " is right here.^"; rtrue; ]; [ UntieSub; "That isn't tied."; ]; [ AttackCutSub; if (second == nothing) { if (knife in player) { print "(with ", (the) knife, ")^"; second = knife; } } <>; ]; [ GoBehindSub; if (noun has door && noun hasnt open) { "You can't."; } if (noun has static || noun has scenery) { "There's nothing there."; } "This would not be useful."; ]; [ InsertBehindSub; if (parent(noun)~=player) "You need to be holding it before you can put it behind \ something else."; if (second>1) { action=##ReceiveBehind; if (RunRoutines(second,before)~=0) { action=##InsertBehind; rtrue; } action=##InsertBehind; } if (second has door && second hasnt open) { "You can't."; } "This would not be helpful."; ]; #ifdef ZDEBUG; [ ZaptoSub; if (noun == 0) { "What number do you want to zapto?"; } LeaveTheater(); ! we're probably at the start of the game. MoveToWorld(noun); switch (noun) { world_Home: PlayerTo(WestPortico); world_November: PlayerTo(NovRoad); world_Silent: PlayerTo(SilBehindStand); world_Dry: PlayerTo(DryEntry); world_Frozen: PlayerTo(FroDesolation); world_Dome: PlayerTo(DomEast); world_Dark: PlayerTo(DarkEntry); world_Claustro: if (location ~= CloLevel1) PlayerTo(CloLevel1); else PlayerTo(CloLevel3); world_Meaning: PlayerTo(MeanRoom); world_Form: PlayerTo(FormRoom1); } ]; [ ZapfireSub; if (noun == 0) "What do you want to zapfire?"; <>; ]; [ ZaptraceSub; parser_trace = noun; print_ret "Setting parser_trace to ", parser_trace, "."; ]; [ ZapstatusSub i j address; print "--- Daemons:^"; for (i=0: ii; if (j~=0) { PrintShortName(j); if (timer_flags->i==2) print ": daemon"; else { print ": timer with ", j.time_left, " turns to go"; } new_line; } } print "--- Floaters:^"; for (i=selfobj+1: i<=top_object: i++) { address=i.&found_in; if (address~=0 && i hasnt absent) { PrintShortName(i); new_line; } } ]; [ ZapSub; switch (noun) { player: Amusing(); tongue: move lump to player; print_ret "Suddenly ", (a) lump, " arrives."; wand: <>; westpillar, eastpillar, silyardgate: if (noun hasnt open) { give noun open; print (The) noun, " pops open.^"; } else { give noun ~open; print (The) noun, " flops closed.^"; } rtrue; novgate: if (novgate hasnt open) { OpenNovGate(); "The gate rattles open."; } else { OpenNovGate(-1); "The gate rattles closed."; } ! eastslab: ! if (noun in EastPillarUp) { ! move noun to EastPillarIn; ! print (The) noun, " descends.^"; ! } ! else { ! move noun to EastPillarUp; ! print (The) noun, " ascends.^"; ! } ! rtrue; tether, buckybridge: if (noun hasnt general) { give noun general; print (The) noun, " generalizes.^"; } else { give noun ~general; print (The) noun, " returns to specificity.^"; } rtrue; silmallcrowd: print "Boing!^"; PlayerTo(SilAtHarp); rtrue; snow: print "Water blows into the crack.^"; move crackwater to cliffcrack; StartDaemon(crackwater); rtrue; default: print "You can't zap ", (the) noun, ".^"; rtrue; } ]; #endif; ! ------------- Startup routine [ Initialise; remove player; player = newplay; location = theaterbench; StartDaemon(sky); ! temperature maintainer StartDaemon(jar); ! oil/water trickle switcher StartDaemon(theplay); MoveToWorld(world_Home); lookmode = 2; ! verbose inventory_style = TERSE_BIT + FULLINV_BIT + ENGLISH_BIT + RECURSE_BIT; ! wide thedark.initial = #r$DarkInitialDark; #ifdef ZDEBUG; move wand to player; print "^[DEBUG] Debugging version! [DEBUG]^"; #endif; new_line; new_line; print "Hot, foul, and dark. How did indoor theater become so fashionable? \ Well enough in spring rain or winter, but not in the thick, dead \ afternoon of high summer. And though ", (emphstring)"Rito and Imita"; print " looks very \ fine, shining with electric moonslight in the enclosed gloom, you're \ much more aware of being crammed in neck-by-neck with your sweaty \ fellow citizens.^^"; print "Damn the crowd, in truth: your mood was hot, foul, and dark when you \ sat down. Aessa was supposed to meet you here. She's made excuses \ before, and you don't think about what it might mean. Try not to \ think, rather. Just watch the story. One of your favorites. But it's \ miserably hot, and you just aren't caught up in the play...^^"; ]; [ Finalise; deadflag = 2; weather = "hot, sticky"; print "The sun's glow has faded in the west of the sky. The crowd outside the \ theater shifts, murmuring; you push a little forward, out from under the \ theater portico. A hot, crowded evening to a hotter, crowded day. But is that \ the start of a breeze? You fan yourself hopefully with the paper in your \ hand -- a playbill for ", (emphstring) "Rito and Imita", " that you must have \ latched onto in the dark.^^"; print "Never mind. It's the moment of the almost-conjunction. People gasp, or sigh. \ The two moons are swinging past each other, seeming to glow in each other's light; \ closer, closer, not quite touching... and away again. So near, yet --^^"; print "Someone is standing there, a few paces ahead, rapt in the sky. \ Curve of chin. Long hair, black in the \ moonslight. To hell with the theater. Dawn is distant yet, so you move \ nearer to her, into the first cool smoky breeze of autumn.^^"; ]; ! ------------- Grammar Include "Grammar"; ! same as ConTopic, but stop at "at" [ ConTopicAt w; consult_from = wn; do w=NextWordStopped(); until (w==-1 || (w=='at')); wn--; consult_words = wn-consult_from; if (consult_words==0) return -1; if (action_to_be==##Ask or ##Answer or ##Tell) { w=wn; wn=consult_from; parsed_number=NextWord(); if (parsed_number=='the' && consult_words>1) parsed_number=NextWord(); wn=w; return 1; } return 0; ]; Verb meta "about" "help" "info" * -> About; Extend "look" * "behind" noun -> LookBehind; Extend "go" * "behind" noun -> GoBehind; Extend "put" * multiexcept "behind" noun -> InsertBehind; Extend "take" first * "down" -> Exit; Extend "drop" * multiexcept "behind" noun -> InsertBehind; Extend "pick" last * multi -> Take; Verb "applaud" "cheer" * -> Applaud; Verb "clap" * -> Applaud * "hands" -> Applaud; Verb "bow" * "to" noun -> Bow; Extend "wave" * "hand" -> WaveHands * "hands" -> WaveHands; Extend "sing" * "at" noun -> Sing * "near" noun -> Sing * "by" noun -> Sing * "to" noun -> Sing; Verb "hum" * -> Sing * "at" noun -> Sing * "near" noun -> Sing * "by" noun -> Sing * "to" noun -> Sing; Verb "scream" "yell" * -> Shout * "at" creature -> Shout * "to" creature -> Shout * ConTopicAt "at" creature -> Answer; Extend only "shout" replace * -> Shout * "at" creature -> Shout * "to" creature -> Shout * ConTopicAt "at" creature -> Answer; Verb "pet" "pat" * noun -> Touch; Verb "follow" "find" "approach" * noun -> Follow; Verb "breathe" "inhale" * -> Smell * noun -> Smell; Verb "knock" * "on" noun -> KnockOn * "at" noun -> KnockOn; Verb "tap" "rap" * "on" noun -> KnockOn * "at" noun -> KnockOn * noun -> KnockOn; Extend "squeeze" * held "on" noun -> PutOn * held "onto" noun -> PutOn * held "against" noun -> PutOn * held "in" noun -> Insert * held "into" noun -> Insert; Verb "crush" * noun -> Squeeze * held "on" noun -> PutOn * held "onto" noun -> PutOn * held "against" noun -> PutOn * held "in" noun -> Insert * held "into" noun -> Insert; Verb "pour" * noun -> Empty * "out" noun -> Empty * noun "out" -> Empty * noun "to" noun -> EmptyT * noun "in" noun -> EmptyT * noun "into" noun -> EmptyT * noun "on" noun -> EmptyT * noun "onto" noun -> EmptyT; Extend "empty" * noun "in" noun -> EmptyT; Extend "burn" replace * noun -> Burn * noun "with" noun -> Burn; Extend "fill" replace * noun -> Fill * noun "from" noun -> Fill * noun "with" noun -> Fill; Extend "attack" * noun "with" held -> Attack; Extend "cut" replace * noun -> AttackCut * noun "with" held -> AttackCut; Verb "untie" "detach" "unfasten" "unhook" "unloop" "free" * noun -> Untie * noun "from" noun -> Untie; Extend "sit" * "down" "on" noun -> Enter * "down" "in" noun -> Enter * "down" "inside" noun -> Enter * "up" "on" noun -> Enter; Verb "step" * "in" noun -> Enter * "on" noun -> Enter * "into" noun -> Enter; Extend "stand" * "in" noun -> Enter; Verb "hide" * "in" noun -> Enter * "behind" noun -> GoBehind; Verb "mount" "ride" "board" * noun -> Enter; Verb "dismount" "disembark" * -> Exit; Extend "dig" * "in" noun -> Dig * "in" noun "with" held -> Dig; Extend "eat" replace * noun -> Eat; Verb "bite" * noun -> Eat; Verb "lick" * noun -> Taste; Extend "swim" * "in" noun -> Swim * "on" noun -> Swim * "under" noun -> Swim * noun -> Swim; Extend "jump" * "across" noun -> JumpOver * "in" noun -> Enter * "into" noun -> Enter; Verb "theatre" "theater" * -> Theatre * special -> Theatre; Verb "lagach" * -> Lagach * special -> Lagach; Extend "swing" replace * -> NoSuchVerb * special -> NoSuchVerb; Verb "shake" * noun -> Wave; Verb "aim" "point" * held "at" noun -> Aim; Extend "look" * "down" -> LookDown * "d" -> LookDown * "up" -> LookUp * "u" -> LookUp; #ifdef ZDEBUG; Verb "zapto" * number -> Zapto; Verb "zaptrace" * number -> Zaptrace; Verb "zapfire" * noun -> Zapfire; Verb "zapstatus" * -> Zapstatus; Verb "zap" * noun -> Zap * "to" number -> Zapto; #endif;