#import "lib.ih"
#import "doors.ih"
#import "pushable.ih"

LibraryMessage 1 "<br><b>~Ruins~</b>
                 <br><i>An Interactive Worked Example</i>
                 <br>Copyright(c)1999 by Angela M. Horns."

! ---------------------------------------------------------------------------- !
!       This version created by R.Rawson-Tetley in October 2001, from
!       Roger Firth's Inform recreation of this game, quoted in Edition 4/1
!       of the Inform Designer's Manual.
!
!                       PLAYER
!                             lamp,dictionary,map
!                       GREAT PLAZA
!                           | mushroom,packing-case,camera,newspaper,steps
!                           |
!                           |
!                       SQUARE CHAMBER -------------------- WORMCAST
!                           | inscriptions,sunlight,(key)         eggsac
!                           |
!                           |
!                       STOOPED CORRIDOR
!                           | statuette,door
!                           |
!                           |
!   UPPER CANYON        SHRINE
!       | ball           /     \ paintings,altar,mask,(priest)
!       |     ----------         ----------
!       |   /                               \
!   XIBALBÁ                                 ANTECHAMBER
!       | stela                                 | cage,skeletons,(warthog)
!       |                                       |
!       |                                       |
!   LOWER CANYON                            BURIAL SHAFT
!       | chasm                                   honeycomb
!       |
!       |
!   PUMICE LEDGE
!         bone
!
! ---------------------------------------------------------------------------- !

! Intro
LibraryMessage 200 "<bgcolor gray><font color=white><clearscreen><br>
                   &nbsp;      <b>RUINS</b>
                   <font color=black><br><bgcolor lightgray><br>
                   <br>         ~But Alligator was not digging the bottom of the hole
                   <br>        Which was to be his grave,
                   <br>        But rather he was digging his own hole
                   <br>        As a shelter for himself~
                   <br>
                   <br>        -- from the Popol Vuh
                   <br><bgcolor gray><br>
                   <font size=2 color=white>
                   <br>[ Please press SPACE to begin.]
                   <waitkey><br>
                   <clearscreen>
                   <br>Days of searching, days of thirsty hacking through the briars of
                   the forest, but at last your patience was rewarded. A discovery!"

GameCode {
       Name "Ruins"
       MaxItemsCanCarry 7
       Verbose yes
       WideInventoryDisplay yes
       SinglePlayerGame yes
       OverrideSecondaryNouns "66 68 69"
       ShowAvailableExits no
       StartingLocation forest
       AllowPersist yes

       Initialise: CodeExtend [
               addverb 201 photo
               addverb 201 photograph
       ]

       Start: Override [

               ' Show the intro screen
               message(200).show

               ' Give starting objects to the player
               map.currentlocation = currentplayer.containerlocation
               dictionary.currentlocation = currentplayer.containerlocation
               sodiumlamp.currentlocation = currentplayer.containerlocation

               ' Show the game version, the library version
               ' and output the start location to the player
               game.displayversion
               call StandardLib.DisplayLibraryVersion
               game.displaycurrentlocation

               ' default male/female pronouns
               call NPCPronouns.init
       ]

       Score: Override [
               var outs = |"You have scored " & currentplayer.score & " (out of a possible 25) in " & currentplayer.turns & " turns, earning you the rank of "|
               if ( currentplayer.score = 25 ) then
                       outs = |outs & "Director of the Carnegie Institution."|
                       currentplayer.print outs
                       end
               endif
               if ( currentplayer.score >= 20 ) then
                       outs = |outs & "Archaeologist."|
                       currentplayer.print outs
                       end
               endif
               if ( currentplayer.score >= 10 ) then
                       outs = |outs & "Curiosity-seeker."|
                       currentplayer.print outs
                       end
               endif
               if ( currentplayer.score >= 5 ) then
                       outs = |outs & "Explorer."|
                       currentplayer.print outs
                       end
               endif
               outs = |outs & "Tourist."|
               currentplayer.print outs
       ]

       AfterInputImmediate: CodeExtend [

                call DarkDaemon.inthedark

               if ( currentplayer.getvalue(warthog) = 1 ) then
                       ;go,look,examine,smell,search,jump
                               end
                       endif
                       #n,s,e,w,u,d,ne,nw,se,sw
                               end
                       endif
                       ;eat
                               currentplayer.print "You haven't the knack of snuffling up to food yet."
                               end
                       endif
                       ;inventory
                               currentplayer.print "You are empty-handed."
                               end
                       endif
                       currentplayer.print "Warthogs can't do anything so involved. If it weren't for the nocturnal eyesight and the lost weight, they'd be worse off all round than people."
                       end
               endif


               ;photo
                       if ( camera.currentlocation <> currentplayer.containerlocation ) then
                               currentplayer.print |"Not without the use of your camera" & "."|
                               end
                       endif
                       if ( input.noun = 4 ) or ( input.noun = |1000000 + currentplayer.index| ) then
                               currentplayer.print "Best not. You haven't shaved since Mexico."
                               end
                       endif
                       if ( currentplayer.itemscarried > 1 ) then
                               currentplayer.print "Photography is a cumbersome business, needing the use of both hands. You'll have to put everything else down."
                               end
                       endif
                       if ( currentplayer.currentlocation = forest.id ) then
                               currentplayer.print "In this rain-soaked forest, best not."
                               end
                       endif
                       if ( currentplayer.cansee = false ) then
                               currentplayer.print "It is far too dark."
                               end
                       endif
               endif

       ]
}

! -----------------------------------------------------------------------------
! Treasure class definition
!

