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


DefineTAction(MoveLeft);
VerbRule(MoveLeft)
    ('move' | 'push') singleDobj ('to' ('the' | ) | ) ('left' | 'leftward')
    : VerbProduction
    action = MoveLeft
    verbPhrase = 'move/moving (what) left'
    missingQ = 'what do you want to move left'
;
DefineTAction(MoveRight);
VerbRule(MoveRight)
    ('move' | 'push') singleDobj ('to' ('the' | ) | ) ('right' | 'rightward')
    : VerbProduction
    action = MoveRight
    verbPhrase = 'move/moving (what) right'
    missingQ = 'what do you want to move right'
;
modify Thing
    dobjFor(MoveRight) asDobjFor(MoveLeft)
    dobjFor(MoveLeft) {
        verify() {
            illogical ('That action makes no sense in this context. ');
        }
    }
;
    
class DioramaComponent: Component
    dobjFor(Feel) {
        check() {
            "{The dobj} is beneath the clear plastic top of the diorama. You can't
            touch it. ";
        }
    }
    cannotTakeMsg = '{The dobj} is beneath the clear plastic top of the diorama.
        You can\'t touch it. '
;

// Each track segment stores its next segment, which is set by the lever.
class TrackSegment: DioramaComponent
    nextSegment = 1
    switchNextSegment (n) {
        nextSegment = n;
    }
;

diorama: Fixture
    'diorama; large stuff world; model table big squashed bubble'
    @arcadeCenter
    "The diorama is a large table, at least ten feet on each side, whose top is
    covered with a low-slung transparent plastic dome. The dome looks rather like a
    great big bubble that has been squashed almost flat. Beneath the dome, spread across the
    table, is what appears to be a detailed scale
    model of a theme park. A silver ribbon of railroad track wends its
    way around the scale model, among brightly colored little plastic things, and there's a
    little bullet-shaped car on the track.
    At the point where the track soars over a miniature riverbed, the four struts holding
    it up are not a functional metallic gray but (starting at the left end) orange, green, red, and
    violet.
    
    <.p>But that's not all. Scattered here and there across the diorama are a
    gold pyramid, a tiny silver
    knight in armor riding a horse, a vertically mounted circle that might be a
    Ferris wheel, a little brown
    shoe, a blue patch with little white flecks scattered across it, and what might,
    if you use your imagination, be a tightly packed bunch of people wearing ritual robes.
    
    <.p>Not far
    from the center of the scale model is what looks like a small rectangular access
    hatch. 
    <<if (fakeGoldCoin.isIn(diorama))>><.p>Lying near the access hatch is a gold coin. <<end>>
    <.p>Mounted at the near side of the diorama, within easy reach, is a little control
    panel consisting of a lever and a button. "
    dobjFor(LookUnder) {
        verify() {}
        check() {}
        action() {
            "You take a peek under the diorama. There\'s probably enough clearance that
            you could crawl under there, if you had a reason to. ";
        }
    }
    dobjFor(CrawlUnder) {
        verify() {}
        // Note: We will want to reject this action when Betsy is following.
        action() {
            "Moving with care, you get down on your knees and crawl under the diorama. ";
            if (betsy.curState == betsyClinging) betsy.setState(betsyByDiorama);
            dioramaUnderside.travelVia(gActor);
        }
    }
;

+ dioramaBubble: Component, Fixture 'clear plastic top; almost flat squashed big; cover bubble'
    "The clear plastic top covers the active part of the diorama. "
    dobjFor(Doff) asDobjFor(Remove)
    dobjFor(Take) asDobjFor(Remove)
    dobjFor(Remove) {
        verify() {}
        check() {
            "The plastic cover of the diorama can\'t be removed. ";
        }
    }
;

