+/* "You're dead, Jim."
+ *
+ * If the current loc is zero, it means the clown got himself killed.
+ * We'll allow this maxdie times. MAXDIE is automatically set based
+ * on the number of snide messages available. Each death results in
+ * a message (81, 83, etc.) which offers reincarnation; if accepted,
+ * this results in message 82, 84, etc. The last time, if he wants
+ * another chance, he gets a snide remark as we exit. When
+ * reincarnated, all objects being carried get dropped at game.oldlc2
+ * (presumably the last place prior to being killed) without change
+ * of props. the loop runs backwards to assure that the bird is
+ * dropped before the cage. (this kluge could be changed once we're
+ * sure all references to bird and cage are done by keywords.) The
+ * lamp is a special case (it wouldn't do to leave it in the cave).
+ * It is turned off and left outside the building (only if he was
+ * carrying it, of course). He himself is left inside the building
+ * (and heaven help him if he tries to xyzzy back into the cave
+ * without the lamp!). game.oldloc is zapped so he can't just
+ * "retreat". */
+
+static void croak(FILE *cmdin)
+/* Okay, he's dead. Let's get on with it. */
+{
+ if (game.closng) {
+ /* He died during closing time. No resurrection. Tally up a
+ * death and exit. */
+ RSPEAK(131);
+ ++game.numdie;
+ score(0);
+ } else {
+ ++game.numdie;
+ if (!YES(cmdin,79+game.numdie*2,80+game.numdie*2,54))
+ score(0);
+ if (game.numdie == MAXDIE)
+ score(0);
+ game.place[WATER]=0;
+ game.place[OIL]=0;
+ if (TOTING(LAMP))
+ game.prop[LAMP]=0;
+ for (int j=1; j<=NOBJECTS; j++) {
+ int i=NOBJECTS + 1 - j;
+ if (TOTING(i)) {
+ int k=game.oldlc2;
+ if (i == LAMP)
+ k=1;
+ DROP(i,k);
+ }
+ }
+ game.loc=3;
+ game.oldloc=game.loc;
+ }
+}
+
+/* Given the current location in "game.loc", and a motion verb number in
+ * "K", put the new location in "game.newloc". The current loc is saved
+ * in "game.oldloc" in case he wants to retreat. The current
+ * game.oldloc is saved in game.oldlc2, in case he dies. (if he
+ * does, game.newloc will be limbo, and game.oldloc will be what killed
+ * him, so we need game.oldlc2, which is the last place he was
+ * safe.) */
+
+static bool playermove(FILE *cmdin, token_t verb)
+{
+ int LL, K2, KK=KEY[game.loc], motion = K;
+ game.newloc=game.loc;
+ if (KK == 0)
+ BUG(26);
+ if (motion == NUL)
+ return true;
+ else if (motion == BACK) {
+ /* Handle "go back". Look for verb which goes from game.loc to
+ * game.oldloc, or to game.oldlc2 If game.oldloc has forced-motion.
+ * K2 saves entry -> forced loc -> previous loc. */
+ motion=game.oldloc;
+ if (FORCED(motion))
+ motion=game.oldlc2;
+ game.oldlc2=game.oldloc;
+ game.oldloc=game.loc;
+ K2=0;
+ if (motion == game.loc)K2=91;
+ if (CNDBIT(game.loc,4))K2=274;
+ if (K2 == 0) {
+ for (;;) {
+ LL=MOD((labs(TRAVEL[KK])/1000),1000);
+ if (LL != motion) {
+ if (LL <= 300) {
+ if (FORCED(LL) && MOD((labs(TRAVEL[KEY[LL]])/1000),1000) == motion)
+ K2=KK;
+ }
+ if (TRAVEL[KK] >= 0) {
+ ++KK;
+ continue;
+ }
+ KK=K2;
+ if (KK == 0) {
+ RSPEAK(140);
+ return true;
+ }
+ }
+
+ motion=MOD(labs(TRAVEL[KK]),1000);
+ KK=KEY[game.loc];
+ break; /* fall through to ordinary travel */
+ }
+ } else {
+ RSPEAK(K2);
+ return true;
+ }
+ }
+ else if (motion == LOOK) {
+ /* Look. Can't give more detail. Pretend it wasn't dark
+ * (though it may "now" be dark) so he won't fall into a
+ * pit while staring into the gloom. */
+ if (game.detail < 3)RSPEAK(15);
+ ++game.detail;
+ game.wzdark=false;
+ game.abbrev[game.loc]=0;
+ return true;
+ }
+ else if (motion == CAVE) {
+ /* Cave. Different messages depending on whether above ground. */
+ RSPEAK((OUTSID(game.loc) && game.loc != 8) ? 57 : 58);
+ return true;
+ }
+ else {
+ /* none of the specials */
+ game.oldlc2=game.oldloc;
+ game.oldloc=game.loc;
+ }
+
+ /* ordinary travel */
+ for (;;) {
+ LL=labs(TRAVEL[KK]);
+ if (MOD(LL,1000) == 1 || MOD(LL,1000) == motion)
+ break;
+ if (TRAVEL[KK] < 0) {
+ /* Non-applicable motion. Various messages depending on
+ * word given. */
+ int spk=12;
+ if (motion >= 43 && motion <= 50)spk=52;
+ if (motion == 29 || motion == 30)spk=52;
+ if (motion == 7 || motion == 36 || motion == 37)spk=10;
+ if (motion == 11 || motion == 19)spk=11;
+ if (verb == FIND || verb == INVENT)spk=59;
+ if (motion == 62 || motion == 65)spk=42;
+ if (motion == 17)spk=80;
+ RSPEAK(spk);
+ return true;
+ }
+ ++KK;
+ }
+ LL=LL/1000;
+
+ for (;;) {
+ game.newloc=LL/1000;
+ motion=MOD(game.newloc,100);
+ if (game.newloc <= 300) {
+ if (game.newloc <= 100) {
+ if (game.newloc == 0 || PCT(game.newloc))
+ break;
+ /* else fall through */
+ } if (TOTING(motion) || (game.newloc > 200 && AT(motion)))
+ break;
+ /* else fall through */
+ }
+ else if (game.prop[motion] != game.newloc/100-3)
+ break;
+ L12:
+ do {
+ if (TRAVEL[KK] < 0)BUG(25);
+ ++KK;
+ game.newloc=labs(TRAVEL[KK])/1000;
+ } while
+ (game.newloc == LL);
+ LL=game.newloc;
+ }
+
+ game.newloc=MOD(LL,1000);
+ if (game.newloc <= 300)
+ return true;
+ if (game.newloc <= 500) {
+ game.newloc=game.newloc-300;
+ switch (game.newloc)
+ {
+ case 1:
+ /* Travel 301. Plover-alcove passage. Can carry only
+ * emerald. Note: travel table must include "useless"
+ * entries going through passage, which can never be used for
+ * actual motion, but can be spotted by "go back". */
+ game.newloc=99+100-game.loc;
+ if (game.holdng == 0 || (game.holdng == 1 && TOTING(EMRALD)))
+ return true;
+ game.newloc=game.loc;
+ RSPEAK(117);
+ return true;
+ case 2:
+ /* Travel 302. Plover transport. Drop the emerald (only use
+ * special travel if toting it), so he's forced to use the
+ * plover-passage to get it out. Having dropped it, go back and
+ * pretend he wasn't carrying it after all. */
+ DROP(EMRALD,game.loc);
+ goto L12;
+ case 3:
+ /* Travel 303. Troll bridge. Must be done only as special
+ * motion so that dwarves won't wander across and encounter
+ * the bear. (They won't follow the player there because
+ * that region is forbidden to the pirate.) If
+ * game.prop(TROLL)=1, he's crossed since paying, so step out
+ * and block him. (standard travel entries check for
+ * game.prop(TROLL)=0.) Special stuff for bear. */
+ if (game.prop[TROLL] == 1) {
+ PSPEAK(TROLL,1);
+ game.prop[TROLL]=0;
+ MOVE(TROLL2,0);
+ MOVE(TROLL2+NOBJECTS,0);
+ MOVE(TROLL,PLAC[TROLL]);
+ MOVE(TROLL+NOBJECTS,FIXD[TROLL]);
+ JUGGLE(CHASM);
+ game.newloc=game.loc;
+ return true;
+ } else {
+ game.newloc=PLAC[TROLL]+FIXD[TROLL]-game.loc;
+ if (game.prop[TROLL] == 0)game.prop[TROLL]=1;
+ if (!TOTING(BEAR)) return true;
+ RSPEAK(162);
+ game.prop[CHASM]=1;
+ game.prop[TROLL]=2;
+ DROP(BEAR,game.newloc);
+ game.fixed[BEAR]= -1;
+ game.prop[BEAR]=3;
+ game.oldlc2=game.newloc;
+ croak(cmdin);
+ return false;
+ }
+ }
+ BUG(20);
+ }
+ RSPEAK(game.newloc-500);
+ game.newloc=game.loc;
+ return true;
+}
+
+static bool do_command(FILE *cmdin)
+{
+ long KQ, VERB, KK, V1, V2;