Item treasure "Treasure Class" {

       OnAction: [

               ;photo
                       if ( this.movedfromoriginallocation = true ) then
                               currentplayer.print "What, and fake the archaeological record?"
                               end
                       endif
                       if ( this.getuserboolean(photoinsitu) = true ) then
                               currentplayer.print "Not again."
                               end
                       endif
                       currentplayer.print |"You set up the elephantine, large-format, wet-plate camera, adjust the sodium lamp and make a patient exposure of the " & this.thename & "."|
                       this.adduserboolean(photoinsitu)
               endif

               end

               proc before_insert

                       if ( input.noun2 = packingcase.nounid ) then
                               call StandardLib.AddScore this.getvalue(culturalvalue)

                               if ( currentplayer.score = 25 ) then
                                       currentplayer.print |"As you carefully pack away the " & this.thename & ", a red-tailed macaw flutters down from the tree-tops, feathers heavy in the recent rain, the sound of its beating wings almost deafening, stone falling against stone... As the skies clear, a crescent moon rises above a peaceful jungle. It is the end of March, 1938, and it is time to go home."|
                                       call StandardLib.Won
                                       end
                               else
                                       returnvalue = "Safely packed away."
                                       end
                               endif
                       endif
               end


               proc initialise
                       this.setvalue(culturalvalue) = 5
                       end
               end

               proc before_get
                       if ( this.currentlocation = packingcase.containerlocation ) then
                               returnvalue = "Unpacking such a priceless artifact had best wait until the Carnegie Intitution can do it."
                               cancelevent
                               end
                       endif
                       if ( this.getuserboolean(photoinsitu) = false ) then
                               returnvalue = "This is the 1930s, not the bad old days. Taking an artifact without recording its context is simply looting."
                               cancelevent
                               end
                       endif
               end

               proc before_remove
                       if ( this.currentlocation = packingcase.containerlocation ) then
                               returnvalue = "Unpacking such a priceless artifact had best wait until the Carnegie Intitution can do it."
                               cancelevent
                               end
                       endif
                       if ( this.getuserboolean(photoinsitu) = false ) then
                               returnvalue = "This is the 1930s, not the bad old days. Taking an artifact without recording its context is simply looting."
                               cancelevent
                               end
                       endif
               end
       ]
}


! ---------------------------------------------------------------------------- !
!       The game begins in the GRAND PLAZA.
!
Location forest "~Great Plaza~" {
       Description "Or so your notes call this low escarpment of limestone, but the rainforest has claimed it back. Dark olive trees crowd in on all sides, the air steams with the mist of a warm recent rain, midges hang in the air. ~Structure 10~ is a shambles of masonry which might once have been a burial pyramid, and little survives except stone-cut steps leading down into darkness below."

       OnInput: [
               ;go
                       #u
                               currentplayer.print "The trees are spiny and you'd cut your hands to ribbons trying to climb them."
                               end
                       endif
                       #in
                               currentplayer.currentlocation = steps.id
                               game.displaycurrentlocation
                               end
                       endif
                       #d
                               if ( steps.getuserboolean(rubblefilled) = true ) then
                                       currentplayer.print |"Rubble blocks the way after only a few steps" & "."|
                                       end
                               else
                                       currentplayer.currentlocation = squarechamber.id
                                       game.displaycurrentlocation
                                       end
                               endif
                       endif
                       #n,s,e,w,ne,nw,se,sw
                               currentplayer.print "The rainforest is dense, and you haven't hacked through it for days to abandon your discovery now. Really, you need a good few artifacts to take back to civilization before you can justify giving up the expedition."
                               end
                       endif
               endif
               ;listen
                       currentplayer.print "Howler monkeys, bats, parrots, macaw."
                       end
               endif

       ]
}

Item mushroom "a speckled mushroom" {
       StartsIn forest
       Nouns "speckled" "mushroom" "fungus" "toadstool"
       Initial "A speckled mushroom grows out of the sodden earth, on a long stalk."
       Description "The mushroom is capped with blotches, and you aren't at all sure it's not a toadstool."
       has edible

       OnAction: [

               ;eat
                       steps.removeuserboolean(rubblefilled)
                       currentplayer.print "You nibble at one corner, unable to trace the source of an acrid taste, distracted by the flight of a macaw overhead which seems to burst out of the sun, the sound of the beating of its wings almost deafening, stone falling against stone."
                       end
               endif
               end
               proc before_get
                       if ( this.getuserboolean(picked) = true ) then
                               returnvalue = "You pick up the slowly-disintegrating mushroom."
                       else
                               this.adduserboolean(picked)
                               returnvalue = "You pick the mushroom, neatly cleaving its thin stalk."
                       endif
               end
               proc before_drop
                       returnvalue = "The mushroom drops to the ground, battered slightly."
                       end
               endif
       ]
}

Item packingcase "a packing case" {
       Nouns "packing" "case" "box" "strongbox"
       StartsIn forest
       Size 2
       Initial "Your packing case rests here, ready to hold any important cultural finds you might make, for shipping back to civilisation."
       StaticMessage "The case is too heavy to bother moving, as long as your expedition is still incomplete."
       has static container open openable
}

Item camera "a wet-plate camera"
       StartsIn packingcase
       Nouns "wet-plate" "plate" "wet" "camera"
       Description "A cumbersome, sturdy, stubborn wooden-framed wet plate model: like all archaeologists, you have a love-hate relationship with your camera."
}

Item newspaper "a month-old newspaper"
       StartsIn packingcase
       Nouns "times" "newspaper" "paper" "month-old" "old"
       Description "~The Times~ for 26 February, 1938, at once damp and brittle after a month's exposure to the climate, which is much the way you feel yourself. Perhaps there is fog in London. Perhaps there are bombs."
       ReadableText "~The Times~ for 26 February, 1938, at once damp and brittle after a month's exposure to the climate, which is much the way you feel yourself. Perhaps there is fog in London. Perhaps there are bombs."
       has readable
}

