/*** TRANSITIONS ***/
Hitms = Proc(vrb, loc, func)
{
    If (Verb == vrb) {
	If (loc) {
	    $move($ME, loc);
	    GO = TRUE;
	}
	If (func) {
	    func();
	}
    }
}

Synvb = Proc(vrb, newvrb)
{
    If (Verb == vrb) {
	Verb = newvrb;
    }
}

road1(ACTION) = Proc()
{
    Hitms(n, gard1, 0);
    Hitms(s, gard2, 0);
    Hitms(e, road2, 0);
    Hitms(w, road3, 0);
}

road2(ACTION) = Proc()
{
    Hitms(n, gard1, 0);
    Hitms(s, gard2, 0);
    Hitms(e, road6, 0);
    Hitms(w, road1, 0);
}

DropKill = Proc()
{
    "The drop would kill you.\n";
    MyLoc = $loc($ME);
    GO = TRUE;
}

road3(ACTION) = Proc()
{
    Hitms(n, 0, DropKill);
    Hitms(s, 0, DropKill);
    Hitms(e, road1, 0);
    Hitms(w, road7, Entr7);
}

road4(ACTION) = Proc()
{
    Hitms(n, farm1, 0);
    Hitms(s, road6, 0);
    Hitms(e, frst1, 0);
    Hitms(w, gard1, 0);
}

road5(ACTION) = Proc()
{
    Hitms(n, road6, 0);
    Hitms(s, town1, 0);
    Hitms(e, frst1, 0);
    Hitms(w, gard2, 0);
}

road6(ACTION) = Proc()
{
    Hitms(n, road4, 0);
    Hitms(s, road5, 0);
    Hitms(e, frst1, 0);
    Hitms(w, road2, 0);
}

road7(ACTION) = Proc()
{
    $miss(Tress, Tress, East7, West7, 0, 0, 0, 0, 0, 0);
}

East7 = Proc()
{
    GO = TRUE;
    If (!HWY7) {
	$move($ME, road3);
    }
    Else {
	Dump7($cont(road7));
	HWY7 = HWY7 - 1;
	Get7($cont(Roadx));
    }
}

West7 = Proc()
{
    GO = TRUE;
    Dump7($cont(road7));
    HWY7 = HWY7 + 1;
    Get7($cont(Roadx));
}

Dump7 = Proc(obj)
{
    If ($link(obj)) {
	Dump7($link(obj));		// start at bottom
    }
    If (obj != $ME) {		// Everything else leaves
	obj.RDLOC = HWY7;		// Retain its location on HWY 7
	$move(obj, Roadx);		// Put it in the box
    }
}

Get7 = Proc(obj)
{
    If (obj) {
	Get7($link(obj));
	If (obj.RDLOC == HWY7) {
	    $move(obj, road7);
	}
    }
}

Entr7 = Proc()
{
    Dump7($cont(road7));
    HWY7 = 0;
    Get7($cont(Roadx));
}

gard1(ACTION) = Proc()
{
    Hitms(n, gard1, 0);
    Hitms(s, road1, 0);
    Hitms(e, gard1, 0);
    Hitms(w, gard1, 0);
}

gard2(ACTION) = Proc()
{
    Hitms(n, road1, 0);
    Hitms(s, gard2, 0);
    Hitms(e, gard2, 0);
    Hitms(w, gard2, 0);
}

FLeave = Proc()
{
    If ($pct(20)) {
	$move($ME, road6);
    }
    GO = TRUE;
}

frst1(ACTION) = Proc()
{
    $miss(FLeave, FLeave, FLeave, FLeave, FLeave, FLeave, FLeave, FLeave, 0, 0);
}

farm1 (ACTION) = Proc()
{
    Synvb(enter, north);
    Hitms(n, farm2, 0);
    Hitms(s, road4, 0);
    Hitms(e, farm3, 0);
    Hitms(w, farm4, 0);
    Hitms(ne, farm3, 0);
    Hitms(nw, farm4, 0);
}

