xref: /netbsd-src/games/battlestar/cypher.c (revision 1182a44c59cae4d586117d55eca24b4b8b173211)
1 /*	$NetBSD: cypher.c,v 1.24 2021/05/02 12:50:43 rillig Exp $	*/
2 
3 /*
4  * Copyright (c) 1983, 1993
5  *	The Regents of the University of California.  All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. Neither the name of the University nor the names of its contributors
16  *    may be used to endorse or promote products derived from this software
17  *    without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29  * SUCH DAMAGE.
30  */
31 
32 #include <sys/cdefs.h>
33 #ifndef lint
34 #if 0
35 static char sccsid[] = "@(#)cypher.c	8.2 (Berkeley) 4/28/95";
36 #else
37 __RCSID("$NetBSD: cypher.c,v 1.24 2021/05/02 12:50:43 rillig Exp $");
38 #endif
39 #endif				/* not lint */
40 
41 #include "extern.h"
42 
43 int
cypher(void)44 cypher(void)
45 {
46 	int     n;
47 	int     junk;
48 	int     lflag = -1;
49 	char    buffer[10];
50 	char   *filename, *rfilename;
51 	size_t	filename_len;
52 
53 	while (wordnumber <= wordcount) {
54 		if (wordtype[wordnumber] != VERB &&
55 		    !(wordtype[wordnumber] == OBJECT &&
56 		    wordvalue[wordnumber] == KNIFE)) {
57 			printf("%s: How's that?\n",
58 			    (wordnumber == wordcount) ? words[0] :
59 			    words[wordnumber]);
60 			return (-1);
61 		}
62 
63 		switch (wordvalue[wordnumber]) {
64 
65 		case AUXVERB:
66 			/*
67 			 * Take the following word as the verb (e.g.
68 			 * "make love", "climb up").
69 			 */
70 			wordnumber++;
71 			continue;
72 
73 		case UP:
74 			if (location[position].access || wiz || tempwiz) {
75 				if (!location[position].access) {
76 					printf("Zap!  A gust of wind lifts ");
77 					puts("you up.");
78 				}
79 				if (!moveplayer(location[position].up, AHEAD))
80 					return (-1);
81 			} else {
82 				puts("There is no way up.");
83 				return (-1);
84 			}
85 			lflag = 0;
86 			break;
87 
88 		case DOWN:
89 			if (!moveplayer(location[position].down, AHEAD))
90 				return (-1);
91 			lflag = 0;
92 			break;
93 
94 		case LEFT:
95 			if (!moveplayer(left, LEFT))
96 				return (-1);
97 			lflag = 0;
98 			break;
99 
100 		case RIGHT:
101 			if (!moveplayer(right, RIGHT))
102 				return (-1);
103 			lflag = 0;
104 			break;
105 
106 		case AHEAD:
107 			if (!moveplayer(ahead, AHEAD))
108 				return (-1);
109 			lflag = 0;
110 			break;
111 
112 		case BACK:
113 			if (!moveplayer(back, BACK))
114 				return (-1);
115 			lflag = 0;
116 			break;
117 
118 		case SHOOT:
119 			if (wordnumber < wordcount &&
120 			    wordvalue[wordnumber + 1] == EVERYTHING) {
121 				int things;
122 				things = 0;
123 				for (n = 0; n < NUMOFOBJECTS; n++)
124 					if (testbit(location[position].objects,
125 					    n) && objsht[n]) {
126 						things++;
127 						wordvalue[wordnumber + 1] = n;
128 						wordnumber = shoot();
129 					}
130 				if (!things)
131 					puts("Nothing to shoot at!");
132 				wordnumber++;
133 				wordnumber++;
134 			} else
135 				shoot();
136 			break;
137 
138 		case TAKE:
139 			if (wordnumber < wordcount &&
140 			    wordvalue[wordnumber + 1] == EVERYTHING) {
141 				int things;
142 				things = 0;
143 				for (n = 0; n < NUMOFOBJECTS; n++)
144 					if (testbit(location[position].objects,
145 					    n) && objsht[n]) {
146 						things++;
147 						wordvalue[wordnumber + 1] = n;
148 						/* Some objects (type NOUNS)
149 						 * have special treatment in
150 						 * take().  For these we
151 						 * must set the type to NOUNS.
152 						 * However for SWORD and BODY
153 						 * all it does is find which
154 						 * of many objects is meant,
155 						 * so we need do nothing here.
156 						 * BATHGOD must become
157 						 * NORMGOD as well.  NOUNS
158 						 * with no special case
159 						 * must be included here to
160 						 * get the right error.  DOOR
161 						 * cannot occur as an object
162 						 * so need not be included.  */
163 						switch(n) {
164 						case BATHGOD:
165 							wordvalue[wordnumber + 1] = NORMGOD;
166 							/* FALLTHROUGH */
167 						case NORMGOD:
168 						case AMULET:
169 						case MEDALION:
170 						case TALISMAN:
171 						case MAN:
172 						case TIMER:
173 						case NATIVE:
174 							wordtype[wordnumber + 1] = NOUNS;
175 							break;
176 						default:
177 							wordtype[wordnumber + 1] = OBJECT;
178 						}
179 						wordnumber = take(location[position].objects);
180 					}
181 				wordnumber++;
182 				wordnumber++;
183 				if (!things)
184 					puts("Nothing to take!");
185 			} else
186 				take(location[position].objects);
187 			break;
188 
189 		case DROP:
190 			if (wordnumber < wordcount &&
191 			    wordvalue[wordnumber + 1] == EVERYTHING) {
192 				int things;
193 				things = 0;
194 				for (n = 0; n < NUMOFOBJECTS; n++)
195 					if (testbit(inven, n)) {
196 						things++;
197 						wordvalue[wordnumber + 1] = n;
198 						wordnumber = drop("Dropped");
199 					}
200 				wordnumber++;
201 				wordnumber++;
202 				if (!things)
203 					puts("Nothing to drop!");
204 			} else
205 				drop("Dropped");
206 			break;
207 
208 		case KICK:
209 		case THROW:
210 			if (wordnumber < wordcount &&
211 			    wordvalue[wordnumber + 1] == EVERYTHING) {
212 				int things, wv;
213 				things = 0;
214 				wv = wordvalue[wordnumber];
215 				for (n = 0; n < NUMOFOBJECTS; n++)
216 					if (testbit(inven, n) ||
217 					    (testbit(location[position].objects, n) && objsht[n])) {
218 						things++;
219 						wordvalue[wordnumber + 1] = n;
220 						wordnumber = throw(wordvalue[wordnumber] == KICK ? "Kicked" : "Thrown");
221 					}
222 				wordnumber += 2;
223 				if (!things)
224 					printf("Nothing to %s!\n",
225 					    wv == KICK ? "kick" : "throw");
226 			} else
227 				throw(wordvalue[wordnumber] ==
228 				    KICK ? "Kicked" : "Thrown");
229 			break;
230 
231 		case TAKEOFF:
232 			if (wordnumber < wordcount &&
233 			    wordvalue[wordnumber + 1] == EVERYTHING) {
234 				int things;
235 				things = 0;
236 				for (n = 0; n < NUMOFOBJECTS; n++)
237 					if (testbit(wear, n)) {
238 						things++;
239 						wordvalue[wordnumber + 1] = n;
240 						wordnumber = takeoff();
241 					}
242 				wordnumber += 2;
243 				if (!things)
244 					puts("Nothing to take off!");
245 			} else
246 				takeoff();
247 			break;
248 
249 		case DRAW:
250 			if (wordnumber < wordcount &&
251 			    wordvalue[wordnumber + 1] == EVERYTHING) {
252 				int things;
253 				things = 0;
254 				for (n = 0; n < NUMOFOBJECTS; n++)
255 					if (testbit(wear, n)) {
256 						things++;
257 						wordvalue[wordnumber + 1] = n;
258 						wordnumber = draw();
259 					}
260 				wordnumber += 2;
261 				if (!things)
262 					puts("Nothing to draw!");
263 			} else
264 				draw();
265 			break;
266 
267 		case PUTON:
268 			if (wordnumber < wordcount &&
269 			    wordvalue[wordnumber + 1] == EVERYTHING) {
270 				int things;
271 				things = 0;
272 				for (n = 0; n < NUMOFOBJECTS; n++)
273 					if (testbit(location[position].objects,
274 					    n) && objsht[n]) {
275 						things++;
276 						wordvalue[wordnumber + 1] = n;
277 						wordnumber = puton();
278 					}
279 				wordnumber += 2;
280 				if (!things)
281 					puts("Nothing to put on!");
282 			} else
283 				puton();
284 			break;
285 
286 		case WEARIT:
287 			if (wordnumber < wordcount &&
288 			    wordvalue[wordnumber + 1] == EVERYTHING) {
289 				int things;
290 				things = 0;
291 				for (n = 0; n < NUMOFOBJECTS; n++)
292 					if (testbit(inven, n)) {
293 						things++;
294 						wordvalue[wordnumber + 1] = n;
295 						wordnumber = wearit();
296 					}
297 				wordnumber += 2;
298 				if (!things)
299 					puts("Nothing to wear!");
300 			} else
301 				wearit();
302 			break;
303 
304 		case EAT:
305 			if (wordnumber < wordcount &&
306 			    wordvalue[wordnumber + 1] == EVERYTHING) {
307 				int things;
308 				things = 0;
309 				for (n = 0; n < NUMOFOBJECTS; n++)
310 					if (testbit(inven, n)) {
311 						things++;
312 						wordvalue[wordnumber + 1] = n;
313 						wordnumber = eat();
314 					}
315 				wordnumber += 2;
316 				if (!things)
317 					puts("Nothing to eat!");
318 			} else
319 				eat();
320 			break;
321 
322 		case PUT:
323 			put();
324 			break;
325 
326 		case INVEN:
327 			if (ucard(inven)) {
328 				puts("You are holding:\n");
329 				for (n = 0; n < NUMOFOBJECTS; n++)
330 					if (testbit(inven, n))
331 						printf("\t%s\n", objsht[n]);
332 				if (WEIGHT == 0) {
333 					printf("\n= %d kilogram%s",
334 					    carrying,
335 					    (carrying == 1 ? "." : "s."));
336 					printf(" (can't lift any weight%s)\n",
337 					    (carrying ?
338 					    " or move with what you have" :
339 					    ""));
340 				} else
341 					printf("\n= %d kilogram%s (%d%%)\n",
342 					    carrying,
343 					    (carrying == 1 ? "." : "s."),
344 					    carrying * 100 / WEIGHT);
345 				if (CUMBER == 0) {
346 					printf("Your arms can't pick ");
347 					printf("anything up.\n");
348 				} else
349 					printf("Your arms are %d%% full.\n",
350 					    encumber * 100 / CUMBER);
351 			} else
352 				puts("You aren't carrying anything.");
353 
354 			if (ucard(wear)) {
355 				puts("\nYou are wearing:\n");
356 				for (n = 0; n < NUMOFOBJECTS; n++)
357 					if (testbit(wear, n))
358 						printf("\t%s\n", objsht[n]);
359 			} else
360 				puts("\nYou are stark naked.");
361 			if (card(injuries, NUMOFINJURIES)) {
362 				puts("\nYou have suffered:\n");
363 				for (n = 0; n < NUMOFINJURIES; n++)
364 					if (injuries[n])
365 						printf("\t%s\n", ouch[n]);
366 				printf("\nYou can still carry up to ");
367 				printf("%d kilogram%s\n", WEIGHT,
368 				    (WEIGHT == 1 ? "." : "s."));
369 			} else
370 				puts("\nYou are in perfect health.");
371 			wordnumber++;
372 			break;
373 
374 		case USE:
375 			lflag = use();
376 			break;
377 
378 		case OPEN:
379 			if (wordnumber < wordcount &&
380 			    wordvalue[wordnumber + 1] == EVERYTHING) {
381 				int things;
382 				things = 0;
383 				for (n = 0; n < NUMOFOBJECTS; n++)
384 					if (testbit(inven, n)) {
385 						things++;
386 						wordvalue[wordnumber + 1] = n;
387 						dooropen();
388 					}
389 				wordnumber += 2;
390 				if (!things)
391 					puts("Nothing to open!");
392 			} else
393 				dooropen();
394 			break;
395 
396 		case LOOK:
397 			if (!notes[CANTSEE] || testbit(inven, LAMPON) ||
398 			    testbit(location[position].objects, LAMPON)
399 			    || matchlight) {
400 				beenthere[position] = 2;
401 				writedes();
402 				printobjs();
403 				if (matchlight) {
404 					puts("\nYour match splutters out.");
405 					matchlight = 0;
406 				}
407 			} else
408 				puts("I can't see anything.");
409 			return (-1);
410 			break;
411 
412 		case SU:
413 			if (wiz || tempwiz) {
414 				printf("\nRoom (was %d) = ", position);
415 				fgets(buffer, 10, stdin);
416 				if (*buffer != '\n')
417 					sscanf(buffer, "%d", &position);
418 				printf("Time (was %d) = ", ourtime);
419 				fgets(buffer, 10, stdin);
420 				if (*buffer != '\n')
421 					sscanf(buffer, "%d", &ourtime);
422 				printf("Fuel (was %d) = ", fuel);
423 				fgets(buffer, 10, stdin);
424 				if (*buffer != '\n')
425 					sscanf(buffer, "%d", &fuel);
426 				printf("Torps (was %d) = ", torps);
427 				fgets(buffer, 10, stdin);
428 				if (*buffer != '\n')
429 					sscanf(buffer, "%d", &torps);
430 				printf("CUMBER (was %d) = ", CUMBER);
431 				fgets(buffer, 10, stdin);
432 				if (*buffer != '\n')
433 					sscanf(buffer, "%d", &CUMBER);
434 				printf("WEIGHT (was %d) = ", WEIGHT);
435 				fgets(buffer, 10, stdin);
436 				if (*buffer != '\n')
437 					sscanf(buffer, "%d", &WEIGHT);
438 				printf("Clock (was %d) = ", ourclock);
439 				fgets(buffer, 10, stdin);
440 				if (*buffer != '\n')
441 					sscanf(buffer, "%d", &ourclock);
442 				printf("Wizard (was %d, %d) = ", wiz, tempwiz);
443 				fgets(buffer, 10, stdin);
444 				if (*buffer != '\n') {
445 					sscanf(buffer, "%d", &junk);
446 					if (!junk)
447 						tempwiz = wiz = 0;
448 				}
449 				printf("\nDONE.\n");
450 				return (0);
451 			} else
452 				puts("You aren't a wizard.");
453 			break;
454 
455 		case SCORE:
456 			printf("\tPLEASURE\tPOWER\t\tEGO\n");
457 			printf("\t%3d\t\t%3d\t\t%3d\n\n", pleasure, power, ego);
458 			printf("This gives you the rating of ");
459 			printf("%s in %d turns.\n", rate(), ourtime);
460 			printf("You have visited %d out of %d rooms ",
461 			    card(beenthere, NUMOFROOMS), NUMOFROOMS);
462 			printf("this run (%d%%).\n",
463 			    card(beenthere, NUMOFROOMS) * 100 / NUMOFROOMS);
464 			break;
465 
466 		case KNIFE:
467 		case KILL:
468 			murder();
469 			break;
470 
471 		case UNDRESS:
472 		case RAVAGE:
473 			ravage();
474 			break;
475 
476 		case SAVE:
477 			printf("\nSave file name (default %s): ",
478 			       DEFAULT_SAVE_FILE);
479 			filename = fgetln(stdin, &filename_len);
480 			if (filename_len == 0
481 			    || (filename_len == 1 && filename[0] == '\n'))
482 				rfilename = save_file_name(DEFAULT_SAVE_FILE,
483 				    strlen(DEFAULT_SAVE_FILE));
484 			else {
485 				if (filename[filename_len - 1] == '\n')
486 					filename_len--;
487 				rfilename = save_file_name(filename,
488 							   filename_len);
489 			}
490 			save(rfilename);
491 			free(rfilename);
492 			break;
493 
494 		case VERBOSE:
495 			verbose = 1;
496 			printf("[Maximum verbosity]\n");
497 			break;
498 
499 		case BRIEF:
500 			verbose = 0;
501 			printf("[Standard verbosity]\n");
502 			break;
503 
504 		case FOLLOW:
505 			lflag = follow();
506 			break;
507 
508 		case GIVE:
509 			give();
510 			break;
511 
512 		case KISS:
513 			kiss();
514 			break;
515 
516 		case LOVE:
517 			love();
518 			break;
519 
520 		case RIDE:
521 			lflag = ride();
522 			break;
523 
524 		case DRIVE:
525 			lflag = drive();
526 			break;
527 
528 		case LIGHT:
529 			light();
530 			break;
531 
532 		case LAUNCH:
533 			if (!launch())
534 				return (-1);
535 			else
536 				lflag = 0;
537 			break;
538 
539 		case LANDIT:
540 			if (!land())
541 				return (-1);
542 			else
543 				lflag = 0;
544 			break;
545 
546 		case TIME:
547 			chime();
548 			break;
549 
550 		case SLEEP:
551 			zzz();
552 			break;
553 
554 		case DIG:
555 			dig();
556 			break;
557 
558 		case JUMP:
559 			lflag = jump();
560 			break;
561 
562 		case BURY:
563 			bury();
564 			break;
565 
566 		case SWIM:
567 			puts("Surf's up!");
568 			break;
569 
570 		case DRINK:
571 			drink();
572 			break;
573 
574 		case QUIT:
575 			die();
576 
577 		default:
578 			puts("How's that?");
579 			return (-1);
580 			break;
581 
582 		}
583 		if (wordnumber < wordcount && *words[wordnumber++] == ',')
584 			continue;
585 		else
586 			return (lflag);
587 	}
588 	return (lflag);
589 }
590