Item steps "stone-cut steps"
       Nouns "steps" "stone" "stairs" "stone-cut" "pyramid" "burial" "structure" "ten" "10"
       StartsIn forest
       OnAction: [
               ;examine
                       if ( this.getuserboolean(rubblefilled) = true ) then
                               currentplayer.print |"Rubble blocks the way after only a few steps" & "."|
                               end
                       endif
                       if ( this.getuserboolean(visitedsquare) = true ) then
                               currentplayer.print "The cracked and worn steps descend into a dim chamber. Yours might have been the first feet to have trodden them for five hundred years. On the top step is inscribed the glyph Q1."
                               end
                       else
                               currentplayer.print "The cracked and worn steps descend into a dim chamber. Yours might be the first feet to have trodden them for five hundred years. On the top step is inscribed the glyph Q1."
                               end
                       endif

               endif
               end
               proc initialise
                       this.adduserboolean(rubblefilled)
               end
       ]

       has scenery
}

Item forestmist "a low mist"
       StartsIn forest
       Nouns "low" "swirling" "mist"
       Description "The mist has an aroma reminiscent of tortilla.",
       has scenery
       OnAction: [
               ;smell
                       currentplayer.print this.defaultexamine
                       end
               endif
               currentplayer.print "The mist is too insubstantial."
       ]
}


! ---------------------------------------------------------------------------- !
!       The SQUARE CHAMBER.
!
Location squarechamber "Square Chamber" {
       Nouns "lintelled" "lintel" "lintels" "doorways"
       Description "A sunken, gloomy stone chamber, ten yards across. A shaft of sunlight cuts in from the steps above, giving the chamber a diffuse light, but in the shadows low lintelled doorways to east and south lead into the deeper darkness of the Temple."
       U_to forest
       E_to wormcast
       S_to corridor
       has light

       OnInput: [

               #u
                       if ( eggsac.currentlocation = currentplayer.containerlocation ) then
                               currentplayer.print "The moment that natural light falls upon the eggsac, it bubbles obscenely and distends. Before you can throw it away, it bursts into a hundred tiny, birth-hungry insects..."
                               call StandardLib.Dead
                               end
                       endif
               endif

               ;put
                       if ( input.noun = eggsac.nounid ) and ( input.noun2 = sunlight.nounid ) then
                               currentplayer.print "You drop the eggsac into the glare of the shaft of sunlight. It bubbles obscenely, distends and then bursts into a hundred tiny insects which run in all directions into the darkness. Only spatters of slime and a curious yellow-stone key remain on the chamber floor."
                               stonekey.currentlocation = currentplayer.currentlocation
                               eggsac.currentlocation = 0
                               end
                       endif
               endif

       ]

       OnDisplay: [
               if ( steps.getuserboolean(beendown) = false ) then
                       steps.adduserboolean(beendown)
               endif
       ]

}

Item carvedinscriptions "carved inscriptions" {
       StartsIn squarechamber
       Nouns "carved" "inscriptions" "carvings" "marks" "markings" "symbols" "moving" "scuttling" "crowd"
       Initial "Carved inscriptions crowd the walls, floor and ceiling."
       Description "Each time you look at the carvings closely, they seem to be still. But you have the uneasy feeling when you look away that they're scuttling, moving about. Two glyphs are prominent: Arrow and Circle."
       StaticMessage "Don't be ridiculous."
       has static
}

Item sunlight "a shaft of sunlight" {
       StartsIn squarechamber
       Nouns "shaft" "of" "sunlight" "sun" "light" "beam" "sunbeam" "ray" "rays" "sun's" "sunlit" "air" "motes" "dust"
       Description "Motes of dust glimmer in the shaft of sunlit air, so that it seems almost solid."
       StaticMessage "It's only an insubstantial shaft of sunlight."
       has static scenery
}

Item chambermist "a low mist"
       StartsIn squarechamber
       Nouns "low" "swirling" "mist"
       Description "The mist has an aroma reminiscent of tortilla.",
       has scenery
       OnAction: [
               ;smell
                       currentplayer.print this.defaultexamine
                       end
               endif
               currentplayer.print "The mist is too insubstantial."
       ]
}

! ---------------------------------------------------------------------------- !
!       The STOOPED CORRIDOR.
!

Location corridor "Stooped Corridor" {
       Description "A low, square-cut corridor, running north to south,
                    stooping you over."

       N_to squarechamber
       S_to shrine
       has darkness

       OnDisplay: [
               ' Display the door
               call LockableTwoWayDoors.displaydoor stonedoorcorr.id
       ]

       OnInput: [
               ' Block player if the door is closed
               ;go,push
                       #s
                               if ( stonedoorcorr.openclosestate = false ) then
                                       currentplayer.print "The door is in the way."
                               endif
                       endif
               endif
       ]
}

Item statuette "a pygmy statuette" extends treasure {
       StartsIn corridor
       Nouns "snake" "mayan" "pygmy" "spirit" "precious" "statuette" "statue"
       Initial "A precious Mayan statuette rests here!"
       Description "A menacing, almost cartoon-like statuette of a pygmy spirit
                    with a snake around its neck."
}

Item stonedoorcorr "a stone door" {
       StartsIn corridor
       Nouns "door" "massive" "big" "stone" "yellow"
       Description "It's just a big stone door."
       ReadableText "The passage is barred by a massive door of yellow stone."
       Initial "The great yellow stone door is open."
       HasUDB locked
       has static openable invisible
       OnAction: [
               call LockableTwoWayDoors.doorhandler stonedoorcorr.id stonedoorshrine.id stonekey.id
       ]
}


