#charset "us-ascii"
#include <advlite.h>

//  The exterior front:
//      parkingLot
//      mainEntrance
//      chartreuseStairwell
//      hedgeBorderedPath
//      behindStairs
//      curvingPath
//      northOfTower
//      untendedGarden
//      patio
//      employeeParking
//      loadingDock

// Outdoor rooms need a RoomPartItem that's pavement.

viewOfStufftown: MultiLoc, Decoration 'Stufftown; shopping; center building'
    "The view of Stufftown is imposing, but not inspiring. "
    locationList = [employeeParking, loadingDock, patio, untendedGarden, hedgeBorderedPath]
    notImportantMsg = 'You\'ll be busy in Stufftown this afternoon, but interacting
        with the building itself is not one of the challenges you\'re likely to face. '
    proper = true
;

//-----------------------------------------------------------------------------
// parkingLot
//-----------------------------------------------------------------------------

class ParkingLotRoom: Room
    dobjFor(Examine) {
        action() {
            "A very few cars are scattered across the parking lot. ";
        }
    }
;

parkingLotBarrier: TravelBarrier
    canTravelerPass(traveler, connector) { return nil; }
    explainTravelBarrier(traveler, connector) {
        "There's nothing over that way but more parking lot. ";
    }
;

pavement: Floor 'pavement; grimy; paving blacktop ground floor'
    "The pavement is rather grimy. "
;

parkingLot: ExteriorLocation, ParkingLotRoom 'Parking Lot'
    "<<one of>>Word of the parade seems to have spread through town like wildfire. Surely on a
    normal Saturday afternoon there would be more than a bare handful of cars in Stufftown's
    broad and rather grimy parking lot. The bulk of
    the shopping center squats
    in decrepit splendor to the south, down a walk. It looks no more
    inviting than you expected it to. <<or>>A bare handful of cars is scattered here and there across the parking lot.
    The bulk of
    the shopping center squats in decrepit splendor to the south, down a walk. <<stopping>>To
    the southwest a narrow drive curves around the building,
    next to it a sign that reads <q>EMPLOYEE PARKING ONLY.</q> "
    
    floorObj = pavement
    regions = [betsyGoneRegion]
    south = mainEntrance
    north () {
        "<<one of>>Moved, perhaps, by a vague impulse to see if you can
        glimpse the lacrosse championship parade from here, you stride out into the
        road. After nearly being run down
        by a passing truck, you scamper back into the parking lot. <<or>>Walk home? But you haven't finished
        your shopping trip yet! <<stopping>>";
    }
    east = "There\'s nothing over that way but more parking lot. "
    northwest asExit(east)
    northeast asExit(east)
    southeast asExit(east)
    west asExit(east)
    southwest = employeeParking
;

+ stufftownFromParkingLot: Distant 'Stufftown; shopping hulking; center bulk mall building structure'
    "The last time you saw Stufftown, ten years ago, at dusk in the dead of winter, you found
    yourself thinking of it as <q>the ill-favored offspring of a fairy castle and a canning
    factory.</q> Today gay pennants fly from the towers and parapets, and a fresh coat of paint
    has been slapped on the hulking structure, but somehow its underlying tawdriness seems
    undiminished. Also, it's larger than you recall. Or perhaps it shriveled and shrank
    in your memory. "
    
    dobjFor(Take) {
        verify () { illogical ('Quite aside from the fact that it\'s about fifty yards away, the building
        surely weighs hundreds of tons. You really ought to try becoming a bit less acquisitive.
            (You\'re an American, am I right?) ');
        }
    }
    
    dobjFor(Enter) {
        verify() {
            illogicalNow ('The building is some distance away to the south. ');
        }
    }
    dobjFor(GoTo) {
        verify() {}
        check() {
            if (!gPlayerChar.isIn(parkingLot))
                "You're already in Stufftown, or quite nearby. ";
        }
        action() {
            doInstead(Go, southDir);
        }
    }
    decorationActions = [Examine, Take, Enter, Photograph, LookAtThrough, GoTo]
;

++ Decoration 'towers;; parapets tower parapet'
    "The details of the architect's grandiose yet inept conception are not important. "
    plural = true
;

++ Decoration 'gay pennants ; gaily colored limp; pennant; them'
    "The gaily colored pennants atop the towers would doubtless flutter festively in the breeze, if there were a
    breeze. Alas, at the moment they're hanging limp. There's a pink pennant at the east end
    of the roof (to the left from where you're standing), then a yellow pennant, a green pennant,
    and a blue one at the west end. "
    notImportantMsg = 'The color scheme is perhaps memorable, but the pennants themselves are not important. '
;

// At present (1/18/18) there are no green pennant, yellow pennant, etc., objects, thus producing
// a bad message.

+ myCar: ExteriorLocation, Booth, Heavy
    'your car; robin\'s-egg blue thrifty dusty my; hybrid auto automobile vehicle'
    "Your thrifty gas/electric hybrid is robin's-egg blue, and only a bit dusty. "
    initiallyOpen = true
    isTransparent = true
    qualified = true
    cannotTakeMsg = 'You\'re not King Kong. '
    dobjFor(Drive) {
        verify() {}
        check() {
            "Giving up so soon? ";
        }
    }
    notLockableMsg = 'Locking and unlocking your car won\'t help you get your hands on the prom dress. '
    cannotOpenMsg = 'Opening and closing your car won\'t help you get your hands on the prom dress. '
;

++ Decoration 'glove compartment'
    "Sorry --- the author has not hidden anything useful in the car\'s glove compartment. "
;

++ Decoration 'steering wheel'
    "It looks quite a lot like any other steering wheel. "
;

+ parkingSign: Consultable, Fixture 'employee parking sign'
    "Stationed next to a narrow drive that curves around the building to the southwest, the
    sign reads <q>EMPLOYEE PARKING ONLY.</q> "
    readDesc = 'The sign reads <q>EMPLOYEE PARKING ONLY.</q> '
;

+otherCars: Heavy, Decoration 'other cars; random; assortment autos vehicles; them'
    "The other cars are pretty much the random assortment you'd expect. "
    dobjFor(Take) {
        verify() { illogical ('You\'re not King Kong. ');
        }
    }
    decorationActions = [Examine, Take]
;

//-----------------------------------------------------------------------------
// mainEntrance
//-----------------------------------------------------------------------------

mainEntrance: ExteriorLocation, Room, ShuffledEventList 'Main Entrance'
    "The heavy structure of the shopping center stretches left and right from here.
    When you crane your neck the building seems almost to be leaning outward, as if it's
    in some danger of collapsing on top of you, or perhaps pouncing on you. Doubtless
    that's only a trick of the light. An arched entryway beckons (metaphorically, at least,
    and only if you're willing to stretch the metaphor to the breaking point, as very little about
    Stufftown could ever be called inviting) directly to the south,
    above it the inscription...\b\b
    <b><center>
    FLOGG & GRABBY'S STUFFTOWN\b
    WE GOT THE VERY BEST STUFF!\b\b
    </center></b>

    ...carved in a pigeon-flecked substance that looks more like plaster than like real stone.
    Affixed to the building next to the arch
    is a garishly glowing digital display board at least six feet high, across which crawls,
    splashes, and dances a variety of enthusiastic messages.<.p>
    
    Running along the building above the arch is a covered-over exterior walkway.
    A walk at street level affords passage east and west along the front of the building,
    and the parking lot lies to the north. A broad stairway nearby leads down to the
    southeast, angling under the building. Standing near the top of the stairway is
    a large drum-shaped trash receptacle. "
    
    eventList = [
        '<.p>The marquee flickers brightly. ',
        '<.p>A crow caws raucously somewhere overhead. ',
        '<.p>A truck rumbles past on the road. ',
        '<.p>A faint unpleasant odor drifts into your nostrils. Before you can identify it, it\'s gone. ',
        '<.p>Rap music from a car passing on the road makes a lingering boom-boom-boom before it fades out. ',
        nil,
        nil,
        nil,
        nil,
        nil,
        nil, 
        nil
    ]
    regions = [betsyGoneRegion, joeFollowingRegion, ajouMarchingRegion]
    floorObj = pavement
    north = parkingLot
    south = bigArch
    in asExit(south)
    southeast: TravelConnector, AjouStairs {
        destination = chartreuseStairwell
        travelBarriers = [wagonBarrier]
    }
    down asExit(southeast)
    east = hedgeBorderedPath
    west = patio
;

+ upperWalkway: Distant 'upper walkway'
    "The walkway stretches to the left and right (that is, east and west) overhead. It's too
    high up for you to get at it from here. "
;
    
+ bigArch: Fixture, Passage, AjouStairs 'arched entryway; grand grandiose; arch archway entry portal passage'
    "The arched entryway is, perhaps, a failed attempt to suggest the grandeur (or at least the
    grandiosity)
    of Roman ruins. It stands to the south, providing, patently, access to the interior of
    Stufftown. An inscription is carved above the arch. "
    
    destination = archedPassage
