Don't build with two -std options.
[open-adventure.git] / main.c
1 /*
2  * The author - Don Woods - apologises for the style of the code; it
3  * is a result of running the original Fortran IV source through a
4  * home-brew Fortran-to-C converter.)
5  */
6 #include <stdlib.h>
7 #include <stdio.h>
8 #include <stdbool.h>
9 #include <getopt.h>
10 #include <signal.h>
11 #include <time.h>
12 #include "main.h"
13 #include "database.h"
14 #include "misc.h"
15
16 long ABB[186], ATLOC[186], BLKLIN = true, DFLAG,
17                 DLOC[7], FIXED[101], HOLDNG,
18                 LINK[201], LNLENG, LNPOSN,
19                 PARMS[26], PLACE[101],
20                 SETUP = 0;
21 signed char rawbuf[LINESIZE], INLINE[LINESIZE+1], MAP1[129], MAP2[129];
22
23 long ABBNUM, AMBER, ATTACK, AXE, BACK, BATTER, BEAR, BIRD, BLOOD, BONUS,
24                  BOTTLE, CAGE, CAVE, CAVITY, CHAIN, CHASM, CHEST, CHLOC, CHLOC2,
25                 CLAM, CLOCK1, CLOCK2, CLOSED, CLOSNG, CLSHNT,
26                 COINS, CONDS, DALTLC, DETAIL,
27                  DKILL, DOOR, DPRSSN, DRAGON, DSEEN[7], DTOTAL, DWARF, EGGS,
28                 EMRALD, ENTER, ENTRNC, FIND, FISSUR, FOOBAR, FOOD,
29                 GRATE, HINT, HINTED[21], HINTLC[21],
30                 I, INVENT, IGO, IWEST, J, JADE, K, K2, KEYS, KK,
31                 KNFLOC, KNIFE, KQ, L, LAMP, LIMIT, LL,
32                 LMWARN, LOC, LOCK, LOOK,
33                 MAGZIN, MAXDIE, MAXTRS, MESH = 123456789,
34                 MESSAG, MIRROR, MXSCOR,
35                 NEWLOC, NOVICE, NUGGET, NUL, NUMDIE, OBJ,
36                 ODLOC[7], OGRE, OIL, OLDLC2, OLDLOC, OLDOBJ, OYSTER,
37                 PANIC, PEARL, PILLOW, PLANT, PLANT2, PROP[101], PYRAM,
38                 RESER, ROD, ROD2, RUBY, RUG, SAPPH, SAVED, SAY,
39                 SCORE, SECT, SIGN, SNAKE, SPK, STEPS, STICK,
40                 STREAM, TALLY, THRESH, THROW, TK[21], TRIDNT,
41                 TRNDEX, TRNLUZ, TROLL, TROLL2,
42                  TURNS, URN, V1, V2, VASE, VEND, VERB,
43                 VOLCAN, VRSION = 25, WATER, WD1, WD1X, WD2, WD2X,
44                 WZDARK = false, ZZWORD;
45 FILE  *logfp;
46 bool oldstyle = false;
47 lcg_state lcgstate;
48
49 extern void initialise();
50 extern void score(long);
51 extern int action(FILE *, long);
52
53 void sig_handler(int signo)
54 {
55     if (signo == SIGINT)
56         if (logfp != NULL)
57             fflush(logfp);
58     exit(0);
59 }
60
61 /*
62  * MAIN PROGRAM
63  */
64
65 static bool do_command(FILE *);
66
67 int main(int argc, char *argv[]) {
68         int ch;
69
70 /*  Adventure (rev 2: 20 treasures) */
71
72 /*  History: Original idea & 5-treasure version (adventures) by Willie Crowther
73  *           15-treasure version (adventure) by Don Woods, April-June 1977
74  *           20-treasure version (rev 2) by Don Woods, August 1978
75  *              Errata fixed: 78/12/25 */
76
77
78 /*  Options. */
79
80         while ((ch = getopt(argc, argv, "l:o")) != EOF) {
81                 switch (ch) {
82                 case 'l':
83                         logfp = fopen(optarg, "w");
84                         if (logfp == NULL)
85                                 fprintf(stderr,
86                                         "advent: can't open logfile %s for write\n",
87                                         optarg);
88                         signal(SIGINT, sig_handler);
89                         break;
90                 case 'o':
91                     oldstyle = true;
92                     break;
93                 }
94         }
95
96 /* Logical variables:
97  *
98  *  CLOSED says whether we're all the way closed
99  *  CLOSNG says whether it's closing time yet
100  *  CLSHNT says whether he's read the clue in the endgame
101  *  LMWARN says whether he's been warned about lamp going dim
102  *  NOVICE says whether he asked for instructions at start-up
103  *  PANIC says whether he's found out he's trapped in the cave
104  *  WZDARK says whether the loc he's leaving was dark */
105
106 #include "funcs.h"
107
108 /* Initialize our LCG PRNG with parameters tested against Knuth vol. 2. by the original authors */
109
110         lcgstate.a = 1093;
111         lcgstate.c = 221587;
112         lcgstate.m = 1048576;
113         long seedval = (long)time(NULL);
114         set_seed(seedval);
115
116 /*  Read the database if we have not yet done so */
117
118         MAP2[1] = 0;
119         if(!SETUP)initialise();
120         if(SETUP > 0) goto L1;
121
122 /*  Unlike earlier versions, adventure is no longer restartable.  (This
123  *  lets us get away with modifying things such as OBJSND(BIRD) without
124  *  having to be able to undo the changes later.)  If a "used" copy is
125  *  rerun, we come here and tell the player to run a fresh copy. */
126
127         RSPEAK(201);
128         exit(0);
129
130 /*  Start-up, dwarf stuff */
131
132 L1:     SETUP= -1;
133         I=0;
134         ZZWORD=RNDVOC(3,0)+MESH*2;
135         NOVICE=YES(stdin, 65,1,0);
136         NEWLOC=1;
137         LOC=1;
138         LIMIT=330;
139         if(NOVICE)LIMIT=1000;
140
141         if (logfp)
142             fprintf(logfp, "seed %ld\n", seedval);
143         
144         for (;;) {
145             if (!do_command(stdin))
146                 break;
147         }
148         score(1);
149 }
150
151 static bool fallback_handler(signed char *buf)
152 /* fallback handler for commands not handled by FORTRANish parser */
153 {
154     long sv;
155     if (sscanf(buf, "seed %ld", &sv) == 1) {
156         set_seed(sv);
157         printf("Seed set to %ld\n", sv);
158         // here we reconfigure any global game state that uses random numbers
159         ZZWORD=RNDVOC(3,0)+MESH*2;
160         return true;
161     }
162     return false;
163 }
164
165 static bool do_command(FILE *cmdin) {
166
167 /*  Can't leave cave once it's closing (except by main office). */
168
169         if(!OUTSID(NEWLOC) || NEWLOC == 0 || !CLOSNG) goto L71;
170         RSPEAK(130);
171         NEWLOC=LOC;
172         if(!PANIC)CLOCK2=15;
173         PANIC=true;
174
175 /*  See if a dwarf has seen him and has come from where he wants to go.  If so,
176  *  the dwarf's blocking his way.  If coming from place forbidden to pirate
177  *  (dwarves rooted in place) let him get out (and attacked). */
178
179 L71:    if(NEWLOC == LOC || FORCED(LOC) || CNDBIT(LOC,3)) goto L74;
180         /* 73 */ for (I=1; I<=5; I++) {
181         if(ODLOC[I] != NEWLOC || !DSEEN[I]) goto L73;
182         NEWLOC=LOC;
183         RSPEAK(2);
184          goto L74;
185 L73:    /*etc*/ ;
186         } /* end loop */
187 L74:    LOC=NEWLOC;
188
189 /*  Dwarf stuff.  See earlier comments for description of variables.  Remember
190  *  sixth dwarf is pirate and is thus very different except for motion rules. */
191
192 /*  First off, don't let the dwarves follow him into a pit or a wall.  Activate
193  *  the whole mess the first time he gets as far as the hall of mists (loc 15).
194  *  If NEWLOC is forbidden to pirate (in particular, if it's beyond the troll
195  *  bridge), bypass dwarf stuff.  That way pirate can't steal return toll, and
196  *  dwarves can't meet the bear.  Also means dwarves won't follow him into dead
197  *  end in maze, but c'est la vie.  They'll wait for him outside the dead end. */
198
199         if(LOC == 0 || FORCED(LOC) || CNDBIT(NEWLOC,3)) goto L2000;
200         if(DFLAG != 0) goto L6000;
201         if(INDEEP(LOC))DFLAG=1;
202          goto L2000;
203
204 /*  When we encounter the first dwarf, we kill 0, 1, or 2 of the 5 dwarves.  If
205  *  any of the survivors is at loc, replace him with the alternate. */
206
207 L6000:  if(DFLAG != 1) goto L6010;
208         if(!INDEEP(LOC) || (PCT(95) && (!CNDBIT(LOC,4) || PCT(85)))) goto L2000;
209         DFLAG=2;
210         for (I=1; I<=2; I++) {
211         J=1+randrange(5);
212         if(PCT(50))DLOC[J]=0;
213         } /* end loop */
214         for (I=1; I<=5; I++) {
215         if(DLOC[I] == LOC)DLOC[I]=DALTLC;
216         ODLOC[I]=DLOC[I];
217         } /* end loop */
218         RSPEAK(3);
219         DROP(AXE,LOC);
220          goto L2000;
221
222 /*  Things are in full swing.  Move each dwarf at random, except if he's seen us
223  *  he sticks with us.  Dwarves stay deep inside.  If wandering at random,
224  *  they don't back up unless there's no alternative.  If they don't have to
225  *  move, they attack.  And, of course, dead dwarves don't do much of anything. */
226
227 L6010:  DTOTAL=0;
228         ATTACK=0;
229         STICK=0;
230         /* 6030 */ for (I=1; I<=6; I++) {
231         if(DLOC[I] == 0) goto L6030;
232 /*  Fill TK array with all the places this dwarf might go. */
233         J=1;
234         KK=DLOC[I];
235         KK=KEY[KK];
236         if(KK == 0) goto L6016;
237 L6012:  NEWLOC=MOD(IABS(TRAVEL[KK])/1000,1000);
238         {long x = J-1;
239         if(NEWLOC > 300 || !INDEEP(NEWLOC) || NEWLOC == ODLOC[I] || (J > 1 &&
240                 NEWLOC == TK[x]) || J >= 20 || NEWLOC == DLOC[I] ||
241                 FORCED(NEWLOC) || (I == 6 && CNDBIT(NEWLOC,3)) ||
242                 IABS(TRAVEL[KK])/1000000 == 100) goto L6014;}
243         TK[J]=NEWLOC;
244         J=J+1;
245 L6014:  KK=KK+1;
246         {long x = KK-1; if(TRAVEL[x] >= 0) goto L6012;}
247 L6016:  TK[J]=ODLOC[I];
248         if(J >= 2)J=J-1;
249         J=1+randrange(J);
250         ODLOC[I]=DLOC[I];
251         DLOC[I]=TK[J];
252         DSEEN[I]=(DSEEN[I] && INDEEP(LOC)) || (DLOC[I] == LOC || ODLOC[I] == LOC);
253         if(!DSEEN[I]) goto L6030;
254         DLOC[I]=LOC;
255         if(I != 6) goto L6027;
256
257 /*  The pirate's spotted him.  He leaves him alone once we've found chest.  K
258  *  counts if a treasure is here.  If not, and tally=1 for an unseen chest, let
259  *  the pirate be spotted.  Note that PLACE(CHEST)=0 might mean that he's
260  *  thrown it to the troll, but in that case he's seen the chest (PROP=0). */
261
262         if(LOC == CHLOC || PROP[CHEST] >= 0) goto L6030;
263         K=0;
264         /* 6020 */ for (J=50; J<=MAXTRS; J++) {
265 /*  Pirate won't take pyramid from plover room or dark room (too easy!). */
266         if(J == PYRAM && (LOC == PLAC[PYRAM] || LOC == PLAC[EMRALD])) goto L6020;
267         if(TOTING(J)) goto L6021;
268 L6020:  if(HERE(J))K=1;
269         } /* end loop */
270         if(TALLY == 1 && K == 0 && PLACE[CHEST] == 0 && HERE(LAMP) && PROP[LAMP]
271                 == 1) goto L6025;
272         if(ODLOC[6] != DLOC[6] && PCT(20))RSPEAK(127);
273          goto L6030;
274
275 L6021:  if(PLACE[CHEST] != 0) goto L6022;
276 /*  Install chest only once, to insure it is the last treasure in the list. */
277         MOVE(CHEST,CHLOC);
278         MOVE(MESSAG,CHLOC2);
279 L6022:  RSPEAK(128);
280         /* 6023 */ for (J=50; J<=MAXTRS; J++) {
281         if(J == PYRAM && (LOC == PLAC[PYRAM] || LOC == PLAC[EMRALD])) goto L6023;
282         if(AT(J) && FIXED[J] == 0)CARRY(J,LOC);
283         if(TOTING(J))DROP(J,CHLOC);
284 L6023:  /*etc*/ ;
285         } /* end loop */
286 L6024:  DLOC[6]=CHLOC;
287         ODLOC[6]=CHLOC;
288         DSEEN[6]=false;
289          goto L6030;
290
291 L6025:  RSPEAK(186);
292         MOVE(CHEST,CHLOC);
293         MOVE(MESSAG,CHLOC2);
294          goto L6024;
295
296 /*  This threatening little dwarf is in the room with him! */
297
298 L6027:  DTOTAL=DTOTAL+1;
299         if(ODLOC[I] != DLOC[I]) goto L6030;
300         ATTACK=ATTACK+1;
301         if(KNFLOC >= 0)KNFLOC=LOC;
302         if(randrange(1000) < 95*(DFLAG-2))STICK=STICK+1;
303 L6030:  /*etc*/ ;
304         } /* end loop */
305
306 /*  Now we know what's happening.  Let's tell the poor sucker about it.
307  *  Note that various of the "knife" messages must have specific relative
308  *  positions in the RSPEAK database. */
309
310         if(DTOTAL == 0) goto L2000;
311         SETPRM(1,DTOTAL,0);
312         RSPEAK(4+1/DTOTAL);
313         if(ATTACK == 0) goto L2000;
314         if(DFLAG == 2)DFLAG=3;
315         SETPRM(1,ATTACK,0);
316         K=6;
317         if(ATTACK > 1)K=250;
318         RSPEAK(K);
319         SETPRM(1,STICK,0);
320         RSPEAK(K+1+2/(1+STICK));
321         if(STICK == 0) goto L2000;
322         OLDLC2=LOC;
323          goto L99;
324
325
326
327
328
329
330 /*  Describe the current location and (maybe) get next command. */
331
332 /*  Print text for current loc. */
333
334 L2000:  if(LOC == 0) goto L99;
335         KK=STEXT[LOC];
336         if(MOD(ABB[LOC],ABBNUM) == 0 || KK == 0)KK=LTEXT[LOC];
337         if(FORCED(LOC) || !DARK(0)) goto L2001;
338         if(WZDARK && PCT(35)) goto L90;
339         KK=RTEXT[16];
340 L2001:  if(TOTING(BEAR))RSPEAK(141);
341         SPEAK(KK);
342         K=1;
343         if(FORCED(LOC)) goto L8;
344         if(LOC == 33 && PCT(25) && !CLOSNG)RSPEAK(7);
345
346 /*  Print out descriptions of objects at this location.  If not closing and
347  *  property value is negative, tally off another treasure.  Rug is special
348  *  case; once seen, its PROP is 1 (dragon on it) till dragon is killed.
349  *  Similarly for chain; PROP is initially 1 (locked to bear).  These hacks
350  *  are because PROP=0 is needed to get full score. */
351
352         if(DARK(0)) goto L2012;
353         ABB[LOC]=ABB[LOC]+1;
354         I=ATLOC[LOC];
355 L2004:  if(I == 0) goto L2012;
356         OBJ=I;
357         if(OBJ > 100)OBJ=OBJ-100;
358         if(OBJ == STEPS && TOTING(NUGGET)) goto L2008;
359         if(PROP[OBJ] >= 0) goto L2006;
360         if(CLOSED) goto L2008;
361         PROP[OBJ]=0;
362         if(OBJ == RUG || OBJ == CHAIN)PROP[OBJ]=1;
363         TALLY=TALLY-1;
364 /*  Note: There used to be a test here to see whether the player had blown it
365  *  so badly that he could never ever see the remaining treasures, and if so
366  *  the lamp was zapped to 35 turns.  But the tests were too simple-minded;
367  *  things like killing the bird before the snake was gone (can never see
368  *  jewelry), and doing it "right" was hopeless.  E.G., could cross troll
369  *  bridge several times, using up all available treasures, breaking vase,
370  *  using coins to buy batteries, etc., and eventually never be able to get
371  *  across again.  If bottle were left on far side, could then never get eggs
372  *  or trident, and the effects propagate.  So the whole thing was flushed.
373  *  anyone who makes such a gross blunder isn't likely to find everything
374  *  else anyway (so goes the rationalisation). */
375 L2006:  KK=PROP[OBJ];
376         if(OBJ == STEPS && LOC == FIXED[STEPS])KK=1;
377         PSPEAK(OBJ,KK);
378 L2008:  I=LINK[I];
379          goto L2004;
380
381 L2009:  K=54;
382 L2010:  SPK=K;
383 L2011:  RSPEAK(SPK);
384
385 L2012:  VERB=0;
386         OLDOBJ=OBJ;
387         OBJ=0;
388
389 /*  Check if this loc is eligible for any hints.  If been here long enough,
390  *  branch to help section (on later page).  Hints all come back here eventually
391  *  to finish the loop.  Ignore "HINTS" < 4 (special stuff, see database notes).
392                 */
393
394 L2600:  if(COND[LOC] < CONDS) goto L2603;
395         /* 2602 */ for (HINT=1; HINT<=HNTMAX; HINT++) {
396         if(HINTED[HINT]) goto L2602;
397         if(!CNDBIT(LOC,HINT+10))HINTLC[HINT]= -1;
398         HINTLC[HINT]=HINTLC[HINT]+1;
399         if(HINTLC[HINT] >= HINTS[HINT][1]) goto L40000;
400 L2602:  /*etc*/ ;
401         } /* end loop */
402
403 /*  Kick the random number generator just to add variety to the chase.  Also,
404  *  if closing time, check for any objects being toted with PROP < 0 and set
405  *  the prop to -1-PROP.  This way objects won't be described until they've
406  *  been picked up and put down separate from their respective piles.  Don't
407  *  tick CLOCK1 unless well into cave (and not at Y2). */
408
409 L2603:  if(!CLOSED) goto L2605;
410         if(PROP[OYSTER] < 0 && TOTING(OYSTER))PSPEAK(OYSTER,1);
411         for (I=1; I<=100; I++) {
412         if(TOTING(I) && PROP[I] < 0)PROP[I]= -1-PROP[I];
413         } /* end loop */
414 L2605:  WZDARK=DARK(0);
415         if(KNFLOC > 0 && KNFLOC != LOC)KNFLOC=0;
416         I=0;
417         if (!GETIN(cmdin, WD1,WD1X,WD2,WD2X))
418             return false;
419
420 /*  Every input, check "FOOBAR" flag.  If zero, nothing's going on.  If pos,
421  *  make neg.  If neg, he skipped a word, so make it zero. */
422
423 L2607:  FOOBAR=(FOOBAR>0 ? -FOOBAR : 0);
424         TURNS=TURNS+1;
425         if(TURNS != THRESH) goto L2608;
426         SPEAK(TTEXT[TRNDEX]);
427         TRNLUZ=TRNLUZ+TRNVAL[TRNDEX]/100000;
428         TRNDEX=TRNDEX+1;
429         THRESH= -1;
430         if(TRNDEX <= TRNVLS)THRESH=MOD(TRNVAL[TRNDEX],100000)+1;
431 L2608:  if(VERB == SAY && WD2 > 0)VERB=0;
432         if(VERB == SAY) goto L4090;
433         if(TALLY == 0 && INDEEP(LOC) && LOC != 33)CLOCK1=CLOCK1-1;
434         if(CLOCK1 == 0) goto L10000;
435         if(CLOCK1 < 0)CLOCK2=CLOCK2-1;
436         if(CLOCK2 == 0) goto L11000;
437         if(PROP[LAMP] == 1)LIMIT=LIMIT-1;
438         if(LIMIT <= 30 && HERE(BATTER) && PROP[BATTER] == 0 && HERE(LAMP)) goto
439                 L12000;
440         if(LIMIT == 0) goto L12400;
441         if(LIMIT <= 30) goto L12200;
442 L19999: K=43;
443         if(LIQLOC(LOC) == WATER)K=70;
444         V1=VOCAB(WD1,-1);
445         V2=VOCAB(WD2,-1);
446         if(V1 == ENTER && (V2 == STREAM || V2 == 1000+WATER)) goto L2010;
447         if(V1 == ENTER && WD2 > 0) goto L2800;
448         if((V1 != 1000+WATER && V1 != 1000+OIL) || (V2 != 1000+PLANT && V2 !=
449                 1000+DOOR)) goto L2610;
450         {long x = V2-1000; if(AT(x))WD2=MAKEWD(16152118);}
451 L2610:  if(V1 == 1000+CAGE && V2 == 1000+BIRD && HERE(CAGE) &&
452                 HERE(BIRD))WD1=MAKEWD(301200308);
453 L2620:  if(WD1 != MAKEWD(23051920)) goto L2625;
454         IWEST=IWEST+1;
455         if(IWEST == 10)RSPEAK(17);
456 L2625:  if(WD1 != MAKEWD( 715) || WD2 == 0) goto L2630;
457         IGO=IGO+1;
458         if(IGO == 10)RSPEAK(276);
459 L2630:  I=VOCAB(WD1,-1);
460         if(I == -1) goto L3000;
461         K=MOD(I,1000);
462         KQ=I/1000+1;
463          switch (KQ-1) { case 0: goto L8; case 1: goto L5000; case 2: goto L4000;
464                 case 3: goto L2010; }
465         BUG(22);
466
467 /*  Get second word for analysis. */
468
469 L2800:  WD1=WD2;
470         WD1X=WD2X;
471         WD2=0;
472          goto L2620;
473
474 /*  Gee, I don't understand. */
475
476 L3000:  SETPRM(1,WD1,WD1X);
477          if (fallback_handler(rawbuf))
478              return true;
479         RSPEAK(254);
480          goto L2600;
481
482 /* Verb and object analysis moved to separate module. */
483
484 L4000:  I=4000; goto Laction;
485 L4090:  I=4090; goto Laction;
486 L5000:  I=5000;
487 Laction:
488          switch (action(cmdin, I)) {
489            case 2: return true;
490            case 8: goto L8;
491            case 2000: goto L2000;
492            case 2009: goto L2009;
493            case 2010: goto L2010;
494            case 2011: goto L2011;
495            case 2012: goto L2012;
496            case 2600: goto L2600;
497            case 2607: goto L2607;
498            case 2630: goto L2630;
499            case 2800: goto L2800;
500            case 8000: goto L8000;
501            case 18999: goto L18999;
502            case 19000: goto L19000;
503            }
504         BUG(99);
505
506 /*  Random intransitive verbs come here.  Clear obj just in case (see "attack").
507                 */
508
509 L8000:  SETPRM(1,WD1,WD1X);
510         RSPEAK(257);
511         OBJ=0;
512         goto L2600;
513
514 /*  Figure out the new location
515  *
516  *  Given the current location in "LOC", and a motion verb number in "K", put
517  *  the new location in "NEWLOC".  The current loc is saved in "OLDLOC" in case
518  *  he wants to retreat.  The current OLDLOC is saved in OLDLC2, in case he
519  *  dies.  (if he does, NEWLOC will be limbo, and OLDLOC will be what killed
520  *  him, so we need OLDLC2, which is the last place he was safe.) */
521
522 L8:     KK=KEY[LOC];
523         NEWLOC=LOC;
524         if(KK == 0)BUG(26);
525         if(K == NUL) return true;
526         if(K == BACK) goto L20;
527         if(K == LOOK) goto L30;
528         if(K == CAVE) goto L40;
529         OLDLC2=OLDLOC;
530         OLDLOC=LOC;
531
532 L9:     LL=IABS(TRAVEL[KK]);
533         if(MOD(LL,1000) == 1 || MOD(LL,1000) == K) goto L10;
534         if(TRAVEL[KK] < 0) goto L50;
535         KK=KK+1;
536          goto L9;
537
538 L10:    LL=LL/1000;
539 L11:    NEWLOC=LL/1000;
540         K=MOD(NEWLOC,100);
541         if(NEWLOC <= 300) goto L13;
542         if(PROP[K] != NEWLOC/100-3) goto L16;
543 L12:    if(TRAVEL[KK] < 0)BUG(25);
544         KK=KK+1;
545         NEWLOC=IABS(TRAVEL[KK])/1000;
546         if(NEWLOC == LL) goto L12;
547         LL=NEWLOC;
548          goto L11;
549
550 L13:    if(NEWLOC <= 100) goto L14;
551         if(TOTING(K) || (NEWLOC > 200 && AT(K))) goto L16;
552          goto L12;
553
554 L14:    if(NEWLOC != 0 && !PCT(NEWLOC)) goto L12;
555 L16:    NEWLOC=MOD(LL,1000);
556         if(NEWLOC <= 300) return true;
557         if(NEWLOC <= 500) goto L30000;
558         RSPEAK(NEWLOC-500);
559         NEWLOC=LOC;
560          return true;
561
562 /*  Special motions come here.  Labelling convention: statement numbers NNNXX
563  *  (XX=00-99) are used for special case number NNN (NNN=301-500). */
564
565 L30000: NEWLOC=NEWLOC-300;
566          switch (NEWLOC) { case 1: goto L30100; case 2: goto L30200; case 3: goto
567                 L30300; }
568         BUG(20);
569
570 /*  Travel 301.  Plover-alcove passage.  Can carry only emerald.  Note: travel
571  *  table must include "useless" entries going through passage, which can never
572  *  be used for actual motion, but can be spotted by "go back". */
573
574 L30100: NEWLOC=99+100-LOC;
575         if(HOLDNG == 0 || (HOLDNG == 1 && TOTING(EMRALD))) return true;
576         NEWLOC=LOC;
577         RSPEAK(117);
578         return true;
579
580 /*  Travel 302.  Plover transport.  Drop the emerald (only use special travel if
581  *  toting it), so he's forced to use the plover-passage to get it out.  Having
582  *  dropped it, go back and pretend he wasn't carrying it after all. */
583
584 L30200: DROP(EMRALD,LOC);
585          goto L12;
586
587 /*  Travel 303.  Troll bridge.  Must be done only as special motion so that
588  *  dwarves won't wander across and encounter the bear.  (They won't follow the
589  *  player there because that region is forbidden to the pirate.)  If
590  *  PROP(TROLL)=1, he's crossed since paying, so step out and block him.
591  *  (standard travel entries check for PROP(TROLL)=0.)  Special stuff for bear. */
592
593 L30300: if(PROP[TROLL] != 1) goto L30310;
594         PSPEAK(TROLL,1);
595         PROP[TROLL]=0;
596         MOVE(TROLL2,0);
597         MOVE(TROLL2+100,0);
598         MOVE(TROLL,PLAC[TROLL]);
599         MOVE(TROLL+100,FIXD[TROLL]);
600         JUGGLE(CHASM);
601         NEWLOC=LOC;
602         return true;
603
604 L30310: NEWLOC=PLAC[TROLL]+FIXD[TROLL]-LOC;
605         if(PROP[TROLL] == 0)PROP[TROLL]=1;
606         if(!TOTING(BEAR)) return true;
607         RSPEAK(162);
608         PROP[CHASM]=1;
609         PROP[TROLL]=2;
610         DROP(BEAR,NEWLOC);
611         FIXED[BEAR]= -1;
612         PROP[BEAR]=3;
613         OLDLC2=NEWLOC;
614          goto L99;
615
616 /*  End of specials. */
617
618 /*  Handle "go back".  Look for verb which goes from LOC to OLDLOC, or to OLDLC2
619  *  If OLDLOC has forced-motion.  K2 saves entry -> forced loc -> previous loc. */
620
621 L20:    K=OLDLOC;
622         if(FORCED(K))K=OLDLC2;
623         OLDLC2=OLDLOC;
624         OLDLOC=LOC;
625         K2=0;
626         if(K == LOC)K2=91;
627         if(CNDBIT(LOC,4))K2=274;
628         if(K2 == 0) goto L21;
629         RSPEAK(K2);
630         return true;
631
632 L21:    LL=MOD((IABS(TRAVEL[KK])/1000),1000);
633         if(LL == K) goto L25;
634         if(LL > 300) goto L22;
635         J=KEY[LL];
636         if(FORCED(LL) && MOD((IABS(TRAVEL[J])/1000),1000) == K)K2=KK;
637 L22:    if(TRAVEL[KK] < 0) goto L23;
638         KK=KK+1;
639          goto L21;
640
641 L23:    KK=K2;
642         if(KK != 0) goto L25;
643         RSPEAK(140);
644         return true;
645
646 L25:    K=MOD(IABS(TRAVEL[KK]),1000);
647         KK=KEY[LOC];
648          goto L9;
649
650 /*  Look.  Can't give more detail.  Pretend it wasn't dark (though it may "now"
651  *  be dark) so he won't fall into a pit while staring into the gloom. */
652
653 L30:    if(DETAIL < 3)RSPEAK(15);
654         DETAIL=DETAIL+1;
655         WZDARK=false;
656         ABB[LOC]=0;
657         return true;
658
659 /*  Cave.  Different messages depending on whether above ground. */
660
661 L40:    K=58;
662         if(OUTSID(LOC) && LOC != 8)K=57;
663         RSPEAK(K);
664         return true;
665
666 /*  Non-applicable motion.  Various messages depending on word given. */
667
668 L50:    SPK=12;
669         if(K >= 43 && K <= 50)SPK=52;
670         if(K == 29 || K == 30)SPK=52;
671         if(K == 7 || K == 36 || K == 37)SPK=10;
672         if(K == 11 || K == 19)SPK=11;
673         if(VERB == FIND || VERB == INVENT)SPK=59;
674         if(K == 62 || K == 65)SPK=42;
675         if(K == 17)SPK=80;
676         RSPEAK(SPK);
677         return true;
678
679 /*  "You're dead, Jim."
680  *
681  *  If the current loc is zero, it means the clown got himself killed.  We'll
682  *  allow this maxdie times.  MAXDIE is automatically set based on the number of
683  *  snide messages available.  Each death results in a message (81, 83, etc.)
684  *  which offers reincarnation; if accepted, this results in message 82, 84,
685  *  etc.  The last time, if he wants another chance, he gets a snide remark as
686  *  we exit.  When reincarnated, all objects being carried get dropped at OLDLC2
687  *  (presumably the last place prior to being killed) without change of props.
688  *  the loop runs backwards to assure that the bird is dropped before the cage.
689  *  (this kluge could be changed once we're sure all references to bird and cage
690  *  are done by keywords.)  The lamp is a special case (it wouldn't do to leave
691  *  it in the cave).  It is turned off and left outside the building (only if he
692  *  was carrying it, of course).  He himself is left inside the building (and
693  *  heaven help him if he tries to xyzzy back into the cave without the lamp!).
694  *  OLDLOC is zapped so he can't just "retreat". */
695
696 /*  The easiest way to get killed is to fall into a pit in pitch darkness. */
697
698 L90:    RSPEAK(23);
699         OLDLC2=LOC;
700
701 /*  Okay, he's dead.  Let's get on with it. */
702
703 L99:    if(CLOSNG) goto L95;
704         NUMDIE=NUMDIE+1;
705         if(!YES(cmdin,79+NUMDIE*2,80+NUMDIE*2,54)) score(0);
706         if(NUMDIE == MAXDIE) score(0);
707         PLACE[WATER]=0;
708         PLACE[OIL]=0;
709         if(TOTING(LAMP))PROP[LAMP]=0;
710         /* 98 */ for (J=1; J<=100; J++) {
711         I=101-J;
712         if(!TOTING(I)) goto L98;
713         K=OLDLC2;
714         if(I == LAMP)K=1;
715         DROP(I,K);
716 L98:    /*etc*/ ;
717         } /* end loop */
718         LOC=3;
719         OLDLOC=LOC;
720          goto L2000;
721
722 /*  He died during closing time.  No resurrection.  Tally up a death and exit. */
723
724 L95:    RSPEAK(131);
725         NUMDIE=NUMDIE+1;
726          score(0);
727
728
729
730
731 /*  Hints */
732
733 /*  Come here if he's been long enough at required loc(s) for some unused hint.
734  *  hint number is in variable "hint".  Branch to quick test for additional
735  *  conditions, then come back to do neat stuff.  Goto 40010 if conditions are
736  *  met and we want to offer the hint.  Goto 40020 to clear HINTLC back to zero,
737  *  40030 to take no action yet. */
738
739 L40000:    switch (HINT-1) { case 0: goto L40100; case 1: goto L40200; case 2: goto
740                 L40300; case 3: goto L40400; case 4: goto L40500; case 5: goto
741                 L40600; case 6: goto L40700; case 7: goto L40800; case 8: goto
742                 L40900; case 9: goto L41000; }
743 /*              CAVE  BIRD  SNAKE MAZE  DARK  WITT  URN   WOODS OGRE
744  *              JADE */
745         BUG(27);
746
747 L40010: HINTLC[HINT]=0;
748         if(!YES(cmdin,HINTS[HINT][3],0,54)) goto L2602;
749         SETPRM(1,HINTS[HINT][2],HINTS[HINT][2]);
750         RSPEAK(261);
751         HINTED[HINT]=YES(cmdin,175,HINTS[HINT][4],54);
752         if(HINTED[HINT] && LIMIT > 30)LIMIT=LIMIT+30*HINTS[HINT][2];
753 L40020: HINTLC[HINT]=0;
754 L40030:  goto L2602;
755
756 /*  Now for the quick tests.  See database description for one-line notes. */
757
758 L40100: if(PROP[GRATE] == 0 && !HERE(KEYS)) goto L40010;
759          goto L40020;
760
761 L40200: if(PLACE[BIRD] == LOC && TOTING(ROD) && OLDOBJ == BIRD) goto L40010;
762          goto L40030;
763
764 L40300: if(HERE(SNAKE) && !HERE(BIRD)) goto L40010;
765          goto L40020;
766
767 L40400: if(ATLOC[LOC] == 0 && ATLOC[OLDLOC] == 0 && ATLOC[OLDLC2] == 0 && HOLDNG >
768                 1) goto L40010;
769          goto L40020;
770
771 L40500: if(PROP[EMRALD] != -1 && PROP[PYRAM] == -1) goto L40010;
772          goto L40020;
773
774 L40600:  goto L40010;
775
776 L40700: if(DFLAG == 0) goto L40010;
777          goto L40020;
778
779 L40800: if(ATLOC[LOC] == 0 && ATLOC[OLDLOC] == 0 && ATLOC[OLDLC2] == 0) goto
780                 L40010;
781          goto L40030;
782
783 L40900: I=ATDWRF(LOC);
784         if(I < 0) goto L40020;
785         if(HERE(OGRE) && I == 0) goto L40010;
786          goto L40030;
787
788 L41000: if(TALLY == 1 && PROP[JADE] < 0) goto L40010;
789          goto L40020;
790
791
792
793
794
795 /*  Cave closing and scoring */
796
797
798 /*  These sections handle the closing of the cave.  The cave closes "clock1"
799  *  turns after the last treasure has been located (including the pirate's
800  *  chest, which may of course never show up).  Note that the treasures need not
801  *  have been taken yet, just located.  Hence clock1 must be large enough to get
802  *  out of the cave (it only ticks while inside the cave).  When it hits zero,
803  *  we branch to 10000 to start closing the cave, and then sit back and wait for
804  *  him to try to get out.  If he doesn't within clock2 turns, we close the
805  *  cave; if he does try, we assume he panics, and give him a few additional
806  *  turns to get frantic before we close.  When clock2 hits zero, we branch to
807  *  11000 to transport him into the final puzzle.  Note that the puzzle depends
808  *  upon all sorts of random things.  For instance, there must be no water or
809  *  oil, since there are beanstalks which we don't want to be able to water,
810  *  since the code can't handle it.  Also, we can have no keys, since there is a
811  *  grate (having moved the fixed object!) there separating him from all the
812  *  treasures.  Most of these problems arise from the use of negative prop
813  *  numbers to suppress the object descriptions until he's actually moved the
814  *  objects. */
815
816 /*  When the first warning comes, we lock the grate, destroy the bridge, kill
817  *  all the dwarves (and the pirate), remove the troll and bear (unless dead),
818  *  and set "closng" to true.  Leave the dragon; too much trouble to move it.
819  *  from now until clock2 runs out, he cannot unlock the grate, move to any
820  *  location outside the cave, or create the bridge.  Nor can he be
821  *  resurrected if he dies.  Note that the snake is already gone, since he got
822  *  to the treasure accessible only via the hall of the mountain king. Also, he's
823  *  been in giant room (to get eggs), so we can refer to it.  Also also, he's
824  *  gotten the pearl, so we know the bivalve is an oyster.  *And*, the dwarves
825  *  must have been activated, since we've found chest. */
826
827 L10000: PROP[GRATE]=0;
828         PROP[FISSUR]=0;
829         for (I=1; I<=6; I++) {
830         DSEEN[I]=false;
831         DLOC[I]=0;
832         } /* end loop */
833         MOVE(TROLL,0);
834         MOVE(TROLL+100,0);
835         MOVE(TROLL2,PLAC[TROLL]);
836         MOVE(TROLL2+100,FIXD[TROLL]);
837         JUGGLE(CHASM);
838         if(PROP[BEAR] != 3)DSTROY(BEAR);
839         PROP[CHAIN]=0;
840         FIXED[CHAIN]=0;
841         PROP[AXE]=0;
842         FIXED[AXE]=0;
843         RSPEAK(129);
844         CLOCK1= -1;
845         CLOSNG=true;
846          goto L19999;
847
848 /*  Once he's panicked, and clock2 has run out, we come here to set up the
849  *  storage room.  The room has two locs, hardwired as 115 (ne) and 116 (sw).
850  *  At the ne end, we place empty bottles, a nursery of plants, a bed of
851  *  oysters, a pile of lamps, rods with stars, sleeping dwarves, and him.  At
852  *  the sw end we place grate over treasures, snake pit, covey of caged birds,
853  *  more rods, and pillows.  A mirror stretches across one wall.  Many of the
854  *  objects come from known locations and/or states (e.g. the snake is known to
855  *  have been destroyed and needn't be carried away from its old "place"),
856  *  making the various objects be handled differently.  We also drop all other
857  *  objects he might be carrying (lest he have some which could cause trouble,
858  *  such as the keys).  We describe the flash of light and trundle back. */
859
860 L11000: PROP[BOTTLE]=PUT(BOTTLE,115,1);
861         PROP[PLANT]=PUT(PLANT,115,0);
862         PROP[OYSTER]=PUT(OYSTER,115,0);
863         OBJTXT[OYSTER]=3;
864         PROP[LAMP]=PUT(LAMP,115,0);
865         PROP[ROD]=PUT(ROD,115,0);
866         PROP[DWARF]=PUT(DWARF,115,0);
867         LOC=115;
868         OLDLOC=115;
869         NEWLOC=115;
870
871 /*  Leave the grate with normal (non-negative) property.  Reuse sign. */
872
873         I=PUT(GRATE,116,0);
874         I=PUT(SIGN,116,0);
875         OBJTXT[SIGN]=OBJTXT[SIGN]+1;
876         PROP[SNAKE]=PUT(SNAKE,116,1);
877         PROP[BIRD]=PUT(BIRD,116,1);
878         PROP[CAGE]=PUT(CAGE,116,0);
879         PROP[ROD2]=PUT(ROD2,116,0);
880         PROP[PILLOW]=PUT(PILLOW,116,0);
881
882         PROP[MIRROR]=PUT(MIRROR,115,0);
883         FIXED[MIRROR]=116;
884
885         for (I=1; I<=100; I++) {
886         if(TOTING(I))DSTROY(I);
887         } /* end loop */
888
889         RSPEAK(132);
890         CLOSED=true;
891         return true;
892
893 /*  Another way we can force an end to things is by having the lamp give out.
894  *  When it gets close, we come here to warn him.  We go to 12000 if the lamp
895  *  and fresh batteries are here, in which case we replace the batteries and
896  *  continue.  12200 is for other cases of lamp dying.  12400 is when it goes
897  *  out.  Even then, he can explore outside for a while if desired. */
898
899 L12000: RSPEAK(188);
900         PROP[BATTER]=1;
901         if(TOTING(BATTER))DROP(BATTER,LOC);
902         LIMIT=LIMIT+2500;
903         LMWARN=false;
904          goto L19999;
905
906 L12200: if(LMWARN || !HERE(LAMP)) goto L19999;
907         LMWARN=true;
908         SPK=187;
909         if(PLACE[BATTER] == 0)SPK=183;
910         if(PROP[BATTER] == 1)SPK=189;
911         RSPEAK(SPK);
912          goto L19999;
913
914 L12400: LIMIT= -1;
915         PROP[LAMP]=0;
916         if(HERE(LAMP))RSPEAK(184);
917          goto L19999;
918
919 /*  Oh dear, he's disturbed the dwarves. */
920
921 L18999: RSPEAK(SPK);
922 L19000: RSPEAK(136);
923         score(0);
924         return true;
925 }