! ---------------------------------------------------------------------------- !
!       The SHRINE.
!
Location shrine "Shrine" {
       Description "This magnificent Shrine shows signs of being hollowed out from
                   already-existing limestone caves, especially in the western of the
                   two long eaves to the south."
       N_to corridor
       SE_to antechamber
       has darkness

       OnDisplay: [
               call LockableTwoWayDoors.displaydoor stonedoorshrine.id
       ]

       OnInput: [
               ;go
                       #sw
                               if ( this.SW <> junction.id ) then
                                       currentplayer.print "The eaves taper out into a crevice which would wind further if it weren't jammed tight with icicles. The glyph of the Crescent is not quite obscured by ice."
                                       end
                               endif
                       endif
                       #n
                               if ( stonedoorshrine.openclosestate = false ) then
                                       currentplayer.print "The door is in the way."
                               endif
                       endif
               endif
       ]
}

Item paintings "the paintings" {
       StartsIn shrine
       Nouns "painting" "paintings" "lord" "captive"
       Initial "Vividly busy paintings, of the armoured Lord trampling on a
                captive, are almost too bright to look at, the graffiti of an
                organised mob."
       Description "The flesh on the bodies is blood-red. The markers of the Long Count
                    date the event to 10 baktun 4 katun 0 tun 0 uinal 0 kin, the sort
                    of anniversary when one Lord would finally decapitate a captured
                    rival who had been ritually tortured over a period of some years,
                    in the Balkanised insanity of the Maya city states."
       StaticMessage "That's hardly portable."
       has static
}

Item stonetable "a slab altar" {
       StartsIn shrine
       Nouns "stone" "table" "slab" "altar" "great"
       Initial "A great stone slab of a table, or altar, dominates the Shrine."
       StaticMessage "That's hardly portable."
       has supporter static sit stand lay
}

Item mask "a jade mosaic face-mask" extends treasure {
       StartsIn stonetable
       Nouns "jade" "mosaic" "face-mask" "mask" "face"
       Initial "Resting on the altar is a jade mosaic face-mask."
       Description "How exquisite it would look in the Museum."
       has wearable

       OnAction: [

               ;wear
                       if ( this.currentlocation <> currentplayer.containerlocation ) then
                               currentplayer.print "(taking the jade mosaic face-mask first)"
                               this.currentlocation = currentplayer.containerlocation
                               currentplayer.outputtoplayer = false
                       endif

                       priest.currentlocation = shrine.id
                       if ( currentplayer.currentlocation = shrine.id ) then
                               currentplayer.print "Looking through the obsidian eyeslits of the mosaic mask, a ghostly presence reveals itself: a mummified calendrical priest, attending your word."
                               currentplayer.outputtoplayer = false
                               end
                       endif
               endif

               ;disrobe,remove
                       priest.currentlocation = 0
               endif
       ]
}

Item stonedoorshrine "a stone door" {
       StartsIn shrine
       Nouns "door" "massive" "big" "stone" "yellow"
       Description "It's just a big stone door."
       ReadableText "The passage is barred by a massive door of yellow stone."
       Initial "The great yellow stone door is open."
       HasUDB locked
       has static openable invisible
       OnAction: [
               call LockableTwoWayDoors.doorhandler stonedoorcorr.id stonedoorshrine.id stonekey.id
       ]
}

! ---------------------------------------------------------------------------- !
!       The WORMCAST.
!
Location wormcast "Wormcast" {
       Description "A disturbed place of hollows carved like a spider's web, strands of
            empty space hanging in stone. The only burrows wide enough to crawl
            through begin by running northeast, south and upwards."
       W_to squarechamber

       OnInput: [
               ;go
                       #s,ne,u
                               currentplayer.print "The wormcast becomes slippery around you, as though your body-heat is melting long hardened resins, and you shut your eyes tightly as you burrow through darkness.<br>"
                               if ( eggsac.currentlocation = currentplayer.containerlocation ) then
                                       currentplayer.currentlocation = squarechamber.id
                                       game.displaycurrentlocation
                                       end
                               else
                                       ' Choose randomly from the corridor, forest and square chamber
                                       var rnum = |3 * random + 1 + makeinteger|
                                       if ( rnum = 1 ) then
                                               currentplayer.currentlocation = corridor.id
                                               game.displaycurrentlocation
                                               end
                                       endif
                                       if ( rnum = 2 ) then
                                               currentplayer.currentlocation = forest.id
                                               game.displaycurrentlocation
                                               end
                                       endif
                                       if ( rnum = 3 ) then
                                               currentplayer.currentlocation = squarechamber.id
                                               game.displaycurrentlocation
                                               end
                                       endif
                               endif
                       endif
                       #n,se,sw,e,w,d,nw
                               if ( currentplayer.getvalue(warthog) = 0 ) then
                                       currentplayer.print "Though you begin to feel certain that something lies behind and through the wormcast, this way must be an animal-run at best: it's far too narrow for your armchair-archaeologist's paunch."
                                       end
                               else
                                       currentplayer.print "The wormcast becomes slippery around your warthog body, and you squeal involuntarily as you burrow through the darkness, falling finally southwards to...<br>"
                                       currentplayer.currentlocation = burialshaft.id
                                       game.displaycurrentlocation
                               endif
                       endif
               endif

               ' If player drops something take it to the square chamber
               ;drop
                       var imid = getitemfromnoun input.noun
                       if ( imid <> 0 ) then
                               currentplayer.print |"The " & item(imid).thename & " slips through one of the burrows and is quickly lost from sight."|
                               item(imid).currentlocation = squarechamber.id
                               end
                       endif
               endif
       ]
}

Item eggsac "a glistening white eggsac" {
       Nouns "egg" "sac" "eggs" "eggsac"
       StartsIn wormcast
       Initial "A glistening white eggsac, like a clump of frogspawn the size of a
                beach ball, has adhered itself to something in a crevice in one
                wall."

       OnAction: [

               end
               proc before_get
                       returnvalue = "Oh my."
               end
       ]
}

