/*
 *      ADVMOVE.C - Collosal Cave Adventure motion routines
 *      (C) 1986 Ravi Bhavnani
 *      All rights reserved
 *
 *      go()            goes to a loc on a specific command
 *      travel()        called by any verb that implies motion
 */

#include "adv.h"


go (x, y)
int     x, y;
/*
 *      GO TO LOCATION y ON COMMAND x.
 */
{
        if (arg1==x || arg2==x)
           here = y;
}


kwd (x)
int     x;
/*
 *      RETURN TRUE IF x APPEARS IN INPUT.
 */
{
        return (arg1==x || arg2==x);
}


travel()
/*
 *      ATTEMPT TO CHANGE LOCATION.
 */
{
int     ok2saynoway,    /* 1 = ok to say "no way in that direction" */
        fakemove,       /* 1 = we moved, although we really didn't  */
        derf;

	dbg ("travel()\n");

        moved = 0;
        fakemove = 0;
        ok2saynoway = 1;

        /* CHANGE COMMANDS LIKE "inside <location>" TO "<location>" */

        if (isdir(arg1) && isdir(arg2))
           {
             arg1 = arg2;
             arg2 = null;
             inword = 1;
           }

        /* MAKE SURE IT'S A VALID COMMAND */

        if (arg1==move)
           if (arg2 == null)
              {
                mtext (whichway, word1);
                RETURN;
              }
           else
              if (isdir(arg2))
                 {
                   arg1 = arg2;
                   arg2 = null;
                 }
              else
                 {
                   msay (what);
                   RETURN;
                 }
        else
           if (arg2!=move && arg2!=null)
              {
                msay (huh);
                RETURN;
              }

        /* CHECK FOR SPECIAL MOTION "go back" */

        if (arg1==back)
           {
	     /* CAN'T GO BACK FROM noback ROOMS OR IF WE'VE USED A MAGIC WORD TO TRAVEL */

             if (noback[here] || here==mists ||
	         (here==y2 && prevloc==building) ||
	         (here==debris && prevloc==building) ||
	         (here==building && (prevloc==y2 || prevloc==debris)))
                {
                  msay (snidely);
                  ok2desc = 0;
                }
             else
                {
                  derf = here;
                  here = prevloc;
                  prevloc = derf;
                  moved = 1;
                }
             RETURN;
           }
        
        /* FOLLOWING CODE ASSUMES DIRECTIONAL VERB IS IN arg1 */

        prevloc = here;
        switch (here)
        {
          case road:
            go (west, hill);
            go (up, hill);
            go (entrance, building);
            go (inside, building);
            go (east, building);
            go (downstream, valley);
            go (gully, valley);
            go (stream, valley);
            go (south, valley);
            go (down, valley);
            go (north, forest);
            go (east, forest);
            go (_depression, depression);
            go (_building, building);
            go (_road, hill);
            break;

          case hill:
            go (_road, road);
            go (_building, road);
            go (front, road);
            go (east, road);
            go (_forest, forest);
            go (south, forest);
	    if (extended)
	       {
	         if (kwd(down))
                    go (north, hayfield);
	         here = chance(50) ? road : hayfield;
	       }
	    else
	       go (down, road);
            break;

	  case hayfield:
	    go (south, hill);
	    go (out, hill);
	    go (back, hill);
	    go (up, hill);
	    if (kwd(inside))
	       {
	         ok2saynoway = 0;
	         if (!seen[needle])
	            {
	              msay (haystack);
	              invisible [needle] = 0;
	              ok2desc = 0;
	            }
	         else
	            msay (haybounce);
	       }
	    break;

          case building:
            go (_road, road);
            go (out, road);
            go (outdoors, road);
            go (west, road);
            if (kwd(stream) || kwd(downstream))
               {
                 msay (pipefit);
                 ok2saynoway = 0;
                 here = building;
               }
	    if (extended)
	       go (north, nearstove);
            break;

          case valley:
            go (upstream, road);
            go (_building, road);
            go (north, road);
            go (_forest, forest);
            go (east, forest);
            go (west, forest);
            go (up, forest);
            go (_depression, depression);
            if (closure < 2)
               {
                 go (south, slit);
                 go (down, slit);
                 go (downstream, slit);
               }
            else
               {
                 go (south, fake_slit);
                 go (down, fake_slit);
                 go (downstream, fake_slit);
               }
            break;

          case forest:
            go (_valley, valley);
            go (east, valley);
            go (down, valley);
            go (west, forest);
            go (south, forest);
            if (chance(50))
               {
                 go (_forest, forest);
                 go (front, forest);
                 go (north, forest);
               }
            else
               {
                 go (_forest, forest2);
                 go (front, forest2);
                 go (north, forest2);
               }
            break;

          case forest2:
            go (_road, road);
            go (north, road);
            go (_valley, valley);
            go (east, valley);
            go (west, valley);
            go (down, valley);
            go (_forest, forest);
            go (south, forest);
            break;

          case slit:
            go (_building, road);
            go (upstream, valley);
            go (north, valley);
            go (_forest, forest);
            go (east, forest);
            go (west, forest);
            go (downstream, depression);
            go (bed, depression);
            go (rock, depression);
            go (south, depression);
            if (kwd(_slit) || kwd(stream) || kwd(down) || kwd(entrance) || kwd(inside))
               {
                 msay (dontfitslit);
                 ok2saynoway = 0;
                 here = slit;
               }
            break;

          case fake_slit:
            go (_building, road);
            go (upstream, valley);
            go (north, valley);
            go (_forest, forest);
            go (east, forest);
            go (west, forest);
            go (downstream, depression);
            go (rock, depression);
            go (bed, depression);
            go (south, depression);
            if (kwd(_slit) || kwd(stream) || kwd(down) || kwd(entrance) || kwd(inside))
               {
                 closure = 5;   /* victory! */
                 lsay (treasureroom);
                 quitting = 0;
                 finis();
               }
            break;

          case depression:
            go (_forest, forest); /* forest */
            go (east, forest2);
            go (west, forest);
            go (south, forest2);
            go (_building, road);
            if (kwd(upstream) || kwd(gully) || kwd(north) || kwd(_slit))
               if (closure < 2)
                  here = slit;
               else
                  here = fake_slit;
            if (kwd(inside) || kwd(down) || kwd(cave))
               {
                 if (val[grate]==1)
                    here = incave;
                 else
                    {
                      msay (cantpasslock);
                      ok2saynoway = 0;
                      here = depression;
                    }
                  break;
               }
            break;

          case incave:
            if (kwd(up) || kwd(out) || kwd(outdoors) || kwd(surface))
               {
                 if (val[grate] == 1)
                    here = depression;
                 else
                    {
                      msay (cantpasslock);
                      here = incave;
                      ok2saynoway = 0;
                    }
                 break;
               }
            go (crawl, cobbles);
            go (_cobbles, cobbles);
            go (inside, cobbles);
            go (west, cobbles);
            go (_pit, pit);
            go (_debris, debris);
            break;

          case cobbles:
            go (out, incave);
            go (surface, incave);
            go (entrance, incave);
            go (east, incave);
            go (inside, debris);
            go (west, debris);
            go (_debris, debris);
            go (_pit, pit);
            break;

          case debris:
            go (entrance, incave);
            go (_cobbles, cobbles);
            go (passage, cobbles);
            go (east, cobbles);
            go (inside, canyon);
            go (up, canyon);
            go (west, canyon);
            go (_pit, pit);
            if (kwd(_depression))
               if (val[grate] == 1)
                  here = depression;
               else
                  {
                    ok2saynoway = 0;
                    here = incave;
                    msay (cantpasslock);
                  }
            break;

          case canyon:
            go (entrance, incave);
            go (down, debris);
            go (east, debris);
            go (_debris, debris);
            go (inside, birdchamber);
            go (up, birdchamber);
            go (west, birdchamber);
            go (_pit, pit);
            if (kwd(_depression))
               if (val[grate] == 1)
                  here = depression;
               else
                  {
                    ok2saynoway = 0;
                    here = incave;
                    msay (cantpasslock);
                  }
            break;

          case birdchamber:
            go (entrance, incave);
            go (_debris, debris);
            go (east, canyon);
            go (passage, pit);
            go (_pit, pit);
            go (west, pit);
            if (kwd(_depression))
               if (val[grate] == 1)
                  here = depression;
               else
                  {
                    ok2saynoway = 0;
                    here = incave;
                    msay (cantpasslock);
                  }
            break;

          case pit:
            if (kwd(down) || kwd(_pit))
               {
                 here = mists;
                 if (invisible[steps])
                    {
                      msay (brokenneck);
                      coroner();
                      break;
                      ok2saynoway = 0;
                      ok2desc = 0;
                    }
                 break;
               }
            go (entrance, incave);
            go (_debris, debris);
            go (passage, birdchamber);
            go (east, birdchamber);
            if (kwd(west) || kwd(crack))
               {
                 msay (mistcrack);
                 ok2saynoway = 0;
                 here = pit;
                 break;
               }
            if (kwd(_depression))
               if (val[grate] == 1)
                  here = depression;
               else
                  {
                    ok2saynoway = 0;
                    ok2desc = 0;
                    here = incave;
                    msay (cantpasslock);
                  }
            break;

          case mists:
            if (invisible[steps] &&
	        (kwd(up) || kwd(_pit) || kwd(dome) || kwd(passage) ||
	         kwd(inside) || kwd(back)))
               {
                 ok2saynoway = 0;
                 ok2desc = 0;
                 msay (unclimbable);
                 break;
               }
            go (up, pit);
            go (dome, pit);
            go (_pit, pit);
            go (left, goldroom);
            go (south, goldroom);
            go (east, sandstone);
            go (hall, eastoffissur);
            go (front, eastoffissur);
            go (west, eastoffissur);
            go (down, mtking);
            go (stairs, mtking);
            go (north, mtking);
            go (_y2, jumble);
            break;

          case eastoffissur:
            go (hall, mists);
            go (east, mists);
            if (kwd(front) || kwd(west) || kwd(cross))
               if (!val[fissure])
                  {
                    msay (nowayacross);
                    ok2saynoway = 0;
                  }
               else
                  here = westoffissur;
            break;

          case goldroom:
            go (hall, mists);
            go (out, mists);
            go (north, mists);
            break;

          case mtking:
            go (stairs, mists);
            go (up, mists);
            go (east, mists);
            if (kwd(north) || kwd(left) || kwd(south) || kwd(right) ||
                kwd(west) || kwd(front) || kwd(sw) || kwd(secret) ||
                kwd(nw) || kwd(se) || kwd(ne) || kwd(down))
                if (near(snake))
                   {
                     ok2saynoway = 0;
                     msay (snakeblocks);
                     here = mtking;
                   }
                else
                   {
                     go (north, lownspassage);
                     go (left, lownspassage);
                     go (south, southside);
                     go (right, southside);
                     go (west, westside);
                     go (front, westside);
                     go (down, vault);
                     go (ne, morion);
                     go (nw, corrid_3);
                     go (se, corrid_1);
                     go (secret, secretew_tite);
                     if (kwd(sw))
                        if (chance(35))
                           here = secretew_tite;
                        else
                           {
                             msay (youdidntmove);
                             ok2saynoway = 0;
                             here = mtking;
                           }
                   }
            break;

          case wend2pit:
            go (east, eend2pit);
            go (cross, eend2pit);
	    go (_slab, slab);
            go (west, slab);
            go (down, westpit);
            go (_pit, westpit);
            if (kwd(hole))
               {
                 msay (too_far_up);
                 ok2saynoway = 0;
                 here = wend2pit;
               }
            break;

          case eastpit:
            go (up, eend2pit);
            go (out, eend2pit);
            break;

          case westpit:
            go (up, wend2pit);
            go (out, wend2pit);
            break;

          case westoffissur:
            go (west, wendmists);
            if (kwd(front) || kwd(cross) || kwd(east))
               {
                 if (val[fissure])
                    here = eastoffissur;
                 else
                    {
                      msay (nowayacross);
                      ok2saynoway = 0;
                    }
                 break;
               }
            if (kwd(north))
               {
                 msay (mistcrawl);
                 here = wendmists;
                 ok2desc = 0;
               }
            break;

          case lownspassage:
            go (hall, mtking);
            go (out, mtking);
            go (south, mtking);
            go (north, y2);
            go (_y2, y2);
            go (down, dirty);
            go (hole, dirty);
            break;

          case southside:
            go (hall, mtking);
            go (out, mtking);
            go (north, mtking);
            break;

          case westside:
            go (hall, mtking);
            go (out, mtking);
            go (east, mtking);
            go (west, crossover);
            go (up, crossover);
            break;

          case y2:
            go (south, lownspassage);
            go (east, jumble);
            go (west, window);
	    go (_plover, plover);
            break;

          case jumble:
            go (down, y2);
            go (_y2, y2);
            go (up, mists);
            break;

          case window:
            go (east, y2);
            go (_y2, y2);
            break;

          case dirty:
            go (east, brink);
            go (crawl, brink);
            go (up, lownspassage);
            go (hole, lownspassage);
            go (west, dusty);
            go (_bedquilt, bedquilt);
            break;

          case brink:
            go (west, dirty);
            go (crawl, dirty);
            go (down, streampit);
            go (_pit, streampit);
            break;

          case streampit:
            go (up, brink);
            go (out, brink);
            if (kwd(_slit) || kwd(stream) || kwd(down) || kwd(downstream) || kwd(upstream))
               {
                 msay (dontfitslit);
                 ok2saynoway = 0;
                 break;
               }
            break;

          case dusty:
            go (east, dirty);
            go (passage, dirty);
            go (down, complex);
            go (_bedquilt, bedquilt);
            break;

          case wendmists:
            go (south, mazea_1);
            go (down, mazea_1);
            go (passage, mazea_1);
            go (east, westoffissur);
            go (west, longhalleast);
            go (crawl, longhalleast);
            if (kwd(north))
               {
                 msay (mistcrawl);
                 ok2saynoway = 0;
                 ok2desc = 0;
                 here = westoffissur;
               }
            break;

          case mazea_1:
            go (up, wendmists);
            if (kwd(north))
               {
                 fakemove = 1;
                 break;
               }
            go (east, mazea_2);
            go (south, mazea_4);
            go (west, mazea_18);
            break;

          case mazea_2:
            go (west, mazea_1);
            go (south, mazea_3);
            go (east, mazea_4);
            break;

          case mazea_3:
            go (east, mazea_2);
            go (down, mazea_7);
            go (south, mazea_9);
            go (north, mazea_20);
            break;

          case mazea_4:
            go (west, mazea_1);
            go (north, mazea_2);
            go (east, mazea_5);
            go (south, mazea_6);
            go (up, mazea_25);
            go (down, mazea_25);
            break;

          case mazea_5:
            go (west, mazea_4);
            go (out, mazea_4);
            break;

          case mazea_6:
            go (east, mazea_4);
            go (out, mazea_4);
            break;

          case mazea_7:
            go (up, mazea_3);
            go (out, mazea_3);
            break;

          case mazea_8:
            go (east, mazea_9);
            go (west, mazea_10);
            break;

          case mazea_9:
            go (east, mazea_3);
            go (west, mazea_8);
            go (down, mazea_10);
            go (south, mazea_11);
            break;

          case mazea_10:
            go (west, mazea_8);
            go (up, mazea_9);
            go (east, mazea_11);
            go (south, mazea_12);
            break;

          case mazea_11:
            go (west, mazea_9);
            go (east, mazea_10);
            if (kwd(south))
               {
                 fakemove = 1;
                 break;
               }
            go (up, mazea_12);
            go (north, mazea_14);
            go (down, mazea_24);
            break;

          case mazea_12:
            go (west, mazea_10);
            go (north, mazea_11);
            go (south, mazea_13);
            break;

          case mazea_13:
            go (west, mazea_12);
            go (out, mazea_12);
            break;

          case mazea_14:
            go (west, mazea_11);
            if (kwd(north))
               {
                 fakemove = 1;
                 break;
               }
            go (down, mazea_15);
            go (east, mazea_16_pit);
            break;

          case mazea_15:
            go (up, mazea_14);
            go (out, mazea_14);
            break;

          case mazea_16_pit:
            go (down, birdchamber);
            go (west, mazea_14);
            go (south, mazea_17);
            go (north, mazea_21);
            go (east, mazea_22);
            break;

          case mazea_17:
            go (east, mazea_16_pit);
            go (out, mazea_16_pit);
            break;

          case longhalleast:
            go (east, wendmists);
            go (up, wendmists);
            go (crawl, wendmists);
            go (west, longhallwest);
            go (north, crossover);
            go (down, crossover);
            go (hole, crossover);
            break;

          case longhallwest:
            go (east, longhalleast);
            go (north, crossover);
            go (south, mazed_107);
            break;

          case crossover:
            go (west, longhalleast);
            go (north, deadend1);
            go (east, westside);
            go (south, longhallwest);
            break;

          case deadend1:
            go (south, crossover);
            go (out, crossover);
            break;

          case complex:
            go (up, dusty);
            go (west, bedquilt);
            go (_bedquilt, bedquilt);
            go (north, shell);
            go (east, anteroom);
            break;

          case bedquilt:
	    go (_slab, slab);
	    go (_low, low);
            go (east, complex);
            go (west, swiss);
            if (kwd(north) || kwd(south) || kwd(up) || kwd(down))
               if (chance(65))
                  {
                    msay (crawl_cavein);
                    ok2saynoway = 0;
                    break;
                  }
               else
                  {
                    go (down, anteroom);
                    if (chance(75))
                       {
                         go (north, low);
                         go (up, dusty);
                         go (south, slab);
                       }
                    else
                       {
                         go (north, secretjunction);
                         go (up, secretnspas);
                         go (south, tallewcnyn);
                       }
                    break;
                  }
              if (kwd(nw))
                 if (chance(50))
                    here = oriental;
                 else
                    {
                      msay (youdidntmove);
                      ok2saynoway = 0;
                    }
            break;

          case swiss:
            go (ne, bedquilt);
            go (west, eend2pit);
            go (east, soft);
	    go (_oriental, oriental);
            if (kwd(nw))
               if (chance(65))
                  here = oriental;
               else
                  {
                    msay (youdidntmove);
                    ok2saynoway = 0;
                  }
            else
               if (kwd(south))
                  if (chance(65))
                     here = tallewcnyn;
                  else
                     {
                       msay (youdidntmove);
                       ok2saynoway = 0;
                     }
            break;

          case eend2pit:
            go (east, swiss);
            go (west, wend2pit);
            go (cross, wend2pit);
            go (down, eastpit);
            go (_pit, eastpit);
            break;

          case slab:
            go (south, wend2pit);
            go (up, secretnscyn);
            go (north, bedquilt);
            break;

          case secretnscyn:	/* dragon is here - allow him to retreat  */
	    if (prevloc==slab)	/* to the room he came from, but no other */
	       {
	         go (down, slab);
	         go (_slab, slab);
	       }
	    if (prevloc==secretcynne1)
	       go (south, secretcynne1);
	    go (out, prevloc);
	    if (kwd(north) || kwd(gully) || kwd(south) || kwd(down))
	       if (near(dragon) && !val[dragon])
	          {
	            msay (past_dragon);
	            ok2saynoway = 0;
	          }
	       else
	          {
	            go (_slab, slab);
	            go (down, slab);
                    go (north, mirrorcnyn);
                    go (gully, reservoir);
                    go (south, secretcynne1);
	          }
            break;

          case secretnspas:
            go (north, secretjunction);
            go (down, bedquilt);
            go (passage, bedquilt);
            go (south, stalact);
            break;

          case secretjunction:
            go (se, bedquilt);
            go (south, secretnspas);
            go (north, window2);
            break;

          case low:
            go (_bedquilt, bedquilt);
            go (sw, sloping);
            go (north, deadend2);
            go (se, oriental);
            break;

          case deadend2:
            go (south, low);
            go (crawl, low);
            go (out, low);
	    go (_low, low);
            break;

          case secretew_tite:
            go (east, mtking);
            go (down, nscanyonwide);
	    go (west, secretcynne1);
/*	    go (west, val[dragon] ? secretcynne1 : secretcynne2); */
            break;

          case nscanyonwide:
            go (south, tighterstill);
            go (north, tallewcnyn);
            break;

          case tighterstill:
            go (north, nscanyonwide);
            break;

          case tallewcnyn:
            go (east, nscanyonwide);
            go (west, deadend3);
            go (north, swiss);
            go (crawl, swiss);
            break;

          case deadend3:
            go (south, tallewcnyn);
            break;

          case mazea_18:
            go (north, mazea_1);
            if (kwd(west) || kwd(south))
               {
                 fakemove = 1;
                 break;
               }
            go (east, mazea_19);
            break;

          case mazea_19:
            go (west, mazea_18);
            go (out, mazea_18);
            break;

          case mazea_20:
            go (south, mazea_3);
            go (out, mazea_3);
            break;

          case mazea_21:
            go (south, mazea_16_pit);
            go (east, mazea_22);
            go (west, mazea_23);
            break;

          case mazea_22:
            go (north, mazea_16_pit);
            go (west, mazea_21);
            go (nw, mazea_26);
            break;

          case mazea_23:
            go (east, mazea_21);
            go (out, mazea_21);
            break;

          case mazea_24:
            go (up, mazea_11);
            go (out, mazea_11);
            break;

          case mazea_25:
            go (up, mazea_4);
            go (down, mazea_4);
            break;

          case mazea_26:
            go (se, mazea_22);
            break;

          case narrowcorrid:
            go (down, westpit);
            go (east, westpit);
            go (west, giant);
            break;

          case incline:
            go (north, cavern);
            go (passage, cavern);
            go (down, low);
            break;

          case giant:
            go (south, narrowcorrid);
            go (east, tunnel_1);
            go (north, immensenspass);
            break;

          case immensenspass:
            go (south, giant);
            go (passage, giant);
            if (kwd(north) || kwd(inside))
               if (val[door])
                  here = cavern;
               else
                  {
                    msay (doorneedsoil);
                    ok2saynoway = 0;
                  }
            break;

          case cavern:
            go (south, immensenspass);
            go (out, immensenspass);
            go (west, incline);
            if (kwd(down))
               {
                 arg2 = null;
                 jump_proc();
                 ok2saynoway = 0;
               }
            break;

          case soft:
            go (west, swiss);
            go (out, swiss);
            break;

          case oriental:
            go (se, swiss);
            go (west, low);
	    go (_low, low);
            go (crawl, low);
            go (up, misty);
            go (north, misty);
            break;

          case misty:
            go (south, oriental);
            go (west, alcove);
            break;

          case alcove:
            go (nw, misty);
            if (kwd(east) || kwd(passage))
               if (!invct)
                  here = plover;
               else
                  if (invct == 1)
                     if (carrying(emerald))
                        here = plover;
                     else
                        {
                          msay (wont_fit);
                          ok2saynoway = 0;
                        }
                  else
                     {
                       msay (wont_fit);
                       ok2saynoway = 0;
                     }
            break;

          case plover:
            go (ne, dark);
            if (kwd(_plover))
               {
                 if (carrying(emerald))
                    dropit (emerald);
                 here = y2;
                 break;
               }
            if (kwd(west) || kwd(passage))
               if (!invct)
                  here = alcove;
               else
                  if (invct == 1)
                     if (carrying(emerald))
                        here = alcove;
                     else
                        {
                          msay (wont_fit);
                          ok2saynoway = 0;
                        }
                  else
                     {
                       msay (wont_fit);
                       ok2saynoway = 0;
                     }
            break;

          case dark:
            go (south, plover);
            go (_plover, plover);
            go (out, plover);
            break;

          case arched:
            go (down, shell);
            go (up, arch_cor_1);
            go (east, arch_cor_1);
            break;

          case shell:
            go (up, arched);
            go (hall, arched);
            go (down, raggedcorrid);
            if (kwd(south))
               if (carrying(clam))
                  {
                    msay (clam2big);
                    ok2saynoway = 0;
                  }
               else
                  if (carrying(oyster))
                     {
                       msay (oyster2big);
                       ok2saynoway = 0;
                     }
                  else
                     here = complex;
            break;

          case raggedcorrid:
            go (up, shell);
	    go (_shell, shell);
            go (down, culdesac);
            break;

          case culdesac:
            go (up, raggedcorrid);
            go (out, raggedcorrid);
	    go (_shell, shell);
            break;

          case anteroom:
            go (up, complex);
            go (west, bedquilt);
            go (east, wittsend);
            break;

          case wittsend:
            go (west, wittsend);
            if (kwd(north) || kwd(south) || kwd(east) || kwd(up) || kwd(down) ||
                kwd(ne) || kwd(nw) || kwd(se) || kwd(sw))
                if (chance(95))
                   {
                     fakemove = 1;
                     here = wittsend;
                   }
                else
                   here = anteroom;
            break;

          case mirrorcnyn:
            go (south, secretnscyn);
            go (north, reservoir);
            break;

          case window2:
            go (west, secretjunction);
            break;

          case stalact:
            go (north, secretnspas);
            if (kwd(down))
               if (chance(40))
                  here = mazea_9;
               else
                  if (chance(50))
                     here = mazea_12;
                  else
                     here = mazea_4;
            break;

          case reservoir:
            go (south, mirrorcnyn);
            go (out, mirrorcnyn);
            if (kwd(north) || kwd(cross))
               {
                 msay (cant_swim);
                 ok2saynoway = 0;
               }
            break;

          case reservoir_n:
            go (north, warm);
            go (passage, warm);
            if (kwd(south) || kwd(cross))
               if (near(turtle))
                  {
                    msay (turtle_back);
                    here = reservoir;
                    ok2desc = 0;
                  }
               else
                  {
                    msay (cant_swim);
                    ok2saynoway = 0;
                  }
            if (here!=prevloc)
	       apport (turtle, limbo);
            break;

          case warm:
	    go (south, reservoir_n);
	    go (_reservoir, reservoir_n);
	    go (ne, balcony);
	    go (_balcony, balcony);
	    break;

          case balcony:
	    go (west, warm);
	    go (out, warm);
	    go (_reservoir, reservoir_n);
	    break;

	  /*
	   * Troll states:
	   *
	   *   0 = wants a bribe
	   *   1 = has just been bribed - disappears
	   *   2 = has just let you cross (in either direction)
	   *   3 = (description-only state)
	   *   4 = has just been scared away by the bear
	   *   5 = (description-only state)
	   */

          case swofchasm:
	    go (sw, sloping);
	    go (_balcony, sloping);
	    if (kwd(ne) || kwd(cross))

	    /* The following code is identical to the code for neofchasm. */

	       if (val[chasm])
	          {
	            msay (no_bridge);		    /* "There is no longer any way across the chasm." */
	            ok2saynoway = 0;
	          }
	       else
		  switch (val[troll])
		  {
		    case 0:
		      apport (troll, here);
		      msay (troll_sez_no);	    /* "The troll refuses to let you cross." */
		      ok2saynoway = 0;
		      break;

		    case 1:
		      if (special1[troll])	    /* Egg toll paid, FFFF done, trying to cross */
		         {
			   if (carrying(bear))
			      {
			        msay (revenge);		    /* Troll zaps bear and adventurer */
				apport (bear, limbo);
				val[chasm] = 1;
			      }
			   else
			      {
				val [chasm] = 2;
				msay (revenge_1);	    /* Troll zaps adventurer */
			      }
			   apport (troll2, limbo);
			   here = ylem;
			   coroner();
			   RETURN;
			 }
		      else			    /* Toll paid, FFFF not done, trying to cross */
		         {
			   if (carrying(bear))
		              {
	                        msay (bear_bridge);		/* Just as you reach the other side, the bridge buckles	     */
	                        val[chasm] = 1;			/* beneath the weight of the bear, which was still following */
	                        apport (troll2, limbo);		/* you around. You scramble desperately for support, but as  */
	                        here = ylem;			/* the bridge collapses you stumble back and fall into the   */
	                        coroner();			/* chasm.                                                    */
	                        RETURN;
			      }
		           else
		              {
			        val[troll] = 2;			/* No description for this state */
				here = (here == swofchasm ? neofchasm : swofchasm);
				special2 [troll] = (here == neofchasm);
			      }
			 }
		      break;

		    case 2:
		      osay (troll, 3);		    /* Steps out from beneath the bridge and demands more treasure */
		      val[troll] = 0;
		      apport (troll, here);
		      apport (troll2, limbo);
		      ok2saynoway = 0;
		      break;

		    case 4:			    /* Crossing after scaring troll with bear */
		      if (carrying(bear))
			 {
			   apport (bear, limbo);
			   val [chasm] = 1;
			   if (special1[troll])
			      msay (revenge);	    /* Troll zaps bear and adventurer */
			   else
			      msay (bear_bridge);   /* Bear and adventurer fall into the chasm */
		           apport (troll2, limbo);
		           here = ylem;
		           coroner();
		           RETURN;
			 }
		      else
		         {
			   if (special1[troll])
			      {
			        msay (revenge_1);   /* Troll zaps adventurer */
				val[chasm] = 2;
				here = ylem;
				coroner();
				RETURN;
			      }
			   else
			      {
			        val[troll] = 2;			/* No description for this state */
			        here = (here == swofchasm ? neofchasm : swofchasm);
			      }
			 }
		      break;

		    default:
		      printf ("GLITCH!  Troll(%d) at %d - please report this bug.\n", val[troll], here);
		      ok2saynoway = 0;
		      break;
		  }
	    break;

          case neofchasm:

	    /* The only way to get to the NE end of the troll bridge is to cross from the SW side */

	    go (ne, corridor);
	    go (_fork, fork);
	    go (view, breathtaker);
	    go (_barren, barren);

	    if (kwd(sw) || kwd(cross))

	    /* The following code is identical to the code for swofchasm. */

	       if (val[chasm])
	          {
	            msay (no_bridge);		    /* "There is no longer any way across the chasm." */
	            ok2saynoway = 0;
	          }
	       else
		  switch (val[troll])
		  {
		    case 0:
		      apport (troll, here);
		      msay (troll_sez_no);	    /* "The troll refuses to let you cross." */
		      ok2saynoway = 0;
		      break;

		    case 1:
		      if (special1[troll])	    /* Egg toll paid, FFFF done, trying to cross */
		         {
			   if (carrying(bear))
			      {
			        msay (revenge);		    /* Troll zaps bear and adventurer */
				apport (bear, limbo);
				val[chasm] = 1;
			      }
			   else
			      {
				val [chasm] = 2;
				msay (revenge_1);	    /* Troll zaps adventurer */
			      }
			   apport (troll2, limbo);
			   here = ylem;
			   coroner();
			   RETURN;
			 }
		      else			    /* Toll paid, FFFF not done, trying to cross */
		         {
			   if (carrying(bear))
		              {
	                        msay (bear_bridge);		/* Just as you reach the other side, the bridge buckles	     */
	                        val[chasm] = 1;			/* beneath the weight of the bear, which was still following */
	                        apport (troll2, limbo);		/* you around. You scramble desperately for support, but as  */
	                        here = ylem;			/* the bridge collapses you stumble back and fall into the   */
	                        coroner();			/* chasm.                                                    */
	                        RETURN;
			      }
		           else
		              {
			        val[troll] = 2;			/* No description for this state */
				here = (here == swofchasm ? neofchasm : swofchasm);
				special2 [troll] = (here == neofchasm);
			      }
			 }
		      break;

		    case 2:
		      osay (troll, 3);		    /* Steps out from beneath the bridge and demands more treasure */
		      val[troll] = 0;
		      apport (troll, here);
		      apport (troll2, limbo);
		      ok2saynoway = 0;
		      break;

		    case 4:			    /* Crossing after scaring troll with bear */
		      if (carrying(bear))
			 {
			   apport (bear, limbo);
			   val [chasm] = 1;
			   if (special1[troll])
			      msay (revenge);	    /* Troll zaps bear and adventurer */
			   else
			      msay (bear_bridge);   /* Bear and adventurer fall into the chasm */
		           apport (troll2, limbo);
		           here = ylem;
		           coroner();
		           RETURN;
			 }
		      else
		         {
			   if (special1[troll])
			      {
			        msay (revenge_1);   /* Troll zaps adventurer */
				val[chasm] = 2;
				here = ylem;
				coroner();
				RETURN;
			      }
			   else
			      {
			        val[troll] = 2;			/* No description for this state */
			        here = (here == swofchasm ? neofchasm : swofchasm);
			      }
			 }
		      break;

		    default:
		      printf ("GLITCH!  Troll(%d) at %d - please report this bug.\n", val[troll], here);
		      ok2saynoway = 0;
		      break;
		  }
	    break;

          case sloping:
	    go (down, low);
	    go (up, swofchasm);
	    go (chasm, swofchasm);
	    go (out, low);
	    break;

          case secretcynne1:
	    go (north, secretnscyn);
	    go (out, secretnscyn);
	    go (front, secretew_tite);
	    go (east, secretew_tite);
	    break;

          case secretcynne2:		/* no way to get here */
	    go (east, secretew_tite);
	    go (out, secretew_tite);
	    if (kwd(front) || kwd(north))
	       if (near(dragon) && !val[dragon])
	          {
	            msay (past_dragon);
	            ok2saynoway = 0;
	          }
	       else
	          here = secretnscyn;
	    break;

          case corridor:
	    go (chasm, neofchasm);
	    go (west, neofchasm);
	    go (east, fork);
	    go (_fork, fork);
	    go (view, breathtaker);
	    go (_barren, barren);
	    break;

          case fork:
	    go (chasm, neofchasm);
	    go (west, corridor);
	    go (ne, warmjunction);
	    go (left, warmjunction);
	    go (se, limestone);
	    go (right, limestone);
	    go (down, limestone);
	    go (view, breathtaker);
	    go (_barren, barren);
	    break;

          case warmjunction:
	    go (south, fork);
	    go (_fork, fork);
	    go (north, breathtaker);
	    go (view, breathtaker);
	    go (east, boulders);
	    go (crawl, boulders);
	    break;

          case breathtaker:
	    go (south, warmjunction);
	    go (passage, warmjunction);
	    go (out, warmjunction);
	    go (_fork, fork);
	    if (kwd(down))		/* LET HIM PLUMMET TO */
	       {			/* TO A PAINFUL DEATH */
	         here = ylem;		
	         splatter();
	         coroner();
	         RETURN;
	       }
	    if (kwd(_valley) || kwd(cross) || kwd(north))
	       if (val[wheatstone] != 2)	/* no bridge */
		  {
	            msay (no_arch);
	            ok2saynoway = 0;
	          }
	       else
	          if (carrying(bear))
	             {
	               msay (leave_bear);	/* archway looks fragile!	*/
	               ok2saynoway = 0;		/* better leave bear		*/
	             }
	          else
	             if (carrying(ring))	/* need ring to cross		*/
	                {
	                  if (!visited[faces])
	                     msay (fumes_miss);
	                  here = faces;
	                }
	             else
	                {
	                  msay (fumes_burn);	/* death */
	                  here = ylem;
	                  coroner();
	                  RETURN;
	                }
	    break;

	  case boulders:
	    go (west, warmjunction);
	    go (out, warmjunction);
	    go (crawl, warmjunction);
	    go (_fork, fork);
	    go (view, breathtaker);
	    break;

          case limestone:
	    go (north, fork);
	    go (up, fork);
	    go (south, barren);
	    go (down, barren);
	    go (_barren, barren);
	    go (view, breathtaker);
	    break;

          case barren:
	    go (west, limestone);
	    go (up, limestone);
	    go (_fork, fork);
	    go (east, bearhere);
	    go (inside, bearhere);
	    go (_barren, bearhere);
	    go (view, breathtaker);
	    break;

          case bearhere:
	    go (west, barren);
	    go (out, barren);
	    go (_fork, fork);
	    go (view, breathtaker);
	    break;

          case limbo:
	    go (out, building);		/* kludge */
	    break;

          case sandstone:
	    go (west, mists);
	    go (out, mists);
	    break;

          case morion:
	    go (south, mtking);
	    go (out, mtking);
	    break;

          case vault:
	    if (kwd(up) || kwd(out) || kwd(north))
	       if (val[safe]==1)
	          {
	            msay (safe_blocks);
	            ok2saynoway = 0;
	          }
	       else
	          here = mtking;
	    if (kwd(inside))
	       if (val[safe]==1)
	          {
	            safeexit = here;
	            here = insafe;
	          }
	       else
	          {
	            msay (cantentersafe);
	            ok2saynoway = 0;
	          }
	    break;

          case insafe:
	    go (out, safeexit);
	    break;

          case corrid_1:
	    go (south, mtking);
	    go (north, corrid_2);
	    break;

          case corrid_2:
	    go (south, corrid_1);
	    go (west, corrid_1);
	    go (north, tool);
	    go (east, tool);
	    break;

          case tool:
	    go (out, corrid_2);
	    go (south, corrid_2);
	    break;

          case corrid_3:
	    go (south, mtking);
	    go (north, spherical);
	    go (east, cubicle);
	    break;

          case cubicle:
	    go (out, corrid_3);
	    go (south, corrid_3);
	    break;

          case spherical:
	    go (out, corrid_3);
	    go (north, corrid_3);
	    break;

          case tunnel_1:
	    go (south, giant);
	    go (north, glassy);
	    break;

          case glassy:
	    go (south, tunnel_1);
	    if (kwd(north) || kwd(_lair))
	       if (near(ogre))
	          {
	            ok2saynoway = 0;
	            msay (ogre_blocks);
	          }
	       else
	          here = lair;
	    break;

          case lair:
	    go (east, brink_1);
	    go (west, glassy);
	    break;

          case brink_1:
	    go (north, lair);
	    go (west, brink_2);
	    go (east, brink_3);
	    break;

          case brink_2:
	    go (north, brink_1);
	    go (se, ice);
	    break;

          case ice:
	    go (nw, brink_2);
	    if (kwd(down) || kwd(east))
	       {
	         msay (oof);
	         here = slide;
	       }
	    break;

/*	ICE-CAVES:

[this way out]                           ENTER
O                                          |
U--   	 -28      -21       -14	      -7-- |
T  \    /   \    /   \     /   \     /    \|
   35--29   27  22    18--15   13   8	 [slide]
    |  |      \ |     |   |     |   |      |
   34  |       \|     |   |     |   |      |
     \ |   26---23    19  16   11---9   6  1  4
      \|    |   |     |   |     |   |   |  |  |
   33- 30   |   |     |   |     |   |   |  |  |
    |  |   25---24    20  17   12   10  5--2--3
   32  |              A
     \ |
      \|
       31

*/
          case slide:
	    go (south, icecave_1);
	    go (nw, icecave_7);
	    if (kwd(up) || kwd(north))
	       {
	         ok2saynoway = 0;
	         msay (slide_slippery);
	       }
	    break;

          case icecave_1:
	    go (north, slide);
	    go (south, icecave_2);
	    break;

          case icecave_2:
	    go (north, icecave_1);
	    go (east, icecave_3);
	    go (west, icecave_5);
	    break;

          case icecave_3:
	    go (west, icecave_2);
	    go (north, icecave_4);
	    break;

          case icecave_4:
	    go (south, icecave_3);
	    go (out, icecave_3);
	    break;

          case icecave_5:
	    go (north, icecave_6);
	    go (east, icecave_2);
	    break;

          case icecave_6:
	    go (south, icecave_5);
	    go (out, icecave_5);
	    break;

          case icecave_7:
	    go (se, slide);
	    go (sw, icecave_8);
	    break;

          case icecave_8:
	    go (ne, icecave_7);
	    go (south, icecave_9);
	    break;

          case icecave_9:
	    go (west, icecave_11);
	    go (south, icecave_10);
	    go (north, icecave_8);
	    break;

          case icecave_10:
	    go (north, icecave_9);
	    go (out, icecave_9);
	    break;

          case icecave_11:
	    go (north, icecave_13);
	    go (south, icecave_12);
	    go (east, icecave_9);
	    break;

          case icecave_12:
	    go (north, icecave_11);
	    go (out, icecave_11);
	    break;

          case icecave_13:
	    go (nw, icecave_14);
	    go (south, icecave_11);
	    break;

          case icecave_14:
	    go (sw, icecave_15);
	    go (se, icecave_13);
	    break;

          case icecave_15:
	    go (ne, icecave_14);
	    go (west, icecave_18);
	    go (south, icecave_16);
	    break;

          case icecave_16:
	    go (north, icecave_15);
	    go (south, icecave_17);
	    break;

          case icecave_17:
	    go (north, icecave_16);
	    go (out, icecave_16);
	    break;

          case icecave_18:
	    go (east, icecave_15);
	    go (nw, icecave_21);
	    go (south, icecave_19);
	    break;

          case icecave_19:
	    go (north, icecave_18);
	    go (south, icecave_20);
	    break;

          case icecave_20:		/* pig here */
	    go (north, icecave_19);
	    go (out, icecave_19);
	    break;

          case icecave_21:
	    go (se, icecave_18);
	    go (sw, icecave_22);
	    break;

          case icecave_22:
	    go (ne, icecave_21);
	    go (south, icecave_23);
	    break;

          case icecave_23:
	    go (north, icecave_22);
	    go (nw, icecave_27);
	    go (west, icecave_26);
	    go (south, icecave_24);
	    break;

          case icecave_24:
	    go (north, icecave_24);
	    go (west, icecave_25);
	    break;

          case icecave_25:
	    go (north, icecave_26);
	    go (east, icecave_24);
	    break;

          case icecave_26:
	    go (east, icecave_23);
	    go (south, icecave_25);
	    break;

          case icecave_27:
	    go (nw, icecave_28);
	    go (se, icecave_23);
	    break;

          case icecave_28:
	    go (se, icecave_27);
	    go (sw, icecave_29);
	    break;

          case icecave_29:
	    go (ne, icecave_28);
	    go (west, icecave_35);
	    go (south, icecave_30);
	    break;

          case icecave_30:
	    go (north, icecave_29);
	    go (nw, icecave_34);
	    go (south, icecave_31);
	    go (west, icecave_33);
	    break;

          case icecave_31:
	    go (north, icecave_30);
	    go (nw, icecave_32);
	    break;

          case icecave_32:
	    go (north, icecave_33);
	    go (se, icecave_31);
	    break;

          case icecave_33:
	    go (south, icecave_32);
	    go (east, icecave_30);
	    break;

          case icecave_34:
	    go (north, icecave_35);
	    go (se, icecave_30);
	    break;

          case icecave_35:
	    go (east, icecave_29);
	    go (south, icecave_34);
	    go (nw, icecave_36);
	    break;

          case icecave_36:		/* THURB works from here */
	    go (se, icecave_35);
	    go (back, icecave_36);
	    go (out, icecave_36);
	    break;

          case brink_3:
	    go (north, brink_1);
	    go (ne, crack_1);   
	    go (crack, crack_1);
	    break;

          case crack_1:
	    go (sw, brink_3);
	    go (se, crack_2);
	    break;

          case crack_2:
	    go (west, crack_1);
	    if (kwd(south))
	       if (near(slime))
	          {
	            msay (slimed);
	            coroner();
	            RETURN;
	          }
	       else
	          here = crack_3;
	    break;

          case crack_3:
	    go (north, crack_2);
	    go (south, crack_4);
	    go (crawl, crack_4);
	    break;

          case crack_4:
	    go (north, crack_3);
	    go (out, crack_3);
	    go (crawl, crack_3);
	    break;

          case arch_cor_1:
	    go (west, arched);
	    if (kwd(east))
	       if (val[quicksand]==0 || carrying(clam) || carrying(oyster))
	          {
	            val[quicksand] = 0;
	            if (special1[quicksand])
	               msay (schlurp2);
	            else
	               {
	                 msay (schlurp);
	                 special1[quicksand] = 1;
	               }
	            here = ylem;
	            coroner();
	            RETURN;
	          }
	       else
	          {
	            here = arch_cor_2;
	            val[quicksand] = 0;
	          }
	    break;

          case arch_cor_2:
	    go (north, arch_fork);
	    if (kwd(west))
	       if (!val[quicksand])
	          {
	            if (special1[quicksand])
	               msay (schlurp2);
	            else
	               {
	                 msay (schlurp);
	                 special1[quicksand] = 1;
	               }
	            here = ylem;
	            coroner();
	            RETURN;
	          }
	       else
	          {
	            here = arch_cor_1;
	            val[quicksand] = 0;
	          }
	    break;

          case arch_fork:
	    go (south, arch_cor_2);
	    go (north, fourier);
	    go (east, jonah);
	    break;

          case fourier:
	    go (nw, arch_fork);
	    go (sw, shelf);
	    break;

          case shelf:
	    go (west, fourier);
	    go (down, beach);
	    go (stairs, beach);
	    break;

          case beach:
	    if (kwd(up) || kwd(stairs)) /* || kwd(west)) */
	       {
	         val[dinghy] = 1;
	         here = shelf;
	       }
	    break;

          case jonah:
	    go (south, in_jonah);
	    go (west, arch_fork);
	    break;

          case in_jonah:
	    go (north, jonah);
	    go (out, jonah);
	    break;

          case faces:
	    go (north, by_figure);
	    if (kwd(cross) || kwd(south))
	       if (val[wheatstone] != 2)
	          {
	            msay (no_arch);
	            ok2saynoway = 0;
	          }
	       else
	          if (carrying(ring))
	             if (carrying(sceptre))
	                {
	                  msay (ghost_bang);
	                  here = ylem;
	                  val[wheatstone] = 0;
	                  coroner();
	                  RETURN;
	                }
	             else
	                here = breathtaker;
	          else
	             {
	               msay (fumes_burn);
	               here = ylem;
	               coroner();
	               RETURN;
	             }
	    break;

          case by_figure:
	    if (val[statue]==1)
	       {
	         go (nw, plain_1);
	         go (north, basque_1);
	         go (ne, banshee_1);
	       }
	    go (south, faces);
	    break;

          case plain_1:
	    go (south, by_figure);
	    if (kwd(north))
	       {
	         val[fog] = 0;		/* MAKE THE FOG VISIBLE */
	         apport (fog, plain_2);
	         here = plain_2;
	         ok2desc = 0;		/* SO WE DON'T GET A BLANK ROOM DESCRIPTION */
	       }
	    break;

          case plain_2:

	    /*
	     * THE ONLY WAY TO ESCAPE IS TO SHUT OFF THE LAMP, NOTICE THE
	     * GLOW AND HEAD TOWARDS IT.
	     */

	    if (kwd(north) || kwd(east) || kwd(south) || kwd(west) ||
	        kwd(ne) || kwd(nw) || kwd(se) || kwd(sw))
	       {

	         /* IF HE DROPS ANYTHING IN THE FOG, IT'S GONE FOREVER! */

	         for (derf=MINOBJECTS; (derf<=MAXOBJECTS); derf++)
	             if (derf != fog)
	                if (portable[derf] && where_is[derf]==here && derf!=lamp)
	                   apport (derf, ylem);

	         /* HE CAN ONLY ESCAPE IF HE GOES TO WHERE THE GLOW IS */

	         if (near(glow))
	            if (kwd((val[glow] + east)))
	               {
	                 here = plain_3;
	                 val[fog] = 8;	/* not so obvious */
	               }
	            else
	               break;		/* "no way in that direction" */
	         else
	            {
	              ok2saynoway = 0;
	              moved = 1;	/* so we execute phog() */
	              break;
	            }
	       }
	    break;

          case plain_3:
	    if (kwd(down))
	       {
	         here = nondescript;
/*		 apport (fog, plain_1);   WHY?? */
	         break;
	       }
	    if (kwd(north) || kwd(east) || kwd(south) || kwd(west) ||
	        kwd(ne) || kwd(nw) || kwd(se) || kwd(sw))
	       {
	         here = plain_2;
	         apport (fog, here);
	         val[fog] = 0;		/* so it starts changing again */
	         ok2desc = 0;		/* so we don't say a blank room description */
	         moved = 1;		/* so we execute phog() */
	       }
	    break;

          case nondescript:
	    go (north, pentagram);
	    if (kwd(up) || kwd(south))
	       {
	         apport (fog, plain_2);
	         here = plain_3;
	       }
	    break;

          case pentagram:
	    go (west, nondescript);
	    go (out, nondescript);
	    go (north, chimney);
	    go (crack, chimney);
	    break;

          case chimney:
	    go (up, tube);
	    go (south, pentagram);
	    go (crack, pentagram);
	    break;

          case tube:
	    go (down, chimney);
	    go (south, tube_slide);
	    break;

          case tube_slide:
	    go (north, tube);
	    if (kwd(south) || kwd(down))
	       {
	         msay (oof);
/*	         ok2desc = 0;	*/
	         here = plain_1;
	       }
	    break;

          case basque_1:
	    go (south, by_figure);
	    if (kwd(north))
	       {
	         here = basque_2;
	         if (++val[basilisk] == 1)
	            msay (bas_grumble);
	       }
	    break;

          case basque_2:
	    go (north, basque_fork);
	    if (kwd(south))
	       {
	         if (--val[basilisk] == 0)
	            if (carrying(plate))
	               {
	                 msay (petrify_self);
	                 val [basilisk] = 2;
			 ok2desc = 0;
	               }
	            else
	               {
	                 msay (petrify_me);
	                 coroner();
	                 RETURN;
	               }
	         here = basque_1;
	       }
	    break;

          case basque_fork:
	    go (north, peelgrunt);
	    go (south, basque_2);
	    go (down, on_steps);
	    go (stairs, on_steps);
	    break;

          case peelgrunt:
	    if (kwd(south) || kwd(out))
	       if (val[safe] == 1)
	          {
	            msay (safe_blocks);
	            ok2saynoway = 0;
	          }
	       else
	          here = basque_fork;
	    else
	       if (kwd(inside))
	          if (val[safe] == 1)
	             {
	               safeexit = here;
	               here = insafe;
	             }
	          else
	             {
	               msay (cantentersafe);
	               ok2saynoway = 0;
	             }
	    break;

          case on_steps:
	    go (up, basque_fork);
	    go (down, steps_exit);
	    go (stairs, steps_exit);
	    break;

          case steps_exit:
	    go (up, on_steps);
	    go (down, storage);
	    go (north, fake_y2);
	    go (stairs, storage);
	    go (out, fake_y2);
	    break;

          case storage:
	    go (up, steps_exit);
	    go (stairs, steps_exit);
	    break;

          case fake_y2:

	    /* PLOVER/PLUGH TAKES YOU TO PLATFORM */

	    go (south, steps_exit);
	    go (west, catacombs_1);
	    go (east, fake_jumble);
	    go (_plover, platform);
	    break;

          case fake_jumble:
	    go (down, fake_y2);
	    go (west, fake_y2);
	    go (up, catacombs_1);
	    break;

          case audience:
	    go (east, audience_e);
	    go (west, catacombs_11);
	    break;

          case audience_e:
	    go (west, audience);
	    break;

          case banshee_1:
	    go (nw, by_figure);
	    go (north, golden);
	    break;

          case golden:
	    go (ne, arabesque);
	    go (nw, translucent);
	    go (south, banshee_1);
	    break;

          case arabesque:
	    go (south, golden);
	    go (out, golden);
	    break;

          case translucent:
	    if (kwd(out) || kwd(east))
	       {
	         if (!special1[goblins])
	            {
	              special1[goblins] = 1;
	              apport (goblins, here);
	              val[goblins] = -1;
	            }
	         here = golden;
	       }
	    break;

          case platform:

	    /* ONLY WAY OUT IS BY SAYING PLOVER/PLUGH WHICH SENDS YOU TO FAKE Y2 */

	    go (_plover, fake_y2);
	    if (kwd(down) || kwd(north) || kwd(south) || kwd(east) || kwd(west)
	                  || kwd(ne) || kwd(nw) || kwd(se) || kwd(sw))
	       {
	         msay (sizzle);
	         here = ylem;
	         coroner();
	         RETURN;
	       }
	    break;

          case cylinderical:
	    break;

          case catacombs_1:
	    go (south, catacombs_2);
	    break;

          case catacombs_2:
	    here = catacombs_1;
	    go (sw, catacombs_3);
	    break;

          case catacombs_3:
	    here = catacombs_2;
	    go (nw, catacombs_4);
	    break;

          case catacombs_4:
	    here = catacombs_3;
	    go (south, catacombs_5);
	    break;

          case catacombs_5:
	    here = catacombs_4;
	    go (down, catacombs_6);
	    break;

          case catacombs_6:
	    here = catacombs_5;
	    go (west, catacombs_7);
	    break;

          case catacombs_7:
	    here = catacombs_6;
	    go (nw, catacombs_8);
	    break;

          case catacombs_8:
	    here = catacombs_7;
	    go (north, catacombs_9);
	    break;

          case catacombs_9:
	    here = catacombs_8;
	    go (south, catacombs_10);
	    break;

          case catacombs_10:
	    here = catacombs_9;
	    go (north, catacombs_11);
	    break;

          case catacombs_11:
	    here = catacombs_10;
	    go (sw, catacombs_12);
	    go (east, audience);
	    break;

          case catacombs_12:
	    here = catacombs_11;
	    go (east, catacombs_13);
	    break;

          case catacombs_13:
	    here = catacombs_12;
	    go (se, catacombs_14);
	    break;

          case catacombs_14:
	    here = catacombs_13;
	    go (ne, catacombs_15);
	    break;

          case catacombs_15:
	    here = catacombs_14;
	    go (east, catacombs_16);
	    break;

          case catacombs_16:
	    here = catacombs_15;
	    go (se, catacombs_17);
	    break;

          case catacombs_17:
	    here = catacombs_16;
	    go (down, catacombs_18);
	    break;

          case catacombs_18:
	    here = catacombs_17;
	    go (south, catacombs_19);
	    break;

          case catacombs_19:
	    here = catacombs_18;
	    go (north, fake_y2);
	    break;

          case mazed_107:
	    go (south, mazed_131);
	    go (sw, mazed_132);
	    go (ne, mazed_133);
	    go (se, mazed_134);
	    go (up, mazed_135);
	    go (nw, mazed_136);
	    go (east, mazed_137);
	    go (west, mazed_138);
	    go (north, mazed_139);
	    go (down, longhallwest);
	    break;

	  case mazed_112:
	    go (sw, mazed_131);
	    go (north, mazed_132);
	    go (east, mazed_133);
	    go (nw, mazed_134);
	    go (se, mazed_135);
	    go (ne, mazed_136);
	    go (west, mazed_137);
	    go (down, mazed_138);
	    go (up, mazed_139);
	    go (south, mazed_140);
	    break;

          case mazed_131:
	    go (west, mazed_107);
	    go (se, mazed_132);
	    go (nw, mazed_133);
	    go (sw, mazed_134);
	    go (ne, mazed_135);
	    go (up, mazed_136);
	    go (down, mazed_137);
	    go (north, mazed_138);
	    go (south, mazed_139);
	    go (east, mazed_112);
	    break;

          case mazed_132:
	    go (nw, mazed_107);
	    go (up, mazed_131);
	    go (north, mazed_133);
	    go (south, mazed_134);
	    go (west, mazed_135);
	    go (sw, mazed_136);
	    go (ne, mazed_137);
	    go (east, mazed_138);
	    go (down, mazed_139);
	    go (se, mazed_112);
	    break;

          case mazed_133:
	    go (up, mazed_107);
	    go (down, mazed_131);
	    go (west, mazed_132);
	    go (ne, mazed_134);
	    go (sw, mazed_135);
	    go (east, mazed_136);
	    go (north, mazed_137);
	    go (nw, mazed_138);
	    go (se, mazed_139);
	    go (south, mazed_112);
	    break;

          case mazed_134:
	    go (ne, mazed_107);
	    go (north, mazed_132);
	    go (nw, mazed_133);
	    go (se, mazed_136);
	    go (east, mazed_135);
	    go (down, mazed_136);
	    go (south, mazed_137);
	    go (up, mazed_138);
	    go (west, mazed_139);
	    go (sw, mazed_112);
	    break;

          case mazed_135:
	    go (north, mazed_107);
	    go (se, mazed_131);
	    go (down, mazed_132);
	    go (south, mazed_133);
	    go (east, mazed_134);
	    go (west, mazed_136);
	    go (sw, mazed_137);
	    go (ne, mazed_138);
	    go (nw, mazed_139);
	    go (up, mazed_112);
	    break;

          case mazed_136:
	    go (east, mazed_107);
	    go (west, mazed_131);
	    go (up, mazed_132);
	    go (sw, mazed_133);
	    go (down, mazed_134);
	    go (south, mazed_135);
	    go (nw, mazed_137);
	    go (se, mazed_138);
	    go (ne, mazed_139);
	    go (north, mazed_112);
	    break;

          case mazed_137:
	    go (se, mazed_107);
	    go (ne, mazed_131);
	    go (south, mazed_132);
	    go (down, mazed_133);
	    go (up, mazed_134);
	    go (nw, mazed_135);
	    go (north, mazed_136);
	    go (sw, mazed_138);
	    go (east, mazed_139);
	    go (west, mazed_112);
	    break;

          case mazed_138:
	    go (down, mazed_107);
	    go (east, mazed_131);
	    go (ne, mazed_132);
	    go (up, mazed_133);
	    go (west, mazed_134);
	    go (north, mazed_135);
	    go (south, mazed_136);
	    go (se, mazed_137);
	    go (sw, mazed_139);
	    go (nw, mazed_112);
	    break;

          case mazed_139:
	    go (sw, mazed_107);
	    go (nw, mazed_131);
	    go (east, mazed_132);
	    go (west, mazed_133);
	    go (north, mazed_134);
	    go (down, mazed_135);
	    go (se, mazed_136);
	    go (up, mazed_137);
	    go (south, mazed_138);
	    go (ne, mazed_112);
	    break;

          case mazed_140:
	    go (north, mazed_112);
	    go (out, mazed_112);
	    break;

	/* THESE ARE EXTENSIONS TO THE 565 POINT VERSION. (RAB) */

	  case nearstove:
	    go (south, building);
	    go (out, road);
	    if (kwd(down))
	       if (!invisible[trapdoor])
	          {
	            if (val[trapdoor])
	               {
	                 here = belowtrap;
	                 msay (trapcloses);
	                 val[trapdoor] = 0;
	               }
	            else
	               {
	                 msay (trapclosed);
	                 ok2saynoway = 0;
	               }
	            break;
	          }
	    break;

	  case belowtrap:
	    go (down, emergency);
	    if (kwd(up) || kwd(_building))
	       if (invisible[trapdoor] || !val[trapdoor])
	          {
	            msay (traphit);
	            ok2saynoway = 0;
	          }
	       else
	          here =  nearstove;
	    break;

	  case emergency:
	    go (up, belowtrap);
	    go (south, southend);
	    go (north, pnjunction);
	    break;

	  case southend:
	    go (north, emergency);
	    go (out, emergency);
	    go (back, emergency);
	    break;

	  case pnjunction:
	    go (south, emergency);
	    go (east, pcorrid);
	    go (west, ncorrid);
	    break;

	  case pcorrid:
	    go (west, pnjunction);
	    go (east, mirrorent1);
	    break;

	  case mirrorent1:
	    go (west, pcorrid);
	    go (east, mirrorroom);
	    go (inside, mirrorroom);
	    break;

	  case mirrorroom:
	    if (kwd(north) || kwd(south) || kwd(ne) || kwd(nw) || kwd(se) || kwd(sw) || kwd(out))
	       {
	         msay (mirror_bang);
	         ok2saynoway = 0;
	       }
	    else
	       if (kwd(east))
	          if (val[mirror2]==1)		/* east, west are the only way out	*/
	             here = mirrorent1;		/* depending on which mirror's broken	*/
	          else
	             {
	               msay (mirror_bang);
	               ok2saynoway = 0;
	             }
	       else
	          if (kwd(west))
	             if (val[mirror2]==2)
	                here = mirrorent2;
	             else
	                {
	                  msay (mirror_bang);
	                  ok2saynoway = 0;
	                }
	    break;

	  case ncorrid:
	    go (east, pnjunction);
	    go (west, nslope);
	    break;
	   
	  case nslope:
	    go (east, ncorrid);
	    go (back, ncorrid);
	    go (down, pathway);
	    break;

	  case pathway:
	    if (kwd(up) || kwd(_ledge))
	       {
	         msay (ledge_high);
	         ok2saynoway = 0;
	       }
	    break;

	  case mirrorent2:
          case treasureroom:
          case ylem:
          default:
            go (out, prevloc);
            printf ("Travel not implemented for loc %d - say \"OUT\" to leave.\n", here);
	    ok2saynoway = 0;
            break;
        }

        /* IF HE COULDN'T MOVE, TELL HIM WHY */

        if (here!=prevloc || fakemove)
           moved = 1;
        else
           if (ok2saynoway)
              {
                ok2desc = 0;
                switch (arg1)
                {
                  /* EITHER HE'S ALREADY THERE OR WE NEED DETAILED INSTRUCTIONS */

                  case surface:
                  case outdoors:
                    if (notincave[here])
                       msay (you_are_there);
                    else
                       msay (needdetail);
                    break;

                  case cave:
                    if (notincave[here])
                       msay (needdetail);
                    else
                       msay (you_are_there);
                    break;

                  case _building:
                    if (here==building || here==nearstove)
                       msay (you_are_there);
                    else
                       msay (needdetail);
                    break;

                  case entrance:
                    if (here==road)
                       msay (you_are_there);
                    else
                       msay (needdetail);
                    break;

                  case gully:
                    if (here==valley)
                       msay (you_are_there);
                    else
                       msay (needdetail);
                    break;

                  case stream:
                    if (here==slit)
                       msay (you_are_there);
                    else
                       msay (needdetail);
                    break;

                  case _depression:
                    if (here==depression)
                       msay (you_are_there);
                    else
                       msay (needdetail);
                    break;

                  case _valley:
                    if (here==valley)
                       msay (you_are_there);
                    else
                       msay (needdetail);
                    break;

                  case _forest:
                    if (here==forest || here==forest2)
                       msay (you_are_there);
                    else
                       msay (needdetail);
                    break;

                  case _pit:
                    if (here==eastpit || here==westpit || here==streampit ||
                        here==mazea_16_pit)
                       msay (you_are_there);
                    else
                       msay (needdetail);
                    break;

                  case _slab:
                    if (here==slab)
                       msay (you_are_there);
                    else
                       msay (needdetail);
                    break;

                  case _bedquilt:
                    if (here==bedquilt)
                       msay (you_are_there);
                    else
                       msay (needdetail);
                    break;

                  case _low:
                    if (here==low)
                       msay (you_are_there);
                    else
                       msay (needdetail);
                    break;

                  /* BE SPECIFIC, PAL! */

                  case inside:
                    if (here==building || here==incave)
                       {
                         msay (you_are_there);
                         break;
                       }
                    else
                       msay (infromout);
                    break;

                  case out:
                    if (here==road || here==depression)
                       {
                         msay (you_are_there);
                         break;
                       }
                     else
                        msay (infromout);
                    break;

                  case front:
                  case left:
                  case right:
                    msay (iamunsure);
                    break;

                  case _y2:
                    if (here == y2)
                       msay (you_are_there);
                    else
                       msay (needdetail);
                    break;

                  case _plover:
	            msay (nothing);
	            break;

                  /* SORRY, NO WAY TO GO IN THAT DIRECTION */

                  default:
                    if (isplace(arg1))
                       msay (needdetail);
                    else
                       msay (nocango);
                    break;
                }
              }
	RETURN;
}