farm2 (ACTION) = Proc()
{
    Synvb(out, s);
    Synvb(enter, n);
    Synvb(east, up);
    Hitms(n, farm6, 0);
    Hitms(s, farm1, 0);
    Hitms(up, farm7, 0);
}

farm3 (ACTION) = Proc()
{
    Hitms(n, farm5, 0);
    Hitms(s, farm1, 0);
    Hitms(e, frst1, 0);
    Hitms(nw, farm5, 0);
    Hitms(sw, farm1, 0);
}

farm4 (ACTION) = Proc()
{
    Hitms(n, farm5, 0);
    Hitms(s, farm1, 0);
    Hitms(w, gard1, 0);
    Hitms(ne, farm5, 0);
    Hitms(se, farm1, 0);
}

farm5 (ACTION) = Proc()
{
    Hitms(e, farm3, 0);
    Hitms(w, farm4, 0);
    Hitms(se, farm3, 0);
    Hitms(sw, farm4, 0);
}

farm6 (ACTION) = Proc()
{
    Hitms(out, farm2, 0);
    Hitms(s, farm2, 0);
}

farm7 (ACTION) = Proc()
{
    Hitms(e, farm2, 0);
    Hitms(d, farm2, PanL);
}


town1 (ACTION) = Proc()
{
    Hitms(n, road5, 0);
    Hitms(s, town2, 0);
    Hitms(e, town3, 0);
    Hitms(w, town4, 0);
}

town2 (ACTION) = Proc()
{
    Hitms(n, town1, 0);
    Hitms(e, town5, 0);
    Hitms(w, town6, 0);
}

town3 (ACTION) = Proc()
{
    Hitms(out, town1, 0);
    Hitms(w, town1, 0);
}

town4 (ACTION) = Proc()
{
    Hitms(e, town1, 0);
    Hitms(out, town1, 0);
}

town5 (ACTION) = Proc()
{
    Hitms(w, town2, 0);
    Hitms(out, town2, 0);
}

town6 (ACTION) = Proc()
{
    Hitms(e, town2, 0);
    Hitms(out, town2, 0);
}


cel01 (ACTION) = Proc()
{
    Hitms(n, cel02, 0);
    Hitms(w, cel04, 0);
    Hitms(u, farm7, 0);
}

cel02 (ACTION) = Proc()
{
    Hitms(n, cel05, 0);
    Hitms(s, cel01, 0);
    Hitms(e, cel20, 0);
}

cel20(ACTION) = Proc()
{
    Hitms(w, cel02, 0);
}

cel03 (ACTION) = Proc()
{
    Hitms(s, cel05, 0);
    If (!dragon.KILLED) {
	Hitms(w, cel13, 0);
	Hitms(ne, cel09, 0);
	Hitms(d, cel09, 0);
    }
}

cel04 (ACTION) = Proc()
{
    Synvb(down, north);
    Hitms(n, cel10, 0);
    Hitms(e, cel01, 0);
    Hitms(w, cel08, 0);
}


MV56= Proc() {Cel6x = 5;}
MV76= Proc() {Cel6x = 7;}
MV67= Proc()
{
    If ((Cel6x != 7) & dragon.AWAKE & !dragon.KILLED) {
	"The ice dragon blocks your attempt to cross!\n\n";
    }
    Else {
	$move($ME, cel07);
    }
    GO = TRUE; // short circuit default error message
}

MV65= Proc()
{
    If ((Cel6x != 5) & dragon.AWAKE & !dragon.KILLED) {
	"The ice dragon blocks your attempt to leave!\n";
    }
    Else {
	$move($ME, cel05);
    }
    GO = TRUE; // short circuit default error message
}


cel05 (ACTION) = Proc()
{
    Hitms(n, cel03, 0);
    Hitms(s, cel02, 0);
    Hitms(ne, cel06, MV56);
}

