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

/* 
 *   mountain.t 
 *
 *   Code for the mountain region of the game; this covers the sequence from 
 *   climbing Skull Mountain, through the chess game, rescuing Felicity from 
 *   the swamp, and escaping from the underground cave sytem.
 */

northRockWall : RoomPart 'north (n) rock steep sheer vertical wall*walls' 
    'north wall'
    "At this point the north wall is almost vertical, rising sheer for fifteen
    feet or so. "
;

southRockWall : RoomPart 'south (s) rock steep wall*walls' 'south wall'
    "The rock wall to the south starts quite low, so that you can easily see
    over its eastern end, but by the time it reaches the gate it's well over
    ten feet high. "
;

ruggedPathway : OutdoorRoom 'Steep and Rugged Pathway' 
    'the steep and rugged pathway'
    "Halfway up the mountainside the path looks even harder to climb, and the
    way up is through a funnel of rock across which is a narrow gate. Beyond
    that the path continues upwards to the west and into what looks like the
    deepest gloom. <<eastLook>>"
    west = narrowGate
    up asExit(west)
    east = fork
    down asExit(east)
    roomParts = static inherited + northRockWall + southRockWall
    thinkHere = "You think that the way up looks a lot less inviting than the
        way down. "
    eastLook = "To the east, the path not only looks a good deal easier, but
        leads down into a bright and pleasant valley that appears far more
        welcoming than anything further up the mountain. "
    downLook = (eastLook)
    westLook = "Immediately to the west is a narrow gate, beyond which the path
        continues upwards into the deepest gloom. "
    upLook = "The sky here looks foreboding enough; over to the west, where the
        summit of the mountain towers above you, it looks even grimmer. "
    southLook = "Far to the south you can see the sparkling blue of the great
        lake. "
    southeastLook = "Down to the southeast you can see the long green valley
        stretching from the foot of the mountain to the shore of the lake. "
;

+ narrowGate : TravelWithMessage, IndirectLockable, Door, StopEventList
    'tall (rusty) (iron) narrow gate*gates' 'narrow gate'
    "The tall iron gate is just about wide enough for one person to pass
    through (when open). <<isLocked ? 'It looks like it must have been a long
        time since anyone has done so, however, since thorns and briars have
        overgrown it and become entangled among its' : 'It\'s made of' >> rusty
    iron bars. "
    destination = skullMountain
    eventList = [
        'Once through the gate, you find the path becomes even steeper and
        narrower, and in places becomes so steep that you find yourself as much
        climbing as walking. Nevertheless, you carry on as best you can,
        although the higher you go, the darker the sky becomes and the bleaker
        the view. At last, after an hour or so of slogging up the mountainside,
        you eventually reach the top. ',
        
        'Once again, you slog your way up the long and arduous mountainside. '
    ]
    cannotClimbMsg {
        if(isOpen)
            return 'That would seem rather pointless: the gate is open so you
                can simply walk straight through. ';
        else
            return 'The gate is too tall climb, and its iron bars provide
                insufficient purchase for your hands and feet. ';
    }
    cannotLockMsg = 'It\'s not lockable. '
    cannotUnlockMsg = 'It doesn\'t have a lock; you\'ll have to find some other
        way to get it to open. '
    cannotOpenLockedMsg = 'You wiggle the gate but cannot get it to open;
        something seems to be jamming it. <.reveal rusty-gate>'
    shouldNotBreakMsg = 'The bars of the gate may be rusty, but they\'re still
        iron, and you find you can\'t make much impression on them. '
    dobjFor(LookThrough)
    {
        preCond = [objVisible]
        verify() { logicalRank(120, 'see through'); }
        action() {
            "Through the gate you see the narrow path continuing to ascend the
            mountainside, becoming steeper as it does so. ";
        }
    }
    dobjFor(Pull) asDobjFor(Push)
    dobjFor(Push)
    {
        remap()
        {
            if(isOpen)
                return [CloseAction, self];
            else
                return [OpenAction, self];
        }
    }
    makeOpen(stat)
    {
        inherited(stat);
        if(stat)
            achievement.awardPointsOnce();
    }
    achievement: Achievement { +1 "opening the narrow gate" }
;

++ Component 'six vertical rusty iron bar*bars' 'rusty iron bars'
    "The six vertical iron bars forming the substance of the gate are all about
    eight feet in length. <<narrowGate.isLocked ? 'A tangle of thorns and
        briars grows round their lower part. ' : '' >>  "
    isPlural = true
    dobjFor(LookThrough) maybeRemapTo(!narrowGate.isOpen, LookThrough, narrowGate)
    dobjFor(Pull) remapTo(Pull, narrowGate)
    dobjFor(Push) remapTo(Push, narrowGate)
    dobjFor(Break) remapTo(Break, narrowGate)
;

