337 lines
		
	
	
		
			6.6 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			337 lines
		
	
	
		
			6.6 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
| /*	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;
 | |
| }
 | 