;

+ inscription: Consultable, Fixture 'carved inscription; (pigeon) flecked pigeon-flecked; substance'
    "The inscription above the archway informs you that you're standing before Flogg & Grabby's Stufftown
    (which you already knew) and that the merchandise on offer within is unsurpassed in
    quality (which seems extremely doubtful). "
    readDesc = "\b\b
    <b><center>
    FLOGG & GRABBY'S STUFFTOWN\b
    WE GOT THE VERY BEST STUFF!\b\b
    </center></b>"
;

+ nearbyStufftown: Fixture 'Stufftown; shopping hulking; center bulk mall building structure'
    "From closer in, the shopping center is more imposing, or at least more intimidating, than
    it appeared from a safe distance. "
    
    dobjFor(Take) {
        verify () { illogical ('The entire building? You\'d never be able to cram it into your
        purse. ');
        }
    }
    dobjFor(Enter) { remap = bigArch }
    dobjFor(GoTo) {
        check() {
            "In a general sense, you're already in Stufftown. ";
        }
    }
;

/*
    The marquee jumble master list. Note that these must remain in
    the vertical order shown in order for the clue in the snack bar
    to work. The missing letters are RCELKB PSECOA OUNATS. In order,
    this is 12-3-10-4-18-15-7-9-13-11-16-8-17-1-2-5-14-6.
     
     MAIN LEVEL:
        HINGE ODORS AND WAG CHIN BAT + R = the groaning sandwich board
        PIG FUMES TOGA THIEF + C = puff the magic stogie
        GRUE FOGS LOUSY ORE = your gorgeous self
        RED VALUE SCANT SOLO = colossal adventure
        STATE IF THIN NEST + E = the finest in taste
        WINTER IN ELF PINK + L = inkwell fine print
        TOOT GO PING -- going to pot
        SLAB SEEDS MAIM YEAR VOTES + K= madame bloviatsky seeress 
        I SCOUR TIRE SHOPS + B = scooters irish pub
        
    UPPER LEVEL:
        A ROSY BULLET EPIC + P = play toes republic
        I MEET NUT -- tune time
        CHART FAT FOE MINING TON = attention marching off
        SQUAW TURF LED FOR THREAD + S = stuff world headquarters
        FRYING MEN REDS + E = my green friends
        NOTICE QUIET FRAIL SENT SCALING + C = racquet science + filling station 
        SHAM MUSIC OR WRIST CUPS = scrumptious scrimshaw
        RISE KEY ALONG THOU + O = heres looking at you
        TIGER NO MASON TIME POSE + A = sometimes a grape notion
        WE PIE HE KEG SHY = sky high pee wee
        
        LOWER LEVEL:
        SO CHASTE BARE CURE + O =  chartreuse caboose
        SHE FANS FART FRIEND + U = feathers fins and fur
        GOTH RIG TRASH HAG + N = hot rags hang right
        LET THIN CATS FIGHT + A = the light fantastic
        HEY LUSH DONUT OVA = you shouldnt have
        LOAD STIR BEE + T = asteroid belt
        MAD REWARDS RANG + S = grandmas drawers
        MUTE VITAL MIRROR CHOPPY PISS DIES = primrose plum video psychiatrist
 */

+ marquee: Consultable, Fixture
    'jumbled marquee; glowing multicolored LED digital display illuminated; board marqee word words board billboard'
    "Unlike the old-fashioned marquee you recall from ten years ago, which had individual white
    letters stuck up not quite haphazardly on a black surface behind a locked glass front,
    today's Stufftown
    marquee is a multicolored marvel of LED billboardsmanship. It seems to have suffered the same sort
    of vandalism, unfortunately, in an electronic form. The words scrolling across it,
    while still perfectly readable, would appear to be pure gibberish. If there\'s something
    of deep importance concealed in the gibberish, winkling it out is not likely to be easy. "
    
    vocabLikelihood = 10
    readDesc = "As you watch, the marquee displays, one after another, three
        lists of words. The mention of levels suggests that this jumble may have at one time
        been a list of the names of the shops --- but possibly the digital gremlin responsible
        for this mess did something worse than just mix up the letters. Within a minute or
        so (and without getting too close to an eyestrain-induced migraine) you're able
        to assemble in your addled brain the following compendium of worrisome nonsense:\b\b
        
        MAIN LEVEL:\n
        \tHINGE ODORS AND WAG CHIN BAT\n
        \tPIG FUMES TOGA THIEF\n
        \tGRUE FOGS LOUSY ORE\n
        \tRED VALUE SCANT SOLO\n
        \tSTATE IF THIN NEST\n
        \tWINTER IN ELF PINK\n
        \tTOOT GO PING\n
        \tSLAB SEEDS MAIM YEAR VOTES\n
        \tI SCOUR TIRE SHOPS\b\b
        
        UPPER LEVEL:\n
        \tA ROSY BULLET EPIC\n
        \tI MEET NUT\n
        \tCHART FAT FOE MINING TON\n
        \tSQUAW TURF LED FOR THREAD\n
        \tFRYING MEN REDS\n
        \tNOTICE QUIET FRAIL SENT SCALING\n
        \tSHAM MUSIC OR WRIST CUPS\n
        \tRISE KEY ALONG THOU\n
        \tTIGER NO MASON TIME POSE\n
        \tWE PIE HE KEG SHY\b\b
        
        LOWER LEVEL:\n
        \tSO CHASTE BARE CURE\n
        \tSHE FANS FART FRIEND\n
        \tGOTH RIG TRASH HAG\n
        \tLET THIN CATS FIGHT\n
        \tHEY LUSH DONUT OVA\n
        \tLOAD STIR BEE\n
        \tMAD REWARDS RANG\n
        \tMUTE VITAL MIRROR CHOPPY PISS DIES "  
;

+trashCan: Container, Heavy
    'trash can; circular concrete green greenish beige trash waste garbage oil; refuse bin innards container drum barrel receptacle opening'
    "The trash can is a concrete barrel, painted a rather startling greenish beige. It's
    about the size of an oil drum. Not surprisingly, there's a circular opening in the top. "
    hiddenIn = [shoppingBag, batteredTrumpet]
    dobjFor(LookIn) {
        action() {
            trashCanAch.awardPointsOnce();
            inherited;
        }
    }
;
     
//-----------------------------------------------------------------------------
// chartreuseStairwell
//-----------------------------------------------------------------------------

chartreuseStairwell: ExteriorLocation, Room 'Stairwell'
    "This not very appealing subterranean grotto terminates, at its southern end,
    in a pair of double doors, above which are mounted a festive sign that reads
    <q>CHARTREUSE CABOOSE.</q> The stairs back up to the main entrance angle upward to the north. "
    regions = [betsyGoneRegion, ajouMarchingRegion]
    
    up: TravelConnector, AjouStairs {
        destination = mainEntrance
        travelBarriers = [wagonBarrier]
    }
    north asExit(up)
    northwest asExit(up)
    south = cabooseExteriorDoorOutside
    in asExit (south)
;

+ Decoration 'stairs; ; stairway staircase stair'
    "They\'re just ordinary stairs. "
;
     
+cabooseSign: ShopSign
    'Chartreuse Caboose +; chartreuse green bright yellow-green curvaceous long feminine kissable pink ; caboose eyelashes lips'
    desc () {
        "Above the lettering that proclaims this the entrance to the Chartreuse
        Caboose is a cutesy cartoon depicting the last car in a railroad train.
        A bright yellow-green, the curvaceous caboose has long feminine eyelashes
        and kissable pink lips. It seems to be waggling from side to side so
        energetically that its rear wheels have flown clean off the track. ";
        if (!mentionedAlready) "To the best of your knowledge, railroad cars seldom produce offspring,
            but it can't be ruled out that some sort of mating ritual is being suggested by
            this. ";
        mentionedAlready = true;
    }
    mentionedAlready = nil
;

+cabooseExteriorDoorOutside: ShopDoorOutside, AjouStairs
    '+; chartreuse caboose double; doors; it them'
    otherSide = cabooseExteriorDoorInside
;

//-----------------------------------------------------------------------------
// hedgeBorderedPath
//-----------------------------------------------------------------------------

towerExterior: MultiLoc, Fixture 'cylindrical tower; round wall; spire'
    "The cylindrical tower is too bulky to be called a spire. It's taller than the rest of the 
    building --- three floors high, as well as you can judge looking up at it from
    below. It's not equipped with windows, and the outer wall is of an unattractive
    yellowish brick. The conical roof is covered with shingles so deep green that
    they might as well be black. <<(me.getOutermostRoom == northOfTower) ? 'A tiny balcony
       juts out from the wall of the tower just overhead. ' : ''>>"
    locationList = [hedgeBorderedPath, northOfTower, curvingPath, untendedGarden]
    dobjFor(Climb) {
        verify() {}
        check() {
            "The wall is vertical, and offers no hand- or footholds. ";
        }
    }
;

+ conicalRoof: MultiLoc, Fixture 'conical roof; green pointed; cone'
    "The conical roof is green and tapers (in the manner of cones from time immemorial)
    to a point. It's a little too squat
    to suggest a wizard's pointed hat, but from certain angles it
    does appear to tilt slightly to one side in a rakish, hat-like way. "
    locationList = [hedgeBorderedPath, upperPromenadeEast, curvingPath, northOfTower, untendedGarden]
;

hedgeBorderedPath: ExteriorLocation, Room 'Hedge-Bordered Path'
    "A high hedge, luxuriant and leafy, borders this narrow gravel walkway on the north (to your left
    as you come down the walk from the Main Entrance, which lies to the west). The blank
    brick wall of the building is to the south. <<startCat()>>Along toward the east end of
    the path a stairway leads upward, and a break in the hedge opens a narrow path to
    the northeast. A few steps past the lower end of the stairway stands a round tower with a
    conical roof. "
    
    regions = [betsyGoneRegion, joeFollowingRegion, ajouMarchingRegion]
    
    west = mainEntrance
    northeast = curvingPath
    east = behindStairs
    up: TravelConnector, Thing {
        destination = hedgePathStairwayUp
        travelBarriers = [wagonBarrier]
    }
    catDaemonID = nil
    startCat() {
        if (catDaemonID == nil) {
            catDaemonID = new Daemon (self, &catDaemon, 1);
        }
    }
    stopCat() {
        catDaemonID.removeEvent();
        catDaemonID = nil;
    }
    catCount = 0
    catDaemon() {
        if (catCount == 0)
            "<.p>A fat gray cat scurries away from you and ducks out of sight
            in a shadowed area tucked away behind the stairs. ";
        if (behindStairs.seen) { stopCat(); return; }
        if (gPlayerChar.getOutermostRoom() != hedgeBorderedPath) return;
        catCount++;
        if (catCount == 4)
            "You hear a soft mewing from behind the stairs. ";
        if (catCount == 9)
        {
            "The fat gray cat darts out from behind the stairs and dashes away. ";
            stopCat();
        }
    }
