// Travel.cpp : move logic
//
//  Private functions:
//

#include "stdafx.h"

#include "AdvInit.h"
#include "AdvIO.h"
#include "AdvMain.h"
#include "AdvUtil.h"
#include "DoVerb.h"
#include "Travel.h"

/////////////////////
// Forward references
void crossTheChasm
  (AdvGlobalContext&  gc,
   bool*              pOk2SayNoWay);

void go
  (AdvGlobalContext&  gc,
   long               nCommand,
   long               nDestination);

bool kwd
  (AdvGlobalContext&  gc,
   long               nCommand);

///////////////////
// Public functions

void climbProc
  (AdvGlobalContext& gc)   // global context
//
//  Handles "climb".
//
{
  gc.m_nPrevLoc = gc.m_nHere;
  switch (gc.m_nHere)
  {
    case nslope:
      gc.m_nHere = pathway;
      break;

    case westpit:
      if (gc.m_nState [plant] == 0)
         sayMessage (gc, noclimbup);
      else
         {
           sayMessage (gc, gc.m_nState [plant] == 2 ? shortplant : longplant);
           gc.m_bOk2Describe = false;
           gc.m_nHere = (gc.m_nState [plant] == 2 ? wend2pit : narrowcorrid);
         }
      break;

    case narrowcorrid:
      gc.m_nHere = westpit;
      break;

    case brink:
      gc.m_nHere = streampit;
      break;

    case streampit:
      gc.m_nHere = brink;
      break;

    case wendmists:
      gc.m_nHere = mazea_1;
      break;

    case mazea_16_pit:
      gc.m_nHere = birdchamber;
      break;

    case complex:
      gc.m_nHere = dusty;
      break;

    case slab:
      gc.m_nHere = secretnscyn;
      break;

    case incline:
      sayMessage (gc, oof);
      gc.m_nHere = low;
      gc.m_bOk2Describe = false;
      break;

    case stalact:
      gc.m_nHere = mazea_12;
      break;

    case breathtaker:
      gc.m_nHere = ylem;
      splatter (gc);
      coroner (gc);
      return;

    case slide:
      sayMessage (gc, slide_slippery);
      gc.m_bOk2Describe = false;
      break;

    case shelf:
      gc.m_nHere = beach;
      break;

    case beach:
      gc.m_nHere = shelf;
      gc.m_nState [dinghy] = 1;
      break;

    case chimney:
      gc.m_nHere = tube;
      break;

    case tube:
      gc.m_nHere = chimney;
      break;

    case basque_fork:
      gc.m_nHere = on_steps;
      break;

    case platform:
      sayMessage (gc, sizzle);
      gc.m_nHere = ylem;
      coroner (gc);
      return;

    case forest:
    case forest2:
      sayMessage (gc, inforest);
      break;

    default:
      gc.m_bOk2Describe = false;
      sayMessage (gc, cantapply);
      break;
  }

  // Did we move?
  gc.m_bMoved = (gc.m_nHere != gc.m_nPrevLoc);
}

void jumpProc
  (AdvGlobalContext& gc)   // global context
//
//  Handles "jump".
//
{
  gc.m_nPrevLoc = gc.m_nHere;
  switch (gc.m_nHere)
  {
    case nslope:
      gc.m_nHere = pathway;
      gc.m_bMoved = true;
      break;

    case westoffissur:
      gc.m_bOk2Describe = false;
      if (gc.m_nState [fissure] == 1)
         sayMessage (gc, trythebridge);
      else
         {
           gc.m_nHere = cavern;
           splatter (gc);
           coroner (gc);
           return;
         }
      break;

    case window:
    case window2:
      sayMessage (gc, brokenneck);
      gc.m_nHere = mirrorcnyn;
      coroner (gc);
      return;

    case cavern:
      gc.m_bOk2Describe = false;
      if (yes (gc, whirlpool))
         {
           long nObjectsLost = 0;
           for (long nObject=MINOBJECTS; (nObject <= MAXOBJECTS); nObject++)
               if (carrying (nObject) && (nObject != lamp))
                  {
                    apport (nObject, limbo);
                    nObjectsLost++;
                  }
           gc.m_nInventory = 0;
           if (carrying (lamp))
              {
                gc.m_nInventory = 1;
                sayMessage (gc, (nObjectsLost > 0 ? flow_rip : flow_down));
              }
           else
              sayMessage (gc, (nObjectsLost > 0 ? flow_d_rip : flow_dark));
           gc.m_nHere = reservoir_n;
           sayMessage (gc, whirl_land);
         }
      break;

    case misty:
      gc.m_nHere = cavern;
      splatter (gc);
      coroner (gc);
      return;

    case stalact:
      gc.m_nHere = mazea_12;
      gc.m_bMoved = true;
      break;

    case balcony:
    case breathtaker:
      gc.m_nHere = ylem;
      splatter (gc);
      coroner (gc);
      return;

    case swofchasm:
    case neofchasm:
      gc.m_bOk2Describe = false;
      if (gc.m_nState [chasm] == 0)
         sayMessage (gc, trythebridge);
      else
         {
           gc.m_nHere = ylem;
           splatter (gc);
           coroner (gc);
           return;
         }
      break;

    case brink_1:
    case brink_2:
    case brink_3:
      plunge (gc);
      break;

    case platform:
      sayMessage (gc, sizzle);
      gc.m_nHere = ylem;
      coroner (gc);
      return;

    default:
      if (chance (50))
         sillyProc (gc);
      else
         sayMessage (gc, chance (50) ? cantapply : nojumping);
      gc.m_bOk2Describe = false;
      break;
  }
}

void plunge
  (AdvGlobalContext& gc)   // global context
//
//  Called by jumpProc() every time the adventurer jumps into a bottomless
//  pit.
//
{
  gc.m_nHere = ylem;
  if (gc.m_nState [lamp] == 1)
     {
       gc.m_nLampLife = 0;
       sayMessage (gc, carrying (lamp) ? fallandstarve : fallandstarved);
     }
  else
     sayMessage (gc, fallandstarved);
  finis (gc);
  cleanupAndExit (gc);
}

void rideProc
  (AdvGlobalContext& gc)   // global context
//
//  Handles "ride".
//
{
  // Figure out what he wants to ride
  if (gc.m_nCmdWords==1)
     if (near (turtle))
        gc.m_nArg2 = turtle;
     else
        {
          sayMessage (gc, nothing2ride);
          return;
        }

  if (!isObject (gc.m_nArg2))
     sayMessage (gc, what);
  else
     if (!near (gc.m_nArg2))
        sayMessageWord (gc, idontsee, gc.m_nArg2);
     else
        if (gc.m_nArg2 == turtle)
           {
             sayMessage (gc, turtle_back);
             gc.m_nHere = reservoir;
             apport (turtle, limbo);
             gc.m_bMoved = true;
           }
        else
           if ((gc.m_nArg2 == dwarf) || (gc.m_nArg2 == troll)   || (gc.m_nArg2 == pirate) ||
               (gc.m_nArg2 == ogre)  || (gc.m_nArg2 == goblins) || (gc.m_nArg2 == djinn))
              sayMessage (gc, repulsive);
           else
              sayMessage (gc, iamgame);
}

void swimProc
  (AdvGlobalContext& gc)   // global context
//
//  Handles "swim".
//
{
  sayMessage (gc, iamgame);
}

void travel
  (AdvGlobalContext& gc)   // global context
