]> git.cameronkatri.com Git - bsdgames-darwin.git/blob - adventure/io.c
Remove unused function and unnecessary prototypes, as per PR 6050 by
[bsdgames-darwin.git] / adventure / io.c
1 /* $NetBSD: io.c,v 1.7 1998/08/29 22:40:07 hubertf 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. All advertising materials mentioning features or use of this software
21 * must display the following acknowledgement:
22 * This product includes software developed by the University of
23 * California, Berkeley and its contributors.
24 * 4. Neither the name of the University nor the names of its contributors
25 * may be used to endorse or promote products derived from this software
26 * without specific prior written permission.
27 *
28 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
29 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
32 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
36 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
37 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38 * SUCH DAMAGE.
39 */
40
41 #include <sys/cdefs.h>
42 #ifndef lint
43 #if 0
44 static char sccsid[] = "@(#)io.c 8.1 (Berkeley) 5/31/93";
45 #else
46 __RCSID("$NetBSD: io.c,v 1.7 1998/08/29 22:40:07 hubertf Exp $");
47 #endif
48 #endif /* not lint */
49
50 /* Re-coding of advent in C: file i/o and user i/o */
51
52 #include <stdio.h>
53 #include <string.h>
54 #include <stdlib.h>
55 #include "hdr.h"
56 #include "extern.h"
57
58
59 void
60 getin(wrd1, wrd2) /* get command from user */
61 char **wrd1, **wrd2; /* no prompt, usually */
62 {
63 char *s;
64 static char wd1buf[MAXSTR], wd2buf[MAXSTR];
65 int first, numch;
66
67 *wrd1 = wd1buf; /* return ptr to internal str */
68 *wrd2 = wd2buf;
69 wd2buf[0] = 0; /* in case it isn't set here */
70 for (s = wd1buf, first = 1, numch = 0;;) {
71 if ((*s = getchar()) >= 'A' && *s <= 'Z')
72 *s = *s - ('A' - 'a');
73 /* convert to upper case */
74 switch (*s) { /* start reading from user */
75 case '\n':
76 *s = 0;
77 return;
78 case ' ':
79 if (s == wd1buf || s == wd2buf) /* initial blank */
80 continue;
81 *s = 0;
82 if (first) { /* finished 1st wd; start 2nd */
83 first = numch = 0;
84 s = wd2buf;
85 break;
86 } else { /* finished 2nd word */
87 FLUSHLINE;
88 *s = 0;
89 return;
90 }
91 default:
92 if (++numch >= MAXSTR) { /* string too long */
93 printf("Give me a break!!\n");
94 wd1buf[0] = wd2buf[0] = 0;
95 FLUSHLINE;
96 return;
97 }
98 s++;
99 }
100 }
101 }
102
103 int
104 yes(x, y, z) /* confirm with rspeak */
105 int x, y, z;
106 {
107 int result = TRUE; /* pacify gcc */
108 char ch;
109 for (;;) {
110 rspeak(x); /* tell him what we want */
111 if ((ch = getchar()) == 'y')
112 result = TRUE;
113 else
114 if (ch == 'n')
115 result = FALSE;
116 FLUSHLINE;
117 if (ch == 'y' || ch == 'n')
118 break;
119 printf("Please answer the question.\n");
120 }
121 if (result == TRUE)
122 rspeak(y);
123 if (result == FALSE)
124 rspeak(z);
125 return (result);
126 }
127
128 int
129 yesm(x, y, z) /* confirm with mspeak */
130 int x, y, z;
131 {
132 int result = TRUE; /* pacify gcc */
133 char ch;
134 for (;;) {
135 mspeak(x); /* tell him what we want */
136 if ((ch = getchar()) == 'y')
137 result = TRUE;
138 else
139 if (ch == 'n')
140 result = FALSE;
141 FLUSHLINE;
142 if (ch == 'y' || ch == 'n')
143 break;
144 printf("Please answer the question.\n");
145 }
146 if (result == TRUE)
147 mspeak(y);
148 if (result == FALSE)
149 mspeak(z);
150 return (result);
151 }
152 /* FILE *inbuf,*outbuf; */
153
154 char *inptr; /* Pointer into virtual disk */
155
156 int outsw = 0; /* putting stuff to data file? */
157
158 char iotape[] = "Ax3F'\003tt$8h\315qer*h\017nGKrX\207:!l";
159 char *tape = iotape; /* pointer to encryption tape */
160
161 int
162 next()
163 { /* next virtual char, bump adr */
164 int ch;
165
166 ch = (*inptr ^ random()) & 0xFF; /* Decrypt input data */
167 if (outsw) { /* putting data in tmp file */
168 if (*tape == 0)
169 tape = iotape; /* rewind encryption tape */
170 *inptr = ch ^ *tape++; /* re-encrypt and replace value */
171 }
172 inptr++;
173 return (ch);
174 }
175
176 char breakch; /* tell which char ended rnum */
177
178 void
179 rdata()
180 { /* "read" data from virtual file */
181 int sect;
182 char ch;
183
184 inptr = data_file; /* Pointer to virtual data file */
185 srandom(SEED); /* which is lightly encrypted. */
186
187 clsses = 1;
188 for (;;) { /* read data sections */
189 sect = next() - '0'; /* 1st digit of section number */
190 #ifdef VERBOSE
191 printf("Section %c", sect + '0');
192 #endif
193 if ((ch = next()) != LF) { /* is there a second digit? */
194 FLUSHLF;
195 #ifdef VERBOSE
196 putchar(ch);
197 #endif
198 sect = 10 * sect + ch - '0';
199 }
200 #ifdef VERBOSE
201 putchar('\n');
202 #endif
203 switch (sect) {
204 case 0: /* finished reading database */
205 return;
206 case 1: /* long form descriptions */
207 rdesc(1);
208 break;
209 case 2: /* short form descriptions */
210 rdesc(2);
211 break;
212 case 3: /* travel table */
213 rtrav();
214 break;
215 case 4: /* vocabulary */
216 rvoc();
217 break;
218 case 5: /* object descriptions */
219 rdesc(5);
220 break;
221 case 6: /* arbitrary messages */
222 rdesc(6);
223 break;
224 case 7: /* object locations */
225 rlocs();
226 break;
227 case 8: /* action defaults */
228 rdflt();
229 break;
230 case 9: /* liquid assets */
231 rliq();
232 break;
233 case 10: /* class messages */
234 rdesc(10);
235 break;
236 case 11: /* hints */
237 rhints();
238 break;
239 case 12: /* magic messages */
240 rdesc(12);
241 break;
242 default:
243 printf("Invalid data section number: %d\n", sect);
244 for (;;)
245 putchar(next());
246 }
247 if (breakch != LF) /* routines return after "-1" */
248 FLUSHLF;
249 }
250 }
251
252 char nbf[12];
253
254
255 int
256 rnum()
257 { /* read initial location num */
258 char *s;
259 tape = iotape; /* restart encryption tape */
260 for (s = nbf, *s = 0;; s++)
261 if ((*s = next()) == TAB || *s == '\n' || *s == LF)
262 break;
263 breakch = *s; /* save char for rtrav() */
264 *s = 0; /* got the number as ascii */
265 if (nbf[0] == '-')
266 return (-1); /* end of data */
267 return (atoi(nbf)); /* convert it to integer */
268 }
269
270 char *seekhere;
271
272 void
273 rdesc(sect) /* read description-format msgs */
274 int sect;
275 {
276 int locc;
277 char *seekstart, *maystart;
278
279 seekhere = inptr; /* Where are we in virtual file? */
280 outsw = 1; /* these msgs go into tmp file */
281 for (oldloc = -1, seekstart = seekhere;;) {
282 maystart = inptr; /* maybe starting new entry */
283 if ((locc = rnum()) != oldloc && oldloc >= 0 /* finished msg */
284 && !(sect == 5 && (locc == 0 || locc >= 100))) { /* unless sect 5 */
285 switch (sect) { /* now put it into right table */
286 case 1:/* long descriptions */
287 ltext[oldloc].seekadr = seekhere;
288 ltext[oldloc].txtlen = maystart - seekstart;
289 break;
290 case 2:/* short descriptions */
291 stext[oldloc].seekadr = seekhere;
292 stext[oldloc].txtlen = maystart - seekstart;
293 break;
294 case 5:/* object descriptions */
295 ptext[oldloc].seekadr = seekhere;
296 ptext[oldloc].txtlen = maystart - seekstart;
297 break;
298 case 6:/* random messages */
299 if (oldloc > RTXSIZ) {
300 printf("Too many random msgs\n");
301 exit(0);
302 }
303 rtext[oldloc].seekadr = seekhere;
304 rtext[oldloc].txtlen = maystart - seekstart;
305 break;
306 case 10: /* class messages */
307 ctext[clsses].seekadr = seekhere;
308 ctext[clsses].txtlen = maystart - seekstart;
309 cval[clsses++] = oldloc;
310 break;
311 case 12: /* magic messages */
312 if (oldloc > MAGSIZ) {
313 printf("Too many magic msgs\n");
314 exit(0);
315 }
316 mtext[oldloc].seekadr = seekhere;
317 mtext[oldloc].txtlen = maystart - seekstart;
318 break;
319 default:
320 printf("rdesc called with bad section\n");
321 exit(0);
322 }
323 seekhere += maystart - seekstart;
324 }
325 if (locc < 0) {
326 outsw = 0; /* turn off output */
327 seekhere += 3; /* -1<delimiter> */
328 return;
329 }
330 if (sect != 5 || (locc > 0 && locc < 100)) {
331 if (oldloc != locc) /* starting a new message */
332 seekstart = maystart;
333 oldloc = locc;
334 }
335 FLUSHLF; /* scan the line */
336 }
337 }
338
339 void
340 rtrav()
341 { /* read travel table */
342 int locc;
343 struct travlist *t = NULL;
344 char *s;
345 char buf[12];
346 int len, m, n, entries = 0;
347
348 for (oldloc = -1;;) { /* get another line */
349 if ((locc = rnum()) != oldloc && oldloc >= 0) { /* end of entry */
350 t->next = 0; /* terminate the old entry */
351 /* printf("%d:%d entries\n",oldloc,entries); */
352 /* twrite(oldloc); */
353 }
354 if (locc == -1)
355 return;
356 if (locc != oldloc) { /* getting a new entry */
357 t = travel[locc] = (struct travlist *) malloc(sizeof(struct travlist));
358 /* printf("New travel list for %d\n",locc); */
359 entries = 0;
360 oldloc = locc;
361 }
362 for (s = buf;; s++) /* get the newloc number /ASCII */
363 if ((*s = next()) == TAB || *s == LF)
364 break;
365 *s = 0;
366 len = length(buf) - 1; /* quad long number handling */
367 /* printf("Newloc: %s (%d chars)\n",buf,len); */
368 if (len < 4) { /* no "m" conditions */
369 m = 0;
370 n = atoi(buf); /* newloc mod 1000 = newloc */
371 } else { /* a long integer */
372 n = atoi(buf + len - 3);
373 buf[len - 3] = 0; /* terminate newloc/1000 */
374 m = atoi(buf);
375 }
376 while (breakch != LF) { /* only do one line at a time */
377 if (entries++)
378 t = t->next = (struct travlist *) malloc(sizeof(struct travlist));
379 t->tverb = rnum(); /* get verb from the file */
380 t->tloc = n; /* table entry mod 1000 */
381 t->conditions = m; /* table entry / 1000 */
382 /* printf("entry %d for %d\n",entries,locc); */
383 }
384 }
385 }
386 #ifdef DEBUG
387
388 void
389 twrite(loq) /* travel options from this loc */
390 int loq;
391 {
392 struct travlist *t;
393 printf("If");
394 speak(&ltext[loq]);
395 printf("then\n");
396 for (t = travel[loq]; t != 0; t = t->next) {
397 printf("verb %d takes you to ", t->tverb);
398 if (t->tloc <= 300)
399 speak(&ltext[t->tloc]);
400 else
401 if (t->tloc <= 500)
402 printf("special code %d\n", t->tloc - 300);
403 else
404 rspeak(t->tloc - 500);
405 printf("under conditions %d\n", t->conditions);
406 }
407 }
408 #endif /* DEBUG */
409
410 void
411 rvoc()
412 {
413 char *s; /* read the vocabulary */
414 int index;
415 char buf[6];
416 for (;;) {
417 index = rnum();
418 if (index < 0)
419 break;
420 for (s = buf, *s = 0;; s++) /* get the word */
421 if ((*s = next()) == TAB || *s == '\n' || *s == LF
422 || *s == ' ')
423 break;
424 /* terminate word with newline, LF, tab, blank */
425 if (*s != '\n' && *s != LF)
426 FLUSHLF;/* can be comments */
427 *s = 0;
428 /* printf("\"%s\"=%d\n",buf,index); */
429 vocab(buf, -2, index);
430 }
431 /* prht(); */
432 }
433
434
435 void
436 rlocs()
437 { /* initial object locations */
438 for (;;) {
439 if ((obj = rnum()) < 0)
440 break;
441 plac[obj] = rnum(); /* initial loc for this obj */
442 if (breakch == TAB) /* there's another entry */
443 fixd[obj] = rnum();
444 else
445 fixd[obj] = 0;
446 }
447 }
448
449 void
450 rdflt()
451 { /* default verb messages */
452 for (;;) {
453 if ((verb = rnum()) < 0)
454 break;
455 actspk[verb] = rnum();
456 }
457 }
458
459 void
460 rliq()
461 { /* liquid assets &c: cond bits */
462 int bitnum;
463 for (;;) { /* read new bit list */
464 if ((bitnum = rnum()) < 0)
465 break;
466 for (;;) { /* read locs for bits */
467 cond[rnum()] |= setbit[bitnum];
468 if (breakch == LF)
469 break;
470 }
471 }
472 }
473
474 void
475 rhints()
476 {
477 int hintnum, i;
478 hntmax = 0;
479 for (;;) {
480 if ((hintnum = rnum()) < 0)
481 break;
482 for (i = 1; i < 5; i++)
483 hints[hintnum][i] = rnum();
484 if (hintnum > hntmax)
485 hntmax = hintnum;
486 }
487 }
488
489
490 void
491 rspeak(msg)
492 int msg;
493 {
494 if (msg != 0)
495 speak(&rtext[msg]);
496 }
497
498
499 void
500 mspeak(msg)
501 int msg;
502 {
503 if (msg != 0)
504 speak(&mtext[msg]);
505 }
506
507
508 void
509 speak(msg) /* read, decrypt, and print a message (not
510 * ptext) */
511 struct text *msg; /* msg is a pointer to seek address and length
512 * of mess */
513 {
514 char *s, nonfirst;
515
516 s = msg->seekadr;
517 nonfirst = 0;
518 while (s - msg->seekadr < msg->txtlen) { /* read a line at a time */
519 tape = iotape; /* restart decryption tape */
520 while ((*s++ ^ *tape++) != TAB); /* read past loc num */
521 /* assume tape is longer than location number */
522 /* plus the lookahead put together */
523 if ((*s ^ *tape) == '>' &&
524 (*(s + 1) ^ *(tape + 1)) == '$' &&
525 (*(s + 2) ^ *(tape + 2)) == '<')
526 break;
527 if (blklin && !nonfirst++)
528 putchar('\n');
529 do {
530 if (*tape == 0)
531 tape = iotape; /* rewind decryp tape */
532 putchar(*s ^ *tape);
533 } while ((*s++ ^ *tape++) != LF); /* better end with LF */
534 }
535 }
536
537
538 void
539 pspeak(m, skip) /* read, decrypt an print a ptext message */
540 int m; /* msg is the number of all the p msgs for
541 * this place */
542 int skip; /* assumes object 1 doesn't have prop 1, obj 2
543 * no prop 2 &c */
544 {
545 char *s, nonfirst;
546 char *numst, save;
547 struct text *msg;
548 char *tbuf;
549
550 msg = &ptext[m];
551 if ((tbuf = (char *) malloc(msg->txtlen + 1)) == 0)
552 bug(108);
553 memcpy(tbuf, msg->seekadr, msg->txtlen + 1); /* Room to null */
554 s = tbuf;
555
556 nonfirst = 0;
557 while (s - tbuf < msg->txtlen) { /* read line at a time */
558 tape = iotape; /* restart decryption tape */
559 for (numst = s; (*s ^= *tape++) != TAB; s++); /* get number */
560
561 save = *s; /* Temporarily trash the string (cringe) */
562 *s++ = 0; /* decrypting number within the string */
563
564 if (atoi(numst) != 100 * skip && skip >= 0) {
565 while ((*s++ ^ *tape++) != LF) /* flush the line */
566 if (*tape == 0)
567 tape = iotape;
568 continue;
569 }
570 if ((*s ^ *tape) == '>' && (*(s + 1) ^ *(tape + 1)) == '$' &&
571 (*(s + 2) ^ *(tape + 2)) == '<')
572 break;
573 if (blklin && !nonfirst++)
574 putchar('\n');
575 do {
576 if (*tape == 0)
577 tape = iotape;
578 putchar(*s ^ *tape);
579 } while ((*s++ ^ *tape++) != LF); /* better end with LF */
580 if (skip < 0)
581 break;
582 }
583 free(tbuf);
584 }