;

+ Decoration 'brick wall; blank featureless'
    "The brick wall is featureless. "
;

+ shadowedArea: Fixture 'shadowed area; shadowy ; recess nook'
    "It appears <<showExit()>>there's a shadowy recess between the stairs and the wall. "
    showExit() {
        behindStairs.isConnectorApparent = true;
    }
    dobjFor(Enter) {
        verify() {}
        action() {
            doInstead (Go, eastDir);
        }
    }
;

+ hedgePathStairwayUp: StairwayUp, AjouStairs 'flight of stairs;; stairway staircase; it them'
    "The stairs lead up to an east-west walkway that runs along the front of
    Stufftown above the ground floor. "
    destination = upperPromenadeEast
    dobjFor(LookBehind) {
        verify() { logical; }
        check() {}
        action() {
            behindStairs.isConnectorApparent = true;
            "Hmm --- there's no sign of the gray cat, but there's a little nook
            back there, directly to the east, that you could easily enter. ";
        }
    }
    dobjFor(GoBehind) {
        verify() { logical; }
        action() {
            behindStairs.isConnectorApparent = true;
            doInstead(Go, eastDir);
        }
    }
;
    
+ narrowPath: PathPassage 'narrow path'
    "The narrow path leads away to the northeast, between the hedge and the curving outer
    wall of the tower. "
    -> curvingPath