class DioramaDecoration: DioramaComponent, Decoration
    desc = "{The subj dobj} {is} in the diorama. "
    decorationActions = [Take, Examine]
    dobjFor (Take) {
        verify() { illogical ( 'You can\'t reach anything through
            the clear plastic cover of the diorama. ' ); }
    }
;

+ DioramaDecoration 'theme park';
+ DioramaDecoration 'gold pyramid';
+ DioramaDecoration 'silver knight;; horse armor';
+ DioramaDecoration 'vertically mounted circle';
+ DioramaDecoration 'little brown shoe';
+ DioramaDecoration 'blue patch';
+ DioramaDecoration 'white flecks;;; them';
+ DioramaDecoration 'people wearing robes;;; them';

+ DioramaDecoration 'struts; ; strut'
    "The struts are colored orange, green, red, and violet. "
    plural = true
;

+ DioramaComponent 'access hatch'
    "The hatch interrupts the otherwise convincing environment of miniature
    figures. "
    dobjFor(Open) {
        verify() {}
        check() {
            "Unfortunately, you can't get at the hatch from here. It's underneath
            the clear plastic cover of the diorama. ";
        }
    }
;

+ fakeGoldCoin: DioramaComponent 'gold coin in the (diorama)'
    "The coin is probably not real gold, it's just
    gold-colored. Its face
    features an elaborate Gothic logo of an intertwined &lsquo;F' and &lsquo;G'. "
    vocabLikelihood = 10
;

//------------------------------------------------------------------------------
// The track and its segments:
//------------------------------------------------------------------------------

+ dTrack: DioramaComponent 'silver railroad track; (train) miniature; junction junctions'
    "The silver track within the diorama is designed rather like a figure 8 within an
    elongated oval. It has six distinct track segments --- the near and far segments
    that run parallel to the front of the diorama, two curving segments, one each at
    the left and right ends, that join the near segment to the far segment, and two segments
    forming the center of the figure 8, which cross one another in the center of the track
    layout.
    <.p>\t\t<IMG SRC=\"track.PNG\">
    
    <.p>At the near side of the oval is a miniature
    platform<<if (!dCar.isMoving)>>, next to which a tiny car is sitting on the track.
    The car is facing to the
    <<dCar.stationOrientation>><<end>>. At a guess, the platform is
    intended to represent a station from which tiny
    passengers could enter or leave the car.
    
    <.p>Along the lengths of track that cross in the center of the layout are rows of tiny
    red signs. Words seem to be written on them, but the signs are too small for you to
    read what they say. "

    // The only segments whose nextSegment can change are 3, 4, 7, and 8:
    switchJunctions (dir) {
        if (dir == 'left') {
            dSeg3.nextSegment = 5;
            dSeg4.nextSegment = 12;
            dSeg7.nextSegment = 1;
            dSeg8.nextSegment = 11;
        }
        else {
            dSeg3.nextSegment = 9;
            dSeg4.nextSegment = 2;
            dSeg7.nextSegment = 10;
            dSeg8.nextSegment = 6;
        }
    }
;

// The defaults for the nextSegment assume the lever starts out at the left.
++ dSeg1: TrackSegment
    nextSegment = 3
;
++ dSeg2: TrackSegment
    nextSegment = 8
;
++ dSeg3: TrackSegment
    nextSegment = 5
;
++ dSeg4: TrackSegment
    nextSegment = 12
;
++ dSeg5: TrackSegment
    nextSegment = 7
;
++ dSeg6: TrackSegment
    nextSegment = 4
;
++ dSeg7: TrackSegment
    nextSegment = 1
;
++ dSeg8: TrackSegment
    nextSegment = 11
;
++ dSeg9: TrackSegment
    nextSegment = 8
;
++ dSeg10: TrackSegment
    nextSegment = 4
;
++ dSeg11: TrackSegment
    nextSegment = 3
;
++ dSeg12: TrackSegment
    nextSegment = 7
;

//-------------------------------------------------------------------------------

// You need to be able to try to READ SIGNS.

+ dSigns: DioramaComponent 'rows of tiny red signs;;; them'
    "The signs are positioned along the lengths of track that cross one another in the center
    of the layout. Words seem to be written on the signs, but they're too small to read. "
    readDesc = "Whatever is written on the little red signs, the letters are too small
        for you to read them. "
;

+ dStation: DioramaComponent 'station; (tiny); platform'
    "The tiny station platform, a raised surface no larger in area than a nickel, but rectangular,
    is situated at the center of the near-side track segment. "
;

+ dCar: DioramaComponent 'tiny car; train streamlined bulbous; capsule'
    desc {
        "Judging by the scale of the diorama, the tiny car looks large enough for only one
        tiny passenger. It has a streamlined shape rather like a bulbous medicine capsule. ";
        if (!isMoving)
            "It's currently at the station, pointing to the <<stationOrientation>>. ";
        else {
            "It's currently ";
            switch (onTrackAt) {
            case 1:
                "heading away from the station, moving to the left. ";
                break;
            case 2:
                "heading away from the station, moving to the right. ";
                break;
            case 3:
                "heading up the left side of the oval, moving away from you. ";
                break;
            case 4:
                "heading down the left side of the oval, moving toward you. ";
                break;
            case 5:
                "moving along the far side of the oval, moving from left to right. ";
                break;
            case 6:
                "moving along the far side of the oval, moving from right to left. ";
                break;
            case 7:
                "heading toward you down the right side of the oval. ";
                break;
            case 8:
                "heading away from you up the right side of the oval. ";
                break;
            case 9:
                "gliding down the diagonal track from the upper left toward the lower right. ";
                break;
            case 10:
                "gliding up the diagonal track from the lower right toward the upper left. ";
                break;
            case 11:
                "traveling down the diagonal track from the upper right to the lower left. ";
                break;
            case 12:
                "traveling up the diagonal track from the lower left to the upper right. ";
                break;
            default:
                "Programming error --- this should never print. ";
            }
        }
    }
    onTrackAt = 1
    nextSegment = 3
    stationOrientation = 'left'
    isMoving = nil
    daemonID = nil
    
    runningDaemon {
        // the onTrackAt property describes where it was LAST turn. In the daemon
        // we will move it, change its onTrackAt, and describe where it is NOW.
        switch (onTrackAt) {
        case 1:
            onTrackAt = dSeg1.nextSegment;
            "The car leaves the station and heads up the curve at the left side of the oval toward
            the Y-shaped junction near the upper left corner. ";
            break;
        case 2:
            onTrackAt = dSeg2.nextSegment;
            "The car leaves the station and heads up the curve at the right side of the oval toward
            the Y-shaped junction near the upper right corner. ";
            break;
        case 3:
            onTrackAt = dSeg3.nextSegment;
            if (onTrackAt == 5)
            "The car bears to the left at the Y-shaped junction at the upper left
            and glides along the track
            at the far side of the oval, moving from left to right. ";
            else
                "The car swings right at the Y-shaped junction at the upper left corner of
                the layout and heads down the diagonal track toward the lower right. ";
            break;
        case 4:
            onTrackAt = dSeg4.nextSegment;
            if (onTrackAt == 2) {
                isMoving = nil;
                if (daemonID != nil) {
                    daemonID.removeEvent();
                    daemonID = nil;
                }
                "The car glides up to the station platform, slowing, and comes to a halt,
                    facing right. ";
                stationOrientation = 'right';
            }
            // else we've veered onto 12:
            else
                "The car swings left at the Y-shaped junction at the lower left corner
                of the layout and heads up the diagonal track toward the upper right. ";
            break;
        case 5:
            onTrackAt = dSeg5.nextSegment;
            "The car curves toward you along the right end of the oval, approaching
            the Y-shaped junction near the lower right corner. ";
            break;
        case 6:
            onTrackAt = dSeg6.nextSegment;
            "The car curves toward you along the left end of the oval, approaching
            the Y-shaped junction near the lower left corner. ";
            break;
        case 7:
            onTrackAt = dSeg7.nextSegment;
            if (onTrackAt == 1) {
                "The car glides up to the station platform, slowing, and comes to a halt,
                facing left. ";
                isMoving = nil;
                if (daemonID != nil) {
                    daemonID.removeEvent();
                    daemonID = nil;
                }
            }
            else
                "The car angles right at the Y-shaped junction at the lower right
                and glides up the diagonal toward the upper left. ";
            break;
        case 8:
            onTrackAt = dSeg8.nextSegment;
            if (onTrackAt == 11) 
                "The car swings left at the Y-shaped junction at the upper right corner
                of the layout and heads down the diagonal track toward the lower left. ";
            else
                "The car glides along the track at the far side of the oval, moving from
                right to left. ";
            break;
        case 9:
            onTrackAt = dSeg9.nextSegment;
            "The car reaches the lower right corner of the layout and
            moves up the curve at the right side of the oval, heading toward
            the Y-shaped junction near the upper right corner. ";
            break;
        case 10:
            onTrackAt = dSeg10.nextSegment;
            "The car reaches the upper left corner of the layout and 
            curves toward you along the left end of the oval, approaching
            the Y-shaped junction near the lower left corner. ";
            break;
        case 11:
            onTrackAt = dSeg11.nextSegment;
            "The car reaches the lower left corner of the track layout and
            moves up the curve at the left side of the oval, heading toward
            the Y-shaped junction near the upper left corner. ";
            break;
        case 12:
            onTrackAt = dSeg12.nextSegment;
            "The car reaches the upper right corner and then curves back toward you
            along the right end of the oval, approaching
            the Y-shaped junction near the lower right corner. ";
            break;
        default:
            "Programming error --- this should never print. ";
        }
    }
;

+ dPanel: Component 'control panel; little'
    "The control panel is mounted within easy reach at the near side of the diorama.
    It has only two controls --- a lever, which is mounted in a horizontal
    slot so that it can be pushed to the left or right, and a button. Currently the lever
    is to the <<dLever.direction>>. "
;

++ dLever: Component 'lever; little'
    "The little lever is mounted on the control panel. Currently it's angled to the
    <<direction>>. "
    // It starts out the game angled to the left:
    direction = 'left'
    dobjFor(MoveLeft) {
        verify() {}
        check() {
            if (direction == 'left') "The lever is already angled to the left. ";
        }
        action() {
            doInstead (Push, dLever);
        }
    }
    dobjFor(MoveRight) {
        verify() {}
        check() {
            if (direction == 'right') "The lever is already angled to the right. ";
        }
        action() {
            doInstead (Push, dLever);
        }
    }
    dobjFor(Move) asDobjFor(Push)
    dobjFor(Push) {
        verify() {}
        check() {}
        action() {
            if (direction == 'left') direction = 'right';
            else direction = 'left';
            dTrack.switchJunctions(direction);
            "You push the little lever to the <<direction>>. ";
        }
    }
    dobjFor(Pull) {
        verify() { illogical ('If you pull the lever, it will probably break off. You
            could push it, though. ');
        }
    }
;

++ dButton: Button 'button'
    "The button is mounted on the control panel. "
    dobjFor(Push) {
        action() {
            if (!junctionBox.isPowered) {
                "You push the button, but nothing happens. ";
                return;
            }
            if (dCar.isMoving) {
                "Pushing the button again seems to have no immediate effect. ";
                return;
            }
            // And now we'll start the car moving:
            if (dCar.daemonID == nil) {
                "As you push the button, the little bullet-shaped car shudders into
                motion. ";
//                , leaving the station platform and
//                heading <<if (dCar.onTrackAt == 1)>>left<<else>>right<<end>>. ";
                dCar.daemonID = new SenseDaemon (dCar, &runningDaemon, 1, &canSee);
                dCar.isMoving = true;
            }
        }
    }
;