! ---------------------------------------------------------------------------- !
!       The ANTECHAMBER.
!
Location antechamber "Antechamber" {
       Description "The southeastern eaves of the Shrine make a curious antechamber."
       NW_to shrine
       has darkness
}

Item cage "an iron cage" {
       StartsIn antechamber
       Initial "override me"
       Nouns "iron" "cage" "bars" "barred" "frame" "glyphs"
       Description "The glyphs read: Bird Arrow Warthog."
       has enterable transparent container open openable static

       OnAction: [

               ;get,go
                       #in
                               currentplayer.print "The skeletons inhabiting the cage come alive, locking bony hands about you, crushing and pummelling. You lose consciousness, and when you recover something grotesque and impossible has occurred...<br>"
                               currentplayer.setvalue(warthog) = 1
                               skeletons.currentlocation = 0
                               warthoglight.currentlocation = currentplayer.containerlocation
                               game.displaycurrentlocation
                       endif
               endif

               ;go
                       #d
                               if ( this.getvalue(flooropen) = 1 ) then
                                       currentplayer.currentlocation = burialshaft.id
                                       game.displaycurrentlocation
                                       end
                               endif
                       endif
               endif

               end
               proc before_displayinitial

                       ' IAGE handles sublocations in a different way to Inform
                       ' - we just override the display description for the object
                       ' in the main location according to where we are. The normal
                       ' library will take care of the rest.

                       ' Show inner desc if we are inside the cage
                       if ( currentplayer.stateitem = cage.id ) then
                               if ( this.getvalue(flooropen) = 1 ) then
                                       returnvalue = "From the floor of the cage, an open earthen pit cuts down into the burial chamber."
                                       cancelevent
                                       end
                               else
                                       returnvalue = "The bars of the cage surround you."
                                       cancelevent
                                       end
                               endif
                       endif

                       ' Otherwise, show the outer description.
                       if ( this.openclosestate = true ) then
                               returnvalue = "An iron-barred cage, large enough to stoop over inside, looms ominously here, its door open. There are some glyphs on the frame."
                               cancelevent
                               end
                       else
                               returnvalue = "The iron cage is closed."
                               cancelevent
                               end
                       endif

               end
       ]
}

Item skeletons "deranged skeletons" {
       Nouns "skeletons" "skeleton" "bone" "skull" "bones" "skulls"
       StartsIn cage
}

! ---------------------------------------------------------------------------- !
!       The BURIAL SHAFT.
!
Location burialshaft "Burial Shaft" {
       Description "In your eventual field notes, this will read:
            ~A corbel-vaulted crypt with an impacted earthen plug as seal
            above, and painted figures conjecturally representing the Nine
            Lords of the Night. Dispersed bones appear to be those of one
            elderly man and several child sacrifices, while other funerary
            remains include jaguar paws.~ (In field notes, it is essential
            not to give any sense of when you are scared witless.)"
       N_to wormcast

       OnInput: [

               ;go
                       #u
                               if ( cage.getvalue(flooropen) = 0 ) then
                                       cage.setvalue(flooropen) = 1
                                       currentplayer.setvalue(warthog) = 0
                                       currentplayer.print "Making a mighty warthog-leap, you butt at the earthen-plug seal above the chamber, collapsing your world in ashes and earth. Something lifeless and terribly heavy falls on top of you: you lose consciousness, and when you recover, something impossible and grotesque has happened...<br>"
                                       warthog.currentlocation = this.id
                                       warthoglight.currentlocation = 0
                                       game.displaycurrentlocation
                                       end
                               else
                                       ' If the floor is already open, take the player up to the cage
                                       currentplayer.currentlocation = antechamber.id
                                       currentplayer.stateitem = cage.id
                                       currentplayer.state = 5
                                       game.displaycurrentlocation
                                       end
                               endif
                       endif

                       #d,s,e,w,ne,nw,se,sw
                               currentplayer.print "The architects of this chamber were less than generous in providing exits. Some warthog seems to have burrowed in from the north, though."
                               end
                       endif
               endif

               ;jump
                       if ( cage.getvalue(flooropen) = 0 ) then
                               cage.setvalue(flooropen) = 1
                               currentplayer.setvalue(warthog) = 0
                               currentplayer.print "Making a mighty warthog-leap, you butt at the earthen-plug seal above the chamber, collapsing your world in ashes and earth. Something lifeless and terribly heavy falls on top of you: you lose consciousness, and when you recover, something impossible and grotesque has happened..."
                               warthog.currentlocation = this.id
                               warthoglight.currentlocation = 0
                               game.displaycurrentlocation
                               end
                       endif
               endif
       ]
}

Item honeycomb "an ancient honeycomb" extends treasure {

       StartsIn burialshaft
       Nouns "ancient" "old" "honey" "honeycomb"
       Initial "An exquisitely preserved, ancient honeycomb rests here!"
       Description "Perhaps some kind of funerary votive offering."
       has edible

       OnAction: [

               ;eat
                       currentplayer.print "Perhaps the most expensive meal of your life. The honey tastes odd, perhaps because it was used to store the entrails of the Lord buried here, but still like honey."
                       end
               endif
       ]
}

! ---------------------------------------------------------------------------- !
!       The UPPER/NORTH CANYON.
!
Location canyonn "Upper End of Canyon" {
       Description "The higher, broader northern end of the canyon rises only to an
                    uneven wall of volcanic karst."
       S_to junction
       d_to junction
       has light
}