;

+ highHedge: Container, Fixture 'high hedge; tall leafy luxuriant green thick; vegetation greenery tangle branches'
    "The hedge is tall, and though there are some small gaps here and there, the greenery is
    so thick that nothing larger than a bird could possibly penetrate
    to its interior. Well, not a turkey. Maybe a nice fat pigeon. "
    dobjFor(Feel) asDobjFor(Search)
    hiddenIn = [birdsNest]
    
    iobjFor(PutIn) {
        verify() {}
        check() {
            "You'd never find {the dobj} again in all that tangle. No, the hedge
                is not a good hiding place. ";
        }
    }
;

++ hedgeGaps: Component 'small gaps; smallish leafy twig-filled; opening gap;them'
    "There are a few smallish, leafy, twig-filled openings among the twigs of the hedge. "
    dobjFor(LookIn) {
        verify() { logical; }
        action() {
            doInstead(LookIn, highHedge);
        }
    }
    dobjFor(PutIn) {
        verify() { logical; }
        action() {
            doInstead(PutIn, highHedge);
        }
    }
;

//-----------------------------------------------------------------------------
// behindStairs
//-----------------------------------------------------------------------------

behindStairs: ExteriorLocation, Room 'Behind the Stairs'
    "There's not <<ropeAch.awardPointsOnce()>>much to see in this little alcove, which is wedged between
    a close-pressing hedge on the north and the walls of the building on the
    south and east. In the cylindrical curve of the east wall is set an arched doorway,
    which is <<behindStairsArch.blocked ? 'blocked by a sheet of gray stone' : 'open'>>.
    On the west, there is just room
    to squeeze between the hedge and the stairs. "
    
    isConnectorApparent = nil
    west = hedgeBorderedPath
    east = behindStairsArch
;

+ behindStairsArch: OctagonExteriorPassage '+; (red) (east); arrow'
    "Carved into the stone at the summit of the stone arch is a red
    arrow that curves down slightly to the right; if it were on a clock face
    it would run from 12:00 to about 1:30.<<if blocked>> At the
    moment, passage through the arch is blocked by a sheet of gray stone.<<else>>
    At the moment, the arch stands invitingly open.<<end>> "
    blocked = true
;

// Do we want the gray stone to be a RoomConnector, a TravelBarrier, or something
// else? When the doorway is open, we want the gray stone to not be there, and
// using cmdDict (or the adv3lite equivalent) to shuffle the vocabulary would be clumsy. It would be better if
// the slate is only present when the passage is blocked. But in that case the slate
// should probably just be a dumb fixture. The doorway itself should be the RoomConnector.
// But: If we do it that way, then the octagonalRoom itself will have, like, 11 RoomConnectors
// in it. This could get awkward. Need to think about this some more.

// I think we can use some sort of TravelConnector -- even a Door -- of which there will be only two in the
// Octagonal Room and the others in the outside rooms. What we do is, when the Octagon moves,
// we adjust the otherSide parameters and isOpen parameters (makeOpen(true)) of the various
// Door objects.

//-----------------------------------------------------------------------------
// curvingPath
//-----------------------------------------------------------------------------

curvingPath: ExteriorLocation, Room 'Curving Path'
    "This narrow gravel walkway curves around the north side of the cylindrical
    tower. The outer side of the curve is blocked by a high fence. To the southwest
    the path lies open; to the east it's blocked by the bars of an iron gate. "
    southwest = hedgeBorderedPath
   east = ironGateOutside
;

+ narrowPath2: PathPassage 'narrow path'
    "The path leads away to the southwest, around the curve of the tower. "
    -> hedgeBorderedPath
;

+ ironGateOutside: Door 'tall iron gate;; fence bar bars'
    "The iron gate is closed, and appears to be quite sturdy. Between the bars you can see a
    rather disheveled-looking garden. "
    lockability = lockableWithKey
    initiallyLocked = true
    otherSide = ironGateInside
    cantClimbMsg = 'The gate is somewhat too tall for you to consider
        climbing over it (even setting aside the likelihood of impaling yourself on the
        rather sharp-looking spikes along the top). '
    dobjFor(Unlock) {
        verify() {}
        check() {
            if (isLocked) "You don\'t seem to have the right key. ";
            else "It's not locked. ";
        }
    }
    dobjFor(Climb) {
        verify() {}
        check() {
            say (cantClimbMsg);
        }
    }
    dobjFor(LookThrough) {
        verify() {}
        action() {
            "Through the gate you can glimpse the northern side of a garden. ";
        }
    }
;

++gateSpikes: Component, Fixture 'sharp spikes'
    "The spikes look quite sharp. "
;

+ gardenView: Distant 'garden; untended disheveled disheveled-looking untidy'
    "The garden is on the other side of the gate. "
;

//-----------------------------------------------------------------------------
// northOfTower
//-----------------------------------------------------------------------------

northOfTower: ExteriorLocation, Room 'North of the Tower'
    "This secluded area is tucked away beneath the north side of the tower. On the
    wall of the tower, too high for you to reach from here, is the railing of a
    balcony. Planted in the ground directly beneath the balcony is a flowerbed. 
    The garden wall to the west is broken by the bars of an iron gate.
    The main part of the garden is to the southeast. "
    theName = 'the north side of the tower'
    dobjFor(Climb) {
        verify() { logicalRank(40); }
    }
    dobjFor(Examine) {
        verify () { nonObvious; }
    }
    
    southeast = untendedGarden
    east asExit(southeast)
    west = ironGateInside
;

+ironGateInside: Door 'iron gate;; bars'
    "The iron gate is closed, and appears to be quite sturdy. Between the bars you can see a path
    curving away to the northwest around the cylindrical tower. "
    lockability = lockableWithKey
    initiallyLocked = true
    otherSide = ironGateOutside
    dobjFor(Unlock) {
        verify() {}
        check() {
            if (isLocked) "You don\'t seem to have the right key. ";
            else "It's not locked. ";
        }
    }
    dobjFor(Climb) {
        verify() {}
        check() {
            say (ironGateOutside.cantClimbMsg);
        }
    }
