! Mines ! ! Copyright (c) 1979, 2005-2009 James L. Dean ! ! Version 2010.10.29 released October 29, 2010 ! ! This Inform program may be distributed or used without payment to its ! author. Derivative works must credit its author. ! ! "Mines" lets you explore mines. The mine you explore is determined by a mine ! number specified at the beginning of a game. ! ! The object of a game is to visit all of the rooms and return all of the ! treasures to the entrance without making too many moves. ! ! In a mine, the passages are straight. So, for example, if you go North to ! leave a room, you can go South to reenter it. The rooms are not evenly ! spaced. However, the distance between adjacent rooms is always a multiple ! of the minimum distance between adjacent rooms. ! ! $MAX_STATIC_DATA=30000 should be specified on the command line when this ! program is compiled. Constant NUM_ROOMS = 99; Constant NUM_TREASURES = 15; Constant NULL = 0; Array bFindPathLocalRoomAlreadyInStack --> (3*NUM_ROOMS-2); Array bPassageBlocked --> (9*NUM_ROOMS-8); Array bRoomMined --> (3*NUM_ROOMS-2); Array bRoomVisited --> (3*NUM_ROOMS-2); Array bTreasureSlain --> 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0; Array nAddend1 --> 4; Array nAddend2 --> 4; Array nBase64 --> 4; Array nCompare1 --> 4; Array nCompare2 --> 4; Array nDifference --> 4; Array nFindPathLocalDirection1 -> (3*NUM_ROOMS-2); Array nFindPathLocalDirection2 -> (3*NUM_ROOMS-2); Array nFindPathLocalDirection3 -> (3*NUM_ROOMS-2); Array nFindPathLocalDirectionRandom -> ((3*NUM_ROOMS-2)*6); Array nFindPathLocalPathLen --> (3*NUM_ROOMS-2); Array nFindPathParameterDirection -> (3*NUM_ROOMS-2); Array nFindPathParameterReturnAddress -> (3*NUM_ROOMS-2); Array nMaxInt16 --> 255 127 0 0; Array nMaxInt16Plus1 --> 0 128 0 0; Array nMinuend --> 4; Array nMinuendTem --> 4; Array nMultiplicand --> 4; Array nMultiplier --> 4; Array nOppositeDirection -> 1 0 3 2 5 4; Array nPathDirectionUsedToEnterRoom -> (6*NUM_ROOMS); Array nPrime --> 3 128 0 0; Array nProduct --> 4; Array nRN --> (8*4); Array nRNPartialSum --> 4; Array nRNSum --> 4; Array nRoomChokepoint --> (3*NUM_ROOMS-2); Array nShift --> 4; Array nSubtrahend --> 4; Array nSum --> 4; Array nTem1 --> 4; Array nTem2 --> 4; Array nTem3 --> 4; Array nTem4 --> 4; Array nTem5 --> 4; Array pFindPathLocalNext --> (3*NUM_ROOMS-2); Array pFindPathLocalPathStack --> (3*NUM_ROOMS-2); Array pFindPathParameterNext --> (3*NUM_ROOMS-2); Array pFindPathParameterRoom --> (3*NUM_ROOMS-2); Array pPassageRoom1 --> (9*NUM_ROOMS-8); Array pPassageRoom2 --> (9*NUM_ROOMS-8); Array pPassageTreasureGuardian --> (9*NUM_ROOMS-8); Array pPathNext --> (6*NUM_ROOMS); Array pPathRoom --> (6*NUM_ROOMS); Array pRoomPassage --> ((3*NUM_ROOMS-2)*6); Array pRoomWithName --> (NUM_ROOMS+1); Array pTreasureRoomTreasure --> (-1) (-1) (-1) (-1) (-1) (-1) (-1) (-1) (-1) (-1) (-1) (-1) (-1) (-1) (-1); Array pTreasureRoomWeapon --> (-1) (-1) (-1) (-1) (-1) (-1) (-1) (-1) (-1) (-1) (-1) (-1) (-1) (-1) (-1); Array szDirection --> "north" "south" "east" "west" "up" "down"; Array szDirectionLetter -> 'N' 'S' 'E' 'W' 'U' 'D'; Array szMine -> (9); Array szRoom --> "You're in a spherical room." "You're in the hall of bones. Dinosaur bones are everywhere." "You're in a subway tunnel. Don't touch that third rail!" "You're in a railroad tunnel. A whistle wails in the distance." "You're in an elfin quiche factory. The elves are out mowing spinach." "You're in an abandoned Plymouth plant. Beware of Road Runners and Barracudas." "You're in an abandoned Dodge plant. There is a Dart embedded in the North wall." "You're in a mouse's nest. You'd best exhale; this is a small room." "You're in a giant crayfish hole. An immense chicken neck is hanging from a rope." "You're in an abandoned coal mine. Beware of methane." "You're in the hall of winds. Presently, the wind is from the south." "You're in a stove pipe!" "You're in a totally darkened room. Although you can see nothing, the sound of dripping water echoes from the walls." "You're in an industrial waste site. Hold your breath and don't touch anything." "You're in the warehouse for an extremely popular brand of home computer. Tacky plastic enclosures abound." "You're in a hobbit's bedroom. The hobbit does not look pleased!" "You're in a troll sewerage processing plant. The air quality is not good." "You're in a rabbit hole. There is a jar of marmalade on a shelf in the wall." "You're in the giant's oven. Fortunately, it hasn't been used for years." "You're in a hobbit's drying room. Tobacco leaves abound." "You're in a large circular room. It is dark in here." "You're in the Crystal Palace. Quartz crystals cover the walls." "You're in the Emerald Room. Green crystals cover the ceiling." "You're in a curtained room." "You're in an air conditioning duct!" "You're in a giant kiln. Smoke stains the walls." "You're in the Hall of Mists. Wisps of white vapor rise from the floor." "You're in an Aztec pyramid. A mummy lies in the northwest corner." "You're in the Room of the Eternal Flame. A large natural gas flame burns in the center of the room. Coming from the west wall you can barely hear the words, 'Fee Fye Foe Fum'." "You're in the Giant's store room. You are surrounded by old rugs, books, chairs, etc." "You're in the Leprechaun's Treasure Room. Unfortunately, the leprechaun's treasure was stolen years ago." "You're in a large tiled room. A girl is inquiring after a rabbit. Feel free to ignore her." "You're in a former nuclear test site. There is a large pile of rubble in the center of the floor. The walls are streaked with a multitude of colors." "You're in a drainage system holding tank. Either it is no longer used, or it hasn't rained in a long time; the room is dry." "You're in Mayor Schiro's bomb shelter." "You're in a room with a waterfall. It is not very impressive; it looks like someone left a water faucet running." "You're in an abandoned Neanderthal home." "You're in a volcanic chimney. The air is getting warmer." "You're in a pit full of snakes. Let's get out of here!!!!" "You're in a salt dome." "You're in Eleanor Roosevelt's privy. Wendell Wilkie buttons cover the wall." "You're in Napoleon's wine cellar. German wines line the shelves." "You're in the space behind the giant's bathroom wall. Large razor blades litter the floor. Step lightly." "You're in the room where all old toe nail clipping come to rest. Used corn pads litter the floor." "You're in the Den of the Horta. The walls are covered with a sticky fluid. Don't touch it; it is extremely corrosive." "You're in a damp room. A small creek runs into a crack in the West wall." "You're in what appears to be a NOPSI manhole." "You're in the cafeteria of Mammoth Cave. The aroma of rancid corned beef assails your nostrils." "You're in a small room with a large table. On the table is a bottle that says, 'Drink me.'" "You're in a Confederate States of America bank vault. Once worthless currency papers the walls." "You're in an abandoned subway station." "You're in a mine shaft. In the distance you can hear seven high pitched voices singing, 'Hi Ho, Hi Ho, ...'" "You're in a Minuteman missile silo." "You're in the giant's mouse trap. Fortunately, you are small enough to escape." "You're in Adolph Hitler's summer bunker." "You're in a dwarf work site. A sign says, ~Under construction. Enter at your own risk.~" "You're in the giant's refrigerator. Dwarf bodies hang from hooks." "You're in the Dragon's Lair. Slightly melted suits of armor litter the floor." "You're in a nuclear waste depository. The walls glow faintly." "You're in Millard Fillmore's tomb. It is dull." "You're in an abandoned corridor of the Strategic Air Command Headquarters. A graffito reads, ~Beware of Bat Guano.~" "You're in a gnome's workshop. Half-completed whoopee cushions line the tables." "You're in the Mummy's Tomb. You've triggered some mechanism and the ceiling is slowly descending." "You're in the Underground Gourmet's retreat. Twinkie and King Don wrappers are piled knee deep." "You're in a Hoola Hoop warehouse. The words ~Shoop Shoop~ echo from the walls." "You're in the first circle of hell. The living are not allowed here." "You're in the hall of the pixies. The furniture appears to have been made from cradles." "You're in a sulfur mine. Molten sulfur churns in a nearby pit. It is becoming difficult to breath." "You're in a fairy mushroom farm. Brilliantly colored mushrooms cover the floor." "You're in an ice cave. Along the western wall, a brontosaurus is defrosting." "You're in the giant's stove. Fortunately, the giant now owns a microwave oven." "You're in the rib cage of a long deceased whale." "You're in a room with six walls. The walls appear to be made of wax. A loud buzzing noise can be heard." "You're in the tomb of a Pharaoh. It has obviously been visited by others; the tomb is in a state of total disarray." "You're in a coal bin. There is a fossilized fern stump here." "You're in a diamond mine. It is uncomfortably hot here." "You're in the bottom of an oil well. The walls are slick." "You're in the lowest level of Project Mohole. The funding bubble burst before the earth did." "You're in the giant's cesspool. Fortunately, the giant was connected to the city sewerage system years ago." "You're in an eighteenth century sewer. The walls are crumbling brick. Small alligators snap at your feet." "You're in the lair of a giant trapdoor spider." "You're in a giant gopher tunnel." "You're in a shell -- the sole remains of a prehistoric turtle." "You're in a small chamber. The walls are made of earth. The air smells of formic acid. A strange squeaking noise can be heard in the distance." "You're in a chamber of columns. The stalagmites and stalactites join here." "You're in a service tunnel. Ducts, pipes, and cables are everywhere." "You're in a gas tank below an abandoned service station. No smoking!" "You're in a huge dark chamber. To one side, a dark, muddy river moves sluggishly. A sign written in ancient Greek says, ~Ferry out of order.~" "You're in a small chamber. It is brightly lit by a peculiar lichen growing on the walls and ceiling. The floor is rocky and steeply sloping. Nearby, a cold, clear creek boils into the floor and out of sight." "You're in the nest of a very large pack rat. There are discarded aluminum Christmas trees, broken steel utility poles, and other shiny, worthless items here." "You're in a dungeon. An iron maiden, a rack, a piano, and other machines of torture can be seen." "You're in the hall of bats. Thousands of bats hang from the ceiling. Watch your step; the droppings are quite deep in places." "You're in a hobgoblin's hideaway." "You're in an electrical substation. A transformer is humming loudly. Nearby, cables crackle with high voltage." "You're in the ~gold~ room. The walls are covered with iron pyrite." "You're in a room with one of Dracula's emergency coffins. The Count is out." "You're in a saltpeter mine. To one side there is a huge wooden evaporation vat. Small crystals of saltpeter cause the walls to sparkle." "You're in the basement cafeteria of a local hospital. Some say that there has been nothing edible here for years." "You're in a troll arsenal. Kegs of gun powder surround you."; Array szRoomDescription --> (3*NUM_ROOMS-2); Array szSeed -> 255; Array szTreasureGuardian --> "gorgon" "grizzly bear" "vampire" "crocodile" "giant crayfish" "troll" "werewolf" "harpy" "cobra" "ferocious snail" "vicious Doberman pinscher" "colossal cockroach" "giant" "Trekkie" "titanic ant"; Array szTreasureTreasure --> "bag full of gold coins" "large blue-white diamond" "sixty carat emerald" "platinum crucifix" "string of pearls" "Ming vase" "list of the next ten winners of the Kentucky Derby" "pile of rubies" "previously undiscovered Rembrandt painting" "ounce of antimatter in magnetic containment" "stack of silver bars" "set of ivory tusks" "Holland and Holland double rifle chambered for .600 Nitro Express" "ancient Greek statue" "five kilograms of plutonium in a lead container"; Array szTreasureWeapon --> "mirror" "pepper spray dispenser" "wooden stake" "roll of duct tape" "jar of Zatarain's Crab Boil" "elfin sword" "silver bullet" "crossbow" "flute fashioned from a dried-out pumpkin" "bag of salt" "soporific-laced dog biscuit" "block of boric acid" "slingshot" "recording of Leonard Nimoy singing ~Proud Mary~" "Fresnel lens"; Array szWayOut -> (NUM_ROOMS+1); Global bCarryingTreasure; Global bChokepointFound; Global bErr; Global bFirstLine; Global bGuarded; Global bOutOfMemory; Global bRank; Global bReenter; Global bResume; Global n; Global nAddIndex; Global nByte1; Global nByte2; Global nCarry; Global nChokepoint; Global nChokepoints; Global nCommand; Global nComparison; Global nDirection; Global nDirection1; Global nDirection2; Global nDirectionOpposite; Global nDistance; Global nDividend; Global nFindPathLocals = 0; Global nFindPathParameters = 0; Global nFirstChar; Global nHeight; Global nIteration; Global nIterations; Global nKeyIndex1; Global nKeyIndex2; Global nKeyLength; Global nKeyStart; Global nLeft; Global nLen; Global nMax; Global nMoves; Global nOffset; Global nPassage; Global nPassages = 0; Global nPaths = 0; Global nPickedUp; Global nQuotient; Global nRandomNumber; Global nRemainder; Global nReplaceIndex; Global nReturnAddress; Global nRoom1; Global nRoom2; Global nRooms; Global nRoomsPossible = 0; Global nRoomsVisited; Global nScore; Global nStep; Global nTem; Global nTemC; Global nTreasure; Global nTreasures; Global nTreasuresCarried; Global nTreasuresRecovered; Global pTreasure; Global nUnblocked; Global nUpperCase; Global nWidth; Global nX; Global nXFirstRoom; Global nY; Global nYFirstRoom; Global nZ; Global nZFirstRoom; Global pFindPathLocals; Global pFindPathLocalsHead; Global pFindPathParameters; Global pFindPathParametersHead; Global pPathStackHead; Global pPassage; Global pRoom; Global pRoomAlongPassage; Global pRoomEntrance; Global pRoomDown; Global pRoomNext; Global pRoomStart; Global pRoomSouth; Global pRoomSouthBase; Global pRoomWest; Global pRoomWestBase; Global pRoomWestBaseBase; Global szDescription; Global szTem; [ ListCommands; print "Commands in the game are ~N~, ~E~, ~S~, ~W~, ~U~, and ~D~ to move North, East, "; print "South, West, Up, or Down, respectively. Other commands are ~C~ to carry "; print "things, ~I~ to inventory what you are carrying, ~L~ to leave treasures, ~P~ to "; print "get the points you've scored, ~O~ for help getting out of the mine, ~H~ for "; print "help, and ~Q~ to quit.^^"; ]; [ DisplayHelp; print "Mines^^"; print "Copyright (c) 1979, 2005-2009 James L. Dean^^"; print "Version 2010.10.29 released October 29, 2010^^"; print "This z-machine program may be distributed or used without payment to its author. Derivative works must credit its author.^^"; print "~Mines~ lets you explore mines. The mine you explore is determined by a mine number specified at the beginning of a game.^^"; print "The object of a game is to visit all of the rooms and return all of the treasures to the entrance without making too many moves.^^"; print "In a mine, the passages are straight. So, for example, if you go North to leave a room, you can go South to reenter "; print "it. The rooms are not evenly spaced. However, the distance between adjacent rooms is always a multiple of the minimum "; print "distance between adjacent rooms.^^"; ListCommands(); ]; [ Add; nCarry=0; for (nByte1=0: nByte1 < 4: ++nByte1) { nTem=(nAddend1-->nByte1)+(nAddend2-->nByte1)+nCarry; if (nTem > 256) { nTem=nTem-256; nCarry=1; } else nCarry=0; nSum-->nByte1=nTem; } ]; [ Subtract; nMinuendTem-->0=nMinuend-->0; nMinuendTem-->1=nMinuend-->1; nMinuendTem-->2=nMinuend-->2; nMinuendTem-->3=nMinuend-->3; for (nByte1=0: nByte1 < 4: ++nByte1) { if (nMinuend-->nByte1 < nSubtrahend-->nByte1) { nMinuend-->nByte1=(nMinuend-->nByte1)+256; if (nByte1 < 3) nMinuend-->(nByte1+1)=(nMinuend-->(nByte1+1))-1; } nDifference-->nByte1=(nMinuend-->nByte1)-(nSubtrahend-->nByte1); } ]; [ Compare; nComparison=0; nComparison=(nCompare1-->3)-(nCompare2-->3); if (nComparison == 0) { nComparison=(nCompare1-->2)-(nCompare2-->2); if (nComparison == 0) { nComparison=(nCompare1-->1)-(nCompare2-->1); if (nComparison == 0) nComparison=(nCompare1-->0)-(nCompare2-->0); } } ]; [ Multiply; for (nByte2=0: nByte2 < 4: ++nByte2) { nProduct-->nByte2=0; nShift-->nByte2=nMultiplicand-->nByte2; } for (nByte2=0: nByte2 < 4: ++nByte2) { nIterations=(nMultiplier-->nByte2); for (nIteration=0: nIteration < nIterations: ++nIteration) { nAddend1-->0=nProduct-->0; nAddend1-->1=nProduct-->1; nAddend1-->2=nProduct-->2; nAddend1-->3=nProduct-->3; nAddend2-->0=nShift-->0; nAddend2-->1=nShift-->1; nAddend2-->2=nShift-->2; nAddend2-->3=nShift-->3; Add(); nProduct-->0=nSum-->0; nProduct-->1=nSum-->1; nProduct-->2=nSum-->2; nProduct-->3=nSum-->3; } nShift-->3=nShift-->2; nShift-->2=nShift-->1; nShift-->1=nShift-->0; nShift-->0=0; } ]; [ ConvertInt16ToBase256; nDividend=n; for (nByte1=0: nByte1 < 4: ++nByte1) { nQuotient=nDividend/256; nRemainder=nDividend-256*nQuotient; nBase64-->nByte1=nRemainder; nDividend=nQuotient; } ]; [ RandomNumber; ! Each pseudo-random number is the modulo sum of the ! previous eight pseudo-random numbers. A prime modulus ! makes it likely that the pseudo-random numbers will be ! uniformly distributed. To speed computation, a partial ! sum of 7 of the 8 previous pseudo-random numbers is maintained. ! For a given set of initial values nRN[i], i=0,1,2,...,7, ! this random number generator should produce the same sequence ! of random numbers. do { nAddend1-->0=nRNPartialSum-->0; nAddend1-->1=nRNPartialSum-->1; nAddend1-->2=nRNPartialSum-->2; nAddend1-->3=nRNPartialSum-->3; nAddend2-->0=nRN-->(4*nAddIndex); nAddend2-->1=nRN-->(4*nAddIndex+1); nAddend2-->2=nRN-->(4*nAddIndex+2); nAddend2-->3=nRN-->(4*nAddIndex+3); Add(); nRNSum-->0=nSum-->0; nRNSum-->1=nSum-->1; nRNSum-->2=nSum-->2; nRNSum-->3=nSum-->3; nCompare1-->0=nRNSum-->0; nCompare1-->1=nRNSum-->1; nCompare1-->2=nRNSum-->2; nCompare1-->3=nRNSum-->3; nCompare2-->0=nPrime-->0; nCompare2-->1=nPrime-->1; nCompare2-->2=nPrime-->2; nCompare2-->3=nPrime-->3; Compare(); if (nComparison >= 0) { nMinuend-->0=nRNSum-->0; nMinuend-->1=nRNSum-->1; nMinuend-->2=nRNSum-->2; nMinuend-->3=nRNSum-->3; nSubtrahend-->0=nPrime-->0; nSubtrahend-->1=nPrime-->1; nSubtrahend-->2=nPrime-->2; nSubtrahend-->3=nPrime-->3; Subtract(); nRNSum-->0=nDifference-->0; nRNSum-->1=nDifference-->1; nRNSum-->2=nDifference-->2; nRNSum-->3=nDifference-->3; } nCompare1-->0=nRNSum-->0; nCompare1-->1=nRNSum-->1; nCompare1-->2=nRNSum-->2; nCompare1-->3=nRNSum-->3; nCompare2-->0=nRN-->(4*nReplaceIndex); nCompare2-->1=nRN-->(4*nReplaceIndex+1); nCompare2-->2=nRN-->(4*nReplaceIndex+2); nCompare2-->3=nRN-->(4*nReplaceIndex+3); Compare(); if (nComparison < 0) { nAddend1-->0=nRNSum-->0; nAddend1-->1=nRNSum-->1; nAddend1-->2=nRNSum-->2; nAddend1-->3=nRNSum-->3; nAddend2-->0=nPrime-->0; nAddend2-->1=nPrime-->1; nAddend2-->2=nPrime-->2; nAddend2-->3=nPrime-->3; Add(); nTem5-->0=nSum-->0; nTem5-->1=nSum-->1; nTem5-->2=nSum-->2; nTem5-->3=nSum-->3; nMinuend-->0=nTem5-->0; nMinuend-->1=nTem5-->1; nMinuend-->2=nTem5-->2; nMinuend-->3=nTem5-->3; nSubtrahend-->0=nRN-->(4*nReplaceIndex); nSubtrahend-->1=nRN-->(4*nReplaceIndex+1); nSubtrahend-->2=nRN-->(4*nReplaceIndex+2); nSubtrahend-->3=nRN-->(4*nReplaceIndex+3); Subtract(); nRNPartialSum-->0=nDifference-->0; nRNPartialSum-->1=nDifference-->1; nRNPartialSum-->2=nDifference-->2; nRNPartialSum-->3=nDifference-->3; } else { nMinuend-->0=nRNSum-->0; nMinuend-->1=nRNSum-->1; nMinuend-->2=nRNSum-->2; nMinuend-->3=nRNSum-->3; nSubtrahend-->0=nRN-->(4*nReplaceIndex); nSubtrahend-->1=nRN-->(4*nReplaceIndex+1); nSubtrahend-->2=nRN-->(4*nReplaceIndex+2); nSubtrahend-->3=nRN-->(4*nReplaceIndex+3); Subtract(); nRNPartialSum-->0=nDifference-->0; nRNPartialSum-->1=nDifference-->1; nRNPartialSum-->2=nDifference-->2; nRNPartialSum-->3=nDifference-->3; } nRN-->(4*nReplaceIndex)=nRNSum-->0; nRN-->(4*nReplaceIndex+1)=nRNSum-->1; nRN-->(4*nReplaceIndex+2)=nRNSum-->2; nRN-->(4*nReplaceIndex+3)=nRNSum-->3; nAddIndex=nReplaceIndex; if (++nReplaceIndex >= 8) nReplaceIndex=0; nCompare1-->0=nRNSum-->0; nCompare1-->1=nRNSum-->1; nCompare1-->2=nRNSum-->2; nCompare1-->3=nRNSum-->3; nCompare2-->0=nMaxInt16-->0; nCompare2-->1=nMaxInt16-->1; nCompare2-->2=nMaxInt16-->2; nCompare2-->3=nMaxInt16-->3; Compare(); } until (nComparison <= 0); nRandomNumber=256*(nRNSum-->1)+(nRNSum-->0); ]; [ SeedRandomNumberGenerator; nKeyLength=0; print "Mine Number? "; szSeed->0=252; read szSeed 0; nOffset=2; for (nKeyLength=0: (nKeyLength < szSeed->1) && (nKeyLength < 8): ++nKeyLength) { nTemC=szSeed->nOffset; szMine->nKeyLength=nTemC; ++nOffset; } print "^"; nKeyIndex1=0; if (nKeyLength < 8) { for (nKeyStart=nKeyLength: nKeyStart < 8: ++nKeyStart) { nRN-->(4*nKeyIndex1)='0'; nRN-->(4*nKeyIndex1)=(nRN-->(4*nKeyIndex1))+1; nRN-->(4*nKeyIndex1+1)=0; nRN-->(4*nKeyIndex1+2)=0; nRN-->(4*nKeyIndex1+3)=0; ++nKeyIndex1; } } nKeyIndex2=0; while (nKeyIndex2 < nKeyLength) { nRN-->(4*nKeyIndex1)=szMine->nKeyIndex2; nRN-->(4*nKeyIndex1)=(nRN-->(4*nKeyIndex1))+1; nRN-->(4*nKeyIndex1+1)=0; nRN-->(4*nKeyIndex1+2)=0; nRN-->(4*nKeyIndex1+3)=0; ++nKeyIndex1; ++nKeyIndex2; } nRNPartialSum-->0=0; nRNPartialSum-->1=0; nRNPartialSum-->2=0; nRNPartialSum-->3=0; for (nKeyIndex1=7: nKeyIndex1 > 0: --nKeyIndex1) { nAddend1-->0=nRNPartialSum-->0; nAddend1-->1=nRNPartialSum-->1; nAddend1-->2=nRNPartialSum-->2; nAddend1-->3=nRNPartialSum-->3; nAddend2-->0=nRN-->(4*nKeyIndex1); nAddend2-->1=nRN-->(4*nKeyIndex1+1); nAddend2-->2=nRN-->(4*nKeyIndex1+2); nAddend2-->3=nRN-->(4*nKeyIndex1+3); Add(); nRNPartialSum-->0=nSum-->0; nRNPartialSum-->1=nSum-->1; nRNPartialSum-->2=nSum-->2; nRNPartialSum-->3=nSum-->3; } nReplaceIndex=1; nAddIndex=0; for (nKeyIndex1=0: nKeyIndex1 < 256: ++nKeyIndex1) RandomNumber(); ]; [ ShuffleRoomDescriptions; for (nRoom1=nRooms-1: nRoom1 > 0: --nRoom1) { RandomNumber(); nRoom2=nRandomNumber%nRoom1; szTem=szRoom-->nRoom1; szRoom-->nRoom1=szRoom-->nRoom2; szRoom-->nRoom2=szTem; } ]; [ ExcavateMine; ! nMax=(int) (10.0+exp(log((double) nRooms)/3.0)); nMax=0; while (nMax*nMax*nMax < nRooms) ++nMax; if (nMax*nMax*nMax == nRooms) nMax=nMax+10; else nMax=nMax+9; do { RandomNumber(); nLen=nRandomNumber%(nMax-3)+3; RandomNumber(); nWidth=nRandomNumber%(nMax-3)+3; RandomNumber(); nHeight=nRandomNumber%(nMax-3)+3; } until ((nLen*nWidth*nHeight >= 2*(nRooms-1)) && (nLen*nWidth*nHeight <= 3*(nRooms-1))); nXFirstRoom=0; RandomNumber(); nYFirstRoom=nRandomNumber%nLen; RandomNumber(); nZFirstRoom=nRandomNumber%nHeight; pRoomWestBase=-1; pRoomWestBaseBase=-1; for (nX=0: (~~ bErr) && (nX < nWidth): ++nX) { pRoomSouthBase=-1; for (nY=0: (~~ bErr) && (nY < nLen): ++nY) { pRoomWest=pRoomWestBase; pRoomSouth=pRoomSouthBase; pRoomDown=-1; for (nZ=0: (~~ bErr) && (nZ < nHeight): ++nZ) { if (nRoomsPossible < 3*NUM_ROOMS-2) { pRoom=nRoomsPossible; ++nRoomsPossible; szRoomDescription-->pRoom=NULL; bRoomMined-->pRoom=false; nRoomChokepoint-->pRoom=-1; bRoomVisited-->pRoom=false; pRoomPassage-->(6*pRoom)=-1; pRoomPassage-->(6*pRoom+1)=-1; pRoomPassage-->(6*pRoom+2)=-1; pRoomPassage-->(6*pRoom+3)=-1; pRoomPassage-->(6*pRoom+4)=-1; pRoomPassage-->(6*pRoom+5)=-1; ! (X,Y,Z) gets linked to (X-1,Y,Z); (X,Y-1,Z); and (X,Y,Z-1) ! pRoomWest pRoomSouth pRoomDown if (nZ == 0) { pRoomSouthBase=pRoom; if (nY == 0) pRoomWestBaseBase=pRoom; } if (pRoomDown ~= -1) { ! link room to one below it if (nPassages < (9*NUM_ROOMS-8)) { pPassage=nPassages; ++nPassages; bPassageBlocked-->pPassage=true; pPassageTreasureGuardian-->pPassage=-1; pPassageRoom1-->pPassage=pRoom; pPassageRoom2-->pPassage=pRoomDown; pRoomPassage-->(6*pRoom+5)=pPassage; pRoomPassage-->(6*pRoomDown+4)=pPassage; } else { bErr=true; print "Fatal error: memory was exhausted.^"; } } if (pRoomSouth ~= -1) { ! link to room to the south if (nPassages < 9*NUM_ROOMS-8) { pPassage=nPassages; ++nPassages; bPassageBlocked-->pPassage=true; pPassageTreasureGuardian-->pPassage=-1; pPassageRoom1-->pPassage=pRoom; pPassageRoom2-->pPassage=pRoomSouth; pRoomPassage-->(6*pRoom+1)=pPassage; pRoomPassage-->(6*pRoomSouth)=pPassage; } else { bErr=true; print "Fatal error: memory was exhausted.^"; } if (pRoomPassage-->(6*pRoomSouth+4) ~= -1) if (pPassageRoom1-->(pRoomPassage-->(6*pRoomSouth+4)) == pRoomSouth) pRoomSouth=pPassageRoom2-->(pRoomPassage-->(6*pRoomSouth+4)); else pRoomSouth=pPassageRoom1-->(pRoomPassage-->(6*pRoomSouth+4)); else pRoomSouth=-1; } if (pRoomWest ~= -1) { ! link to the room to the west if (nPassages < 9*NUM_ROOMS-8) { pPassage=nPassages; ++nPassages; bPassageBlocked-->pPassage=true; pPassageTreasureGuardian-->pPassage=-1; pPassageRoom1-->pPassage=pRoom; pPassageRoom2-->pPassage=pRoomWest; pRoomPassage-->(6*pRoom+3)=pPassage; pRoomPassage-->(6*pRoomWest+2)=pPassage; } else { bErr=true; print "Fatal error: memory was exhausted.^"; } if (pRoomPassage-->(6*pRoomWest+4) ~= -1) if (pPassageRoom1-->(pRoomPassage-->(6*pRoomWest+4)) == pRoomWest) pRoomWest=pPassageRoom2-->(pRoomPassage-->(6*pRoomWest+4)); else pRoomWest=pPassageRoom1-->(pRoomPassage-->(6*pRoomWest+4)); else pRoomWest=-1; } ! If this is the first room, connect it to the entrance. if ((nX == nXFirstRoom) && (nY == nYFirstRoom) && (nZ == nZFirstRoom)) { if (nPassages < 9*NUM_ROOMS-8) { pPassage=nPassages; ++nPassages; bPassageBlocked-->pPassage=false; pPassageTreasureGuardian-->pPassage=-1; pPassageRoom1-->pPassage=pRoom; pPassageRoom2-->pPassage=pRoomEntrance; pRoomPassage-->(6*pRoom+3)=pPassage; pRoomPassage-->(6*pRoomEntrance+2)=pPassage; } else { bErr=true; print "Fatal error: memory was exhausted.^"; } } pRoomDown=pRoom; } else { bErr=true; print "Fatal error: memory was exhausted.^"; } } if (pRoomWestBase ~= -1) { if (pRoomPassage-->(6*pRoomWestBase) ~= -1) { if (pPassageRoom1-->(pRoomPassage-->(6*pRoomWestBase)) == pRoomWestBase) pRoomWestBase=pPassageRoom2-->(pRoomPassage-->(6*pRoomWestBase)); else pRoomWestBase=pPassageRoom1-->(pRoomPassage-->(6*pRoomWestBase)); } } } pRoomWestBase=pRoomWestBaseBase; } nChokepoint=-1; nTreasure=0; pRoom=pRoomEntrance; nRoom1=0; while (nRoom1 < nRooms) { pRoomStart=pRoom; RandomNumber(); nDirection1=nRandomNumber%6; nDirectionOpposite=nOppositeDirection->nDirection1; RandomNumber(); nDistance=nRandomNumber%3+1; nStep=0; while ((pRoomPassage-->(6*pRoom+nDirection1) ~= -1) && (nStep < nDistance)) { pPassage=pRoomPassage-->(6*pRoom+nDirection1); if (pPassageRoom1-->pPassage == pRoom) pRoomNext=pPassageRoom2-->pPassage; else pRoomNext=pPassageRoom1-->pPassage; if (bPassageBlocked-->pPassage) if ((nRoomChokepoint-->pRoomNext == nChokepoint) || (~~ (bRoomMined-->pRoomNext))) { pRoom=pRoomNext; bRoomMined-->pRoom=true; nRoomChokepoint-->pRoom=nChokepoint; bPassageBlocked-->pPassage=false; if (szRoomDescription-->pRoom ~= NULL) ++nStep; else { nUnblocked=0; for (nDirection2=6: ((nUnblocked < 2) && (nDirection2-- > 0)):) if (nDirection2 ~= nDirectionOpposite) if (pRoomPassage-->(6*pRoom+nDirection2) ~= -1) if (~~ (bPassageBlocked-->(pRoomPassage-->(6*pRoom+nDirection2)))) ++nUnblocked; if (nUnblocked < 2) ++nStep; else nStep=nDistance; } } else nStep=nDistance; else { ++nStep; pRoom=pRoomNext; nChokepoint=nRoomChokepoint-->pRoom; } } if (nStep) { if (szRoomDescription-->pRoom == NULL) { szRoomDescription-->pRoom=szRoom-->nRoom1; nDirection1=0; nUnblocked=0; for (nDirection2=6: ((nUnblocked < 2) && (nDirection2-- > 0)):) if (pRoomPassage-->(6*pRoom+nDirection2) ~= -1) if (~~ (bPassageBlocked-->(pRoomPassage-->(6*pRoom+nDirection2)))) { nDirection1=nDirection2; ++nUnblocked; } if (nUnblocked == 1) { n=nRooms-nRoom1; ConvertInt16ToBase256(); nTem1-->0=nBase64-->0; nTem1-->1=nBase64-->1; nTem1-->2=nBase64-->2; nTem1-->3=nBase64-->3; RandomNumber(); n=nRandomNumber; ConvertInt16ToBase256(); nTem2-->0=nBase64-->0; nTem2-->1=nBase64-->1; nTem2-->2=nBase64-->2; nTem2-->3=nBase64-->3; nMultiplicand-->0=nTem2-->0; nMultiplicand-->1=nTem2-->1; nMultiplicand-->2=nTem2-->2; nMultiplicand-->3=nTem2-->3; nMultiplier-->0=nTem1-->0; nMultiplier-->1=nTem1-->1; nMultiplier-->2=nTem1-->2; nMultiplier-->3=nTem1-->3; Multiply(); nTem3-->0=nProduct-->0; nTem3-->1=nProduct-->1; nTem3-->2=nProduct-->2; nTem3-->3=nProduct-->3; n=(nTreasures-nTreasure); ConvertInt16ToBase256(); nTem1-->0=nBase64-->0; nTem1-->1=nBase64-->1; nTem1-->2=nBase64-->2; nTem1-->3=nBase64-->3; nMultiplicand-->0=nTem1-->0; nMultiplicand-->1=nTem1-->1; nMultiplicand-->2=nTem1-->2; nMultiplicand-->3=nTem1-->3; nMultiplier-->0=nMaxInt16Plus1-->0; nMultiplier-->1=nMaxInt16Plus1-->1; nMultiplier-->2=nMaxInt16Plus1-->2; nMultiplier-->3=nMaxInt16Plus1-->3; Multiply(); nTem4-->0=nProduct-->0; nTem4-->1=nProduct-->1; nTem4-->2=nProduct-->2; nTem4-->3=nProduct-->3; nCompare1-->0=nTem3-->0; nCompare1-->1=nTem3-->1; nCompare1-->2=nTem3-->2; nCompare1-->3=nTem3-->3; nCompare2-->0=nTem4-->0; nCompare2-->1=nTem4-->1; nCompare2-->2=nTem4-->2; nCompare2-->3=nTem4-->3; Compare(); if (nComparison < 0) { nChokepoint=nTreasure; pPassageTreasureGuardian-->(pRoomPassage-->(6*pRoom+nDirection1))=nTreasure; ++nTreasure; } } nRoomChokepoint-->pRoom=nChokepoint; pRoomWithName-->nRoom1=pRoom; ++nRoom1; } } } pRoomWithName-->nRoom1=pRoomEntrance; nChokepoints=nTreasure; ]; [ HideTreasuresAndWeapons; for (nTreasure=0: nTreasure < nTreasures: ++nTreasure) { bChokepointFound=false; nRoom1=0; while ((~~ bChokepointFound) && (nRoom1 < nRooms)) if (nRoomChokepoint-->(pRoomWithName-->nRoom1) == nTreasure) bChokepointFound=true; else ++nRoom1; if (bChokepointFound) { do { RandomNumber(); nRoom1=nRandomNumber%nRooms; } until (nRoomChokepoint-->(pRoomWithName-->nRoom1) == nTreasure); pTreasureRoomTreasure-->nTreasure=pRoomWithName-->nRoom1; do { RandomNumber(); nRoom1=nRandomNumber%(nRooms+1); } until (nRoomChokepoint-->(pRoomWithName-->nRoom1) < nTreasure); pTreasureRoomWeapon-->nTreasure=pRoomWithName-->nRoom1; } else { RandomNumber(); nRoom1=nRandomNumber%nRooms; pTreasureRoomTreasure-->nTreasure=pRoomWithName-->nRoom1; pTreasureRoomWeapon-->nTreasure=pRoomWithName-->nRooms; } } ]; [ ListTreasures; for (nTreasure=nTreasures: nTreasure-- > 0:) if (pTreasureRoomTreasure-->nTreasure == pRoom) { nFirstChar=(szTreasureTreasure-->nTreasure)->0; if ((nFirstChar == 'A') || (nFirstChar == 'E') || (nFirstChar == 'I') || (nFirstChar == 'O') || (nFirstChar == 'U') || (nFirstChar == 'a') || (nFirstChar == 'e') || (nFirstChar == 'i') || (nFirstChar == 'o') || (nFirstChar == 'u')) print "There is an "; else print "There is a "; print (string) szTreasureTreasure-->nTreasure; print " here.^^"; } ]; [ ListWeapons; for (nTreasure=nTreasures: nTreasure-- > 0:) if (pTreasureRoomWeapon-->nTreasure == pRoom) { nFirstChar=(szTreasureWeapon-->nTreasure)->0; if ((nFirstChar == 'A') || (nFirstChar == 'E') || (nFirstChar == 'I') || (nFirstChar == 'O') || (nFirstChar == 'U') || (nFirstChar == 'a') || (nFirstChar == 'e') || (nFirstChar == 'i') || (nFirstChar == 'o') || (nFirstChar == 'u')) print "There is an "; else print "There is a "; print (string) szTreasureWeapon-->nTreasure; print " here.^^"; } ]; [ ListPassages; nPassages=0; for (nPassage=6: nPassage-- > 0:) if (pRoomPassage-->(6*pRoom+nPassage) ~= -1) ++nPassages; if (nPassages > 1) print "There are passages"; else print "There is a passage"; nPassage=0; for (nDirection=0: nDirection < 6: ++nDirection) if ((pRoomPassage-->(6*pRoom+nDirection) ~= -1) && (~~ bPassageBlocked-->(pRoomPassage-->(6*pRoom+nDirection)))) { if (++nPassage > 1) if (nPassages ~= 2) print ","; print " "; if (nPassage == nPassages) if (nPassages > 1) print "and "; print (string) szDirection-->nDirection; } print ".^^"; for (nDirection=0: nDirection < 6: ++nDirection) { szDescription=NULL; pRoomAlongPassage=pRoom; while ((pRoomPassage-->(6*pRoomAlongPassage+nDirection) ~= -1) && (~~ bPassageBlocked-->(pRoomPassage-->(6*pRoomAlongPassage+nDirection))) && (szDescription == NULL)) { pTreasure=pPassageTreasureGuardian-->(pRoomPassage-->(6*pRoomAlongPassage+nDirection)); if (pTreasure ~= -1) { print "The passage "; print (string) szDirection-->nDirection; nFirstChar=(szTreasureGuardian-->pTreasure)->0; if ((nFirstChar == 'A') || (nFirstChar == 'E') || (nFirstChar == 'I') || (nFirstChar == 'O') || (nFirstChar == 'U') || (nFirstChar == 'a') || (nFirstChar == 'e') || (nFirstChar == 'i') || (nFirstChar == 'o') || (nFirstChar == 'u')) print " is guarded by an "; else print " is guarded by a "; print (string) szTreasureGuardian-->pTreasure; print ".^^"; } if (pPassageRoom1-->(pRoomPassage-->(6*pRoomAlongPassage+nDirection)) == pRoomAlongPassage) pRoomAlongPassage=pPassageRoom2-->(pRoomPassage-->(6*pRoomAlongPassage+nDirection)); else pRoomAlongPassage=pPassageRoom1-->(pRoomPassage-->(6*pRoomAlongPassage+nDirection)); szDescription=szRoomDescription-->pRoomAlongPassage; } } ]; [ Points; nScore=0; nTreasuresRecovered=0; nTreasuresCarried=0; nRoomsVisited=0; for (nRoom1=0: nRoom1 <= nRooms: ++nRoom1) if (bRoomVisited-->(pRoomWithName-->nRoom1)) ++nRoomsVisited; print "You have moved "; print nMoves; print " times to visit "; print nRoomsVisited; print " of "; print nRooms+1; print " locations.^"; for (nTreasure=nTreasures: nTreasure-- > 0:) if (pTreasureRoomTreasure-->nTreasure == -1) ++nTreasuresCarried; print "You hold "; print nTreasuresCarried; print " of "; print nTreasures; print " treasures.^"; for (nTreasure=nTreasures: nTreasure-- > 0:) if (pTreasureRoomTreasure-->nTreasure == pRoomEntrance) ++nTreasuresRecovered; print "You have returned "; print nTreasuresRecovered; print " of "; print nTreasures; print " treasures to the entrance of the mine.^^"; nScore=25*nRoomsVisited/(nRooms+1)+75*nTreasuresRecovered/nTreasures+45*nTreasuresCarried/nTreasures; if (nMoves > 5*nRooms) { nScore=nScore-nMoves/(5*nRooms); if (nScore < 0) nScore=0; } print "You have scored "; print nScore; print " of 100 points.^^"; if (bRank) { if (nScore < 25) print "Your score ranks you as a beginner.^"; else if (nScore < 50) print "Your score ranks you as a novice adventurer.^"; else if (nScore < 75) print "Your score ranks you as a seasoned explorer.^"; else if (nScore < 100) print "Your score ranks you as a grissly old prospector.^"; else print "Your score ranks you as an expert treasure hunter; there is no higher rating.^"; } ]; [ Carry; nPickedUp=0; for (nTreasure=nTreasures: nTreasure-- > 0:) { if (pTreasureRoomWeapon-->nTreasure == pRoom) { ++nPickedUp; pTreasureRoomWeapon-->nTreasure=-1; } if (pTreasureRoomTreasure-->nTreasure == pRoom) { ++nPickedUp; pTreasureRoomTreasure-->nTreasure=-1; } } if (nPickedUp == 0) print "There is nothing to carry.^^"; ]; [ Leave; nLeft=0; for (nTreasure=nTreasures: nTreasure-- > 0:) if (pTreasureRoomTreasure-->nTreasure == -1) { ++nLeft; pTreasureRoomTreasure-->nTreasure=pRoom; } if (nLeft == 0) print "You aren't carrying anything to leave.^^"; ]; [ Inventory; bFirstLine=true; for (nTreasure=nTreasures: nTreasure-- > 0:) if (pTreasureRoomTreasure-->nTreasure == -1) { if (bFirstLine) { print "You are carrying the following:^^"; bFirstLine=false; } print " "; print (string) szTreasureTreasure-->nTreasure; print "^"; } for (nTreasure=nChokepoints: nTreasure-- > 0:) if ((pTreasureRoomWeapon-->nTreasure == -1) && (~~ (bTreasureSlain-->nTreasure))) { if (bFirstLine) { print "You are carrying the following:^^"; bFirstLine=false; } print " "; print (string) szTreasureWeapon-->nTreasure; print "^"; } if (bFirstLine) print "You aren't carrying anything.^^"; else print "^"; ]; [ Move; if ((pRoomPassage-->(6*pRoom+nDirection) ~= -1) && (~~ (bPassageBlocked-->(pRoomPassage-->(6*pRoom+nDirection))))) { bGuarded=false; szDescription=NULL; pRoomAlongPassage=pRoom; while ((pRoomPassage-->(6*pRoomAlongPassage+nDirection) ~= -1) && (szDescription == NULL)) { if (pPassageTreasureGuardian-->(pRoomPassage-->(6*pRoomAlongPassage+nDirection)) ~= -1) if (pTreasureRoomWeapon-->(pPassageTreasureGuardian-->(pRoomPassage-->(6*pRoomAlongPassage+nDirection))) ~= -1) { print "You carry nothing to overcome the "; print (string) szTreasureGuardian-->(pPassageTreasureGuardian-->(pRoomPassage-->(6*pRoomAlongPassage+nDirection))); print ".^^"; } else { print "Your "; print (string) szTreasureWeapon-->(pPassageTreasureGuardian-->(pRoomPassage-->(6*pRoomAlongPassage+nDirection))); print " overcomes the "; print (string) szTreasureGuardian-->(pPassageTreasureGuardian-->(pRoomPassage-->(6*pRoomAlongPassage+nDirection))); print ".^^"; bTreasureSlain-->(pPassageTreasureGuardian-->(pRoomPassage-->(6*pRoomAlongPassage+nDirection)))=true; pPassageTreasureGuardian-->(pRoomPassage-->(6*pRoomAlongPassage+nDirection))=-1; } if (pPassageRoom1-->(pRoomPassage-->(6*pRoomAlongPassage+nDirection)) == pRoomAlongPassage) pRoomAlongPassage=pPassageRoom2-->(pRoomPassage-->(6*pRoomAlongPassage+nDirection)); else pRoomAlongPassage=pPassageRoom1-->(pRoomPassage-->(6*pRoomAlongPassage+nDirection)); szDescription=szRoomDescription-->pRoomAlongPassage; } if (~~ bGuarded) { ++nMoves; bRoomVisited-->pRoomAlongPassage=true; pRoom=pRoomAlongPassage; } } else print "You can't go that way.^^"; ]; [ FindPathToEntrance; bOutOfMemory=false; pFindPathLocals=-1; pFindPathLocalsHead=-1; pFindPathParameters=-1; pFindPathParametersHead=-1; if (nFindPathParameters < 3*NUM_ROOMS-2) { pFindPathParameters=nFindPathParameters; ++nFindPathParameters; pFindPathParameterNext-->pFindPathParameters=pFindPathParametersHead; pFindPathParameterRoom-->pFindPathParameters=pRoomStart; nFindPathParameterDirection->pFindPathParameters=0; nFindPathParameterReturnAddress->pFindPathParameters=0; pFindPathParametersHead=pFindPathParameters; pPathStackHead=-1; bResume=false; nIterations=0; do { ++nIterations; bReenter=false; if (bResume) { for (:(~~ bOutOfMemory) && (~~ bReenter) && (szWayOut->0 == 0) && ((nFindPathLocalDirection1->pFindPathLocalsHead) > 0):) { nFindPathLocalDirection1->pFindPathLocalsHead=(nFindPathLocalDirection1->pFindPathLocalsHead)-1; nFindPathLocalDirection2->pFindPathLocalsHead=nFindPathLocalDirectionRandom->(6*pFindPathLocalsHead+(nFindPathLocalDirection1->pFindPathLocalsHead)); if (pRoomPassage-->(6*(pFindPathParameterRoom-->pFindPathParametersHead)+(nFindPathLocalDirection2->pFindPathLocalsHead)) ~= -1) { if (~~ (bPassageBlocked-->(pRoomPassage-->(6*(pFindPathParameterRoom-->pFindPathParametersHead)+(nFindPathLocalDirection2->pFindPathLocalsHead))))) { if (pPassageRoom1-->(pRoomPassage-->(6*(pFindPathParameterRoom-->pFindPathParametersHead)+(nFindPathLocalDirection2->pFindPathLocalsHead))) == pFindPathParameterRoom-->pFindPathParametersHead) if (nFindPathParameters < 3*NUM_ROOMS-2) { pFindPathParameters=nFindPathParameters; ++nFindPathParameters; pFindPathParameterNext-->pFindPathParameters=pFindPathParametersHead; pFindPathParameterRoom-->pFindPathParameters=pPassageRoom2-->(pRoomPassage-->(6*(pFindPathParameterRoom-->pFindPathParametersHead)+(nFindPathLocalDirection2->pFindPathLocalsHead))); nFindPathParameterDirection->pFindPathParameters=nFindPathLocalDirection2->pFindPathLocalsHead; nFindPathParameterReturnAddress->pFindPathParameters=1; pFindPathParametersHead=pFindPathParameters; bReenter=true; } else bOutOfMemory=true; else if (nFindPathParameters < 3*NUM_ROOMS-2) { pFindPathParameters=nFindPathParameters; ++nFindPathParameters; pFindPathParameterNext-->pFindPathParameters=pFindPathParametersHead; pFindPathParameterRoom-->pFindPathParameters=pPassageRoom1-->(pRoomPassage-->(6*(pFindPathParameterRoom-->pFindPathParametersHead)+(nFindPathLocalDirection2->pFindPathLocalsHead))); nFindPathParameterDirection->pFindPathParameters=nFindPathLocalDirection2->pFindPathLocalsHead; nFindPathParameterReturnAddress->pFindPathParameters=1; pFindPathParametersHead=pFindPathParameters; bReenter=true; } else bOutOfMemory=true; } } } if (~~ bOutOfMemory) { if (~~ bReenter) { pPathStackHead=pPathNext-->(pFindPathLocalPathStack-->pFindPathLocalsHead); pFindPathLocalPathStack-->pFindPathLocalsHead=-1; pFindPathLocals=pFindPathLocalsHead; pFindPathLocalsHead=pFindPathLocalNext-->pFindPathLocals; --nFindPathLocals; pFindPathLocals=-1; } } } else bReenter=true; if (~~ bOutOfMemory) { if (bReenter) do { bReenter=false; if (nFindPathLocals < 3*NUM_ROOMS-2) { pFindPathLocals=nFindPathLocals; ++nFindPathLocals; pFindPathLocalNext-->pFindPathLocals=pFindPathLocalsHead; pFindPathLocalsHead=pFindPathLocals; if (pFindPathParameterRoom-->pFindPathParametersHead == pRoomEntrance) { nFindPathLocalPathLen-->pFindPathLocalsHead=0; pFindPathLocalPathStack-->pFindPathLocalsHead=pPathStackHead; while (pFindPathLocalPathStack-->pFindPathLocalsHead ~= -1) { if (szRoomDescription-->(pPathRoom-->(pFindPathLocalPathStack-->pFindPathLocalsHead)) ~= NULL) nFindPathLocalPathLen-->pFindPathLocalsHead=(nFindPathLocalPathLen-->pFindPathLocalsHead)+1; pFindPathLocalPathStack-->pFindPathLocalsHead=pPathNext-->(pFindPathLocalPathStack-->pFindPathLocalsHead); } if (nFindPathLocalPathLen-->pFindPathLocalsHead <= NUM_ROOMS) { szWayOut->(nFindPathLocalPathLen-->pFindPathLocalsHead)=0; nUpperCase=szDirectionLetter->(nFindPathParameterDirection->pFindPathParametersHead); nFindPathLocalPathLen-->pFindPathLocalsHead=(nFindPathLocalPathLen-->pFindPathLocalsHead)-1; szWayOut->(nFindPathLocalPathLen-->pFindPathLocalsHead)=nUpperCase; pFindPathLocalPathStack-->pFindPathLocalsHead=pPathStackHead; while (pFindPathLocalPathStack-->pFindPathLocalsHead ~= -1) { if (pPathNext-->(pFindPathLocalPathStack-->pFindPathLocalsHead) ~= -1) { if (szRoomDescription-->(pPathRoom-->(pFindPathLocalPathStack-->pFindPathLocalsHead)) ~= NULL) { nUpperCase=szDirectionLetter->(nPathDirectionUsedToEnterRoom->(pFindPathLocalPathStack-->pFindPathLocalsHead)); nFindPathLocalPathLen-->pFindPathLocalsHead=(nFindPathLocalPathLen-->pFindPathLocalsHead)-1; szWayOut->(nFindPathLocalPathLen-->pFindPathLocalsHead)=nUpperCase; } } pFindPathLocalPathStack-->pFindPathLocalsHead=pPathNext-->(pFindPathLocalPathStack-->pFindPathLocalsHead); } } else bOutOfMemory=true; } else { bFindPathLocalRoomAlreadyInStack-->pFindPathLocalsHead=false; pFindPathLocalPathStack-->pFindPathLocalsHead=pPathStackHead; while ((pFindPathLocalPathStack-->pFindPathLocalsHead ~= -1) && (~~ (bFindPathLocalRoomAlreadyInStack-->pFindPathLocalsHead))) { if (pPathRoom-->(pFindPathLocalPathStack-->pFindPathLocalsHead) == pFindPathParameterRoom-->pFindPathParametersHead) bFindPathLocalRoomAlreadyInStack-->pFindPathLocalsHead=true; else bFindPathLocalRoomAlreadyInStack-->pFindPathLocalsHead=false; pFindPathLocalPathStack-->pFindPathLocalsHead =pPathNext-->(pFindPathLocalPathStack-->pFindPathLocalsHead); } if (~~ (bFindPathLocalRoomAlreadyInStack-->pFindPathLocalsHead)) { if (nPaths < 6*NUM_ROOMS) { pFindPathLocalPathStack-->pFindPathLocalsHead=nPaths; ++nPaths; pPathRoom-->(pFindPathLocalPathStack-->pFindPathLocalsHead)=pFindPathParameterRoom-->pFindPathParametersHead; nPathDirectionUsedToEnterRoom->(pFindPathLocalPathStack-->pFindPathLocalsHead) =nFindPathParameterDirection->pFindPathParametersHead; pPathNext-->(pFindPathLocalPathStack-->pFindPathLocalsHead)=pPathStackHead; pPathStackHead=pFindPathLocalPathStack-->pFindPathLocalsHead; nFindPathLocalDirection1->pFindPathLocalsHead=6; while (nFindPathLocalDirection1->pFindPathLocalsHead > 0) { nFindPathLocalDirection1->pFindPathLocalsHead=(nFindPathLocalDirection1->pFindPathLocalsHead)-1; nFindPathLocalDirectionRandom->(6*pFindPathLocalsHead+(nFindPathLocalDirection1->pFindPathLocalsHead)) =nFindPathLocalDirection1->pFindPathLocalsHead; } for (nFindPathLocalDirection1->pFindPathLocalsHead=5: nFindPathLocalDirection1->pFindPathLocalsHead > 0:) { RandomNumber(); nFindPathLocalDirection2->pFindPathLocalsHead =nRandomNumber%((nFindPathLocalDirection1->pFindPathLocalsHead)+1); nFindPathLocalDirection3->pFindPathLocalsHead =nFindPathLocalDirectionRandom->(6*pFindPathLocalsHead+(nFindPathLocalDirection1->pFindPathLocalsHead)); nFindPathLocalDirectionRandom->(6*pFindPathLocalsHead+(nFindPathLocalDirection1->pFindPathLocalsHead)) =nFindPathLocalDirectionRandom->(6*pFindPathLocalsHead+(nFindPathLocalDirection2->pFindPathLocalsHead)); nFindPathLocalDirectionRandom->(6*pFindPathLocalsHead+(nFindPathLocalDirection2->pFindPathLocalsHead)) =nFindPathLocalDirection3->pFindPathLocalsHead; nFindPathLocalDirection1->pFindPathLocalsHead=(nFindPathLocalDirection1->pFindPathLocalsHead)-1; } for (nFindPathLocalDirection1->pFindPathLocalsHead=6: (~~ bOutOfMemory) && (~~ bReenter) && (szWayOut->0 == 0) && (nFindPathLocalDirection1->pFindPathLocalsHead > 0):) { nFindPathLocalDirection1->pFindPathLocalsHead=(nFindPathLocalDirection1->pFindPathLocalsHead)-1; nFindPathLocalDirection2->pFindPathLocalsHead =nFindPathLocalDirectionRandom->(6*pFindPathLocalsHead+(nFindPathLocalDirection1->pFindPathLocalsHead)); if (pRoomPassage-->(6*(pFindPathParameterRoom-->pFindPathParametersHead)+(nFindPathLocalDirection2->pFindPathLocalsHead)) ~= -1) { if (~~ (bPassageBlocked-->(pRoomPassage-->(6*(pFindPathParameterRoom-->pFindPathParametersHead)+(nFindPathLocalDirection2->pFindPathLocalsHead))))) { if (pPassageRoom1-->(pRoomPassage-->(6*(pFindPathParameterRoom-->pFindPathParametersHead)+(nFindPathLocalDirection2->pFindPathLocalsHead))) == pFindPathParameterRoom-->pFindPathParametersHead) if (nFindPathParameters < 3*NUM_ROOMS-2) { pFindPathParameters=nFindPathParameters; ++nFindPathParameters; pFindPathParameterNext-->pFindPathParameters=pFindPathParametersHead; pFindPathParameterRoom-->pFindPathParameters =pPassageRoom2-->(pRoomPassage-->(6*(pFindPathParameterRoom-->pFindPathParametersHead)+(nFindPathLocalDirection2->pFindPathLocalsHead))); nFindPathParameterDirection->pFindPathParameters=nFindPathLocalDirection2->pFindPathLocalsHead; nFindPathParameterReturnAddress->pFindPathParameters=1; pFindPathParametersHead=pFindPathParameters; bReenter=true; } else bOutOfMemory=true; else if (nFindPathParameters < 3*NUM_ROOMS-2) { pFindPathParameters=nFindPathParameters; ++nFindPathParameters; pFindPathParameterNext-->pFindPathParameters=pFindPathParametersHead; pFindPathParameterRoom-->pFindPathParameters =pPassageRoom1-->(pRoomPassage-->(6*(pFindPathParameterRoom-->pFindPathParametersHead)+(nFindPathLocalDirection2->pFindPathLocalsHead))); nFindPathParameterDirection->pFindPathParameters=nFindPathLocalDirection2->pFindPathLocalsHead; nFindPathParameterReturnAddress->pFindPathParameters=1; pFindPathParametersHead=pFindPathParameters; bReenter=true; } else bOutOfMemory=true; } } } if (~~ bReenter) { pPathStackHead=pPathNext-->(pFindPathLocalPathStack-->pFindPathLocalsHead); pFindPathLocalPathStack-->pFindPathLocalsHead=-1; } } else bOutOfMemory=true; } } if (~~ bReenter) { pFindPathLocals=pFindPathLocalsHead; pFindPathLocalsHead=pFindPathLocalNext-->pFindPathLocals; --nFindPathLocals; pFindPathLocals=-1; } } else bOutOfMemory=true; } until (bOutOfMemory || (~~ bReenter)); } if (~~ bOutOfMemory) { nReturnAddress=nFindPathParameterReturnAddress->pFindPathParametersHead; pFindPathParameters=pFindPathParametersHead; pFindPathParametersHead=pFindPathParameterNext-->pFindPathParameters; --nFindPathParameters; pFindPathParameters=-1; bResume=true; } } until (bOutOfMemory || (nReturnAddress == 0) || (nIterations >= 1000)); } else bOutOfMemory=true; nPaths=0; nFindPathLocals=0; nFindPathParameters=0; ]; [ WayOut; if (pRoom == pRoomEntrance) print "You're already at the entrance.^^"; else { bCarryingTreasure=false; for (nTreasure=nTreasures: (~~ bCarryingTreasure) && (nTreasure-- > 0):) if (pTreasureRoomTreasure-->nTreasure == -1) bCarryingTreasure=true; else bCarryingTreasure=false; if (bCarryingTreasure) { szWayOut->0=0; pRoomStart=pRoom; FindPathToEntrance(); if (szWayOut->0 ~= 0) { do { RandomNumber(); nRoom1=nRandomNumber%nRooms; } until (pRoomWithName-->nRoom1 ~= pRoom); pTreasureRoomTreasure-->nTreasure=pRoomWithName-->nRoom1; print "The pirate takes one of your treasures. As he leaves, he shouts the letters ~"; nByte1=0; while (szWayOut->nByte1 ~= 0) { print (char) szWayOut->nByte1; ++nByte1; } print "~.^^"; } else print "Nothing happens.^^"; } else print "Nothing happens.^^"; } ]; [ PlayGame; nMoves=0; pRoom=pRoomEntrance; nCommand='Q'; do { print (string) szRoomDescription-->pRoom; print "^^"; ListTreasures(); ListWeapons(); ListPassages(); print "Command? "; @read_char 1 -> nCommand; print (char) nCommand; print "^^"; switch (nCommand) { 'n', 'N': nDirection=0; Move(); 's', 'S': nDirection=1; Move(); 'e', 'E': nDirection=2; Move(); 'w', 'W': nDirection=3; Move(); 'u', 'U': nDirection=4; Move(); 'd', 'D': nDirection=5; Move(); 'c', 'C': Carry(); 'h', 'H': DisplayHelp(); 'i', 'I': Inventory(); 'l', 'L': Leave(); 'o', 'O': WayOut(); 'p', 'P': bRank=false; Points(); 'q', 'Q': bRank=true; Points(); default: print "I don't recognize that command.^^"; ListCommands(); } } until ((nCommand == 'q') || (nCommand == 'Q')); ]; [ Main; bErr=false; if (nRoomsPossible < 3*NUM_ROOMS-2) { pRoomEntrance=nRoomsPossible; ++nRoomsPossible; szRoomDescription-->pRoomEntrance="You're in the entrance to the mine."; bRoomMined-->pRoomEntrance=true; nRoomChokepoint-->pRoomEntrance=-1; bRoomVisited-->pRoomEntrance=true; pRoomPassage-->(6*pRoomEntrance)=-1; pRoomPassage-->(6*pRoomEntrance+1)=-1; pRoomPassage-->(6*pRoomEntrance+2)=-1; pRoomPassage-->(6*pRoomEntrance+3)=-1; pRoomPassage-->(6*pRoomEntrance+4)=-1; pRoomPassage-->(6*pRoomEntrance+5)=-1; DisplayHelp(); SeedRandomNumberGenerator(); nRooms=NUM_ROOMS; ShuffleRoomDescriptions(); nTreasures=NUM_TREASURES; pTreasure=0; nChokepoints=0; ExcavateMine(); if (~~ bErr) { HideTreasuresAndWeapons(); PlayGame(); } } else { bErr=true; print "Fatal error: memory was exhausted.^"; } ];