Item hugeball "a huge pumice-stone ball" {
       StartsIn canyonn
       Nouns "huge" "pumice" "pumice-stone" "stone" "ball"
       Initial "A huge pumice-stone ball rests here, eight feet wide."
       Description "A good eight feet across, though fairly lightweight."
       StaticMessage "There's a lot of stone in an eight-foot sphere."
       has static

       OnAction: [

               ;pull,turn
                       currentplayer.print "It wouldn't be so very hard to get rolling."
                       end
               endif

               ;push
                       #ne
                               if ( currentplayer.currentlocation = junction.id ) then
                                       currentplayer.print "The Shrine entrance is far less than eight feet wide."
                                       end
                               endif
                       endif
                       if ( input.adverb = 0 ) then
                               currentplayer.print "It wouldn't be so very hard to get rolling."
                               end
                       endif
                       #n,u
                               currentplayer.print "You strain to push the ball uphill."
                       endif
                       #s,d
                               currentplayer.print "The ball is hard to stop once underway."
                       endif
                       call PushableItems.before_push this.id
                       end
               endif
       ]
}



! ---------------------------------------------------------------------------- !
!       The XIBALBÁ/JUNCTION.
!
Location junction "Xibalba" {
       Description "Fifty metres beneath rainforest, and the sound of water is
            everywhere: these deep, eroded limestone caves extend like
            taproots. A slither northeast by a broad collapsed column of
            ice-covered rock leads back to the Shrine, while a kind of canyon
            floor extends uphill to the north and downwards to south,
            pale white like shark's teeth in the diffused light from the
            sodium lamp above."
       NE_to shrine
       N_to canyonn
       U_to canyonn
       S_to canyons
       D_to canyons
       has light
}

Item stela "a stela" extends treasure {
       StartsIn junction
       Nouns "stela" "boundary" "stone" "marker"
       Initial "A modest-sized stela, or boundary stone, rests on a ledge at head height."
       Description "The carvings appear to warn that the boundary of Xibalba,
            Place of Fright, is near. The Bird glyph is prominent."
}

! ---------------------------------------------------------------------------- !
!       The LOWER/SOUTH CANYON.
!
Location canyons "Lower End of Canyon" {
       Description "At the lower, and narrower, southern end, the canyon stops dead at
            a chasm of vertiginous blackness. Nothing can be seen or heard
            from below."
       N_to junction
       U_to junction

       OnDisplay: [
               if ( hugeball.getuserboolean(plugginggap) = false ) and ( hugeball.currentlocation = this.id ) then
                       hugeball.currentlocation = 0
                       this.S = onball.id
                       this.description = "The southern end of the canyon now continues onto the pumice-stone ball, wedged into the chasm."
                       currentplayer.print "The pumice-stone ball rolls out of control down the last few feet of the canyon before shuddering into the jaws of the chasm, bouncing back a little and catching you a blow on the side of the forehead. You slump forward, bleeding, and... the pumice-stone shrinks, or else your hand grows, because you seem now to be holding it, staring at Alligator, son of seven-Macaw, across the ball-court of the Plaza, the heads of his last opponents impaled on spikes, a congregation baying for your blood, and there is nothing to do but to throw anyway, and... but this is all nonsense, and you have a splitting headache."
                       end
               endif
       ]

       OnInput: [

               #s,d
                       if ( this.S <> onball.id ) then
                               currentplayer.print "Into the chasm?"
                               end
                       endif
               endif
       ]
       has light
}

Item chasm "a horrifying chasm" {
       StartsIn canyons
       Nouns "blackness" "chasm" "pit" "horrifying" "bottomless"
       has scenery

       OnAction: [

               ;jump
                       #in
                               currentplayer.print "You plummet through the silent void of darkness, cracking your skull against an outcrop of rock. Amidst the pain and redness you dimly make out the God with the Owl-Headdress..."
                               call StandardLib.CustomDeath "You have been captured"
                               end
                       endif

                       #over
                               currentplayer.print "It's far too wide."
                               end
                       endif
               endif

               ;search
                       currentplayer.print "The chasm is deep and murky"
                       end
               endif

               ;put,drop,throw
                       #in
                               if ( input.noun2 = this.nounid ) then
                                       var imid = getitemfromnoun input.noun
                                       if ( imid <> 0 ) then
                                               currentplayer.print |"The " & item(imid).thename & " tumbles silently into the darkness of the chasm."|
                                               item(imid).currentlocation = 0
                                               end
                                       endif
                               endif
                       endif
               endif

               end
       ]
}

! ---------------------------------------------------------------------------- !
!       The PUMICE LEDGE.
!
Location onball "Pumice-Stone Ledge" {
       Description "An impromptu ledge formed by the pumice-stone ball, wedged into
            place in the chasm. The canyon nevertheless ends here."
       N_to canyons
       D_to canyons
       U_to canyons
       has light
}

Item incisedbone "an incised bone" extends treasure {
       StartsIn onball
       Nouns "incised" "carved" "bone"
       Initial "Of all the sacrificial goods thrown into the chasm, perhaps
            nothing will be reclaimed: nothing but an incised bone, lighter
            than it looks, which projects from a pocket of wet silt in the
            canyon wall."
       Description "A hand holding a brush pen appears from the jaws of Itzamna,
            inventor of writing, in his serpent form."
}