;

//Note: If it becomes possible to hang a cloth from the spikes, they'll need to be a
//MultiLoc.

++gateSpikes2: Component, Fixture 'sharp spikes'
    "The spikes look fairly sharp. "
;

+ balconyFromBeneath: Distant 'balcony;; railing'
    "The balcony is ten or twelve feet overhead, and protrudes a couple of feet from
    the wall of the tower. A railing runs along it. "
;

+ flowerbed: Container, Fixture 'flowerbed; flower; dirt soil bed'
    "In the flowerbed is planted a festive display of marigolds, which are effusively in bloom. "
;

++ plantedMarigolds: Fixture 'blooming marigolds; festive pretty golden; flowers blossoms blooms plants; them'
    "The marigolds, as befitting their name, are golden. "
    someAlreadyPicked = nil
    plural = true
    smellDesc = "The marigolds are fragrant. "
    dobjFor(Take) {
        verify() {}
        check() {
            if (someAlreadyPicked) "You've already picked some marigolds. No need to decimate the
                flowerbed any further. ";
        }
        action() {
            someAlreadyPicked = true;
            bunchOfMarigolds.moveInto(me);
            "You carefully pluck a little bunch of marigolds. ";
        }
    }
;

bunchOfMarigolds: PDportable
    'picked bunch of marigolds[n]; festive pretty golden little; flowers blossoms blooms bunch; it them'
    "The bunch of marigolds is pretty and fragrant. "
    bulk = 15
    smellDesc = "The marigolds are fragrant. "
;

//-----------------------------------------------------------------------------
// untendedGarden
//-----------------------------------------------------------------------------

// Note: Given the rapidly increasing complexity of this environment, I'm wondering
// whether that arched doorway will need to be replaced with an opening-and-closing
// arch.

untendedGarden: ExteriorLocation, Room 'Untended Garden'
    "The bushes and flowerbeds in this walled garden are in a somewhat disheveled state.
    Dominating the landscaping is a stone angel (not weeping, fortunately) who stands
    gazing down into a small pond (the pond not being, as far as can be determined,
    named Amelia). The other notable feature of the garden is a circular picnic
    table<<if (bob.getOutermostRoom() == untendedGarden)>>,
    at which three men are seated<<end>>.
    
    <.p>A secluded area
    north of the cylindrical tower lies somewhat to the northwest of the main part of the garden.
    The outer wall of the garden to the south and east is unbroken.
    The curving wall of the tower to the west, however, is set off by an arched doorway. "
    northwest = northOfTower
    west = gardenArch
    south = 'The garden wall is solid, and too high to climb. '
    east asExit(south)
    north asExit(south)
;

+ Decoration 'bushes; disheveled; bush'
    "The bushes have not been well tended. "
    plural = true
;
+ Decoration 'flowerbeds; disheveled; flowers flower'
    "The flowerbeds have not been well tended. "
    plural = true
;

+ cardGame: Decoration 'game; (card)'
    "The card game is in progress on the table. "
;

+ gardenArch: OctagonExteriorPassage '+; (west)'
;

+ pond: Container, Fixture 'small pond; circular; pool water circle'
    "The pond is roughly circular, and about ten feet in diameter. The water shimmers
    faintly in the sunlight<<if (stoneAngel.curState == angelHarping)>>, and ripples
    dance in response to the gentle music of the angel's harp<<end>>. "
    notifyInsert(obj) {
        "If you put anything in the pond, retrieving it will be difficult (and it will
        get wet). Better not. ";
        exit;
    }
    dobjFor(SwimIn) asDobjFor(Enter)
    dobjFor(Enter) {
        verify() {}
        check() {
            "You didn't bring your bathing suit. ";
        }
    }
    dobjFor(Drink) {
        verify() {}
        check() {
            "Not even the blessed gaze of a stone angel is sufficient to keep an
            open-air pond clean enough to drink from. Anyway, you're not thirsty. ";
        }
    }
    iobjFor(FillWith) {
        verify() {}
        check() {
            "The water of the pond is not useful. ";
        }
    }
    dobjFor(PutIn) {
        verify() {}
        check() {
            "The water of the pond is not useful. ";
        }
    }
;

+ cardTable: Fixture, Surface 'circular table; (card) picnic sturdy'
    "The sturdy table is, by courtesy, a picnic table, since it's situated outdoors
    and equipped with non-detachable benches.
    <<if al.location == cardTableBenches>>Three men are sitting at the table, engaged
    in a game of cards. <<end>>"
    contentsListedInLook = nil
;

++ cardTableBenches: Component, Platform 'benches; (card) (table);; them'
    "The benches surround the table. "
;

//-----------------------------------------------------------------------------
// stoneAngel
//-----------------------------------------------------------------------------

harpMusic: Noise 'music; (harp) soft mellifluous; melody strumming'
    "From the harp emanates a soft mellifluous strumming. "
    listenDesc = "The sound of the angel's harp ripples lightly across the afternoon. "
;

stoneAngel: Actor 'stone angel; grimy gray; wings hands gaze; it him' @untendedGarden
    "The angel might be carved of stone or cast of concrete. In either event,
    his (her?) grimy gray color bespeaks years spent standing in this sad outdoor vigil. "
    cannotTakeMsg = 'The stone angel is quite obviously too large and heavy for you to
        consider carrying it (him?) around. '
    cannotPutPersonMsg = 'That\'s unlikely to be a useful thing to do. '
    cannotEatMsg = 'The stone would break your teeth. '
    cannotKissMsg = 'The angel is not a blarney stone. '
    attackResponseMsg = 'Attacking an angel? What would God think? '
    smellDesc = "You smell nothing unexpected. "
    shouldNotFeelMsg = "You feel nothing unexpected. "
    iobjFor(PutIn) {
        verify() {}
        check() {
            if (gDobj != angelHarp) "A stone angel cannot contain things. ";
        }
        action() {
            doInstead(GiveTo, angelHarp, stoneAngel);
        }
    }
;

+ angelInert: ActorState
    stateDesc = "His wings are furled, his hands open as if he were holding something that's not
    there, and his gaze falls sorrowfully upon the surface of the pond. "
    isInitState = true
;

++ DefaultAnyTopic
    "The angel fails to respond. "
;

++ GiveShowTopic @angelHarp
    topicResponse () {
        stoneAngel.setState (angelHarping);
        "The angel's arms reach out slowly and enfold the harp. Ever so gently, he
        begins strumming the strings, and while his facial expression seems not to
        have changed at all, somehow he radiates a sense of satisfaction now that
        was missing before.
        
        <.p>The music of the harp stirs ripples on the surface of the pond. After
        a few seconds, something rises to the surface from the depths of the pond --- 
        something transparent. It appears to be a crystal ball. ";
        crystalBallAch.awardPointsOnce();
        angelHarp.moveInto(stoneAngel);
        crystalBall.moveInto(pond);
        harpMusic.moveInto(untendedGarden);
    }
