1/*	$NetBSD: main.c,v 1.22 2021/05/02 12:50:43 rillig Exp $	*/
2
3/*-
4 * Copyright (c) 1991, 1993
5 *	The Regents of the University of California.  All rights reserved.
6 *
7 * The game adventure was originally written in Fortran by Will Crowther
8 * and Don Woods.  It was later translated to C and enhanced by Jim
9 * Gillogly.  This code is derived from software contributed to Berkeley
10 * by Jim Gillogly at The Rand Corporation.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 *    notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 *    notice, this list of conditions and the following disclaimer in the
19 *    documentation and/or other materials provided with the distribution.
20 * 3. Neither the name of the University nor the names of its contributors
21 *    may be used to endorse or promote products derived from this software
22 *    without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 */
36
37#include <sys/cdefs.h>
38#ifndef lint
39__COPYRIGHT("@(#) Copyright (c) 1991, 1993\
40 The Regents of the University of California.  All rights reserved.");
41#endif /* not lint */
42
43#ifndef lint
44#if 0
45static char sccsid[] = "@(#)main.c	8.1 (Berkeley) 6/2/93";
46#else
47__RCSID("$NetBSD: main.c,v 1.22 2021/05/02 12:50:43 rillig Exp $");
48#endif
49#endif /* not lint */
50
51/*      Re-coding of advent in C: main program */
52
53#include <sys/file.h>
54#include <err.h>
55#include <signal.h>
56#include <stdio.h>
57#include <stdlib.h>
58#include <unistd.h>
59#include "hdr.h"
60#include "extern.h"
61
62int
63main(int argc, char **argv)
64{
65	int     i;
66	int     rval, ll;
67	struct text *kk;
68
69	/* revoke setgid privileges from dm */
70	setgid(getgid());
71
72	init();		/* Initialize everything */
73	signal(SIGINT, trapdel);
74
75	if (argc > 1) {		/* Restore file specified */
76				/* Restart is label 8305 (Fortran) */
77		i = restore(argv[1]);	/* See what we've got */
78		switch (i) {
79		case 0:	/* The restore worked fine */
80			yea = Start();
81			k = null;
82			unlink(argv[1]);	/* Don't re-use the save */
83			goto l8;		/* Get where we're going */
84		case 1:				/* Couldn't open it */
85			errx(1,"can't open file");	/* So give up */
86		case 2:				/* Oops -- file was altered */
87			rspeak(202);		/* You dissolve */
88			exit(1);	/* File could be non-adventure */
89		}			/* So don't unlink it. */
90	}
91	startup();			/* prepare for a user */
92
93	for (;;) {			/* main command loop (label 2) */
94		if (newloc < 9 && newloc != 0 && isclosing) {
95			rspeak(130);	/* if closing leave only by */
96			newloc = loc;	/* main office */
97			if (!panic)
98				clock2 = 15;
99			panic = TRUE;
100		}
101		rval = fdwarf();	/* dwarf stuff */
102		if (rval == 99)
103			die(99);
104
105l2000:		if (loc == 0)
106			die(99);	/* label 2000 */
107		kk = &stext[loc];
108		if ((abb[loc] % abbnum) == 0 || kk->seekadr == 0)
109			kk = &ltext[loc];
110		if (!forced(loc) && dark()) {
111			if (wasdark && pct(35)) {
112				die(90);
113				goto l2000;
114			}
115			kk = &rtext[16];
116		}
117#if 0
118l2001:
119#endif
120		if (toting(bear))
121			rspeak(141);	/* 2001 */
122		speak(kk);
123		k = 1;
124		if (forced(loc))
125			goto l8;
126		if (loc == 33 && pct(25) && !isclosing)
127			rspeak(8);
128		if (!dark()) {
129			abb[loc]++;
130			for (i = atloc[loc]; i != 0; i = links[i]) { /* 2004 */
131				obj = i;
132				if (obj > 100)
133					obj -= 100;
134				if (obj == steps && toting(nugget))
135					continue;
136				if (prop[obj] < 0) {
137					if (closed)
138						continue;
139					prop[obj] = 0;
140					if (obj == rug || obj == chain)
141						prop[obj] = 1;
142					tally--;
143					if (tally == tally2 && tally != 0)
144						if (limit > 35)
145							limit = 35;
146				}
147				ll = prop[obj];	/* 2006 */
148				if (obj == steps && loc == fixed[steps])
149					ll = 1;
150				pspeak(obj, ll);
151			}	/* 2008 */
152			goto l2012;
153	l2009:		k = 54;	/* 2009 */
154	l2010:		spk = k;
155	l2011:		rspeak(spk);
156		}
157l2012:		verb = 0;	/* 2012 */
158		obj = 0;
159l2600:		checkhints();	/* to 2600-2602 */
160		if (closed) {
161			if (prop[oyster] < 0 && toting(oyster))
162				pspeak(oyster, 1);
163			for (i = 1; i < 100; i++)
164				if (toting(i) && prop[i] < 0)	/* 2604 */
165					prop[i] = -1 - prop[i];
166		}
167		wasdark = dark();	/* 2605 */
168		if (knfloc > 0 && knfloc != loc)
169			knfloc = 1;
170		getin(&wd1, &wd2);
171		if (delhit) {	/* user typed a DEL */
172			delhit = 0;	/* reset counter */
173			copystr("quit", wd1);	/* pretend he's quitting */
174			*wd2 = 0;
175		}
176l2608:		if ((foobar = -foobar) > 0)
177			foobar = 0;	/* 2608 */
178		/* should check here for "magic mode" */
179		turns++;
180		if (demo && turns >= SHORT)
181			done(1);	/* to 13000 */
182
183		if (verb == say && *wd2 != 0)
184			verb = 0;
185		if (verb == say)
186			goto l4090;
187		if (tally == 0 && loc >= 15 && loc != 33)
188			clock1--;
189		if (clock1 == 0) {
190			closing();	/* to 10000 */
191			goto l19999;
192		}
193		if (clock1 < 0)
194			clock2--;
195		if (clock2 == 0) {
196			caveclose();	/* to 11000 */
197			continue;	/* back to 2 */
198		}
199		if (prop[lamp] == 1)
200			limit--;
201		if (limit <= 30 && here(batter) && prop[batter] == 0
202		    && here(lamp)) {
203			rspeak(188);	/* 12000 */
204			prop[batter] = 1;
205			if (toting(batter))
206				drop(batter, loc);
207			limit = limit + 2500;
208			lmwarn = FALSE;
209			goto l19999;
210		}
211		if (limit == 0) {
212			limit = -1;	/* 12400 */
213			prop[lamp] = 0;
214			rspeak(184);
215			goto l19999;
216		}
217		if (limit < 0 && loc <= 8) {
218			rspeak(185);	/* 12600 */
219			gaveup = TRUE;
220			done(2);	/* to 20000 */
221		}
222		if (limit <= 30) {
223			if (lmwarn || !here(lamp))
224				goto l19999;	/* 12200 */
225			lmwarn = TRUE;
226			spk = 187;
227			if (place[batter] == 0)
228				spk = 183;
229			if (prop[batter] == 1)
230				spk = 189;
231			rspeak(spk);
232		}
233l19999:	k = 43;
234		if (liqloc(loc) == water)
235			k = 70;
236		if (weq(wd1, "enter") &&
237		    (weq(wd2, "strea") || weq(wd2, "water")))
238			goto l2010;
239		if (weq(wd1, "enter") && *wd2 != 0)
240			goto l2800;
241		if ((!weq(wd1, "water") && !weq(wd1, "oil"))
242		    || (!weq(wd2, "plant") && !weq(wd2, "door")))
243			goto l2610;
244		if (at(vocab(wd2, 1, 0)))
245			copystr("pour", wd2);
246
247l2610:		if (weq(wd1, "west"))
248			if (++iwest == 10)
249				rspeak(17);
250l2630:		i = vocab(wd1, -1, 0);
251		if (i == -1) {
252			spk = 60;	/* 3000 */
253			if (pct(20))
254				spk = 61;
255			if (pct(20))
256				spk = 13;
257			rspeak(spk);
258			goto l2600;
259		}
260		k = i % 1000;
261		kq = i / 1000 + 1;
262		switch (kq) {
263		case 1:
264			goto l8;
265		case 2:
266			goto l5000;
267		case 3:
268			goto l4000;
269		case 4:
270			goto l2010;
271		default:
272			bug(22);
273		}
274
275l8:
276		switch (march()) {
277		case 2:
278			continue;	/* i.e. goto l2 */
279		case 99:
280			die(99);
281			goto l2000;
282		default:
283			bug(110);
284		}
285
286l2800:		copystr(wd2, wd1);
287		*wd2 = 0;
288		goto l2610;
289
290l4000:		verb = k;
291		spk = actspeak[verb];
292		if (*wd2 != 0 && verb != say)
293			goto l2800;
294		if (verb == say)
295			obj = *wd2;
296		if (obj != 0)
297			goto l4090;
298#if 0
299l4080:
300#endif
301		switch (verb) {
302		case 1:	/* take = 8010 */
303			if (atloc[loc] == 0 || links[atloc[loc]] != 0)
304				goto l8000;
305			for (i = 1; i <= 5; i++)
306				if (dloc[i] == loc && dflag >= 2)
307					goto l8000;
308			obj = atloc[loc];
309			goto l9010;
310		case 2:
311		case 3:
312		case 9:	/* 8000 : drop,say,wave */
313		case 10:
314		case 16:
315		case 17:	/* calm,rub,toss */
316		case 19:
317		case 21:
318		case 28:	/* find,feed,break */
319		case 29:	/* wake */
320	l8000:		printf("%s what?\n", wd1);
321			obj = 0;
322			goto l2600;
323		case 4:
324		case 6:	/* 8040 open,lock */
325			spk = 28;
326			if (here(clam))
327				obj = clam;
328			if (here(oyster))
329				obj = oyster;
330			if (at(door))
331				obj = door;
332			if (at(grate))
333				obj = grate;
334			if (obj != 0 && here(chain))
335				goto l8000;
336			if (here(chain))
337				obj = chain;
338			if (obj == 0)
339				goto l2011;
340			goto l9040;
341		case 5:
342			goto l2009;	/* nothing */
343		case 7:
344			goto l9070;	/* on */
345		case 8:
346			goto l9080;	/* off */
347		case 11:
348			goto l8000;	/* walk */
349		case 12:
350			goto l9120;	/* kill */
351		case 13:
352			goto l9130;	/* pour */
353		case 14:		/* eat: 8140 */
354			if (!here(food))
355				goto l8000;
356	l8142:		destroy(food);
357			spk = 72;
358			goto l2011;
359		case 15:
360			goto l9150;	/* drink */
361		case 18:		/* quit: 8180 */
362			gaveup = yes(22, 54, 54);
363			if (gaveup)
364				done(2);	/* 8185 */
365			goto l2012;
366		case 20:	/* invent=8200 */
367			spk = 98;
368			for (i = 1; i <= 100; i++) {
369				if (i != bear && toting(i)) {
370					if (spk == 98)
371						rspeak(99);
372					blklin = FALSE;
373					pspeak(i, -1);
374					blklin = TRUE;
375					spk = 0;
376				}
377			}
378			if (toting(bear))
379				spk = 141;
380			goto l2011;
381		case 22:
382			goto l9220;	/* fill */
383		case 23:
384			goto l9230;	/* blast */
385		case 24:		/* score: 8240 */
386			scoring = TRUE;
387			printf("If you were to quit now, you would score");
388			printf(" %d out of a possible ", score());
389			printf("%d.", maxscore);
390			scoring = FALSE;
391			gaveup = yes(143, 54, 54);
392			if (gaveup)
393				done(2);
394			goto l2012;
395		case 25:	/* foo: 8250 */
396			k = vocab(wd1, 3, 0);
397			spk = 42;
398			if (foobar == 1 - k)
399				goto l8252;
400			if (foobar != 0)
401				spk = 151;
402			goto l2011;
403	l8252:		foobar = k;
404			if (k != 4)
405				goto l2009;
406			foobar = 0;
407			if (place[eggs] == plac[eggs]
408			    || (toting(eggs) && loc == plac[eggs]))
409				goto l2011;
410			if (place[eggs] == 0 && place[troll] == 0 &&
411			    prop[troll] == 0)
412				prop[troll] = 1;
413			k = 2;
414			if (here(eggs))
415				k = 1;
416			if (loc == plac[eggs])
417				k = 0;
418			move(eggs, plac[eggs]);
419			pspeak(eggs, k);
420			goto l2012;
421		case 26:	/* brief=8260 */
422			spk = 156;
423			abbnum = 10000;
424			detail = 3;
425			goto l2011;
426		case 27:	/* read=8270 */
427			if (here(magazine))
428				obj = magazine;
429			if (here(tablet))
430				obj = obj * 100 + tablet;
431			if (here(message))
432				obj = obj * 100 + message;
433			if (closed && toting(oyster))
434				obj = oyster;
435			if (obj > 100 || obj == 0 || dark())
436				goto l8000;
437			goto l9270;
438		case 30:	/* suspend=8300 */
439			spk = 201;
440			if (demo)
441				goto l2011;
442			printf("I can suspend your adventure for you so");
443			printf(" you can resume later, but\n");
444			printf("you will have to wait at least");
445			printf(" %d minutes before continuing.", latency);
446			if (!yes(200, 54, 54))
447				goto l2012;
448			datime(&saveday, &savet);
449			ciao();	/* Do we quit? */
450			continue;	/* Maybe not */
451		case 31:	/* hours=8310 */
452			printf("Colossal cave is closed 9am-5pm Mon ");
453			printf("through Fri except holidays.\n");
454			goto l2012;
455		default:
456			bug(23);
457		}
458
459l4090:
460		switch (verb) {
461		case 1:	/* take = 9010 */
462	l9010:		switch (trtake()) {
463			case 2011:
464				goto l2011;
465			case 9220:
466				goto l9220;
467			case 2009:
468				goto l2009;
469			case 2012:
470				goto l2012;
471			default:
472				bug(102);
473			}
474		l9020: case 2:	/* drop = 9020 */
475			switch (trdrop()) {
476			case 2011:
477				goto l2011;
478			case 19000:
479				done(3);
480			case 2012:
481				goto l2012;
482			default:
483				bug(105);
484			}
485#if 0
486	l9030:
487#endif
488		case 3:
489			switch (trsay()) {
490			case 2012:
491				goto l2012;
492			case 2630:
493				goto l2630;
494			default:
495				bug(107);
496			}
497		l9040: case 4:
498		case 6:	/* open, close */
499			switch (tropen()) {
500			case 2011:
501				goto l2011;
502			case 2010:
503				goto l2010;
504			default:
505				bug(106);
506			}
507		case 5:
508			goto l2009;	/* nothing */
509		case 7:			/* on   9070 */
510	l9070:		if (!here(lamp))
511				goto l2011;
512			spk = 184;
513			if (limit < 0)
514				goto l2011;
515			prop[lamp] = 1;
516			rspeak(39);
517			if (wasdark)
518				goto l2000;
519			goto l2012;
520
521		case 8:		/* off */
522	l9080:		if (!here(lamp))
523				goto l2011;
524			prop[lamp] = 0;
525			rspeak(40);
526			if (dark())
527				rspeak(16);
528			goto l2012;
529
530		case 9:	/* wave */
531			if ((!toting(obj)) && (obj != rod || !toting(rod2)))
532				spk = 29;
533			if (obj != rod || !at(fissure) || !toting(obj) || isclosing)
534				goto l2011;
535			prop[fissure] = 1 - prop[fissure];
536			pspeak(fissure, 2 - prop[fissure]);
537			goto l2012;
538		case 10:
539		case 11:
540		case 18:	/* calm, walk, quit */
541		case 24:
542		case 25:
543		case 26:	/* score, foo, brief */
544		case 30:
545		case 31:	/* suspend, hours */
546			goto l2011;
547		l9120: case 12:/* kill */
548			switch (trkill()) {
549			case 8000:
550				goto l8000;
551			case 8:
552				goto l8;
553			case 2011:
554				goto l2011;
555			case 2608:
556				goto l2608;
557			case 19000:
558				done(3);
559			default:
560				bug(112);
561			}
562		l9130: case 13:/* pour */
563			if (obj == bottle || obj == 0)
564				obj = liq();
565			if (obj == 0)
566				goto l8000;
567			if (!toting(obj))
568				goto l2011;
569			spk = 78;
570			if (obj != oil && obj != water)
571				goto l2011;
572			prop[bottle] = 1;
573			place[obj] = 0;
574			spk = 77;
575			if (!(at(plant) || at(door)))
576				goto l2011;
577			if (at(door)) {
578				prop[door] = 0;	/* 9132 */
579				if (obj == oil)
580					prop[door] = 1;
581				spk = 113 + prop[door];
582				goto l2011;
583			}
584			spk = 112;
585			if (obj != water)
586				goto l2011;
587			pspeak(plant, prop[plant] + 1);
588			prop[plant] = (prop[plant] + 2) % 6;
589			prop[plant2] = prop[plant] / 2;
590			k = null;
591			goto l8;
592		case 14:	/* 9140 - eat */
593			if (obj == food)
594				goto l8142;
595			if (obj == bird || obj == snake || obj == clam
596			    || obj == oyster || obj == dwarf || obj == dragon
597			    || obj == troll || obj == bear)
598				spk = 71;
599			goto l2011;
600		l9150: case 15:/* 9150 - drink */
601			if (obj == 0 && liqloc(loc) != water && (liq() != water
602			    || !here(bottle)))
603				goto l8000;
604			if (obj != 0 && obj != water)
605				spk = 110;
606			if (spk == 110 || liq() != water || !here(bottle))
607				goto l2011;
608			prop[bottle] = 1;
609			place[water] = 0;
610			spk = 74;
611			goto l2011;
612		case 16:	/* 9160: rub */
613			if (obj != lamp)
614				spk = 76;
615			goto l2011;
616		case 17:	/* 9170: throw */
617			switch (trtoss()) {
618			case 2011:
619				goto l2011;
620			case 9020:
621				goto l9020;
622			case 9120:
623				goto l9120;
624			case 8:
625				goto l8;
626			case 9210:
627				goto l9210;
628			default:
629				bug(113);
630			}
631		case 19:
632		case 20:	/* 9190: find, invent */
633			if (at(obj) || (liq() == obj && at(bottle))
634			    || k == liqloc(loc))
635				spk = 94;
636			for (i = 1; i <= 5; i++)
637				if (dloc[i] == loc && dflag >= 2
638				    && obj == dwarf)
639					spk = 94;
640			if (closed)
641				spk = 138;
642			if (toting(obj))
643				spk = 24;
644			goto l2011;
645		l9210: case 21:/* feed */
646			switch (trfeed()) {
647			case 2011:
648				goto l2011;
649			default:
650				bug(114);
651			}
652		l9220: case 22:/* fill */
653			switch (trfill()) {
654			case 2011:
655				goto l2011;
656			case 8000:
657				goto l8000;
658			case 9020:
659				goto l9020;
660			default:
661				bug(115);
662			}
663		l9230: case 23:/* blast */
664			if (prop[rod2] < 0 || !closed)
665				goto l2011;
666			bonus = 133;
667			if (loc == 115)
668				bonus = 134;
669			if (here(rod2))
670				bonus = 135;
671			rspeak(bonus);
672			done(2);
673		l9270: case 27:/* read */
674			if (dark())
675				goto l5190;
676			if (obj == magazine)
677				spk = 190;
678			if (obj == tablet)
679				spk = 196;
680			if (obj == message)
681				spk = 191;
682			if (obj == oyster && hinted[2] && toting(oyster))
683				spk = 194;
684			if (obj != oyster || hinted[2] || !toting(oyster)
685			    || !closed)
686				goto l2011;
687			hinted[2] = yes(192, 193, 54);
688			goto l2012;
689#if 0
690	l9280:
691#endif
692		case 28:	/* break */
693			if (obj == mirror)
694				spk = 148;
695			if (obj == vase && prop[vase] == 0) {
696				spk = 198;
697				if (toting(vase))
698					drop(vase, loc);
699				prop[vase] = 2;
700				fixed[vase] = -1;
701				goto l2011;
702			}
703			if (obj != mirror || !closed)
704				goto l2011;
705			rspeak(197);
706			done(3);
707#if 0
708	l9290:
709#endif
710		case 29:	/* wake */
711			if (obj != dwarf || !closed)
712				goto l2011;
713			rspeak(199);
714			done(3);
715
716		default:
717			bug(24);
718		}
719
720l5000:
721		obj = k;
722		if (fixed[k] != loc && !here(k))
723			goto l5100;
724l5010:		if (*wd2 != 0)
725			goto l2800;
726		if (verb != 0)
727			goto l4090;
728		printf("What do you want to do with the %s?\n", wd1);
729		goto l2600;
730l5100:		if (k != grate)
731			goto l5110;
732		if (loc == 1 || loc == 4 || loc == 7)
733			k = depression;
734		if (loc > 9 && loc < 15)
735			k = entrance;
736		if (k != grate)
737			goto l8;
738l5110:		if (k != dwarf)
739			goto l5120;
740		for (i = 1; i <= 5; i++)
741			if (dloc[i] == loc && dflag >= 2)
742				goto l5010;
743l5120:		if ((liq() == k && here(bottle)) || k == liqloc(loc))
744			goto l5010;
745		if (obj != plant || !at(plant2) || prop[plant2] == 0)
746			goto l5130;
747		obj = plant2;
748		goto l5010;
749l5130:		if (obj != knife || knfloc != loc)
750			goto l5140;
751		knfloc = -1;
752		spk = 116;
753		goto l2011;
754l5140:		if (obj != rod || !here(rod2))
755			goto l5190;
756		obj = rod2;
757		goto l5010;
758l5190:		if ((verb == find || verb == invent) && *wd2 == 0)
759			goto l5010;
760		printf("I see no %s here\n", wd1);
761		goto l2012;
762	}
763}
764