//
//  Move logic.
//
{
bool  bFakeMove;      // flag: pretend we moved
bool  bOk2SayNoWay;   // flag: it's OK to say "No way in that direction"

  gc.m_bMoved = false;
  bFakeMove = false;
  bOk2SayNoWay = true;

  // This flag appears to be set to true - why??  (RAB 12/11/2000)
  gc.m_bExtendedVersion = false;

  // Change commands like "inside <location>" to "<location>"
  if (isDirection (gc.m_nArg1) && isDirection (gc.m_nArg2))
     {
       gc.m_nArg1 = gc.m_nArg2;
       gc.m_nArg2 = null;
       gc.m_nCmdWords = 1;
     }

  // Make sure it's a valid command
  if (gc.m_nArg1 == move)
     if (gc.m_nArg2 == null)
        {
          sayMessageText (gc, whichway, gc.m_szArg1);
          return;
        }
     else
        if (isDirection (gc.m_nArg2))
           {
             gc.m_nArg1 = gc.m_nArg2;
             gc.m_nArg2 = null;
           }
        else
           {
             sayMessage (gc, what);
             return;
           }
  else
     if ((gc.m_nArg2 != move) && (gc.m_nArg2 != null))
        {
          sayMessage (gc, huh);
          return;
        }

  // Check for special motion "go back"
  if (gc.m_nArg1 == back)
     {
       // Can't go back from "noback" rooms or if we've used a magic word to travel
       bool   bCantGoBack = false;
       if (gc.m_noBack [gc.m_nHere])
          bCantGoBack = true;
       if (gc.m_nHere == mists)
          bCantGoBack = true;
       if ((gc.m_nHere == y2) && (gc.m_nPrevLoc == building))
          bCantGoBack = true;
       if ((gc.m_nHere == debris) && (gc.m_nPrevLoc == building))
          bCantGoBack = true;
       if ((gc.m_nHere == building) && ((gc.m_nPrevLoc == y2) || (gc.m_nPrevLoc == debris)))
          bCantGoBack = true;
       if (bCantGoBack)
          {
            sayMessage (gc, snidely);
            gc.m_bOk2Describe = false;
          }
       else
          {
            long  nTempLocation = gc.m_nHere;
            gc.m_nHere = gc.m_nPrevLoc;
            gc.m_nPrevLoc = nTempLocation;
            gc.m_bMoved = true;
          }
       return;
     }

  // The following code assumes directional verb is in gc.m_nArg1
  gc.m_nPrevLoc = gc.m_nHere;
  switch (gc.m_nHere)
  {
    case road:
      go (gc, entrance, building);
      go (gc, inside, building);
      go (gc, east, building);
      go (gc, downstream, valley);
      go (gc, gully, valley);
      go (gc, stream, valley);
      go (gc, south, valley);
      go (gc, down, valley);
      go (gc, north, forest);
      go (gc, east, forest);
      go (gc, _depression, depression);
      go (gc, _building, building);
      go (gc, west, hill);
      go (gc, up, hill);
      go (gc, _road, hill);
      if (gc.m_bExtendedVersion)
         {
           go (gc, west, hill_extended);
           go (gc, up, hill_extended);
           go (gc, _road, hill_extended);
         }
      break;

    case hill:
      go (gc, _road, road);
      go (gc, _building, road);
      go (gc, front, road);
      go (gc, east, road);
      go (gc, _forest, forest);
      go (gc, south, forest);
      go (gc, down, road);
      break;

    case hill_extended:
      go (gc, _road, road);
      go (gc, _building, road);
      go (gc, front, road);
      go (gc, east, road);
      go (gc, _forest, forest);
      go (gc, south, forest);
      go (gc, north, hayfield);
      if (kwd (gc, down))
         gc.m_nHere = chance (50) ? road : hayfield;
      break;

    case hayfield:
      go (gc, south, hill);
      go (gc, out, hill);
      go (gc, back, hill);
      go (gc, up, hill);
      if (kwd (gc, inside))
         {
           bOk2SayNoWay = false;
           if (!gc.m_seen [needle])
              {
                sayMessage (gc, haystack);
                gc.m_invisible [needle] = false;
                gc.m_bOk2Describe = false;
              }
           else
              sayMessage (gc, haybounce);
         }
      break;

    case building:
      go (gc, _road, road);
      go (gc, out, road);
      go (gc, outdoors, road);
      go (gc, west, road);
      if (kwd (gc, stream) || kwd (gc, downstream))
         {
           sayMessage (gc, pipefit);
           bOk2SayNoWay = false;
           gc.m_nHere = building;
         }
      if (gc.m_bExtendedVersion)
         go (gc, north, nearstove);
      break;

    case valley:
      go (gc, upstream, road);
      go (gc, _building, road);
      go (gc, north, road);
      go (gc, _forest, forest);
      go (gc, east, forest);
      go (gc, west, forest);
      go (gc, up, forest);
      go (gc, _depression, depression);
      if (gc.m_nClosure < 2)
         {
           go (gc, south, slit);
           go (gc, down, slit);
           go (gc, downstream, slit);
         }
      else
         {
           go (gc, south, fake_slit);
           go (gc, down, fake_slit);
           go (gc, downstream, fake_slit);
         }
      break;

    case forest:
      go (gc, _valley, valley);
      go (gc, east, valley);
      go (gc, down, valley);
      go (gc, west, forest);
      go (gc, south, forest);
      if (gc, chance(50))
         {
           go (gc, _forest, forest);
           go (gc, front, forest);
           go (gc, north, forest);
         }
      else
         {
           go (gc, _forest, forest2);
           go (gc, front, forest2);
           go (gc, north, forest2);
         }
      break;

    case forest2:
      go (gc, _road, road);
      go (gc, north, road);
      go (gc, _valley, valley);
      go (gc, east, valley);
      go (gc, west, valley);
      go (gc, down, valley);
      go (gc, _forest, forest);
      go (gc, south, forest);
      break;

    case slit:
      go (gc, _building, road);
      go (gc, upstream, valley);
      go (gc, north, valley);
      go (gc, _forest, forest);
      go (gc, east, forest);
      go (gc, west, forest);
      go (gc, downstream, depression);
      go (gc, bed, depression);
      go (gc, rock, depression);
      go (gc, south, depression);
      if (kwd (gc, _slit) || kwd (gc, stream) || kwd (gc, down) || kwd (gc, entrance) || kwd (gc, inside))
         {
          sayMessage (gc, dontfitslit);
          bOk2SayNoWay = false;
          gc.m_nHere = slit;
        }
      break;

    case fake_slit:
      go (gc, _building, road);
      go (gc, upstream, valley);
      go (gc, north, valley);
      go (gc, _forest, forest);
      go (gc, east, forest);
      go (gc, west, forest);
      go (gc, downstream, depression);
      go (gc, rock, depression);
      go (gc, bed, depression);
      go (gc, south, depression);
      if (kwd (gc, _slit) || kwd (gc, stream) || kwd (gc, down) || kwd (gc, entrance) || kwd (gc, inside))
         {
           gc.m_nClosure = 5;     // victory!
           describePlace (gc, treasureroom, true);
           gc.m_bQuitting = false;
           finis (gc);
         }
      break;

    case depression:
      go (gc, _forest, forest);
      go (gc, east, forest2);
      go (gc, west, forest);
      go (gc, south, forest2);
      go (gc, _building, road);
      if (kwd (gc, upstream) || kwd (gc, gully) || kwd (gc, north) || kwd (gc, _slit))
         if (gc.m_nClosure < 2)
            gc.m_nHere = slit;
         else
            gc.m_nHere = fake_slit;
      if (kwd (gc, inside) || kwd (gc, down) || kwd (gc, cave))
         {
           if (gc.m_nState [grate] == 1)
              gc.m_nHere = incave;
           else
              {
                sayMessage (gc, cantpasslock);
                bOk2SayNoWay = false;
                gc.m_nHere = depression;
              }
           break;
         }
      break;

    case incave:
      if (kwd (gc, up) || kwd (gc, out) || kwd (gc, outdoors) || kwd (gc, surface))
         {
           if (gc.m_nState [grate] == 1)
              gc.m_nHere = depression;
           else
              {
                sayMessage (gc, cantpasslock);
                gc.m_nHere = incave;
                bOk2SayNoWay = false;
              }
           break;
         }
      go (gc, crawl, cobbles);
      go (gc, _cobbles, cobbles);
      go (gc, inside, cobbles);
      go (gc, west, cobbles);
      go (gc, _pit, pit);
      go (gc, _debris, debris);
      break;

    case cobbles:
      go (gc, out, incave);
      go (gc, surface, incave);
      go (gc, entrance, incave);
      go (gc, east, incave);
      go (gc, inside, debris);
      go (gc, west, debris);
      go (gc, _debris, debris);
      go (gc, _pit, pit);
      break;

    case debris:
      go (gc, entrance, incave);
      go (gc, _cobbles, cobbles);
      go (gc, passage, cobbles);
      go (gc, east, cobbles);
      go (gc, inside, canyon);
      go (gc, up, canyon);
      go (gc, west, canyon);
      go (gc, _pit, pit);
      if (kwd (gc, _depression))
         if (gc.m_nState [grate] == 1)
            gc.m_nHere = depression;
         else
            {
              bOk2SayNoWay = false;
              gc.m_nHere = incave;
              sayMessage (gc, cantpasslock);
            }
      break;

    case canyon:
      go (gc, entrance, incave);
      go (gc, down, debris);
      go (gc, east, debris);
      go (gc, _debris, debris);
      go (gc, inside, birdchamber);
      go (gc, up, birdchamber);
      go (gc, west, birdchamber);
      go (gc, _pit, pit);
      if (kwd (gc, _depression))
         if (gc.m_nState [grate] == 1)
            gc.m_nHere = depression;
         else
            {
              bOk2SayNoWay = false;
              gc.m_nHere = incave;
              sayMessage (gc, cantpasslock);
            }
      break;

    case birdchamber:
      go (gc, entrance, incave);
      go (gc, _debris, debris);
      go (gc, east, canyon);
      go (gc, passage, pit);
      go (gc, _pit, pit);
      go (gc, west, pit);
      if (kwd (gc, _depression))
         if (gc.m_nState [grate] == 1)
            gc.m_nHere = depression;
         else
            {
              bOk2SayNoWay = false;
              gc.m_nHere = incave;
              sayMessage (gc, cantpasslock);
            }
      break;

    case pit:
      if (kwd (gc, down) || kwd (gc, _pit))
         {
           gc.m_nHere = mists;
           if (gc.m_invisible [steps])
              {
                sayMessage (gc, brokenneck);
                coroner (gc);
                break;
                bOk2SayNoWay = false;
                gc.m_bOk2Describe = false;
              }
           break;
         }
      go (gc, entrance, incave);
      go (gc, _debris, debris);
      go (gc, passage, birdchamber);
      go (gc, east, birdchamber);
      if (kwd (gc, west) || kwd (gc, crack))
         {
           sayMessage (gc, mistcrack);
           bOk2SayNoWay = false;
           gc.m_nHere = pit;
           break;
         }
      if (kwd (gc, _depression))
         if (gc.m_nState [grate] == 1)
            gc.m_nHere = depression;
         else
            {
              bOk2SayNoWay = false;
              gc.m_bOk2Describe = false;
              gc.m_nHere = incave;
              sayMessage (gc, cantpasslock);
            }
      break;

    case mists:
      if (gc.m_invisible [steps] &&
          (kwd (gc, up) || kwd (gc, _pit) || kwd (gc, dome) || kwd (gc, passage) ||
           kwd (gc, inside) || kwd (gc, back)))
         {
           bOk2SayNoWay = false;
           gc.m_bOk2Describe = false;
           sayMessage (gc, unclimbable);
           break;
         }
      go (gc, up, pit);
      go (gc, dome, pit);
      go (gc, _pit, pit);
      go (gc, left, goldroom);
      go (gc, south, goldroom);
      go (gc, east, sandstone);
      go (gc, hall, eastoffissur);
      go (gc, front, eastoffissur);
      go (gc, west, eastoffissur);
      go (gc, down, mtking);
      go (gc, stairs, mtking);
      go (gc, north, mtking);
      go (gc, _y2, jumble);
      break;

    case eastoffissur:
      go (gc, hall, mists);
      go (gc, east, mists);
      if (kwd (gc, front) || kwd (gc, west) || kwd (gc, cross))
         if (gc.m_nState [fissure] == 0)
            {
              sayMessage (gc, nowayacross);
              bOk2SayNoWay = false;
            }
         else
            gc.m_nHere = westoffissur;
      break;

    case goldroom:
      go (gc, hall, mists);
      go (gc, out, mists);
      go (gc, north, mists);
      break;

    case mtking:
      go (gc, stairs, mists);
      go (gc, up, mists);
      go (gc, east, mists);
      if (kwd (gc, north) || kwd (gc, left) || kwd (gc, south) || kwd (gc, right) ||
          kwd (gc, west) || kwd (gc, front) || kwd (gc, sw) || kwd (gc, secret) ||
          kwd (gc, nw) || kwd (gc, se) || kwd (gc, ne) || kwd (gc, down))
      if (near (snake))
         {
           sayMessage (gc, snakeblocks);
           bOk2SayNoWay = false;
           gc.m_nHere = mtking;
         }
      else
         {
           go (gc, north, lownspassage);
           go (gc, left, lownspassage);
           go (gc, south, southside);
           go (gc, right, southside);
           go (gc, west, westside);
           go (gc, front, westside);
           go (gc, down, vault);
           go (gc, ne, morion);
           go (gc, nw, corrid_3);
           go (gc, se, corrid_1);
           go (gc, secret, secretew_tite);
           if (kwd (gc, sw))
              if (chance (35))
                 gc.m_nHere = secretew_tite;
              else
                 {
                   sayMessage (gc, youdidntmove);
                   bOk2SayNoWay = false;
                   gc.m_nHere = mtking;
                 }
         }
      break;

    case wend2pit:
      go (gc, east, eend2pit);
      go (gc, cross, eend2pit);
      go (gc, _slab, slab);
      go (gc, west, slab);
      go (gc, down, westpit);
      go (gc, _pit, westpit);
      if (kwd (gc, hole))
         {
           sayMessage (gc, too_far_up);
           bOk2SayNoWay = false;
           gc.m_nHere = wend2pit;
         }
      break;

    case eastpit:
      go (gc, up, eend2pit);
      go (gc, out, eend2pit);
      break;

    case westpit:
      go (gc, up, wend2pit);
      go (gc, out, wend2pit);
      break;

    case westoffissur:
      go (gc, west, wendmists);
      if (kwd (gc, front) || kwd (gc, cross) || kwd (gc, east))
         {
           if (gc.m_nState [fissure] != 0)
              gc.m_nHere = eastoffissur;
           else
              {
                sayMessage (gc, nowayacross);
                bOk2SayNoWay = false;
              }
           break;
         }
      if (kwd (gc, north))
         {
           sayMessage (gc, mistcrawl);
           gc.m_nHere = wendmists;
           gc.m_bOk2Describe = false;
         }
      break;

    case lownspassage:
      go (gc, hall, mtking);
      go (gc, out, mtking);
      go (gc, south, mtking);
      go (gc, north, y2);
      go (gc, _y2, y2);
      go (gc, down, dirty);
      go (gc, hole, dirty);
      break;

    case southside:
      go (gc, hall, mtking);
      go (gc, out, mtking);
      go (gc, north, mtking);
      break;

    case westside:
      go (gc, hall, mtking);
      go (gc, out, mtking);
      go (gc, east, mtking);
      go (gc, west, crossover);
      go (gc, up, crossover);
      break;

    case y2:
      go (gc, south, lownspassage);
      go (gc, east, jumble);
      go (gc, west, window);
      go (gc, _plover, plover);
      break;

    case jumble:
      go (gc, down, y2);
      go (gc, _y2, y2);
      go (gc, up, mists);
      break;

    case window:
      go (gc, east, y2);
      go (gc, _y2, y2);
      break;

    case dirty:
      go (gc, east, brink);
      go (gc, crawl, brink);
      go (gc, up, lownspassage);
      go (gc, hole, lownspassage);
      go (gc, west, dusty);
      go (gc, _bedquilt, bedquilt);
      break;

    case brink:
      go (gc, west, dirty);
      go (gc, crawl, dirty);
      go (gc, down, streampit);
      go (gc, _pit, streampit);
      break;

    case streampit:
      go (gc, up, brink);
      go (gc, out, brink);
      if (kwd (gc, _slit) || kwd (gc, stream) || kwd (gc, down) ||
          kwd (gc, downstream) || kwd (gc, upstream))
         {
           sayMessage (gc, dontfitslit);
           bOk2SayNoWay = false;
         }
      break;

    case dusty:
      go (gc, east, dirty);
      go (gc, passage, dirty);
      go (gc, down, complex);
      go (gc, _bedquilt, bedquilt);
      break;

    case wendmists:
      go (gc, south, mazea_1);
      go (gc, down, mazea_1);
      go (gc, passage, mazea_1);
      go (gc, east, westoffissur);
      go (gc, west, longhalleast);
      go (gc, crawl, longhalleast);
      if (kwd (gc, north))
         {
           sayMessage (gc, mistcrawl);
           bOk2SayNoWay = false;
           gc.m_bOk2Describe = false;
           gc.m_nHere = westoffissur;
         }
      break;

    case mazea_1:
      go (gc, up, wendmists);
      if (kwd (gc, north))
         {
           bFakeMove = true;
           break;
         }
      go (gc, east, mazea_2);
      go (gc, south, mazea_4);
      go (gc, west, mazea_18);
      break;

    case mazea_2:
      go (gc, west, mazea_1);
      go (gc, south, mazea_3);
      go (gc, east, mazea_4);
      break;

    case mazea_3:
      go (gc, east, mazea_2);
      go (gc, down, mazea_7);
      go (gc, south, mazea_9);
      go (gc, north, mazea_20);
      break;

    case mazea_4:
      go (gc, west, mazea_1);
      go (gc, north, mazea_2);
      go (gc, east, mazea_5);
      go (gc, south, mazea_6);
      go (gc, up, mazea_25);
      go (gc, down, mazea_25);
      break;

    case mazea_5:
      go (gc, west, mazea_4);
      go (gc, out, mazea_4);
      break;

    case mazea_6:
      go (gc, east, mazea_4);
      go (gc, out, mazea_4);
      break;

    case mazea_7:
      go (gc, up, mazea_3);
      go (gc, out, mazea_3);
      break;

    case mazea_8:
      go (gc, east, mazea_9);
      go (gc, west, mazea_10);
      break;

    case mazea_9:
      go (gc, east, mazea_3);
      go (gc, west, mazea_8);
      go (gc, down, mazea_10);
      go (gc, south, mazea_11);
      break;

    case mazea_10:
      go (gc, west, mazea_8);
      go (gc, up, mazea_9);
      go (gc, east, mazea_11);
      go (gc, south, mazea_12);
      break;

    case mazea_11:
      go (gc, west, mazea_9);
      go (gc, east, mazea_10);
      if (kwd (gc, south))
         {
           bFakeMove = true;
           break;
         }
      go (gc, up, mazea_12);
      go (gc, north, mazea_14);
      go (gc, down, mazea_24);
      break;

    case mazea_12:
      go (gc, west, mazea_10);
      go (gc, north, mazea_11);
      go (gc, south, mazea_13);
      break;

    case mazea_13:
      go (gc, west, mazea_12);
      go (gc, out, mazea_12);
      break;

    case mazea_14:
      go (gc, west, mazea_11);
      if (kwd (gc, north))
         {
           bFakeMove = true;
           break;
         }
      go (gc, down, mazea_15);
      go (gc, east, mazea_16_pit);
      break;

    case mazea_15:
      go (gc, up, mazea_14);
      go (gc, out, mazea_14);
      break;

    case mazea_16_pit:
      go (gc, down, birdchamber);
      go (gc, west, mazea_14);
      go (gc, south, mazea_17);
      go (gc, north, mazea_21);
      go (gc, east, mazea_22);
      break;

    case mazea_17:
      go (gc, east, mazea_16_pit);
      go (gc, out, mazea_16_pit);
      break;

    case longhalleast:
      go (gc, east, wendmists);
      go (gc, up, wendmists);
      go (gc, crawl, wendmists);
      go (gc, west, longhallwest);
      go (gc, north, crossover);
      go (gc, down, crossover);
      go (gc, hole, crossover);
      break;

    case longhallwest:
      go (gc, east, longhalleast);
      go (gc, north, crossover);
      go (gc, south, mazed_107);
      break;

    case crossover:
      go (gc, west, longhalleast);
      go (gc, north, deadend1);
      go (gc, east, westside);
      go (gc, south, longhallwest);
      break;

    case deadend1:
      go (gc, south, crossover);
      go (gc, out, crossover);
      break;

    case complex:
      go (gc, up, dusty);
      go (gc, west, bedquilt);
      go (gc, _bedquilt, bedquilt);
      go (gc, north, shell);
      go (gc, east, anteroom);
      break;

    case bedquilt:
      go (gc, _slab, slab);
      go (gc, _low, low);
      go (gc, east, complex);
      go (gc, west, swiss);
      if (kwd (gc, north) || kwd (gc, south) || kwd (gc, up) || kwd (gc, down))
         if (chance (65))
            {
              sayMessage (gc, crawl_cavein);
              bOk2SayNoWay = false;
              break;
            }
         else
            {
              go (gc, down, anteroom);
              if (chance (75))
                 {
                   go (gc, north, low);
                   go (gc, up, dusty);
                   go (gc, south, slab);
                 }
              else
                 {
                   go (gc, north, secretjunction);
                   go (gc, up, secretnspas);
                   go (gc, south, tallewcnyn);
                 }
              break;
            }
      if (kwd (gc, nw))
         if (chance (50))
            gc.m_nHere = oriental;
         else
            {
              sayMessage (gc, youdidntmove);
              bOk2SayNoWay = false;
            }
      break;

    case swiss:
      go (gc, ne, bedquilt);
      go (gc, west, eend2pit);
      go (gc, east, soft);
      go (gc, _oriental, oriental);
      if (kwd (gc, nw))
         if (chance (65))
            gc.m_nHere = oriental;
         else
            {
              sayMessage (gc, youdidntmove);
              bOk2SayNoWay = false;
            }
      else
         if (kwd (gc, south))
            if (chance(65))
               gc.m_nHere = tallewcnyn;
            else
              {
                sayMessage (gc, youdidntmove);
                bOk2SayNoWay = false;
              }
      break;

    case eend2pit:
      go (gc, east, swiss);
      go (gc, west, wend2pit);
      go (gc, cross, wend2pit);
      go (gc, down, eastpit);
      go (gc, _pit, eastpit);
      break;

    case slab:
      go (gc, south, wend2pit);
      go (gc, up, secretnscyn);
      go (gc, north, bedquilt);
      break;

    case secretnscyn:             // dragon is gc.m_nHere - allow him to retreat
      if (gc.m_nPrevLoc == slab)  // to the room he came from, but no other
         {
           go (gc, down, slab);
           go (gc, _slab, slab);
         }
      if (gc.m_nPrevLoc == secretcynne1)
         go (gc, south, secretcynne1);
      go (gc, out, gc.m_nPrevLoc);
      if (kwd (gc, north) || kwd (gc, gully) || kwd (gc, south) || kwd (gc, down))
         if (near (dragon) && (gc.m_nState [dragon] == 0))
            {
              sayMessage (gc, past_dragon);
              bOk2SayNoWay = false;
            }
         else
            {
              go (gc, _slab, slab);
              go (gc, down, slab);
              go (gc, north, mirrorcnyn);
              go (gc, gully, reservoir);
              go (gc, south, secretcynne1);
            }
      break;

    case secretnspas:
      go (gc, north, secretjunction);
      go (gc, down, bedquilt);
      go (gc, passage, bedquilt);
      go (gc, south, stalact);
      break;

    case secretjunction:
      go (gc, se, bedquilt);
      go (gc, south, secretnspas);
      go (gc, north, window2);
      break;

    case low:
      go (gc, _bedquilt, bedquilt);
      go (gc, sw, sloping);
      go (gc, north, deadend2);
      go (gc, se, oriental);
      break;

    case deadend2:
      go (gc, south, low);
      go (gc, crawl, low);
      go (gc, out, low);
      go (gc, _low, low);
      break;

    case secretew_tite:
      go (gc, east, mtking);
      go (gc, down, nscanyonwide);
      go (gc, west, secretcynne1);
      break;

    case nscanyonwide:
      go (gc, south, tighterstill);
      go (gc, north, tallewcnyn);
      break;

    case tighterstill:
      go (gc, north, nscanyonwide);
      break;

    case tallewcnyn:
      go (gc, east, nscanyonwide);
      go (gc, west, deadend3);
      go (gc, north, swiss);
      go (gc, crawl, swiss);
      break;

    case deadend3:
      go (gc, south, tallewcnyn);
      break;

    case mazea_18:
      go (gc, north, mazea_1);
      if (kwd (gc, west) || kwd (gc, south))
         {
           bFakeMove = true;
           break;
         }
      go (gc, east, mazea_19);
      break;

    case mazea_19:
      go (gc, west, mazea_18);
      go (gc, out, mazea_18);
      break;

    case mazea_20:
      go (gc, south, mazea_3);
      go (gc, out, mazea_3);
      break;

    case mazea_21:
      go (gc, south, mazea_16_pit);
      go (gc, east, mazea_22);
      go (gc, west, mazea_23);
      break;

    case mazea_22:
      go (gc, north, mazea_16_pit);
      go (gc, west, mazea_21);
      go (gc, nw, mazea_26);
      break;

    case mazea_23:
      go (gc, east, mazea_21);
      go (gc, out, mazea_21);
      break;

    case mazea_24:
      go (gc, up, mazea_11);
      go (gc, out, mazea_11);
      break;

    case mazea_25:
      go (gc, up, mazea_4);
      go (gc, down, mazea_4);
      break;

    case mazea_26:
      go (gc, se, mazea_22);
      break;

    case narrowcorrid:
      go (gc, down, westpit);
      go (gc, east, westpit);
      go (gc, west, giant);
      break;

    case incline:
      go (gc, north, cavern);
      go (gc, passage, cavern);
      go (gc, down, low);
      break;

    case giant:
      go (gc, south, narrowcorrid);
      go (gc, east, tunnel_1);
      go (gc, north, immensenspass);
      break;

    case immensenspass:
      go (gc, south, giant);
      go (gc, passage, giant);
      if (kwd (gc, north) || kwd (gc, inside))
         if (gc.m_nState [door] != 0)
            gc.m_nHere = cavern;
         else
            {
              sayMessage (gc, doorneedsoil);
              bOk2SayNoWay = false;
            }
      break;

    case cavern:
      go (gc, south, immensenspass);
      go (gc, out, immensenspass);
      go (gc, west, incline);
      if (kwd (gc, down))
         {
           gc.m_nArg2 = null;
           jumpProc (gc);
           bOk2SayNoWay = false;
         }
      break;

    case soft:
      go (gc, west, swiss);
      go (gc, out, swiss);
      break;

    case oriental:
      go (gc, se, swiss);
      go (gc, west, low);
      go (gc, _low, low);
      go (gc, crawl, low);
      go (gc, up, misty);
      go (gc, north, misty);
      break;

    case misty:
      go (gc, south, oriental);
      go (gc, west, alcove);
      break;

    case alcove:
      go (gc, nw, misty);
      if (kwd (gc, east) || kwd (gc, passage))
         if (gc.m_nInventory == 0)
            gc.m_nHere = plover;
         else
            if (gc.m_nInventory == 1)
               if (carrying (emerald))
                  gc.m_nHere = plover;
               else
                  {
                    sayMessage (gc, wont_fit);
                    bOk2SayNoWay = false;
                  }
            else
               {
                 sayMessage (gc, wont_fit);
                 bOk2SayNoWay = false;
               }
      break;

    case plover:
      go (gc, ne, dark);
      if (kwd (gc, _plover))
         {
           if (carrying (emerald))
              dropIt (emerald);
           gc.m_nHere = y2;
           break;
         }
      if (kwd (gc, west) || kwd (gc, passage))
         if (gc.m_nInventory == 0)
            gc.m_nHere = alcove;
         else
            if (gc.m_nInventory == 1)
               if (carrying (emerald))
                  gc.m_nHere = alcove;
               else
                  {
                    sayMessage (gc, wont_fit);
                    bOk2SayNoWay = false;
                  }
            else
               {
                 sayMessage (gc, wont_fit);
                 bOk2SayNoWay = false;
               }
      break;

    case dark:
      go (gc, south, plover);
      go (gc, _plover, plover);
      go (gc, out, plover);
      break;

    case arched:
      go (gc, down, shell);
      go (gc, up, arch_cor_1);
      go (gc, east, arch_cor_1);
      break;

    case shell:
      go (gc, up, arched);
      go (gc, hall, arched);
      go (gc, down, raggedcorrid);
      if (kwd (gc, south))
         if (carrying (clam))
            {
              sayMessage (gc, clam2big);
              bOk2SayNoWay = false;
            }
         else
            if (carrying (oyster))
               {
                 sayMessage (gc, oyster2big);
                 bOk2SayNoWay = false;
               }
            else
               gc.m_nHere = complex;
      break;

    case raggedcorrid:
      go (gc, up, shell);
      go (gc, _shell, shell);
      go (gc, down, culdesac);
      break;

    case culdesac:
      go (gc, up, raggedcorrid);
      go (gc, out, raggedcorrid);
      go (gc, _shell, shell);
      break;

    case anteroom:
      go (gc, up, complex);
      go (gc, west, bedquilt);
      go (gc, east, wittsend);
      break;

    case wittsend:
      go (gc, west, wittsend);
      if (kwd (gc, north) || kwd (gc, south) || kwd (gc, east) || kwd (gc, up) ||
          kwd (gc, down)  || kwd (gc, ne)    || kwd (gc, nw)   || kwd (gc, se) ||
          kwd (gc, sw))
         if (chance (95))
            {
              bFakeMove = true;
              gc.m_nHere = wittsend;
            }
         else
            gc.m_nHere = anteroom;
      break;

    case mirrorcnyn:
      go (gc, south, secretnscyn);
      go (gc, north, reservoir);
      break;

    case window2:
      go (gc, west, secretjunction);
      break;

    case stalact:
      go (gc, north, secretnspas);
      if (kwd (gc, down))
         if (chance (40))
            gc.m_nHere = mazea_9;
         else
            if (chance (50))
               gc.m_nHere = mazea_12;
            else
               gc.m_nHere = mazea_4;
      break;

    case reservoir:
      go (gc, south, mirrorcnyn);
      go (gc, out, mirrorcnyn);
      if (kwd (gc, north) || kwd (gc, cross))
         {
           sayMessage (gc, cant_swim);
           bOk2SayNoWay = false;
         }
      break;

    case reservoir_n:
      go (gc, north, warm);
      go (gc, passage, warm);
      if (kwd (gc, south) || kwd (gc, cross))
         if (near (turtle))
            {
              sayMessage (gc, turtle_back);
              gc.m_nHere = reservoir;
              gc.m_bOk2Describe = false;
            }
         else
            {
              sayMessage (gc, cant_swim);
              bOk2SayNoWay = false;
            }
      if (gc.m_nHere != gc.m_nPrevLoc)
         apport (turtle, limbo);
      break;

    case warm:
      go (gc, south, reservoir_n);
      go (gc, _reservoir, reservoir_n);
      go (gc, ne, balcony);
      go (gc, _balcony, balcony);
      break;

    case balcony:
      go (gc, west, warm);
      go (gc, out, warm);
      go (gc, _reservoir, reservoir_n);
      break;

    case swofchasm:
      go (gc, sw, sloping);
      go (gc, _balcony, sloping);
      if (kwd (gc, ne) || kwd (gc, cross))
         crossTheChasm (gc, &bOk2SayNoWay);
      break;

    case neofchasm:
      // The only way to get to the NE end of the troll bridge is to cross from the SW side
      go (gc, ne, corridor);
      go (gc, _fork, fork);
      go (gc, view, breathtaker);
      go (gc, _barren, barren);
      if (kwd (gc, sw) || kwd (gc, cross))
         crossTheChasm (gc, &bOk2SayNoWay);
      break;

    case sloping:
      go (gc, down, low);
      go (gc, up, swofchasm);
      go (gc, chasm, swofchasm);
      go (gc, out, low);
      break;

    case secretcynne1:
      go (gc, north, secretnscyn);
      go (gc, out, secretnscyn);
      go (gc, front, secretew_tite);
      go (gc, east, secretew_tite);
      break;

    case secretcynne2:    // no way to get gc.m_nHere!
      go (gc, east, secretew_tite);
      go (gc, out, secretew_tite);
      if (kwd (gc, front) || kwd (gc, north))
         if (near (dragon) && (gc.m_nState [dragon] == 0))
            {
              sayMessage (gc, past_dragon);
              bOk2SayNoWay = false;
            }
         else
            gc.m_nHere = secretnscyn;
      break;

    case corridor:
      go (gc, chasm, neofchasm);
      go (gc, west, neofchasm);
      go (gc, east, fork);
      go (gc, _fork, fork);
      go (gc, view, breathtaker);
      go (gc, _barren, barren);
      break;

    case fork:
      go (gc, chasm, neofchasm);
      go (gc, west, corridor);
      go (gc, ne, warmjunction);
      go (gc, left, warmjunction);
      go (gc, se, limestone);
      go (gc, right, limestone);
      go (gc, down, limestone);
      go (gc, view, breathtaker);
      go (gc, _barren, barren);
      break;

    case warmjunction:
      go (gc, south, fork);
      go (gc, _fork, fork);
      go (gc, north, breathtaker);
      go (gc, view, breathtaker);
      go (gc, east, boulders);
      go (gc, crawl, boulders);
      break;

    case breathtaker:
      go (gc, south, warmjunction);
      go (gc, passage, warmjunction);
      go (gc, out, warmjunction);
      go (gc, _fork, fork);
      if (kwd (gc, down))
         {
           // Let him plummet to to a painful death
           gc.m_nHere = ylem;		
           splatter (gc);
           coroner (gc);
           return;
         }
      if (kwd (gc, _valley) || kwd (gc, cross) || kwd (gc, north))
         if (gc.m_nState [wheatstone] != 2)   // no bridge
            {
              sayMessage (gc, no_arch);
              bOk2SayNoWay = false;
            }
         else
            if (carrying (bear))
               {
                 sayMessage (gc, leave_bear);   // archway looks fragile - better leave bear!
                 bOk2SayNoWay = false;
               }
            else
               if (carrying (ring))   // need ring to cross
                  {
                    if (gc.m_visited [faces] == 0)
                       sayMessage (gc, fumes_miss);
                    gc.m_nHere = faces;
                  }
               else
                  {
                    sayMessage (gc, fumes_burn);  // death
                    gc.m_nHere = ylem;
                    coroner (gc);
                    return;
                  }
      break;

    case boulders:
      go (gc, west, warmjunction);
      go (gc, out, warmjunction);
      go (gc, crawl, warmjunction);
      go (gc, _fork, fork);
      go (gc, view, breathtaker);
      break;

    case limestone:
      go (gc, north, fork);
      go (gc, up, fork);
      go (gc, south, barren);
      go (gc, down, barren);
      go (gc, _barren, barren);
      go (gc, view, breathtaker);
      break;

    case barren:
      go (gc, west, limestone);
      go (gc, up, limestone);
      go (gc, _fork, fork);
      go (gc, east, bearhere);
      go (gc, inside, bearhere);
      go (gc, _barren, bearhere);
      go (gc, view, breathtaker);
      break;

    case bearhere:
      go (gc, west, barren);
      go (gc, out, barren);
      go (gc, _fork, fork);
      go (gc, view, breathtaker);
      break;

    case limbo:
      go (gc, out, building);   // kludge
      break;

    case sandstone:
      go (gc, west, mists);
      go (gc, out, mists);
      break;

    case morion:
      go (gc, south, mtking);
      go (gc, out, mtking);
      break;

    case vault:
      if (kwd (gc, up) || kwd (gc, out) || kwd (gc, north))
         if (gc.m_nState [safe] == 1)
            {
              sayMessage (gc, safe_blocks);
              bOk2SayNoWay = false;
            }
         else
            gc.m_nHere = mtking;
      if (kwd (gc, inside))
         if (gc.m_nState [safe] == 1)
            {
              gc.m_nSafeExit = gc.m_nHere;
              gc.m_nHere = insafe;
            }
         else
            {
              sayMessage (gc, cantentersafe);
              bOk2SayNoWay = false;
            }
      break;

    case insafe:
      go (gc, out, gc.m_nSafeExit);
      break;

    case corrid_1:
      go (gc, south, mtking);
      go (gc, north, corrid_2);
      break;

    case corrid_2:
      go (gc, south, corrid_1);
      go (gc, west, corrid_1);
      go (gc, north, tool);
      go (gc, east, tool);
      break;

    case tool:
      go (gc, out, corrid_2);
      go (gc, south, corrid_2);
      break;

    case corrid_3:
      go (gc, south, mtking);
      go (gc, north, spherical);
      go (gc, east, cubicle);
      break;

    case cubicle:
      go (gc, out, corrid_3);
      go (gc, south, corrid_3);
      break;

    case spherical:
      go (gc, out, corrid_3);
      go (gc, north, corrid_3);
      break;

    case tunnel_1:
      go (gc, south, giant);
      go (gc, north, glassy);
      break;

    case glassy:
      go (gc, south, tunnel_1);
      if (kwd (gc, north) || kwd (gc, _lair))
         if (near (ogre))
            {
              bOk2SayNoWay = false;
              sayMessage (gc, ogre_blocks);
            }
         else
            gc.m_nHere = lair;
      break;

    case lair:
      go (gc, east, brink_1);
      go (gc, west, glassy);
      break;

    case brink_1:
      go (gc, north, lair);
      go (gc, west, brink_2);
      go (gc, east, brink_3);
      break;

    case brink_2:
      go (gc, north, brink_1);
      go (gc, se, ice);
      break;

    case ice:
      go (gc, nw, brink_2);
      if (kwd (gc, down) || kwd (gc, east))
         {
           sayMessage (gc, oof);
           gc.m_nHere = 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 (gc, south, icecave_1);
      go (gc, nw, icecave_7);
      if (kwd (gc, up) || kwd (gc, north))
         {
           bOk2SayNoWay = false;
           sayMessage (gc, slide_slippery);
         }
      break;

    case icecave_1:
      go (gc, north, slide);
      go (gc, south, icecave_2);
      break;

    case icecave_2:
      go (gc, north, icecave_1);
      go (gc, east, icecave_3);
      go (gc, west, icecave_5);
      break;

    case icecave_3:
      go (gc, west, icecave_2);
      go (gc, north, icecave_4);
      break;

    case icecave_4:
      go (gc, south, icecave_3);
      go (gc, out, icecave_3);
      break;

    case icecave_5:
      go (gc, north, icecave_6);
      go (gc, east, icecave_2);
      break;

    case icecave_6:
      go (gc, south, icecave_5);
      go (gc, out, icecave_5);
      break;

    case icecave_7:
      go (gc, se, slide);
      go (gc, sw, icecave_8);
      break;

    case icecave_8:
      go (gc, ne, icecave_7);
      go (gc, south, icecave_9);
      break;

    case icecave_9:
      go (gc, west, icecave_11);
      go (gc, south, icecave_10);
      go (gc, north, icecave_8);
      break;

    case icecave_10:
      go (gc, north, icecave_9);
      go (gc, out, icecave_9);
      break;

    case icecave_11:
      go (gc, north, icecave_13);
      go (gc, south, icecave_12);
      go (gc, east, icecave_9);
      break;

    case icecave_12:
      go (gc, north, icecave_11);
      go (gc, out, icecave_11);
      break;

    case icecave_13:
      go (gc, nw, icecave_14);
      go (gc, south, icecave_11);
      break;

    case icecave_14:
      go (gc, sw, icecave_15);
      go (gc, se, icecave_13);
      break;

    case icecave_15:
      go (gc, ne, icecave_14);
      go (gc, west, icecave_18);
      go (gc, south, icecave_16);
      break;

    case icecave_16:
      go (gc, north, icecave_15);
      go (gc, south, icecave_17);
      break;

    case icecave_17:
      go (gc, north, icecave_16);
      go (gc, out, icecave_16);
      break;

    case icecave_18:
      go (gc, east, icecave_15);
      go (gc, nw, icecave_21);
      go (gc, south, icecave_19);
      break;

    case icecave_19:
      go (gc, north, icecave_18);
      go (gc, south, icecave_20);
      break;

    case icecave_20:    // pig gc.m_nHere
      go (gc, north, icecave_19);
      go (gc, out, icecave_19);
      break;

    case icecave_21:
      go (gc, se, icecave_18);
      go (gc, sw, icecave_22);
      break;

    case icecave_22:
      go (gc, ne, icecave_21);
      go (gc, south, icecave_23);
      break;

    case icecave_23:
      go (gc, north, icecave_22);
      go (gc, nw, icecave_27);
      go (gc, west, icecave_26);
      go (gc, south, icecave_24);
      break;

    case icecave_24:
      go (gc, north, icecave_24);
      go (gc, west, icecave_25);
      break;

    case icecave_25:
      go (gc, north, icecave_26);
      go (gc, east, icecave_24);
      break;

    case icecave_26:
      go (gc, east, icecave_23);
      go (gc, south, icecave_25);
      break;

    case icecave_27:
      go (gc, nw, icecave_28);
      go (gc, se, icecave_23);
      break;

    case icecave_28:
      go (gc, se, icecave_27);
      go (gc, sw, icecave_29);
      break;

    case icecave_29:
      go (gc, ne, icecave_28);
      go (gc, west, icecave_35);
      go (gc, south, icecave_30);
      break;

    case icecave_30:
      go (gc, north, icecave_29);
      go (gc, nw, icecave_34);
      go (gc, south, icecave_31);
      go (gc, west, icecave_33);
      break;

    case icecave_31:
      go (gc, north, icecave_30);
      go (gc, nw, icecave_32);
      break;

    case icecave_32:
      go (gc, north, icecave_33);
      go (gc, se, icecave_31);
      break;

    case icecave_33:
      go (gc, south, icecave_32);
      go (gc, east, icecave_30);
      break;

    case icecave_34:
      go (gc, north, icecave_35);
      go (gc, se, icecave_30);
      break;

    case icecave_35:
      go (gc, east, icecave_29);
      go (gc, south, icecave_34);
      go (gc, nw, icecave_36);
      break;

    case icecave_36:    // THURB works from gc.m_nHere
      go (gc, se, icecave_35);
      go (gc, back, icecave_36);
      go (gc, out, icecave_36);
      break;

    case brink_3:
      go (gc, north, brink_1);
      go (gc, ne, crack_1);   
      go (gc, crack, crack_1);
      break;

    case crack_1:
      go (gc, sw, brink_3);
      go (gc, se, crack_2);
      break;

    case crack_2:
      go (gc, west, crack_1);
      if (kwd (gc, south))
         if (near (slime))
            {
              sayMessage (gc, slimed);
              coroner (gc);
              return;
            }
         else
            gc.m_nHere = crack_3;
      break;

    case crack_3:
      go (gc, north, crack_2);
      go (gc, south, crack_4);
      go (gc, crawl, crack_4);
      break;

    case crack_4:
      go (gc, north, crack_3);
      go (gc, out, crack_3);
      go (gc, crawl, crack_3);
      break;

    case arch_cor_1:
      go (gc, west, arched);
      if (kwd (gc, east))
      if ((gc.m_nState [quicksand] == 0) || carrying(clam) || carrying(oyster))
         {
           gc.m_nState [quicksand] = 0;
           if (gc.m_special1 [quicksand])
              sayMessage (gc, schlurp2);
           else
              {
                sayMessage (gc, schlurp);
                gc.m_special1 [quicksand] = true;
              }
           gc.m_nHere = ylem;
           coroner (gc);
           return;
         }
      else
         {
           gc.m_nHere = arch_cor_2;
           gc.m_nState [quicksand] = 0;
         }
      break;

    case arch_cor_2:
      go (gc, north, arch_fork);
      if (kwd (gc, west))
         if (gc.m_nState [quicksand] == 0)
            {
              if (gc.m_special1 [quicksand])
                 sayMessage (gc, schlurp2);
              else
                 {
                   sayMessage (gc, schlurp);
                   gc.m_special1 [quicksand] = true;
                 }
              gc.m_nHere = ylem;
              coroner (gc);
              return;
            }
         else
            {
              gc.m_nHere = arch_cor_1;
              gc.m_nState [quicksand] = 0;
            }
      break;

    case arch_fork:
      go (gc, south, arch_cor_2);
      go (gc, north, fourier);
      go (gc, east, jonah);
      break;

    case fourier:
      go (gc, nw, arch_fork);
      go (gc, sw, shelf);
      break;

    case shelf:
      go (gc, west, fourier);
      go (gc, down, beach);
      go (gc, stairs, beach);
      break;

    case beach:
      if (kwd (gc, up) || kwd (gc, stairs))
         {
           gc.m_nState [dinghy] = 1;
           gc.m_nHere = shelf;
         }
      break;

    case jonah:
      go (gc, south, in_jonah);
      go (gc, west, arch_fork);
      break;

    case in_jonah:
      go (gc, north, jonah);
      go (gc, out, jonah);
      break;

    case faces:
      go (gc, north, by_figure);
      if (kwd (gc, cross) || kwd (gc, south))
         if (gc.m_nState [wheatstone] != 2)
            {
              sayMessage (gc, no_arch);
              bOk2SayNoWay = false;
            }
         else
            if (carrying (ring))
               if (carrying (sceptre))
                  {
                    sayMessage (gc, ghost_bang);
                    gc.m_nHere = ylem;
                    gc.m_nState [wheatstone] = 0;
                    coroner (gc);
                    return;
                  }
               else
                  gc.m_nHere = breathtaker;
            else
               {
                 sayMessage (gc, fumes_burn);
                 gc.m_nHere = ylem;
                 coroner (gc);
               }
      break;

    case by_figure:
      if (gc.m_nState [statue]==1)
         {
           go (gc, nw, plain_1);
           go (gc, north, basque_1);
           go (gc, ne, banshee_1);
          }
      go (gc, south, faces);
      break;

    case plain_1:
      go (gc, south, by_figure);
      if (kwd (gc, north))
         {
           gc.m_nState [fog] = 0;   // make the fog visible
           apport (fog, plain_2);
           gc.m_nHere = plain_2;
           gc.m_bOk2Describe = false;   // 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 (gc, north) || kwd (gc, east) || kwd (gc, south) || kwd (gc, west) ||
          kwd (gc, ne) || kwd (gc, nw) || kwd (gc, se) || kwd (gc, sw))
         {
           // If he drops anything in the fog, it's gone forever!
           for (long nObject=MINOBJECTS; (nObject <= MAXOBJECTS); nObject++)
               if (nObject != fog)
                  if (gc.m_portable [nObject] &&
                      (gc.m_nWhereIs [nObject] == gc.m_nHere) &&
                      (nObject != lamp))
                     apport (nObject, ylem);

           // He can only escape if he goes to where the glow is
           if (near (glow))
              if (kwd (gc, (gc.m_nState [glow] + east)))
                 {
                   gc.m_nHere = plain_3;
                   gc.m_nState [fog] = 8;   // not so obvious
                 }
              else
                 break;   // "no way in that direction"
           else
              {
                bOk2SayNoWay = false;
                gc.m_bMoved = true;   // so we execute phog()
                break;
              }
         }
      break;

    case plain_3:
      if (kwd (gc, down))
         {
           gc.m_nHere = nondescript;
           break;
         }
      if (kwd (gc, north) || kwd (gc, east) || kwd (gc, south) || kwd (gc, west) ||
          kwd (gc, ne)    || kwd (gc, nw)   || kwd (gc, se)    || kwd (gc, sw))
         {
           gc.m_nHere = plain_2;
           apport (fog, gc.m_nHere);
           gc.m_nState [fog] = 0;       // so it starts changing again
           gc.m_bOk2Describe = false;   // so we don't say a blank room description
           gc.m_bMoved = true;          // so we execute phog()
         }
      break;

    case nondescript:
      go (gc, north, pentagram);
      if (kwd (gc, up) || kwd (gc, south))
         {
           apport (fog, plain_2);
           gc.m_nHere = plain_3;
         }
      break;

    case pentagram:
      go (gc, west, nondescript);
      go (gc, out, nondescript);
      go (gc, north, chimney);
      go (gc, crack, chimney);
      break;

    case chimney:
      go (gc, up, tube);
      go (gc, south, pentagram);
      go (gc, crack, pentagram);
      break;

    case tube:
      go (gc, down, chimney);
      go (gc, south, tube_slide);
      break;

    case tube_slide:
      go (gc, north, tube);
      if (kwd (gc, south) || kwd (gc, down))
         {
           sayMessage (gc, oof);
           gc.m_nHere = plain_1;
         }
      break;

    case basque_1:
      go (gc, south, by_figure);
      if (kwd (gc, north))
         {
           gc.m_nHere = basque_2;
           gc.m_nState [basilisk]++;
           if (gc.m_nState [basilisk] == 1)
              sayMessage (gc, bas_grumble);
         }
      break;

    case basque_2:
      go (gc, north, basque_fork);
      if (kwd (gc, south))
         {
           gc.m_nState [basilisk]--;
           if (gc.m_nState [basilisk] == 0)
              if (carrying (plate))
                 {
                   sayMessage (gc, petrify_self);
                   gc.m_nState [basilisk] = 2;
                   gc.m_bOk2Describe = false;
                 }
              else
                 {
                   sayMessage (gc, petrify_me);
                   coroner (gc);
                   return;
                 }
           gc.m_nHere = basque_1;
         }
      break;

    case basque_fork:
      go (gc, north, peelgrunt);
      go (gc, south, basque_2);
      go (gc, down, on_steps);
      go (gc, stairs, on_steps);
      break;

    case peelgrunt:
      if (kwd (gc, south) || kwd (gc, out))
         if (gc.m_nState [safe] == 1)
            {
              sayMessage (gc, safe_blocks);
              bOk2SayNoWay = false;
            }
         else
            gc.m_nHere = basque_fork;
      else
         if (kwd (gc, inside))
            if (gc.m_nState [safe] == 1)
               {
                 gc.m_nSafeExit = gc.m_nHere;
                 gc.m_nHere = insafe;
               }
            else
               {
                 sayMessage (gc, cantentersafe);
                 bOk2SayNoWay = false;
               }
      break;

    case on_steps:
      go (gc, up, basque_fork);
      go (gc, down, steps_exit);
      go (gc, stairs, steps_exit);
      break;

    case steps_exit:
      go (gc, up, on_steps);
      go (gc, down, storage);
      go (gc, north, fake_y2);
      go (gc, stairs, storage);
      go (gc, out, fake_y2);
      break;

    case storage:
      go (gc, up, steps_exit);
      go (gc, stairs, steps_exit);
      break;

    case fake_y2:
      // plover/plugh takes you to platform
      go (gc, south, steps_exit);
      go (gc, west, catacombs_1);
      go (gc, east, fake_jumble);
      go (gc, _plover, platform);
      break;

    case fake_jumble:
      go (gc, down, fake_y2);
      go (gc, west, fake_y2);
      go (gc, up, catacombs_1);
      break;

    case audience:
      go (gc, east, audience_e);
      go (gc, west, catacombs_11);
      break;

    case audience_e:
      go (gc, west, audience);
      break;

    case banshee_1:
      go (gc, nw, by_figure);
      go (gc, north, golden);
      break;

    case golden:
      go (gc, ne, arabesque);
      go (gc, nw, translucent);
      go (gc, south, banshee_1);
      break;

    case arabesque:
      go (gc, south, golden);
      go (gc, out, golden);
      break;

    case translucent:
      if (kwd (gc, out) || kwd (gc, east))
         {
           if (!gc.m_special1 [goblins])
              {
                gc.m_special1 [goblins] = true;
                apport (goblins, gc.m_nHere);
                gc.m_nState [goblins] = -1;
              }
            gc.m_nHere = golden;
         }
      break;

    case platform:
      // Only way out is by saying plover/plugh which sends you to fake Y2
      go (gc, _plover, fake_y2);
      if (kwd (gc, down) || kwd (gc, north) || kwd (gc, south) || kwd (gc, east) ||
          kwd (gc, west) || kwd (gc, ne)    || kwd (gc, nw)    || kwd (gc, se)   ||
          kwd (gc, sw))
         {
           sayMessage (gc, sizzle);
           gc.m_nHere = ylem;
           coroner (gc);
           return;
         }
      break;

    case cylinderical:
      // No way out!
      break;

    case catacombs_1:
      go (gc, south, catacombs_2);
      break;

    case catacombs_2:
      gc.m_nHere = catacombs_1;
      go (gc, sw, catacombs_3);
      break;

    case catacombs_3:
      gc.m_nHere = catacombs_2;
      go (gc, nw, catacombs_4);
      break;

    case catacombs_4:
      gc.m_nHere = catacombs_3;
      go (gc, south, catacombs_5);
      break;

    case catacombs_5:
      gc.m_nHere = catacombs_4;
      go (gc, down, catacombs_6);
      break;

    case catacombs_6:
      gc.m_nHere = catacombs_5;
      go (gc, west, catacombs_7);
      break;

    case catacombs_7:
      gc.m_nHere = catacombs_6;
      go (gc, nw, catacombs_8);
      break;

    case catacombs_8:
      gc.m_nHere = catacombs_7;
      go (gc, north, catacombs_9);
      break;

    case catacombs_9:
      gc.m_nHere = catacombs_8;
      go (gc, south, catacombs_10);
      break;

    case catacombs_10:
      gc.m_nHere = catacombs_9;
      go (gc, north, catacombs_11);
      break;

    case catacombs_11:
      gc.m_nHere = catacombs_10;
      go (gc, sw, catacombs_12);
      go (gc, east, audience);
      break;

    case catacombs_12:
      gc.m_nHere = catacombs_11;
      go (gc, east, catacombs_13);
      break;

    case catacombs_13:
      gc.m_nHere = catacombs_12;
      go (gc, se, catacombs_14);
      break;

    case catacombs_14:
      gc.m_nHere = catacombs_13;
      go (gc, ne, catacombs_15);
      break;

    case catacombs_15:
      gc.m_nHere = catacombs_14;
      go (gc, east, catacombs_16);
      break;

    case catacombs_16:
      gc.m_nHere = catacombs_15;
      go (gc, se, catacombs_17);
      break;

    case catacombs_17:
      gc.m_nHere = catacombs_16;
      go (gc, down, catacombs_18);
      break;

    case catacombs_18:
      gc.m_nHere = catacombs_17;
      go (gc, south, catacombs_19);
      break;

    case catacombs_19:
      gc.m_nHere = catacombs_18;
      go (gc, north, fake_y2);
      break;

    case mazed_107:
      go (gc, south, mazed_131);
      go (gc, sw, mazed_132);
      go (gc, ne, mazed_133);
      go (gc, se, mazed_134);
      go (gc, up, mazed_135);
      go (gc, nw, mazed_136);
      go (gc, east, mazed_137);
      go (gc, west, mazed_138);
      go (gc, north, mazed_139);
      go (gc, down, longhallwest);
      break;

    case mazed_112:
      go (gc, sw, mazed_131);
      go (gc, north, mazed_132);
      go (gc, east, mazed_133);
      go (gc, nw, mazed_134);
      go (gc, se, mazed_135);
      go (gc, ne, mazed_136);
      go (gc, west, mazed_137);
      go (gc, down, mazed_138);
      go (gc, up, mazed_139);
      go (gc, south, mazed_140);
      break;

    case mazed_131:
      go (gc, west, mazed_107);
      go (gc, se, mazed_132);
      go (gc, nw, mazed_133);
      go (gc, sw, mazed_134);
      go (gc, ne, mazed_135);
      go (gc, up, mazed_136);
      go (gc, down, mazed_137);
      go (gc, north, mazed_138);
      go (gc, south, mazed_139);
      go (gc, east, mazed_112);
      break;

    case mazed_132:
      go (gc, nw, mazed_107);
      go (gc, up, mazed_131);
      go (gc, north, mazed_133);
      go (gc, south, mazed_134);
      go (gc, west, mazed_135);
      go (gc, sw, mazed_136);
      go (gc, ne, mazed_137);
      go (gc, east, mazed_138);
      go (gc, down, mazed_139);
      go (gc, se, mazed_112);
      break;

    case mazed_133:
      go (gc, up, mazed_107);
      go (gc, down, mazed_131);
      go (gc, west, mazed_132);
      go (gc, ne, mazed_134);
      go (gc, sw, mazed_135);
      go (gc, east, mazed_136);
      go (gc, north, mazed_137);
      go (gc, nw, mazed_138);
      go (gc, se, mazed_139);
      go (gc, south, mazed_112);
      break;

    case mazed_134:
      go (gc, ne, mazed_107);
      go (gc, north, mazed_132);
      go (gc, nw, mazed_133);
      go (gc, se, mazed_136);
      go (gc, east, mazed_135);
      go (gc, down, mazed_136);
      go (gc, south, mazed_137);
      go (gc, up, mazed_138);
      go (gc, west, mazed_139);
      go (gc, sw, mazed_112);
      break;

    case mazed_135:
      go (gc, north, mazed_107);
      go (gc, se, mazed_131);
      go (gc, down, mazed_132);
      go (gc, south, mazed_133);
      go (gc, east, mazed_134);
      go (gc, west, mazed_136);
      go (gc, sw, mazed_137);
      go (gc, ne, mazed_138);
      go (gc, nw, mazed_139);
      go (gc, up, mazed_112);
      break;

    case mazed_136:
      go (gc, east, mazed_107);
      go (gc, west, mazed_131);
      go (gc, up, mazed_132);
      go (gc, sw, mazed_133);
      go (gc, down, mazed_134);
      go (gc, south, mazed_135);
      go (gc, nw, mazed_137);
      go (gc, se, mazed_138);
      go (gc, ne, mazed_139);
      go (gc, north, mazed_112);
      break;

    case mazed_137:
      go (gc, se, mazed_107);
      go (gc, ne, mazed_131);
      go (gc, south, mazed_132);
      go (gc, down, mazed_133);
      go (gc, up, mazed_134);
      go (gc, nw, mazed_135);
      go (gc, north, mazed_136);
      go (gc, sw, mazed_138);
      go (gc, east, mazed_139);
      go (gc, west, mazed_112);
      break;

    case mazed_138:
      go (gc, down, mazed_107);
      go (gc, east, mazed_131);
      go (gc, ne, mazed_132);
      go (gc, up, mazed_133);
      go (gc, west, mazed_134);
      go (gc, north, mazed_135);
      go (gc, south, mazed_136);
      go (gc, se, mazed_137);
      go (gc, sw, mazed_139);
      go (gc, nw, mazed_112);
      break;

    case mazed_139:
      go (gc, sw, mazed_107);
      go (gc, nw, mazed_131);
      go (gc, east, mazed_132);
      go (gc, west, mazed_133);
      go (gc, north, mazed_134);
      go (gc, down, mazed_135);
      go (gc, se, mazed_136);
      go (gc, up, mazed_137);
      go (gc, south, mazed_138);
      go (gc, ne, mazed_112);
      break;

    case mazed_140:
      go (gc, north, mazed_112);
      go (gc, out, mazed_112);
      break;

    // These are extensions to the 565 point version. (Ravi B)
    case nearstove:
      go (gc, south, building);
      go (gc, out, road);
      if (kwd (gc, down))
      if (!gc.m_invisible [trapdoor])
         {
           if (gc.m_nState [trapdoor] != 0)
              {
                gc.m_nHere = belowtrap;
                sayMessage (gc, trapcloses);
                gc.m_nState [trapdoor] = 0;
              }
           else
              {
                sayMessage (gc, trapclosed);
                bOk2SayNoWay = false;
              }
         }
      break;

    case belowtrap:
      go (gc, down, emergency);
      if (kwd (gc, up) || kwd (gc, _building))
         if (gc.m_invisible [trapdoor] || (gc.m_nState [trapdoor] == 0))
            {
              sayMessage (gc, traphit);
              bOk2SayNoWay = false;
            }
         else
            gc.m_nHere =  nearstove;
      break;

    case emergency:
      go (gc, up, belowtrap);
      go (gc, south, southend);
      go (gc, north, pnjunction);
      break;

    case southend:
      go (gc, north, emergency);
      go (gc, out, emergency);
      go (gc, back, emergency);
      break;

    case pnjunction:
      go (gc, south, emergency);
      go (gc, east, pcorrid);
      go (gc, west, ncorrid);
      break;

    case pcorrid:
      go (gc, west, pnjunction);
      go (gc, east, mirrorent1);
      break;

    case mirrorent1:
      go (gc, west, pcorrid);
      go (gc, east, mirrorroom);
      go (gc, inside, mirrorroom);
      break;

    case mirrorroom:
      if (kwd (gc, north) || kwd (gc, south) || kwd (gc, ne) || kwd (gc, nw) || kwd (gc, se) ||
          kwd (gc, sw)    || kwd (gc, out))
         {
           sayMessage (gc, mirror_bang);
           bOk2SayNoWay = false;
         }
      else
         if (kwd (gc, east))
            if (gc.m_nState [mirror2] == 1)   // east, west are the only way out
               gc.m_nHere = mirrorent1;       // depending on which mirror's broken
            else
               {
                 sayMessage (gc, mirror_bang);
                 bOk2SayNoWay = false;
               }
         else
            if (kwd (gc, west))
               if (gc.m_nState [mirror2] == 2)
                  gc.m_nHere = mirrorent2;
               else
                  {
                    sayMessage (gc, mirror_bang);
                    bOk2SayNoWay = false;
                  }
      break;

    case ncorrid:
      go (gc, east, pnjunction);
      go (gc, west, nslope);
      break;

    case nslope:
      go (gc, east, ncorrid);
      go (gc, back, ncorrid);
      go (gc, down, pathway);
      break;

    case pathway:
      if (kwd (gc, up) || kwd (gc, _ledge))
         {
           sayMessage (gc, ledge_high);
           bOk2SayNoWay = false;
         }
      break;

    case mirrorent2:
    case treasureroom:
    case ylem:
    default:
      go (gc, out, gc.m_nPrevLoc);
      printf ("Travel not implemented for loc %d - say \"OUT\" to leave.\n", gc.m_nHere);
      bOk2SayNoWay = false;
      break;
  }

  // If he couldn't move, tell him why
  if ((gc.m_nHere != gc.m_nPrevLoc) || bFakeMove)
     gc.m_bMoved = true;
  else
     if (bOk2SayNoWay)
        {
          gc.m_bOk2Describe = false;
          switch (gc.m_nArg1)
          {
            // Either he's already there or we need detailed instructions
            case surface:
            case outdoors:
              if (gc.m_notInCave [gc.m_nHere])
                 sayMessage (gc, you_are_there);
              else
                 sayMessage (gc, needdetail);
              break;

            case cave:
              if (gc.m_notInCave [gc.m_nHere])
                 sayMessage (gc, needdetail);
              else
                 sayMessage (gc, you_are_there);
              break;

            case _building:
              if (at (building) || at (nearstove))
                 sayMessage (gc, you_are_there);
              else
                 sayMessage (gc, needdetail);
              break;

            case entrance:
              if (at (road))
                 sayMessage (gc, you_are_there);
              else
                 sayMessage (gc, needdetail);
              break;

            case gully:
              if (at (valley))
                 sayMessage (gc, you_are_there);
              else
                 sayMessage (gc, needdetail);
              break;

            case stream:
              if (at (slit))
              sayMessage (gc, you_are_there);
              else
              sayMessage (gc, needdetail);
              break;

            case _depression:
              if (at (depression))
                 sayMessage (gc, you_are_there);
              else
                 sayMessage (gc, needdetail);
              break;

            case _valley:
              if (at (valley))
                 sayMessage (gc, you_are_there);
              else
                 sayMessage (gc, needdetail);
              break;

            case _forest:
              if (at (forest) || at (forest2))
                 sayMessage (gc, you_are_there);
              else
                 sayMessage (gc, needdetail);
              break;

            case _pit:
              if (at (eastpit) || at (westpit) || at (streampit) || at (mazea_16_pit))
                 sayMessage (gc, you_are_there);
              else
                 sayMessage (gc, needdetail);
              break;

            case _slab:
              if (at (slab))
                 sayMessage (gc, you_are_there);
              else
                 sayMessage (gc, needdetail);
              break;

            case _bedquilt:
              if (at (bedquilt))
                 sayMessage (gc, you_are_there);
              else
                 sayMessage (gc, needdetail);
              break;

            case _low:
              if (at (low))
                 sayMessage (gc, you_are_there);
              else
                 sayMessage (gc, needdetail);
              break;

            // Be specific, pal!
            case inside:
              if (at (building) || at (incave))
                 {
                   sayMessage (gc, you_are_there);
                   break;
                 }
              else
                 sayMessage (gc, infromout);
              break;

            case out:
              if (at (road) || at (depression))
                 {
                   sayMessage (gc, you_are_there);
                   break;
                 }
              else
                 sayMessage (gc, infromout);
              break;

            case front:
            case left:
            case right:
              sayMessage (gc, iamunsure);
              break;

            case _y2:
              if (at (y2))
                 sayMessage (gc, you_are_there);
              else
                 sayMessage (gc, needdetail);
              break;

            case _plover:
              sayMessage (gc, nothing);
              break;

            // Sorry, no way to go in that direction
            default:
              if (isPlace (gc.m_nArg1))
                 sayMessage (gc, needdetail);
              else
                 sayMessage (gc, nocango);
              break;
          }
        }
}

////////////////////
// Private functions

void crossTheChasm
  (AdvGlobalContext&  gc,             // global context
   bool*              pOk2SayNoWay)   // flag: OK to say "No way to go in that direction"
//
//  Logic used for crossing the chasm.  This function is called by travel().
//
{
  if (gc.m_nState [chasm] != 0)
     {
       sayMessage (gc, no_bridge);    // There is no longer any way across the chasm.
       *pOk2SayNoWay = false;
     }
  else
     // 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)
     switch (gc.m_nState [troll])
     {
       case 0:
         // The troll refuses to let you cross
         apport (troll, gc.m_nHere);
         sayMessage (gc, troll_sez_no);
         *pOk2SayNoWay = false;
         break;

       case 1:
         // Egg toll paid, FFFF done, trying to cross
         if (gc.m_special1 [troll])
            {
              if (carrying (bear))
                 {
                   // Troll zaps bear and adventurer
                   sayMessage (gc, revenge);
                   apport (bear, limbo);
                   gc.m_nState [chasm] = 1;
                 }
              else
                 {
                   // Troll zaps adventurer
                   gc.m_nState [chasm] = 2;
                   sayMessage (gc, revenge_1);
                 }
              apport (troll2, limbo);
              gc.m_nHere = ylem;
              coroner (gc);
              return;
            }
         else
            // Toll paid, FFFF not done, trying to cross
            {
              if (carrying (bear))
                 {
                   sayMessage (gc, bear_bridge);  // Just as you reach the other side, the bridge buckles
                   gc.m_nState [chasm] = 1;		    // beneath the weight of the bear, which was still following
                   apport (troll2, limbo);		    // you around. You scramble desperately for support, but as
                   gc.m_nHere = ylem;			        // the bridge collapses you stumble back and fall into the
                   coroner (gc);                  // chasm.
                   return;
                 }
              else
                 {
                   gc.m_nState [troll] = 2;   // No description for this state
                   gc.m_nHere = (gc.m_nHere == swofchasm ? neofchasm : swofchasm);
                   gc.m_special2 [troll] = (gc.m_nHere == neofchasm);
                 }
            }
         break;

       case 2:
         describeObject (gc, troll, 3);       // Steps out from beneath the bridge and demands more treasure
         gc.m_nState [troll] = 0;
         apport (troll, gc.m_nHere);
         apport (troll2, limbo);
         *pOk2SayNoWay = false;
         break;

       case 4:
         // Crossing after scaring troll with bear
         if (carrying (bear))
            {
              apport (bear, limbo);
              gc.m_nState [chasm] = 1;
              if (gc.m_special1 [troll])
                 sayMessage (gc, revenge);        // Troll zaps bear and adventurer
              else
                 sayMessage (gc, bear_bridge);    // Bear and adventurer fall into the chasm
              apport (troll2, limbo);
              gc.m_nHere = ylem;
              coroner (gc);
              return;
            }
         else
            if (gc.m_special1 [troll])
               {
                 sayMessage (gc, revenge_1);    // Troll zaps adventurer
                 gc.m_nState [chasm] = 2;
                 gc.m_nHere = ylem;
                 coroner (gc);
                 return;
               }
            else
               {
                 gc.m_nState [troll] = 2;       // No description for this state
                 gc.m_nHere = (gc.m_nHere == swofchasm ? neofchasm : swofchasm);
               }
         break;

       default:
         printf ("GLITCH!  Troll (%d) at %d\n", gc.m_nState [troll], gc.m_nHere);
         printf ("Please send a bug report to ravib@ravib.com.  Thanks!\n");
         *pOk2SayNoWay = false;
         break;
  }
}

void go
  (AdvGlobalContext&  gc,             // global context
   long               nCommand,       // command
   long               nDestination)   // destination location
//
//  Travels to specified destination on specified command.
//
{
  if (kwd (gc, nCommand))
     gc.m_nHere = nDestination;
}

bool kwd
  (AdvGlobalContext&  gc,         // global context
   long               nCommand)   // command
//
//  Returns true if command contains specified keyword.
//
{
  if ((gc.m_nArg1 == nCommand) || (gc.m_nArg2 == nCommand))
     return (true);
  return (false);
}