;

+ angelHarping: ActorState
    stateDesc = "He is cradling the harp gently in his arms, and strumming it lightly. "
;

++ DefaultCommandTopic
    "The angel continues to play the harp. "
;

++ DefaultAskTellTopic
    "The angel fails to respond. "
;

++ DefaultGiveShowTopic
    "The angel seems not to be interested in anything but the harp. "
;

//-----------------------------------------------------------------------------
// patio
//-----------------------------------------------------------------------------


patioPavement: Floor 'pavement; grimy; paving blacktop ground'
    "The pavement is rather grimy. Set in the pavement is a small metal grate. "
;

grate: Fixture, KeyedContainer 'small metal grate; hinged (round); hinge opening openings' @patio
    "The metal grate is set flush with the pavement, and has numerous round openings,
    each about the size of an old-fashioned silver dollar. It's hinged on one side.
    An unfortunate smell is emanating from the grate.<<if (greenOoze.isIn(grate))>> At a guess, the smell owes its
    presence to the quantity of virulently glistening green ooze pulsating
    sluggishly below the grate.<<end>> "
    openedAlready = nil
    isTransparent = true
    isLocked = true
    isOpen = nil
    canSmellIn = true
    allowPourIntoMe = true
    allowPourOntoMe = true
    canReachIn {
        if (isOpen) return true;
        if ((gAction == PourOnto) || (gAction == PourInto)) return true;
        return nil;
    }
    dobjFor(LookIn) {
        remap = (isOpen && deadOoze.location == self ? deadOoze : nil )
        preCond = [objVisible]
    }
    dobjFor(PryWith) asDobjFor(OpenWith)
    dobjFor(OpenWith) {
        verify() {
            if (isOpen) illogical ('You\'ve already opened the grate. ');
        }
        check() {
            if (gIobj && (gIobj != screwdriver)) "You can\'t open the grate that way. ";
        }
        action() {
            makeOpen(true);
            makeLocked(nil);
            if (openedAlready) {
                "This time it's easier. ";
            }
            else {
                openedAlready = true;
                "With a little effort, you're able to pry up the grate using the screwdriver. ";
            }
        }
    }
    dobjFor(UnscrewWith) asDobjFor(Unscrew)
    dobjFor(Unscrew) {
        verify() { illogical ( 'There don\'t appear to be any screw heads on the grate. ') ; }
    }
    dobjFor(Pry) {
        verify() {}
        check() {
            "You\'ll need to be specific about what you want to pry it with. ";
        }
    }
    dobjFor(Open) {
        check () {
            if (!openedAlready)
            "The grate doesn't appear to be locked or bolted shut. Probably it's just
                rusted. For whatever reason, you can't get it open. ";
        }
    }
//    lookInDesc {
//        "Through the openings in the grate you can see a quantity of glistening green ooze. ";
//    }
//    dobjFor(Search) {
//        precond = []
//        verify() {}
//        check() {}
//        action() {
//            lookInDesc;
//        }
//    }
    dobjFor(SmellSomething) {
        action() {
            "Something down below the grate smells pretty awful. Most likely that putrid mass of glistening
            green ooze. ";
        }
    }
;

+ greenOoze: Fixture
    'some glistening green ooze; pulsating sluggish disgusting nauseating virulent putrid rank; filth slime muck'
    "The ooze glistens virulently. "
    canPourIntoMe = true
    allowPourIntoMe = true
    allowPourOntoMe = true
    searchListed = true
    isDead = nil
    dobjFor(LookIn) {
        check() {
            if (grate.isOpen)
                "To do that, you'd have to touch it. Afterward, you'd need a truckload of Handi Wipes to
                get your fingers clean. ";
            else
                "First you'll need to get the grate open. ";
        }
    }
    dobjFor(Feel) asDobjFor(Take)
    dobjFor(TakeFrom) asDobjFor(Take)
    dobjFor(Take) {
        preCond = [objVisible]
        verify() {}
        check () {
            "The very thought of touching the virulent muck makes you want to
                wash your hands. If you actually got a drop of it on you, you'd be washing
                your hands for days. <<if (!grate.isOpen)>>Besides, it's down there
                underneath the grate. ";
        }
    }
    dobjFor(SmellSomething) {
        action() {
            "The ooze smells remarkably rank. ";
        }
    }
;

patio: ExteriorLocation, Room 'Patio'
    "A trio of wrought-iron chairs here flanks a similar table, the lot shielded from the sun (inadequately)
    by a wrought-iron parasol. Over the low hedge to the
    north you can see the parking lot. Stufftown's Main Entrance is off to the east,
    and to the south is a glass door beneath a sign that reads <q>THE GROANING SANDWICH BOARD.</q>
    Set in the pavement here is a small grate. "
    
    regions = [betsyGoneRegion, joeFollowingRegion]
    
    floorObj = patioPavement
    
    east = mainEntrance
    south = sandwichShopDoorOutside
;

+ Distant 'main entrance'
    "The main entrance is a few steps east of the patio. "
;

+ Decoration 'low hedge; untrimmed; bush bushes'
    "The low hedge hasn't been trimmed lately. "
;

+ lotFromPatio: Distant 'parking lot'
    "The parking lot looks pretty much the way it did a few minutes ago. "
;

+ sandwichShopDoorOutside: ShopDoorOutside '+ ; groaning sandwich board snack'
    "The door is on the south side of the patio. "
    otherSide = sandwichShopDoorInside
;

+ sandwichSign: ShopSign 'Groaning Sandwich Board +; fly-specked (brown) (green) groaning sandwich board; bread pickles'
    "In letters painted to look like bread (a fly-specked brown) and pickles (bilious green), the sign reads
    <q>THE GROANING SANDWICH BOARD.</q> "
;

+ patioChairs: Decoration
    vocab = 'wrought-iron chairs; uncomfortable black iron metal; seat seats curlicue filigree'
    desc = "The black wrought-iron chairs are much alike --- masses of metal curlicues and filigree. They look
        quite uncomfortable. "
    plural = true
    decorationActions = [Examine, Take, SitIn, SitOn]
    dobjFor(SitIn) asDobjFor(SitOn)
    dobjFor(SitOn) {
        verify() {}
        action() {
            "You plop down in the nearest chair for a moment to take a breather, but it\'s not
            very comfortable, and anyway, miles to go before you sleep and all that. You stand
            up again. ";
        }
    }
    dobjFor(Take) {
        verify() {}
        check() {
            "You heft the nearest chair experimentally. Not surprisingly, it proves both
                heavy and unwieldy. Having no particular need to burden yourself with such an object,
                you put it back down. ";
        }
    }