! ---------------------------------------------------------------------------- !
!       Objects which are moved into position as the game proceeds
!
Item sodiumlamp "a sodium lamp" {
       Nouns "sodium" "lamp" "heavy"
       Initial "must have initial description to override"
       has lightsource

       OnAction: [

               ;examine
                       var oput = "It is a heavy-duty archaeologist's lamp, "
                       if ( this.islit = false ) then
                               oput = |oput & "currently off."|
                       else
                               if ( this.getvalue(batterypower) < 10 ) then
                                       oput = |oput & "glowing a dim yellow."|
                               else
                                       oput = |oput & "blazing with brilliant yellow light."|
                               endif
                       endif
                       currentplayer.print oput
               endif

               ;switch
                       #on
                               if ( this.getvalue(batterypower) = 0 ) then
                                       currentplayer.print "Unfortunately, the battery seems to be dead."
                                       end
                               endif
                       endif
               endif

               ;light
                       if ( this.getvalue(batterypower) = 0 ) then
                               currentplayer.print "Unfortunately, the battery seems to be dead."
                               end
                       endif
               endif

               ;push
                       #sw
                               if ( currentplayer.currentlocation = shrine.id ) then
                                       currentplayer.print "The nearest you can do is to push the sodium lamp to the very lip of the Shrine, where the cave floor falls away."
                                       end
                               endif
                       endif
                       call PushableItems.before_push this.id
                       end
               endif



               end
               proc initialise
                       this.setvalue(batterypower) = 100
               end
               proc before_get
                       if ( this.islit = true ) then
                               returnvalue = "The bulb's too delicate and the metal handle's too hot to lift the lamp while it's switched on."
                               cancelevent
                       endif
               end
               proc before_displayinitial
                       if ( this.islit = true ) then
                               returnvalue = "The sodium lamp squats on the ground, burning away."
                               cancelevent
                               end
                       else
                               returnvalue = "The sodium lamp squats heavily on the ground."
                               cancelevent
                               end
                       endif
               end
               proc each_turn

                       ' This means that our custom description will always be used
                       this.movedfromoriginallocation = false

                       ' Battery daemon
                       if ( this.islit = true ) then
                               var batp = this.getvalue(batterypower)
                               batp = |batp - 1|
                               this.setvalue(batterypower) = batp
                               if ( batp = 10 ) then
                                       currentplayer.print "The sodium lamp is getting dimmer!"
                                       end
                               endif
                               if ( batp = 5 ) then
                                       currentplayer.print "The sodium lamp can't last much longer."
                                       end
                               endif
                               if ( batp = 0 ) then
                                       currentplayer.print "The sodium lamp fades and suddenly dies."
                                       this.islit = false
                                       game.displaycurrentlocation
                                       end
                               endif
                       endif
               end
       ]
}

Item dictionary "Waldeck's Mayan dictionary" {
       Nouns "dictionary" "local" "guide" "book" "mayan" "waldeck" "waldeck's"
       Description "Compiled from the unreliable lithographs of the legendary raconteur
            and explorer ~Count~ Jean Frederic Maximilien Waldeck
            (1766??-1875), this guide contains what little is known of the
            glyphs used in the local ancient dialect."

       OnAction: [

               ;consult

                       if ( input.noun2 = 0 ) then
                               currentplayer.print "Try ~consult dictionary about -name of glyph-~."
                               end
                       endif

                       var lookupnoun = input.snoun2

                       if ( lookupnoun = "q1" ) then
                               currentplayer.print "(This is one glyph you have memorised!)<br><br>Q1: ~sacred site~."
                               end
                       endif

                       if ( lookupnoun = "crescent" ) then
                               currentplayer.print "Crescent: believed pronounced ~xibalba~, though its meaning is unknown."
                               end
                       endif

                       if ( lookupnoun = "arrow" ) then
                               currentplayer.print "Arrow: ~journey; becoming~."
                               end
                       endif

                       if ( lookupnoun = "skull" ) then
                               currentplayer.print "Skull: ~death, doom; fate (not nec. bad)~."
                               end
                       endif

                       if ( lookupnoun = "circle" ) then
                               currentplayer.print "Circle: ~the Sun; also life, lifetime~."
                               end
                       endif

                       if ( lookupnoun = "jaguar" ) then
                               currentplayer.print "Jaguar: ~lord~."
                               end
                       endif

                       if ( lookupnoun = "monkey" ) then
                               currentplayer.print "Monkey: ~priest?~."
                               end
                       endif

                       if ( lookupnoun = "bird" ) then
                               if ( this.getvalue(correct) = 0 ) then
                                       currentplayer.print "Bird: ~rich, affluent?~."
                                       end
                               else
                                       currentplayer.print "Bird: ~dead as a stone~."
                                       end
                               endif
                       endif

                       currentplayer.print "That glyph is so far unrecorded."
               endif
       ]
}

! This may seem a little odd - I am using an item here that represents the available
! glyphs for looking up in the dictionary. This way we have a fast test to see
! what is understood and what is not without resorting to using input.contains or
! an ask statement and parsing it ourselves. This is a useful trick.
Item glyphs "the dictionary glyphs" {
       StartsIn limbo
       Nouns "q1" "crescent" "arrow" "skull" "circle" "jaguar" "monkey" "bird"
}


Item map "a sketch-map of Quintana Roo" {
       Nouns "map" "sketch" "sketch-map" "quintana" "roo"
       Description "This map marks little more than the creek which brought you
            here, off the south-east edge of Mexico and into deepest
            rainforest, broken only by this raised plateau."
}

Item stonekey "a stone key" {
       StartsIn limbo
       Nouns "stone" "key"
}

