/*** 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);
}