;

+ ironTable: Surface, Fixture
    'wrought-iron table; (black) small round metal wrought iron'
    "The black wrought-iron table is small and round. Jutting up from the center
    is a pole, atop which is mounted a parasol. "
    dobjFor(Take) {
        verify() {}
        check() {
            "With a bit of effort you're able to heft the near edge of the table,
                but that only causes the parasol above it to sway alarmingly. No, it\'s just
                too bulky and awkward to be moved. ";
        }
    }
;
++ parasol: Component
    'wrought-iron parasol; (black); pole umbrella shade'
    "A pole mounted in the center of the table is topped with a black metal parasol. Though
    metal, the parasol is patterned to look (unconvincingly) like wicker. "
;
    
+ oozeOdor: Odor 'rank odor; putrid unfortunate; smell scent aroma'
    "Something smells pretty bad, no doubt about that. "
    smellDesc = "Something nearby smells really bad. The odor seems to be strongest when
        you're standing directly above the small metal grate. "
;

     
//-----------------------------------------------------------------------------
// employeeParking
//-----------------------------------------------------------------------------

wreckedLamborghini: Heavy 'wrecked Lamborghini; damaged bright red sports; car auto wreck'
    "The Lamborghini <<if (readyToTow)>>is a mess. The front end is
    bent and crinkled --- also dripping wet<<else>>is nose-down in the creek at the west edge of
    the parking lot. It looks pretty badly damaged<<end>>. "
    specialDesc () {
        if (readyToTow)
            "The Lamborghini has been winched up out of the creek, and is now chained
            close behind the tow truck. ";
        else
            "The red Lamborghini is buried up to its hood ornament in the
            creek<<if (towTruck.getOutermostRoom() == employeeParking)>>, and a chain
            extends from its rear axle up the slope to a winch on the back of a tow
            truck<<end>>. ";
    }
    dobjFor(Drive) {
        verify() {}
        check() { "It's a little late for that, don't you think? "; }
    }
    readyToTow = nil
    dobjFor(Enter) {
        verify() {}
        check() {
            if (!readyToTow) "It's a good bet the door is jammed. Anyway, you'd get wet and muddy trying
            to do that. ";
            else "That would be pointless. Also, you'd be drawing attention to yourself. You're done
                with the Lamborghini --- just let them tow it away. ";
        }
    }
    dobjFor(Pull) {
        verify() {}
        check() {
            "You're not a tow truck. ";
        }
    }
;

Doer 'pull redWagon east; pull redWagon up'
    execAction (c) {
        "The wagon can only roll on a level surface. ";
        abort;
    }
    where = employeeParking
;

employeeParking: ExteriorLocation, Room 'Employee Parking Lot'
    "Like the main parking lot, the employee lot is nearly empty --- doubtless, at this hour on this
    particular
    Saturday afternoon, a tribute to the popularity of lacrosse. To the west, the land
    slopes off steeply toward a creek, and indeed the surface of the parking lot tilts
    a bit in that direction; it's not level.
    
    <.p>A concrete loading dock is built against
    the wall of Stufftown to the east, up a short flight of steps, and a brick-paved path leads
    off to the south, around the corner of the building. The main customer parking lot is
    off to the northeast. "
    
    regions = [joeFollowingRegion]
    
    north asExit(northeast)
    northeast = parkingLot
    east: TravelConnector {
        destination = loadingDock
        travelBarriers = [wagonBarrier]
    }
    up asExit(east)
    south = brickPath2
    west = "There's nothing over there but the creek<<if (wreckedLamborghini.isIn(employeeParking))>> and
        what's left of the poor Lamborghini<<end>>. "
;

+ Decoration 'steps;;; them'
    "The steps lead up to the loading dock. "
;

+ brickPath2: PathPassage
    'brick-paved path; brick paved'
    "The brick path leads off to the south, where it turns left and disappears around the corner
    of the building. "
    destination = footOfPole
    getFacets = [brickPath]
    travelDesc = "You make your way southward and turn to the east as you round the corner of the building. "
;


+ loadingDockExterior: Enterable, Fixture 'loading dock; solid battered concrete; block'
    "It looks to be in every respect an ordinary loading dock, though possibly
    more battered by careless truck drivers than some. It's positioned against the
    west side of the building, directly to the east from where you're standing. "
    destination = loadingDock
    solidMsg = 'It\'s just a solid block of concrete. '
    dobjFor(LookUnder) {
        verify() { illogical ( solidMsg );
        }
    }
    dobjFor(LookBehind) asDobjFor (LookUnder)
    dobjFor(Board) asDobjFor(Climb)
    dobjFor(Climb) {
        verify() {}
        action() {
            doInstead(Go, eastDir);
        }
    }
;

+ lamborghini: ExteriorLocation, Enterable 'flashy sports car; sleek expensive bright red; lamborghini model'
    "Though you're not too familiar with sports cars, you happen to know that this one
    is a Lamborghini<<tLamborghini.makeFamiliar()>> --- a flashy and fearfully expensive model. 
    Its license plate reads EUGRAB1. "
    specialDesc = "<<if (rollingDaemonID)>>The Lamborghini is rolling faster and
        faster down the parking lot toward the creek<<else>>The most striking vehicle
        in the employee parking lot is a sleek bright
        red sports car<<end>>. "
    dobjFor(Push) {
        verify() {}
        check() {
            "You give it a shove, but it's not moving. Evidently the handbrake has been set. ";
        }
    }
    dobjFor(Open) {
        verify() {}
        check() {
            "No need to open it; you can just get in. ";
        }
    }
    dobjFor(Unlock) {
        verify() {}
        check() {
            "It's not locked. If you want to get in, just go right ahead. ";
        }
    }
    dobjFor(Drive) {
        verify() {}
        check() { "You'd have to be in the car to do that. "; }
    }
    dobjFor(LookUnder) {
        verify() {}
        check() {
            "Bits of stray gravel, a couple of oil spots --- no, there's nothing interesting
            under the car. ";
        }
    }
    destination = lamborghiniInterior
    cannotTakeMsg = 'You\'re not King Kong. '
    rollingCount = 0
    rollingDaemon {
        rollingCount++;
        if (rollingCount < 2) return;
        if (gPlayerChar.getOutermostRoom == lamborghiniInterior) {
            "Before you can get out of the car, it rumbles and bounces down the slope and
            takes a nosedive into the creek. You bang your head on the steering wheel and
            wake three days later in the hospital. The bandages on your head are bad enough,
            but to make matters worse, you're handcuffed to the bedframe. Evidently you've
            been arrested for malicious mischief --- or possibly for grand theft auto. ";
            finishGameMsg('You have failed in your quest.', [finishOptionUndo]);
        }
        else {
            "With a muffled crash, the Lamborghini takes a nosedive into the creek. ";
            lamborghini.rollingDaemonID.removeEvent();
            lamborghini.rollingDaemonID = nil;
            wreckedLamborghini.moveInto(employeeParking);
            // Because we're going to need to talk about it later:
            self.familiar = nil;
            self.seen = nil;
            wreckedLamborghini.familiar = true;
            self.moveInto(nil);
        }
    }
    rollingDaemonID = nil
