- goto L2000;
-
-/* Things are in full swing. Move each dwarf at random, except if he's seen us
- * he sticks with us. Dwarves stay deep inside. If wandering at random,
- * they don't back up unless there's no alternative. If they don't have to
- * move, they attack. And, of course, dead dwarves don't do much of anything. */
-
-L6010: game.dtotal=0;
- ATTACK=0;
- STICK=0;
- /* 6030 */ for (I=1; I<=NDWARVES; I++) {
- if(game.dloc[I] == 0) goto L6030;
-/* Fill TK array with all the places this dwarf might go. */
- J=1;
- KK=game.dloc[I];
- KK=KEY[KK];
- if(KK == 0) goto L6016;
-L6012: game.newloc=MOD(labs(TRAVEL[KK])/1000,1000);
- {long x = J-1;
- if(game.newloc > 300 || !INDEEP(game.newloc) || game.newloc == game.odloc[I] || (J > 1 &&
- game.newloc == TK[x]) || J >= 20 || game.newloc == game.dloc[I] ||
- FORCED(game.newloc) || (I == 6 && CNDBIT(game.newloc,3)) ||
- labs(TRAVEL[KK])/1000000 == 100) goto L6014;}
- TK[J]=game.newloc;
- J=J+1;
-L6014: KK=KK+1;
- {long x = KK-1; if(TRAVEL[x] >= 0) goto L6012;}
-L6016: TK[J]=game.odloc[I];
- if(J >= 2)J=J-1;
- J=1+randrange(J);
- game.odloc[I]=game.dloc[I];
- game.dloc[I]=TK[J];
- game.dseen[I]=(game.dseen[I] && INDEEP(game.loc)) || (game.dloc[I] == game.loc || game.odloc[I] == game.loc);
- if(!game.dseen[I]) goto L6030;
- game.dloc[I]=game.loc;
- if(I != 6) goto L6027;
-
-/* The pirate's spotted him. He leaves him alone once we've found chest. K
- * counts if a treasure is here. If not, and tally=1 for an unseen chest, let
- * the pirate be spotted. Note that game.place(CHEST)=0 might mean that he's
- * thrown it to the troll, but in that case he's seen the chest (game.prop=0). */
-
- if(game.loc == game.chloc || game.prop[CHEST] >= 0) goto L6030;
- K=0;
- /* 6020 */ for (J=50; J<=MAXTRS; J++) {
-/* Pirate won't take pyramid from plover room or dark room (too easy!). */
- if(J == PYRAM && (game.loc == PLAC[PYRAM] || game.loc == PLAC[EMRALD])) goto L6020;
- if(TOTING(J)) goto L6021;
-L6020: if(HERE(J))K=1;
- } /* end loop */
- if(game.tally == 1 && K == 0 && game.place[CHEST] == 0 && HERE(LAMP) && game.prop[LAMP]
- == 1) goto L6025;
- if(game.odloc[6] != game.dloc[6] && PCT(20))RSPEAK(127);
- goto L6030;
-
-L6021: if(game.place[CHEST] != 0) goto L6022;
-/* Install chest only once, to insure it is the last treasure in the list. */
- MOVE(CHEST,game.chloc);
- MOVE(MESSAG,game.chloc2);
-L6022: RSPEAK(128);
- /* 6023 */ for (J=50; J<=MAXTRS; J++) {
- if(J == PYRAM && (game.loc == PLAC[PYRAM] || game.loc == PLAC[EMRALD])) goto L6023;
- if(AT(J) && game.fixed[J] == 0)CARRY(J,game.loc);
- if(TOTING(J))DROP(J,game.chloc);
-L6023: /*etc*/ ;
- } /* end loop */
-L6024: game.dloc[6]=game.chloc;
- game.odloc[6]=game.chloc;
- game.dseen[6]=false;
- goto L6030;
-
-L6025: RSPEAK(186);
- MOVE(CHEST,game.chloc);
- MOVE(MESSAG,game.chloc2);
- goto L6024;
-
-/* This threatening little dwarf is in the room with him! */
-
-L6027: game.dtotal=game.dtotal+1;
- if(game.odloc[I] != game.dloc[I]) goto L6030;
- ATTACK=ATTACK+1;
- if(game.knfloc >= 0)game.knfloc=game.loc;
- if(randrange(1000) < 95*(game.dflag-2))STICK=STICK+1;
-L6030: /*etc*/ ;
- } /* end loop */
-
-/* Now we know what's happening. Let's tell the poor sucker about it.
- * Note that various of the "knife" messages must have specific relative
- * positions in the RSPEAK database. */
-
- if(game.dtotal == 0) goto L2000;
- SETPRM(1,game.dtotal,0);
- RSPEAK(4+1/game.dtotal);
- if(ATTACK == 0) goto L2000;
- if(game.dflag == 2)game.dflag=3;
- SETPRM(1,ATTACK,0);
- K=6;
- if(ATTACK > 1)K=250;
- RSPEAK(K);
- SETPRM(1,STICK,0);
- RSPEAK(K+1+2/(1+STICK));
- if(STICK == 0) goto L2000;
- game.oldlc2=game.loc;
- goto L99;
-
-/* Describe the current location and (maybe) get next command. */
-
-/* Print text for current loc. */
-
-L2000: if(game.loc == 0) goto L99;
+ return true;
+ }
+
+ /* Things are in full swing. Move each dwarf at random,
+ * except if he's seen us he sticks with us. Dwarves stay
+ * deep inside. If wandering at random, they don't back up
+ * unless there's no alternative. If they don't have to
+ * move, they attack. And, of course, dead dwarves don't do
+ * much of anything. */
+ game.dtotal=0;
+ attack=0;
+ stick=0;
+ for (int i=1; i<=NDWARVES; i++) {
+ int k;
+ if (game.dloc[i] == 0)
+ continue;
+ /* Fill TK array with all the places this dwarf might go. */
+ int j=1;
+ kk=KEY[game.dloc[i]];
+ if (kk != 0)
+ do {
+ game.newloc=MOD(labs(TRAVEL[kk])/1000,1000);
+ /* Have we avoided a dwarf enciounter? */
+ bool avoided = (game.newloc > 300 ||
+ !INDEEP(game.newloc) ||
+ game.newloc == game.odloc[i] ||
+ (j > 1 && game.newloc == TK[j-1]) ||
+ j >= 20 ||
+ game.newloc == game.dloc[i] ||
+ FORCED(game.newloc) ||
+ (i == PIRATE && CNDBIT(game.newloc,3)) ||
+ labs(TRAVEL[kk])/1000000 == 100);
+ if (!avoided) {
+ TK[j++] = game.newloc;
+ }
+ ++kk;
+ } while
+ (TRAVEL[kk-1] >= 0);
+ TK[j]=game.odloc[i];
+ if (j >= 2)
+ --j;
+ j=1+randrange(j);
+ game.odloc[i]=game.dloc[i];
+ game.dloc[i]=TK[j];
+ game.dseen[i]=(game.dseen[i] && INDEEP(game.loc)) || (game.dloc[i] == game.loc || game.odloc[i] == game.loc);
+ if (!game.dseen[i]) continue;
+ game.dloc[i]=game.loc;
+ if (i == PIRATE) {
+ /* The pirate's spotted him. He leaves him alone once we've
+ * found chest. K counts if a treasure is here. If not, and
+ * tally=1 for an unseen chest, let the pirate be spotted.
+ * Note that game.place(CHEST)=0 might mean that he's thrown
+ * it to the troll, but in that case he's seen the chest
+ * (game.prop=0). */
+ if (game.loc == game.chloc || game.prop[CHEST] >= 0)
+ continue;
+ k=0;
+ for (int j=MINTRS; j<=MAXTRS; j++) {
+ /* Pirate won't take pyramid from plover room or dark
+ * room (too easy!). */
+ if (j == PYRAM && (game.loc == PLAC[PYRAM] || game.loc == PLAC[EMRALD])) {
+ if (HERE(j))
+ k=1;
+ continue;
+ }
+ if (TOTING(j)) {
+ if (game.place[CHEST] == 0) {
+ /* Install chest only once, to insure it is
+ * the last treasure in the list. */
+ MOVE(CHEST,game.chloc);
+ MOVE(MESSAG,game.chloc2);
+ }
+ RSPEAK(128);
+ for (int j=MINTRS; j<=MAXTRS; j++) {
+ if (!(j == PYRAM && (game.loc == PLAC[PYRAM] || game.loc == PLAC[EMRALD]))) {
+ if (AT(j) && game.fixed[j] == 0)
+ CARRY(j,game.loc);
+ if (TOTING(j))
+ DROP(j,game.chloc);
+ }
+ }
+ game.dloc[PIRATE]=game.chloc;
+ game.odloc[PIRATE]=game.chloc;
+ game.dseen[PIRATE]=false;
+ goto jumpout;
+ }
+ if (HERE(j))
+ k=1;
+ }
+ /* Force chest placement before player finds last treasure */
+ if (game.tally == 1 && k == 0 && game.place[CHEST] == 0 && HERE(LAMP) && game.prop[LAMP] == 1) {
+ RSPEAK(186);
+ MOVE(CHEST,game.chloc);
+ MOVE(MESSAG,game.chloc2);
+ game.dloc[PIRATE]=game.chloc;
+ game.odloc[PIRATE]=game.chloc;
+ game.dseen[PIRATE]=false;
+ continue;
+ }
+ if (game.odloc[PIRATE] != game.dloc[PIRATE] && PCT(20))
+ RSPEAK(127);
+ continue;
+ }
+
+ /* This threatening little dwarf is in the room with him! */
+ ++game.dtotal;
+ if (game.odloc[i] == game.dloc[i]) {
+ ++attack;
+ if (game.knfloc >= 0)
+ game.knfloc=game.loc;
+ if (randrange(1000) < 95*(game.dflag-2))
+ ++stick;
+ }
+ jumpout:;
+ }
+
+ /* Now we know what's happening. Let's tell the poor sucker about it.
+ * Note that various of the "knife" messages must have specific relative
+ * positions in the RSPEAK database. */
+ if (game.dtotal == 0)
+ return true;
+ SETPRM(1,game.dtotal,0);
+ RSPEAK(4+1/game.dtotal);
+ if (attack == 0)
+ return true;
+ if (game.dflag == 2)game.dflag=3;
+ SETPRM(1,attack,0);
+ K=6;
+ if (attack > 1)K=250;
+ RSPEAK(K);
+ SETPRM(1,stick,0);
+ RSPEAK(K+1+2/(1+stick));
+ if (stick == 0)
+ return true;
+ game.oldlc2=game.loc;
+ return false;
+}
+
+/* "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 OLgame.dloc 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];
+ game.newloc=game.loc;
+ if (KK == 0)
+ BUG(26);
+ if (K == NUL)
+ return true;
+ if (K == 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. */
+ K=game.oldloc;
+ if (FORCED(K))
+ K=game.oldlc2;
+ game.oldlc2=game.oldloc;
+ game.oldloc=game.loc;
+ K2=0;
+ if (K == game.loc)K2=91;
+ if (CNDBIT(game.loc,4))K2=274;
+ if (K2 == 0) {
+ L21:
+ LL=MOD((labs(TRAVEL[KK])/1000),1000);
+ if (LL != K) {
+ if (LL <= 300) {
+ if (FORCED(LL) && MOD((labs(TRAVEL[KEY[LL]])/1000),1000) == K)
+ K2=KK;
+ }
+ if (TRAVEL[KK] >= 0) {
+ KK=KK+1;
+ goto L21;
+ }
+ KK=K2;
+ if (KK == 0) {
+ RSPEAK(140);
+ return true;
+ }
+ }
+
+ K=MOD(labs(TRAVEL[KK]),1000);
+ KK=KEY[game.loc];
+ goto L9;
+ }
+ RSPEAK(K2);
+ return true;
+ }
+ if (K == 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.detail+1;
+ game.wzdark=false;
+ game.abbrev[game.loc]=0;
+ return true;
+ }
+ if (K == CAVE) {
+ /* Cave. Different messages depending on whether above ground. */
+ RSPEAK((OUTSID(game.loc) && game.loc != 8) ? 57 : 58);
+ return true;
+ }
+ game.oldlc2=game.oldloc;
+ game.oldloc=game.loc;
+
+L9:
+ for (;;) {
+ LL=labs(TRAVEL[KK]);
+ if (MOD(LL,1000) == 1 || MOD(LL,1000) == K)
+ break;
+ if (TRAVEL[KK] < 0) {
+ /* Non-applicable motion. Various messages depending on
+ * word given. */
+ SPK=12;
+ if (K >= 43 && K <= 50)SPK=52;
+ if (K == 29 || K == 30)SPK=52;
+ if (K == 7 || K == 36 || K == 37)SPK=10;
+ if (K == 11 || K == 19)SPK=11;
+ if (verb == FIND || verb == INVENT)SPK=59;
+ if (K == 62 || K == 65)SPK=42;
+ if (K == 17)SPK=80;
+ RSPEAK(SPK);
+ return true;
+ }
+ KK=KK+1;
+ }
+ LL=LL/1000;
+
+L11:
+ game.newloc=LL/1000;
+ K=MOD(game.newloc,100);
+ if (game.newloc <= 300) {
+ if (game.newloc <= 100)
+ goto L14;
+ if (TOTING(K) || (game.newloc > 200 && AT(K)))
+ goto L16;
+ goto L12;
+ }
+ if (game.prop[K] != game.newloc/100-3)
+ goto L16;
+L12:
+ do {
+ if (TRAVEL[KK] < 0)BUG(25);
+ KK=KK+1;
+ game.newloc=labs(TRAVEL[KK])/1000;
+ } while
+ (game.newloc == LL);
+ LL=game.newloc;
+ goto L11;
+
+L14:
+ if (game.newloc != 0 && !PCT(game.newloc))
+ goto L12;
+L16:
+ 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;
+ long obj, i;
+ static long IGO = 0;
+
+ /* Can't leave cave once it's closing (except by main office). */
+ if (OUTSID(game.newloc) && game.newloc != 0 && game.closng) {
+ RSPEAK(130);
+ game.newloc=game.loc;
+ if (!game.panic)game.clock2=15;
+ game.panic=true;
+ }
+
+ /* See if a dwarf has seen him and has come from where he
+ * wants to go. If so, the dwarf's blocking his way. If
+ * coming from place forbidden to pirate (dwarves rooted in
+ * place) let him get out (and attacked). */
+ if (game.newloc != game.loc && !FORCED(game.loc) && !CNDBIT(game.loc,3)) {
+ for (i=1; i<=NDWARVES-1; i++) {
+ if (game.odloc[i] == game.newloc && game.dseen[i]) {
+ game.newloc=game.loc;
+ RSPEAK(2);
+ break;
+ }
+ }
+ }
+ game.loc=game.newloc;
+
+ if (!dwarfmove())
+ croak(cmdin);
+
+ /* Describe the current location and (maybe) get next command. */
+
+ /* Print text for current loc. */
+
+L2000: if (game.loc == 0)
+ croak(cmdin);