#!/usr/bin/perl print "Content-type: text/html\n\n"; ## ## This adaptation of "Colossal Cave Adventure," the game ## originally written by Willie Crowther and Don Woods, was ## created by Arthur O'Dwyer, 2003--2005. Most of the in-game ## text is copyright Crowther and Woods; the design and ## implementation of this program is released to the public ## domain by its author, 2005. ## ################################################################ ## ARGUMENTS ## ## rm=N Room number, 0 .. $MAXROOM. Sets $RoomNumber. ## ## in=XXX Packed inventory, as a number base $MAXITEM. ## Must be unpacked into @ihas_by_item first. ## ## ## rh=XXX Room Has X; packed inventory times $MAXROOM ## plus the room whose contents are listed. ## There may be a lot of these. Basically diffs ## from the values listed in @item_home. ## Must be unpacked into @room_contents first. ## er=XXX After unpacking mod $MAXROOMS, all these rooms have ## nothing at all in them. Set @room_contents accordingly. ## ## f=NXXX Flags set N; XXX = three chars base 64 via table: ## "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-+" ## Convert number to binary, then set flags 18*N+(XXX). ## XXX is stored in order flag 0... flag 18, bitwise. ## There MUST be a multiple of 18 flags! ## ## x=N Examining object N. Sets $CurrentlyExamining. ## ## msg=TXT Message "TXT". Sets $CurrentlyMessaging, and prints ## the appropriate message from %message_desc. Messages ## don't get hypertexted, except for a "Back" button. ## ## dw=N Sets $NounDollar to N. ## ################################################################ ## VARIABLES ## ## @item_by_num Maps between item names ('keys') and ## %n item numbers (2). ## ## @item_home Default room contents, as packed 'in' strings. ## @room_contents Current room contents, as packed 'in' strings. ## ## @ihas_by_num Booleans; is item number N in inventory? ## $NumberOfItemsCarried Number of items in inventory, as calculated ## from in=XXX by unpack_args. ## ## @room_by_num Maps between room names ('inside building') and ## %r room numbers (1). ## @room_desc HTML room descriptions; links in [brackets]. ## @room_links Href code for [brackets] in @room_desc. ## ## @item_desc HTML object descriptions; links in [brackets]. ## @item_links Href code for [brackets] in @item_desc. ## ## %message_desc HTML message text. No [bracket-links] allowed. ## ## %f Maps flag names ('gotwater') to numbers (1). ## @flag Booleans; is flag N currently on? ## ## $RoomNumber Current room number (rm=N). ## ## $CurrentlyExamining Item number of object we're looking at, in ## range (1..$MAXITEM-1). ## ## $CurrentlyMessaging Text label of current message, e.g., 'EATF' ## ## $NounDollar Item number of object we're "puzzling over." ## Same role as $NOUN$ in AGT, for href_say() ## messages. ## ## $argsPickingUpThisItem Hint to pack_args() that this item should ## not be included in the current room's contents. ## THIS VARIABLE SHOULD *NOT* AFFECT THE PLAYER'S ## INVENTORY LIST! It makes the object actually ## "disappear" from the room. ## $argsDroppingThisItem Hint to pack_args() that this item should ## be included in the current room's contents. ## THIS VARIABLE SHOULD *NOT* AFFECT THE PLAYER'S ## INVENTORY LIST! It makes the object actually ## "appear" in the room. ## ################################################################ use integer; ############################################################# ## use strict; ## ## ## use CGI::Carp qw(fatalsToBrowser); ## ## ############################################################# my $MAXITEM = 27; my $MAXABSTRACTITEM = 115; my $MAXFLAG = 54; my $MAXROOM = 70; my $RoomNumber = 0; my $CurrentlyExamining = 0; my $CurrentlyMessaging = ""; my $NounDollar = 0; my $argsPickingUpThisItem = 0; my $argsDroppingThisItem = 0; my $DarknessCounter = 0; sub pack_args(); sub reunpack_args($); sub start_desc(); sub done_desc(); sub can_see_room(); sub item_in_room($); sub item_short_name($); sub is_treas($); sub ihas_treas($); sub print_possessions(); sub print_room_description($); sub print_item_description($); sub stop_game(); ## INVENTORY ITEMS my @ihas_by_num = (0) x $MAXITEM; ## boolean - have I got such-and-such? my $NumberOfItemsCarried = 0; my @item_by_num; my %n = ( ## Items: 'off lamp' => 1, 'on lamp' => 2, 'keys' => 3, 'food' => 4, 'empty bottle' => 5, 'bottle of water' => 6, 'bottle of oil' => 7, 'rusty wand' => 8, 'cheerful bird' => 9, 'caged bird' => 10, 'wicker cage' => 11, 'green snake' => 12, 'gold nugget' => 13, 'diamonds' => 14, 'silver bars' => 15, 'jewelry' => 16, 'rare coins' => 17, 'giant clam' => 18, 'giant oyster' => 19, 'pearl' => 20, 'magazine' => 21, 'treasure chest' => 22, 'pool of oil' => 23, 'little plant' => 24, '12-foot beanstalk' => 25, 'huge beanstalk' => 26, 'stream' => 101, 'building' => 102, 'grate down' => 103, 'grate up' => 104, 'mist' => 105, 'fissure' => 106, 'nugget note' => 107, 'stone steps down' => 108, 'stone steps up' => 109, 'crystal bridge' => 110, 'forest' => 111, 'shadowy figure' => 112, 'sea air' => 113, 'bedrock block' => 114, ); foreach my $i (keys %n) { $item_by_num[$n{$i}] = $i; } ## IN-GAME FLAGS my @flag = (0) x $MAXFLAG; ## boolean - is flag X turned on, or off? my %f = ( ## Flags: 'VIEWING_SELF' => 0, 'MSG_GOT_WATER' => 1, 'MSG_GOT_OIL' => 2, 'MSG_SPILL_WATER' => 3, 'MSG_SPILL_OIL' => 4, 'MSG_LIT_LAMP' => 5, 'MSG_EXT_LAMP' => 6, 'GRATE_OPEN' => 7, 'MSG_GRATE_OPEN' => 8, 'MSG_GRATE_CLOSE' => 9, 'MSG_TRANSPORT' => 10, 'TRIED_JUMP' => 11, 'MSG_JUMP_TO_DEATH' => 12, 'CRYSTAL_BRIDGE' => 13, ## Does the crystal bridge exist? 'VIEW_ROOM' => 14, 'SLIT_SHOWN' => 15, 'BIRD_FLAG' => 16, 'MSG_GOT_BIRD' => 17, 'MSG_NO_SNAKE' => 18, 'MSG_DROP_CAGE' => 19, 'MSG_FREE_BIRD' => 20, 'SNAKE_HNT1' => 21, 'SNAKE_HNT2' => 22, 'FIENDISH_1' => 23, ## For use in the two mazes. 'FIENDISH_2' => 24, ## Five of these modify the room number, 'FIENDISH_3' => 25, ## and the sixth is a simple random 'FIENDISH_4' => 26, ## flag whose value doesn't do anything. 'FIENDISH_5' => 27, ## This keeps browsers from changing the 'FIENDISH_6' => 28, ## link colors of rooms we've already 'FIENDISH_7' => 29, ## visited. >;) 'MAZE_DEADEND' => 30, 'BEHIND_BLOCK' => 31, 'MED_PLANT' => 32, ## Does the medium plant exist? 'HUGE_PLANT' => 33, ## Does the huge plant exist? 'MSG_CLIMB_MED' => 34, 'MSG_CLIMB_HUGE' => 35, 'MSG_WATER_LITTLE' => 36, 'MSG_WATER_MED' => 37, 'MSG_WATER_HUGE' => 38, 'MSG_OIL_PLANT' => 39, 'USELESS1' => 40, 'USELESS3' => 41, 'USELESS4' => 42, 'USELESS5' => 43, 'USELESS6' => 44, 'USELESS7' => 45, 'USELESS8' => 46, 'USELESS9' => 47, 'USELESSA' => 48, 'USELESSB' => 49, 'USELESSC' => 50, 'USELESSD' => 51, 'USELESSE' => 52, 'USELESSF' => 53, ); ## IN-GAME MESSAGES my %message_desc = ( 'EATF' => q(My, that food was tasty!), 'LBTT' => q(Maybe there are batteries inside the lamp.), 'PPES' => q(There's nothing special about the sewer pipes.), 'H2O' => q(You have taken a drink from the stream. The water). q( tastes strongly of minerals, but is not unpleasant.). q( It is extremely cold.), 'SLIT' => q(You can't fit through a 2-inch slit!), 'ANCH' => q(You don't seem to be able to budge the steel grate.), 'GLOK' => q(You can't reach the lock, no matter how hard you try.), 'SURF' => q(Sunlight filters through the bars of the grate.). q( If only you were on the other side of it.), 'MAGI' => q(A brief note on the nature of magic. Some scholars). q( would have it that the command of magical powers). q( comes naturally to those with a special aptitude,). q( and to others only after long years of training.). q( These scholars are full of it. Those who dwell). q( in caves have always known that magic spells are). q( child's play as long as you know the right words.), 'MGNO' => q(Nothing happens.), 'CRCK' => q(The crack is far too small for you to follow.), 'JBRI' => q(I respectfully suggest you go across the bridge). q( instead of jumping.), 'JFIS' => q(On second thought, the fissure is still much). q( too wide to jump.), 'DARK' => q(It is pitch black. You can't see your hand in front). q( of your face.), 'PITS' => q(One of the many dangers of cave exploring is the). q( danger of falling into a pit. Colossal Cave in). q( particular is known to be riddled with these deep). q( crevasses, often filled with water or sharp rocks). q( and debris from the cave above. Suffice it to say,). q( you wouldn't want to be caught in the cave without a). q( light source of some kind.), 'BRD1' => q(The bird was unafraid when you entered, but as you). q( approach it becomes disturbed and you cannot catch it.), 'BRD2' => q(The bird is frightened right now and you cannot catch). q( it no matter what you try. Perhaps you might try later.), 'BRD3' => q(You can catch the bird, but you cannot carry it.), 'RIDI' => q(Don't be ridiculous!), 'BULK' => q(You cannot lift any more.), 'DWHA' => q(What do you want to do with the $NOUN$?), 'VTRE' => q(As you drop the $NOUN$, it vanishes in a clash of). q( cymbals and a puff of orange smoke! A distant). q( voice booms:

You have gained 10 points!

), 'VMWE' => q(As you drop the $NOUN$, it vanishes very quietly). q( in a puff of light black smoke. A hollow). q( voice whispers:

You have gained 1 point!

), 'SNK1' => q(A huge fierce green snake bars your way!), 'SNK2' => q(You can't get by the snake.), 'SNK3' => q(Going that way would require getting very close to). q( the snake! I'm sorry, but I just can't allow it. ). q( For your own good, you can't go that way.), 'SNKH' => q(You can't kill the snake, or drive it away, or avoid). q( it, or anything like that. There is a way to get by,). q( but you don't have the necessary resources right now.), 'SNBH' => q(You can't kill the snake, or drive it away, or avoid). q( it, or anything like that. There is a way to get by,). q( but I'm not going to tell you what it is.), 'MGNS' => q(Nothing happens. The snake looks amused.), 'CNGO' => q(You can't go that way!), 'NTOE' => q(The walls of the room do not afford any purchase). q( to your hands and feet. You slide back down.), 'CLNU' => q(You can't possibly be serious!
). q( The dome is unclimbable!), 'DWRD' => q[I'm afraid it is written in Dwarvish (a language]. q[ somewhat like Perl, and totally unreadable).], 'ULUK' => q(You look as ugly as ever.), 'OYMV' => q(You can't fit the $NOUN$ through that little passage!), 'BQCR' => q(You have crawled around in some little holes and). q( found your way blocked by a recent cave-in. You are). q( now back in the main passage.), 'STAR' => q[Unfortunately (for you), the magazine is written in]. q( Dwarvish -- so you get very little out of the articles.). q( However, the pictures give you new inspiration to). q( explore the cave further.). 'STPI' => q(The pictures are full-page photos of cave formations,). q( just like the ones you've seen in your adventures.). q( Several of the pictures show Dwarves standing next to). q( the formations for scale, which is somewhat confusing,). q( as Dwarves are really very short.). 'BLCY' => q(The canyon runs into a mass of boulders - dead end.), 'DECY' => q(The canyon here becomes too tight to go farther south.), '2PNH' => q(The hole is too far up to reach.), '2PHH' => q(There is a huge beanstalk stretching all the way up). q( to the hole!), '2PRT' => q(The plant has exceptionally deep roots and cannot be). q( pulled free.), 'EXLV' => q(The eastern end of this passage is filled with a). q( soft organic light filtered through the veins of). q( thousands of bright green leaves attached to the). q( broad trunk of a twenty-foot beanstalk. It's a). q( really beautiful sight. Too bad you don't have). q( time to fully appreciate it - you have to get on). q( with this adventure.), 'WITT' => <

Cave under construction beyond this point
Proceed at your own risk

Witt construction company

EOF , ); ## ROOMS my @room_by_num; my %r = ( ## Room names: 'end of road' => 0, 'inside building' => 1, 'valley' => 2, 'slit in streambed' => 3, 'outside grate' => 4, 'hill by road' => 5, 'forest' => 6, 'open forest' => 7, 'below the grate' => 8, 'cobble crawl' => 9, 'debris room' => 10, 'awkward canyon' => 11, 'bird chamber' => 12, 'top of small pit' => 13, 'hall of mists' => 14, 'east of fissure' => 15, 'nugget of gold room' => 16, 'hall of mt. king' => 17, 'low n-s passage' => 18, 'south side chamber' => 19, 'west side chamber' => 20, 'west of fissure' => 21, 'w end - hall of mists'=> 22, 'crossover of passages'=> 23, 'blocked passageway' => 24, '"Y2"' => 25, 'window on pit' => 26, 'jumble of rock' => 27, 'low wide passage' => 28, ## Note the extra space in the 'low wide passage ' => 29, ## second room's name! 'dirty passage' => 30, 'brink of small pit' => 31, 'bottom of small pit' => 32, 'east end of long hall'=> 33, 'west end of long hall'=> 34, 'dusty rock room' => 35, 'complex junction' => 36, 'shell room' => 37, 'arched hall' => 38, 'sloping corridor' => 39, 'sloping corridor ' => 40, 'cul-de-sac' => 41, ## lots of rooms for the little twisty maze, all alike: 42-55 'brink of pit' => 56, 'pirate\'s den' => 57, 'bedquilt' => 58, 'anteroom' => 59, 'witt\'s end' => 60, 'slab room' => 61, 'swiss cheese room' => 62, 'tall e-w canyon' => 63, 'wide place' => 64, 'e end of twopit room'=> 65, 'w end of twopit room'=> 66, 'east pit' => 67, 'west pit' => 68, 'long narrow corridor'=> 69, ); foreach my $i (keys %r) { $room_by_num[$r{$i}] = $i; } foreach (42..55) { $room_by_num[$_] = 'twisty little maze'; } my @item_home = (0) x $MAXROOM; $item_home[$r{'inside building'}] = $n{'off lamp'}*($MAXITEM**3) + $n{'food'}*($MAXITEM**2) + $n{'keys'}*($MAXITEM) + $n{'bottle of water'}; $item_home[$r{'debris room'}] = $n{'rusty wand'}; $item_home[$r{'cobble crawl'}] = $n{'wicker cage'}; $item_home[$r{'bird chamber'}] = $n{'cheerful bird'}; $item_home[$r{'east of fissure'}] = $n{'diamonds'}; $item_home[$r{'nugget of gold room'}] = $n{'gold nugget'}; $item_home[$r{'hall of mt. king'}] = $n{'green snake'}; $item_home[$r{'low n-s passage'}] = $n{'silver bars'}; $item_home[$r{'south side chamber'}] = $n{'jewelry'}; $item_home[$r{'west side chamber'}] = $n{'rare coins'}; $item_home[$r{'shell room'}] = $n{'giant clam'}; $item_home[$r{'anteroom'}] = $n{'magazine'}; $item_home[$r{'pirate\'s den'}] = $n{'treasure chest'}; $item_home[$r{'east pit'}] = $n{'pool of oil'}; $item_home[$r{'west pit'}] = $n{'little plant'}; my @room_contents = @item_home; ## ## ROOM AND ITEM DESCRIPTIONS! ## my @room_desc = < You see a small building at the crest of a hill to the [north]. ROOM 4 NEXT [You] are in a 20-foot depression floored with bare dirt. Set into the dirt is a strong steel [grate] mounted in concrete. A [dry streambed] leads into the depression. ROOM 5 NEXT [You] have walked up a hill, still in the [forest]. The road slopes back down the [other side] of the hill. There is a [building] in the distance. ROOM 6 NEXT [You] are in open [forest], with a deep [valley] to one side. ROOM 7 NEXT [You] are in open [forest] near both a [valley] and a [road]. ROOM 8 NEXT [You] are in a small chamber beneath a 3x3 [steel grate] to the [surface]. A low crawl over cobbles leads inward to the [west]. ROOM 9 NEXT [You] are crawling over cobbles in a low [east]-[west] passage. There is a dim light at the [east end] of the passage. ROOM 10 NEXT [You] are in a debris room filled with stuff washed in from the surface. A [low wide passage] with cobbles becomes plugged with mud and debris here, but an awkward canyon leads [upward] and [west]. A note on the wall says: [Magic Word] "[XYZZY]" ROOM 11 NEXT [You] are in an awkward sloping [east]/[west] canyon. ROOM 12 NEXT [You] are in a splendid chamber thirty feet high. The walls are frozen rivers of orange stone. An awkward canyon and a good passage exit from [east] and [west] sides of the chamber. ROOM 13 NEXT At your feet is a small pit breathing traces of white [mist]. An [east passage] ends here except for a [small crack] leading on.

[Rough stone steps] lead [down] to the pit. ROOM 14 NEXT [You] are at one end of a vast hall stretching forward out of sight to the [west]. There are openings to [either] [side]. Nearby, a wide stone staircase leads [downward]. The hall is filled with [wisps of white mist] swaying to and fro almost as if alive. A cold wind blows up the staircase. There is a passage at the top of a dome behind you.