cel06 (ACTION) = Proc()
{
    Hitms(e, 0, MV67);
    Hitms(sw, 0, MV65);
    If ((!dragon.KILLED) & dragon.AWAKE & ($loc($ME) == cel06)) { //still here
	MyLoc = -1;
    }
}

cel07 (ACTION) = Proc()
{
    Synvb(out, west);
    Hitms(w, cel06, MV76);
}

Thirst = Proc()
{
    If ($loc($ME) == desert) {
	"The blazing sun is too much for you, I'm afraid.\n";
	die();
    }
}

Move08 = Proc()
{
    If (RBTouch) {
	If (dragon.KILLED) {
	    $move($ME, field);
        }
	Else {
	    $move($ME, desert);
	    $sfus($ME, Thirst, 10);
	}
    }
    Else {
	"You bump your nose against the painting.\n";
	MyLoc = $loc($ME);
    }
    GO = TRUE;
}

cel08 (ACTION) = Proc()
{
    Hitms(e, cel04, 0);
    Hitms(w, 0, Move08);
}

Slippery = Proc()
{
    "The waterfall is to slick for you to climb.\n";
    MyLoc = $loc($ME);
    GO = TRUE;
}

CrackEntr = Proc()
{
    "You slip through the crack in the waterfall.\n";
}

Get21 = Proc()
{
    Var t, t1;
    t = $cont(riverx);
    While (t) {
	If (t.Loc21 == RiverLoc) {
	    t1 = $link(t);
	    $move(t, cel21);
	    t = t1;
        }
	Else {
	    t = $link(t);
	}
    }
}

Dump21 = Proc()
{
    Var t, t1;
    t = $cont(cel21);
    While (t) {
	If (t != $ME) {
	    t.Loc21 = RiverLoc;
	    t1 = $link(t);
	    $move(t, riverx);
	    t = t1;
        }
	Else {
	    t = $link(t);
	}
    }
}

Entr21 = Proc()
{
    RiverLoc = 1;
    Get21();
}

cel09 (ACTION) = Proc()
{
    Hitms(n, cel21, Entr21);
    Hitms(u, 0, Slippery);
    Hitms(s, cel18, CrackEntr);
}

Move11 = Proc()
{
    If (dragon.KILLED) {
	If (!wetsuit.WORN) {
	    "The pit is full of water!!!\n";
        }
	Else {
	    "That water looks mighty dangerous.  Are you sure?  ";
	    If ($yorn()) {
                "You leap into the pit and are immediately grabbed by a "
                "mighty current which pulls you down, down, down...  Soon "
                "the pressure becomes too great for you to breathe, and the "
                "last thing you remember is feeling somewhat like an "
                "elephant's footstool.\n";
		die();
	    }
	}
	MyLoc = $loc($ME);
    }
    Else {
	$move($ME, cel11);
    }
    GO = TRUE;
}

cel10 (ACTION) = Proc()
{
    Synvb(up, s);
    Hitms(s, cel04, 0);
    Hitms(d, 0, Move11);
}

cel11 (ACTION) = Proc()
{
    If (GOVERB & !<clear crystal>.LIGHT) {
        "You trip and fall into a pit that you were unable to see "
        "in the dark!\n";
	die();
    }
    Hitms(e, cel12, 0);
    Hitms(w, cel16, 0);
}

cel12 (ACTION) = Proc()
{
    Hitms(w, cel11, 0);
}

WaterEntr = Proc()
{
    If ($ME.HAS > globe.WEIGH) {
	If (!wetsuit.WORN) {
            "Whatever you're carrying drags you down into the icy waters!\n";
	    die();
	}
    }
}

cel13 (ACTION) = Proc()
{
    If (Verb == down) {
	If (cel13.HOLED) {
	    WaterEntr();
	    "You plunge into the icy waters!\n";
	    $move($ME, cel14);
	    GO = TRUE;
	    $exit(1);
	}
    }
    Hitms(e, cel03, 0);
    Hitms(w, cel19, 0);
}