Character priest "a mummified priest" {
       StartsIn limbo
       Nouns "mummified" "priest"
       Initial "Behind the slab, a mummified priest stands waiting,
            barely alive at best, impossibly venerable."
       Description "He is desiccated and hangs together only by will-power. Though his
            first language is presumably local Mayan, you have the curious
            instinct that he will understand your speech."

       OnAction: [

               ;ask
                       var seln = input.snoun2

                       if ( seln = "dictionary" ) or ( seln = "book" ) then
                               if ( dictionary.getvalue(correct) = 0 ) then
                                       currentplayer.print "~The ~bird~ glyph... very funny.~"
                                       end
                               else
                                       currentplayer.print "~A dictionary? Really?~"
                                       end
                               endif
                       endif

                       if ( seln = "glyph" ) or ( seln = "glyphs" ) or ( seln = "mayan" ) or ( seln = "dialect" ) then
                               currentplayer.print "~In our culture, the Priests are ever literate.~"
                               end
                       endif

                       if ( seln = "lord" ) or ( seln = "tomb" ) or ( seln = "shrine" ) or ( seln = "temple" ) then
                               currentplayer.print "~This is a private matter.~"
                               end
                       endif

                       if ( seln = "paintings" ) then
                               currentplayer.print "The calendrical priest frowns. ~10 baktun, 4 katun, that makes 1,468,800 days since the beginning of time: in your calendar 19 January 909.~"
                               end
                       endif

                       if ( seln = "ruins" ) then
                               currentplayer.print "~The ruins will ever defeat thieves. In the underworld, looters are tortured through eternity.~ A pause. ~As are archaeologists.~"
                               end
                       endif

                       if ( seln = "web" ) or ( seln = "wormcast" ) then
                               currentplayer.print "~No man can pass the Wormcast.~"
                               end
                       endif

                       if ( seln = "xibalba" ) then
                               if ( shrine.SW = junction.id ) then
                                       currentplayer.print "The priest shakes his bony finger."
                                       end
                               else
                                       currentplayer.print "The priest extends one bony finger southwest toward the icicles, which vanish like frost as he speaks. ~Xibalba, the Underworld.~"
                                       shrine.SW = junction.id
                                       end
                               endif
                       endif

                       currentplayer.print "You must find your own answer."
               endif

               ;tell
                       currentplayer.print "The priest has no interest in your sordid life."
                       end
               endif

               ;attack,kiss
                       this.currentlocation = 0
                       currentplayer.print "The priest desiccates away into dust until nothing remains, not a breeze nor a bone."
                       end
               endif

               ;show,give
                       if ( input.noun = dictionary.nounid ) and ( dictionary.getvalue(correct) = 0 ) then
                               currentplayer.print "The priest reads a little of the book, laughing in a hollow, whispering way. Unable to restrain his mirth, he scratches in a correction somewhere before returning the book."
                               dictionary.setvalue(correct) = 1
                               end
                       endif
                       if ( input.noun = newspaper.nounid ) then
                               currentplayer.print "He looks at the date. ~12 baktun 16 katun 4 tun 1 uinal 12 kin~, he declares before browsing the front page. ~Ah. Progress, I see.~"
                               end
                       endif
                       currentplayer.print "The priest is not interested in earthly things."
                       end
               endif
       ]

       OnTalk: [

               ;go
                       currentplayer.print "~I must not leave the Shrine.~"
                       end
               endif
               currentplayer.print "~It is not your orders I serve.~"
       ]
}

! Same trick again - I am using a dummy object for the priests range
! of understandings.
Item priestwords "the priest's words" {
       StartsIn limbo
       Nouns "dictionary" "book" "glyph" "glyphs" "mayan" "dialect" "lord" "tomb" "shrine" "temple" "paintings" "ruins" "web" "wormcast" "xibalba"
}


Character warthog "Warthog" {
       Nouns "wart" "hog" "warthog"
       Initial "A warthog snuffles and grunts about in the ashes."
       Description "Muddy and grunting."
}
Item warthoglight "warthog light" {
       has light lightsource
}



! -----------------------------------------------------------------------------
! Stuff for dealing with the dark
!
Item soundoftinyclaws "a sound of tiny claws" {
       StartsIn limbo
       Nouns "tiny" "claws" "sound" "scuttling" "scuttle" "things" "creatures" "monsters" "insects"
       StaticMessage "The creatures evade you, chittering."
       has static
       OnAction: [
               ;listen
                       currentplayer.print "How intelligent they sound, for mere insects."
                       end
               endif
               ;touch,taste
                       currentplayer.print "You wouldn't want to. Really."
                       end
               endif
               ;smell
                       currentplayer.print "You can only smell your own fear."
                       end
               endif
               ;attack
                       currentplayer.print "They easily evade your flailing about."
                       end
               endif
               currentplayer.print "The creatures evade you, chittering."
       ]
}

Module DarkDaemon {

proc inthedark

       if ( currentplayer.cansee = false ) then

               soundoftinyclaws.currentlocation = currentplayer.currentlocation

               currentplayer.setvalue(darkturns) = |currentplayer.getvalue(darkturns) + 1|
               var dtur = currentplayer.getvalue(darkturns)

               if ( dtur = 1 ) then
                       currentplayer.print "Somewhere, tiny claws are scuttling."
                       currentplayer.outputtoplayer = false
                       end
               endif

               if ( dtur = 2 ) then
                       currentplayer.print "The scuttling draws a little nearer, and your breathing grows loud and hoarse."
                       currentplayer.outputtoplayer = false
                       end
               endif

               if ( dtur = 3 ) then
                       currentplayer.print "The perspiration of terror runs off your brow. The creatures are almost here!"
                       currentplayer.outputtoplayer = false
                       end
               endif

               if ( dtur = 4 ) then
                       currentplayer.print "You feel a tickling at your extremities and kick outward, shaking something chitinous off. Their sound alone is a menacing rasp."
                       currentplayer.outputtoplayer = false
                       end
               endif

               if ( dtur = 5 ) then
                       currentplayer.print "Suddenly there is a tiny pain, of a hypodermic-sharp fang at your calf. Almost at once your limbs go into spasm your shoulders and knee-joints lock, your tongue swells..."
                       call StandardLib.Dead
                       end
               endif

       else
               currentplayer.setvalue(darkturns) = 0
               soundoftinyclaws.currentlocation = 0
       endif
end
}