/*
 * Copyright (c) 2021 Ross Cunniff
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
AdjecClass red();
AdjecClass green();
AdjecClass blue();
AdjecClass clear();
AdjecClass glass();
AdjecClass silver();

NounClass message();            // Predeclare the noun, we use it several times

MpuThing redMessage(road2) {        // It's red so there can be others elsewhere
    adjec = red
    noun = message
    WEIGH = CAPAC
    ldesc = proc() {"There is a message scratched in the dirt.\n";}
    sdesc = proc() {"a message in the dirt";}
    action = proc() {
        if ((Verb == V_read) || (Verb == examine)) {
            "'in' is a preposition.  'enter' is a verb.\n";
            ExitPhase(PHX_ACTOR);
        }
    }
}

MpuThing keys(town4) {
    WEIGH = 2
    ldesc = proc() {"There's a set of keys here.\n";}
    sdesc = proc() {"a set of keys";}
}

AdjecClass tool();
NounClass box();

class ToolBox(MpuThing) {
    public var HOLDS, pOpens, pLocks, pLocked, pLight, pOpened, pSeen;
}
ToolBox toolBox(farm5) {
    adjec = tool
    noun = box
    WEIGH = CAPAC
    HOLDS = 50
    pOpens = true
    pLocks = true
    pLocked = true
    pLight = true
    ldesc = proc() {
        if ($ME.loc == toolBox) {
            "You are in a huge wooden structure, towering up at least 80 feet ",
            "above your head, with wooden walls formed of immense 10-foot by ",
            "50-foot boards.  Everything here, even the grains of dust which ",
            "cover the wooden floor, seems immense.  ";
            if (toolBox.pOpened)
                "Above your head, the top of the structure is open, ",
                "and sunlight streams in.\n";
            else
                "The structure is closed at the top, but enough light ",
                "comes in from between the boards to enable you to see.\n";
        }
        else {
            "Against the house is a heavy ";
            if (toolBox.pOpened)
                "tool box with the lid open.\n";
            else if (toolBox.pLocked)
                "tool box with a rusty lock, painted with an insignia ",
                "composed of blue and green squares, joined at their ",
                "corners.\n";
            else
                "tool box, the lid of which is ajar.\n";
        }
    }
    sdesc = proc() {
        if ($ME.loc == toolBox)
            return Sayer("Inside Huge Box", oadl::nargs());
        else
            "a tool box";
    }
    action = proc() {
        if (Phase == PHASE_ROOM) {
            // This is the room action
            if ((Verb == drop) || (Verb == V_throw)) {
                // We don't want to keep track of lots of small things
                "You just lost ";
                Dobj.sdesc();
                " in a crack between the wooden floorboards!\n";
                Dobj.move($ALL);
            }
        }
        else if (Verb == lock) {
            if (toolBox.pOpened) {
                "You must close it first.\n";
                ExitPhase(PHX_ACTOR);
            }
            else if (toolBox.pLocked) {
                "It's already locked!\n";
                ExitPhase(PHX_ACTOR);
            }
            else if (keys.loc == $ME) {
                "The tool box seals with a CLICK!\n";
                toolBox.pLocked = true;
                ExitPhase(PHX_ACTOR);
            }
        }
        else if (Verb == unlock) {
            if (!toolBox.pLocked) {
                "It's already unlocked!\n";
                ExitPhase(PHX_ACTOR);
            }
            else if (keys.loc == $ME) {
                "One of the keys fits!  The box is unlocked.\n";
                toolBox.pLocked = false;
                ExitPhase(PHX_ACTOR);
            }
        }
        else if (Verb == examine) {
            if (toolBox.pOpened)
                "The tool box is open.\n";
            else if (toolBox.pLocked)
                "The tool box is locked.\n";
            else
                "The tool box is ajar.\n";
            ExitPhase(PHX_ACTOR);
        }
    }
}
Synonym toolbox(toolBox);

NounClass spoon();

MpuThing silverSpoon(farm6) {
    adjec = silver
    noun = spoon
    POINT = 10
    WEIGH = 1
    ldesc = proc() {"There is a beautiful silver spoon here.\n";}
    sdesc = proc() {"a silver spoon";}
}

class WetSuit(MpuThing) { public var WORN; }
WetSuit wetsuit(cel15) {
    ldesc = proc() {"There is a wetsuit here.\n";}
    sdesc = proc() {
        "a wetsuit";
        if (wetsuit.WORN) " (being worn)";
    }
    WEIGH = 50
    action = proc() {
        if (Verb == wear) {
            if (wetsuit.loc != $ME) {
                "You don't have the wetsuit!\n";
                ExitPhase(PHX_ACTOR);
            }
            else if (wetsuit.WORN) {
                "You are already wearing it!\n";
                ExitPhase(PHX_ACTOR);
            }
            else {
                wetsuit.WORN = true;
                "OK, you're wearing the wetsuit.\n";
                ExitPhase(PHX_ACTOR);
            }
        }
        else if (Verb == remove) {
            if (wetsuit.WORN) {
                wetsuit.WORN = false;
                "OK, you're no longer wearing the wetsuit.\n";
                ExitPhase(PHX_ACTOR);
            }
            else {
                "You are not wearing the wetsuit!\n";
                ExitPhase(PHX_ACTOR);
            }
        }
        else if (Verb == drop) {
            if (wetsuit.WORN) {
                "You'll have to remove the wetsuit first.\n";
                Skip = true;
            }
        }
    }
}

MpuThing signpost(Roadx) {
    RDLOC=10
    WEIGH=CAPAC
    ldesc = proc() {"There is a signpost by the side of the road.\n";}
    sdesc = proc() {"a signpost";}
    action = proc() {
        if ((Verb == V_read) || (Verb == examine)) {
            "Pointing east, it says: 'Unuchevala: 10 miles'\n";
            ExitPhase(PHX_ACTOR);
        }
    }
}

class Globe(MpuThing) {public var pLight;}
Globe globe(toolBox) {
    WEIGH = 20
    ldesc = proc() {
        if (globe.pLight)
            "A globe of stone glows brightly here.\n";
        else
            "There is a strange globe of polished stone here.\n";
    }
    sdesc = proc() {
        if (globe.pLight)
            "a glowing globe of stone";
        else
            "a stone globe";
    }
    action = proc() {
        if (Verb == rub) {
            if (globe.pLight) {
                "The light from the stone globe fades away.\n";
                globe.pLight = false;
            }
            else {
                "The stone globe glows brightly!\n";
                globe.pLight = true;
            }
            MyLoc = -1;
            ExitPhase(PHX_ACTOR);
        }
        else if (Verb == examine) {
            if (globe.pLight) {
                "The globe is glowing.\n";
                ExitPhase(PHX_ACTOR);
            }
        }
    }
}

MpuThing crowbar(town3) {
    WEIGH = 100
    ldesc = proc() {"There is a long crowbar here.\n";}
    sdesc = proc() {"a crowbar";}
}

proc crydie()
{
    "What POWER!  The magic crystal releases a flood of energy in ",
    "a split-second!  Unfortunately, you were a little close...\n";
    Die();
}

// Dragon Stuff

class Dragon(MpuThing) { public var AWAKE, KILLED; }
Dragon dragon(cel06) {...}

Synonym white(clear);
NounClass crystal();

class Crystal(MpuThing) { public var WORKD = 0, pLight; }
Crystal greenCrystal(cel07)     { adjec = green  noun = crystal  ... }
Crystal redCrystal(cel08)       { adjec = red    noun = crystal  ... }
Crystal blueCrystal(cel10)      { adjec = blue   noun = crystal  ... }
Crystal clearCrystal(cel09)     { adjec = clear  noun = crystal  ... }

Synonym diamond(clearCrystal);
Synonym sapphire(blueCrystal);
Synonym ruby(redCrystal);
Synonym emerald(greenCrystal);

... greenCrystal {
    WEIGH=15
    POINT=35
    ldesc = proc() {"There is a beautiful green crystal here!\n";}
    sdesc = proc() {"a green crystal";}
    action = proc() {
        if (Verb == take) {
            if ((!dragon.KILLED) && ($ME.loc == cel07)) {
                if (!dragon.AWAKE) {
                    "You hear a stirring nearby.\n";
                    Tempr = Tempr + 2;
                    dragon.AWAKE = true;
                    cel06.pSeen = false;
                }
                else {
                    Tempr = 0;
                }
            }
        }
        else if (Verb == drop) {
            if ((!dragon.KILLED) && ($ME.loc == cel07)) {
                Tempr = Tempr - 2;
                if (Tempr <= 0) {
                    dragon.AWAKE = false;
                    "You hear a deep  Y A W N  nearby.\n";
                }
                cel06.pSeen = false;
            }
        }
        else if (Verb == touch) {
            if (Dobj == redCrystal) {
                if ($ME.loc == toolBox) {
                    "The red and green crystals flare briefly!\n";
                    Grow();
                    $ME.move(cel01);
                    MyLoc = -1;
                }
                else {
                    "Nothing happens.\n";
                }
                ExitPhase(PHX_ACTOR);
            }
            else if (Dobj == blueCrystal) {
                if (!Wizrd && (greenCrystal.WORKD > 2)) {
                    "Nothing happens.\n";
                }
                else {
                    greenCrystal.WORKD = greenCrystal.WORKD + 1;
                    "The blue and green crystals flare briefly!\n";
                    $ME.move(toolBox);
                    Shrink();
                    MyLoc = -1;
                }
                ExitPhase(PHX_ACTOR);
            }
            else if (Dobj == clearCrystal) {
                "Nothing happens.\n";
                ExitPhase(PHX_ACTOR);
            }
        }
        else if (Verb == V_break) {
            if (Dobj == greenCrystal) {
                crydie();
            }
        }
    }
}

... redCrystal {
    WEIGH=15
    POINT=15
    ldesc = proc() {"There is a beautiful red crystal here!\n";}
    sdesc = proc() {"a red crystal";}
    action = proc() {
        if (Verb == touch) {
            if (Dobj == clearCrystal) {
                if (Wizrd || (clearCrystal.WORKD < 2)) {
                    "The red and clear crystals flare briefly!\n";
                    clearCrystal.WORKD = clearCrystal.WORKD + 1;
                    clearCrystal.pLight = true;
                    "The clear crystal blazes forth with a magical ",
                    "incandescence brilliant enough to penetrate even ",
                    "the deepest darkness!!\n\n";
                    MyLoc = -1;
                    $ME.setfuse( CRout, 7);
                    ExitPhase(PHX_ACTOR);
                }
                else {
                    "Nothing happens.\n";
                    ExitPhase(PHX_ACTOR);
                }
            }
            else if (Dobj == greenCrystal) {
                if ($ME.loc == toolBox) {
                    "The red and green crystals flare briefly!\n";
                    Grow();
                    $ME.move(cel01);
                    MyLoc  = -1;
                }
                else {
                    "Nothing happens.\n";
                }
                ExitPhase(PHX_ACTOR);
            }
            else if (Dobj == blueCrystal) {
                if (($ME.loc == desert) || ($ME.loc == field)) {
                    "The red and blue crystals flare briefly!\n";
                    $ME.move(cel08);
                    MyLoc = -1;
                }
                else {
                    "Nothing happens.\n";
                }
                ExitPhase(PHX_ACTOR);
            }
        }
        else if (Verb == V_break) {
            if (Dobj == redCrystal) {
                crydie();
            }
        }
    }
}

... blueCrystal {
    WEIGH=15
    POINT=15
    ldesc = proc() {"There is a beautiful blue crystal here!\n";}
    sdesc = proc() {"a blue crystal";}
    action = proc() {
        if (Verb == touch) {
            if (Dobj == redCrystal) {
                    if (($ME.loc == desert) || ($ME.loc == field)) {
                    "The red and blue crystals flare briefly!\n";
                    $ME.move(cel08);
                    MyLoc = -1;
                }
                else {
                    "Nothing happens.\n";
                }
                ExitPhase(PHX_ACTOR);
            }
            else if (Dobj == greenCrystal) {
                if (!Wizrd && (greenCrystal.WORKD > 2)) {
                    "Nothing happens.\n";
                }
                else {
                    "The blue and green crystals flare briefly!\n";
                    $ME.move(toolBox);
                    Shrink();
                    MyLoc = -1;
                    greenCrystal.WORKD = greenCrystal.WORKD + 1;
                }
                ExitPhase(PHX_ACTOR);
            }
            else if (Dobj == clearCrystal) {
                "Nothing happens.\n";
                ExitPhase(PHX_ACTOR);
            }
        }
        else if (Verb == V_break) {
            if (Dobj == blueCrystal) {
                crydie();
            }
        }
    }
}

proc CRout()
{
    clearCrystal.pLight = false;
    "The glowing magical crystal seems to have gone dark.\n";
}

... clearCrystal {
    WEIGH=15
    POINT=40
    ldesc = proc() {
        "There is a beautiful clear crystal here";
        if (clearCrystal.pLight) {
            " (GLOWING!)";
        }
        "!\n";
    }
    sdesc = proc() {
        "a clear crystal";
        if (clearCrystal.pLight) {
            " (GLOWING!)";
        }
    }
    action = proc() {
        if (Verb == touch) {
            if (Dobj == redCrystal) {
                if (Wizrd || (clearCrystal.WORKD < 2)) {
                    "The red and clear crystals flare briefly!\n";
                    clearCrystal.WORKD = clearCrystal.WORKD + 1;
                    clearCrystal.pLight = true;
                    "The clear crystal blazes forth with a magical ",
                    "incandescence brilliant enough to penetrate even the ",
                    "deepest darkness!!\n\n";
                    MyLoc = -1;
                    $ME.setfuse(CRout, 7);
                    ExitPhase(PHX_ACTOR);
                }
                else {
                    "Nothing happens.\n";
                    ExitPhase(PHX_ACTOR);
                }
            }
            else if (Dobj == greenCrystal) {
                "Nothing happens.\n";
                ExitPhase(PHX_ACTOR);
            }
            else if (Dobj == blueCrystal) {
                "Nothing happens.\n";
                ExitPhase(PHX_ACTOR);
            }
        }
        else if (Verb == V_break) {
            if (Dobj == redCrystal) {
                crydie();
            }
        }
    }
}

proc KillDragon;

class Wood(MpuThing) {public var pFlame;}
Wood wood(cel20) {...}

proc KillDragon;
proc DRdem(isLdesc) // Dragon Daemon.  Increases temper in my presence
{
    if (dragon.KILLED || !dragon.AWAKE) {
        if (isLdesc) "\n";
        return 0;
    }
    if ($ME.loc == dragon.loc) {
        if (greenCrystal.loc == $ME) {      // even worse!
            Tempr = Tempr + 1;
        }
        Tempr = Tempr + 1;
        if (wood.pFlame && (wood.loc == $ME.loc)) {
            KillDragon();
            return 0;
        }
    }
    if (Tempr >= 7) {
        "Jeez, I didn't know ice dragons could reach their boiling point! ",
        "In a final flare of rage, he opens his mouth and breathes his frigid ",
        "breath in a blast in your direction.  It's a bit much for you.";
        Die();
    }
    else if (Tempr >= 6)
        "Gee, he looks like he's really at the edge!";
    else if (Tempr >= 5)
        "This is one upset dragon!  Be careful!";
    else if (Tempr >= 3)
        "He's getting angrier...";
    else
        "He looks a little peeved.";
    if (isLdesc) "\n";
}

... dragon {
    WEIGH = CAPAC
    ldesc = proc() {
        if (dragon.AWAKE)
            "There is a fierce ice dragon glaring balefully in your ",
            "direction.  ";
        else
            "There is a large white dragon sleeping peacefully in the middle ",
            "of the cavern floor.  ";
        DRdem(1);
    }
    sdesc = proc() {
        if (dragon.AWAKE)
            "a fierce dragon.  ";
        else
            "a somnolent dragon.  ";
        if (MyLoc != $ME.loc) {
            DRdem(0);
        }
    }
    action = proc() {               // Man, the things you can try here...
        if (dragon.AWAKE) {                 // This is the harder stuff
            if (Verb == strike) {
                "This just seems to get him angrier!\n";
                Tempr = Tempr + 1;
                ExitPhase(PHX_ACTOR);
            }
            else if (Verb == V_throw) {
                if (Iobj == dragon) {
                    if (Dobj.WEIGH > 75) {
                        "This just bruises him!  Now he's getting mad!\n";
                        Tempr = Tempr + 1;
                        ExitPhase(PHX_ACTOR);
                    }
                    else {
                        "That object is just too light to hurt him.\n";
                        ExitPhase(PHX_ACTOR);
                    }
                }
                else { // Dobj action
                    "This amuses the dragon no end!\n";
                    ExitPhase(PHX_ACTOR);
                }
            }                                       // end of Throw  case
        }
        else { // he's snoozing
            if (Verb == wake) {
                "You manage to waken him.  He's not happy.\n";
                Tempr = 1;
                dragon.AWAKE = true;
                if ((wood.loc == $ME.loc) && wood.pFlame) {
                    KillDragon();
                }
                ExitPhase(PHX_ACTOR);
            }
            else if (Verb == strike) {
                "Now you woke him up!  He's upset, too!\n";
                Tempr = 2;
                dragon.AWAKE = true;
                ExitPhase(PHX_ACTOR);
            }
            else if (Verb == V_throw) {
                if (Iobj == dragon) {
                    if (Dobj.WEIGH > 75) {
                        "It's just heavy enough to waken him.  The bruise ",
                        "doesn't help his temper any either.\n";
                        dragon.AWAKE = true;
                        Tempr = 3;
                        ExitPhase(PHX_ACTOR);
                    }
                    else {
                        "That object is just too light to wake him.\n";
                        ExitPhase(PHX_ACTOR);
                    }
                }
                else {
                    "Don't hurt yourself trying!\n";
                    ExitPhase(PHX_ACTOR);
                }
            }                                       // end of Throw  case
        }
    }
}

class Money(MpuThing) { public var FOUND; }
Money money() {
    WEIGH = 1
    ldesc = proc() {"There is a stack of money here!\n";}
    sdesc = proc() {"a stack of money";}
    POINT = 30
}
Synonym stack(money);

class Bed(MpuThing) { public var pOpened; }
Bed bed(farm7) {
    WEIGH = CAPAC
    sdesc = proc() {"an old, rickety bed";}
    action = proc() {
        if (Verb == move) {
            if (bed.pOpened) {
                "Stop messing with the bed, it's fragile!\n";
                ExitPhase(PHX_ACTOR);
            }
            "Moving the bed seems to have loosened one of the wall panels ",
            "on the west wall.\n";
            bed.pOpened = true;
            ExitPhase(PHX_ACTOR);
        }
        else if ((Verb == look) && (Iobj == bed)) {
            if (Prep == underPrep) {
                if (!money.FOUND) {
                    "You find some money under the bed!\n";
                    money.move($ME.loc);
                    money.FOUND = true;
                    ExitPhase(PHX_ACTOR);
                }
            }
            else if (bed.pOpened) {
                "The bed has been moved.\n";
                ExitPhase(PHX_ACTOR);
            }
        }
    }
}

class Panel(MpuThing) { public var pOpens, pOpened; }
Panel panel(farm7) {
    pOpens = true
    WEIGH = CAPAC
    action = proc() {
        if ((Verb == open) || (Verb == pry)) {
            if ((Iobj == crowbar) && (crowbar.loc == $ME)) {
                if (!bed.pOpened) {
                    "There aren't any loose enough.\n";
                    ExitPhase(PHX_ACTOR);
                }
                "The loose panel comes away, revealing a secret stairway ",
                "down, down...\n";
                panel.pOpened = true;
            }
            else {
                "You can't seem to get the panel open.\n";
            }
            ExitPhase(PHX_ACTOR);
        }
    }
}

class Bottle(MpuThing) {public var pTrans, pSeen;}
Bottle bottle(town6) {
    WEIGH = 5
    ldesc = proc() {"There is a bottle here.\n";}
    sdesc = proc() {"a bottle";}
    pTrans = true
    action = proc() {
        if (Verb == open) {
            "Hm, the bottle is somehow sealed shut.\n";
            ExitPhase(PHX_ACTOR);
        }
        else if (Verb == V_break) {
            "Wow, is that heavy glass!  It won't break!\n";
            ExitPhase(PHX_ACTOR);
        }
        else if (Verb == strike) {
            if (Iobj == bottle)
                "Weird thing to do with it.\n";
            else
                "Nice try, but it isn't even scratched.\n";
            ExitPhase(PHX_ACTOR);
        }
    }
}

MpuThing ship(bottle) {
    ldesc = proc() {"There is a golden model ship here!\n";}
    sdesc = proc() {"a golden model ship";}
    WEIGH = 5
    POINT = 50
}
Synonym model(ship);

class Well(MpuThing) { public var pNoTake, pOpened; }
Well well(town5) {
    pNoTake = true
    pOpened = true
    action = proc() {
        if (Iobj == well) {
            if (Verb == drop) {
                TWN5y();
            }
        }
    }
}

MpuThing painting(cel08) {
    action = proc() {
        if (Verb == take) {
            "You can't take the painting.\n";
            Skip = true;
        }
        else {
            "Fiddling with the painting is silly.\n";
            ExitPhase(PHX_ACTOR);
        }
    }
}

MpuThing grate(riverx) {
    Loc21 = GRATELOC
    action = proc() {
        if (Verb == take) {
            "You can't take the grate.\n";
            Skip = true;
        }
        else {
            "Fiddling with the grate is useless.\n";
            ExitPhase(PHX_ACTOR);
        }
    }
}

class Insignia(MpuThing) { public var pNoTake; }
Insignia insignia() {
    pNoTake = true
    WEIGH = CAPAC
    action = proc() {
        if (Verb == examine) {
            "The insignia consists of ";
            if ($ME.loc == cel01)
                "red and green squares ";
            else if ($ME.loc == cel04)
                "red and clear squares ";
            else if ($ME.loc == cel08)
                "red and blue squares ";
            else if ($ME.loc == farm5)
                "blue and green squares ";
            "joined at the corners.\n";
            ExitPhase(PHX_ACTOR);
        }
        "There's nothing useful to do with the insignia.\n";
        ExitPhase(PHX_ACTOR);
    }
}
Synonym square(insignia);

class GlassBox(MpuThing) {
    public var pSeen, pTrans, pOpens, pOpened, SHRNK, HOLDS, pSeen;
}
GlassBox glassBox(cel08) {
    adjec = glass
    noun = box
    HOLDS=1
    pTrans=true
    pOpens=true
    pOpened=false
    SHRNK=true          // First seen as a tiny box
    ldesc = proc() {
        if ($ME.SHRNK == glassBox.SHRNK) {
            "There is a big glass case here.\n";
            glassBox.WEIGH = CAPAC;
            glassBox.HOLDS = 50;
        }
        else {
            if ($ME.SHRNK) {
                "Before you looms a huge glass wall, inscribed with the ",
                "words, 'program error!'\n";
            }
            else {
                "There is a tiny glass box with a snap lid here.\n";
                glassBox.WEIGH = 5;
                glassBox.HOLDS = 1;
            }
        }
    }
    sdesc = proc() {
        if ($ME.SHRNK == glassBox.SHRNK) {
            "a glass case";
            glassBox.WEIGH = CAPAC;
            glassBox.HOLDS = 50;
        }
        else {
            if ($ME.SHRNK) {
                "a huge glass wall, inscribed with the words, ",
                "'program error'";
            }
            else {
                "a tiny glass box";
                glassBox.WEIGH = 5;
                glassBox.HOLDS = 1;
            }
        }
    }
    action = proc() {
        if (Verb == examine) {
            if (glassBox.pOpened)
                "The case is opened.\n";
            else
                "The case is closed (pun not intended).\n";
            ExitPhase(PHX_ACTOR);
        }
    }
}
Synonym _case(glassBox,"case");        // "case" is a keyword, careful

class Sand(MpuThing) {public var SHRNK;}
Sand sand(glassBox) {
    SHRNK=true
    WEIGH=1
    ldesc = proc() {
        if (sand.SHRNK && !$ME.SHRNK) {
            sand.POINT = 0;
            "There is a grain of sand here.\n";
        }
        else {
            "There is a beautiful porcelain statue here!\n";
            sand.POINT = 50;
        }
    }
    sdesc= proc() {
        if (sand.SHRNK && !$ME.SHRNK) {
            sand.POINT = 0;
            "a grain of sand";
        }
        else {
            "a porcelain statue";
            sand.POINT = 50;
        }
    }
    action = proc() {
        if (Verb == take) {
            if (sand.SHRNK && !$ME.SHRNK) {
                "You fumble the grain of sand and lose it on the ground.\n";
                sand.move($ALL);
                Skip = true;
            }
        }
    }
}
Synonym statue(sand);

class Hole(MpuThing) {public var pNoTake;}
Hole hole {
    pNoTake = true
    action = proc() {
        "You can't do anything useful with the hole.\n";
        ExitPhase(PHX_ACTOR);
    }
}

MpuThing rock(road5) {
    ldesc = proc() {"There is a plain-looking rock here.\n";}
    sdesc = proc() {"an ordinary rock";}
    action = proc() {
        if ((Verb == take) && (Dobj == rock)) {
            "Mmph!  Heavy!\n";
        }
    }
    WEIGH=100
}

class Ivory(MpuThing) {public var IFOUND;}
Ivory ivory(riverx) {
    WEIGH = 5
    POINT = 30
    Loc21 = GRATELOC
    ldesc = proc() {
        "There is a beautiful piece of ivory ";
        if (!ivory.IFOUND) {
            "wedged in the grate.\n";
            ivory.IFOUND = true;
        }
        else {
            "here.\n";
        }
    }
    sdesc = proc() {
        "a piece of ivory";
        if (!ivory.IFOUND) {
            " (wedged in the grate)";
            ivory.IFOUND = true;
        }
    }
}

MpuThing matches(cel12) {
    ldesc = proc() {"There is a book of waterproof matches here.\n";}
    sdesc = proc() {"a book of matches";}
    action = proc() {
        if (((Verb == light) || (Verb == burn)) && (Dobj == matches)) {
            "OK, you light a match, which quickly burns out.\n";
            ExitPhase(PHX_ACTOR);
        }
    }
    WEIGH = 1
}
Synonym book(matches);

proc WoodBurn()
{
    if (wood.loc == $ME.loc) {
        "The wood burns down to a pile of ashes, which blows away.\n";
    }
    wood.move($ALL);
    wood.pFlame = false;
}


... wood {
    ldesc = proc() {
        "There is a pile of ";
        if (wood.pFlame) "burning ";
        "wood here.\n";
    }
    sdesc = proc() {
        "a pile of ";
        if (wood.pFlame) "burning ";
        "wood";
    }
    WEIGH = 100
    action = proc() {
        if (wood.pFlame) {
            "The wood is too hot to touch.\n";
            if ((Verb == take)  || (Verb == drop)) {
                Skip = true;
                return 0;
            }
            else {
                ExitPhase(PHX_ACTOR);
            }
        }
        else if ((Verb == burn) || (Verb == light)) {
            if (!Iobj) {
                "You must tell me how to do that!\n";
                ExitPhase(PHX_ACTOR);
            }
            else if (Iobj != matches) {
                "That doesn't seem to work.\n";
                ExitPhase(PHX_ACTOR);
            }
            else if (wood.loc == $ME) {
                "You can't manage that while you are holding the wood.\n";
                ExitPhase(PHX_ACTOR);
            }
            "You strike a match and apply it to the wood, which bursts ",
            "into flames.\n";
            if (dragon.AWAKE && ($ME.loc == dragon.loc)) {
                KillDragon();
            }
            else {
                wood.pFlame = true;
                $ME.setfuse(WoodBurn, 3);
            }
            ExitPhase(PHX_ACTOR);
        }
    }
}

proc KillDragon()
{
    "The dragon, attracted by the bright flame of the burning wood, snaps it ",
    "up in its jaws.  Suddenly, the dragon realizes what it has done!  It ",
    "tries to spit out the wood, but it is too late!  The dragon evaporates ",
    "with a deafening whistle and a burst of steam!  ";
    if ((bottle.loc == $ME.loc) || (bottle.loc == $ME)) {
        "The sound of the whistle shatters the bottle, ",
        "releasing the golden ship model!  ";
        ship.move($ME.loc);
        bottle.move($ALL);
    }
    "Upon the death of the dragon, the ice melts with astonishing speed.\n";
    $ME.delfuse(WoodBurn);
    wood.move($ALL);
    dragon.KILLED = true;
    dragon.move($ALL);
    cel06.pSeen = false;
    cel05.pSeen = false;
    cel03.pSeen = false;
    cel10.pSeen = false;
    cel08.pSeen = false;
}

class Goblet(MpuThing) {public var FREED;}
Goblet goblet(cel19) {
    WEIGH = 5
    POINT = 25
    ldesc = proc() {
        if (!goblet.FREED)
            "There is a beautiful golden goblet frozen in the ice!\n";
        else
            "There is a beautiful golden goblet here!\n";
    }
    sdesc = proc() {
        "a golden goblet";
        if (!goblet.FREED) " (frozen in the ice)";
    }
    action = proc() {
        if (!goblet.FREED) {
            "There's not much you can do with the goblet while it's frozen ",
            "in the ice.\n";
            ExitPhase(PHX_ACTOR);
        }
    }
}

MpuThing newspaper(town2) {
    ldesc = proc() {
        "There is a newspaper fluttering in the breeze here.\n";
    }
    sdesc = proc() {"a newspaper";}
    action = proc() {
        if ((Verb == V_read) || (Verb == examine)) {
            "               UNUCHEVALA NEWS -- VOLU$ME II NUMBER 1\n",
            "\n",
            "VANDALS THREATEN COWLEY\n",
            "\n",
            "\tLast night,  unknown vandals attacked the farm of Mr. Cowley, ",
            "north of town.  They sprayed \"DIE, HEATHENS\" on  his front ",
            "door (in reference to his admittedly strange  beliefs).   Cowley ",
            "says that this is not the first such threat he has received. ",
            "However, he says that he will deal with the vandals in his own ",
            "way.   Unfortunately,  we have been unable to contact Mr. Cowley ",
            "personally, since he has not been seen hereabouts ",
            "since last night.\n",
            "\n",
            "DROUGHT IMMINENT, SAY LOCAL FAR$MERS\n",
            "\n",
            "\tThe  Unuchevala  River has recently  been  falling,  and ",
            "little relief is in sight for our  local farmers.   \"I'm agonna ",
            "leave here, purty soon,\" said one farmer  (who chose to ",
            "remain anonymous).   \"It's all that danged Cowley's fault, ",
            "messin'  about  with  things  that  ain't natrawl-like.  I ",
            "caint even raise 'nuff to feed myself, not mentionin' the ",
            "resta the town.\"\n",
            "\n",
            "WEATHER -- Continued dry, with no rain in sight.\n",
            "\n";
            ExitPhase(PHX_ACTOR);
        }
        else if ((Verb == burn) || (Verb == light)) {
            if (!Iobj) {
                "You must tell me how to do that!\n";
                ExitPhase(PHX_ACTOR);
            }
            else if (Iobj != matches) {
                "That doesn't seem to work.\n";
                ExitPhase(PHX_ACTOR);
            }
            else if (newspaper.loc == $ME) {
                "You can't manage to do that while holding the newspaper.\n";
                ExitPhase(PHX_ACTOR);
            }
            "The newspaper lights easily, burning down to ashes which blow ",
            "away.\n";
            if (($ME.loc == dragon.loc) && dragon.AWAKE) {
                // give the player a hint
                "The dragon notices the flash and approaches the newspaper, ",
                "but the fire dies down before the dragon can reach it.\n";
            }
            newspaper.move($ALL);
            ExitPhase(PHX_ACTOR);
        }
    }
}
Synonym paper(newspaper);

class Ice(MpuThing) {public var pNoTake;}
Ice ice {
    pNoTake = true
    action = proc() {
        if ((Verb == V_break) || (Verb == hit)) {
            if (Dobj == ice) {
                if (!Iobj) {
                    "You must tell me how to do that.\n";
                    ExitPhase(PHX_ACTOR);
                }
                if ($ME.loc == cel19) {
                    if (Iobj.WEIGH > 20) {
                        if (!goblet.FREED) {
                            "You manage to free the goblet.\n";
                            goblet.FREED = true;
                            goblet.move(cel19);
                            ExitPhase(PHX_ACTOR);
                        }
                    }
                }
                else if ($ME.loc == cel13) {
                    if (!cel13.HOLED) {
                        if (Iobj.WEIGH > 75) {
                            "You swing at the ice with the ", Iobj.name,
                            ", which breaks through and sinks into ",
                            "the icy waters below!\n";
                            Iobj.move($ALL);
                            $ME.HAS = $ME.HAS - Iobj.WEIGH;
                            cel13.HOLED = true;
                            ExitPhase(PHX_ACTOR);
                        }
                    }
                }
                "The ice chips a bit, but does not break.\n";
                ExitPhase(PHX_ACTOR);
            }
        }
        "You can't do that!\n";
        ExitPhase(PHX_ACTOR);
    }
}

class Socket(MpuThing) { public var pNoTake = true; }
Socket socket(cel20) {...}
Synonym outlet(socket);
Synonym receptacle(socket);

MpuThing token; // forward decl

class Toaster(MpuThing) { public var PLUGGED; }
Toaster toaster($ALL) {
    WEIGH = 5
    sdesc = proc() {"a toaster";}
    ldesc = proc() {"There is an old-fashioned toaster here.\n";}
    action = proc() {
        if (Verb == take) {
            if (toaster.PLUGGED)
                "You can't take the toaster while it's plugged in!\n";
            else if (token.loc == toaster) {
                "Something rattles inside the toaster as you take it.\n";
                toaster.move($ME);
            }
            Skip = true;
        }
        else if (Verb == plug) {
            if (((Iobj == toaster) && !Dobj & (Prep == inPrep)) |
                ((Dobj == toaster) && (Iobj == socket) & (Prep == inPrep)))
            {
                if (socket.loc != $ME.loc)
                    "I don't see a socket here.\n";
                else if (toaster.PLUGGED)
                    "It's already plugged in!\n";
                else {
                    if (token.loc == toaster) {
                        "As you plug the toaster in, a bell rings, and ",
                        "something pops out!\n";
                        token.move($ME.loc);
                    }
                    else
                        "OK, the toaster is plugged in.\n";
                    toaster.move($ME.loc);
                    toaster.PLUGGED = true;
                }
                ExitPhase(PHX_ACTOR);
            }
            else {
                "I can't do that!\n";
                ExitPhase(PHX_ACTOR);
            }
        }
        else if (Verb == unplug) {
            if (!((Dobj == toaster) && (!Iobj || (Iobj == socket))))
                "Why would anybody want to do such a thing?\n";
            else if (!toaster.PLUGGED)
                "It's already unplugged!\n";
            else {
                "You unplug the toaster.\n";
                toaster.PLUGGED = false;
            }
            ExitPhase(PHX_ACTOR);
        }
    }
}

MpuThing token(toaster) {
    WEIGH = 1
    ldesc = proc() {"There is a bus token here.\n";}
    sdesc = proc() {"a bus token";}
    action = proc() {
        if (Verb == examine) {
            "The token reads, \"This token redeemable for one (1) trip by ",
            "bus along the Unuchevala - Doscale route.  No cash value.\"\n";
            ExitPhase(PHX_ACTOR);
        }
    }
}

... socket {
    sdesc = proc() {"a socket";}
    action = proc() {
        if ((Dobj != toaster) && ((Verb == plug) || (Verb == unplug))) {
            "You really shouldn't play with electrical sockets.\n";
            ExitPhase(PHX_ACTOR);
        }
        else if (Verb == take) {
            "The socket is firmly attached to the wall.\n";
            Skip = true;
        }
    }
}

class Bus(MpuThing) {
    public var
        pSeen, pLight = true, pNoTake= true, RDLOC = 5, WEIGH = CAPAC, MOVING;
}
Bus bus(Roadx) {
    ldesc = proc() {
        if ($ME.loc == bus) {
            "You are on board a rusty old bus";
            if (bus.MOVING) {
                ", which is travelling ";
                if (bus.loc == city) "east"; else "west";
                " down a dusty road.";
            }
            else
                ".  The only way to go is out.";
            "  There is a slot by the door, above which is a sign ",
            "reading, \"FARE: 25 CENTS\"\n";
        }
        else {
            "There is a rusty old bus here, ";
            if ((HWY7 == 11) || (bus.loc == city))
                "facing east.\n";
            else if (HWY7 == 5)
                "facing west.\n";
        }
    }
    sdesc = proc() {
        if ($ME.loc == bus)
            return Sayer("Bus", oadl::nargs());
        else
            "a bus";
    }
    action = proc() {
        if ($ME.loc == bus) {
            if (GOVERB) {
                if (bus.MOVING) {
                    "You can go nowhere while the bus is moving.\n";
                    GOVERB = false;
                }
                else if (Verb == exit) {
                    if (bus.loc == city)
                        $ME.move(city);
                    else {
                        $ME.move(road7);
                        Get7(Roadx.cont);
                    }
                    GOVERB = false;
                }
            }
        }
        else if (Verb == enter) {
            if ($ME.loc != bus.loc) {
                "You see no bus here.\n";
                ExitPhase(PHX_ACTOR);
            }
            "You board the bus.\n";
            if ($ME.loc == road7)
                Dump7(road7.cont);              // Put the bus at Roadx
            $ME.move(bus);
            ExitPhase(PHX_ACTOR);
        }
        else if (Verb == take) {
            "Get real!\n";
            ExitPhase(PHX_ACTOR);
        }
        else if (Verb == examine) {
            if (($ME.loc == road7) && (HWY7 == 5))
                "There is smoke pouring out from the engine compartment.  ";
            "The door is open, and you may enter if you wish.\n";
            ExitPhase(PHX_ACTOR);
        }
    }
}

proc BStop()
 {
    bus.MOVING = false;
    if (bus.loc == city) {
        "The bus grinds to a halt with a loud noise that ",
        "leads you to believe that it has done its last run.\n";
        bus.move(Roadx);
        bus.RDLOC = 11;
        HWY7 = 11;
    }
    else {
        "The bus swings around so that it faces east, then ",
        "turns itself off.\n";
        bus.move(city);
    }
}


class Bag(MpuThing) { public var pOpens = true, pOpened, HOLDS = 15; }
Bag bag(building) {
    WEIGH = 3
    ldesc = proc() {"There is a large canvas bag here.\n";}
    sdesc = proc() {"a bag";}
}
Synonym sack(bag);

class SilverRod(MpuThing) { public var WAVED; }
NounClass rod();
SilverRod silverRod(bag) {
    adjec = silver noun = rod
    WEIGH = 8
    POINT = 100
    ldesc = proc() {"There is a large silver rod here.\n";}
    sdesc = proc() {"a silver rod";}
    action = proc() {
        if ((Verb == wave) && (Dobj == silverRod)) {
            "A faint humming noise comes from the rod!";
            if (!silverRod.WAVED && ($ME.loc == cel08)) {
                "  The painting seems subtly altered.\n";
                silverRod.WAVED = true;
            }
            else
                "\n";
            ExitPhase(PHX_ACTOR);
        }
    }
}

class Slot(MpuThing) { public var pNoTake = true, pOpened = true; }
Slot slot(bus) {
    sdesc = proc() {"a coin slot";}
    action = proc() {
        if ((Verb == drop) && (Iobj == slot)) {
            if ($ME.loc != bus)
                "You see no slot here.\n";
            else if (!Dobj)
                "You must tell me what to drop into the slot.\n";
            else if (Dobj != token)
                "The ", Dobj.name, " doesn't fit into the slot.\n";
            else {
                "As you drop the token into the slot, the bus starts to ",
                "move with a nauseating jerking motion!\n";
                bus.MOVING = true;
                if (bus.loc == city) {
                    $ME.setfuse(BStop, 3);
                    token.move($ALL);
                }
                else {
                    $ME.setfuse(BStop, 4);
                    token.move(bag);
                }
            }
            Skip = true;
        }
        else if (Verb == take) {
            "The slot is not easily graspable.\n";
            Skip = true;
        }
    }
}