Drown = Proc()
{
    If (($loc($ME) == cel14) | ($loc($ME) == cel17)) {
	If (!wetsuit.WORN) {
            "You can't hold your breath any longer.  The last thing you "
            "feel is the odd sensation of water entering your lungs.\n";
	    die();
	}
    }
}

cel14 (ACTION) = Proc()
{
    If (Verb == up) {
	If (cel13.HOLED) {
	    "You pop out through a hole in the ice!\n";
	    $move($ME, cel13);
	    GO = TRUE;
	    $exit(1);
        }
	Else {
	     "You are blocked by an icy roof above!\n";
	}
    }
    Hitms(w, cel15, 0);
    Hitms(e, cel17, 0);
    $sfus($ME, Drown, 1);
}

cel15(ACTION) = Proc()
{
    Synvb(up, south);
    Synvb(enter, e);
    Hitms(e, cel14, WaterEntr);
    Hitms(s, cel16, 0);
}

cel16(ACTION) = Proc()
{
    Synvb(down, north);
    Hitms(n, cel15, 0);
    Hitms(e, cel11, 0);
}

cel17(ACTION) = Proc()
{
    Hitms(ne, cel18, 0);
    Hitms(w, cel14, 0);
    $sfus($ME, Drown, 1);
}

Swim = Proc()
{
    "You dive into the icy waters.\n";
    WaterEntr();
}

cel18(ACTION) = Proc()
{
    Synvb(enter, sw);
    Hitms(n, cel09, 0);
    Hitms(sw, cel17, Swim);
}

cel19(ACTION) = Proc()
{
    Hitms(e, cel13, 0);
}

North21 = Proc()
{
    Dump21();
    RiverLoc = RiverLoc + 1;
    GO = TRUE;
    cel21.SEEN = FALSE;
    Get21();
}

South21 = Proc()
{
    Dump21();
    GO = TRUE;
    RiverLoc = RiverLoc - 1;
    cel21.SEEN = FALSE;
    If (!RiverLoc) {
	$move($ME, cel09);
    }
    Else {
	Get21();
    }
}

CantClimb = Proc()
{
    "The sides of the river bed are too steep for you to climb.\n";
    MyLoc = $loc($ME);
    GO = TRUE;
}

GrateThere = Proc()
{
    "The grate blocks your attempt to move that way.\n";
    MyLoc = $loc($ME);
    GO = TRUE;
}

cel21(ACTION) = Proc()
{
    If (RiverLoc == GRATELOC)
	$miss(South21, GrateThere, CantClimb, CantClimb, 0, 0, 0, 0, 0, 0);
    Else If (RiverLoc == BEND1LOC)
	$miss(CantClimb, South21, CantClimb, North21, 0, 0, 0, 0, 0, 0);
    Else If ((RiverLoc > BEND1LOC) & (RiverLoc < BEND2LOC))
	$miss(CantClimb, CantClimb, South21, North21, 0, 0, 0, 0, 0, 0);
    Else If (RiverLoc == BEND2LOC)
	$miss(CantClimb, North21, South21, CantClimb, 0, 0, 0, 0, 0, 0);
    Else If (RiverLoc == BEND2LOC)
	$miss(South21, North21, CantClimb, CantClimb, 0, 0, 0, 0, 0, 0);
    Else // RiverLoc < BEND1LOC
	$miss(North21, South21, CantClimb, CantClimb, 0, 0, 0, 0, 0, 0);
}

desert(ACTION) = Proc()
{
    Hitms(n, desert, 0);
    Hitms(s, desert, 0);
    Hitms(e, desert, 0);
    Hitms(w, desert, 0);
    Hitms(ne, desert, 0);
    Hitms(nw, desert, 0);
    Hitms(se, desert, 0);
    Hitms(sw, desert, 0);
}

field(ACTION) = Proc()
{
    Hitms(n, 0, ENDGAME);
}