[Rough stone steps] lead [up] to the dome. ROOM 15 NEXT [You] are on the east bank of a [fissure] slicing clear across the hall. The [mist] is quite thick here, and the fissure is too wide to [jump]. The hall continues to the [east]. ROOM 16 NEXT This is a low room with only the one [exit] and a crude note on the wall. The note says: [You won't get it up the steps.] ROOM 17 NEXT [You] are in the hall of the mountain king, with [passages] [off] [in] [all] [direction][s] - [north], [east], [west], and [south]. A wide stone staircase leads [up] the way you came. ROOM 18 NEXT [You] are in a low [north]-[south] passage at a hole in the floor. The hole goes [down] to an east-west passage. ROOM 19 NEXT [You] are in the south side chamber. The exit is to the [north]. ROOM 20 NEXT [You] are in the west side chamber of the [hall of the mountain king]. A passage continues to the [west]. ROOM 21 NEXT [You] are on the west side of the [fissure] in the hall of mists.

The hall continues to the [west], and a low passage exits to the [north]. ROOM 22 NEXT [You] are at the west end of the [hall of mists]. A low wide crawl continues [west] and another goes [north]. To the [south] is a little passage 6 feet off the floor. ROOM 23 NEXT [You] are at a crossover of a high [north]-[south] passage and a low [east]-[west] one. ROOM 24 NEXT [You] are in a passageway leading [north]. There is a sign on the wall of the passage saying This way to the Cave's Main Office. Just beyond the sign, there has been a cave-in and the passageway is blocked. The only exit is to the [south]. ROOM 25 NEXT [You] are in a large room, with a passage to the [south], a passage to the [west], and a wall of broken rock to the [east]. There is a large "Y2" on a rock in the room's center. ROOM 26 NEXT [You]'re at a low window overlooking a huge pit, which extends up out of sight. A floor is indistinctly visible over 50 feet below. Traces of [white mist] cover the floor of the pit, becoming thicker to the right. Marks in the dust around the window would seem to suggest that someone has been here recently.

Directly across the pit from you and 25 feet away there is a similar window looking into a lighted room. A [shadowy figure] can be seen there peering back at you.

[Back] ROOM 27 NEXT [You] are in a [jumble] of rock, with [cracks] [everywhere]. ROOM 28 NEXT [You] have crawled through a very low wide passage [parallel to] and [north of] the hall of mists. ROOM 29 NEXT [You] have crawled through a very low wide passage [parallel to] and [north of] the hall of mists. ROOM 30 NEXT [You] are in a dirty broken passage. To the east is a [crawl]. To the west is a [large passage]. [Above you] is another passage. ROOM 31 NEXT [You] are on the brink of a small clean climbable [pit]. A crawl leads [west]. ROOM 32 NEXT [You] are in the bottom of a small pit with a little [stream], which enters and exits through tiny slits.

[Back] ROOM 33 NEXT [You] are at the east end of a [very long hall] apparently without side chambers. To the [east] a low wide crawl slants [up]. To the [north] a round two foot hole slants [down]. ROOM 34 NEXT [You] are at the west end of a very long featureless hall. The [hall] joins up with a narrow [north]/[south] passage. ROOM 35 NEXT [You] are in a large room full of dusty rocks. There is a [big hole] in the floor. There are cracks everywhere, and a passage leading [east]. ROOM 36 NEXT [You] are at a complex junction. A low hands and knees passage from the [north] joins a higher crawl from the [east] to make a [walking passage] going west. There is also a large room [above], but there are no hand or toe holds to climb up.

The air is damp here. ROOM 37 NEXT [You]'re in a large room carved out of sedimentary rock. The floor and walls are littered with bits of shells imbedded in the stone. A shallow passage proceeds [downward], and a somewhat steeper one leads [up]. A low hands and knees passage enters from the [south]. ROOM 38 NEXT [You] are in an arched hall. A [coral passage] once continued up and east from here, but is now blocked by debris. The [air] smells of sea water.

[Back] ROOM 39 NEXT [You] are in a long [sloping] corridor with ragged sharp walls.

[Back] ROOM 40 NEXT [You] are in a long [sloping] corridor with ragged sharp walls.

[Back] ROOM 41 NEXT [You] are in a cul-de-sac about eight feet across.

[Back] ROOM 42 NEXT [You] are in a [maze] of [twisty] [little] [passages], [all] [alike]. [] ROOM 43 NEXT [You] are in a [maze] of [twisty] [little] [passages], [all] [alike]. ROOM 44 NEXT [You] are in a [maze] of [twisty] [little] [passages], [all] [alike]. ROOM 45 NEXT [You] are in a [maze] of [twisty] [little] [passages], [all] [alike]. ROOM 46 NEXT [You] are in a [maze] of [twisty] [little] [passages], [all] [alike]. ROOM 47 NEXT [You] are in a [maze] of [twisty] [little] [passages], [all] [alike]. ROOM 48 NEXT [You] are in a [maze] of [twisty] [little] [passages], [all] [alike]. ROOM 49 NEXT [You] are in a [maze] of [twisty] [little] [passages], [all] [alike]. ROOM 50 NEXT [You] are in a [maze] of [twisty] [little] [passages], [all] [alike]. ROOM 51 NEXT [You] are in a [maze] of [twisty] [little] [passages], [all] [alike]. ROOM 52 NEXT [You] are in a [maze] of [twisty] [little] [passages], [all] [alike]. ROOM 53 NEXT [You] are in a [maze] of [twisty] [little] [passages], [all] [alike]. ROOM 54 NEXT [You] are in a [maze] of [twisty] [little] [passages], [all] [alike]. ROOM 55 NEXT [You] are in a [maze] of [twisty] [little] [passages], [all] [alike]. ROOM 56 NEXT [You] are on the brink of a thirty foot pit with a massive orange column down one wall. You could [climb down] here but you could not get back up. The [maze] [continues] [at] [this] [level]. ROOM 57 NEXT [You] are in the Pirate's den. It is very messy and smells awful. There is a black Jolly Rodger flag hanging from the ceiling -- too high to reach. There are exits leading [east], [west], [south], [north], [up] and [down]. ROOM 58 NEXT [You] are in bedquilt, a long [east]/[west] passage with [holes] [everywhere]. To explore at random select [north], [south], [up] or [down]. ROOM 59 NEXT [You] are in an anteroom leading to a [large passage] to the east. Small passages go [west] and [up]. The remnants of recent digging are evident. A sign in midair here says:

Cave under construction beyond this point.
Proceed at your own risk.

Witt construction company
ROOM 60 NEXT [You] are at Witt's end. [Passages] [lead] [off] [in] [ALL] [directions]. ROOM 61 NEXT [You] are in a large low circular chamber whose floor is an immense slab fallen from the ceiling (slab room). [East] and [west] there once were large passages, but they are now filled with boulders. Low small passages go [north] and [south], and the south one quickly bends [west] around the boulders. ROOM 62 NEXT [You] are in a room whose walls resemble swiss cheese. Obvious passages go [west], [east], [northeast], and [northwest]. Part of the room is occupied by a large bedrock [block]. ROOM 63 NEXT [You] are in a tall [east]-[west] canyon. A [low tight crawl] goes 3 feet north and seems to open up. ROOM 64 NEXT [You] are at a wide place in a very tight [north]-[south] canyon. ROOM 65 NEXT [You] are at the east end of the twopit room. The floor here is littered with thin rock slabs, which make it easy to [descend] the pits. There is a [path] here bypassing the pits to connect passages from [east] and [west]. There are holes all over, but the only big one is on the wall directly over the [west pit] where you can't get at it. ROOM 66 NEXT [You] are at the west end of the twopit room. There is a large [hole] in the wall above the [pit] at this end of the room.

A [path] leads around the pits to the east. ROOM 67 NEXT [You] are at the bottom of the eastern pit in the [twopit room]. ROOM 68 NEXT [You] are at the bottom of the western pit in the [twopit room]. There is a large [hole] in the wall about 25 feet above you. ROOM 69 NEXT [You] are in a long, narrow corridor stretching out of sight to the [west]. At the [eastern end] is a hole through which you can see a [profusion of leaves]. ROOM 70 NEXT EOF my @room_links = <pluvialis sauatarola. Its belly is quite black -- hence, the name: black-bellied plover. It also has white plumage with a white stripe extending across its forehead, around its crown and nape and down the sides of its breast. Its undertail is white. Its call is a drawn-out, mournful, three note whistle with the second note lower pitched, like plee - o - ee.

This particular plover seems quite happy and is singing cheerfully. ITEM 'caged bird' NEXT There is a [little bird] inside the wicker cage. # The bird is a black-bellied plover (rhymes with "lover" not "clover"). Its Latin name is pluvialis sauatarola. Its belly is quite black -- hence, the name: black-bellied plover. It also has white plumage with a white stripe extending across its forehead, around its crown and nape and down the sides of its breast. Its undertail is white. Its call is a drawn-out, mournful, three note whistle with the second note lower pitched, like plee - o - ee.

The bird doesn't appear to like the cage because it has stopped singing. ITEM 'wicker cage' NEXT There is a small [wicker cage] discarded nearby. # The wicker cage is a fairly simple design with an opening on the top. ITEM 'green snake' NEXT A [huge green fierce snake] bars the way! # The snake is about 8 feet long and about 10 inches in diameter. It has raised its head up and is following you with its eyes. It is hissing at you and its forked tongue is darting in and out of its mouth with every hiss. ITEM 'gold nugget' NEXT There is a large sparkling [nugget of gold] here! # The nugget weighs about two pounds and is worth a [lot of money]. ITEM 'diamonds' NEXT There are several [diamonds] here! # The diamonds are about 100 carats each and are perfectly clear. ITEM 'silver bars' NEXT There are [bars of silver] here! # There are four silver bars -- each weighing about 5 pounds. ITEM 'jewelry' NEXT There is [precious jewelry] here! # There are several necklaces and bracelets made of gold and silver. Each of the pieces also has jewels set into the metal. This stuff didn't come out of a Cracker Jack box -- by any means! ITEM 'rare coins' NEXT There are many [rare coins] here! # The coins are all quite old and made of gold and silver. ITEM 'giant clam' NEXT There is an enormous [clam] here with its shell tightly closed. # The clam is about 4 feet across and is quite heavy. ITEM 'giant oyster' NEXT There is an enormous [oyster] here with its shell tightly closed. # Interesting. There seems to be something [written] on the underside of the oyster. ITEM 'pearl' NEXT Off to one side lies a [glistening pearl]! # The pearl is perfectly round and about six inches in diameter. It is quite shiny and you can see your [reflection] in it. ITEM 'magazine' NEXT There is a recent issue of ["Spelunker Today" magazine] here. # The magazine is a slick high-gloss production with numerous cave [pictures] and a variety of [articles]. ITEM 'treasure chest' NEXT The pirate's [treasure chest] is here! # The pirate's chest is made of gold with jewels set into its top. ITEM 'pool of oil' NEXT There is a small [pool of oil] in one corner of the pit. # Lord only knows where this oil came from. But here it is, in a little pool in a depression at one side of this pit. ITEM 'little plant' NEXT There is a [tiny little plant] in the pit, murmuring "Water, water..." # The plant cries out, Water... water, please... water. ITEM '12-foot beanstalk' NEXT A [12-foot-tall beanstalk] stretches out of the pit, bellowing "Water!!!" # The plant bellows, Water!... water, please!... water!

[Climb it] ITEM 'huge beanstalk' NEXT There is a [gigantic beanstalk] stretching all the way up to the hole. # The plant has almost filled the bottom of the pit. It stretches all the way up to the hole in the wall of the twopit room.

[Climb it] ITEM 29 NEXT EOF @item_desc[101..200] = <'; } sub href_start_over() { return ''; } { my $dummy_number = 0; sub href_dummy() { ++$dummy_number; return qq(); } } sub href_myself() { my $tmp = $flag[$f{'VIEWING_SELF'}]; $flag[$f{'VIEWING_SELF'}] = 1; my $text = pack_args(); $flag[$f{'VIEWING_SELF'}] = $tmp; return href_it($text); } sub href_go($) { return href_say('WITT') if ($_[0] == -1); my $rm_no = $RoomNumber; my $f7tmp = $flag[$f{'FIENDISH_7'}]; $RoomNumber = $_[0]; $flag[$f{'FIENDISH_7'}] = 0; my $text = pack_args(); $RoomNumber = $rm_no; $flag[$f{'FIENDISH_7'}] = $f7tmp; return href_it($text); } sub href_go_view($) { my $rm_no = $RoomNumber; my $vtmp = $flag[$f{'VIEW_ROOM'}]; my $f7tmp = $flag[$f{'FIENDISH_7'}]; $RoomNumber = $_[0]; $flag[$f{'VIEW_ROOM'}] = 1; $flag[$f{'FIENDISH_7'}] = 0; $RoomNumber = $_[0]; my $text = pack_args(); $RoomNumber = $rm_no; $flag[$f{'VIEW_ROOM'}] = $vtmp; $flag[$f{'FIENDISH_7'}] = $f7tmp; return href_it($text); } sub href_ex($) { my $tmp = $CurrentlyExamining; $CurrentlyExamining = $_[0]; my $text = pack_args(); $CurrentlyExamining = $tmp; return href_it($text); } sub href_get_bird(); sub href_get_caged_bird(); sub href_pickup($) { ## This assumes that the item is actually here! if ($_[0] == $n{'green snake'}) { return href_say('RIDI'); } if ($_[0] == $n{'pool of oil'}) { return href_toggle_bottle(); } elsif ($_[0] == $n{'little plant'} || $_[0] == $n{'12-foot beanstalk'} || $_[0] == $n{'huge beanstalk'}) { return href_say('2PRT'); } elsif ($NumberOfItemsCarried >= 7) { return href_say('BULK'); } elsif ($_[0] == $n{'cheerful bird'}) { return href_get_bird(); } elsif ($_[0] == $n{'caged bird'}) { return href_get_caged_bird(); } elsif ($_[0] == $n{'wicker cage'} && item_in_room($n{'caged bird'})) { return href_get_caged_bird(); } my $tmp = $argsPickingUpThisItem; $argsPickingUpThisItem = $_[0]; $ihas_by_num[$_[0]] = 1; my $text = pack_args(); $argsPickingUpThisItem = $tmp; $ihas_by_num[$_[0]] = 0; return href_it($text); } sub href_free_caged_bird(); sub href_drop_caged_bird(); sub href_vanish_treas($); sub href_drop($) { ## This assumes that the player is actually carrying the item! if ($_[0] == $n{'caged bird'}) { return href_free_caged_bird(); } elsif ($_[0] == $n{'wicker cage'} && $ihas_by_num[$n{'caged bird'}]) { return href_drop_caged_bird(); } elsif ($RoomNumber == $r{'inside building'} and is_treas($_[0])) { return href_vanish_treas($_[0]); } elsif ($RoomNumber == $r{'witt\'s end'} and $_[0] == $n{'magazine'}) { return href_vanish_magazine($_[0]); } my $tmp = $argsDroppingThisItem; $argsDroppingThisItem = $_[0]; $ihas_by_num[$_[0]] = 0; my $text = pack_args(); $argsDroppingThisItem = $tmp; $ihas_by_num[$_[0]] = 1; return href_it($text); } sub href_say($) { my $tmp = $CurrentlyMessaging; $CurrentlyMessaging = $_[0]; my $text = pack_args(); $CurrentlyMessaging = $tmp; return href_it($text); } sub href_vanish_treas($) { ## Drop a treasure inside the building and it vanishes, for now... ## Assumes that $_[0] is a treasure and that we're in the building. my $nountmp = $NounDollar; $ihas_by_num[$_[0]] = 0; $NounDollar = $_[0]; my $text = href_say('VTRE'); $ihas_by_num[$_[0]] = 1; $NounDollar = $nountmp; } sub href_vanish_magazine($) { ## Drop the magazine inside Witt's End and it vanishes, for now... ## Assumes that $_[0] is the magazine and that we're at Witt's End. my $nountmp = $NounDollar; $ihas_by_num[$_[0]] = 0; $NounDollar = $_[0]; my $text = href_say('VMWE'); $ihas_by_num[$_[0]] = 1; $NounDollar = $nountmp; return $text; } sub href_stream() { if ($ihas_by_num[$n{'empty bottle'}]) { $ihas_by_num[$n{'empty bottle'}] = 0; $ihas_by_num[$n{'bottle of water'}] = 1; $flag[$f{'MSG_GOT_WATER'}] = 1; $flag[$f{'VIEW_ROOM'}] = 1; my $text = pack_args(); $ihas_by_num[$n{'empty bottle'}] = 1; $ihas_by_num[$n{'bottle of water'}] = 0; $flag[$f{'MSG_GOT_WATER'}] = 0; $flag[$f{'VIEW_ROOM'}] = 0; return href_it($text); } else { return (rand(100) < 50)? href_ex($n{'stream'}): href_say('H2O'); } } sub href_slit() { if ($flag[$f{'SLIT_SHOWN'}]) { return href_go($r{'outside grate'}); } $flag[$f{'SLIT_SHOWN'}] = 1; my $text = href_say('SLIT'); $flag[$f{'SLIT_SHOWN'}] = 0; return $text; } sub href_lamp_batt() { href_say('LBTT'); } sub href_lamp_toggle() { ## Turn on or off the lamp either while carrying it (case 1) ## or just when it's in the same room with you (case 2). my $text; my $tmp = $CurrentlyExamining; my $lit_lamp = $flag[$f{'MSG_LIT_LAMP'}]; my $ext_lamp = $flag[$f{'MSG_EXT_LAMP'}]; my $view = $flag[$f{'VIEW_ROOM'}]; if (can_see_room() == 0) { ## If you were in the dark, then view the room! $flag[$f{'VIEW_ROOM'}] = 1; } $CurrentlyExamining = 0; $flag[$f{'MSG_LIT_LAMP'}] = 0; $flag[$f{'MSG_EXT_LAMP'}] = 0; if ($ihas_by_num[$n{'on lamp'}] or $ihas_by_num[$n{'off lamp'}]) { $ihas_by_num[$n{'on lamp'}] = ! $ihas_by_num[$n{'on lamp'}]; $ihas_by_num[$n{'off lamp'}] = ! $ihas_by_num[$n{'off lamp'}]; if ($ihas_by_num[$n{'on lamp'}]) { $flag[$f{'MSG_LIT_LAMP'}] = 1; } else { $flag[$f{'MSG_EXT_LAMP'}] = 1; } $text = pack_args(); $ihas_by_num[$n{'on lamp'}] = ! $ihas_by_num[$n{'on lamp'}]; $ihas_by_num[$n{'off lamp'}] = ! $ihas_by_num[$n{'off lamp'}]; } else { my $pickuptmp = $argsPickingUpThisItem; my $droptmp = $argsDroppingThisItem; if (item_in_room($n{'on lamp'})) { $argsPickingUpThisItem = $n{'on lamp'}; $argsDroppingThisItem = $n{'off lamp'}; $flag[$f{'MSG_EXT_LAMP'}] = 1; } else { $argsPickingUpThisItem = $n{'off lamp'}; $argsDroppingThisItem = $n{'on lamp'}; $flag[$f{'MSG_LIT_LAMP'}] = 1; } $text = pack_args(); $argsPickingUpThisItem = $pickuptmp; $argsDroppingThisItem = $droptmp; } $CurrentlyExamining = $tmp; $flag[$f{'MSG_LIT_LAMP'}] = $lit_lamp; $flag[$f{'MSG_EXT_LAMP'}] = $ext_lamp; $flag[$f{'VIEW_ROOM'}] = $view; return href_it($text); } sub href_eat_food() { ## make sure the food gets eaten whether he's carrying it or not! my $tmp = $argsPickingUpThisItem; my $tmp2 = $CurrentlyExamining; $argsPickingUpThisItem = $n{'food'}; $CurrentlyExamining = 0; $ihas_by_num[$n{'food'}] = 0; my $text = href_say('EATF'); $argsPickingUpThisItem = $tmp; $CurrentlyExamining = $tmp2; $ihas_by_num[$n{'food'}] = 1; return $text; } sub href_toggle_bottle() { ## Fill or empty the bottle either while carrying it (case 1) ## or, when it's in the same room with you, do nothing yet (case 2). my $text; if ($ihas_by_num[$n{'bottle of water'}]) { if ($RoomNumber == $r{'west pit'}) { return href_water_plant(); } $ihas_by_num[$n{'bottle of water'}] = 0; $ihas_by_num[$n{'empty bottle'}] = 1; $flag[$f{'MSG_SPILL_WATER'}] = 1; $flag[$f{'VIEW_ROOM'}] = 1; $text = pack_args(); $flag[$f{'MSG_SPILL_WATER'}] = 0; $flag[$f{'VIEW_ROOM'}] = 0; $ihas_by_num[$n{'bottle of water'}] = 1; $ihas_by_num[$n{'empty bottle'}] = 0; return href_it($text); } elsif ($ihas_by_num[$n{'bottle of oil'}]) { if ($RoomNumber == $r{'west pit'}) { return href_oil_plant(); } $ihas_by_num[$n{'bottle of oil'}] = 0; $ihas_by_num[$n{'empty bottle'}] = 1; $flag[$f{'MSG_SPILL_OIL'}] = 1; $flag[$f{'VIEW_ROOM'}] = 1; $text = pack_args(); $flag[$f{'MSG_SPILL_OIL'}] = 0; $flag[$f{'VIEW_ROOM'}] = 0; $ihas_by_num[$n{'bottle of oil'}] = 1; $ihas_by_num[$n{'empty bottle'}] = 0; return href_it($text); } elsif ($ihas_by_num[$n{'empty bottle'}]) { if ($RoomNumber == $r{'valley'} or $RoomNumber == $r{'slit in streambed'} or $RoomNumber == $r{'bottom of small pit'} or $RoomNumber == $r{'inside building'}) { $ihas_by_num[$n{'bottle of water'}] = 1; $ihas_by_num[$n{'empty bottle'}] = 0; $flag[$f{'MSG_GOT_WATER'}] = 1; $flag[$f{'VIEW_ROOM'}] = 1; $text = href_it(pack_args()); $flag[$f{'MSG_GOT_WATER'}] = 0; $flag[$f{'VIEW_ROOM'}] = 0; $ihas_by_num[$n{'bottle of water'}] = 0; $ihas_by_num[$n{'empty bottle'}] = 1; } elsif ($RoomNumber == $r{'east pit'}) { $ihas_by_num[$n{'bottle of oil'}] = 1; $ihas_by_num[$n{'empty bottle'}] = 0; $flag[$f{'MSG_GOT_OIL'}] = 1; $flag[$f{'VIEW_ROOM'}] = 1; $text = href_it(pack_args()); $flag[$f{'MSG_GOT_OIL'}] = 0; $flag[$f{'VIEW_ROOM'}] = 0; $ihas_by_num[$n{'bottle of oil'}] = 0; $ihas_by_num[$n{'empty bottle'}] = 1; } else { my $tmp = $NounDollar; $NounDollar = $n{'empty bottle'}; $text = href_say('DWHA'); $NounDollar = $tmp; } return $text; } else { return href_dummy(); } } sub href_water_plant() { ## Empty the water bottle at location 'west pit'. my $medtmp = $flag[$f{'MED_PLANT'}]; my $hugetmp = $flag[$f{'HUGE_PLANT'}]; my $picktmp = $argsPickingUpThisItem; my $droptmp = $argsDroppingThisItem; $ihas_by_num[$n{'bottle of water'}] = 0; $ihas_by_num[$n{'empty bottle'}] = 1; $flag[$f{'VIEW_ROOM'}] = 1; if (item_in_room($n{'little plant'})) { $flag[$f{'MSG_WATER_LITTLE'}] = 1; $argsPickingUpThisItem = $n{'little plant'}; $argsDroppingThisItem = $n{'12-foot beanstalk'}; $flag[$f{'MED_PLANT'}] = 1; } elsif (item_in_room($n{'12-foot beanstalk'})) { $flag[$f{'MSG_WATER_MED'}] = 1; $argsPickingUpThisItem = $n{'12-foot beanstalk'}; $argsDroppingThisItem = $n{'huge beanstalk'}; $flag[$f{'MED_PLANT'}] = 0; $flag[$f{'HUGE_PLANT'}] = 1; } elsif (item_in_room($n{'huge beanstalk'})) { $flag[$f{'MSG_WATER_HUGE'}] = 1; $argsPickingUpThisItem = $n{'huge beanstalk'}; $flag[$f{'HUGE_PLANT'}] = 0; } else { $flag[$f{'MSG_SPILL_WATER'}] = 1; } $text = pack_args(); $flag[$f{'MSG_WATER_LITTLE'}] = 0; $flag[$f{'MSG_WATER_MED'}] = 0; $flag[$f{'MSG_WATER_HUGE'}] = 0; $flag[$f{'MED_PLANT'}] = $medtmp; $flag[$f{'HUGE_PLANT'}] = $hugetmp; $flag[$f{'MSG_SPILL_WATER'}] = 0; $flag[$f{'VIEW_ROOM'}] = 0; $ihas_by_num[$n{'bottle of water'}] = 1; $ihas_by_num[$n{'empty bottle'}] = 0; $argsPickingUpThisItem = $picktmp; $argsDroppingThisItem = $droptmp; return href_it($text); } sub href_oil_plant() { ## Empty the water bottle at location 'west pit'. $ihas_by_num[$n{'bottle of oil'}] = 0; $ihas_by_num[$n{'empty bottle'}] = 1; $flag[$f{'VIEW_ROOM'}] = 1; if (item_in_room($n{'little plant'}) or item_in_room($n{'12-foot beanstalk'}) or item_in_room($n{'huge beanstalk'})) { $flag[$f{'MSG_OIL_PLANT'}] = 1; } else { $flag[$f{'MSG_SPILL_OIL'}] = 1; } $text = pack_args(); $flag[$f{'MSG_OIL_PLANT'}] = 0; $flag[$f{'MSG_SPILL_OIL'}] = 0; $flag[$f{'VIEW_ROOM'}] = 0; $ihas_by_num[$n{'bottle of oil'}] = 1; $ihas_by_num[$n{'empty bottle'}] = 0; return href_it($text); } sub href_a_grate() { ## 'steel grate' from above my $grate_is_open = $flag[$f{'GRATE_OPEN'}]; if ($grate_is_open) { return href_go($r{'below the grate'}); } elsif ($ihas_by_num[$n{'keys'}]) { $flag[$f{'GRATE_OPEN'}] = 1; $flag[$f{'MSG_GRATE_OPEN'}] = 1; my $text = pack_args(); $flag[$f{'GRATE_OPEN'}] = 0; $flag[$f{'MSG_GRATE_OPEN'}] = 0; return href_it($text); } else { return href_ex($n{'grate down'}); } } sub href_b_grate() { ## 'steel grate' from below my $grate_is_open = $flag[$f{'GRATE_OPEN'}]; if ($grate_is_open) { return href_ex($n{'grate up'}); } else { my $tmp = $NounDollar; $NounDollar = $n{'grate up'}; my $text = href_say('DWHA'); $NounDollar = $tmp; return $text; } } sub href_c_grate() { ## 'surface' from below my $grate_is_open = $flag[$f{'GRATE_OPEN'}]; if ($grate_is_open) { return href_go($r{'outside grate'}); } else { return href_say('SURF'); } } sub href_xyzzy() { if ($RoomNumber == $r{'inside building'} or $RoomNumber == $r{'debris room'}) { $RoomNumber = $r{'inside building'}+$r{'debris room'} - $RoomNumber; my $tmp = $flag[$f{'MSG_TRANSPORT'}]; my $tmp2 = $flag[$f{'VIEW_ROOM'}]; $flag[$f{'MSG_TRANSPORT'}] = 1; $flag[$f{'VIEW_ROOM'}] = 1; my $text = pack_args(); $RoomNumber = $r{'inside building'}+$r{'debris room'} - $RoomNumber; $flag[$f{'MSG_TRANSPORT'}] = $tmp; $flag[$f{'VIEW_ROOM'}] = $tmp2; return href_it($text); } else { return href_say('MGNO'); } } sub href_get_bird() { if ($ihas_by_num[$n{'rusty wand'}]) { $flag[$f{'BIRD_FLAG'}] = ! $flag[$f{'BIRD_FLAG'}]; my $text = href_say( $flag[$f{'BIRD_FLAG'}] ? 'BRD1': 'BRD2' ); $flag[$f{'BIRD_FLAG'}] = ! $flag[$f{'BIRD_FLAG'}]; return $text; } elsif ($ihas_by_num[$n{'wicker cage'}]) { my $picktmp = $argsPickingUpThisItem; my $birdtmp = $flag[$f{'BIRD_FLAG'}]; $argsPickingUpThisItem = $n{'cheerful bird'}; $ihas_by_num[$n{'caged bird'}] = 1; $flag[$f{'MSG_GOT_BIRD'}] = 1; $flag[$f{'BIRD_FLAG'}] = 1; if ($CurrentlyExamining == $n{'cheerful bird'}) { $CurrentlyExamining = $n{'caged bird'}; } my $text = pack_args(); $argsPickingUpThisItem = $picktmp; $ihas_by_num[$n{'caged bird'}] = 0; $flag[$f{'MSG_GOT_BIRD'}] = 0; $flag[$f{'BIRD_FLAG'}] = $birdtmp; if ($CurrentlyExamining == $n{'caged bird'}) { $CurrentlyExamining = $n{'cheerful bird'}; } return href_it($text); } else { return href_say('BRD3'); } } sub href_get_caged_bird() { ## Both the cage and the bird are in the current room. ## We have to pick both of them up simultaneously. ## So, save the whole state and make drastic changes! my $saved_state = pack_args(); my $picktmp = $argsPickingUpThisItem; $ihas_by_num[$n{'caged bird'}] = 1; $argsPickingUpThisItem = $n{'caged bird'}; ## This line makes changes to the actual CURRENT state! reunpack_args(pack_args()); $ihas_by_num[$n{'wicker cage'}] = 1; $argsPickingUpThisItem = $n{'wicker cage'}; my $next = pack_args(); ## Restore the saved state. reunpack_args($saved_state); $argsPickingUpThisItem = $picktmp; return href_it($next); } sub href_drop_caged_bird() { ## Both the cage and the bird are in our possession. ## We have to drop both of them simultaneously. ## So, save the whole state and make drastic changes! my $saved_state = pack_args(); my $droptmp = $argsDroppingThisItem; $ihas_by_num[$n{'caged bird'}] = 0; $argsDroppingThisItem = $n{'caged bird'}; ## This line makes changes to the actual CURRENT state! reunpack_args(pack_args()); $ihas_by_num[$n{'wicker cage'}] = 0; $argsDroppingThisItem = $n{'wicker cage'}; $flag[$f{'MSG_DROP_CAGE'}] = 1; $flag[$f{'MSG_VIEW_ROOM'}] = 1; my $next = pack_args(); ## Restore the saved state. reunpack_args($saved_state); $argsDroppingThisItem = $droptmp; return href_it($next); } sub href_free_caged_bird() { ## Open the cage and let out the bird. my $droptmp = $argsDroppingThisItem; my $picktmp = $argsPickingUpThisItem; my $viewtmp = $flag[$f{'VIEW_ROOM'}]; $ihas_by_num[$n{'caged bird'}] = 0; $argsDroppingThisItem = $n{'cheerful bird'}; $flag[$f{'MSG_FREE_BIRD'}] = 1; $flag[$f{'VIEW_ROOM'}] = 1; if (item_in_room($n{'green snake'})) { ## The bird drives away the snake! $argsPickingUpThisItem = $n{'green snake'}; $flag[$f{'MSG_NO_SNAKE'}] = 1; } my $text = pack_args(); $ihas_by_num[$n{'caged bird'}] = 1; $argsDroppingThisItem = $droptmp; $argsPickingUpThisItem = $picktmp; $flag[$f{'MSG_FREE_BIRD'}] = 0; $flag[$f{'MSG_NO_SNAKE'}] = 0; $flag[$f{'VIEW_ROOM'}] = $viewtmp; return href_it($text); } sub href_go_snake($) { if ( ! item_in_room($n{'green snake'}) ) { return href_go($_[0]); } else { my $text; my $hnt1tmp = $flag[$f{'SNAKE_HNT1'}]; my $hnt2tmp = $flag[$f{'SNAKE_HNT2'}]; ## Increment the two-bit hint counter. $flag[$f{'SNAKE_HNT1'}] = ($hnt1tmp | $hnt2tmp); $flag[$f{'SNAKE_HNT2'}] = ($hnt1tmp | ! $hnt2tmp); if ($hnt1tmp and ! $hnt2tmp) { ## Give the hint. if ($ihas_by_num[$n{'caged bird'}]) { $text = href_say('SNBH'); } else { $text = href_say('SNKH'); } } else { if (rand(100) < 50) { $text = href_say('SNK1'); } elsif (rand(50) < 25) { $text = href_say('SNK2'); } else { $text = href_say('SNK3'); } } $flag[$f{'SNAKE_HNT1'}] = $hnt1tmp; $flag[$f{'SNAKE_HNT2'}] = $hnt2tmp; return $text; } } sub href_jump_fissure() { if ($flag[$f{'CRYSTAL_BRIDGE'}]) { return href_say('JBRI'); } elsif ($flag[$f{'TRIED_JUMP'}]) { $flag[$f{'MSG_JUMP_TO_DEATH'}] = 1; my $text = href_it(pack_args()); $flag[$f{'MSG_JUMP_TO_DEATH'}] = 0; return $text; } else { $flag[$f{'TRIED_JUMP'}] = 1; my $text = href_say('JFIS'); $flag[$f{'TRIED_JUMP'}] = 0; return $text; } } sub href_go_bridge() { if ($RoomNumber == $r{'east of fissure'}) { return href_go_view($r{'west of fissure'}); } elsif ($RoomNumber == $r{'west of fissure'}) { return href_go_view($r{'east of fissure'}); } else { stop_game; } } sub href_wave_rod() { if ($ihas_by_num[$n{'rusty wand'}] == 0) { return href_dummy(); } elsif (($RoomNumber==$r{'east of fissure'} or $RoomNumber==$r{'west of fissure'}) and $flag[$f{'CRYSTAL_BRIDGE'}]==0) { ## The bridge will appear if we wave the rod here! my $viewtmp = $flag[$f{'VIEW_ROOM'}]; $flag[$f{'CRYSTAL_BRIDGE'}] = 1; $flag[$f{'VIEW_ROOM'}] = 1; my $text = pack_args(); $flag[$f{'CRYSTAL_BRIDGE'}] = 0; $flag[$f{'VIEW_ROOM'}] = $viewtmp; return href_it($text) . "For some reason, you feel like waving it around."; } elsif (rand(100) < 50) { ## The bridge will NOT appear if we wave the rod here. ## Give a cute message if the snake is here. my $text = (item_in_room[$n{'green snake'}])? 'MGNS': 'MGNO'; return href_say($text) . "For some reason, you feel like waving it around."; } else { ## Don't even bother to give the message. return href_dummy(); } } sub href_go_nugget($) { if ($ihas_by_num[$n{'gold nugget'}]) { return href_say('CLNU'); } else { return href_go_view($_[0]); } } sub href_go_clam($) { my $nountmp = $NounDollar; if ($ihas_by_num[$n{'giant clam'}]) { $NounDollar = $n{'giant clam'}; } elsif ($ihas_by_num[$n{'giant oyster'}]) { $NounDollar = $n{'giant oyster'}; } else { return href_go($_[0]); } my $text = href_say('OYMV'); $NounDollar = $nountmp; return $text; } sub href_go_maze($) { my $f1tmp = $flag[$f{'FIENDISH_1'}]; my $f2tmp = $flag[$f{'FIENDISH_2'}]; my $f3tmp = $flag[$f{'FIENDISH_3'}]; my $f4tmp = $flag[$f{'FIENDISH_4'}]; my $f5tmp = $flag[$f{'FIENDISH_5'}]; my $f6tmp = $flag[$f{'FIENDISH_6'}]; my $f7tmp = $flag[$f{'FIENDISH_7'}]; my $randn = int 16+rand(2); $flag[$f{'FIENDISH_1'}] = ($randn & (1<<0))? 1: 0; $flag[$f{'FIENDISH_2'}] = ($randn & (1<<1))? 1: 0; $flag[$f{'FIENDISH_3'}] = ($randn & (1<<2))? 1: 0; $flag[$f{'FIENDISH_4'}] = ($randn & (1<<3))? 1: 0; $flag[$f{'FIENDISH_5'}] = ($randn & (1<<4))? 1: 0; $flag[$f{'FIENDISH_6'}] = (rand(100) < 50)? 1: 0; $flag[$f{'FIENDISH_7'}] = 1; ## indicates that we're in the maze my $text; if ($_[0] == -1) { $RoomNumber ^= $randn; $text = href_say('CNGO'); $RoomNumber ^= $randn; } else { $text = href_go($_[0] ^ $randn); } $flag[$f{'FIENDISH_1'}] = $f1tmp; $flag[$f{'FIENDISH_2'}] = $f2tmp; $flag[$f{'FIENDISH_3'}] = $f3tmp; $flag[$f{'FIENDISH_4'}] = $f4tmp; $flag[$f{'FIENDISH_5'}] = $f5tmp; $flag[$f{'FIENDISH_6'}] = $f6tmp; $flag[$f{'FIENDISH_7'}] = $f7tmp; return $text; } sub href_maze_de($) { my $f1tmp = $flag[$f{'FIENDISH_1'}]; my $f2tmp = $flag[$f{'FIENDISH_2'}]; my $f3tmp = $flag[$f{'FIENDISH_3'}]; my $f4tmp = $flag[$f{'FIENDISH_4'}]; my $f5tmp = $flag[$f{'FIENDISH_5'}]; my $f6tmp = $flag[$f{'FIENDISH_6'}]; my $f7tmp = $flag[$f{'FIENDISH_7'}]; my $randn = int rand(32); $flag[$f{'FIENDISH_1'}] = ($randn & (1<<0))? 1: 0; $flag[$f{'FIENDISH_2'}] = ($randn & (1<<1))? 1: 0; $flag[$f{'FIENDISH_3'}] = ($randn & (1<<2))? 1: 0; $flag[$f{'FIENDISH_4'}] = ($randn & (1<<3))? 1: 0; $flag[$f{'FIENDISH_5'}] = ($randn & (1<<4))? 1: 0; $flag[$f{'FIENDISH_6'}] = (rand(100) < 50)? 1: 0; $flag[$f{'FIENDISH_7'}] = 1; $flag[$f{'MAZE_DEADEND'}] = 1; $RoomNumber ^= $randn; my $text = pack_args(); $RoomNumber ^= $randn; $flag[$f{'FIENDISH_1'}] = $f1tmp; $flag[$f{'FIENDISH_2'}] = $f2tmp; $flag[$f{'FIENDISH_3'}] = $f3tmp; $flag[$f{'FIENDISH_4'}] = $f4tmp; $flag[$f{'FIENDISH_5'}] = $f5tmp; $flag[$f{'FIENDISH_6'}] = $f6tmp; $flag[$f{'FIENDISH_7'}] = $f7tmp; $flag[$f{'MAZE_DEADEND'}] = 0; return href_it($text); } sub href_maze_back($) { if ($flag[$f{'FIENDISH_7'}]) { return href_dummy(); } my $text = href_go($_[0]); return '

' . $text . 'Back'; } sub href_go_bq($) { if ($_[0] == 0) { if (rand(100) < 33) { return href_go(-1); ## $r{'north-south canyon'}); } elsif (rand(100) < 50) { return href_go(-1); ## $r{'junction of canyons'}); } else { return href_go(-1); ## $r{'large low room'}); } } else { return href_say('BQCR'); } } sub href_go_witt() { my $f1tmp = $flag[$f{'FIENDISH_1'}]; my $f2tmp = $flag[$f{'FIENDISH_2'}]; my $f3tmp = $flag[$f{'FIENDISH_3'}]; my $f4tmp = $flag[$f{'FIENDISH_4'}]; my $f5tmp = $flag[$f{'FIENDISH_5'}]; my $f6tmp = $flag[$f{'FIENDISH_6'}]; my $randn = int rand(32); $flag[$f{'FIENDISH_1'}] = ($randn & (1<<0))? 1: 0; $flag[$f{'FIENDISH_2'}] = ($randn & (1<<1))? 1: 0; $flag[$f{'FIENDISH_3'}] = ($randn & (1<<2))? 1: 0; $flag[$f{'FIENDISH_4'}] = ($randn & (1<<3))? 1: 0; $flag[$f{'FIENDISH_5'}] = ($randn & (1<<4))? 1: 0; $flag[$f{'FIENDISH_6'}] = (rand(100) < 50)? 1: 0; $RoomNumber ^= $randn; my $text = href_say('BQCR'); $RoomNumber ^= $randn; $flag[$f{'FIENDISH_1'}] = $f1tmp; $flag[$f{'FIENDISH_2'}] = $f2tmp; $flag[$f{'FIENDISH_3'}] = $f3tmp; $flag[$f{'FIENDISH_4'}] = $f4tmp; $flag[$f{'FIENDISH_5'}] = $f5tmp; $flag[$f{'FIENDISH_6'}] = $f6tmp; return $text; } sub href_go_witt_exit($) { if (rand(100) < 20) { return href_go($_[0]); } else { return href_go_witt(); } } sub href_behind_block() { if ($flag[$f{'BEHIND_BLOCK'}]) { my $text = href_go($r{'tall e-w canyon'}); return "

There is a small ${text}passage behind the block."; } elsif (rand(100) < 33) { $flag[$f{'BEHIND BLOCK'}] = 1; my $text = href_go($r{'tall e-w canyon'}); return "

You find a small ${text}passage behind the block!"; } else { return href_dummy() } } sub href_ex_twopit_hole() { if ($flag[$f{'HUGE_PLANT'}]) { return href_say('2PHH') } else { return href_say('2PNH') } } sub href_climb_bs() { if ($flag[$f{'HUGE_PLANT'}]) { $flag[$f{'MSG_CLIMB_HUGE'}] = 1; my $text = href_go_view($r{'long narrow corridor'}); $flag[$f{'MSG_CLIMB_HUGE'}] = 0; return $text; } else { $flag[$f{'MSG_CLIMB_MED'}] = 1; my $text = href_go_view($r{'w end of twopit room'}); $flag[$f{'MSG_CLIMB_MED'}] = 0; return $text; } } ##################################################### ## PROCESSING THE ARGUMENTS (in both directions) ## ##################################################### sub deal_with_fiendish() { my $randn = 0; $randn = ($randn << 1) | $flag[$f{'FIENDISH_5'}]; $randn = ($randn << 1) | $flag[$f{'FIENDISH_4'}]; $randn = ($randn << 1) | $flag[$f{'FIENDISH_3'}]; $randn = ($randn << 1) | $flag[$f{'FIENDISH_2'}]; $randn = ($randn << 1) | $flag[$f{'FIENDISH_1'}]; $RoomNumber ^= $randn; $flag[$f{'FIENDISH_1'}] = 0; $flag[$f{'FIENDISH_2'}] = 0; $flag[$f{'FIENDISH_3'}] = 0; $flag[$f{'FIENDISH_4'}] = 0; $flag[$f{'FIENDISH_5'}] = 0; $flag[$f{'FIENDISH_6'}] = 0; } sub pack_flags { my $table = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-+'; my $text = substr($table, ($_[0] & 0x3F), 1); $text .= substr($table, (($_[1]>>12) & 0x3F), 1); $text .= substr($table, (($_[1]>>6) & 0x3F), 1); $text .= substr($table, (($_[1]) & 0x3F), 1); return $text; } sub unpack_flags($) { stop_game if (length($_[0]) != 4); my $table = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-+'; my $text = $_[0]; my $byte = substr($text, 0, 1); my $fl_no = index($table, $byte); stop_game if ($fl_no < 0); my $flag; $byte = index($table, substr($text, 3, 1)); stop_game if ($byte < 0); $flag = $byte; $byte = index($table, substr($text, 2, 1)); stop_game if ($byte < 0); $flag |= $byte << 6; $byte = index($table, substr($text, 1, 1)); stop_game if ($byte < 0); $flag |= $byte << 12; for my $j (0 .. 17) { $flag[18*$fl_no + $j] = (0 != ($flag & (1 << 17-$j))); } } sub pack_args() { my $text = "rm=${RoomNumber}"; my $pack_inv = 0; foreach my $i (1..$MAXITEM-1) { if ($ihas_by_num[$i]) { $pack_inv = $pack_inv * $MAXITEM + $i; if ($pack_inv >= 1_000_000 / $MAXITEM) { $text .= "&in=${pack_inv}"; $pack_inv = 0; } } } $text .= "&in=${pack_inv}" if ($pack_inv != 0); ## A little bit of extra compression; otherwise, we get a lot ## of argument strings with ...rh=6&rh=9&rh=10&rh=14...! my $empty_rooms = 0; foreach my $i (0 .. $MAXROOM-1) { my $orig_rmcnt = $room_contents[$i]; if ($argsPickingUpThisItem || $argsDroppingThisItem) { my $tmp1 = $room_contents[$i]; my $tmp2 = ($i == $RoomNumber)? $argsDroppingThisItem: 0; while ($tmp1) { if ($tmp1 % $MAXITEM != $argsPickingUpThisItem) { $tmp2 *= $MAXITEM; $tmp2 += $tmp1 % $MAXITEM; } $tmp1 /= $MAXITEM; } ## Unfortunately, to make the "item_in_room" code work, ## we have to re-reverse the contents of the room so that ## other rooms' contents don't magically change. If that ## happens, items start disappearing from inventories. $room_contents[$i] = 0; while ($tmp2) { $room_contents[$i] *= $MAXITEM; $room_contents[$i] += $tmp2 % $MAXITEM; $tmp2 /= $MAXITEM; } } if ($room_contents[$i] != $item_home[$i]) { if ($room_contents[$i] != 0) { my $rh = $room_contents[$i] * $MAXROOM + $i; $text .= "&rh=${rh}"; } else { $empty_rooms = $empty_rooms * $MAXROOM + $i; if ($empty_rooms >= 1_000_000 / $MAXROOM) { $text .= "&er=${empty_rooms}"; $empty_rooms = 0; } } } $room_contents[$i] = $orig_rmcnt; } if ($empty_rooms != 0) { $text .= "&er=${empty_rooms}"; } foreach my $fl_no (0 .. ($MAXFLAG/18)-1) { my $fl = 0; foreach $j (0 .. 17) { $fl = ($fl << 1) + ($flag[18*$fl_no + $j] != 0); } if ($fl != 0) { $text .= "&f="; $text .= pack_flags($fl_no, $fl); } } if ($CurrentlyExamining) { $text .= "&x=${CurrentlyExamining}"; } if ($CurrentlyMessaging) { $text .= "&msg=${CurrentlyMessaging}"; } if ($NounDollar) { $text .= "&dw=${NounDollar}"; } if ($DarknessCounter) { $text .= "&dc=${DarknessCounter}"; } return "advent.cgi?" . $text; } sub unpack_args { my $cgi_args = join('&', @_); @_ = split(/&/, $cgi_args); foreach my $i (@_) { my $varname; my $vardata; ($varname, $vardata) = split(/=/, $i); if ($varname eq "rm") { $RoomNumber = $vardata; } elsif ($varname eq "in") { my $invent_compact = $vardata; while ($invent_compact != 0) { stop_game if ($ihas_by_num[$invent_compact % $MAXITEM]); $ihas_by_num[$invent_compact % $MAXITEM] = 1; ++$NumberOfItemsCarried; $invent_compact /= $MAXITEM; } } elsif ($varname eq "rh") { my $rm_no = $vardata % $MAXROOM; my $invent_compact = $vardata / $MAXROOM; if ($room_contents[$rm_no] == $item_home[$rm_no]) { $room_contents[$rm_no] = 0; } while ($invent_compact != 0) { $room_contents[$rm_no] *= $MAXITEM; $room_contents[$rm_no] += $invent_compact % $MAXITEM; $invent_compact /= $MAXITEM; } } elsif ($varname eq "er") { ## All these rooms are completely empty. while ($vardata != 0) { $room_contents[$vardata % $MAXROOM] = 0; $vardata /= $MAXROOM; } } elsif ($varname eq "f") { unpack_flags($vardata); } elsif ($varname eq "x") { stop_game if ($CurrentlyExamining != 0); $CurrentlyExamining = $vardata; stop_game if ($CurrentlyExamining <= 0); stop_game if ($MAXITEM <= $CurrentlyExamining && $CurrentlyExamining < 101); stop_game if ($CurrentlyExamining >= $MAXABSTRACTITEM); } elsif ($varname eq "msg") { stop_game if ($CurrentlyMessaging ne ""); $CurrentlyMessaging = $vardata; } elsif ($varname eq "dw") { stop_game if ($NounDollar != 0); $NounDollar = $vardata; stop_game if ($NounDollar <= 0); stop_game if ($MAXITEM <= $NounDollar && $NounDollar < 101); stop_game if ($NounDollar >= $MAXABSTRACTITEM); } elsif ($varname eq "dc") { stop_game if ($DarknessCounter != 0); $DarknessCounter = $vardata; stop_game if ($DarknessCounter <= 0); } else { stop_game; } } deal_with_fiendish(); stop_game if ($RoomNumber < 0 || $RoomNumber >= $MAXROOM); } sub reunpack_args($) { ## This function is dangerous! It completely overwrites ## the current game state! $RoomNumber = 0; @ihas_by_num = (0) x $MAXITEM; $NumberOfItemsCarried = 0; @room_contents = @item_home; @flag = (0) x $MAXFLAG; $CurrentlyExamining = 0; $CurrentlyMessaging = ""; $DarknessCounter = 0; $NounDollar = 0; my $arg = $_[0]; $arg =~ s/advent\.cgi\?//i; unpack_args($arg); } ############################################################# ## Process cmd-line arguments... ## ############################################################# my @args = split(/&/, $ENV{'QUERY_STRING'}); unpack_args(@args); ############################################################# ## PLAY THE GAME... show the room description ## ############################################################# start_desc(); if ($flag[$f{'VIEW_ROOM'}]) { $CurrentlyMessaging = ""; $CurrentlyExamining = 0; $flag[$f{'VIEWING_SELF'}] = 0; $flag[$f{'VIEW_ROOM'}] = 0; } if ($flag[$f{'MSG_SPILL_WATER'}]) { print "

Your bottle is empty and your feet are wet.\n"; $flag[$f{'MSG_SPILL_WATER'}] = 0; } elsif ($flag[$f{'MSG_SPILL_OIL'}]) { if ($RoomNumber == $r{'valley'}) { print "

You pour out the bottle into the stream.
\n"; print "The oil streams away with the current.\n"; } else { print "

Your bottle is empty and your feet are wet.\n"; } $flag[$f{'MSG_SPILL_OIL'}] = 0; } elsif ($flag[$f{'MSG_GOT_WATER'}]) { print "

You have filled your bottle with water.\n"; $flag[$f{'MSG_GOT_WATER'}] = 0; } elsif ($flag[$f{'MSG_GOT_OIL'}]) { print "

You have filled your bottle with oil.\n"; $flag[$f{'MSG_GOT_OIL'}] = 0; } elsif ($flag[$f{'MSG_GOT_BIRD'}]) { print "

You catch the bird and put it inside the wicker cage.\n"; $flag[$f{'MSG_GOT_BIRD'}] = 0; } elsif ($flag[$f{'MSG_LIT_LAMP'}]) { my $the = ($ihas_by_num[$n{'on lamp'}])? 'Your': 'The'; print "

${the} lamp is now shining brightly!\n"; $flag[$f{'MSG_LIT_LAMP'}] = 0; } elsif ($flag[$f{'MSG_EXT_LAMP'}]) { my $the = ($ihas_by_num[$n{'off lamp'}])? 'Your': 'The'; print "

${the} lamp is now off.\n"; $flag[$f{'MSG_EXT_LAMP'}] = 0; } elsif ($flag[$f{'MSG_GRATE_OPEN'}]) { print "

The grate is now open.\n"; $flag[$f{'MSG_GRATE_OPEN'}] = 0; } elsif ($flag[$f{'MSG_GRATE_CLOSE'}]) { print "

The grate is now shut and locked.\n"; $flag[$f{'MSG_GRATE_CLOSE'}] = 0; } elsif ($flag[$f{'MSG_TRANSPORT'}]) { print <As you say the magic word, you are instantly transported to ...
EOL $flag[$f{'MSG_TRANSPORT'}] = 0; } elsif ($flag[$f{'MSG_JUMP_TO_DEATH'}]) { print <With a giant running leap, you sail up and over the chasm! Unfortunately, however, you don't sail over all of the chasm. You fall for a long time before landing on the rocks that litter the floor of the pit far below. EOL print "

"; print href_start_over() . "Play again
"; done_desc(); } elsif ($flag[$f{'MSG_DROP_CAGE'}]) { print "

You put the cage (with the bird in it) on the ground.". " The bird has stopped singing.\n"; $flag[$f{'MSG_DROP_CAGE'}] = 0; } elsif ($flag[$f{'MSG_FREE_BIRD'}]) { print "

You release the bird from the wicker cage.\n"; $flag[$f{'MSG_FREE_BIRD'}] = 0; } elsif ($flag[$f{'MSG_OIL_PLANT'}]) { print "

The plant indignantly shakes the oil off its\n"; print "leaves and asks: \"Water?\"\n"; $flag[$f{'MSG_OIL_PLANT'}] = 0; } elsif ($flag[$f{'MSG_WATER_LITTLE'}]) { print "

You pour the water onto the little plant.\n"; print "

The plant spurts into furious growth for a few seconds.\n"; $flag[$f{'MSG_WATER_LITTLE'}] = 0; } elsif ($flag[$f{'MSG_WATER_MED'}]) { print "

The plant grows explosively, almost filling the bottom\n"; print "of the pit.\n"; $flag[$f{'MSG_WATER_MED'}] = 0; } elsif ($flag[$f{'MSG_WATER_HUGE'}]) { print "

You've over-watered the plant! It's shriveling up!\n"; print "It's... it's... dying! It's disappeared!\n"; print "You murderer!\n"; $flag[$f{'MSG_WATER_HUGE'}] = 0; } elsif ($flag[$f{'MSG_CLIMB_MED'}]) { print "

You climb up the plant and out of the pit.\n"; $flag[$f{'MSG_CLIMB_MED'}] = 0; } elsif ($flag[$f{'MSG_CLIMB_HUGE'}]) { print "

You climb up the beanstalk and scurry through the\n"; print "hole in the ceiling of the cavern.\n"; $flag[$f{'MSG_CLIMB_HUGE'}] = 0; } if ($flag[$f{'MSG_NO_SNAKE'}]) { print "

The little bird attacks the green snake,\n"; print "and in an astounding flurry drives the snake away.\n"; $flag[$f{'MSG_NO_SNAKE'}] = 0; } if ($CurrentlyMessaging ne "") { my $text = $message_desc{$CurrentlyMessaging}; my $name = ($NounDollar)? item_short_name($NounDollar): 'zebra'; $text =~ s/\$NOUN\$/${name}/i; $CurrentlyMessaging = ''; my $back = href_it(pack_args()); print $text; print "\n

${back}Back

\n"; done_desc(); } if ($CurrentlyExamining != 0) { my $tmp = $CurrentlyExamining; print_item_description($tmp); $CurrentlyExamining = 0; my $back = href_it(pack_args()); print "\n

${back}Back

\n"; done_desc(); } if ($flag[$f{'VIEWING_SELF'}]) { print "

You look as ugly as ever.\n"; print_possessions(); $flag[$f{'VIEWING_SELF'}] = 0; my $text = href_it(pack_args()); print "\n

${text}Back

\n"; done_desc(); } if (can_see_room()) { if ($flag[$f{'MAZE_DEADEND'}]) { $flag[$f{'MAZE_DEADEND'}] = 0; my $text = href_go_maze($RoomNumber); print "

Dead end.

\n

${text}Back

\n"; done_desc(); } print_room_description($RoomNumber); if (($RoomNumber==$r{'east of fissure'} or $RoomNumber==$r{'west of fissure'}) and ($flag[$f{'CRYSTAL_BRIDGE'}])) { my $bridge = href_ex($n{'crystal bridge'}); print "

A ${bridge}crystal bridge now spans the fissure.
\n"; } elsif (($RoomNumber == $r{'e end of twopit room'} or $RoomNumber == $r{'w end of twopit room'}) and ($flag[$f{'MED_PLANT'}])) { my $west = ($RoomNumber==$r{'e end of twopit room'})? 'west ': ''; print "

The top of a 12-foot-tall beanstalk is poking up out of\n"; print "the ${west}pit.\n"; } elsif (($RoomNumber == $r{'e end of twopit room'} or $RoomNumber == $r{'w end of twopit room'}) and ($flag[$f{'HUGE_PLANT'}])) { my $west = ($RoomNumber==$r{'e end of twopit room'})? 'west ': ''; print "

There is a huge beanstalk growing out of the ${west}pit"; print " up to the hole.\n"; } done_desc(); } else { ++$DarknessCounter; if ($DarknessCounter > 2 && rand(100) < 10) { print "You fell into a pit and broke every bone in your body!\n"; print "

"; print href_start_over() . "Play again
"; done_desc(); } my $dark = href_say('DARK'); my $you = href_myself(); my $pits = href_say('PITS'); print "It is now ${dark}pitch dark. If you proceed". " ${you}you will likely ${pits}fall into a pit.\n"; done_desc(); } ############################################################### sub can_see_room() { return 1 if ($RoomNumber <= $r{'cobble crawl'}); return 1 if ($ihas_by_num[$n{'on lamp'}]); return 1 if (item_in_room($n{'on lamp'})); return 0; } sub print_room_description($) { print "

"; my $rm_no = shift @_; my $text = $room_desc[$rm_no]; my $linkn = 0; @atoms = split(/(\[.*?\])/s, $text); for my $i (0 .. $#atoms) { if (substr($atoms[$i],0,1) eq '[') { my @links = eval $room_links[$rm_no]; print $links[$linkn++]; print substr($atoms[$i], 1, -1); print ""; } else { print $atoms[$i]; } } my $items = $room_contents[$RoomNumber]; if ($items != 0) { print "

\n"; } while ($items != 0) { my $current_item = $items % $MAXITEM; my $text = $item_desc[$current_item]; $text = substr($text, 0, index($text,'#')); @atoms = split(/(\[.*?\])/s, $text); for my $i (0 .. $#atoms) { if (substr($atoms[$i],0,1) eq '[') { my $examine_link = href_ex($current_item); print $examine_link; print substr($atoms[$i], 1, -1); print ""; } else { print $atoms[$i]; } } print "
\n"; $items /= $MAXITEM; } } sub print_possessions() { my $actually_carrying_anything = 0; foreach my $current_item (1 .. $MAXITEM-1) { next if ($ihas_by_num[$current_item] == 0); if (! $actually_carrying_anything) { print "

You are carrying:
\n

\n"; } else { print "

You are not carrying anything.\n"; } if ($ihas_by_num[$n{'on lamp'}]) { my $lamp = href_ex($n{'on lamp'}); my $turn_off = href_lamp_toggle(); print "Your ${lamp}lamp is ${turn_off}shining brightly.
\n"; } } sub print_item_description($) { print "

\n"; my $item = shift @_; my $text = $item_desc[$item]; $text = substr($text, 1+index($text,'#')); my $linkn = 0; @atoms = split(/(\[.*?\])/s, $text); for my $i (0 .. $#atoms) { if (substr($atoms[$i],0,1) eq '[') { my @links = eval $item_links[$item]; print $links[$linkn++]; print substr($atoms[$i], 1, -1); print ""; } else { print $atoms[$i]; } } print "\n"; if (item_in_room($item) and ($item < 100)) { my $tmp = $CurrentlyExamining; $CurrentlyExamining = 0; my $pickup_link = href_pickup($item); $CurrentlyExamining = $tmp; $_ = item_short_name($CurrentlyExamining); my $it = (/.*s$/)? 'them': 'it'; print "

${pickup_link}\[Pick ${it} up]\n"; } } sub item_short_name($) { my $text = $item_desc[$_[0]]; my $idx = index($text, '['); $text = substr($text, $idx+1, index($text,']')-$idx-1); return $text; } sub is_treas($) { return 1 if ($_[0] == $n{'gold nugget'}); return 1 if ($_[0] == $n{'diamonds'}); return 1 if ($_[0] == $n{'jewelry'}); return 1 if ($_[0] == $n{'rare coins'}); return 1 if ($_[0] == $n{'silver bars'}); return 1 if ($_[0] == $n{'pearl'}); return 1 if ($_[0] == $n{'treasure chest'}); return 0; } sub ihas_treas($) { for my $i (1 .. $MAXITEM) { if (is_treas($i) && $ihas_by_num[$i]) { @list_treasures = (@list_treasures, $i); } } if (@list_treasures > 0) { return $list_treasures[rand @list_treasures]; } return 0; } sub item_in_room($) { ## If "picking it up" changes the room - it's here! my $texto = pack_args(); my $tmp = $argsPickingUpThisItem; $argsPickingUpThisItem = $_[0]; my $text = pack_args(); $argsPickingUpThisItem = $tmp; return ($texto ne $text); } sub start_desc() { my $room_name = $room_by_num[$RoomNumber]; print "\n\n"; print "Adventure: ${room_name}\n"; print "\n\n\n"; } sub done_desc() { print "\n\n\n"; exit 0; } sub stop_game() { print "

Error 404: bad CGI arguments.

\n"; die; }