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