! _Hunter, in Darkness_ ! Special source-code edition ! Copyright 1999 Andrew Plotkin ! http://www.eblong.com/zarf/if.html ! This source code is provided for personal, educational use only. ! See README file for details. ! --- The sentence fragmenter. ! 0: Start of paragraph (after newline) ! 1: End of sentence (after period) ! 2: After a letter Global fragpos; [ FragInit; fragpos = 0; ]; [ fragwbeg let; if (fragpos == 0) { let = let - 32; ! capitalize fragpos = 2; } else if (fragpos == 1) { let = let - 32; ! capitalize fragpos = 2; print (char) ' '; } else { print (char) ' '; } print (char) let; ]; [ fragword wd; print (string) wd; fragpos = 2; ]; [ fragperiod; if (fragpos == 2) { print (char) '.'; fragpos = 1; } ]; [ fragcomand; if (fragpos == 2) { print ", and"; } ]; [ fragcomma; if (fragpos == 2) { print ","; } ]; [ fragwarningsquasher; fragword(); fragcomand(); fragwbeg(); fragperiod(); fragwarningsquasher(); ]; ! --- Oh, the maze, the ramblin' rollin' maze. Global blood_trail; ! Are we following blood or smell? Global mazeloc; ! The seed of all maze room generation. Global maze_exout = 0; ! Which exit object is the right one? Global mazedistance = 0; ! How many times has the player picked the right exit? Array mazeexits --> maze_ex1 maze_ex2 maze_ex3; Global seen_exit = false; ! Has the player seen the clue for the correct exit? Global seen_count = 0; ! How many times in a row has the player taken the correct ! exit, sight seen? When this reaches 2, it jumps and sticks on -1. Global maze_final = -1; ! When set, this is the exit room of the maze. [ MazeSetup mz diff diff2 maxdiff ix ex exobj jx kx nameaddr signsum; mz = mazeloc; for (ix = child(MazeCache) : ix : ix = jx) { jx = sibling(ix); if (ix.maze_pos == mz) { move ix to Maze; } } seen_exit = false; if (blood_trail) maxdiff = -64; else maxdiff = 64; maze_exout = 0; signsum = 0; for (ex = 0 : ex < 3 : ex++) { exobj = mazeexits-->ex; nameaddr = exobj.&name; switch ((mz+ex) % 3) { 0: diff = 0; 1: diff = 10923; 2: diff = -10923; } !ix = ((mz % (2009+ex*2)) & 7); !ix = ((mz % (47+ex*2)) & 7); !ix = ((mz % (217+ex*2)) & 7); !if (ix >= 4) { ! diff2 = (ix - 3); ! signsum++; !} !else { ! diff2 = (-(ix + 1)); ! signsum--; !} ix = ((mz % (217+ex*2)) % 6); if (ix >= 3) { diff2 = (ix - 2); signsum++; } else { diff2 = (-(ix + 1)); signsum--; } if (signsum == 3 or -3) diff2 = (-diff2); diff = diff + diff2; exobj.destination = (mz + diff) & $7FFF; if (blood_trail) { if (diff2 > maxdiff || (diff2 == maxdiff && ((mz % 9) < 4))) { maxdiff = diff2; maze_exout = exobj; } } else { if (diff2 < maxdiff || (diff2 == maxdiff && ((mz % 9) > 4))) { maxdiff = diff2; maze_exout = exobj; } } !print diff2; if (ex == 2) print ".^"; else print ", "; ix = ((mz % (49+ex*2)) % 5); while (1) { for (jx=0 : jxjx).dircode == ix) break; } if (jx == ex) break; ix = (ix+1) % 5; } exobj.dircode = ix; switch (ix) { 0: nameaddr-->0 = 'left'; nameaddr-->1 = 'left'; nameaddr-->2 = 'left'; 1: nameaddr-->0 = 'right'; nameaddr-->1 = 'right'; nameaddr-->2 = 'right'; 2: nameaddr-->0 = 'up'; nameaddr-->1 = 'u//'; nameaddr-->2 = 'ascend'; 3: nameaddr-->0 = 'down'; nameaddr-->1 = 'd//'; nameaddr-->2 = 'descend'; 4: nameaddr-->0 = 'ahead'; nameaddr-->1 = 'forward'; nameaddr-->2 = 'forwards'; } ix = ((mz % (57+ex*2)) % 7); if ((ix == 5 or 6) && (exobj.dircode ~= 2 or 3)) { ix = ix - 5; } exobj.formcode = ix; switch (ix) { 0: nameaddr-->3 = 'tunnel'; 1: nameaddr-->3 = 'passage'; 2: nameaddr-->3 = 'crawl'; 3: nameaddr-->3 = 'crack'; 4: nameaddr-->3 = 'path'; 5: nameaddr-->3 = 'chimney'; 6: nameaddr-->3 = 'pit'; } ix = ((mz % (67+ex*2)) % 11); exobj.modcode = ix; switch (ix) { 0: nameaddr-->4 = 'twisty'; 1: nameaddr-->4 = 'narrow'; 2: nameaddr-->4 = 'wide'; 3: nameaddr-->4 = 'twisting'; 4: nameaddr-->4 = 'steep'; 5: nameaddr-->4 = 'rough'; 6: nameaddr-->4 = 'low'; default: nameaddr-->4 = ',none'; } } if (blood_trail) { mazesmell.phase = 0; mazebats.phase = mazedistance; } else { mazebats.phase = 0; switch (mazedistance) { 3, 4: mazesmell.phase = 1; 5: mazesmell.phase = 2; default: mazesmell.phase = 0; } } if (mazebats in Maze) remove mazebats; if (mazesmell in Maze) remove mazesmell; if (maze_final ~= -1 && ~~blood_trail) { move mazesmell to Maze; } ix = false; jx = false; kx = false; if ((mz & $7) == 0 or 3 or 4) ix = true; if ((mz & $7) == 1 or 4 or 5) jx = true; if ((mz & $7) == 2 or 3 or 5) kx = true; if ((mz & $7) == 6 or 7) { ix = true; jx = true; kx = true; } if (kx && ((mz % 5) == 1)) { if (mazepool notin Maze) move mazepool to Maze; } else { if (mazepool in Maze) remove mazepool; } if (jx && ((mz % 7) == 0)) { if (mazemud notin Maze) move mazemud to Maze; } else { if (mazemud in Maze) remove mazemud; } if (jx && ((mz % 7) == 2 or 3)) { if (mazesand notin Maze) move mazesand to Maze; } else { if (mazesand in Maze) remove mazesand; } if (jx && ((mz % 7) == 4 or 6)) { if (mazechips notin Maze) move mazechips to Maze; } else { if (mazechips in Maze) remove mazechips; } ]; [ ColumnTitle mz any any2; any = true; switch ((mz % 33) % 8) { 0: print "Large"; 1: print "Largish"; 2: print "Small"; 3: print "Smallish"; 4: print "Tiny"; 5: print "Cramped"; default: any = false; } any2 = false; if (~~any) { any2 = true; switch ((mz % 37) % 6) { 0: print "Elongated"; 1: print "Round"; 2: print "Roundish"; 3: print "Oblong"; default: any2 = false; } } switch ((mz % 41) % 8) { 0, 1: if ((~~any) && (~~any2)) print "Dull"; print " "; print "Cave"; 2, 3: if (any || any2) print " "; print "Cavern"; 4, 5: if ((~~any) && (~~any2)) print "Dull"; print " "; print "Room"; 6: if (any || any2) print " "; print "Pit"; 7: if (any || any2) print " "; print "Dome"; default: if (any || any2) print " "; print "Chamber"; } ]; [ ColumnHead mz ix any any2; ix = (mz % 31); if (ix < 15) print (fragwbeg) 't', "his is a"; else print (fragwbeg) 'y', "ou are in a"; any = true; switch ((mz % 33) % 8) { 0: print " large"; 1: print " largish"; 2: print " small"; 3: print " smallish"; 4: print " tiny"; 5: print " cramped"; default: any = false; } any2 = true; switch ((mz % 37) % 6) { 0: if (any) print ","; else print "n"; print " elongated"; 1: print " round"; 2: print " roundish"; 3: if (any) print ","; else print "n"; print " oblong"; default: any2 = false; } switch ((mz % 41) % 8) { 0, 1: if ((~~any) && (~~any2)) print " dull"; print " cave"; 2, 3: print " cavern"; 4, 5: if ((~~any) && (~~any2)) print " dull"; print " room"; 6: print " pit"; 7: print " dome"; default: print " chamber"; } switch (mz % 47) { 3, 12, 17, 28, 33: print ", with a"; if (mz & 1) print " high"; else print " low"; print " roof"; 5, 13, 20, 41, 45: print " which is mazed with"; if (mz & 1) print " fine"; else print " deep"; print " cracks"; } fragperiod(); ]; [ mazecolor mz; switch ((mz / 2) % 13) { 0: print (fragwbeg) 'w', "hite"; 1: print (fragwbeg) 'b', "rown"; 2: print (fragwbeg) 'd', "ark grey"; 3: print (fragwbeg) 'p', "ale grey"; 4: print (fragwbeg) 'b', "lue"; 5: print (fragwbeg) 'g', "reen"; 6: print (fragwbeg) 'p', "ink"; 7: print (fragwbeg) 'g', "reenish"; 8: print (fragwbeg) 'r', "eddish"; 9: print (fragwbeg) 'o', "range"; 10: print (fragwbeg) 'y', "ellow"; 11: print (fragwbeg) 'y', "ellowish"; 12: print (fragwbeg) 'v', "iolet"; } ]; [ ColumnA mz ix; ix = (mz & $20); switch (mz % 9) { 0: print (fragwbeg) 'r', "agged fringes of", (mazecolor) mz, " mineral hang from the ceiling"; 1: print (fragwbeg) 'd', "elicate", (mazecolor) mz, " crystals grow"; if (ix) print " here and there"; else print " everywhere"; 2: print (fragwbeg) 'n', "eedles of", (mazecolor) mz, " calcite spray from the rocks"; if (ix) print " nearby"; else print " here and there"; 3: print (fragwbeg) 's', "talactites hang low overhead"; 4: print (mazecolor) mz, " travertine seems to pour"; if (ix) print " endlessly"; print " down the wall nearby"; 5: if (ix) print (fragwbeg) 'l', "acy, twisted"; else print (fragwbeg) 'r', "opy"; print " pillars rise from floor to roof"; 6: print (fragwbeg) 'c', "ascades of", (mazecolor) mz, " flowstone billow across the walls"; 7: if (ix) print (fragwbeg) 'd', "irty"; print (mazecolor) mz, " striations band the walls"; 8: print (fragwbeg) 's', "talactites form heavy stone fringes across the"; if (ix) print " roof"; else print " ceiling"; } ]; [ ColumnB mz ix; ix = (mz & $10); switch (mz % 7) { 0: print (fragwbeg) 'a'; if (ix) print " thick"; else print " thin"; print " layer of mud lies underfoot"; 1: print (fragwbeg) 't', "he ground is worn into polished flowing curves"; 2: print (fragwbeg) 't', "he floor is crusted with"; if (ix) print " wet"; else print " damp"; print " sand"; 3: if (ix) print (fragwbeg) 'f', "ine dry"; else print (fragwbeg) 'd', "ry, fine"; print " sand is drifted delicately across the floor"; 4: print (fragwbeg) 'j', "agged slabs"; if (ix) print " litter the floor"; else print " lie around your feet"; 5: print (fragwbeg) 's', "talagmites cluster thickly around you"; 6: print (fragwbeg) 'g', "ravel and"; if (ix) print " chipped rock"; else print " small rock chips"; print " cover the ground"; } ]; [ ColumnC mz ix; ix = (mz & $08); switch (mz % 5) { 0: print (fragwbeg) 'w', "ater trickles audibly, somewhere nearby"; 1: print (fragwbeg) 'a', " small still pool lies to one side"; 2: print (fragwbeg) 'y', "ou can hear water rushing in the distance"; 3: print (fragwbeg) 't', "he uncertain light seems a bit"; if (ix) print " brighter"; else print " dimmer"; 4: print (fragwbeg) 't', "he air is"; if (ix) print " chill and damp"; else print " damp and chill"; } ]; Object MazeCache; Object Maze with short_name [; ColumnTitle(mazeloc); #ifdef ZDEBUG; print " ", mazeloc; #endif; rtrue; ], seen_once false, description [ mz form; mz = mazeloc; if (mz == -1) { print "(BUG) Null room... "; } form = mz & $7; if (~~self.seen_once) { self.seen_once = true; print "Eventually, you manage to sit up and look around.^^"; } #ifdef ZDEBUG; print (address) (maze_ex1.&name)-->0, ":", maze_ex1.destination; if (maze_exout == maze_ex1) print "!"; print " ", (address) (maze_ex2.&name)-->0, ":", maze_ex2.destination; if (maze_exout == maze_ex2) print "!"; print " ", (address) (maze_ex3.&name)-->0, ":", maze_ex3.destination; if (maze_exout == maze_ex3) print "!"; print " (", mazedistance, "/", seen_count, ")"; print ".^"; #endif; FragInit(); ColumnHead(mz); switch (form) { 0: ColumnA(mz); 1: ColumnB(mz); 2: ColumnC(mz); 3: ColumnC(mz); fragcomand(); ColumnA(mz); 4: ColumnA(mz); fragcomand(); ColumnB(mz); 5: ColumnB(mz); fragperiod(); ColumnC(mz); 6: ColumnB(mz); fragperiod(); ColumnA(mz); fragcomand(); ColumnC(mz); 7: ColumnA(mz); fragcomand(); ColumnC(mz); fragperiod(); ColumnB(mz); } fragperiod(); maze_ex1.long_name(); fragcomma(); maze_ex2.long_name(); fragcomand(); maze_ex3.long_name(); fragperiod(); new_line; rtrue; ], before [; Examine: if ((noun == walls_obj or d_obj) && mazebats in self && mazebats.phase >= 7) { <>; } WaveHands: if (mazebats in self) <>; ], light_level 1, ambient_sound [ mz; if (mazebats in self) <>; mz = mazeloc; if (((mz % 5) == 0 or 2) && ((mz & $7) == 2 or 3 or 5 or 6 or 7)) "You can hear water."; ], ambient_smell [; if (mazesmell in self) <>; ], when_unbandage [; print "You pull the end of the cloth free; the wound underneath begins bleeding freely. You hastily rewrap it"; if (mazebats in self) print " before the bats notice"; "."; ], phase 10, each_turn [; self.phase++; if (self.phase > 20) { self.phase = random(13); print "^You shake your head, side to side, trying to push off the weight of weariness for another few minutes. Keep moving.^"; } if (mazebats.seen_once) { mazebats.seen_once = false; print "^The bats here seem to have fled.^"; } ], daemon MazeDaemonFunc; Class MazeExit class ObjExit with name ',none' ',none' ',none' ',none' ',none', destination 0, dircode -1, formcode -1, modcode -1, description [; FragInit(); self.long_name(); fragperiod(); print " You can see only more darkness beyond."; new_line; rtrue; ], door_to [ ix jx mz; mz = mazeloc; for (ix = child(Maze) : ix : ix = jx) { jx = sibling(ix); if (ix provides maze_pos) { ix.maze_pos = mz; move ix to MazeCache; } } if (self == maze_exout) { if (seen_count ~= -1) { if (seen_exit) { seen_count++; if (seen_count == 2) seen_count = -1; } } if (maze_final == -1) { mazedistance++; } else { if (maze_final == mz) mazedistance = 6; else mazedistance = 0; } if (mazedistance >= 6) { maze_final = mz; print "The "; self.short_name(2); print " opens abruptly into vast space.^"; if (blood_trail) return Antechamber; else return TopSlope; } } else { if (seen_count ~= -1) { seen_count = 0; } mazedistance = 0; } ! switch ((mz + self.destination) % 7) { print something } if (Maze.phase > 18) { Maze.phase = random(7) + 6; print "You grimly push your aching feet onward.^"; } mazeloc = self.destination; MazeSetup(); return Maze; ], short_name [ flag; switch (self.modcode) { 0: print "twisty "; 1: print "narrow "; 2: print "wide "; 3: print "twisting "; 4: print "steep "; 5: print "rough "; 6: print "low "; ! default: ! do nothing } switch (self.formcode) { 0: print "tunnel"; 1: print "passage"; 2: print "crawl"; 3: print "crack"; 4: print "path"; 5: print "chimney"; 6: print "pit"; } if (flag == 0) { switch (self.dircode) { 0: print " left"; 1: print " right"; 2: print " up"; 3: print " down"; 4: print " ahead"; } } else if (flag == 2) { ! do nothing } else { switch (self.dircode) { 0: print " to the left"; 1: print " to the right"; 2: print " leading up"; 3: print " leading down"; 4: print " ahead"; } } rtrue; ], long_name [ ix; print (fragwbeg) 'a'; switch (self.modcode) { 0: print " twisty"; 1: print " narrow"; 2: print " wide"; 3: print " twisting"; 4: print " steep"; 5: print " rough"; 6: print " low"; ! default: ! do nothing } switch (self.formcode) { 0: print " tunnel"; 1: print " passage"; 2: print " crawl"; 3: print " crack"; 4: print " path"; 5: print " chimney"; 6: print " pit"; default: print " (BUG)"; } ix = ((mazeloc + self.dircode) & 6) / 2; switch (self.dircode) { 0: switch (ix) { 0: print " goes left"; 1: print " leads left"; 2: print " heads left"; 3: print " runs left"; } 1: switch (ix) { 0: print " goes right"; 1: print " leads right"; 2: print " heads right"; 3: print " runs right"; } 2: switch (ix) { 0: print " ascends"; 1: print " leads up"; 2: print " heads up"; 3: print " climbs up"; } 3: switch (ix) { 0: print " descends"; 1: print " leads down"; 2: print " heads down"; 3: print " runs down"; } 4: if (ix < 2) print " leads ahead"; else print " leads forward"; default: print " (BUG) uninitialized exit"; } ]; MazeExit maze_ex1 "(BUG)" Maze; MazeExit maze_ex2 "(BUG)" Maze; MazeExit maze_ex3 "(BUG)" Maze; Object maze_formations "formations" Maze with name 'formations', parse_name [ wd num; wd = NextWord(); while (wd == 'formation' or 'stalagmite' or 'stalactite' or 'pillar' or 'pillars' or 'fringe' or 'fringes' or 'needle' or 'needles' or 'crystal' or 'crystals' or 'mineral' or 'minerals' or 'travertine' or 'flowstone' or 'striation' or 'calcite') { num++; wd = NextWord(); } return num; ], description "Hours ago, you might have been impressed.", before [; Examine, VagueShoot: rfalse; default: "It's just stone."; ], has scenery pluralname; Object mazepool "pool" with name 'small' 'still' 'pool' 'muddy' 'water', description "Just a bit of muddy water that's gathered at a low point in the cave.", before [; Search: "There is nothing in the water but silt."; Take: "You have no way to carry water."; Taste: "The water is muddy and harsh."; Drink: "The water is muddy and harsh. You cannot force yourself to swallow much."; Touch: "It's cold."; Pull, Push, Rub: "You splash a bit."; ], has scenery; Object mazemud "mud" with name 'mud' 'thick' 'thin' 'layer', article "some", before [; Examine, VagueShoot: rfalse; default: "It's just mud."; ], has scenery; Object mazesand "sand" with name 'sand' 'fine' 'dry' 'crusted' 'damp', article "some", before [; Examine, VagueShoot: rfalse; default: "It's just sand."; ], has scenery; Object mazechips "small stones" with name 'small' 'stones' 'chip' 'chips' 'slab' 'slabs' 'chipped' 'jagged' 'gravel' 'rock' 'bits' 'bit', before [; Examine, VagueShoot: rfalse; default: "It's just bits of rock."; ], has scenery pluralname; ! --- Daemon stuff Object mazebats "bats" with name 'bat' 'bats', phase 0, seen_once false, ! used for the "bats gone" message. initial [; switch (self.phase) { 5, 6: "Several bats flicker silently above, circling in the shadows."; 7 to 10: "Several bats cluster on the ground nearby."; default: "(BUG) Bats not here."; } ], description [; switch (self.phase) { 5, 6: "There are six or eight bats -- they're hard enough to see, let alone count, fluttering wildly around the roof."; 7 to 10: seen_exit = true; print "The bats cluster on the ground near the "; maze_exout.short_name(1); print_ret ". They seem to be licking at the stone."; default: "(BUG) Bats not here."; } ], before [; Examine, VagueShoot: rfalse; Smell: rfalse; Listen: if (self.phase <= 6) { "The air is full of rustle and rattle, wing on wing."; } else { "You hear tiny sucking sounds."; } default: if (self.phase <= 6) { self.phase = 5; "The bats are not coming within reach."; } else { self.phase = 5; "The bats startle up in a chittering cloud."; } ], when_shot [ curbolt; move curbolt to location; print " Your hands are not as steady as they were; you miss."; if (self.phase <= 6) { self.phase = 5; " The bats whirl agitatedly."; } else { self.phase = 5; " The bats scatter agitatedly about the cave."; } ], has static pluralname; Object mazesmell "smell" with name 'smell' 'odor' 'whiff', phase 0, before [; Examine: <>; Smell: if (maze_final ~= -1) { if (mazeloc == maze_final) { seen_exit = true; print "The smell welling from the "; maze_exout.short_name(1); " is thick and rank."; } else { "You can no longer tell where the smell is coming from."; } } seen_exit = true; switch (mazedistance) { 0, 1, 2: print "The faintest trace of the ", (NameWumpus) 0, " hangs in the air"; print ". It seems stronger near the "; maze_exout.short_name(1); "."; 3, 4: print "The smell of the ", (NameWumpus) 0, " is stronger here"; print ". It's coming from the "; maze_exout.short_name(1); "."; 5: print "The smell welling from the "; maze_exout.short_name(1); print_ret " is thick and rank. The ", (NameWumpus) 0, " is near."; } "(BUG) Unknown cave distance."; default: "You're not making sense."; ], has scenery; [ MazeReenterStart; mazeloc = maze_final; mazedistance = 0; if (blood_trail) mazebats.seen_once = true; ]; [ MazeDaemonStart; mazeloc = 13285; blood_trail = wumpus_wounded; mazedistance = 0; StartDaemon(maze); ]; [ MazeDaemonFunc; if (location ~= Maze) { mazedistance = 0; StopDaemon(Maze); return; } if (blood_trail) { mazebats.phase++; switch (mazebats.phase) { 3: print "^A scrap of shadow flickers across a wall.^"; 4: if (mazedistance == 3) print "^A scrap of shadow flickers nearby as you enter.^"; 5: move mazebats to Maze; print "^Again, shadow-flutter. More bats. They don't seem to have noticed you yet.^"; 6: if (mazedistance == 5) { move mazebats to Maze; print "^Bats flutter wildly about, disturbed by your arrival.^"; } 7: print "^One bat, then another, settles to the ground"; if (seen_count == -1) { print " near the "; maze_exout.short_name(1); } print ". You shift back uneasily, but they are staying well away.^"; 10: mazebats.phase = 7; print "^The bats shift eagerly, crawling over their patch of stone.^"; } } else { mazesmell.phase++; switch (mazesmell.phase) { 2: if (mazedistance >= 3) move mazesmell to Maze; 3: if (mazesmell notin Maze) move mazesmell to Maze; switch (mazedistance) { 0, 1, 2: print "^You catch a distant whiff of something"; if (seen_count == -1) { print ", drifting from the "; maze_exout.short_name(1); } print ".^"; 3, 4: print "^You catch a whiff of something rank"; if (seen_count == -1) { print " from the "; maze_exout.short_name(1); } print ".^"; 5: print "^The scent of the ", (NameWumpus) 0, " hangs all around you"; if (seen_count == -1) { print ". It's welling from the "; maze_exout.short_name(1); } print ".^"; } } } ];