;

++ licensePlate: Component, Decoration 'license plate; personalized'
    "The personalized license plate reade EUGRAB1. "
;

++ carDoor: Component, Fixture 'car door'
    "The door is part of the sports car. "
    notRelevantMsg = 'No need to fiddle about with the car door; you can enter
            the car directly. '
    dobjFor(Open) {
        verify() { illogical ( notRelevantMsg ); }
    }
    dobjFor(Unlock) {
        verify { illogical ( notRelevantMsg ); }
    }
;

// Note: At some point we might want to give a hint as to the character or number of employees
// on the premises by being a lot more specific about their cars.

+employeeCars: Decoration, Heavy 'other cars; employees\'; autos vehicles; them'
    "The cars are pretty much the random assortment you\'d expect. "
;

+ creek: Distant 'creek; ; stream river water'
    "The creek is off to the west. "
;

// --------------------------------------------------------------------------
// in the Lamborghini
// --------------------------------------------------------------------------

Doer 'get out'
    execAction(c) {
        doInstead(Go, outDir);
    }
    where = lamborghiniInterior
;

lamborghiniInterior: Room 'Inside the Lamborghini' 'car; auto vehicle'
    "Aside from the rich leather smell of the upholstery and the sparkling chrome
    in which the dashboard instruments are mounted, the most obvious feature of
    the sports car's interior is the large brake lever positioned between the bucket
    seats. "
    smellDesc = 'It has that wonderful new-car smell. '
    dobjFor(SmellSomething) {
        verify() {}
        action() {
            "<<smellDesc>> ";
        }
    }
    dobjFor(Drive) {
        verify() {}
        check() {
            "You don't have the ignition key. ";
        }
    }
    dobjFor(Enter) {
        verify() { illogicalAlready ( 'You\'re already inside the car. ' ); }
    }
    out = employeeParking
    vocabWords = 'inside (the) Lamborghini; sports; car'
;

+ Odor 'new-car smell'
    "Ah, that lovely new-car smell. "
    smellDesc = "You pause for a moment to breathe in the scent of a new car with
        leather upholstery. "
;

+ Fixture 'car windows; window windshield'
    "The windows of the car are about what you'd expect. "
    dobjFor(LookThrough) {
        verify() {}
        action() {
            doInstead (Examine, outsideTheCar);
        }
    }
;

+ outsideTheCar: Distant 'parking lot; employee'
    "Through the windows of the car you can see the employee parking lot. Nothing interesting
    going on out there, and that's just as well. "
;

+ lamborDecorations: Decoration 'dashboard; bucket steering chrome; seat seats leather wheel instruments upholstery'
    "The car's fancy fittings are not important. That brake lever, though.... "
;

+ brakeLever: Fixture 'brake lever; large'
    "The brake lever is positioned between the bucket seats, within easy reach of the
    driver. "
    dobjFor(Lift) asDobjFor(Pull)
    dobjFor(Push) asDobjFor(Pull)
    dobjFor(Pull) {
        verify() {}
        check() {
            if (!released)
                "The lever is currently pulled up, locking the brakes. You could probably
                release it --- but if you do that, you'll need to get out of the car quickly,
                because the car will surely roll down the parking lot and into the creek. ";
            else
                "You grope for the lever and miss. Oh, no! ";
        }
    }
    released = nil
    dobjFor(Move) asDobjFor(Release)
    dobjFor(Release) {
        verify() {}
        action() {
            if (lamborghini.rollingDaemonID == nil) {
                released = true;
                lamborghini.rollingDaemonID = new Daemon(lamborghini, &rollingDaemon, 1);
                "The Lamborghini starts rolling, slowly at first and then more rapidly, down
                the west side of the parking lot toward the creek. If you don't get out of the
                car <i>right now,</i> you're going to be in serious danger in about three seconds. ";
            }
            else "You fumble, panic-stricken, at the brake lever. ";
        }
    }
;
            
//-----------------------------------------------------------------------------
// loadingDock
//-----------------------------------------------------------------------------

Doer 'pull redWagon west; pull redWagon down'
    execAction (c) {
        "The wagon can only roll on a level surface. ";
        abort;
    }
    where = loadingDock
;

loadingDock: ExteriorLocation, Room 'Loading Dock'
    "From this concrete platform you can look out and down across the employee parking lot to
    the west (not that there's much to see). A very large, corrugated steel door on the east side
    of the dock evidently provides utilitarian access to the interior of Stufftown. Mounted next
    to the door is a metal box equipped with a large red button. "
    
    west: TravelConnector {
        destination = employeeParking
        travelBarriers = [wagonBarrier]
    }
    down asExit(west)
    east = rollupDoorExterior
    in asExit(east)
;

+ viewOfLot: Distant 'parking lot; employee'
    "The employee parking lot slopes away to the west. "
;

+ rollupDoorExterior: Door 'corrugated steel door; metal large'
    "The door is made of corrugated metal. "
    otherSide = rollupDoorInterior
    lockability = indirectLockable
    isOpen = nil
    dobjFor(Close) {
        verify() {
            if (!isOpen) illogicalNow ('The metal door is already closed. ');
        }
        check() {
            "The cylinder containing the rolled-up door is too high for you to reach,
            but there may be another way to close it. ";
        }
    }
    dobjFor(Attack) {
        verify() {}
        check() {
            "Other than a rather satisfying booming banging noise, your assault has no result. ";
        }
    }
;

+ metalBox: Fixture 'metal box'
    "The box is mounted on the wall next to the door. Set squarely in the face of the box is
    a large red button. "
;

++ redButton: Component, Fixture 'large red button'
    "The red button is situated on the front of the metal box. "
    dobjFor(Push) {
        preCond = [touchObj]
        verify() {}
        check() {
            if (!junctionBox.isPowered) "<i>Click.</i> You press the button, but nothing happens. ";
        }
        action() {
            if (!rollupDoorExterior.isOpen) {
                // rollupDoorExterior.makeLocked(nil);
                rollupDoorExterior.makeOpen(true);
                "With a loud grumbling, grinding noise, the metal door rolls up, revealing
                a large interior room. ";
            }
            else {
                rollupDoorExterior.makeOpen(nil);
                //rollupDoorExterior.makeLocked(true);
                "With a loud clashing, crashing noise, the metal door rolls down. ";
            }
        }
    }
;

