#charset "us-ascii"
#include <adv3.h>
#include <en_us.h>
#include "AHA.h"

/* 
 *   HellHall.t 
 *
 *   This covers the area of the map the player first encounters on entering 
 *   Hell. 
 */

boilerFloor: defaultFloor
    desc = "It's covered with dusty ash<<boilerHandle.discovered ? ', in the
        midst of which is set a small black handle' : '' >>."
    dobjFor(LookIn) remapTo(LookIn, boilerAsh)
;

insideBoiler: Room 'Inside the Boiler' 'the inside of the boiler'
    "This large metal chamber looks horribly like the inside of some giant
    boiler. Fortunately, judging from the dusty ash on the floor, it\'s been
    quite a while since this one was last lit. The flue pipe down which you
    descended is directly above you, and there's some kind of door to the east,
    in which is set a grimy oval window.  <<boilerHandle.discovered ?
      'Moreover, a small black handle in set into the floor. ' : ''>>"
    up: NoTravelMessage { "The flue pipe is too high up for you to reach, and
        even if you could, there doesn't seem to be much you could get a
        purchase on inside it. You'll just have to hope you can find another
        way back to that golden glow. " }
    east = boilerDoorInside
    out asExit(east)
    vocabWords = 'inside/boiler'
    thinkHere = "You\'re awfully glad that this boiler doesn\'t look like it\'s
        been lit in a while, but you'd really like to get out of here. "
    roomParts = static inherited - defaultFloor + boilerFloor
    roomBeforeAction
    {
        if(gActionIs(Jump))
        {
            "{You/he} jump{s} as high as {it actor/he} can, but {it actor/he}
            still can't reach the flue pipe. ";
            exit; 
        }
    }
    roomAfterAction
    {
        if(gActionIs(Yell))
            "The sound reverberates deafeningly round the inside of the
            boiler. ";
    }
    
    upLook = "Above your head is the mouth of the flue pipe.  "
    eastLook()
    {
        if(boilerDoorInside.isOpen)
            "The door is open, and there's a chamber outside, but you can't see
            much of it from here. ";
        else
            inherited;
    }
    
#ifdef __DEBUG
    verifyDobjPow() { nonObvious; }  
#endif
;

+ RoomPartItem, Distant 'broad flue mouth/opening/pipe' 'flue'
    "The opening of the broad pipe is directly above you. "
    tooDistantMsg = 'You can\'t reach it. '
    specialNominalRoomPartLocation = defaultCeiling
    specialDesc = "In the ceiling is the end of the flue pipe. "
    verifyDobjClimb() { illogical(tooDistantMsg + ' You\'ll have to hope 
        you can find another way to reach that golden glow. '); }
    dobjFor(ClimbUp) asDobjFor(Climb)
;

+ boilerDoorInside : RoomPartItem, IndirectLockable, Door 
    '(east) (e) oval thick brass (boiler) door'   'boiler door'
    "The oval door, in which is set a small oval window, is made of thick
    brass. "
    dobjFor(Lock) maybeRemapTo(boilerHandle.discovered, Push, boilerHandle)
    dobjFor(Unlock) maybeRemapTo(boilerHandle.discovered, Pull, boilerHandle)
    dobjFor(Push) asDobjFor(Open)
    dobjFor(Pull) asDobjFor(Close)
    dobjFor(Attack) asDobjFor(Break)  
    initNominalRoomPartLocation = defaultEastWall
    initSpecialDesc = "A thick brass door is set into the east wall of the
        boiler. "
    shouldNotBreakMsg = 'It\'s made of thick brass, and proves remarkably
        resilient; you can\'t even dent it. '
    futileToKnockOnMsg = 'A hollow knocking sound echoes round the inside of
        the boiler. '
;

class BoilerWindow : Component 'small thick oval grimy window/glass*windows' 
    'small oval window'
    shouldNotBreakMsg = 'The glass proves surprisingly tough -- you fail to
        make any impression on it. '
    cannotCleanMsg = 'You\'d need industrial-strength cleaning materials to
        make much impression on all that grime, and you don\'t have any to
        hand. '
    cannotOpenMsg = 'It\'s fitted in the door, and quite clearly doesn\'t open
        independently of the door. '
    dobjFor(LookIn) asDobjFor(LookThrough)
    dobjFor(Attack) asDobjFor(Break)
;

++ BoilerWindow 
    desc = "The glass on the window is pretty grimy, but you can just make out
        some sort of chamber on the other side. "
    dobjFor(LookThrough) asDobjFor(Examine) 
;


+ boilerAsh: Immovable 'black dusty spent powdery sooty ash/soot' 'dusty ash'
    "The black, sooty ash looks like the remains of the fuel that was consumed
    the last time the boiler was lit. "
    
    dobjFor(LookIn)
    {
        action()
        {
            if(boilerHandle.discovered)
                "You find nothing else of interest in the ash. ";
            else
            {
                "You find nothing of interest concealed in the ash itself, but
                the act of disturbing it while you search reveals a small black
                handle set into the floor. ";
                boilerHandle.discover;
            }
        }
    }
    dobjFor(Search) asDobjFor(LookIn)
    dobjFor(LookUnder) asDobjFor(LookIn)
    dobjFor(Dig) asDobjFor(LookIn)
    dobjFor(LieOn) remapTo(LieOn, boilerFloor)
    dobjFor(SitOn) remapTo(SitOn, boilerFloor)
    nothingBehindMsg = 'It\'s not in front of anything. '
    cannotTakeMsg = 'You don\'t want to be carrying that mucky stuff around
        with you. '
    cannotMoveMsg = 'Merely rearranging the ash seems rather a futile
        exercise. '
    tasteDesc = "It tastes decidedly overcooked. "
    feelDesc = "It feels rather powdery. "
    soundDesc = "As hard as you listen, the ash remains obstinately silent. "
    cannotCleanMsg = 'You forgot to bring an ash-cleaning kit. ' 
    cannotBurnMsg = 'It\'s thoroughly burned already. '
    cannotExtinguishMsg = 'It stopped burning long ago. '
    cannotEatMsg = 'It reminds you too much of your early attempts at cooking. '
    shouldNotBreakMsg = 'You can hardly do that until you work out what 
        unbroken ash would look like. '
    uselessToAttackMsg = 'You are not yet ready to vent your frustration
        on a heap of defenceless ash. '
    notWearableMsg = 'No point -- you don\'t have any sackcloth to go with it
        and there\'s no one around to appreciate such an act of penitence. '
    
;

++ SimpleOdor 'stale air' 'stale air'
    "There's a strong smell of spent ash and stale air. "
;

+ boilerHandle : Hidden, Lever, Fixture 
    'small black handle/lever*handles*levers' 'handle'
    "The small black handle is set into the floor of the boiler. "
    makePulled(pulled)
    {
        if(pulled)
        {
            "The handle is quite stiff, but you just manage to pull it, and as
            you do so you hear a click from the door. ";
            achievement.awardPointsOnce();
        }
        else
            "You push the handle back into its original 
            position<<boilerDoorInside.isOpen ? '' : ', and there\'s
                a corresponding clunk from the door'>>. ";
        
        if(!boilerDoorInside.isOpen) // it can't be locked if it's open.
        boilerDoorInside.makeLocked(!pulled);
        inherited(pulled);
    }
    achievement: Achievement { +1 "unlocking the boiler door" }
    cannotTurnMsg = '{You/he} {can\'t} turn it; it\'s the sort of handle you
        push and pull. '
    dobjFor(Take)
    {
        verify()
        {
            if(isPulled)
                inherited;
        }
        action()
        {
            "You can't take the handle, it\'s fixed in place, but in your
            attempt to take it you pull it instead. ";
            nestedAction(Pull, self);
        }
    }
;

+ Enterable -> boilerDoorInside 'chamber' 'chamber'
    "You can't really see that much of the chamber
    outside<<boilerDoorInside.isOpen ? ', even through the open door' : '
        through the grimy window'>>. "
;



//==============================================================================
boilerRoom : Room 'Boiler Room' 'the boiler room'
    "A huge brass boiler fills at least half the space in this chamber. Much of
    the rest is taken up with the tangle of pipes sprawling out of the boiler,
    some going up through the ceiling, and others disappearing into the walls.
    Otherwise there's not much here apart from a way out to the north. "
    in = boilerDoorOutside
    west asExit(in)
    north = hellHall
    out asExit(north)
    thinkHere = "You're struck by how nineteenth-century everything looks here. "
    lookWest = "Directly to the west is the huge brass boiler. "
;

+ boiler: Enterable -> boilerDoorOutside 
    'huge old brass boiler boiler/casing*boilers' 'boiler'
    "It's a huge brass boiler, with pipes sticking out in all directions
    (though the main one disappears up through the ceiling), a plethora of
    valves, and an oval door. "
    iobjFor(PutIn)
    {
        preCond = [touchObj, objOpen]  
        verify() { }
        action()
        {
            gDobj.moveInto(insideBoiler);
            "{You/he} put{s} {the dobj/him} inside the boiler. ";
        }
    }
    dobjFor(Open) remapTo(Open, boilerDoorOutside)
    dobjFor(Close) remapTo(Close, boilerDoorOutside)
    dobjFor(Unlock) remapTo(Unlock, boilerDoorOutside)
    dobjFor(Lock) remapTo(Lock, boilerDoorOutside)
    isOpen = (boilerDoorOutside.isOpen)
    isLocked = (boilerDoorOutside.isLocked)
    cannotClimbMsg = 'It might be possible to clamber over the boiler, but it
        looks probably difficuly, possibly dangerous, and almost certainly
        pointless. '
;

++ boilerDoorOutside : Lockable, Door ->boilerDoorInside 
    'oval brass (boiler) door*doors' 
    'boiler door'
    "It's an oval door, made of brass, with a small oval window. "
;

+++ BoilerWindow 
    desc = "The window is made of thick glass, and is pretty grimy. "
;

++ Fixture '(boiler) brass various tangle/pipe/pipes' 'boiler pipes'
    "A number of brass pipes protrude from the boiler in a variety of
    directions, but the main one is the flue that heads directly up through the
    ceiling. Most of the others vanish into various walls, presumably to convey
    heat to other regions of hell. "
    isPlural = true
    cannotCleanMsg = 'Perhaps they could do with a bit of a polish, but you
        don\'t have any brass polish to hand, and it might not be the best us
        of your time even if you had. '
    cannotClimbMsg = 'You could conceivably clamber over the pipes, but since
        that wouldn\'t take you anywhere it would be rather pointless. '
    cannotDetachMsg = 'The pipes are too firmly fixed in place to be detached
        from the boiler. '
    feelDesc = "Once upon a time some of those pipes presumably felt piping
        hot, but they\'re all cold now. "
;

++ Distant 'main flue pipe' 'flue pipe'
    "The flue pipe emerges from the top of the boiler and disappears up into
    the ceiling, there, no doubt, to continue its journey to the surface. "
    tooDistantMsg = '{You/he} can\'t reach it. '
;

++ Decoration 'rusted rusty plethora/valve/valves*valves' 'valves'
    "There are a number of valves both on the boiler casing and on the various
    pipes; presumably some of them once controlled the flow of heat, but they
    now all look rusted in place. "
    isPlural = true
    notImportantMsg = 'The valves won\'t do anything now; they\'ve been rusted
        in place far too long. Besides, the boiler is obviously out of
        commission. '
;

+ RoomPartItem, ExitPortal ->hellHall 'way out/archway/exit*exits' 'way out'
    "The only way out from the boiler room is through an archway to the north. "
    specialDesc = "In the north wall is an archway. "
    specialNominalRoomPartLocation = defaultNorthWall
;

+ newspaper: Readable 'old yellowed brittle diabolical full 
    article/newspaper/paper/copy/gazette*papers*newspapers' 'old newspaper'
    "The paper is yellowed and brittle, but it appears to be a copy of the
    <i>Diabolical Gazette</i> dated February 1864.<.p>"
    readDesc = "<<described ? nil : actionDobjExamine()>>
        <<newspaperHeadline.desc>>\b
        The article continues <q>Due to the recent judgment in Privy Council,
        sweeping reforms will need to be implemented throughout the netherworld
        with immediate effect. In particular, now that the nineteenth century
        has clearly turned its back on hell fire, our main boiler (which has
        given many years of sterling service subjecting Hell's inmates to a
        healthy roasting) will be decommissioned. In order to move with the
        times we must devise new psychological methods of torture to replace
        the crude,    old-fashioned physical methods that are now widely seen
        as out of date.</q> "
    initSpecialDesc = "An old newspaper lies abandoned on the ground near the
        boiler. "
    dobjFor(Read)  {  preCond = static inherited + objHeld  } 
    futileToKnockOnMsg = 'The newspaper rustles a little. ' 
    feelDesc = "It feels like paper. "
    soundDesc = "It's a silent paper; talking ones hadn't been invented in
        1864. "
    smellDesc = "It smells a bit musty, but what do you expect after it's being
        left lying around for the best part of a century and a half? "
;

++ newspaperHeadline: Component 'headline' 'headline'
    "The main headline reads: HELL DISMISSED WITH COSTS -- ORTHODOX MEMBERS OF
    THE ESTABLISHED CHURCH DENIED THEIR LAST CHANCE OF EVERLASTING DAMNATION. "
    bulk = 0
    weight = 0
    nothingBehindMsg ='Perhaps you\'d better read the full article. '
;

//==========================================================================

hellHall : Room 'Long Hall' 'the long hall'
    "The purpose of this long hall is not entirely clear, but it looks a bit
    like some long-unvisited corner of a Victorian museum. Few exhibits are
    left, apart from a shelf running along part of the west wall with a strange
    device nearby, but an impressive mural running the length of the east wall
    depicts some of the bloodier events of the nineteenth century.   An exit to
    the south is clearly marked <q>Boiler Room</q>, while at the opposite end
    are archways to the northeast and northwest. A smart brass sign hangs over
    that to the northeast, while an old wooden sign marks that to the
    northwest. Between them, an old oak bureau nestles against the north
    wall. "
    vocabWords = 'long hall'
    south = boilerRoom
    northeast: TravelWithMessage, OneWayRoomConnector, StopEventList {
        -> bunker
        canTravelerPass(traveler)  
        { 
            return traveler.allContents.indexWhich({x: !x.isModern }) == nil; 
        }
        explainTravelBarrier(traveler) 
        { 
            snapDoor.doScript(); 
            if(traveler.allContents.indexWhich({x: !x.isModern && 
                                               x not in (pen, examBooklet)}))
                return;
            if(traveler.allContents.indexOf(pen) && !pen.isModern)
                "It seems even the old ink in the pen is enough to trigger the
                barrier. ";
            else if(traveler.allContents.indexOf(examBooklet) 
                    && !examBooklet.isModern)
                "It appears that even the small amount of old ink used to write
                in the booklet is enough to trigger the barrier. ";
        }
        travelDesc { if(gRevealed('snap-shut')) doScript; }
        eventList = 
    [
        '{You/he} step{s} nervously through the opening, but this time the
        fanged doors mercifully refrain from impeding your progress. ',
        
        'Unencumbered by the past once more, {you/he} venture{s} through the archway a 
        second time, and for a second time the fanged doors hold their peace. ',
        
        'With more confidence, {you/he} step{s} through the archway a third time. ',
        
        '{You/he} pass{es} through the archway uneventfully. '
    ]
        snapDoor: StopEventList {
        [
            new function {
                "As you take a step to the northeast a sharp-fanged double door
                snaps shut across the arch, blocking your exit and very nearly
                parting you from your bodily extremities. You instinctively
                spring back, dropping all your possessions in shock, whereupon
                the door just as suddenly snaps back open again. <<bunker.seen
                  ? '' : '\bYour eyes turn again to the smart brass sign, as
                      you seek to ponder its deeper meaning. '>> <.reveal
                snap-shut> ";
                foreach(local cur in gPlayerChar.contents)
                    if(isPortable(cur))
                {
                    cur.wornBy = nil;
                    cur.moveInto(hellHall);
                }
                fangDoor.makePresent();
            },
                
            'Once again the sharped-fanged double door snaps violently shut
            across the archway, causing you to jump smartly back, although this
            time you just manage to avoid dropping anything; once again you
            sneak an anxious glance at the smart brass sign. ',
            
            'As you approach the arch, the sharp-fanged double door once again
            snaps shut across it, making it impossible for you pass through. '
        ]
        }
        
    }
    northwest: TravelMessage {
        -> viaAntiqua
        "You set off along the passage, which starts off quite well made, but
        becomes cruder the further you advance down it. Victorian plaster-work
        gives way to baroque brickwork, then mediaeval stonework, while the
        sense of crumbling decay steadily grows. At various points along the
        passage murals depict the tortures of the damned, gradually becoming
        more lurid in depiction (if more faded in colouring) as you walk by;
        every now and again you even pass some macabre exhibit, such as a
        rotting pile of wood once intended for the burning of heretics, or some
        rusting rack, poker or iron maiden, once in use as an instrument of
        torture (and in at least one case labelled AD MAIOREM GLORIAM DEI).
        Eventually you come to a point in the passage where there's a door in
        the wall to the north. "
    }
    thinkHere = "You more you look at this place, the more it strikes you as
        being like some abandoned Victorian museum. "
    northwestLook = "To the northwest is an archway marked
        <q>Via Antiqua</q>. <<nwArch.nothingThroughMsg>>"
    northeastLook = "To the northeast is the archway marked
        <q>Via Moderna</q>. <<neArch.nothingThroughMsg>>"
    
    throwDests = [[northwestDirection, nwArch], [northeastDirection, neArch]] 
    
;

+ Readable, Fixture '(ne) (northeastern) smart brass sign*signs' 'brass sign'
    "The brass sign is fixed over the archway in the northeast corner of the hall.
    <<readDesc()>> "
    readDesc = "It reads <q><FONT FACE=TADS-SANS>VIA MODERNA -- Leave The Past 
        Behind!</FONT></q>"     
    nothingBehindMsg = &cannotSeeBehindMsg   
;

+ Readable, Fixture '(nw) (northwestern) old wood wooden sign*signs' 
    'wooden sign'
    "The old wooden sign is fixed over the archway leading northwest.
    <<readDesc>> "
    readDesc = "It reads <q><FONT FACE=TADS-SCRIPT>VIA ANTIQUA
        -- Discover Your Roots!</FONT></q>."
    nothingBehindMsg = &cannotSeeBehindMsg
;

+ nwArch: EntryPortal -> viaAntiqua
    '(nw) (northwest) classical arch/archway/doorway*arches*archways' 
    'northwest arch'
    "The arch in the northwest corner of the wall is of robustly classical
    design. An old wooden sign is attached directly above it. "
    nothingThroughMsg = 'Through the archway you see the start of a long passage
        running to the northwest. '
;

+ neArch: RoomPartItem, EntryPortal -> (hellHall.northeast)
    '(ne) (northeast) art deco arch/doorway/archway*arches*archways' 
    'northeast arch'
    "The arch leading northeast has a distinct art deco look about it. Above it
    is a smart brass sign. "
    specialNominalRoomPartLocation = defaultNorthWall
    specialDesc = "In the north wall are a couple of archways: one, leading
        northeast, labelled <q>Via Moderna</q> and the other, leading
        northwest, labelled <q>Via Antiqua</q>. "
    nothingThroughMsg = 'Through the archway you catch a glimpse of the inside
        of a concrete bunker. '
    iobjFor(ThrowInto)
    {
        verify() { }
        action()
        {
            if(gDobj.isModern)
            {
                inherited;        
            }
            else
            {
                nestedAction(Drop, gDobj);
                "{The dobj/he} sail{s} towards the northeast archway, but {is}
                interrupted in {its dobj/her} flight by a pair of doors
                snapping shut across the opening. {The dobj/he} bounce{s} off
                the doors and fall{s} to the floor, whereupon the doors snap
                open again. ";
            }
        }
    }
;

+ Distant 'long start/passage' 'long passage'
    "The start of the passage appears to be solidly built; you can't see that
    much of it from here but it appears to run for quite a distance. "
    dobjFor(Enter) remapTo(Northwest)
;

+ Distant 'concrete (inside)/bunker' 'concrete bunker'
    "You can't see much of it from here. "
    dobjFor(Enter) remapTo(Northeast)
;

+ fangDoor: PresentLater, Unthing 'sharp-fanged sharp fanged nw northwest
    double door' 
    'double door'
    notHereMsg = 'You can\'t see it right now; it sprang open again
        as soon as you stopped trying to go through the arch. '
    
;

+ impressiveMural : Fixture 'impressive bloodier bloody mural/events' 'mural'
    "Some of the events depicted in the mural look like routine acts of
    torture, murder, enslavement and oppression, although you also recognize
    what appear to be scenes from various nineteenth-century conflicts as the
    American Civil War, the Crimean War, the Franco-Prussian War, and, of
    course, the Napoleonic War. All these scenes contain particularly harrowing
    depictions of agonized soldiers being variously hacked to death and blown
    to bits. A closer examination reveals a number of smirking demons strolling
    unharmed through each scene, often helping to direct the slaughter. "
    initNominalRoomPartLocation = defaultEastWall
    isListedInRoomPart(part) { return isNominallyInRoomPart(part); }
    nothingBehindMsg = 'You can\'t see directly behind the mural, but it would
        not be unreasonable to suppose that you\'d find the wall there. '   
;

++ Component 'extreme crimean american civil napoleonic nineteenth-century
    franco-prussian slaughter/violence/carnage/battle/war*wars*scenes*battles' 
    'wars'
    "All the wars shown in the mural are depicted with extreme violence. "
    isPlural = true
;

++ Component 'harrowing human badly wounded agonized
    depictions/soldiers/participants' 'soldiers'
    "None of the soldiers shown in the mural seem to be doing well; even those
    dishing out the punishment look badly wounded themselves, and the vast
    majority are in the process of being shelled, shot or bayoneted. "
    isPlural = true
; 

++ Component 'smirking demons/denizens/(hell)' 'smirking demons'
    "Although dressed in a variety of military uniforms, the demons in the
    mural are plainly recognizable as demons. Unlike the human participants,
    the demons stride unscathed through the carnage, busily egging the soldiers
    on to slaughter one another. "
    isPlural = true
;

++ Component 'military uniforms' 'uniforms'
    "The uniforms depicted in the picture seem to be of every nation that
    fought at some point during the nineteenth century. "
    isPlural = true
;

++ Component 'routine 
    victims/oppressors/torture/murder/enslavement/oppression/suffering' 
    'suffering'
    "Although warfare is the most prominently portrayed variety of human
    suffering portrayed in the mural, it is not the only one: murder, torture,
    slavery and oppression are all given their due, with as many humans as
    possible depicted as both victims and oppressors, while once again smirking
    demons egg them on. "
    isMassNoun = true
;

+ strangeDevice: CustomFixture 'strange kinetoscope/device*exhibits' 
    'strange device'
    "It comprises a black box mounted on a stout metal pole. Some kind of lens
    or eyepiece protrudes from the front of the box, while a handle stands out
    from one side and a small panel is set in the other. "  
    dobjFor(LookThrough)
    {
        verify() { }
        preCond = [touchObj, objVisible, actorStanding]
        action()
        {
            if(lookingThrough)
            {
                "You continue to look through the eyepiece, and you still don't
                see much but a grey blur. ";
                myFuse.removeEvent();
            }
            else
                "You stoop to look through the eyepiece. You don't see much but
                a grey blur. ";
            lookingThrough = true;
            myFuse = new Fuse(self, &stopLooking, 1);
        }
    }
    iobjFor(PutIn) remapTo(PutIn, DirectObject, deviceCompartment)
    myFuse = nil
    beforeAction
    {
        if(gActionIn(Stand, StandOn) && lookingThrough)
        {
            myFuse.removeEvent();
            stopLooking;      
            exit;
        }    
    }
    lookingThrough = nil
    stopLooking 
    { 
        lookingThrough = nil; 
        myFuse = nil;
        if(gPlayerChar.isIn(location) && gPlayerChar.posture == standing)
            "<.p>You stand up straight again. ";
    }
    cannotTakeMsg = 'It\'s securely fixed in place. '
    shouldNotBreakMsg = 'That would be pointless. '
    uselessToAttackMsg = 'You might damage it, and you\'ve no reason to do
        that. '
    cannotSwitchMsg = 'You can\'t see any switches on the device. '
    cannotTurnOnMsg = &notElectricalMsg
    cannotTurnOffMsg = &notElectricalMsg
;

++ Component 'crude bent metal handle/shaft/grip*handles*shafts*grips' 'handle'
    "The handle is little more than a bent metal shaft with a crude grip. "
    dobjFor(Turn)
    {
        verify() { }
        action()
        {
            local disk = (deviceCompartment.contents.length > 0 ? 
                          deviceCompartment.contents[1] : nil );
            "You turn the handle ";
            if(disk == nil)
                "but nothing much happens. "; 
            else if(strangeDevice.lookingThrough && disk.propDefined(&playVideo))
                disk.playVideo;
            else
                "but nothing much happens apart from a quiet clattering from
                inside the box. ";
            if(fuseID != nil)
                fuseID.removeEvent();
            fuseID = new SenseFuse(self, &doFuse, 1, self, sight);
        }
    }
    fuseID = nil
    doFuse()
    {
        fuseID = nil;
        "The handle stops turning and <<strangeDevice.theName>> falls quiet. ";
    }
    dobjFor(Push) asDobjFor(Turn)
    dobjFor(Pull) asDobjFor(Turn)
    cannotScrewMsg = 'The handle already seems pretty securely fixed. '
    cannotUnscrewMsg = 'There doesn\'t seem to be any way to do that; you can
        turn the handle, but it remains firmly fixed to the device, and you
        can\'t see any screws you could undo, even assuming you had a
        screwdriver. '  
    
;

++ Component 'black box' 'black box'
    "It's about nine inches long, six inches high, and five inches wide.
    A handle sticks out one side, some kind of panel is fixed to the
    other, and a lens protrudes from one end. "
    dobjFor(LookThrough) remapTo(LookThrough, strangeDevice)
    iobjFor(PutIn) remapTo(PutIn, DirectObject, deviceCompartment)
;

+++ Component 'lens/eyepiece*lenses*eyepieces' 'lens'
    "The eyepiece is at about the right height to look through, with just
    a little stooping. "
    dobjFor(LookThrough) remapTo(LookThrough, strangeDevice)
    dobjFor(LookIn) remapTo(LookThrough, strangeDevice)
;

+++ deviceCompartment : OpenableContainer, SingleContainer, RestrictedContainer, 
    Component 
    'small round (black) (box) (some) (kind)/panel/flap/compartment*compartments' 
    'panel'
    "The small panel on the side of the black box is "
    openStatus()
    {
        if(isOpen)
            "open, revealing a small round compartment behind";
        else 
            "about four inches long";
    }   
    descContentsLister : thingContentsLister
    {
        showListEmpty(pov, parent)
        {
            "<<parent.openStatus>>. ";
        }
        showListPrefixWide(itemCount, pov, parent)
        {
            "<<parent.openStatus>>. The compartment
            contain<<parent.verbEndingS>> ";
        }
    }
    makeOpen(stat)
    {
        inherited(stat);
        name = (stat ? 'compartment' : 'panel');
    }  
    bulkCapacity = 2
    validContents = [blackDisk, greyDisk]
    cannotMoveMsg = 'Please be more specific: the panel can be opened or closed. '
    dobjFor(Push) asDobjFor(Close)
    dobjFor(Pull) asDobjFor(Open)
;

++++ blackDisk: Thing  'small smooth black disk/disc*disks*discs' 'black disk'
    "The black disk is wafer thin and about four inches in diameter. A closer
    examination reveals that it has a large number of tiny translucent segments
    distributed evenly round the rim. "
    playVideo = "and all at once you see a crude, jerky black-and-white motion
        picture. A woman in vaguely oriental clothing walks into a garden and
        stares at the mouth of a cave from which a stone has been rolled away.
        Her hand flies to her mouth in an exaggerated gesture of confusion, she
        dashes around in a passable imitation of a headless chicken for a few
        frames, then bumps into the gardener, with whom she gets into a highly
        animated (though silent) conversation. While she is thus distracted a
        pair of workdemons with fiendish smiles and waxed moustaches sneak in
        behind her and, in absurdly accelerated motion, lay a railway line
        running into the cave. They finish and depart just in time for the
        woman to conclude her conversation with the gardner, and turn her
        attention back to the cave. Sparing the new railway tracks no more than
        a cursory glance, she walks along them towards the mouth of the cave,
        but, just as she gets there a steam locomotive thunders out of the cave
        (or is it now a tunnel?) and runs straight over her, while off to the
        side the workdemons giggle away furiously. The short movie ends with
        the gardener giving a despairing shrug and starting to dig a grave next
        to the railway line. <.reveal train-movie>"
;

class DiskSegment : Component 'tiny black square translucent segments/patterns' 
    'translucent segments'
    "The tiny transparent segments are too small to make out clearly with the
    naked eye. Each one seems to have some kind of black pattern etched on it,
    but without a magnifying glass you can't make the patterns out. Each
    segment is roughly square, and they're distributed evenly round the
    circumference of the disk. "
    isPlural = true
    bulk = 0
    weight = 0
    afterAction()
    {
        if(gDobj is in (self, location))
            logRank = 100;
        else if(gDobj is in (greyDisk, blackDisk))
            logRank = 0;
    }
    logRank = 50
    filterResolveList(lst, action, whichObj, np, requiredNum)
    {
        /* 
         *   Don't change the list if there's less than two objects in it, 
         *   or no more than the required number
         */
        
        if(lst.length < 2 && requiredNum != nil && lst.length <= requiredNum)
            return lst;
        
        /* 
         *   If the other disk has been referred to more recently, assume 
         *   that's the one that's meant and remove me from the lst. 
         */  
        if(logRank == 0)
            return lst.subset({x: x.obj_ != self} );
        
        return lst;
    }
;

+++++ DiskSegment
    
;

++ Component 'stout metal pole*poles' 'stout metal pole'
    "It's about five feet high, with one end fixed firmly to the ground and
    the other supporting the black box. "
;

+ Surface, Fixture 'plain wooden shelf*shelves' 'wooden shelf'
    "It's a plain wooden shelf, about four feet long, securely fixed to the
    west wall. "
    initNominalRoomPartLocation = defaultWestWall
    nothingBehindMsg = 'Behind the shelf is the wall. '
;

++ greenBox: ComplexContainer 'dark green box*boxes*exhibits' 'dark green box'
    "The dark green box is unremarkable, apart from its having an openable lid,
    a small black button on one side, and a large brass horn protuding from the
    other. "
    subContainer: ComplexComponent, Openable, SingleContainer, RestrictedContainer {
        validContents = [straussCylinder, silverCylinder]
        makeOpen(stat)
        {
            if(stat && !gAction.isImplicit && contents.length == 0)
                "Opening the green box reveals a green felt lining and a pair
                of brass supports, one at each end of the box. ";
            inherited(stat);
        }
        bulkCapacity = 2
        dobjFor(LookIn)
        {
            action()
            {
                "The box is lined with green felt, and has a pair of brass
                supports inside, one at each end. ";
                if(contents.length > 0)
                    "Between these supports is <<contents[1].aName>>. ";
            }
        }
        iobjFor(TakeFrom)
        {
            precond = [touchObj, objOpen]
        }
    }
    iobjFor(TakeFrom) remapTo(TakeFrom, DirectObject, subContainer)
    
    
    bulk = 4
    weight = 3
    cannotSwitchMsg = 'You can\'t see any switches on the device. '
    cannotTurnOnMsg = &notElectricalMsg
    cannotTurnOffMsg = &notElectricalMsg
;

+++ Button, Component 'small round black button*buttons' 'black button'
    "It's small, black and round, and protrudes just a short way out of the
    side of the dark green box. "
    dobjFor(Push)
    {
        action()
        {
            if(straussCylinder.isIn(location.subContainer))
                "<<greenBox.isOpen ? 'The cylinder starts to turn, and then a'
                  : 'A'>> faint sound of music emanates from the horn on the
                side. You recognize the strains of Strauss's
                <I>Lebenjesuwalzer</i> (<q>Life of Jesus Waltz</q>)<.reveal
                strauss>";
            else if(silverCylinder.isIn(location.subContainer))
                "The <<greenBox.isOpen ? 'cylinder starts to turn, and the' : ''>>
                sound of a crackly chorus
                of scratchy demonic singing emanates from the horn on the side:\b
                <q><i>Onward demon soldiers, egging on to war,\n
                Causing death and havoc; spilling blood and gore!\n
                Onward into battle, see those humans go,\n
                Killing one another, and not their real foe!\n
                Onward demon soldiers, egging on to war,\n
                Causing death and havoc; spilling blood and gore!\b
                
                Like a mighty army, move the silly sods,\n
                Hate and greed and folly liven up the odds!\n
                What with care their wise build up, we can soon destroy,\n
                Knock it down with gun or bomb, they'll use their latest toy!\n
                Onward demon soldiers, egging on to war,\n
                Causing death and havoc; spilling blood and gore!\b
                
                When they build a city, we shall knock it down!\n
                Make them use their weapons to destroy their town!\n
                Dreams of conquering glory leave them in the lurch,\n
                All their work is flattened now except a ruined church!\n
                Onward demon soldiers, egging on to war,\n
                Causing death and havoc; spilling blood and gore!</i></q>";
            else
                "Nothing happens. ";         
        }
    }
;

+++ Component 'large brass horn*horns' 'brass horn'
    "The brass horn reminds you a little of a speaking-trumpet, but
    it\'s fixed to the side of the box. "
    owner = greenBox
;

+++ Hidden, Component '(green) felt lining*linings' 'green lining'
    "The green felt lining covers the base and sides of the interior of the
    box. "   
    discovered = (greenBox.subContainer.isOpen)
    owner = greenBox
;

+++ greenLid: Openable, Component 'openable (green) lid/top*lids' 'green lid'
    masterObject = static location
    owner = greenBox
;

+++ Hidden, Component 'brass notched delicate strip notch/support/pair/notches/supports' 
    'brass supports'
    "Each support is a delicate strip of roughly D-shaped brass, notched at the
    top. "
    isPlural = true    
    discovered = (greenBox.subContainer.isOpen)
    iobjFor(PutIn) remapTo(PutIn, DirectObject, greenBox )
    iobjFor(PutOn)  remapTo(PutIn, DirectObject, greenBox )
    iobjFor(AttachTo) remapTo(PutIn, DirectObject, greenBox)
    iobjFor(FastenTo) remapTo(PutIn, DirectObject, greenBox)
    iobjFor(TakeFrom) remapTo(TakeFrom, DirectObject, greenBox)
    shouldNotBreakMsg = 'That might stop the thing from working, and you\'ve
        no desire to do that. '
    owner = greenBox
;

++ redBox: ComplexContainer 'small red flat box*boxes*exhibits' 'small red box'
    "It's about nine inches by six by three, and has a flat lid. "
    subContainer: ComplexComponent, OpenableContainer {
        bulkCapacity = 6
    }
    iobjFor(TakeFrom) remapTo(TakeFrom, DirectObject, subContainer)
;

+++ redLid: Component 'openable plain flat (red) box lid/top*lids' 'red lid'
    "It's just a plain red box lid, currently <<redBox.isOpen ? 'open' :
      'closed'>>. "
    dobjFor(Open) remapTo(Open, redBox)
    dobjFor(Close) remapTo(Close, redBox)
    owner = redBox
;

class MetalCylinder: Thing 'spiral groove/cylinder/spindles*cylinders'
    bulk = 2
    dobjFor(Remove)
    {
        action()
        {
            if(location != nil && location.ofKind(Container))
            {
                //        reportBefore('(from ' + location.theName + ')\n');
                replaceAction(TakeFrom, self, location);
            }
            else
                inherited;
        }
    }
    cannotTurnMsg = (isIn(greenBox) ? 'If you want it to turn, try pressing the
        black button. ' : 'Turning it there won\'t achieve much. ')
;

+++ straussCylinder: MetalCylinder 'brass small spindly letters/label' 
    'brass cylinder'
    "The brass cylinder is etched with a spiral groove running round its
    surface. A short length of thin spindle protudes from each end. A label
    attached to one end reads <q>Also sprach David Friedrich</q> in small
    spindly letters. "
    bulk = 2
    subLocation = &subContainer
;

+++ silverCylinder: MetalCylinder 'silver -' 'silver cylinder'
    "The silver cylinder is etched with a spiral groove running round its
    surface. A short length of thin spindle protudes from each end. "
    bulk = 2
    subLocation = &subContainer 
;

+++ greyDisk: Thing 'grey gray disc/disk*disks*discs' 'grey disk'
    "The grey disk is wafer thin and about four inches in diameter. A closer
    examination reveals that it has a large number of translucent segments
    distributed evenly round the rim. "
    bulk = 2
    playVideo = "and you find yourself watching a crude, jerky monochrone
        motion picture. In the first half you watch a city growing at breakneck
        speed: it starts out as apparently Graeco-Roman, with classical
        temples, a forum, and statues of ancient gods, as well as Roman-style
        insulae and palaces; then a different set of builders come along and
        construct mediaeval additions: timber-framed houses, a church in the
        form of a basilica, and a grand Gothic cathedral.\b
        But no sooner have the builders finished than the destroyers follow,
        one set after another. First, a mediaeval siege sends rocks from
        mangonels hurtling over among the ancient statues; looting soldiers
        follow, setting fire to the timber-framed houses. Then come men with
        pikes and arquebuses, battling among the palaces and insulae, until
        they too are shattered. Musketmen take up station in the grand
        cathedral, firing on all and sundry until their enemies drag huge
        artillery pieces into the square and pound the cathedral into a pile of
        rubble. Another wave of invaders follow, now armed with nineteenth
        century rifles, crude grenades and primitive machine-guns, battling it
        out among the ruins, until nothing is left standing but the basilica,
        and all else is mud and rubble.\b
        At this point a pair of demons stroll across the scene, and nod to each
        other with evident satisfaction, before holding up a placard that
        reads, <q>And now on to some <i>real</i> destruction!</q>.\b And there
        the silent movie ends.<.reveal movie-seen> <.reveal war-movie>"   
    subLocation = &subContainer
;

++++ DiskSegment
    
;

+ bureau: ComplexContainer, Heavy 'old wooden oak bureau/furniture/desk*desks' 'bureau'
    "It's one of those nice old pieces of furniture that converts into a desk
    when you open the lid. This one has a pair of drawers underneath its lid
    and looks like it's made of oak. "
    subContainer : ComplexComponent, LockableWithKey, OpenableContainer {
        keyList = [brassKey]
        initiallyLocked = true
        initiallyOpen = nil
        makeOpen(stat)
        {
            inherited(stat);
            if(stat)
                achievement.awardPointsOnce();
        }
        achievement: Achievement { +1 "getting the bureau open" }
        cannotOpenLockedMsg = 'The bureau appears to be locked. <.reveal
            bureau-locked>'
        lockStatusObvious = (gRevealed('bureau-locked'))
    }
    shouldNotBreakMsg = 'You have no desire to damage such a nice old piece
        of furniture. '
    uselessToAttackMsg = (shouldNotBreakMsg) 
    hideFromAll(action)
    {
        if(action.ofKind(TakeAction))
            return true;
        return nil;
    } 
    cannotEatMsg = 'That would doubtless give you the most terrible indigestion. '
    nothingBehindMsg = 'It\'s hard against the wall, so there\'s probably
        nothing behind it, but since the bureau is too heavy to move there\'s
        no way {you/he} can actually check. '
    iobjFor(TakeFrom) remapTo(TakeFrom, DirectObject, subContainer)
;

++ inkBottle: Thing 'blue ink bottle/ink*bottles' 'bottle of ink'
    "It's a bottle of blue ink, almost <<used ? 'empty' : 'full'>>. "
    used = nil
    iobjFor(FillWith)
    {
        verify() { }
        action() {
            if(!gAction.isImplicit)
                "{You/he} fill{s} {the dobj/him} with the blue ink from the
                bottle. ";
            gDobj.full = true;
            used = true;
        }
    }
    dobjFor(Open)
    {
        verify()
        {
            /* 
             *   Since this isn't really an openable container it's not the 
             *   ideal target for this action.
             */
            logicalRank(90, 'not container');
        }
        action()
        {
            "You open the bottle of ink and satisfy yourself that there is
            indeed some ink inside, and then close it again to avoid any risk
            of spilling the stuff. ";
        }
    }  
    cannotCloseMsg = 'It isn\'t open. '
    cannotPourMsg = '{You/he} do{es}n\'t want to waste the ink (or make a mess). '
    subLocation = &subContainer
    shouldNotBreakMsg = 'You don\'t want to do that -- you\'ll get ink
        everywhere! '
    cannotCleanMsg = 'It doesn\'t look that dirty. '
    cannotDrinkMsg = 'You\'re not that thirsty. '
    
    iobjFor(PutIn)
    {
        verify()
        {
            if(gDobj == nil && tentativeDobj_ != nil &&
               tentativeDobj_.indexWhich({x: x.obj_ is in (pen, steelRod)}) == nil)
                //        illogical(inkBottleMsg);
                inherited;
            else if(gDobj not in (pen, steelRod))
                //        illogical(inkBottleMsg);
                inherited;
        }
        action()
        {
            if(gDobj == pen)
                replaceAction(FillWith, pen, self);
            if(gDobj == steelRod)
                "{You/he} dip{s} the rod in the bottle of ink, but the small
                amount of ink it collects quickly runs off again, leaving the
                rod useless for writing -- not that it would make much of a pen
                anyway. ";
        }
    }
    inkBottleMsg = '{The dobj/he} probably wouldn\'t fit in the ink bottle,
        and you\'ve no reason to cover {it dobj/him} in ink. '
    notAContainerMsg = iobjMsg(inkBottleMsg)   
    smellDesc = "It has that distinctive inky smell. "
;

class Drawer : OpenableContainer, Component
    'plain-fronted (oak) (wooden) drawer*drawers' 'drawer'
    "It's a plain-fronted wooden drawer. "
    dobjFor(Pull) asDobjFor(Open)
    dobjFor(Push) asDobjFor(Close)
    shouldNotBreakMsg = 'That would be totally unnecessary. '
    cannotCleanMsg = 'You give the front of the drawer a wipe, but it
        doesn\'t seem to make much difference. '
    cannotDetachMsg = 'It\'s probably best to leave the drawers in the bureau. '
    owner = location  
;

++ Drawer 'top -' 'top drawer'  
    //  specialContentsLister = roomPartSpecialDescLister
;

+++ ComplexContainer 'large yellowing yellow crinkled lining 
    piece/paper*pieces*papers' 
    'large piece of lining paper'
    "It's about four feet long and eighteen inches wide; it was probably once
    white, but has long since yellowed. "
    initSpecialDesc = "The inside of the top drawer is lined with yellowing
        lining paper. "
    initDesc = "The paper was once white, but has long since yellowed. It's
        been laid fairly neatly in the bottom of the drawer, but doesn't look
        quite even. "
    feelDesc = "<<brassKey.isIn(subUnderside) ? 'When you run your hand over
        the lining paper you feel a small hard object under it near one end' :
          'It feels just a little rough'>>. "
    subSurface : ComplexComponent, Surface {
        iobjFor(PutOn)
        {
            verify() {
                if(lexicalParent.isIn(gPlayerChar))
                    illogicalNow('{You/he} can\'t put anything on the lining
                        paper while you\'re carrying it.' );
                inherited;    
            }
        }
    }
    subUnderside: ComplexComponent, Underside {
        iobjFor(PutUnder)
        {
            verify() { 
                if(lexicalParent.isIn(gPlayerChar))
                    illogicalNow('{You/he} can\'t put anything under the lining
                        paper while you\'re carrying it.' );
                inherited;  
            }  
        }
    }
    dobjFor(Take)
    {
        action()
        {
            if(subSurface.contents.length > 0)
            {
                "As you pick up {the dobj/him}, ";
                if(subSurface.contents.length == 1)
                    "<<subSurface.contents[1].theName>>";
                else
                    "everything";
                "that was on it slips off. ";
                foreach (local obj in subSurface.contents)
                    obj.moveInto(location);
            }
            inherited;
        }
    }
    iobjFor(TakeFrom) remapTo(TakeFrom, DirectObject, subSurface)
    dobjFor(Pull) maybeRemapTo(!moved, Take, self)  
    hideFromAll(action)
    {
        return !moved && action.ofKind(TakeAction);
    }
    futileToKnockOnMsg = 'There\'s a faint crinkling sound as your hand strikes
        the paper. '
    cannotWriteOnMsg = 'It doesn\'t make a very good writing surface: it\'s too
        yellowed and too crinkled. '
;

++++ brassKey: Hidden, Key 'small plain brass key*keys' 'small brass key'
    "It's a very ordinary, plain small brass key. "
    subLocation = &subUnderside
;

++ Drawer 'bottom -' 'bottom drawer'
;

++ oakLid: Openable, Surface, Component '(oak) (bureau) (desk) lid*lids' 
    'oak lid'
    "Like the rest of the bureau, the lid is made of oak. "
    dobjFor(UnlockWith) remapTo(UnlockWith, bureau, IndirectObject)
    dobjFor(Unlock) remapTo(Unlock, bureau)
    dobjFor(Lock) remapTo(Lock, bureau)
    dobjFor(Open) remapTo(Open, bureau)
    openDesc = ( isOpen ? 'currently open flat, forming a
        convenient writing surface' : 'currently closed, and so sloping at an
            angle of about forty-five degrees'  )
    iobjFor(PutOn)
    {
        verify()
        {
            if(!isOpen)
                illogicalNow('{You/he} can\'t put anything on the lid while
                    it\'s closed (because it\'s sloping at too much of an
                    angle). '); 
            inherited;
        }
    }     
    isOpen = (bureau.subContainer.isOpen)
    dobjFor(Close)
    {
        action()
        {
            if(contents.length > 0)
            {
                "As you close the lid, ";
                if(contents.length == 1)
                    "<<contents[1].theName>>";
                else
                    "everything";
                " resting on it slides off into the bureau. ";
                foreach (local obj in contents)
                    obj.moveInto(bureau.subContainer);
            }
            replaceAction(Close, bureau);
        }
    }
    dobjFor(LookBehind) { preCond = [touchObj, objOpen] }
    owner = bureau
    
    /*  
     *   Experimental means of deciding which lid is meant 
     *
     *   The idea is that if we've just referred to the bureau or its lid, 
     *   then a command directed to an unspecified lid is probably meant to 
     *   refer to the bureau lid, so we filter the resolve list to include 
     *   only the oak lid. Conversely if the red box, green box or their 
     *   lids have been referred to more recently, a command referring purely
     *   to a lid doesn't mean the oak lid, so we remove it from the resolve
     *   list.
     *
     *   But if there's only one lid in the resolve list, we leave it as it 
     *   is (in this case there's no ambiguity to resolve).
     */
    filterResolveList(lst, action, whichObj, np, requiredNum)
    {
        if(lst.length < 2 || lastLidObj == nil)
            return lst;
        
        if(lastLidObj is in (self, bureau))
            return lst.subset({x: x.obj_ == self });
        else            
            return lst.subset({x: x.obj_ != self} );    
    }
    afterAction()
    {
        if(lidObjList.indexOf(gDobj) != nil)
            lastLidObj = gDobj;
        if(lidObjList.indexOf(gIobj) != nil)
            lastLidObj = gIobj;      
    }  
    lastLidObj = nil
    lidObjList = [redBox, greenBox, bureau, oakLid, redLid, greenLid]
;


+ exitToSouth: RoomPartItem, EntryPortal ->boilerRoom 'southern exit*exits' 'exit'
    "The exit to the south is marked <q>Boiler Room</q>. "
    initNominalRoomPartLocation = defaultSouthWall
    initSpecialDesc = "In the south wall is the exit to the boiler room. "
    disambigName = 'southern exit'
    dobjFor(GetOutOf) asDobjFor(Enter)
;

grammar adjWord(exitSouth) :
    'exit' 'to' 'the' 'south'
    : SpecialNounPhraseProd
    getMatchList = [exitToSouth]    
    getAdjustedTokens =
    ['exit', &noun, 'to', &adjective, 'the', &adjective, 'south', &adjective]
;

//==============================================================================

viaAntiqua: Room 'Via Antiqua' 'the Via Antiqua'
    "The only item of interest at this particular point is a small door in the
    wall to the north. The Via Antiqua continues slowly crumbling into
    disrepair towards the northwest, and gradually improving towards the
    southeast.  "
    southeast = hellHall
    northwest: TravelMessage {
        -> antiquity
        "As you walk on from the breach in the wall, the dressed stone gives
        way to crude undressed stone and then to beaten earth. The earthen
        walls become increasingly crumbly the further on you walk, but not
        through vegetation, since nothing lives here, and you sense that
        nothing can. Indeed, the further on you walk, the further you feel that
        any kind of order you can appreciate is slowly giving way to chaos, or
        if not to chaos, then to a kind of order too alien to grasp. "
    }
    north = smallDoor
    thinkHere = "You don't think is a terribly interesting place to hang about in. "
    northwestLook = "The Via Antiqua continues to the northwest, slowly
        crumbing into disrepair. "
    southeastLook = "To the southeast the Via Antiqua runs down a gradually
        improving route. "
    northLook = "Directly to the north is a small door in the wall.
        <<smallDoor.isOpen ? 'The door is open, and you can make out a large
            space beyond. ' : ''>>"
    
    throwDests = [[northDirection, smallDoor]]
;

+ smallDoor: RoomPartItem, Door ->cathedralBackDoor 'small door' 'small door'
    "It leads through the north wall. "
    initNominalRoomPartLocation = defaultNorthWall
    initSpecialDesc = "A small door leads through the north wall. "
;

//===============================================================================

cathedralRoof: RoomPart 'high drab black arched vaulted ceiling/roof' 'arched roof'
    "The high vaulted ceiling soars above you, but is painted a drab black. "
;

cathedral : Room 'Vast Cathedral' 'the cathedral'
    "The inside of this vast cathedral is impressive in its way -- but utterly
    bare. If there ever were any furnishings here, any pews, pulpits, altars,
    fonts or statues, they have been stripped away, leaving this huge, echoing,
    empty space devoid of life or symbolism, apart from its cruciform shape and
    high arched roof, and the dull stained-glass windows. A small back door
    leads out of the cathedral to the south, while a large pair of double doors
    leads northwards. "
    south = cathedralBackDoor
    north = doubleDoors
    roomParts = static inherited - defaultCeiling + cathedralRoof
    thinkHere = "You're not quite sure what to make of this: a cathedral in
        Hell seems so obviously out of place. You wonder whether there's some
        subtle mockery or twist somewhere. <<sgWindows.described ? 'It\'s the
            green-skinned woman depicted in the stained glass windows that
            seems to strike the most discordant note, though apart from her
            strange colouring, you can\'t work out what\'s so disturbing about
            her.' : ''>>"
    
    roomBeforeAction()
    {
        if(gActionIs(Yell))
        {
            "Your voice echoes round the vast empty space. ";
            exit;
        }
    }  
;

+ cathedralBackDoor: RoomPartItem, Door 'small back door' 'back door'
    initNominalRoomPartLocation = defaultSouthWall
    initSpecialDesc = "A small door is set in the south wall, 
        under a row of stained glass windows. "
;

+ doubleDoors: RoomPartItem, Door 'large double pair/doors' 'large double doors'
    isPlural = true
    makeOpen(stat)
    {
        inherited(stat);
        if(stat && steelRod.isIn(nil))
        {
            "As you swing open the doors, you catch sight of something drop
            from one of the hinges, and hear it clatter onto the cathedral
            floor. ";
            steelRod.moveInto(location);
            steelRod.moved = nil;
            if(gPlayerChar.canSee(steelRod))
                gSetSeen(steelRod);
        }
    }
    initNominalRoomPartLocation = defaultNorthWall
    initSpecialDesc = "A large pair of double doors is set in the north wall. "
;

++ Component 'steel hinge/hinges' 'steel hinges'
    "Both doors are hung on a number of steel hinges. "
    isPlural = true
    iobjFor(PutIn)
    {
        verify() {}
        check()
        {
            if(gDobj == steelRod)
                failCheck('You can\'t find which hinge the rod dropped out
                    of. ');
            else
                failCheck('{That dobj/he} won\'t fit in any of the hinges. ');
        }
    }
;

+ Vaporous 'cruciform (cathedral) (ground) shape/plan' 'cruciform shape'
    "As part of its symbolism, the cathedral ground plan is roughly in the
    shape of a cross, though why that symbolism should seem appropriate in hell
    escapes you. " 
;

+ sgWindows: CustomFixture, Distant 'dull stained glass stained-glass windows' 
    'stained-glass windows'
    "They look dull because the light from outside is so poor. Most of them
    contain scenes of conventional piety, but there seems to be a particular
    concentration on the Empty Tomb and Jesus walking on the sea, as well a
    particularly prominent representation of Moses and his rod. A couple of
    windows show something rather less conventional, however: a green-skinned
    woman with a mass of orange hair. Stranger still, one of the windows
    depicts a blonde woman drowning in a swamp. But the largest and most
    striking window depicts a glorious golden celestial city. <.reveal
    green-skin>"
    isPlural = true
    initNominalRoomPartLocation = defaultNorthWall
    cannotTakeMsg = 'That\'s plainly impracticable. '
    shouldNotBreakMsg = 'Only a philistine, a vandal or a puritan would go
        around breaking antique stained-glass windows in a cathedral, and
        you\'re none of those things. '
;

++ Component, Distant 'most breathtaking striking celestial largest 
    glorious golden city/glow/(window)'
    'celestial city'
    "The celestial city looks breathtaking: a place of ultimate felicity and
    bliss. Your heart leaps at the sight; you feel certain that this must be
    the city you saw as a distant golden glow across the chasm, and the sight
    of it renews your determination to find a way through hell to some place
    where you can reach that city. "   
;


++ Component, Distant 'jesus walking on (the) christ/(sea)/(water)' 'Jesus'
    "Where Jesus appears in the stained-glass windows he\'s generally depicted 
    as walking on the sea. "
    isHim = true
    isProperName = true
;

++ Component, Distant 'dark blue sea/water' 'sea'
    "The sea in the windows is shown as dark blue. "
;

++ Component, Distant 'empty tomb/scene' 'empty tomb'
    "There are various conventional depictions of the Empty Tomb scene in the
    stained-glass windows, but none of them is especially noteworthy. "
;

++ ggWoman: Component, Distant 'tall lithe beautiful angular green-skinned green 
    skin long-haired redhead/woman*women' 'green-skinned woman'
    "In all the windows in which she appears, she's depicted as tall, lithe,
    long-haired and angular; you can't quite make up your mind whether she's
    also meant to be beautiful. She is in a way -- but it's quite a harsh kind
    of beauty. "
    isHer = true
;

++ sgBlonde : Component, Distant 'blonde drowning woman felicity hope/woman*women'
    'blonde woman'
    "Although you can't be absolutely sure who she's meant to be, the blonde
    woman bears a striking resemblance to Felicity Hope. And a very strange
    thing happens as you stare at the window in which she's pictured: it's
    almost as if you can see her struggling, and as if from time to time she
    turns to you with a mute appeal for help. <.reveal felicity-picture>"   
    isHer = true
;

++ Component, Distant 'bubbling mass/swamp/muck/marsh' 'swamp'
    "It's depicted as a mass of bubbling muck. "
;

+++ Component, Distant 'exceptionally striking bright very long orange hair' 
    'orange hair'
    "In addition to be a striking shade of bright orange, in all the windows in
    which it's shown, the green woman's hair is depicted as being exceptionally
    long, falling almost to her thighs. "
    isMassNoun = true
;

++ moses: Component, Distant 'moses' 'Moses'
    "Moses is depicted in the window performing the serpent-rod trick described
    at Exodus 4:1-5. "
    isProperName = true
    isHim = true
;

++ Decoration, Distant 'moses\' tail/rod/serpent' 'Moses\' rod'
    "Moses' rod is shown in the process of being turned back from serpent to
    rod as Moses picks it up by the tail. "
    isQualifiedName = true   
    notImportantMsg = 'You can\'t do that; it\'s part of the window. '
;


+ Distant 'conventional scenes/piety' 'scenes'
    "Most of the scenes in the stained-glass windows depict the Empty Tomb,
    or Jesus walking on the sea. At least one of them, however, is
    devoted to Moses. "
    isPlural = true
    tooDistantMsg = '{You/he} can\'t reach them. '
;


+ SimpleNoise 'utter dying silence/echoes/footfall' 'sound'
    "Silence, utter silence, apart from the dying echoes of your own footfall. "
;

steelRod: Thing 'short thin narrow metal steel rod/pin' 'short steel rod'
    "It's very narrow, no more than a few millimetres in diameter, and only a
    few centimetres -- say about three inches (you find it so much easier to
    think in the old imperial units) -- in length. "
    initSpecialDesc = "A short steel rod lies on the ground near the door. "  
    useSpecialDescInRoomPart(part) 
    {
        return !moved && part==defaultFloor;
    }
    cannotTurnMsg = 'Turning the rod doesn\'t achieve anything. '
;

//===================================================================================

ancientCity : OutdoorRoom 'City Square' 'the city square'
    "A huge Gothic cathedral stands immediately to the south of this large city
    square, while directly to the east lies a large basilica. A mixture of
    classical and Gothic buildings surrounds the other sides of the square,
    while long streets lead off to north and west. "
    south = cathedralDoors
    north : FakeConnector {
        "You stroll up the northern street past an ancient classical temple, a
        large Colliseum, and a disused market forum. Everywhere you look gives
        the impression of decaying grandeur; but it is silent decaying
        grandeur: there is not a soul in sight and the place is utterly dead,
        so after wandering round for a while you return to the central
        square. "      
    }
    east = narthex   
    west = statueStreet
    vocabWords = 'city square'
    thinkHere = "The city looks very grand, but it feels deserted. You wonder
        when anyone else was last here. You also wonder about the existence of
        this city in Hell -- it seems a bit long-abandoned to be Dis --  and
        about its having both a cathedral and a church. Perhaps the emptiness
        of the city is somehow the point. "
    actorKnowsDestination(actor, conn)
    {
        if(conn==east) return true;
        return inherited(actor, conn);
    }
    southLook = "Immediately to the south is the cathedral. "
    eastLook = "To the east lies a large basilica. "
    northLook = "A long street leads off to the north. "
    westLook = "A long street leads off to the west. "
    defaultLook(dir) { "The square is surrounded by a mixture of classical
        and Gothic buildings. "; }
;

+ Enterable -> cathedralDoors 'huge towering gothic cathedral' 'cathedral'
    "The cathedral, Gothic in design, and towering in scope, totally dominates
    the southern side of the square, elbowing all other buildings aside. It
    looks vaguely reminiscent of the great cathedral at Chartres, and totally
    out of place in an ancient city in hell. "
    tasteDesc = "You don't feel inclined to taste the masonry. "
;

+ SimpleNoise 'silence' 'silence'
    "The silence is deafening, as they say. "
;

+ cathedralDoors : Door ->doubleDoors 'large double cathedral doors' 
    'cathedral doors'
    "A large pair of doors lead back into the cathedral. "
    isPlural = true
;


+ Enterable ->narthex 'large church/basilica' 'large basilica'
    "The large basilica stands modestly on the east side of the square; it may
    be large for a basilica, but it is totally dwarfed by the cathedral to the
    south. In antiquity many basilicas were originally Roman administrative
    buildings (such a law courts), but this one appears to be some kind of
    church. "
    tasteDesc = "You don't feel at all inclined to taste the masonry. "
    nothingBehindMsg = &cannotSeeBehindMsg
;

+ Distant 'long streets' 'long streets'
    "Long streets lead off to both north and west. "
    isPlural = true
;

+ Decoration 'other classical gothic mixture/buildings' 'other buildings'
    "A mixture of classical and gothic buildings surround the square, the most
    notable being the Gothic Cathedral to the south and the classical basilica
    to the east. "
    isPlural = true
    tasteDesc = "You don't feel inclined to taste the masonry. "
;

//===================================================================================

statueStreet : OutdoorRoom 'Street of Statues' 'the street of statues'
    "The street leading west from the square is lined with ancient stone
    statues on both sides. To the north, behind some of the most prominent
    statues, lies a large pagan temple. "
    east = ancientCity
    north = paganTemple
    west: FakeConnector {
        "Beyond the statues the street leads on into an endless residential
        district where Roman <i>insulae</i> jostle with mediaeval cottages and
        near-eastern hovels. You wander round for what seems like half an
        eternity, but find nothing more interesting than a few shards of broken
        pottery, even when you overcome your strange reluctance to look inside
        some of the buildings. But perhaps your reluctance is not so strange,
        since everything is so grey, and a strong sense of death and decay
        hangs over all. Of life there is no sign at all: the only thing that
        moves is the dust you disturb by your passage. When you finally decide
        you can bear it no more, you wander back to the street of statues. "
    }
    thinkHere = "The mixture of statues here strikes you as seriously odd. "
    westLook = "The street continues to the west. "
    eastLook = "To the east, the street runs back to the main square. "
    northLook = "To the north lies the entrance to a pagan temple. "
    defaultLook(dir) { "Both sides of the street are lined with ancient 
        stone statues. "; }
    enterRoom(traveler) { traveler.lastStatueLoc = self; }
;

+ Enterable ->ancientCity 'main square' 'main square'
    "It lies to the east, at the end of the street. "
;

+ stoneStatues : Fixture 'ancient pagan christian (stone) angelic saint st. 
    peter/zeus/statues/saints/deities/figure/madonna/child/isis/horus/figure' 
    'ancient stone statues'
    "Although the statues are fixed and unmoving, there seems to be something
    strangely fluid about them, since you're not quite sure whether you're
    looking at pagan deities, Christian saints, or demonic counterfeits. You
    stop before a statue of a tall, patriarchal, bearded man and can't decide
    whether it's Zeus, St Peter, or Professor Wortschlachter. The angelic
    figure at the end of the row suddenly looks demonic when viewed close to.
    The face of the stone madonna looks strangely like that of Felicity Hope -
    but then you are undecided whether you are looking at madonna and child or
    Isis and Horus. But the <<womanStatue.extraDesc>>"   
;

+ womanStatue : Fixture 'tall lithe long-haired most female woman striking 
    statue/woman' 
    'statue of a tall woman'
    "The <<extraDesc>> "
    extraDesc = "most striking statue is that of a tall, lithe woman with very
        long hair, which stands prominently just in front of the pagan temple.
        <<gRevealed('green-skin') ? 'She reminds you strongly of the
            green-skinned woman you saw depicted in the some of the
            cathedral\'s stained-glass windows. ' : ''>>"
    isHer = true
    isIt = true
;

++ Component 'very long hair' 'very long hair'
    "The statue is depicted with hair falling to below her waist. "
    feelDesc = "It's hard stone, like the rest of the statue. "
    cannotMoveMsg = 'It\'s fixed firmly to the statue and doesn\'t move. '
;

+ Enterable ->paganTemple 'classical entrance large pagan temple/portico' 
    'pagan temple'
    "The temple is of austerely classical design, with gleaming white pillars
    framing the entrance portico. "
    nothingBehindMsg = &cannotSeeBehindMsg
;

+ Decoration 'classical gleaming white pillars' 'white pillars'
    "The pillars are of classical style; collectively 
    they frame the portico. "
    isPlural = true
;

//==============================================================================
narthex: Room 'Narthex of Basilica' 'the narthex'
    "This small chamber is little more than an antechamber to the nave, which
    lies through an archway to the east. A dusty stone font squats by the exit
    back out to the street, to the west, while a flight of steps leads down
    into the crypt below. "
    west = ancientCity
    out asExit(west)
    down = basilicaSteps
    east = nave
    thinkHere = "You can't see much here that catches your interest. "
    enteringRoom(traveler)
    {
        foreach(local cur in ruinNarthex.contents)
            if(isPortable(cur))
            cur.moveInto(self);
    }
    outLook = "The western exit looks out over the city square. "
    throwDests = [[eastDirection, narthexEastArch], [westDirection, narthexSquare]]
;

+ narthexEastArch: RoomPartItem, EntryPortal -> nave 
    'open rounded archway/arch*arches*archways' 'archway'
    "It's quite a rounded arch, open to the nave beyond. "
    initNominalRoomPartLocation = defaultEastWall
    initSpecialDesc = "In the east wall is an archway leading through to 
        the nave. "
    nothingThroughMsg = 'Through the archway you can see part of the nave. '
    nothingBehindMsg = &cannotLookBehindMsg
;

+ narthexSquare: Enterable ->ancientCity 'large city square' 'city square'
    "The large city square lies outside to the west. "
    nothingBehindMsg = &cannotLookBehindMsg
;

+ basilicaSteps : StairwayDown, Platform 'stone flight/steps/stairs' 
    'flight of stone steps'
    "The steps lead down to the crypt. "
;

+ Enterable ->nave 'nave' 'nave'
    "You can't see much of it from here; it lies through the archway to the
    east. "
    nothingBehindMsg = &cannotSeeBehindMsg
;


font: MultiLoc, Fixture, Container 'dusty stone font' 'stone font'
    "It's possible that the font once contained water, but it's as dry as dust
    now; but then who would conduct a baptism in hell? "
    cannotFillMsg = 'Since {you/he} {have} no immediate plans to conduct a
        baptism, there wouldn\'t appear to be much point in filling the
        font with anything. '
    locationList = [narthex, ruinNarthex]  
    bulkCapacity = 30
;


DistanceConnector [nave, apse]
;

//=================================================================================
nave: Room 'Nave' 'the nave'
    "This large rectangular area is broken up by two rows of columns leading
    from the narthex to the west towards the apse to the east. Every now
    and again some trick of echo or wind sounds like voices whispering. "
    west = narthex
    east = apse
    out asExit(west)
    in asExit(east)
    roomParts = static inherited - defaultEastWall
    thinkHere = "You think there's something decidedly spooky about this place.
        It's not just the hint of whispering, it's the very notion of building
        a place of worship in hell. You can't quite <i>see</i> anything wrong
        with it, but you feel there must be some kind of subtle mockery or
        blasphemy intended in it. "
    eastLook = "To the east lies the apse, at the back of which is a 
        colourful mosaic. "
    westLook = "To the west lies the way back out into the narthex. "
    throwDests = [[eastDirection, naveApse]]
;

+ SimpleNoise 'ghostly dry whispering hint/trick/echo/wind/chorus/voices/whispers' 
    'voices'
    "Just at the threshold of audibility, or perhaps just below it, you seem to
    hear a chorus of ghostly whispering voices intone, <q><i>kyrie eleison;
    christe eleison</i></q>, but the whispers are as dry as dust, and you're
    not sure you really hear them: it might just be your imagination, or a
    trick of the basilica's acoustics. "
    isPlural = true
    soundSize = large
;

+ SimpleOdor 'stale faint whiff/incense/air' 'incense'
    "You're not quite sure, but you think you may just detect a faint whiff 
    of incense -- but perhaps it's just the stale air here. "
    soundSize = large
;

+ Decoration 'two smooth cylindrical rows/columns/pillars' 'columns'
    "Two rows of smooth cylindrical pillars run down the length of the nave. "
    isPlural = true
;

+ naveApse: Enterable, Distant ->apse 'apse' 'apse'
    "The apse is a semi-circular area to the east, with a colourful mosaic
    on its curved east wall. "
    remoteDesc(pov)
    {
        if(pov == apse)
            apse.desc;
    }
    futileToKnockOnMsg = 'You can\'t do that from here. '
;

//==============================================================================
apse: Room 'Apse' 'the apse'
    "The apse is a semi-circular area that once formed the sanctuary from which
    worship would have been conducted -- if worship ever was conducted in this
    strange corner of hell. There is nothing left here now apart from the bare
    stonework and a colourful mosaic on the east wall of the apse. "
    roomParts = static inherited - defaultWestWall
    west = nave 
    out asExit(west)  
    thinkHere()
    {
        if(gRevealed('mosaic-desc'))
            "You wonder why the mosaic depicts <i>that</i> particular scene,
            and whether its significance is to be understood from a devout or a
            diabolical perspective. It would be possible to see the mosaic as a
            thoroughly orthodox portrait of Christ triumphantly treading the
            waves, but it would also be possible to see it as a subversive
            portrait of an uncaring Christ striding showily over the sea
            leaving his disciples in imminent danger of drowning. ";
        else
            "You think the mosaic may be worth a closer look. ";
    }
    westLook = "To the west lies the nave. "
    outLook = (westLook)
;

+ Decoration 'bare stonework/stone' 'bare stonework'
    "Just floor and walls. Apart from the mosaic the apse is quite unadorned:
    there's no choir stall, pulpit, or altar as one might expect here. "
;

+ mosaic: RoomPartItem, Fixture 'colourful mosaic/tiles' 'colourful mosaic'
    "The mosaic is an iconic representation of a triumphant Christ, his head
    surrounded by a golden nimbus, treading purposefully across storm-tossed
    waters while a bunch of frightened men look on from a frail fishing-boat.
    One of the men in the boat is half-standing, as if contemplating stepping
    over the edge.<.reveal mosaic-desc>"
    remoteDesc(pov)
    {
        "You can't make out all the details from here: the predominant colours
        are blue and brown, representing a boat in possible difficulty on a
        storm-tossed sea or lake. ";
    }
    initNominalRoomPartLocation = defaultEastWall
    initSpecialDesc = "On the east wall of the apse is a colourful mosaic. "
    nothingBehindMsg = 'Short of chipping the mosaic off the wall, which
        you\'re not prepared to do, there\'s no way you can actually look
        behind it; but it seems entirely obvious that were you to do so all
        you\'d find is the wall. '
;

++ Component 'iconic triumphant jesus christ/figure/representation/messiah' 
    'Christ'
    "The Christ in this representation looks very European, with long dark hair
    and a beard on a pale face. He is shown trampling the waves underfoot as he
    walks in the general direction of the fishing-boat. "
    isHim = true
    nothingBehindMsg = &cannotLookBehindMsg
;

+++ Component 'golden gold nimbus/halo/circle/head' 'nimbus'
    "The nimbus (or halo) is a gold circle surrounding the head of the
    Christ-figure on the mosaic. "
    nothingBehindMsg = &cannotLookBehindMsg
;

+++ Component 'pale typically european face/features' 'pale face'
    "Christ's face on the mosaic is depicted with typically European features. "
    nothingBehindMsg = &cannotLookBehindMsg
;

++ Component 'frail small crowded brown wooden fishing boat/fishing-boat' 
    'fishing-boat'
    "The frail wooden fishing-boat looks small and crowded, and in imminent
    danger of being either swamped or smashed by the raging sea. "
    nothingBehindMsg = &cannotLookBehindMsg
;

++ Component 'brilliant blue raging highly stylized storm-tossed 
    sea/lake/waters/water/waves' 'sea'
    "The mosaic uses a brilliant blue to depict the sea, which takes up at
    least half the picture. It's shown with some highly stylized waves tossing
    the boat and seemingly raging all around the Christ-figure. "
    nothingBehindMsg = &cannotLookBehindMsg
;

++ Component 'frightened standing frightened-looking men' 'frightened-looking men'
    "The men in the boat have various expressions of terror on their faces;
    since they're all looking out over the storm-tossed sea towards the figure
    trampling the waves it's not clear whether it's the storm or the
    sea-walking figure that's terrifying them the most. One of them, shown
    half-standing as if about to leave the boat, has his eyes clearly fixed on
    the Christ who's trampling the waves towards them. "
    isPlural = true
    nothingBehindMsg = &cannotLookBehindMsg
;

//=============================================================================

cryptNorthWall : defaultNorthWall
    dobjFor(Push) remapTo(Push, gardenPainting)
    dobjFor(Attack) remapTo(Push, gardenPainting)
;

crypt: Room 'Crypt' 'the crypt'
    "This crypt is strangely like a small cave. The walls are smooth-hewn into
    the rock, and to one side sits a smooth stone slab, large enough for a
    single body, set in an <i>arcosolium</i> niche. <<northDesc>> way out is
    back up the stone steps. "
    roomRemoteDesc(pov)
    {
        "Through the square opening to the south you look into the crypt, a
        small cave-like room with smooth-hewn walls. ";
    }
    northDesc()
    {
        if(gardenPainting.isOpen)
            "A circular opening in the north wall leads out into a dark cave;
            the only other";
        else
            "On the north wall is painted what at first sight looks like an
            exit from the cave overlooking a garden, but even a cursory glance
            dispels this illusion. The only real";   
    }
    northLook()
    {
        if(gardenPainting.isOpen)
            describeRemoteRoom(gardenCave);
        else
            inherited;
    }
    up = cryptSteps
    north = gardenPainting
    out : ConditionalConnector { 
        -> cryptSteps
        ": north or up"
        @(gardenPainting.isOpen)
    }
    roomParts = static inherited - defaultNorthWall + cryptNorthWall
    thinkHere = "Strangely, although this looks like a tomb, it's not obvious
        that anyone's ever been buried here (but then, what would be the point
        of burying anyone in hell?). You strongly suspect that this crypt is
        more iconic than practical in function. "   
;

+ SimpleOdor 'stale musty smell/odor/odour/air' 'musty smell'
    "The air smells stale and musty here, although there's nothing like the
    stench of rotting flesh. "
;

+ arcosolium: Fixture 'arch-shaped arcosolium niche/recess' 
    '<i>arcosolium</i> niche'
    "It's an arch-shaped burial recess cut into the east wall of the crypt,
    large enough to allow a body to be laid out parallel to the wall. "
    aName = ('an ' + name)
    initNominalRoomPartLocation = defaultEastWall
    iobjFor(PutIn) remapTo(PutOn, DirectObject, slab)
    occluded = true
    nothingBehindMsg = 'There\'s nothing behind it but the wall. '
;


+ slab: Bed, Fixture 'smooth bare empty stone slab' 'smooth stone slab'
    "The slab is hard against the east wall of the crypt, and would be just
    about large enough (though not very comfortable) to lie on. A closer
    examination reveals some carvings on the side of the slab. "
    reachableObjects = [arcosolium, defaultEastWall]
    nothingBehindMsg = 'There\'s nothing behind it but the wall. '
;

++ Component 'panel/triptych*panels*carvings' 'carvings'
    "The carvings form a triptych. The first panel shows two bearded men in
    middle eastern dress manhandling a corpse into a rock tomb while a huddle
    of frightened women look on from the distance; the second depicts an angel,
    complete with wings and halo, rolling away the stone from the mouth of the
    tomb; the third shows a young man in a shroud-like robe gesturing towards a
    bare stone slab just like the one you're looking at. "
    isPlural = true  
    nothingBehindMsg = 'Behind the carvings is the slab they\'re carved on. '
;

+++ Component 'two carved bearded man*men' 'bearded men'
    "Both men are bearded and clothed in flowing robes. One is holding the feet
    of the corpse, while the other has his hands under the corpse's armpits and
    is backing into the mouth of the tomb. "
    isPlural = true
    occluded = true
    nothingBehindMsg = &cannotLookBehindMsg
;

+++ Component 'pallid figure/body/corpse*corpses*bodies*figures' 'corpse'
    "The corpse is a pallid figure dressed only in a loincloth. Close
    inspection reveals indentations in his hands and feet, presumably
    representing the nail-marks from crucifixion. "
    occluded = true
    nothingBehindMsg = &cannotLookBehindMsg
;

++++ Component 'narrow strip/loincloth/cloth' 'loincloth'
    "It's depicted as a narrow strip of cloth modestly covering the middle of
    the corpse. "
    occluded = true
    nothingBehindMsg = &cannotLookBehindMsg
;

++++ Component 'pierced hands/hand' 'pierced hands'
    "Both hands of the corpse are visible, bearing the imprint of the nails. "
    isPlural = true
    occluded = true
    nothingBehindMsg = &cannotLookBehindMsg
;

+++++ Component 'round imprint/(nails)/nail-marks/indentations/imprints' 'imprint'
    "The imprint of the nails is represented by a round indentation in the
    hands and feet. "  
    occluded = true  
    nothingBehindMsg = &cannotLookBehindMsg
;

++++ Component 'bare feet/foot' 'bare feet'
    "The bare feet of the corpse are shown bearing the imprint of a nail. "
    isPlural = true
    occluded = true
    nothingBehindMsg = &cannotLookBehindMsg
;

+++ Component 'rock tomb' 'rock tomb'
    "The rock tomb shown in the carvings could almost have been modelled on the
    crypt you're <<gActor.posture.participle>> in, except that it's depicted as
    set in the kind of garden painted on the north wall. "
    occluded = true
    nothingBehindMsg = &cannotLookBehindMsg
;

+++ Component 'frightened crouching huddle/women*women' 
    'frightened huddle of women'
    "The women are shown peering at the tomb from behind a tree, some distance
    away, with their robes covering their heads. "
    occluded = true
    nothingBehindMsg = &cannotLookBehindMsg
;


+++ Component 'androgynous angel/figure*figures*angels' 'angel'
    "The angel is rather conventionally depicted: an androgynous figure with
    long wavy hair and a pair of wings, effortlessly rolling away the circular
    stone as if it were made of polystyrene. "
    occluded = true
    nothingBehindMsg = &cannotLookBehindMsg
;

++++ Component 'pair/wings/shoulders' 'wings'
    "The angel's wings sprout from behind his shoulders in typically angelic
    fashion; they don't look all that aerodynamically effective, but they make
    it quite obvious that the person they belong to is an angel. "
    isPlural = true
    occluded = true
    nothingBehindMsg = &cannotLookBehindMsg
;

++++ Component 'long wavy hair' 'long wavy hair'
    "The angel's long wavy hair helps make him look rather effeminate,
    contributing to the angel's androgynous portrayal. "
    occluded = true
    nothingBehindMsg = &cannotLookBehindMsg
;

++++ Component 'carved round circular nimbus/halo/circle' 'halo'
    "The angel's halo is depicted as a circle carved round his head. "
    occluded = true
    nothingBehindMsg = &cannotLookBehindMsg
;

+++ Component 'young man/youth*men' 'young man'
    "The young man appears to be draped in a shroud. He is shown in a dramatic
    pose, one hand pointing to the empty slab. Despite his youth something
    about his face reminds you of Professor Wortschlachter. "
    occluded = true
    nothingBehindMsg = &cannotLookBehindMsg
;

++++ Component 'robe/shroud*robes*shrouds' 'shroud'
    "The carving is uncoloured, but your knowledge of Mark 16:5 makes you think
    of this shroud as white nonetheless, even though you suspect some
    conflation with Mark 14:52."   
    occluded = true
    nothingBehindMsg = &cannotLookBehindMsg
;

+++ Button, Component 'circular round stone*stones' 'round stone'
    "The round stone in the carving looks like it would be about six feet in
    diameter; it's shown in the process of being rolled away by the angel. "
    dobjFor(Push)
    {
        action()
        {   
            "The round stone is stiff, but it moves in just a fraction; ";
            if(gardenPainting.isOpen)
                "nothing else happens. ";
            else
            {
                "then you are startled by a loud <i>bang</i> as the painting on
                the north wall cracks and shatters in a cloud of dust. ";
                gardenPainting.makeOpen(true);
            }
        }
    }
    occluded = true
    nothingBehindMsg = &cannotLookBehindMsg
; 

+ gardenPainting : TravelWithMessage, SecretDoor '(cave) circular
    garden/painting/exit/picture' 
    'painting of a garden' 
    desc()
    {
        if(isOpen)
            "The circular opening leads into a dark cave. ";
        else
            "The picture (which appears to have been painted on something other
            than solid rock) shows a circular exit overlooking a small enclosed
            garden. Over to the left is a tall tree, and to the right a woman
            in a bright red dress, with a grassy sward between them. ";
    }
    initNominalRoomPartLocation = cryptNorthWall
    isListedInRoomPart(part) { return isNominallyInRoomPart(part); }
    cannotTravel() {  "You'd have to be seriously myopic to mistake the
        painting on the north wall for a real exit. ";  }
    dobjFor(Push)
    {
        verify()
        {
            if(isOpen) illogicalAlready('You\'ve already pushed it open. ');
        }
        action()
        {
            "When you give it a stout push the painting gives way with a sharp
            <i>crack</i>, dissolving into dust and fragments and revealing a
            dark and dismal cave beyond. ";
            makeOpen(true);        
        }
    }
    dobjFor(Pull)
    {
        verify()
        {
            if(isOpen)
                inaccessible('There\'s nothing left of it to pull. ');
            else
                illogical('There\'s nothing to get a purchase on to pull it. ');
        }
    }
    dobjFor(Move)
    {
        verify()
        {
            if(isOpen)
                inaccessible('There\'s nothing left of it to move. ');
            else
                illogical('It seems to be fairly well fixed in place. ');
        }
    }
    dobjFor(LookBehind)
    {
        verify()
        {
            if(isOpen)
                inaccessible('There\'s nothing left to look behind. ');
            else
                illogical('{You/he} can\'t see behind it. ');
        }
    }
    makeOpen(stat)
    {
        inherited(stat);
        if(stat)
        {
            name = 'circular exit';
            PresentLater.makePresentByKeyIf('cave-painting', nil);
            PresentLater.makePresentByKey('dank-cave');
            achievement.awardPointsOnce();
            initializeVocabWith('opening');
        }
        
    }
    dobjFor(Break) asDobjFor(Push)
    dobjFor(Attack) asDobjFor(Push)
    dobjFor(LookIn) maybeRemapTo(!isOpen, Examine, self)
    dobjFor(LookThrough)
    {
        action()
        {
            if(isOpen)
                crypt.describeRemoteRoom(gardenCave);
            else
                "You can't see through it. ";
        } 
    }
    dobjFor(Open)
    {
        verify()
        {
            if(isOpen)
                illogicalAlready('You\'ve already opened a way through the
                    painting. ');
            else
                nonObvious;
        }
        action()
        {
            "You can't see any obvious way to open it, but when you press it
            very lightly it bows a little at your touch. ";
        }
    }
    feelDesc()
    {
        if(isOpen)
            "There's not much of it left to touch. ";
        else
            "From touching it, you'd say that the picture had been painted on
            sheet of plywood or something similar. ";
    }
    destination = gardenCave
    travelDesc = "You feel a very strange jarring sensation as you pass through
        the hole where the painting was, as if you've somehow done something
        rather more than pass through a perfectly ordinary hole; it's almost as
        if some other dimension of travel were involved. "
    achievement: Achievement { +1 "finding the way through the painting in the
        crypt" }
    occluded = true
    futileToKnockOnMsg 
    {
        if(isOpen)
            return 'There\'s nothing to knock on. ';
        else
            return 'It sounds surprisingly hollow. ';
    }
;

++ PresentLater, Component 'red red-clad woman*women' 'red-clad woman'
    "The woman is depicted with a pretty face and very long brown hair; in the
    painting she seems to be forever advancing towards the mouth of the tomb. "
    initiallyPresent = true
    plKey = 'cave-painting'
    nothingBehindMsg = &cannotLookBehindMsg
    
;

+++ Component 'very long brown waist-length hair' 'brown hair'
    "Although the woman is facing you, she's painted so you can see her
    waist-length hair spilling out from behind her back. "
    nothingBehindMsg = &cannotLookBehindMsg
;

+++ Component 'bright very long red dress*dresses' 'red dress'
    "It's depicted as a very long dress, completely covering the woman's body
    and legs. "
    nothingBehindMsg = &cannotLookBehindMsg
;

+++ Component 'conventionally pretty face*faces' 'pretty face'
    "It's depicted as a conventionally pretty face. "
    nothingBehindMsg = &cannotLookBehindMsg
;

++ PresentLater, Component 'green grassy sward/grass' 'grassy sward'
    "The grassy sward occupies the foreground and middle ground of the picture,
    forming the bulk of the garden depicted therein. "
    initiallyPresent = true
    plKey = 'cave-painting'
    nothingBehindMsg = &cannotLookBehindMsg
;


++ PresentLater, Component 'tall spreading apple tree*trees' 'apple tree'
    "It's a tall, spreading apple tree, shown in full blossom. "
    initiallyPresent = true
    plKey = 'cave-painting'
    nothingBehindMsg = &cannotLookBehindMsg
;

+++ Component 'full pink white blossom' 'blossom'
    "The blossom, mostly white with just a hint of pink, is depicted as
    covering the tree, making it seem pregnant with the promise of new life. "
    isMassNoun = true
    nothingBehindMsg = &cannotLookBehindMsg
;


+ cryptSteps : StairwayUp, Platform -> basilicaSteps 'stone flight/steps/stairs'
    'flight of stone steps'
    "The steps lead up to the nave above. "
    occluded = true
    nothingBehindMsg = &cannotLookBehindMsg
;

+ PresentLater, Enterable ->gardenCave 'dark dank dismal cave' 'dismal cave'
    "<<gardenCave.desc>>"
    plKey = 'dank-cave'
    occluded = true
    nothingBehindMsg = &cannotLookBehindMsg
;

Occluder, DistanceConnector [crypt, gardenCave]
    transSensingThru(sense)
    {
        return gardenPainting.isOpen ? distant : opaque;
    }
    occludeObj (obj, sense, pov) 
    {
        return !obj.isIn(pov.getOutermostRoom) && obj.occluded;
    }
;


//==============================================================================

dustyFloor : Floor 'rough dusty floor' 'dusty floor'
    "The floor of the cave is rough and covered in dust. "
;

gcCeiling : RoomPart 'strangely even artificial ceiling/roof' 'roof'
    "<<flagstone.isOpen ? flagstone.desc : 'The roof of the cave looks
        strangely even -- so much so that it must be artificial. '>>"
    occluded = true
    
;

gcSouthWall : RoomPart 's south wall*walls' 'south wall'
    "There's a large hole in the south wall. "
    occluded = true
;

gardenCave : Room 'Dank Cave' 'the dank cave'
    "This cave is vaguely reminiscent of the garden in the painting, except
    that everything is dead and dank. In place of the healthy tree is a rotting
    timber pillar; in place of the woman a statue; and in place of the grassy
    sward a dusty floor. "
    south = crypt
    brightness = 2
    up = flagstone
    roomParts = [dustyFloor, gcCeiling, gcSouthWall, defaultWestWall, defaultEastWall,
        defaultNorthWall]
    roomRemoteDesc(actor)
    {
        "Through the opening you look into a cave. <<desc>> ";
    }
    
#ifdef __MULTIROUTE
    down = statueDoor
    out: ConditionalConnector
    {
        -> crypt
        ": south<<flagstone.isOpen ? (statueDoor.isOpen ? ', up or down' : 
                                      ' or up') : ' or down'>>"
        @(flagstone.isOpen || statueDoor.isOpen)
    }
#else
    out : ConditionalConnector
    {
        -> crypt
        ": south or up"
        @(flagstone.isOpen)
    }
#endif
    southLook { describeRemoteRoom(crypt); }
    thinkHere = "This feels a most unwelcoming place, and you wish yourself out
        of it as soon as possible. You also suspect it may provide the
        hermeneutical key to the entire basilica, in the form of a deliberate
        mockery of the resurrection story, for what appeared to be an exit from
        the tomb to a garden full of life has turned out to be instead a way
        into this place of death and decay. "
    roomBeforeAction()
    {
        if(gActionIs(Up) && !flagstone.isOpen)
        {
            "{You/he} can\'t see any way out up there. ";
            exit;
        }
    }
    enterRoom(traveler) { traveler.lastStatueLoc = self; }
;

+ SimpleOdor 'rotting smell/air/decay' 'rotting smell'
    "There's a strong smell of rotting and decay. " 
;

+ Decoration 'thick dust' 'thick dust'
    "Thick dust covers the floor of the cave. "
    isMassNoun = true
;

+ EntryPortal -> crypt 'large south (s) square opening/hole*holes' 'large hole'
    "The large hole in the south wall is easily large enough to walk through. "
    occluded = true
    dobjFor(LookThrough)
    {
        action() { location.describeRemoteRoom(crypt); }
    }
    disambigName = 'south hole'
    nothingBehindMsg = &cannotLookBehindMsg
;

+ Fixture 'rotting timber wood wooden plank/pillar/prop*props*pillars' 
    'wooden pillar'
    "The pillar is in the same position in the cave as the tree depicted in the
    garden; but unlike the tree, it is dead and rotting. It might conceivably
    be serving as a prop to hold up the ceiling, but it looks like it is only
    just up to the task. "
    feelDesc = "The wood feels damp and flaky. It's also quite rough. "
    sightSize = large
    dobjFor(Push)
    {
        verify() { nonObvious; }
        check() {
            if(flagstone.isOpen)
            {
                reportFailure('You don\'t want to try that again -- the whole
                    roof might cave in! Besides, the wooden pillar might be
                    useful for climbing up. ');
                exit;
            }
        }
        action()
        {
            "The wooden pillar shifts only a fraction, but it's enough to send
            a flagstone crashing down from the ceiling up above. The flagstone
            shatters on the floor -- fortunately you manage to dodge both it
            and its flying fragments -- and a square hole appears in the
            ceiling. ";
            flagstone.makeOpen(true);
            flagstoneFragments.makePresent();
            dislodgedFlagstone.makePresent();
            achievement.awardPointsOnce();
        }
    }
    dobjFor(Pull) asDobjFor(Push)  
    dobjFor(Move) asDobjFor(Push)
    dobjFor(Attack) asDobjFor(Push)
    dobjFor(Climb) maybeRemapTo(gActor.isIn(getOutermostRoom), Up)
    dobjFor(ClimbUp) maybeRemapTo(gActor.isIn(getOutermostRoom), Up)
    achievement : Achievement { +1 "opening up the way up out of the dank cave" }
;

+ flagstone : TravelWithMessage, HiddenDoor, StopEventList
    'square hole*holes' 'square hole'
    "There's a square hole in the ceiling some way above you; it looks like you
    could reach it by climbing up the wooden prop. "
    travelDesc { doScript; }
    eventList = [
        'You try the wooden prop, and it seems like it might hold
        your weight, so you climb up it and hoist yourself through the square
        hole in the ceiling. ',
        
        'You climb up the wooden prop once more, and haul yourself through
        the square hole in the ceiling. ' 
    ]
    occluded = true
    nothingBehindMsg = &cannotLookBehindMsg
;

+ flagstoneFragments: PresentLater, Decoration
    'stone shattered flagstone flagstone*fragments' 'flagstone fragments'
    "Shattered fragments of the flagstone lie scattered on the floor, the
    smallest no larger than your thumb, the largest no smaller than your
    foot. "
    notImportantMsg = 'You may as well leave them alone, since they\'re of
        no conceivable use. '
    isPlural = true
;


+ skullStatue: Fixture '(stone) carved/body/woman/statue' 'stone statue'
    "The statue is carved with the body of a woman, and a robe like that shown
    in the picture, but the face is a skull, strangely, almost grotesquely,
    surrounded with a mane of long hair. "
    feelDesc = "It feels like it's made of stone, but then that is indeed
        what it is made of. "
    sightSize = large
    dobjFor(Push)
    {
        verify() { nonObvious; }
        action() {
            "The statue sways just a fraction, but it's apparently too heavy
            for you to topple. ";
        }
    }
    dobjFor(Pull) asDobjFor(Push)
    dobjFor(Move) asDobjFor(Push)
;

++ Component 'ugly macabre skull/face*skulls*faces' 'face'
    "Where the statue's face should be, an ugly skull grimaces at you.  "
    feelDesc = "More rough stone. "
    remoteDesc(pov) { "It looks rather like a skull from here. "; }
    nothingBehindMsg = &cannotSeeBehindMsg
;

++ Component 'long robe*robes' 'long robe'
    "The robe covers most of the statue. "
    feelDesc = "It feels just like the cold stone it is. "
    sightSize = large
    nothingBehindMsg = &cannotSeeBehindMsg
;

++ Component 'exceedingly carefully carved (stone) thick long mane/hair' 
    'long mane of hair'
    "Although the statue has the face of a skull, it is also carved with a thick
    mane of hair all the way down to the statue's waist. Perhaps the sculptor
    was trying to make some point about the transience of human beauty. "
    sightSize = large
#ifdef __MULTIROUTE
    feelDesc = "It's just rough stone, like the rest of the statue -- except
        that when you touch it you almost get the feeling that the hair has been
        carved from a separate piece of stone. "   
#else
    feelDesc = "It's just rough stone, like the rest of the statue. "
#endif
    
    dobjFor(Pull)
    {
        verify() { nonObvious; }
        action() { 
#ifdef __MULTIROUTE     
            statueDoor.openOrClose(); 
#else
            "It seems pretty firmly fixed in place -- nothing happens. ";
#endif
        }
    }
    
    dobjFor(Move) asDobjFor(Pull)
;

#ifdef __MULTIROUTE

+ statueDoor: HiddenDoor 'open trap door/trapdoor' 'trap door'
    "The open trap door leads down into the darkness below. "
    makeOpen(stat)
    {
        inherited(stat);
        "As you pull the statue's carefully carved long hair, there's a
        creaking from the statue, and another from the floor near its base,
        whereupon <<stat ? 'a trap door opens in the floor, near the foot of
            the statue' : 'the trap door closes again' >>. ";     
        if(stat)
            achievement.addToScoreOnce(1);
    }
    openOrClose() { makeOpen(!isOpen); }
    achievement: Achievement { "opening the trap door by the statue" }
    remoteDesc(pov)
    {
        "The trapdoor is open in the floor near the foot of the statue in the
        dank cave. ";
    }
    
;

//==============================================================================

class DawnCaveWall : RoomPart 'flickering wall*walls' 'wall'
    "This cave is so ancient, or so young, or so recently created, that its
    walls don't seem entirely sure whether they really exist or not. They keep
    flickering in and out of existence, a bit like a quantum mechanical wall
    whose state vector is yet to collapse. "
    nothingThroughMsg = '{You/he} get{s} the impression that there\'s
        <i>something</i> behind {the dobj/him}, but as the wall keeps
        flickering, {it actor/he} can\'t quite make out what it is. '
    dobjFor(GoThrough)
    {
        verify() { nonObvious; }
        action()
        {
            "{You/he} stare{s} at the wall for a few moments, and then thinking
            to {yourself}, <q>What the hell!</q>, {you/he} take{s} a flying
            leap through it, only to find that {it actor/he} pass{es} straight
            through it and end{s} up in a very strange place indeed.<.p>";
            nestedAction(TravelVia, veryStrangePlace);
        }
    }
    dobjFor(Enter) asDobjFor(GoThrough)
    feelDesc = "It feels very strange, since it offers virtually no resistance
        to your touch. "
    cannotMoveMsg = '{You/he} can\'t, since {your} hands pass straight through it. '
    dobjFor(KnockOn) asDobjFor(Feel)
;


antWall: DawnCaveWall '(w) (e) (n) (s) (sw) (ne) southwest northeast north
    south east west -' 
    'walls'
    isPlural = true
;

#endif

antiquity: Room 'Cave at the Dawn of Time' 'the cave at the dawn of time'   
    "You call this place a cave for want of anything better to call it, but
    it's so unbelievably ancient that it almost defies human understanding: you
    might just as well call it <q><<getPhrase()>></q>. You can't even make up
    your mind whether it's a large cave-like space or a small cave-like space,
    or perhaps even a non-space. Nothing lives here, nothing at
    all<<deadTree.isIn(self) ? ', but a stunted tree has died here and still
        stands at the centre of the cave' : ''>>. A reasonably safe-looking
    passage -- if it can be called a passage -- leads off to the southeast,
    while to the northwest is a <i>something</i> that seems barely able to
    maintain itself in existence. <<roomParts.indexOf(defaultWestWall) ? '' :
      'Indeed, even the walls of this place seem uncertain whether they truly
      exist. '>> "
    
    southeast = viaAntiqua
    northwest: TravelMessage { -> edgeOfChaos
        "You walk on a few trembling paces, hesitating as reality threatens to
        dissolve around you with each faltering step you take. The walls of the
        passage go from rock to sand to something not-quite-solid, with holes
        flickering in and out of existence through its shimmering substance, as
        if it can't quite hold together. You hesitate to press on any further
        into this realm of not-quite-being, lest you cease to be yourself, and
        you finally stop at the point where the crumbling sand gives way to the
        waters of chaos. "
    }
    getPhrase() { return phraseList.getNextValue(); }
    phraseList : ShuffledList {
        valueList = [
            'Terra incognita',
            '&kappa;&alpha;&iota; &pi;&alpha;&sigma;&alpha; &eta; &gamma;&eta;
            &eta;
            &alpha;&rho;&chi;&alpha;&iota;&omicron;&tau;&epsilon;&rho;&alpha;',
            'bara elohim eth ha shamayim va-eth ha-aretz',
            'vloda, wu-fog lksda thrhr',
            'tyree upoo feeger sluvbgy',
            'baa baa gasha',
            'sluga footh pu-malik'
        ]
    }
#ifdef __MULTIROUTE   
    //   roomParts = [defaultFloor, defaultCeiling, antEastWall, antWestWall, antSouthWall,
    //     antNorthWall]
    
    roomParts = [defaultFloor, defaultCeiling, antWall]
    cannotGoThatWay()
    {
        if(veryStrangePlace.seen)
            replaceAction(Enter, antWall);
        else
            "You don't really think you can walk through a wall, do you?
            <<yesNo()>>";       
    }  
    yesNo() {  yesNoResponse.set(self, &throughWall); }
    throughWall(yes)
    {
        if(yes)
        {
            "You stare at the wall for a moment, then walk briskly towards it,
            expecting to bounce off it when you collide. But the wall proves to
            be so insubstantial that you pass straight through. ";
            nestedAction(TravelVia, veryStrangePlace);
        }
        else
            "It would be rather a strange thing to try. ";
    } 
    
    
#endif     
    thinkHere = "You have a strong sense of being somewhere you're not meant to be --
        or rather, somewhere where no human being is meant to be. "   
    southeastLook = "To the southeast is a reasonably safe looking passage. "
    northwestLook = "To the northwest is a <i>something</i> -- perhaps a
        passage of sorts -- that seems barely able to maintain itself in
        existence. "
;

+ deadTree: Decoration 'stunted grey gray seemingly dead withered tree' 
    'withered tree'
    "The tree is stunted, grey, and seemingly dead. Its branches are bare. "
    specialDesc = 'A withered tree stands to one side. '
    dobjFor(Default)
    {
        verify() { logicalRank(70, 'not so good'); }
        action() {
            "At the first touch the tree collapses into a cloud of grey dust,
            which is borne away on the breeze. ";
            moveInto(nil);
            unTree.makePresent();
        }
    }
    dobjFor(Examine) { action() { inherited; } }
    dobjFor(Smell)  { action() { inherited; } }
    dobjFor(ListenTo)  { action() { inherited; } }
    dobjFor(Read)  { action() { inherited; } }
    dobjFor(LookIn) { action() { inherited; } }
    getFacets = [unTree]
;

++ Component 'bare gnarled knotted grotesque branches/shapes' 'bare branches'
    "The branches are not only not bare, but gnarled and knotted into the most
    grotesque shapes. "   
    isPlural = true
    dobjFor(Examine) { action() { inherited; } }
    dobjFor(Smell)  { action() { inherited; } }
    dobjFor(ListenTo)  { action() { inherited; } }
    dobjFor(Read)  { action() { inherited; } }
    dobjFor(LookIn) { action() { inherited; } }
    dobjFor(Default)
    {
        verify() { logicalRank(70, 'not so good'); }
        action() { replaceAction(Push, deadTree); }
    }
;

+ unTree: PresentLater, Unthing 'stunted grey gray seemingly dead withered tree' 
    'withered tree'
    'The stunted grey tree is no longer here; it collapsed into a cloud of dust
    when you touched it. '    
;

+ EntryPortal ->edgeOfChaos 'flickering (northwest) (nw) something/passage' 'something'
    "It looks like it's a continuation of the passage, but it flickers
    alarmingly. "
    nothingBehindMsg = &cannotSeeBehindMsg
;

eocGround : defaultGround 'dusty sand' 'ground'
    desc = "The ground here is a sort of dusty sand. "
    feelDesc = "You jerk your hand away almost at once, since the sensation of
        touching the not-quite-real ground is so disorientingly weird, and not
        at all pleasant -- it has a slimey, insubstantial feel. "
    dobjFor(KnockOn) asDobjFor(Feel)
;

eocSky : defaultSky 'black dark void/blackness' 'sky'
    "The sky here is virtually black; not so much the blackness of thick cloud
    as the darkness of a total void, for even the frequent flashes of lightning
    seem to reveal nothing substantial in the blackness. "
;

edgeOfChaos : OutdoorRoom 'Edge of Chaos' 'the edge of chaos'
    "The waves of an endless, chaotic sea to north and west are illuminated by
    continuous flashes of lightning. A barely-existent passage leads back to
    the southeast from the sands of an insubstantial beach. "
    southeast = antiquity
    out asExit(southeast)
    north: NoTravelMessage {
        "The sea of chaos blocks your path, and it quite obviously can neither
        be entered or crossed by any entity that wishes to continue to exist. "
    }
    west asExit(north)
    northwest asExit(north)
    atmosphereList : ShuffledEventList {
    [
        'The chaotic waves beat against the fragile shore. ',
        'A particularly bright spear of lightning rends the air above the
        chaotic sea. ',
        'A boom of thunder nearly deafens you. ',
        'The wind howls all around, buffeting your body and threatening to tear
        you apart. ',
        'The crash of the waves mingles with the rumble of thunder to create a
        chaotic cacophony of painful noise. ',
        'A flash of lightning reveals the tortured twisting of the sea; by
        freak or diabolical design it momentarily appears that the waves form
        the outline of Satan himself. '     
    ]
    }
    thinkHere = "You think that this is no fit place for a mere mortal to hang
        about. "
    afterAction()
    {
        if(gActionIs(Yell))
            "But your <<gVerbName>> is barely audible above the cacophany, and
            is instantly snatched away by the wind. ";
    }
    southeastLook = "Back to the southeast leads the only passage away from the
        beach. "
    defaultLook(dir)
    {  
        if(dir is in (northDirection, northwestDirection, westDirection))
            "The chaotic sea stretches as far as you can see to the
            <<dir.name>>. ";
        else
            inherited(dir);
    } 
    roomParts = [eocGround, eocSky]
;

+ chaosSea: Fixture 'endless raging chaotic sea/chaos/waves/water/waters' 'sea'
    "The sea rages to north and west, black waves -- whether of water or of
    nothingness you can't quite tell -- constantly tossed by a howling wind. "
    dobjFor(Swim)
    {
        verify() { }
        check()
        {
            reportFailure('You\'d either drown or be ripped to shreds by the
                chaotic forces out there -- better to stay on terra (sorta)
                firma. ');
            exit;
        }
    }
    dobjFor(Enter) asDobjFor(Swim)
    cannotWalkOnMsg = 'No mortal could attemp to trample that chaos and expect
        to survive the experience. '
    cannotCrossMsg = static cannotWalkOnMsg
    cannotDrinkMsg = 'There\'s no way you\'re going to try swallowing any
        of that stuff! '
    notAContainerMsg = (gIobj==self ? 'Anything tossed into that raging chaos
        would be lost forever, so you think better of it. ' : nil)   
    feelDesc = "You don't want to touch it -- you'd probably lose your hand. "
    uselessToAttackMsg = 'That would probably damage you a lot more than the sea. '
    nothingBehindMsg = 'You can\'t see far enough to see what -- if anything --
        lies behind the sea. '
    nothingUnderMsg = 'You cannot see what lies beneath the raging sea. '
    nothingThroughMsg = 'You can see nothing through the black waters. '
    lookInDesc = "The sea is full of raging waters. "
    
    dobjFor(KnockOn) asDobjFor(Feel)
    dobjFor(Taste) asDobjFor(Drink)
    iobjFor(ThrowInto) asIobjFor(PutIn)
    iobjFor(ThrowAt) asIobjFor(PutIn)
;

++ SimpleNoise 'howling incessant wind/thunder/rumble/crash/noise/crashing' 'howling wind'
    "The constant howling wind has to compete with both the incessant crashing
    of the waves and the crash and rumble of thunder. "
;

+ Decoration 'insubstantial fragile beach/sands/shore/dust' 'beach'
    "What you think of as the beach is the insubstantial shore just before the
    dust-like sand gives way to the sea of chaos. It is just about solid enough
    to stand on. "
    cannotStandOnMsg = 'You are already standing on the beach, such as it is. '
    dobjFor(StandOn) { verify() { illogicalAlready(cannotStandOnMsg); }  }   
    notImportantMsg = 'There\'s really not a lot you can do with it. '
    dobjFor(Enter) asDobjFor(StandOn)
    dobjFor(Feel) remapTo(Feel, eocGround)
    dobjFor(KnockOn) remapTo(Feel, eocGround)
    nothingBehindMsg = 'Beyond the fragile beach lies the endless chaotic sea. '
;


+ Vaporous 'continuous flashes/lightning' 'lightning'
    "The lightning flickers over every part of the chaotic sea, shedding scant
    illumination other the otherwise deeply dark scene. "
;

+ PathPassage 'barely existent barely-existent passage' 'barely existent passage'
    "It seems to be flickering in and out of existence, as if it's not quite sure
    whether it's really there or not. "
    destination = antiquity
    nothingBehindMsg = &cannotSeeBehindMsg
;