minix/commands/advent/travel.c
2009-11-09 10:26:00 +00:00

336 lines
6.6 KiB
C

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