++ thornsBriars: CustomImmovable 'tangle/thorns/briars/weeds' 'thorns and briars'
    "A mess of uprooted thorns and briars lies discarded by the side of the
    path. "
    initDesc = "A tangle of thorns and briars is intertwined among the rusty
        iron bars of the gate. "
    isInInitState = (narrowGate.isLocked)
    dobjFor(Pull)
    {
        verify()
        {
            if(!narrowGate.isLocked)
                illogicalAlready('You\'ve already disentangled the thorns and
                    briars from the gate. ');
        }
        action()
        {
            narrowGate.makeLocked(nil);
            "You manage to pull the thorns and briars away from the gate,
            scratching your hands quite badly as you do so. "; 
            moveInto(ruggedPathway);
            initializeVocabWith('uprooted discarded mess');       
        }
    }
    dobjFor(TakeFrom) maybeRemapTo(isInInitState, Take, self)
    dobjFor(Remove) asDobjFor(Pull)  
    dobjFor(Break) asDobjFor(Pull)
    dobjFor(Take)
    {
        verify() { if(!narrowGate.isLocked) illogicalNow(cannotTakeMsg); }
        action()
        {
            nestedAction(Pull, self);
            "Having no further use for <<theName>>, you toss them aside. ";
        }
    }
    cannotTakeMsg = 'You have no use for them. '
    dobjFor(KnockOn) { verify() { illogical(&cannotKnockOnHoleMsg); } }
    isPlural = true
;


+ EntryPortal 'narrow rock funnel/rock*funnels' 'rock funnel'
    "The funnel is formed by a dip in the path between two steep walls of
    rock. "
    dobjFor(TravelVia) remapTo(TravelVia, narrowGate)
    nothingBehindMsg = 'Behind the funnel the path continues up the
        mountainside. '
;


+ bpValley : Distant 'bright long green pleasant valley*valleys' 'valley'
    "The valley is a bright expanse of green many hundred feet below,
    stretching south towards the shore of a great lake. "
;

+ Distant 'great sparkling blue shore/lake/sea*seas*lakes*shores' 'lake'
    "The southern edge of the valley forms the northern shore of a great blue
    lake that stretches as far south, east and west as you can see; indeed, the
    lake could almost be a sea. "
;



+ Fixture 'steep narrow path*paths' 'steep path'
    "Beyond the gate, the path leads even more steeply up the side of the
    mountain. Down to the east, the path looks somewhat easier as it leads back
    down into the valley. "
    dobjFor(Take) maybeRemapTo(gVerbName == 'take', Follow, self)
    dobjFor(Follow)
    {
        verify() { }
        action() {
            "Which way do you want to go, up or down? ";
        }
    }
    cannotEnterMsg = 'You\'re already on the path. '
    nothingBehindMsg = &unclearWhatBehindMsg
    cannotTakeMsg = &cannotPickUpMsg
;

+ Distant 'towering top/mountain/mountainside*mountains*tops' 'mountain'
    "The mountain towers above you to the west; its top looks shrouded in
    deep darkness. "
    dobjFor(Climb) remapTo(TravelVia, narrowGate)
    dobjFor(ClimbUp) remapTo(TravelVia, narrowGate)
;

+ Distant 'unnatural deep deepest darkness/gloom' 'deep darkness'
    "Deep darkness shrouds the top of the towering mountain high above you to
    the west. There seems to be something unnatural about it. "
    isMassNoun = true
;

grammar nounPhrase(thornsAndBriars) :
    ('thorns' 'and' 'briars') | ('briars' 'and' 'thorns')
    : SpecialNounPhraseProd
    getMatchList = [thornsBriars]
    getAdjustedTokens =
    ['thorns', &noun, 'and', &adjective, 'briars', &noun]
;

grammar nounPhrase(brightAndPleasant) :
    'bright' 'and' 'pleasant' 
    : SpecialNounPhraseProd
    getMatchList = [bpValley]
    getAdjustedTokens =
    ['bright', &noun, 'and', &adjective, 'pleasant', &noun]
;

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

class Titulus: Component 'titulus*tituli' 'titulus'
    dobjFor(WriteOn)
    {
        verify() { illogicalAlready('{The dobj/he} already has an
            inscription. '); }
    }
    dobjFor(WriteSomethingOn) asDobjFor(WriteOn)
    notASurfaceMsg = iobjMsg(notPossibleMsg)
    notPossibleMsg = 'That is neither possible nor necessary. '
    cannotAttachToMsg = iobjMsg(notPossibleMsg)
;


blackSky: defaultSky 'almost black dark background/sky*skies' 'dark sky'
    "The sky here is so dark it is almost black, unrelieved by so much as a
    single star. "
;


skullMountain: OutdoorRoom 'Skull Mountain' 'Skull Mountain'
    "The top of this mountain is the most desolate place imaginable. Nothing
    grows here among the barren, jagged rock. Three tall empty crosses are
    fixed in the ground, and above them a black sun in a dark sky leeches the
    light from all around. The only glimmer of light is a distant golden glow
    far, far to the west. <<crossHole.isOpen ? crossHole.desc : ''>> "
    vocabWords = 'skull mountain'
    cannotGoMsg = 'That way lies impenetrable darkness. '
    roomParts = [defaultGround, blackSky]
    east = ruggedPathway
    down = crossHole  
    west: NoTravelMessage {
        "You can find no path leading west from here: you'd just fall off the
        mountain. You'll have to find another way to reach that golden glow. "
    }
    out : ConditionalConnector
    {
        -> ruggedPathway
        ": east or down"
        @(crossHole.isOpen)
    }
    thinkHere = "It\'s obvious that this is a scene of crucifixion. It strongly
        calls to mind Golgotha, the <q>Place of the Skull</q> that was the site
        of the crucifixion scene in Mark 15.21-39 and parallels. According to
        Mark, Jesus was crucified between two bandits, the inscription or
        <i>titulus</i> affixed to his cross read <q>The King of the Jews</q>,
        and there was darkness over the whole land from noon till three (when
        Jesus expired)." 
    defaultLook(d) { "This mountaintop looks pretty bleak whichever way you
        look, and the all-encompassing darkness makes it impossible to see
        anything much beyond it. "; }
    eastLook = "<<defaultLook(eastDirection)>> But to the east, you see a path
        leading back down. "
    westLook = "Far, far to the west is a distant golden glow. "
    downLook
    {
        if(crossHole.isOpen)
            replaceAction(LookThrough, crossHole);     
    }
    roomBeforeAction
    {
        if(gActionIs(JumpOffI) && crossHole.isOpen)
        {       
            replaceAction(Down);       
        }
    }
    dobjFor(StandOn) remapTo(StandOn, defaultGround)
;

+ Distant 'black even darker disk/disc/sun*suns' 'black sun'
    "The black sun high above appears as an even darker disk against the dark
    background of the sky; it sucks in light from all around, casting darkness
    and gloom over the whole land. "
;

+ Distant 'distant far golden gold glimmer/glow/blotch/light' 'golden glow'
    "Admittedly, it's no more than a golden blotch on the western horizon, but
    you feel certain it's the golden glow you saw across the chasm. "
    initDesc = "A flood of hope surges through you as you finally see that glow
        again. <<desc>>Your determination to find a way to reach it is renewed. "
    isInInitState = (!described)
;

+ Fixture 's south southern southernmost tall empty 
    crossbeam/cross*crosses*beams*crossbeams' 
    'southern cross'
    "It is a rough wooden cross, with the remains of dark bloodstains on its
    crossbeam; just above where the condemned man's head would have been is a
    titulus, which has the word <q>Bandit</q> engraved on it. "
    cannotClimbMsg = 'You have no desire to mount the cross. '
;

++ Titulus 's south southern -' 'southern titulus'
    "It has the word <q>Bandit</q> engraved on it. "
;

+ Decoration 'dark remains*bloodstains' 'dark bloodstains'
    "They're roughly where you'd expect if the victim had bled from nail-wounds
    through wrists or palms. "
    isPlural = true
;

+ Decoration 'barren broken black jagged sea/desolation/rock*rocks' 'barren rock'
    "Black, broken, barren rock covers the mountaintop in a sea of desolation. "
    isMassNoun = true
;

+ Vaporous 'all-encompassing (all) encompassing darkness/gloom' 'gloom'
    "Apart from the distant glimmer to the west, the gloom is all-encompassing,
    shrouding the mountaintop in eternal darkness. "
    isQualifiedNoun = true
;

+ centralCross: Fixture 'central centre center middle tall empty cross*crosses' 
    'central cross'
    "It is a rough wooden cross, slightly taller than those on either side of
    it. <<titulus.desc>>" 
    iobjFor(AttachTo) remapTo(AttachTo, DirectObject, titulus)
    iobjFor(PutOn) remapTo(PutOn, DirectObject, titulus)  
    dobjFor(WriteOn) remapTo(WriteOn, titulus)
    dobjFor(WriteSomethingOn) remapTo(WriteOn, titulus)
;

++ titulus: OutOfReach, Component 'central titulus*tituli' 'central titulus'
    "The titulus of the central cross <<attachedWord == nil ? 'is blank'
      : 'bears the word <q>' + attachedWord.name + '</q>'>>. "
    pluralName = 'tituli'
    attachedWord = nil
    iobjFor(AttachTo)
    {
        verify()
        {
            if(!gActor.canTouch(self))
                illogicalNow(cannotReachMsg);
            if(attachedWord != nil)
                illogicalAlready('There\'s already a word on the central
                    titulus. ');
        }
    }
    iobjFor(PutOn)
    {
        verify() { 
            if(!gActor.canTouch(self))
                illogicalNow(cannotReachMsg);
        }
        check()
        {
            if(!gDobj.ofKind(Word))
            {  
                reportFailure('{You/he} can\'t put {that dobj/him} on the
                    titulus. ');
                exit;
            }
        }
        action() { replaceAction(AttachTo, gDobj, self); }   
    }
    dobjFor(WriteOn)
    {
        preCond = [objVisible]
        verify() 
        { 
            if(attachedWord != nil)
                illogicalAlready('The central titulus already has an
                    inscription. ');
        }
        
        check()
        {
            if(wordPile.discovered)
                failCheck('There\'s no need to <i>write</i> anything on the
                    central titulus; you already have some ready-made
                    words. ');
            else
                failCheck('You don\'t have a suitable engraving tool -- maybe a
                    more thorough search will reveal what you need. ');
        }
    }
    dobjFor(WriteSomethingOn) asDobjFor(WriteOn)
    canObjReachSelf(obj) { return obj.isIn(largeStone); }
    achievement : Achievement { +1 "attaching a word to the titulus" }
    cannotReachMsg = '{You\'re/he\'s} not quite tall enough to reach the
        titulus of the central cross from the ground. <.reveal titulus-reach>'
;

+ Fixture 'n north northenmost northern tall empty 
    cross/crossbeam*crosses*beams*crossbeams' 
    'northern cross'
    "It is a rough wooden cross, with the remains of dark bloodstains on its
    crossbeam; just above where the condemned man's head would have been is a
    titulus, which has the word <q>Robber</q> engraved on it. "
;

++ Titulus 'n north northern -' 'northern titulus'
    "It has the word <q>Robber</q> engraved on it. "
;

+ bonePile: Thing 'old human bone pile/bones' 'pile of old bones'
    "You're no expert on such matters, but so far as you can tell the bones are
    human ones. Your best guess is that the pile contains the bones of two
    people mixed together. "
    initSpecialDesc = "A pile of old bones lies strewn round the crosses. "
    dobjFor(LookIn)
    {
        preCond = static inherited + touchObj
        action()
        {
            if(!wordPile.moved)
            {
                wordPile.makePresent();
                "Amongst old bones you make a most extraordinary find:
                a stack of words. " ;
            }
            else
                "There doesn\'t seem to be much left among the bones. ";
        }
    }
    dobjFor(LookUnder) asDobjFor(LookIn)
;

+ largeStone : Platform 'large flat stone/surfaces*stones' 'large stone'
    "It's quite a large stone, with flat surfaces on top and underneath. "
    initSpecialDesc = "A large stone lies on the ground. "
    dobjFor(StandOn)
    {
        action()
        {
            mainReport('(first placing the stone at the foot of the central
                cross)\n
                {You/he} stand{s} on top of the stone. ');
            inherited;      
        }
    }
    dobjFor(Take)
    {
        action()
        {
            "It's a pretty hefty stone, but you just about manage to pick it
            up. ";
            inherited;
        }
    }
    dobjFor(ThrowAt)
    {
        action()
        {
            "It makes a clumsy missile, but you do your best to toss the heavy
            stone at {the iobj/him}.<.p>";
            inherited;
        }
    }
    dobjFor(Climb) asDobjFor(StandOn)
    roomBeforeAction
    {
        if(gActionIn(JumpOffI, Jump))
        {       
            replaceAction(Down);       
        }
    }
    reachableObjects = [titulus, centralCross]
    //  restrictedReach = nil
    allowedPostures = [standing, sitting]
    weight = 10
    bulk = 8
;

+ wordPile: PresentLater, Collective, RestrictedContainer 'stack/words*words' 
    'stack of words'
    "Curiously, it's a stack of words that seem to exist purely as sequences of
    letters. "
    canPutIn(obj) { return obj.ofKind(Word); }
    descContentsLister : thingContentsLister {
        showListPrefixWide(itemCount, pov, parent)
            { "The <<itemCount>1 ? 'words include:' : 'only word left in it is'>> "; }
    } 
    inlineContentsLister: inlineListingContentsLister {
        showListPrefixWide(cnt, pov, parent)
            { " (which contains the word<<cnt>1 ?'s' : ''>> "; }
    }
    isCollectiveFor(obj) { return obj.isIn(self); }
    
    /* If there's only one word left in me, then I have ceased to exist as a stack*/
    afterAction()
    {
        if(contents.length == 1)
        { 
            contents[1].moveInto(location);
            unWordPile.moveInto(getOutermostRoom);
            moveInto(nil);
        }
    }
    dobjFor(AttachTo)
    {
        verify() 
        {
            illogical(notWithWholeStackMsg);
        }
    }
    
    dobjFor(PutOn)
    {
        check()
        {
            if(gIobj is in (titulus, centralCross))
                failCheck(notWithWholeStackMsg);
        }
    }
    notWithWholeStackMsg = 'You can\'t put the whole stack of words on there,
        but a single word might be a different proposition. '
    weight = 0
    pluralOrder = 1
;

Word template 'wordName';

class Word : Thing
    desc = "It's simply the word <q><<wordName>></q>; that is the sequence of
        letters spelling out the word <q><<wordName>></q> mounted on an
        invisible background -- a strange kind of object, to be sure, but then
        this is a strange kind of place. "
    vocabWords = ('word sequence/letters/' + wordName + '*sequences*words')
    wordName = ''
    aName = ('<q>' + name + '</q>')
    theName = (aName)
    name = (wordName)
    
    dobjFor(AttachTo)
    {
        verify() { }
        check() {
            if(gIobj != titulus)
            {
                reportFailure('{You/he} can\'t attach any words to
                    {that iobj/him}. ');
                exit;
            }
        }
        action()
        {
            titulus.attachedWord = self;
            titulus.initializeVocabWith(name);
            titulus.achievement.awardPointsOnce();
            self.moveInto(nil);       
            "{You/he} attach{es} the word <q><<wordName>></q> to the titulus of
            the central cross. As you do so, the word burns itself into the
            wood of the titulus so that it appears engraved there; at the same
            moment there is a rumbling beneath your feet, and you see a hole
            open up near the base of the cross. ";
            crossHole.makeOpen(true);
            chessPiece.setPieceName(wordName);       
        }
    }
    dobjFor(KnockOn) { verify() { illogical('You can hardly knock on a word. '); } }
    weight = 0
;

++ Word 'hope' pluralOrder = 20;
++ Word 'love' pluralOrder = 50;
++ Word 'truth' pluralOrder = 60;
++ Word 'justice' pluralOrder = 40;
++ Word 'courage' pluralOrder = 5;
++ Word 'faith' pluralOrder = 10;
++ Word 'integrity' pluralOrder = 30;


+ crossHole : HiddenDoor 'large dark 
    space/hole/tomb/mouth/opening*holes*mouths*tombs' 
    'large hole'
    "A large hole opens into a tomb near the foot of the central cross. "
    destination = tunnel
    iobjFor(ThrowInto) remapTo(PutIn, DirectObject, self)
    iobjFor(PutIn)
    {
        verify() {}
        check()
        {
            failCheck('For some reason {you/he} find{s} {it actor/he} can\'t
                fit {the dobj/him} through the hole. ');
        }
    }
    dobjFor(JumpDown) asDobjFor(Enter)
    dobjFor(KnockOn) { verify() { illogical(&cannotKnockOnHoleMsg); } }  
    nothingThroughPassageMsg = 'Through the hole you can just make out a dark
        space below. '
    nothingBehindMsg = &cannotLookBehindMsg
;

unWordPile : Unthing 'stack/words' 'stack of words'
    'Now that you\'ve separated all the words, the stack has ceased to exist as
    a stack. '
;

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

tunnelCeiling: defaultCeiling
    desc = "The ceiling is of rough-hewn rock, with a round opening in it at
        the east end. "
;

tunnel : Room 'Tomb Tunnel' 'the tomb tunnel'
    "This place is as much tunnel as tomb. Towards the darker east end there is
    a flat shelf of rock, and beyond that, right at the east end, a round hole
    high up in the ceiling looks up at a black sky. Such light as there is
    comes from the west, towards which the tunnel runs. "
    up : FakeConnector { "Although at first sight it looked like you might
        manage to climb back out of the tomb, it seems you can't after all;
        it\'s too high up." 
        noteTraversal { isConnectorApparent = nil; }
    }
    west = chessRoom  
    out asExit(west)
    vocabWords = 'tomb tunnel'
    roomParts = static inherited - defaultCeiling + tunnelCeiling - defaultWestWall
    thinkHere = "You think that this place looks like a rather half-hearted
        attempt to reconstruct Jesus' tomb. "
    westLook = "A tunnel runs westwards from the west end of the tomb. "
    roomBeforeAction()
    {
        if(gActionIs(Jump))
        {
            "You jump as high as you can, but you still can't reach the opening
            in the ceiling. ";
            exit;
        }
    }
;

+  flatShelf: RoomPartItem, Bed, Fixture 'flat slightly rough shelf/rock*shelves' 
    'flat shelf of rock'
    "It's a flat, slightly rough shelf of rock, large enough to lie on, cut
    into the rock wall. There's no evidence that anyone's been put here
    recently, though. "
    allowedPostures = [sitting, lying]
    cannotStandOnMsg = 'There\'s not enough headroom over the shelf. '
    reachableObjects = [defaultEastWall, defaultNorthWall]
    initNominalRoomPartLocation = defaultEastWall
    initSpecialDesc = "A flat shelf of rock has been cut into the east wall. "
    nothingBehindMsg = 'There\'s nothing behind the shelf apart from the wall. '
;

+ Decoration 'rock wall*(walls)' 'rock wall'
    "<<flatShelf.initSpecialDesc>> There's nothing special about the others. "
;

+ Distant 'large round opening/hole*holes*openings' 'opening'
    "The opening is a large round hole above your head. "
    tooDistantMsg = '{You/he} can\'t reach it -- it\'s too high up. '
;

+ Vaporous 'light' 'light'
    "Such light as there is comes from the west. "
;

+ EntryPortal ->chessRoom 'rock-hewn tunnel' 'tunnel'
    "The rock-hewn tunnel continues to the west. "
    nothingBehindMsg = &cannotLookMsg
;

+ Distant 'utterly black circle/sky' 'black sky'
    "All you can make out from here is a circle of black sky through the round
    hole above you. "
;

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

chessRoomWestWall : defaultWestWall
    desc()
    {
        if(fissureDoor.isOpen)
            "There's a large crack in the west wall, wide enough to step
            through. ";
        else
            "There's nothing special about the west wall. ";
    }
;

chessRoomEastWall : defaultEastWall
    desc()
    {
        if(chessDoor.isOpen)
            "The east wall looks pretty plain, apart from the dark tunnel that
            leads off through it. ";
        else
            "The east wall is utterly plain, the entrance to the dark tunnel
            having disappeared. ";
    }
;

chessRoomFloor : Floor 'floor/ground' 'floor'
    "It's covered with a pattern of sixty-four red and white squares. "
;

chessRoom : Room 'Chess Room' 'the chess room'
    "There are two obvious reasons for calling this the chess room. The first
    is the pattern of red and white squares on the floor. The second is the
    chess board set out for playing on the table in the middle of the room. <<
      chessDoor.isOpen ? 'The room itself is well lit, but a dark tunnel
          disappears off into the gloom to the east. ' :
      ''>><<fissureDoor.isOpen ? 'A large fissure has opened up in the west
          wall. ' : ''>> "
    east = chessDoor
    west = fissureDoor
    out : ConditionalConnector
    {
        ->(chessDoor.isOpen ? chessDoor : fissureDoor)
        @(!chessDoor.isOpen && !fissureDoor.isOpen)
        whichWayMsg = "There doesn't seem to be any way out right now. "
    }
    
    thinkHere()
    {
        if(fissureDoor.isOpen)
            "You suspect that not much more is going to happen here, and that
            you may as well leave. ";
        else if(chessDoor.isOpen)
            "You think this is one of the oddest games of chess you've ever
            seen, and you're rather curious to see how it will turn out. ";
        else
            "You reckon you really have no option but to accept the emperor's
            challenge and attempt to defeat him at chess. ";
    }
    roomParts = [chessRoomFloor, chessRoomEastWall, chessRoomWestWall, 
        defaultNorthWall, defaultSouthWall, defaultCeiling]
;

+ chessDoor : HiddenDoor 'dark tunnel/gloom*tunnels' 'dark tunnel'
    "The tunnel leads off into the gloom to the east. "
    initiallyOpen = true
    destination = tunnel
    nothingBehindMsg = &cannotLookBehindMsg
;

+ fissureDoor : HiddenDoor 'large fissure/crack*cracks*fissures' 'fissure'
    "The fissure that's opened up in the west wall looks easily large
    enough to squeeze through. "
    destination = tunnelJunction
    dobjFor(KnockOn) { verify() { illogical(&cannotKnockOnHoleMsg); } }
    nothingBehindMsg = &cannotLookBehindMsg
;

+ chessBoard: Fixture, ComplexContainer 'four-legged chess 
    chessboard/board/table/game*boards*tables*furniture'
    'chess board'
    "The chess board is inset into the top of the four-legged table of which it
    effectively forms a part. It's a fairly standard board, except that its
    squares are red and white instead of black and white. "
    subSurface : ComplexComponent, Surface { }
    subUnderside: ComplexComponent, Underside { }
;

++ decorationPieces: Decoration 
    'red white auxiliary chess sicarius/centurion/cohort/temple/set/piece*pieces' 
    'chess pieces'
    "A closer examination reveals this to be a rather curious chess set. Along
    with pawns are pieces such as priest, temple, centurion, sicarius, and a
    number of other oddities. "
    notImportantMsg = 'You had better leave the pieces to those playing the
        game. '
    isPlural = true
    subLocation = &subUnderside
;

+ rAndWSquares: Decoration 'chequer checker red white squares/pattern*patterns' 
    'red and white squares'
    "There are red and white square on the floor and on the chessboard, the
    chequer pattern on the former imitating that on the latter. Both chessboard
    and floor have sixty-four squares, so it follows that the squares on the
    floor are rather larger than those on the board. "
;

+ whiteChair: Chair, CustomImmovable, StopEventList
    'stark upright plain white chair*chairs*furniture' 'white chair'
    "The white chair is about as plain as it can be: a stark upright chair
    painted white. "
    reachableObjects = [chessBoard]
    cannotTakeMsg = 'It seems to be fixed in place. '
    dobjFor(SitOn)
    {
        action()
        {
            inherited;
            doScript();
        }     
    }
    eventList = [
        {: "<.p>As you sit on the chair and survey the chess board, you are
            struck by the apocalyptic nature of the contest that awaits. The
            whore, the beast and the emperor all represent one thing: the
            powers opposed to divine rule. But why should you be the one to
            defeat them? <<chessPiece.seen ? '' : 'And with what? None of the
                white pieces on the board look remotely powerful enough. '>> " },
        nil
    ]
;

+ redChair: Chair, CustomImmovable 'wide plush gold golden red back/chair/throne/
    cushions/eagles*chairs*thrones*furniture' 'red chair'
    "The red chair is very grand, almost a throne, with plush red cushions and
    wide arms. Each of the arms ends in a golden eagle, while across the back
    of the chair <q>SPQR</q> is emblazoned in gold letters. "   
    cannotTakeMsg = '{You/he} can hardly move it while someone\'s sitting in it. '
;

++ Component 'gold emblazoned letters' 'gold letters'
    "The gold letters emblazoned on the back of the chair read SPQR. "
    isPlural = true
    dobjFor(KnockOn) { verify() { illogical(&cannotKnockOnHoleMsg); } }
;

++ Component 'wide arms' 'wide arms'
    "The arms of the red chair are wide enough for the arms of its occupant to
    rest, and they both come to an end in a golden eagle. "
    isPlural = true
    nothingBehindMsg = 'There\'s not much behind the arms. '
;

+++ Component 'imperial gold golden eagle*eagles' 'golden eagles'
    "The golden eagles at the end of the chair arms are depicted facing each other. "
    isPlural = true
    nothingBehingMsg = 'Behind the eagles are the arms they\'re attached to. '
;


grammar adjWord(rAndW) :
    'red' 'and' 'white'
    : SpecialNounPhraseProd
    getMatchList = [rAndWSquares]    
    getAdjustedTokens =
    ['red', &adjective, 'and', &adjective, 'white', &adjective]
;

actorSeatedOnWhiteChair: PreCondition
    checkPreCondition(obj, allowImplicit)
    {
        /* 
         *   if the actor is already seated in the white chair, there's 
         *   nothing we need to do
         */
        if (gActor.isIn(whiteChair) && gActor.posture == sitting)
            return nil;
        
        /* the actor isn't already seated - try an implicit 'sit' command */
        if (allowImplicit && tryImplicitAction(SitOn, whiteChair))
        {
            /* 
             *   we successfully executed the command; check to make sure it 
             *   worked, and if not, abort the command without further 
             *   comment (if the command failed, presumably the command 
             *   showed an explanation as to why) 
             */
            if (!gActor.isIn(whiteChair) && gActor.posture == sitting)
                exit;
            
            /* tell the caller we executed an implicit command */
            return true;
        }
        
        /* the actor isn't seated in the white chair - fail */
        reportFailure('{You/he} must be sitting at the chessboard to move your
            pieces.');
        exit;
    }
;


class WhiteChessPiece: PresentLater, Thing
    vocabWords = 'white chess piece*pieces'
    notImportantMsg = ( emperor.isStone ? 'The game is over, and you have
        no further use for any of the chess pieces. ' : 
                       'To employ this piece in this chess game use either <a
                       HREF="' + movePiece + '" >' + movePiece + '</a>
                           or <a HREF="TAKE RED  ' + withPiece + '" NOENTER>
                               TAKE red piece ' + 
                       withPiece + '</a>. ')      
    
    dobjFor(Move)
    {
        preCond = [touchObj, actorSeatedOnWhiteChair]
        verify() { verifyChessPlay(); }      
        check() { }
        action() {
            "{You/he} move{s} {the dobj/him} a few squares. ";
        }
    }
    movePiece = ('MOVE ' + name.toUpper)
    withPiece = ('WITH ' + name.toUpper)
    dobjFor(Examine) { verify() { inherited; }  }
    dobjFor(Default) { verify() { illogical(notImportantMsg); }  }
    iobjFor(Default)  { verify() { illogical(notImportantMsg); }  }
    
    iobjFor(AttackWith) remapTo(TakeWith, DirectObject, self)
    
    iobjFor(TakeWith)
    {
        preCond = [touchObj, actorSeatedOnWhiteChair]
        verify() { verifyChessPlay(); }     
    }
    verifyChessPlay()
    {
        gMessageParams(obj);
        obj = self;
        if(emperor.curState == emperorStone)
            illogicalNow('The game is over. ');
        if(!isIn(chessBoard.subSurface))
            illogicalNow('{The obj/he} must be on the board before {you/he} 
                can move {it obj/him}. ');       
    }
    location = chessBoard.subSurface
    plKey = 'chess'
    owner = gPlayerChar
    
#ifdef __DEBUG
    dobjFor(Snarf) {  verify() { inherited Thing; } }   
#endif
;

class RedChessPiece : PresentLater, Thing
    notImportantMsg = ( emperor.isStone ? 'The game is over. ' :
                       'You had better leave your opponent\'s pieces alone. ' )
    cannotTakeWithMsg = 'You can\'t take anything with one of your opponent\'s
        pieces. '
    vocabWords = 'red chess piece*pieces'
    dobjFor(TakeWith)
    {
        verify() 
        {
            if(!isIn(chessBoard.subSurface))
                illogicalAlready('{The dobj/he} has already been taken. '); 
            
        }
        check()
        {
            if(rand(10) < 2)
            {
                reportFailure('Your ' + gIobj.name + ' is not in the right
                    position to take that. ');
                exit;
            }
        }    
        action()
        {
            "You take {the dobj/him} with {the iobj/him}. ";
            moveInto(nil);
        }
    }
    dobjFor(Take)
    {
        verify() 
        { 
            if(emperor.isStone)
                illogicalNow(notImportantMsg);
            else
                verifyDobjTakeWith(); 
        }
        check() { }
        action() { askForIobj(TakeWith); }
    }
    dobjFor(Default) { verify() { illogical(notImportantMsg); } }
    dobjFor(Examine) { verify() { inherited; } }
    
#ifdef __DEBUG
    dobjFor(Snarf)
    {  
        verify() 
        { 
            if(isIn(gActor)) illogicalAlready('{You/he} already {have}
                {it dobj/him}.'); 
        }      
    }
#endif
    
    location = chessBoard.subSurface
    plKey = 'chess'
    owner = emperor
;

chessPiece : Hidden, WhiteChessPiece 
    'strangely shaped white chess your piece/queen*pieces*queens' 
    'strangely shaped white chess piece'
    "It's a strangely shaped piece, but you instinctively recognize that it
    represents <<pieceName>>. The same instinctive recognition tells you that
    this piece is effectively your queen. "
    initDesc = "<<desc>>\bAs you study the chess piece, further understanding
        dawns: it was <<pieceName>> you considered crucified on Skull Mountain;
        your Queen must thus represent <<pieceName>> resurrected. "
    isInInitState = (!described)
    pieceName = 'Hope'
    setPieceName(str)
    {
        initializeVocabWith(str);
        pieceName = str.substr(1, 1).toUpper + str.substr(2);    
    }
    movePiece = ('MOVE ' + pieceName.toUpper)
    withPiece = ('WITH ' + pieceName.toUpper)
    isListed = true
    isListedInContents = true
    dobjFor(Take)
    {
        verify() 
        {
            if(!isIn(chessBoard.subSurface))
                delegated Thing;
            else
                illogicalNow(notImportantMsg);
        }
        check() { delegated Thing; }
        action() { delegated Thing; }
    }
    dobjFor(PutOn)
    {
        verify() 
        {
            if(!isIn(chessBoard.subSurface))
            {
                if(emperor.curState != emperorPlaying)
                    illogicalNow('You know better than to interfere with the
                        game like that. ');
                else
                    delegated Thing;      
            }
            else
                inherited;
        }
    }
    dobjFor(Examine)
    {
        action()
        {
            inherited;
            name = pieceName + ' (your queen)';
            isProperName = true;
        }
    }  
    location = chessBoard.subUnderside
    initiallyPresent = true
    plKey = ''
;

whore: RedChessPiece 'scarlet harlot/whore/babylon/queen*queens'
    'Scarlet Whore of Babylon'
    "The whore is depicted as dressed in scarlet finery and mounted upon a
    beast, with a crown upon her head. You perceive that this piece represents
    the red queen, while the beast on which she is mounted represents the red
    king."
    isHer = true
    isIt = true
    isListed = nil
    dobjFor(TakeWith)
    {
        check() { }
        action() 
        {
            if(gIobj == chessPiece)
            {
                "You move {the iobj/him} onto the same square as the Scarlet
                Whore. The beast on which she sits raises its claw to strike,
                but your \^<<gIobj.pieceName>> halts it with a word. <q>Now
                begone!</q> \^<<gIobj.pieceName>> roars at the beast and the
                whore with the voice of a lion, <q>Your time is at an end;
                begone! For you have afflicted the meek and injured the
                peaceable, and you have held sway over the world with much
                terror, and over the earth with grievous oppression. Therefore
                you will surely disappear, so that the whole earth, freed from
                your violence, may be refreshed and relieved. Begone!</q>\b
                These words stream furiously from the mouth of your
                \^<<gIobj.pieceName>> in a shower of sparks, a stream of fire
                that burns up both whore and beast until not so much as a
                cinder of them is left.\b          
                You look up at the Emperor in triumph, <q>No empire, no
                Emperor!</q> you declare.\b
                The Emperor gives you a very stony look in response, and starts
                to look very grey. After a moment or two you realize that he
                has in fact turned to stone. Just then there's a loud rumbling
                and trembling as a wide crack opens up in the west wall behind
                him. ";
                moveInto(nil);
                emperor.initializeVocabWith('stone statue');
                emperor.setCurState(emperorStone);
                fissureDoor.makeOpen(true);
                achievement.awardPointsOnce();
                challengeManager.setChallenge(nil);
            }
            else
            {
                "You move {the iobj/him} up to the Scarlet Whore, but instead
                of your piece taking the Emperor's, the beast on which the
                Whore is seated rakes your <<gIobj.name>> with its claws and
                tears it to shreds, much to the Emperor's evident amusement. ";
                gIobj.moveInto(nil);
            }
        }
    }  
    achievement: Achievement { +2 "defeating the Emperor at chess" }  
;

+ Component 'small red crown' 'whore\'s crown'
    "It's just a small red crown, to scale with the rest of the figure. "
    owner = whore
    dobjFor(TakeFrom)
    {
        verify()
        {
            if(gIobj == nil && gTentativeIobj.indexWhich({x: x.obj_ == whore} )
               || gIobj == whore)
                logicalRank(150, 'whore\'s crown');     
            else    
                inherited;
        }
        check()
        {
            reportFailure(&cannotTakeComponentMsg, location);
            exit;
        }  
    }
;

+ beast: Component 'red scarlet beast/king*kings*beasts' 'scarlet beast'
    "The beast has ten horns and seven heads, with ten diadems upon its horns.
    It is like a leopard, but its feet are like a bear's, and its mouth is like
    a lion's mouth; yet even as you look at it you also think it rather
    resembles an eagle with twelve feathered wings and three heads; indeed its
    refusal to stay in one shape or the other is part of its nightmarish
    quality. One feature of the beast that does remain constant is the base on
    which it stands, on which are inscribed the letters VI VI VI. From the
    diadems on the horns you deduce that this beast represents the red king. "
    dobjFor(Take) remapTo(Take, whore)
    dobjFor(TakeWith) remapTo(TakeWith, whore, IndirectObject)  
;

++ Component 'red base/(beast)/letters' 'base of the beast'
    "It's red, like the rest of the beast, and it's marked with the
    letters VI VI VI. "
;

++ Component 'horns' 'horns'
    "Most of the time the scarlet beast has ten of them, but it will keep
    shape-shifting. "
    isPlural = true
    owner = location
;

++ Component 'grotesque bestial heads' 'heads'
    "Whether the beast has three of them or seven, they all look bestial and
    grotesque. " 
    isPlural = true
    owner = location
;

++ Component 'diadems' 'diadems'
    "The diadems on the beast horns presumably symbolise its political power. "
    isPlural = true
    owner = location
;

++ Component 'feathered eagle\'s wings' 'feathered wings'
    "Sometimes they look like eagle's wings, sometimes they morph into extra
    heads and horns, as the beast keeps changing shape. "
    isPlural = true
    owner = location
;

++ Component 'lion\'s ravening ferocious mouth/mouths' 'mouth'
    "The beast's mouth (or mouths) is (or mare) ravening and ferocious,
    looking for something to devour. "
    owner = location
;

pawnGroup: CollectiveGroup 'red white *pawns*peasants' 'pawns'
    "The pawns are carved to look like rather shabby peasants. "
;

class RedPawn: RedChessPiece 'red chess shabby peasant/pawn*pawns*pieces*peasants' 
    'red pawn'
    "The pawns are carved to look like rather shabby peasants. "
    isEquivalent = true
    theName = (aName)
    collectiveGroup = pawnGroup
    dobjFor(Eat) 
    {
        verify() { illogical('It\'s a pawn, not a prawn! '); }
    }
;

RedPawn;
RedPawn;
RedPawn;
RedPawn;
RedPawn;
RedPawn;

RedChessPiece '(roman) cavalryman/knight*knights' 'red knight'
    "The red knight looks much like a Roman cavalryman. "
;

RedChessPiece '(roman) legionary*legionaries' 'red legionary'
    "The piece representing the legionary looks just like that: a Roman
    legionary complete with spear, shield, gladius and helmet. "
;

+ Component 'helmet' 'helmet'
    owner = location
;

+ Component 'long rectangular shield' 'shield'
    "It's long and rectangular. "
    owner = location
;

+ Component 'short stabbing gladius/sword' 'gladius'
    "It's a short stabbing sword. "
    owner = location
;

+ Component 'spear' 'spear'
    owner = location
    dobjFor(KnockOn) { verify() { illogical(&cannotKnockOnHoleMsg); } }
;

RedChessPiece '(roman) senator*senators' 'red senator'
    "The piece is a senator by its robes; from its pose it might either be
    declaiming in the senate or performing some sacerdotal function in a pagan
    Roman rite. "
;

class WhitePawn: WhiteChessPiece 'shabby peasant/pawn*pawns*peasants' 'white pawn'
    "The pawns are carved to look like rather shabby peasants. "
    isEquivalent = true
    theName = (aName)
    collectiveGroup = pawnGroup
    dobjFor(Eat) 
    {
        verify() { illogical('It looks like a ******* peasant, not a plucked pheasant! '); }
    }
;

pawn1: WhitePawn;
pawn2: WhitePawn;
pawn3: WhitePawn;
pawn4: WhitePawn;
pawn5: WhitePawn;
pawn6: WhitePawn;

priest: WhiteChessPiece 'priest*priests' 'white priest'
    "The white priest is depicted as wearing suitable priestly attire. "
;

knight: WhiteChessPiece '(jewish) knight*knights/cavalryman' 'white knight'
    "It's presumably meant to look like someone's idea of a Jewish cavalryman
    of the period. "
;

castle: WhiteChessPiece 'tower/castle/rook*castles*rooks' 'white castle'
    "It looks a bit like a miniature tower: perhaps it's meant to represent one
    of the towers in the walls of Jerusalem. "
;

sicarius: WhiteChessPiece 'sicarius*sicarii' 'white sicarius'
    "According to Josephus, the <i>sicarii</i> were a type of urban terrorist
    who assassinated collaborators in a crowd and then melted away into the
    multitude. This figure of a sicarius is accordingly depicted brandishing a
    small dagger, the sicarii's preferred weapon (from which they took their
    name). "
;

whiteSoul: WhiteChessPiece 'soul/king*kings*souls' 'white soul'
    "The white soul is depicted as wearing a white shroud and a crown. You know
    instinctively that this piece is effectively your king. "
    checkIobjTakeWith()
    {
        inherited;
        if(gDobj==whore)
        {
            reportFailure('You dare not risk your soul in such a manoeuvre. ');
            exit;
        }
    }
;

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

tunnelJunction : Room 'Tunnel Junction' 'the tunnel junction'
    "A tunnel from the north joins the rough east-west tunnel at this point.
    The air from the north smells rather fresher than that from the west, and
    the northern branch of the tunnel looks rather brighter too. "
    east: OneWayRoomConnector {
        -> chessRoom
        canTravelerPass(traveler) { return !snake.moved; }
        explainTravelBarrier(traveler)
        { 
            "The fissure in the chess room wall seems to have closed up again;
            you can no longer get back in there. ";
        }
    }
    north = eden
    west = swampside
    thinkHere = "There's not much here but a junction. "
    roomParts = [defaultFloor, defaultCeiling, defaultSouthWall, defaultNorthWall]
    northLook = "To the north runs the shortest and brightest of the tunnels
        leading from this junction. "
    westLook = "The tunnel continues some distant to the west. "
    eastLook = "You see a tunnel leading off to the east. "
;

+ SimpleOdor 'unpleasant marshy fresh sweet air/smell' 'air'
    "The air from the west has an unpleasant marshy smell about it, while that
    from the north smells fresh and sweet. "
;

//==============================================================================
edenGround: defaultGround 'fresh spring turf/ground/grass' 'ground'
    "The ground here is fresh, springy turf. "
;

eden : OutdoorRoom 'Paradisal Garden' 'the paradisal garden'
    "To the north the garden stretches as far as you can see, while to the west
    grows every kind of shrub. To the south is the entrance to a cave, and to
    the east a peaceful grove of trees. Pride of place, however, goes to the
    majestic tree that stands proud and alone right here, at the centre of the
    garden. "
    roomFirstDesc = "You emerge into a garden that is astonishingly paradisal
        compared with the places you've just come from. For a moment you stop,
        staring in wonder. Then, once again, understanding dawns: you are still
        playing out the apocalyptic mythology of the New Testament, in this
        case <i>Endzeit</i>-<i>Urzeit</i>, the notion that the final defeat of
        evil at the end would result in the restoration of the paradise at the
        beginning. With the defeat of the evil powers symbolized by the
        Emperor, the Whore and the Beast, you have quite predictably arrived at
        the Garden of Eden. "
    south = tunnelJunction
    
    /* 
     *   This game was written before the DeadEndConnector was added to the 
     *   library; it makes no practical difference here, but in this sort of 
     *   situation the DeadEndConnector would now be used rather than the 
     *   FakeConnector.
     */
    
    north: FakeConnector { "You wander round the huge garden for a while, but
        then return to the tree near its centre. " }
    east: FakeConnector { "You go and look behind the shrubs towards the east
        of the gardens, but though it's all very picturesque and you enjoy your
        stroll, you find nothing particularly remarkable, so you return to the
        great tree at the centre. " }
    west: FakeConnector { "You take a long walk in the shade of the trees on 
        the west side of the garden, but eventually wander back to the large
        tree at the centre. " }
    out asExit(south)
    roomParts = [edenGround, blueSky]
    thinkHere = "This place corresponds quite closely to your mental picture
        of the Garden of Eden. "
    vocabWords = 'paradisal paradise/eden/garden*gardens' 
    westLook = "Over to the west you see every kind of shrub growing. "
    eastLook = "To the east lies a peaceful grove of trees. "
    southLook = "The garden continues to the south, towards the entrance of a
        cave. "
    defaultLook(d) { "The paradisal garden surrounds you on every side. "; }
;

+ Distant 'peaceful green russet giant oak ash beech 
    pine grove/trees*trees oaks elms pines redwoods' 'peaceful grove'
    "It looks like every variety of tree you have ever seen grows there,
    together with a great many you have never seen before. Oaks, elms, pines,
    ash, beech trees and even giant redwoods all have their place, not crowding
    one another, but standing apart at a respectful distance so that the
    sunlight has space to play between them. "
    dobjFor(Enter) remapTo(West)
;

+ Vaporous 'sun light/sunlight' 'sunlight'
    "You're not entirely sure how this garden manages to have sunlight without
    a sun, but somehow it seems churlish or inappropriate to ask such questions
    in such a spot -- or maybe it\'s just that you\'re finding it hard to get
    your poor dead brain to focus right now. In any case, some sort of light
    that closely resembles sunlight floods the garden and plays among the trees
    and shrubs. "
;

+ Distant 'tasteful every green low colourful kind/shrub/array*shrubs bushes 
    flowers' 'shrubs'
    "A tasteful array of every kind of shrub and flower stretches colourfully
    to the the east, interspersed with low bushes cunningly laid out. "
    isPlural = true
    dobjFor(Enter) remapTo(East)
;

+ edenCave : EntryPortal -> tunnelJunction 
    'mouth/cave/entrance*caves*entrances*mouths' 'cave'
    "The mouth of the cave lies just a short way through the garden to the
    south. "
    nothingBehindMsg = &cannotSeeBehindMsg
;

+ appleTree: Fixture 'central majestic (apple) low tree/branch*trees*branches' 
    'central tree'
    "This majestic tree stands right at the centre of the garden.
    <<apple.isIn(self) ? 'A single apple dangles from a low branch. ' : ''>>"
    dobjFor(Climb)
    {
        preCond = [touchObj]
        verify() {}
        check() {
            reportFailure('It doesn\'t look that easy to climb, and you can\'t
                see any point in trying. ');
            exit;
        }
    }
    cannotClimbMsg = 'It\'s possible you could climb it, but you can\'t see what
        possible purpose doing so would serve. '
    
;

++ apple : Food 'golden delicious single dangerous large round green
    apple*fruit*apples' 
    'apple' "It's large, green and round. "
    initSpecialDesc = ""
    dobjFor(Eat)
    {
        preCond = [objHeld]
        action()
        {
            "The apple turns out to be sweet and juicy; you can\'t imagine what
            that snake was going on about.\b
            Then you start to find out.\b
            Your consciousness and understanding start to grow exponentially,
            as all knowledge of good and evil floods your brain. You come to
            know the origins of evil and the true nature of good. You learn to
            discern the precise proportions of good and evil in every thought
            and deed. In flash after flash of insight you understand what the
            ultimate fate of the universe will be: whether good will triumph,
            how evil will be rewarded, how the age-old conflict between good
            and evil will be resolved. Yes! Now at last you understand it
            all...\b";
            inputManager.pauseForMore(true);
            "... but the knowledge proves too much for you. There is only so
            much reality humankind can bear, and the full understanding of the
            evil in your own heart proves heart-breaking, as does your insight
            into the wasted potential for good. Besides, it's simply too much
            information overload for your finite mind. As your consciousness
            expands to judge every good and evil deed of every creature that
            ever lived or will live throughout the universe, your synapses
            start to burn out and your head feels ready to burst...\b
            Good, evil, good, goo goo fevil boo gar vile snook hope doog live
            floof Aaghhhh!...\b";
            
            finishGameMsg('YOU HAVE GONE TOTALLY INSANE',
                          [finishOptionFullScore, finishOptionUndo]);
        }
    }
    dobjFor(Taste) asDobjFor(Eat)
    smellDesc = "It smells fresh and sweet. "
    disambigName = 'golden delicious apple'
;

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

Occluder, DistanceConnector [swampside, stonePodium]
    occludeObj(obj, sense, pov)
    {
        if(pov.isIn(swampside))  
            return obj == stonePodiumFloor;
        else
            return obj is in (defaultFloor);
    }
;

swampside: Room 'Swamp Cave' 'the swamp cave'
    "Most of this large rectangular cave is taken up by the fetid swamp
    immediately to the west of the narrow strip of dry land you're
    <<gPostureName>> on. This narrow strip effectively forms a path running
    south to a tunnel and north to a large stone podium situated along the
    north side of the swamp, while a second tunnel leads away to the east. "
    roomFirstDesc = "You emerge into a large cave, and at once stop in horror
        and amazement, for the first thing you set eyes on is a blonde woman
        sinking into a vile-looking swamp<<gRevealed('felicity-picture') ? ',
            just as you saw pictured before' : ''>>. "
    
    east = tunnelJunction
    south = mountainTunnel
    north = stonePodium
    thinkHere()
    {
        if(felicity.isIn(swamp))
            "You wonder vaguely how Felicity got into the swamp, but you're
            horrified to see here there and your main concern right now is to
            rescue her. ";
        else
            "The swamp with is vile smell of humbug and its steadily popping
            buzz-words reminds you of something you were suffering not that
            long ago. ";
    }
    roomParts = static inherited - defaultNorthWall
    northLook
    {
        "The strip of land continues northwards to a large stone podium. ";
        listRemoteContents(stonePodium);
    }
    roomRemoteDesc(actor)
    {
        if(actor.isIn(stonePodium))
            "To the south a narrow strip of land runs alongside a large
            smelly swamp. ";
    }
    southLook = "The strip of land runs south to the entrance of a tunnel. "
    eastLook = "Directly to the east is the entrance to a tunnel. "
    westLook  { nestedAction(Examine, swamp); }  
    throwDests = [[westDirection, swamp], [southwestDirection, swamp], 
        [northwestDirection, swamp], [eastDirection, swampTunnelEast]]
    
;

+ swampTunnelEast: EntryPortal ->tunnelJunction 
    'main (east) (e) entrance/tunnel*tunnels' 'main tunnel'
    "The main tunnel leads off to the east, away from the swamp. "
    dobjFor(KnockOn) { verify() { illogical(&cannotKnockOnHoleMsg); } }
    nothingBehindMsg = &cannotLookBehindMsg
;

+ EntryPortal ->mountainTunnel 'second (south) (s) tunnel*tunnels' 'second tunnel'
    "The second tunnel leads off to the south, where the narrow strip of dry
    land meets the south wall of the cave. "
    dobjFor(KnockOn) { verify() { illogical(&cannotKnockOnHoleMsg); } }
    nothingBehindMsg = &cannotLookBehindMsg  
;

//+ swampPodium : Enterable -> stonePodium 'large stone podium' 'large stone podium'
//  "The podium is a large stone platform standing well proud of the swamp and
//   running along its northern edge. "
//  dobjFor(StandOn) asDobjFor(Enter)
//;

+ swamp : OutOfReach, Booth, Fixture 'disgusting vile vile-looking malodorous 
    brown smelly fetid foetid swamp/marsh/mire*swamps'
    'swamp'
    "The swamp is a seething, bubbling mass of disgusting brown mire. It covers
    a rectangular area about the size of a large lecture theatre; to west and
    south it's bounded by the walls of the cave, to east by a narrow strip of
    dry land<<gActor.isIn(swampside) ? ' on which you\'re ' + gPostureName : ''
      >>, and to the north by the stone podium<<gActor.isIn(stonePodium) ? ' on
          which you\'re ' + gPostureName : '' >>. "  
    
    dobjFor(StandOn)
    {
        verify()
        {
            illogical('There\'s no point trying to enter the swamp; you\'d
                simply sink and drown in it. ');
        }
    }
    dobjFor(LieOn)
    {
        verify()
        {
            illogical('You certainly don\'t want to do that; you\'d sink into
                it and drown. ');
        }
    }
    iobjFor(ThrowInto)
    {
        verify() { }
        remap() { }
        action() {
            if(gDobj == rope)
                "You throw one end of the rope into the swamp. ";
            else
            {
                "You throw {the dobj/him} into the swamp, where {it dobj/he}
                sink{s} rapidly out of sight. ";
                gDobj.moveInto(nil);
            }
        }
    }
    dobjFor(Swim) asDobjFor(StandOn)
    iobjFor(ThrowAt) remapTo(ThrowInto, DirectObject, self)
    dobjFor(KnockOn) { verify() { illogical(&cannotKnockOnHoleMsg); } }
    sightSize = large
    smellSize = large
    soundSize = large
    canObjReachSelf(obj) { return true; }  
    feelDesc = "It's wet, clammy, sticky and generally unpleasant. "
    allowedPostures = [standing]
    cannotSitOnMsg = 'You\'re just as likely to sink in it sitting as standing. '
    cannotLieOnMsg = 'You can\'t lie <i>on</i> it; you\'d sink straight into it. '
#ifdef __DEBUG
    verifyDobjPow() { logicalRank(140, 'locator'); }
#endif
;

++ Odor 'strong stench/humbug' 'stench'
    descWithSource = "A strong stench of humbug rises from the swamp. "
    sourceDesc = "The swamp reeks of humbug. "
    hereWithSource = (descWithSource)
    isAmbient = nil
    displaySchedule = [2, 2, 4, 4, 8]
    continueEmanation()
    {
        if(rope.pulls != 3)
            inherited;
    }
;

++ Noise 'bubble/pop*bubbles' 'bubble'
    descWithSource = "A bubble on the surface of the marsh pops loudly
        with a noise that sounds like <q><<popWord>></q>. "
    hereWithSource = (descWithSource)
    isAmbient = nil
    displaySchedule = [1, 2, 3, 3, 5]
    popWord() { return popWords.getNextValue; }
    popWords : ShuffledList {
        valueList =
    [
        'Religionsgeschichte', 'Semiotic', 'Midrash', 'Ideological', 'Allegorical',
        'Exegesis', 'Targumim', 'Proto-rabbinic', 'Demythologization', 'Boundaries',
        'Philonic', 'Intertexture', 'Binary Opposition', 'Leitmotiv', 'Q Parallel',
        'Sitz im Leben'
    ]
        suppressRepeats = true    
    }
    continueEmanation()
    {
        if(rope.pulls != 3)
            inherited;
    }
;


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


stonePodiumFloor : Floor 'perfectly smooth polished stone floor/ground' 'floor'
    "The floor is perfectly smooth, as if the stone has been carefully leveled
    and polished. "
;

class SPWall : RoomPart 'stone rough rock wall/rock*walls' 'wall'
    "It's a rough rock wall, seemingly carved out of the end of the cave. "
;

sPNWall: SPWall 'north (n) -' 'north wall'
;

sPEWall: SPWall 'east (e) - ' 'east wall'
;

sPWWall: SPWall 'west (w) - ' 'west wall'
;

stonePodium: Room 'Stone Podium' 'the stone podium'
    "This curious chamber, enclosed by walls of rock on three sides, has a
    perfectly smooth floor that acts as a raised area overlooking the swamp to
    the south. A stone lectern stands on the southern edge of the floor,
    opposite a carving high up on the northern wall. A path leads round the
    eastern side of the swamp to the south. "
    south = swampside
    roomParts = [stonePodiumFloor, sPNWall, sPEWall, sPWWall, defaultCeiling]
    thinkHere = "This place reminds you of something, but something as seen
        from a slightly different perspective in a rather different form. "
    southLook 
    {
        describeRemoteRoom(swampside);     
    }
    inRoomName(pov) { return 'on the podium'; }
    vocabWords = 'large stone podium/platform'
    remoteDesc(pov)
    {
        "The podium is a large stone platform standing well proud of the swamp
        and running along its northern edge. ";
    }
    sightSize = large
    dobjFor(Enter) maybeRemapTo(gActor.isIn(swampside), North)
    cannotEnterMsg = 'You\'re already there. '
    dobjFor(StandOn) 
    {
        remap()
        {
            if(gActor.isIn(self))
                return [StandAction];
            else
                return [NorthAction];
        }
    }
;

+ Fixture, Surface 'stone lectern*lecterns' 'stone lectern'
    "The curiously positioned lectern looks much like an ordinary wooden one,
    except that it is carved from solid stone and fixed firmly in place. "
;

++ parchment: Hidden, Readable 'grey badly damaged lecture faded
    piece/parchment/writing/notes' 
    'piece of grey parchment'
    "The piece of grey parchment is badly damaged, and the writing on it is
    only partially decipherable. From what remains, you surmise that it could
    be a set of lecture notes. "
    readDesc = "The only part you can make out clearly reads:\b
        <q>Religionsgeschichtliche exegesis of Philonic midrash in its
        demythologizing Sitz im Leben...\n
        Binary opposition between marsh and dry land...\n
        ... no life beyond the grave, this is as impossible as...\n
        Moses... snake... rod... Pharaoh... \n
        Exodus typology... signs and wonders...\n
        all myth... couldn\'t really happen...\n
        My mind is as empty as the tomb...</q>"
    discover()
    {
        inherited;
        reportAfter('The parchment is so grey that it\'s almost the same colour
            as the stone lectern, which is why you almost missed it. ');   
    }
    sightSize = small
;

+ Distant 'circular clock/carving/design/rim*carvings*designs' 'circular carving'
    "The carving is of a circular design with a sequence of Roman numerals
    round the rim - effectively a clock without hands. There is also an
    inscription at the centre of the clock. "
    initNominalRoomPartLocation = sPNWall
    dobjFor(Read) remapTo(Read, clockInscription)
;

++ Component, Distant 'roman numerals' 'Roman numerals'
    "They run round the rim of the carving in just the sequence you'd expect on 
    a clock: I, II, III, IV, V, VI, VII, VIII, IX, X, XI, XII. "
    isPlural = true 
    dobjFor(Read) asDobjFor(Examine)
;

++ clockInscription: Component, Distant 'inscription/centre/center/(clock)' 
    'inscription'
    "The inscription reads: HIC TEMPUS NON FUGIT. You translate this as <q>Time
    does not fly here.</q> "
    dobjFor(Read) asDobjFor(Examine)
;

++ Unthing 'hands' 'hands'
    'The clock has no hands -- perhaps because in eternity no time passes. '
;

+ PathPassage, Distant 'dry path/land/strip*paths' 'path'
    "The path is a strip of dry land running along the east side of the swamp. "
    destination = swampside
    dobjFor(StandOn) asDobjFor(TravelVia)
    nothingBehindMsg = &unclearWhatBehindMsg
;

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

mountainTunnel : Room 'Tunnel End' 'the end of the tunnel'
    "The narrow tunnel from the north comes to an end in a rough-hewn limestone
    chamber with a flat shelf of rock to one side and a loculus (or niche) to
    the other. To the south is <<mountainDoor.isOpen ? 'an opening' : 'a
        shallow recess'>>. <<wheelCompartment.isIn(self) ? 'Next to it is a
            compartment. ' : ''>> "
    
    north = swampside
    south = mountainDoor
    out : ConditionalConnector {
        -> swampside
        ": north or south"
        @(mountainDoor.isOpen)
    }
    thinkHere = "This place seems to be yet another attempt to represent Jesus'
        burial-place. "
    roomParts = static inherited - defaultNorthWall
    northLook = "To the north the tunnel leads back towards the swamp. "
    vocabWords = 'end/tunnel'
    
;

+ RoomPartItem, Platform, Fixture 'flat shelf/rock' 'flat shelf of rock'
    "It's about three feet off the ground, three feet wide and six feet long. "
    reachableObjects = [defaultEastWall]
    initNominalRoomPartLocation = defaultEastWall
    initSpecialDesc = "Against the east wall is flat shelf of rock. "
    nothingBehindMsg = 'Only the wall lies behind the rock. '
;

+ tunnelLoculus: RoomPartItem, Container, Fixture 
    'plain rough-hewn rough burial niche/loculus' 
    'loculus' "It's a plain, rough-hewn burial niche; about six inches square
        or so. "
    initNominalRoomPartLocation = defaultWestWall
    initSpecialDesc = "In the west wall is a loculus. "
    dobjFor(KnockOn) { verify() { illogical(&cannotKnockOnHoleMsg); } }
    nothingBehindMsg = &cannotLookBehindMsg
;

++ ossuary2: OpenableContainer '(stone) crude limestone (bone) ossuary/box' 
    'limestone ossuary'
    "It's a crudely-carved limestone ossuary with no decoration of any kind;
    obviously not a bone-box for the wealthy. "
    dobjFor(Open)
    {
        verify()
        {
            if(isIn(tunnelLoculus))
                illogicalNow('{You/he} can\'t open the ossuary while it\'s in
                    the niche.' );
            else
                inherited;
        }
    }
    dobjFor(Take)
    {
        action()
        {
            if(!moved)
            {
                "Removing the ossuary from its loculus reveals a small lever
                protruding from the rear of the niche. ";
                gSetSeen(smallLever);
            }
            inherited;
        }
    }
    iobjFor(BlockWith) { verify() { } }
    nothingBehindMsg = (isIn(tunnelLoculus) ? 'You can\'t see behind the ossuary
        while it\'s in the niche. ' : nil)
;

+++ oldBones: Thing 'old bleached dry human bones/bone' 'old bones'
    "The old bones are bleached and dry. They may once have come from human
    limbs, but between them they hardly make up a complete skeleton. "
    isPlural = true 
    iobjFor(BlockWith) { verify() { } }
;


++ smallLever: Hidden, SpringLever, Fixture 'small protruding projecting lever*levers' 
    'small lever'
    "The lever projects out of the side of the niche towards its rear. " 
    initSpecialDesc = "Towards the rear of the niche what looks like a small
        lever of some sort projects from the wall. "
    discovered = (!ossuary2.isIn(tunnelLoculus))  
    discover() {}
    dobjFor(Pull)
    {
        verify()
        {
            local pullActor;
            if((pullActor = pulledBy) != nil)
            {
                gMessageParams(pullActor);
                illogicalAlready('{The pullActor/he} {is} already pulling the
                    lever. '); 
            }
        }
        action()
        {
            "As {you/he} pull{s} the lever, a compartment opens in the south
            wall, next to the <<mountainDoor.isOpen ? 'opening' :'recess'>>,
            revealing a large iron wheel inside. ";
            wheelCompartment.makePresent();
            pulledBy = gActor;
        }
    } 
    pulledBy = nil
    beforeAction()
    {
        if(gActionIn(ThrowAt, ThrowTo))
            return;
        if(gActor == pulledBy && gDobj != nil && 
           gDobj != self && !gActionIs(Examine) )
        {
            "As {you/he} release{s} the lever, the compartment closes,
            concealing the iron wheel.<.p>";
            wheelCompartment.makePresentIf(nil);
            pulledBy = nil;
            if(gDobj is in (ironWheel, wheelCompartment) 
               || gDobj.isIn(ironWheel) || gIobj == ironWheel
               || (gIobj != nil && gIobj.isIn(wheelCompartment)) 
               || gIobj == wheelCompartment )
                exit;
        }
    }
    cannotPutBehindMsg {  
        if(pulledBy != nil )
            return 'That isn\'t possible; to put anything behind the lever
                {you/he} would first need to remove {your/her} arm from the
                loculus, but then the lever would spring back into place, thus
                preventing anything from being put behind it. ';
        else
            return 'The lever gets in the way of any attempt to put anything
                behind it. ';
    }
    dobjFor(BlockWith)
    {
        verify() { }
        check()
        {
            if(gIobj == ossuary2)
                failCheck('The ossuary is too large to fit over the lever. ');
            else
                failCheck('The attempt to wedge the lever with {the iobj/him}
                    proves fruitless; {you/he} {can\'t} fit {the iobj/him} into
                    a position where {it iobj/he}\'ll stay put. ');
        }
    }
    iobjFor(FastenTo) asIobjFor(AttachTo)
    iobjFor(AttachTo)
    {
        verify() { }
        check()
        {
            if(gDobj == rope)
                failCheck('The niche is too narrow; you can\'t get your hands
                    in to tie a knot. ');
            else
                failCheck('There\'s not enough room in the niche to allow you
                    to attach {the dobj/him} to the lever. ');
        }
    }
;

+ wheelCompartment: PresentLater, Fixture, Container 'compartment*compartments' 
    'compartment'
    "It's set in the south wall next to the <<mountainDoor.isOpen ? 'opening'
      :'recess'>>, and is about two foot square. "   
    dobjFor(BlockWith) 
    {
        verify() { }
        action()
        {
            "There's no need to do that now. ";
        }
    }
    nothingBehindMsg = &cannotLookBehindMsg
;

++ ironWheel : Fixture 'large iron wheel*wheels' 'iron wheel'
    "The wheel is about eighteen inches in diameter. It comprises a rim
    connected to a central hub with four iron spokes. "
    dobjFor(Turn)
    {
        verify() { }
        action() {
            "As {you/he} turn{s} the wheel, ";
            if(mountainDoor.isOpen)
                "an iron spike rises out of the ground towards the right-hand
                end of the opening to the south. Since this serves no useful
                purpose, {you/he} turn{s} the wheel back again and the spike
                sinks out of sight. ";
            else
                openDoor();
        }
    }
    openDoor()
    {
        "a creaking sound starts to come from the recess. Slowly, a crack
        appears at ground level towards its right-hand end. As the crack
        widens, you see that a metal spike is rising from the ground, gradually
        pushing up one end of the stone slab. {You/he} continue{s} to turn the
        wheel, the spike continues to rise, and the slab starts to tilt, until
        with  a loud <i>thump</i> it topples over, leaving a large rectangular
        opening to the south. Since the spike now partly blocks the opening,
        {you/he} wind{s} the wheel back so that the spike sinks back into the
        ground. ";
        mountainDoor.makeOpen(true);    
        PresentLater.makePresentByKeyIf('demon', nil);    
        pipe.blocked = true;    
        pipeCable.moveInto(nil);
        achievement.awardPointsOnce();
    }
    achievement: Achievement { +1 "getting Felicity to help you with the lever
        and wheel" }
    specialDesc = "Inside the compartment is an iron wheel. "
    iobjFor(FastenTo) asIobjFor(AttachTo)
    iobjFor(AttachTo)
    {
        verify() { }
        action() { "There's no need to do that. "; }
    }
;

+++ Component '(iron) rim*rims' 'rim'
    "It's about an inch thick. Like the rest of the wheel, it's made of iron. "
    dobjFor(Turn) remapTo(Turn, ironWheel)
;

+++ Component 'four iron spokes' 'iron spokes'
    "Each of the spokes is about half an inch thick and six inches long. "
    isPlural = true
    dobjFor(Turn) remapTo(Turn, ironWheel)
;

+++ Component 'central hub*hubs' 'hub'
    "The hub is about four inches in diameter. "
;

+ mountainDoor: RoomPartItem, SecretDoor 'large rectangular stone separate shallow 
    opening/recess/slab/stone*slabs*openings*recesses' 'recess'
    "<<isOpen ? 'The shallow recess is only a few inches deep, but' : 'The
        opening is'>> about six feet high by three wide<<isOpen ? 'and looks
            out over a small enclosed garden' : '. A closer examination
                suggests that the rear wall of the recess could be a separate
                slab of stone'>>. "
    makeOpen(stat)
    {
        name = stat ? 'opening' : 'recess';
        inherited(stat);
    }
    dobjFor(Push)
    {
        verify() {
            if(isOpen)
                illogicalNow('The slab has already been moved aside. ');
            else
                nonObvious;
        }
        action()
        {
            "You hear a brief scraping noise as the slab forming the wall of
            the recess moves a fraction, but it's too heavy to move any
            further. ";
        }
    }
    dobjFor(Move) asDobjFor(Push)
    initNominalRoomPartLocation = defaultSouthWall
    initSpecialDesc = "In the south wall is << isOpen ? 'an opening overlooking 
        a small garden' : 'a shallow recess'>>. "    
    nothingBehindMsg = &cannotLookBehindMsg
;


+ Hidden, Distant 'small walled enclosed garden*gardens' 'small walled garden'
    "There's not much to it, so far as you can see: just a solitary apple tree
    and some scraggy grass. "
    dobjFor(Enter) remapTo(South)
    discovered = (mountainDoor.isOpen)
;

+ Hidden, Distant 'solitary stunted bare wintry apple tree*trees' 'apple tree'
    "It looks stunted, bare and wintry. "
    discovered = (mountainDoor.isOpen)  
;

+ Hidden, Distant 'scraggy green grass*grasses' 'scraggy grass'
    "It barely covers the enclosed garden. "
    discovered = (mountainDoor.isOpen)  
;