-static bool do_command(FILE *cmdin) {
-
-/* Can't leave cave once it's closing (except by main office). */
-
-L2: if(!OUTSID(NEWLOC) || NEWLOC == 0 || !CLOSNG) goto L71;
- RSPEAK(130);
- NEWLOC=LOC;
- if(!PANIC)CLOCK2=15;
- 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). */
-
-L71: if(NEWLOC == LOC || FORCED(LOC) || CNDBIT(LOC,3)) goto L74;
- /* 73 */ for (I=1; I<=5; I++) {
- if(ODLOC[I] != NEWLOC || !DSEEN[I]) goto L73;
- NEWLOC=LOC;
- RSPEAK(2);
- goto L74;
-L73: /*etc*/ ;
- } /* end loop */
-L74: LOC=NEWLOC;
-
-/* Dwarf stuff. See earlier comments for description of variables. Remember
- * sixth dwarf is pirate and is thus very different except for motion rules. */
-
-/* First off, don't let the dwarves follow him into a pit or a wall. Activate
- * the whole mess the first time he gets as far as the hall of mists (loc 15).
- * If NEWLOC is forbidden to pirate (in particular, if it's beyond the troll
- * bridge), bypass dwarf stuff. That way pirate can't steal return toll, and
- * dwarves can't meet the bear. Also means dwarves won't follow him into dead
- * end in maze, but c'est la vie. They'll wait for him outside the dead end. */
-
- if(LOC == 0 || FORCED(LOC) || CNDBIT(NEWLOC,3)) goto L2000;
- if(DFLAG != 0) goto L6000;
- if(INDEEP(LOC))DFLAG=1;
- goto L2000;
-
-/* When we encounter the first dwarf, we kill 0, 1, or 2 of the 5 dwarves. If
- * any of the survivors is at loc, replace him with the alternate. */
-
-L6000: if(DFLAG != 1) goto L6010;
- if(!INDEEP(LOC) || (PCT(95) && (!CNDBIT(LOC,4) || PCT(85)))) goto L2000;
- DFLAG=2;
- for (I=1; I<=2; I++) {
- J=1+randrange(5);
- if(PCT(50))DLOC[J]=0;
- } /* end loop */
- for (I=1; I<=5; I++) {
- if(DLOC[I] == LOC)DLOC[I]=DALTLC;
- ODLOC[I]=DLOC[I];
- } /* end loop */
- RSPEAK(3);
- DROP(AXE,LOC);
- 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: DTOTAL=0;
- ATTACK=0;
- STICK=0;
- /* 6030 */ for (I=1; I<=6; I++) {
- if(DLOC[I] == 0) goto L6030;
-/* Fill TK array with all the places this dwarf might go. */
- J=1;
- KK=DLOC[I];
- KK=KEY[KK];
- if(KK == 0) goto L6016;
-L6012: NEWLOC=MOD(IABS(TRAVEL[KK])/1000,1000);
- {long x = J-1;
- if(NEWLOC > 300 || !INDEEP(NEWLOC) || NEWLOC == ODLOC[I] || (J > 1 &&
- NEWLOC == TK[x]) || J >= 20 || NEWLOC == DLOC[I] ||
- FORCED(NEWLOC) || (I == 6 && CNDBIT(NEWLOC,3)) ||
- IABS(TRAVEL[KK])/1000000 == 100) goto L6014;}
- TK[J]=NEWLOC;
- J=J+1;
-L6014: KK=KK+1;
- {long x = KK-1; if(TRAVEL[x] >= 0) goto L6012;}
-L6016: TK[J]=ODLOC[I];
- if(J >= 2)J=J-1;
- J=1+randrange(J);
- ODLOC[I]=DLOC[I];
- DLOC[I]=TK[J];
- DSEEN[I]=(DSEEN[I] && INDEEP(LOC)) || (DLOC[I] == LOC || ODLOC[I] == LOC);
- if(!DSEEN[I]) goto L6030;
- DLOC[I]=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 PLACE(CHEST)=0 might mean that he's
- * thrown it to the troll, but in that case he's seen the chest (PROP=0). */
-
- if(LOC == CHLOC || 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 && (LOC == PLAC[PYRAM] || LOC == PLAC[EMRALD])) goto L6020;
- if(TOTING(J)) goto L6021;
-L6020: if(HERE(J))K=1;
- } /* end loop */
- if(TALLY == 1 && K == 0 && PLACE[CHEST] == 0 && HERE(LAMP) && PROP[LAMP]
- == 1) goto L6025;
- if(ODLOC[6] != DLOC[6] && PCT(20))RSPEAK(127);
- goto L6030;
-
-L6021: if(PLACE[CHEST] != 0) goto L6022;
-/* Install chest only once, to insure it is the last treasure in the list. */
- MOVE(CHEST,CHLOC);
- MOVE(MESSAG,CHLOC2);
-L6022: RSPEAK(128);
- /* 6023 */ for (J=50; J<=MAXTRS; J++) {
- if(J == PYRAM && (LOC == PLAC[PYRAM] || LOC == PLAC[EMRALD])) goto L6023;
- if(AT(J) && FIXED[J] == 0)CARRY(J,LOC);
- if(TOTING(J))DROP(J,CHLOC);
-L6023: /*etc*/ ;
- } /* end loop */
-L6024: DLOC[6]=CHLOC;
- ODLOC[6]=CHLOC;
- DSEEN[6]=false;
- goto L6030;
-
-L6025: RSPEAK(186);
- MOVE(CHEST,CHLOC);
- MOVE(MESSAG,CHLOC2);
- goto L6024;
-
-/* This threatening little dwarf is in the room with him! */
-
-L6027: DTOTAL=DTOTAL+1;
- if(ODLOC[I] != DLOC[I]) goto L6030;
- ATTACK=ATTACK+1;
- if(KNFLOC >= 0)KNFLOC=LOC;
- if(randrange(1000) < 95*(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(DTOTAL == 0) goto L2000;
- SETPRM(1,DTOTAL,0);
- RSPEAK(4+1/DTOTAL);
- if(ATTACK == 0) goto L2000;
- if(DFLAG == 2)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;
- OLDLC2=LOC;
- goto L99;
-
-
-
-
-
-
-/* Describe the current location and (maybe) get next command. */
-
-/* Print text for current loc. */
-
-L2000: if(LOC == 0) goto L99;
- KK=STEXT[LOC];
- if(MOD(ABB[LOC],ABBNUM) == 0 || KK == 0)KK=LTEXT[LOC];
- if(FORCED(LOC) || !DARK(0)) goto L2001;
- if(WZDARK && PCT(35)) goto L90;
- KK=RTEXT[16];
-L2001: if(TOTING(BEAR))RSPEAK(141);
- SPEAK(KK);
- K=1;
- if(FORCED(LOC)) goto L8;
- if(LOC == 33 && PCT(25) && !CLOSNG)RSPEAK(7);
-
-/* Print out descriptions of objects at this location. If not closing and
- * property value is negative, tally off another treasure. Rug is special
- * case; once seen, its PROP is 1 (dragon on it) till dragon is killed.
- * Similarly for chain; PROP is initially 1 (locked to bear). These hacks
- * are because PROP=0 is needed to get full score. */
-
- if(DARK(0)) goto L2012;
- ABB[LOC]=ABB[LOC]+1;
- I=ATLOC[LOC];
-L2004: if(I == 0) goto L2012;
- OBJ=I;
- if(OBJ > 100)OBJ=OBJ-100;
- if(OBJ == STEPS && TOTING(NUGGET)) goto L2008;
- if(PROP[OBJ] >= 0) goto L2006;
- if(CLOSED) goto L2008;
- PROP[OBJ]=0;
- if(OBJ == RUG || OBJ == CHAIN)PROP[OBJ]=1;
- TALLY=TALLY-1;
-/* Note: There used to be a test here to see whether the player had blown it
- * so badly that he could never ever see the remaining treasures, and if so
- * the lamp was zapped to 35 turns. But the tests were too simple-minded;
- * things like killing the bird before the snake was gone (can never see
- * jewelry), and doing it "right" was hopeless. E.G., could cross troll
- * bridge several times, using up all available treasures, breaking vase,
- * using coins to buy batteries, etc., and eventually never be able to get
- * across again. If bottle were left on far side, could then never get eggs
- * or trident, and the effects propagate. So the whole thing was flushed.
- * anyone who makes such a gross blunder isn't likely to find everything
- * else anyway (so goes the rationalisation). */
-L2006: KK=PROP[OBJ];
- if(OBJ == STEPS && LOC == FIXED[STEPS])KK=1;
- PSPEAK(OBJ,KK);
-L2008: I=LINK[I];
- goto L2004;
-
-L2009: K=54;
-L2010: SPK=K;
-L2011: RSPEAK(SPK);
-
-L2012: VERB=0;
- OLDOBJ=OBJ;
- OBJ=0;
-
-/* Check if this loc is eligible for any hints. If been here long enough,
- * branch to help section (on later page). Hints all come back here eventually
- * to finish the loop. Ignore "HINTS" < 4 (special stuff, see database notes).
- */
-
-L2600: if(COND[LOC] < CONDS) goto L2603;
- /* 2602 */ for (HINT=1; HINT<=HNTMAX; HINT++) {
- if(HINTED[HINT]) goto L2602;
- if(!CNDBIT(LOC,HINT+10))HINTLC[HINT]= -1;
- HINTLC[HINT]=HINTLC[HINT]+1;
- if(HINTLC[HINT] >= HINTS[HINT][1]) goto L40000;
-L2602: /*etc*/ ;
- } /* end loop */
-
-/* Kick the random number generator just to add variety to the chase. Also,
- * if closing time, check for any objects being toted with PROP < 0 and set
- * the prop to -1-PROP. This way objects won't be described until they've
- * been picked up and put down separate from their respective piles. Don't
- * tick CLOCK1 unless well into cave (and not at Y2). */
-
-L2603: if(!CLOSED) goto L2605;
- if(PROP[OYSTER] < 0 && TOTING(OYSTER))PSPEAK(OYSTER,1);
- for (I=1; I<=100; I++) {
- if(TOTING(I) && PROP[I] < 0)PROP[I]= -1-PROP[I];
- } /* end loop */
-L2605: WZDARK=DARK(0);
- if(KNFLOC > 0 && KNFLOC != LOC)KNFLOC=0;
- I=0;
- if (!GETIN(cmdin, WD1,WD1X,WD2,WD2X))
- return false;
-
-/* Every input, check "FOOBAR" flag. If zero, nothing's going on. If pos,
- * make neg. If neg, he skipped a word, so make it zero. */
-
-L2607: FOOBAR=(FOOBAR>0 ? -FOOBAR : 0);
- TURNS=TURNS+1;
- if(TURNS != THRESH) goto L2608;
- SPEAK(TTEXT[TRNDEX]);
- TRNLUZ=TRNLUZ+TRNVAL[TRNDEX]/100000;
- TRNDEX=TRNDEX+1;
- THRESH= -1;
- if(TRNDEX <= TRNVLS)THRESH=MOD(TRNVAL[TRNDEX],100000)+1;
-L2608: if(VERB == SAY && WD2 > 0)VERB=0;
- if(VERB == SAY) goto L4090;
- if(TALLY == 0 && INDEEP(LOC) && LOC != 33)CLOCK1=CLOCK1-1;
- if(CLOCK1 == 0) goto L10000;
- if(CLOCK1 < 0)CLOCK2=CLOCK2-1;
- if(CLOCK2 == 0) goto L11000;
- if(PROP[LAMP] == 1)LIMIT=LIMIT-1;
- if(LIMIT <= 30 && HERE(BATTER) && PROP[BATTER] == 0 && HERE(LAMP)) goto
- L12000;
- if(LIMIT == 0) goto L12400;
- if(LIMIT <= 30) goto L12200;
-L19999: K=43;
- if(LIQLOC(LOC) == WATER)K=70;
- V1=VOCAB(WD1,-1);
- V2=VOCAB(WD2,-1);
- if(V1 == ENTER && (V2 == STREAM || V2 == 1000+WATER)) goto L2010;
- if(V1 == ENTER && WD2 > 0) goto L2800;
- if((V1 != 1000+WATER && V1 != 1000+OIL) || (V2 != 1000+PLANT && V2 !=
- 1000+DOOR)) goto L2610;
- {long x = V2-1000; if(AT(x))WD2=MAKEWD(16152118);}
-L2610: if(V1 == 1000+CAGE && V2 == 1000+BIRD && HERE(CAGE) &&
- HERE(BIRD))WD1=MAKEWD(301200308);
-L2620: if(WD1 != MAKEWD(23051920)) goto L2625;
- IWEST=IWEST+1;
- if(IWEST == 10)RSPEAK(17);
-L2625: if(WD1 != MAKEWD( 715) || WD2 == 0) goto L2630;
- IGO=IGO+1;
- if(IGO == 10)RSPEAK(276);
-L2630: I=VOCAB(WD1,-1);
- if(I == -1) goto L3000;
- K=MOD(I,1000);
- KQ=I/1000+1;
- switch (KQ-1) { case 0: goto L8; case 1: goto L5000; case 2: goto L4000;
- case 3: goto L2010; }
- BUG(22);
-
-/* Get second word for analysis. */
-
-L2800: WD1=WD2;
- WD1X=WD2X;
- WD2=0;
- goto L2620;
-
-/* Gee, I don't understand. */
-
-L3000: SETPRM(1,WD1,WD1X);
- /* This is a kludge. The command parser we inherited from the base 2.5
- * barfs on numeric tokens. It will fall through to here when it sees
- * seed NNNN. Instead of barfing, go straight to the action processor
- * where it will examine the raw input. This will fo away when we get
- * rid of the obfuscated FORTRANoid input processing.
- */
- if (strncmp(raw_input, "seed", 4) == 0) {
- I=4090; K=34;
- goto Laction;
- } else {
- RSPEAK(254);
- goto L2600;
- }
-
-/* Verb and object analysis moved to separate module. */
-
-L4000: I=4000; goto Laction;
-L4090: I=4090; goto Laction;
-L5000: I=5000;
-Laction:
- switch (action(cmdin, I)) {
- case 2: return true;
- case 8: goto L8;
- case 2000: goto L2000;
- case 2009: goto L2009;
- case 2010: goto L2010;
- case 2011: goto L2011;
- case 2012: goto L2012;
- case 2600: goto L2600;
- case 2607: goto L2607;
- case 2630: goto L2630;
- case 2800: goto L2800;
- case 8000: goto L8000;
- case 18999: goto L18999;
- case 19000: goto L19000;
- }
- BUG(99);
-
-/* Random intransitive verbs come here. Clear obj just in case (see "attack").
- */
-
-L8000: SETPRM(1,WD1,WD1X);
- RSPEAK(257);
- OBJ=0;
- goto L2600;
-
-/* Figure out the new location
- *
- * Given the current location in "LOC", and a motion verb number in "K", put
- * the new location in "NEWLOC". The current loc is saved in "OLDLOC" in case
- * he wants to retreat. The current OLDLOC is saved in OLDLC2, in case he
- * dies. (if he does, NEWLOC will be limbo, and OLDLOC will be what killed
- * him, so we need OLDLC2, which is the last place he was safe.) */
-
-L8: KK=KEY[LOC];
- NEWLOC=LOC;
- if(KK == 0)BUG(26);
- if(K == NUL) return true;
- if(K == BACK) goto L20;
- if(K == LOOK) goto L30;
- if(K == CAVE) goto L40;
- OLDLC2=OLDLOC;
- OLDLOC=LOC;
-
-L9: LL=IABS(TRAVEL[KK]);
- if(MOD(LL,1000) == 1 || MOD(LL,1000) == K) goto L10;
- if(TRAVEL[KK] < 0) goto L50;
- KK=KK+1;
- goto L9;
-
-L10: LL=LL/1000;
-L11: NEWLOC=LL/1000;
- K=MOD(NEWLOC,100);
- if(NEWLOC <= 300) goto L13;
- if(PROP[K] != NEWLOC/100-3) goto L16;
-L12: if(TRAVEL[KK] < 0)BUG(25);
- KK=KK+1;
- NEWLOC=IABS(TRAVEL[KK])/1000;
- if(NEWLOC == LL) goto L12;
- LL=NEWLOC;
- goto L11;
-
-L13: if(NEWLOC <= 100) goto L14;
- if(TOTING(K) || (NEWLOC > 200 && AT(K))) goto L16;
- goto L12;
-
-L14: if(NEWLOC != 0 && !PCT(NEWLOC)) goto L12;
-L16: NEWLOC=MOD(LL,1000);
- if(NEWLOC <= 300) return true;
- if(NEWLOC <= 500) goto L30000;
- RSPEAK(NEWLOC-500);
- NEWLOC=LOC;
- return true;
-
-/* Special motions come here. Labelling convention: statement numbers NNNXX
- * (XX=00-99) are used for special case number NNN (NNN=301-500). */
-
-L30000: NEWLOC=NEWLOC-300;
- switch (NEWLOC) { case 1: goto L30100; case 2: goto L30200; case 3: goto
- L30300; }
- BUG(20);
-
-/* 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". */
-
-L30100: NEWLOC=99+100-LOC;
- if(HOLDNG == 0 || (HOLDNG == 1 && TOTING(EMRALD))) return true;
- NEWLOC=LOC;
- RSPEAK(117);
- return true;
-
-/* 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. */
-
-L30200: DROP(EMRALD,LOC);
- goto L12;
-
-/* 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
- * PROP(TROLL)=1, he's crossed since paying, so step out and block him.
- * (standard travel entries check for PROP(TROLL)=0.) Special stuff for bear. */
-
-L30300: if(PROP[TROLL] != 1) goto L30310;
- PSPEAK(TROLL,1);
- PROP[TROLL]=0;
- MOVE(TROLL2,0);
- MOVE(TROLL2+100,0);
- MOVE(TROLL,PLAC[TROLL]);
- MOVE(TROLL+100,FIXD[TROLL]);
- JUGGLE(CHASM);
- NEWLOC=LOC;
- return true;
-
-L30310: NEWLOC=PLAC[TROLL]+FIXD[TROLL]-LOC;
- if(PROP[TROLL] == 0)PROP[TROLL]=1;
- if(!TOTING(BEAR)) return true;
- RSPEAK(162);
- PROP[CHASM]=1;
- PROP[TROLL]=2;
- DROP(BEAR,NEWLOC);
- FIXED[BEAR]= -1;
- PROP[BEAR]=3;
- OLDLC2=NEWLOC;
- goto L99;
-
-/* End of specials. */
-
-/* Handle "go back". Look for verb which goes from LOC to OLDLOC, or to OLDLC2
- * If OLDLOC has forced-motion. K2 saves entry -> forced loc -> previous loc. */
-
-L20: K=OLDLOC;
- if(FORCED(K))K=OLDLC2;
- OLDLC2=OLDLOC;
- OLDLOC=LOC;
- K2=0;
- if(K == LOC)K2=91;
- if(CNDBIT(LOC,4))K2=274;
- if(K2 == 0) goto L21;
- RSPEAK(K2);
- return true;
-
-L21: LL=MOD((IABS(TRAVEL[KK])/1000),1000);
- if(LL == K) goto L25;
- if(LL > 300) goto L22;
- J=KEY[LL];
- if(FORCED(LL) && MOD((IABS(TRAVEL[J])/1000),1000) == K)K2=KK;
-L22: if(TRAVEL[KK] < 0) goto L23;
- KK=KK+1;
- goto L21;
-
-L23: KK=K2;
- if(KK != 0) goto L25;
- RSPEAK(140);
- return true;
-
-L25: K=MOD(IABS(TRAVEL[KK]),1000);
- KK=KEY[LOC];
- goto L9;
-
-/* 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. */
-
-L30: if(DETAIL < 3)RSPEAK(15);
- DETAIL=DETAIL+1;
- WZDARK=false;
- ABB[LOC]=0;
- return true;
-
-/* Cave. Different messages depending on whether above ground. */
-
-L40: K=58;
- if(OUTSID(LOC) && LOC != 8)K=57;
- RSPEAK(K);
- return true;
-
-/* Non-applicable motion. Various messages depending on word given. */
-
-L50: 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;
+static bool dwarfmove(void)
+/* Dwarves move. Return true if player survives, false if he dies. */
+{
+ int kk, stick, attack;
+ long tk[21];
+
+ /* Dwarf stuff. See earlier comments for description of
+ * variables. Remember sixth dwarf is pirate and is thus
+ * very different except for motion rules. */
+
+ /* First off, don't let the dwarves follow him into a pit or
+ * a wall. Activate the whole mess the first time he gets as
+ * far as the hall of mists (loc 15). If game.newloc is
+ * forbidden to pirate (in particular, if it's beyond the
+ * troll bridge), bypass dwarf stuff. That way pirate can't
+ * steal return toll, and dwarves can't meet the bear. Also
+ * means dwarves won't follow him into dead end in maze, but
+ * c'est la vie. They'll wait for him outside the dead
+ * end. */
+ if (game.loc == 0 || FORCED(game.loc) || CNDBIT(game.newloc, COND_NOARRR))
+ return true;
+
+ /* Dwarf activity level ratchets up */
+ if (game.dflag == 0) {
+ if (INDEEP(game.loc))
+ game.dflag = 1;
+ return true;
+ }
+
+ /* When we encounter the first dwarf, we kill 0, 1, or 2 of
+ * the 5 dwarves. If any of the survivors is at loc,
+ * replace him with the alternate. */
+ if (game.dflag == 1) {
+ if (!INDEEP(game.loc) || (PCT(95) && (!CNDBIT(game.loc, COND_NOBACK) || PCT(85))))
+ return true;
+ game.dflag = 2;
+ for (int i = 1; i <= 2; i++) {
+ int j = 1 + randrange(NDWARVES - 1);
+ if (PCT(50))
+ game.dloc[j] = 0;
+ }
+ for (int i = 1; i <= NDWARVES - 1; i++) {
+ if (game.dloc[i] == game.loc)
+ game.dloc[i] = DALTLC;
+ game.odloc[i] = game.dloc[i];
+ }
+ rspeak(DWARF_RAN);
+ drop(AXE, game.loc);
+ 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++) {
+ if (game.dloc[i] == 0)
+ continue;
+ /* Fill tk array with all the places this dwarf might go. */
+ unsigned int j = 1;
+ kk = tkey[game.dloc[i]];
+ if (kk != 0)
+ do {
+ game.newloc = T_DESTINATION(travel[kk]);
+ /* Have we avoided a dwarf encounter? */
+ bool avoided = (SPECIAL(game.newloc) ||
+ !INDEEP(game.newloc) ||
+ game.newloc == game.odloc[i] ||
+ (j > 1 && game.newloc == tk[j - 1]) ||
+ j >= DIM(tk) - 1 ||
+ game.newloc == game.dloc[i] ||
+ FORCED(game.newloc) ||
+ (i == PIRATE && CNDBIT(game.newloc, COND_NOARRR)) ||
+ T_NODWARVES(travel[kk]));
+ if (!avoided) {
+ tk[j++] = game.newloc;
+ }
+ ++kk;
+ } while
+ (!travel[kk - 1].stop);
+ 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 (spotted_by_pirate(i))
+ 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;
+ }
+ }
+
+ /* 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;
+ rspeak(game.dtotal == 1 ? DWARF_SINGLE : DWARF_PACK, game.dtotal);
+ if (attack == 0)
+ return true;
+ if (game.dflag == 2)game.dflag = 3;
+ if (attack > 1) {
+ rspeak(THROWN_KNIVES, attack);
+ rspeak(stick > 1 ? MULTIPLE_HITS : (stick == 1 ? ONE_HIT : NONE_HIT), stick);
+ } else {
+ rspeak(KNIFE_THROWN);
+ rspeak(MISSES_YOU);
+ }
+ if (stick == 0)
+ return true;
+ game.oldlc2 = game.loc;
+ return false;
+}