text: /*	module TRAVEL.C						*
   *      Routine to handle motion requests			*/
  
  
  #include	<stdio.h>
  #include	<stdlib.h>
  #include	"advent.h"
  #include	"advdec.h"
  #include	"advcave.h"
  
  struct trav travel[MAXTRAV];
  static int kalflg;
  static int bcrossing = 0;
  static int phuce[2][4] = {158, 160, 167, 166,
  			  160, 158, 166, 167};
  
  _PROTOTYPE(static void goback, (void));
  _PROTOTYPE(static void ck_kal, (void));
  _PROTOTYPE(static void dotrav, (void));
  _PROTOTYPE(static void badmove, (void));
  _PROTOTYPE(static void spcmove, (int rdest));
  
  void domove()
  {
      gettrav(g.loc, travel);
      switch (motion) {
      case NULLX:
  	break;
      case BACK:
  	goback();
  	break;
      case CAVE:
  	if (outside(g.loc))
  	    rspeak(57);
  	else
  	    rspeak(58);
  	break;
      default:
  	g.oldloc2 = g.oldloc;
  	g.oldloc = g.loc;
  	dotrav();
      }
      newtravel = TRUE;
      return;
  }
  
  /*
    Routine to handle request to return
    from whence we came!
  */
  static void goback()
  {
      int kk, k2, want, temp;
      struct trav strav[MAXTRAV];
  
      want = forced(g.oldloc) ? g.oldloc2 : g.oldloc;
      g.oldloc2 = g.oldloc;
      g.oldloc = g.loc;
      k2 = 0;
      if (want == g.loc) {
  	rspeak(91);
  	ck_kal();
  	return;
      }
      for (kk = 0; travel[kk].tdest != -1; ++kk) {
  	if (!travel[kk].tcond && travel[kk].tdest == want) {
  	    motion = travel[kk].tverb;
  	    dotrav();
  	    return;
  	}
  	if (!travel[kk].tcond) {
  	    temp = travel[kk].tdest;
  	    gettrav(temp, strav);
  	    if (forced(temp) && strav[0].tdest == want)
  		k2 = temp;
  	}
      }
      if (k2) {
  	motion = travel[k2].tverb;
  	dotrav();
      } else
  	rspeak(140);
      ck_kal();
      return;
  }
  
  static void ck_kal()
  {
      if (g.newloc >= 242 && g.newloc <= 247) {
  	if (g.newloc == 242)
  	    kalflg = 0;
  	else if (g.newloc == (g.oldloc + 1))
  	    kalflg++;
  	else
  	    kalflg = -10;
      }
  }
  
  /*
    Routine to figure out a new location
    given current location and a motion.
  */
  static void dotrav()
  {
      unsigned char mvflag, hitflag, kk;
      int rdest, rverb, rcond, robject;
      int pctt;
  
      g.newloc = g.loc;
      mvflag = hitflag = 0;
      pctt = ranz(100);
  
      for (kk = 0; travel[kk].tdest >= 0 && !mvflag; ++kk) {
  	rdest = travel[kk].tdest;
  	rverb = travel[kk].tverb;
  	rcond = travel[kk].tcond;
  	robject = rcond % 100;
  
  	if ((rverb != 1) && (rverb != motion) && !hitflag)
  	    continue;
  	++hitflag;
  	switch (rcond / 100) {
  	case 0:
  	    if ((rcond == 0) || (pctt < rcond))
  		++mvflag;
  	    break;
  	case 1:
  	    if (robject == 0)
  		++mvflag;
  	    else if (toting(robject))
  		++mvflag;
  	    break;
  	case 2:
  	    if (toting(robject) || at(robject))
  		++mvflag;
  	    break;
  	case 3:
  	case 4:
  	case 5:
  	case 7:
  	    if (g.prop[robject] != (rcond / 100) - 3)
  		++mvflag;
  	    break;
  	default:
  	    bug(37);
  	}
      }
      if (!mvflag)
  	badmove();
      else if (rdest > 500)
  	rspeak(rdest - 500);
      else if (rdest > 300)
  	spcmove(rdest);
      else {
  	g.newloc = rdest;
  	ck_kal();
      }
      newtravel = TRUE;
      return;
  }
  
  /*
    The player tried a poor move option.
  */
  static void badmove()
  {
      int msg;
  
      msg = 12;
      if (motion >= 43 && motion <= 50)
  	msg = 9;
      if (motion == 29 || motion == 30)
  	msg = 9;
      if (motion == 7 || motion == 36 || motion == 37)
  	msg = 10;
      if (motion == 11 || motion == 19)
  	msg = 11;
      if (motion == 62 || motion == 65 || motion == 82)
  	msg = 42;
      if (motion == 17)
  	msg = 80;
      rspeak(msg);
      return;
  }
  
  /*
    Routine to handle very special movement.
  */
  static void spcmove(rdest)
  int rdest;
  {
      int load, obj, k;
  
      switch (rdest - 300) {
      case 1:				/* plover movement via alcove */
  	load = burden(0);
  	if (!load || (load == burden(EMERALD) && holding(EMERALD)))
  	    g.newloc = (99 + 100) - g.loc;
  	else
  	    rspeak(117);
  	break;
      case 2:				/* trying to remove plover, bad
  					   route */
  	if (enclosed(EMERALD))
  	    extract(EMERALD);
  	drop(EMERALD, g.loc);
  	g.newloc = 33;
  	break;
      case 3:				/* troll bridge */
  	if (g.prop[TROLL] == 1) {
  	    pspeak(TROLL, 1);
  	    g.prop[TROLL] = 0;
  	    move(TROLL2, 0);
  	    move((TROLL2 + MAXOBJ), 0);
  	    move(TROLL, plac[TROLL]);
  	    move((TROLL + MAXOBJ), fixd[TROLL]);
  	    juggle(CHASM);
  	    g.newloc = g.loc;
  	} else {
  	    g.newloc = plac[TROLL] + fixd[TROLL] - g.loc;
  	    if (g.prop[TROLL] == 0)
  		g.prop[TROLL] = 1;
  	    if (toting(BEAR)) {
  		rspeak(162);
  		g.prop[CHASM] = 1;
  		g.prop[TROLL] = 2;
  		drop(BEAR, g.newloc);
  		g.fixed[BEAR] = -1;
  		g.prop[BEAR] = 3;
  		if (g.prop[SPICES] < 0)
  		    ++g.tally2;
  		g.oldloc2 = g.newloc;
  		death();
  	    }
  	}
  	break;
      case 4:
  	/* Growing or shrinking in area of tiny door.  Each time he
  	   does this, everything must be moved to the new loc.
  	   Presumably, all his possesions are shrunk or streched along
  	   with him. Phuce[2][4] is an array containg four pairs of
  	   "here" (K) and "there" (KK) locations. */
  	k = phuce[0][g.loc - 161];
  	g.newloc = phuce[1][g.loc - 161];
  	for (obj = 1; obj < MAXOBJ; obj++) {
  	    if (obj == BOAT)
  		continue;
  	    if (g.place[obj] == k && (g.fixed[obj] == 0 || g.fixed[obj] == -1))
  		move(obj, g.newloc);
  	}
  	break;
      case 5:
  	/* Phone booth in rotunda. Trying to shove past gnome, to get
  	   into phone booth. */
  	if ((g.prop[BOOTH] == 0 && pct(35)) || g.visited[g.loc] == 1) {
  	    rspeak(263);
  	    g.prop[BOOTH] = 1;
  	    move(GNOME, 188);
  	} else {
  	    if (g.prop[BOOTH] == 1)
  		rspeak(253);
  	    else
  		g.newloc = 189;
  	}
  	break;
      case 6:
  	/* Collapsing clay bridge.  He can cross with three (or fewer)
  	   thing.  If more, of if carrying obviously heavy things, he
  	   may end up in the drink. */
  	g.newloc = g.loc == 235 ? 190 : 235;
  	bcrossing++;
  	load = burden(0);
  	if (load > 4) {
  	    k = (load + bcrossing) * 6 - 10;
  	    if (!pct(k))
  		rspeak(318);
  	    else {
  		rspeak(319);
  		g.newloc = 236;
  		if (holding(LAMP))
  		    move(LAMP, 236);
  		if (toting(AXE) && enclosed(AXE))
  		    extract(AXE);
  		if (holding(AXE))
  		    move(AXE, 208);
  		for (obj = 1; obj < MAXOBJ; obj++)
  		    if (toting(obj))
  			destroy(obj);
  		g.prop[CHASM2] = 1;
  	    }
  	}
  	break;
      case 7:
  	/* Kaleidoscope code is here. */
  	if (kalflg == 5) {
  	    g.newloc = 248;
  	    g.oldloc = 247;
  	} else {
  	    g.newloc = 242 + ranz(5);
  	    g.oldloc = g.newloc - 1;
  	    kalflg = g.newloc == 242 ? 0 : -10;
  	}
  	break;
      default:
  	bug(38);
      }
      return;
  }
  
  /*
    Routine to fill travel array for a given location
  */
  void gettrav(loc, travel)
  int loc;
  struct trav *travel;
  {
      int i;
      long t, *lptr;
  
      lptr = cave[loc - 1];
      for (i = 0; i < MAXTRAV; i++) {
  	t = *lptr++;
  	if (!(t)) {
  	    travel->tdest = -1;		/* end of array	 */
  	    return;			/* terminate for loop	 */
  	}
  	travel->tverb = (int) (t % 1000);
  	t /= 1000;
  	travel->tdest = (int) (t % 1000);
  	t /= 1000;
  	travel->tcond = (int) (t % 1000);
  	travel++;
      }
      bug(25);
      return;
  }
  