]>
git.cameronkatri.com Git - bsdgames-darwin.git/blob - adventure/io.c
86f0c8508203fb5d609c6b4d893f0dcc29e17cf4
1 /* $NetBSD: io.c,v 1.3 1995/04/24 12:21:37 cgd Exp $ */
4 * Copyright (c) 1991, 1993
5 * The Regents of the University of California. All rights reserved.
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.
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
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.
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
43 static char sccsid
[] = "@(#)io.c 8.1 (Berkeley) 5/31/93";
45 static char rcsid
[] = "$NetBSD: io.c,v 1.3 1995/04/24 12:21:37 cgd Exp $";
49 /* Re-coding of advent in C: file i/o and user i/o */
56 getin(wrd1
,wrd2
) /* get command from user */
57 char **wrd1
,**wrd2
; /* no prompt, usually */
59 static char wd1buf
[MAXSTR
],wd2buf
[MAXSTR
];
62 *wrd1
=wd1buf
; /* return ptr to internal string*/
64 wd2buf
[0]=0; /* in case it isn't set here */
65 for (s
=wd1buf
, first
=1, numch
=0;;)
66 { if ((*s
=getchar())>='A' && *s
<='Z') *s
= *s
- ('A' -'a');
67 /* convert to upper case */
68 switch(*s
) /* start reading from user */
73 if (s
==wd1buf
||s
==wd2buf
) /* initial blank */
76 if (first
) /* finished 1st wd; start 2nd */
81 else /* finished 2nd word */
87 if (++numch
>=MAXSTR
) /* string too long */
88 { printf("Give me a break!!\n");
89 wd1buf
[0]=wd2buf
[0]=0;
99 confirm(mesg
) /* confirm irreversible action */
101 { register int result
;
102 printf("%s",mesg
); /* tell him what he did */
103 if (getchar()=='y') /* was his first letter a 'y'? */
110 yes(x
,y
,z
) /* confirm with rspeak */
112 { register int result
;
115 { rspeak(x
); /* tell him what we want*/
116 if ((ch
=getchar())=='y')
118 else if (ch
=='n') result
=FALSE
;
120 if (ch
=='y'|| ch
=='n') break;
121 printf("Please answer the question.\n");
123 if (result
==TRUE
) rspeak(y
);
124 if (result
==FALSE
) rspeak(z
);
128 yesm(x
,y
,z
) /* confirm with mspeak */
130 { register int result
;
133 { mspeak(x
); /* tell him what we want*/
134 if ((ch
=getchar())=='y')
136 else if (ch
=='n') result
=FALSE
;
138 if (ch
=='y'|| ch
=='n') break;
139 printf("Please answer the question.\n");
141 if (result
==TRUE
) mspeak(y
);
142 if (result
==FALSE
) mspeak(z
);
146 /* FILE *inbuf,*outbuf; */
148 char *inptr
; /* Pointer into virtual disk */
150 int outsw
= 0; /* putting stuff to data file? */
152 char iotape
[] = "Ax3F'\003tt$8h\315qer*h\017nGKrX\207:!l";
153 char *tape
= iotape
; /* pointer to encryption tape */
155 next() /* next virtual char, bump adr */
159 ch
=(*inptr
^ random()) & 0xFF; /* Decrypt input data */
160 if (outsw
) /* putting data in tmp file */
161 { if (*tape
==0) tape
=iotape
; /* rewind encryption tape */
162 *inptr
= ch
^ *tape
++; /* re-encrypt and replace value */
168 char breakch
; /* tell which char ended rnum */
170 rdata() /* "read" data from virtual file*/
174 inptr
= data_file
; /* Pointer to virtual data file */
175 srandom(SEED
); /* which is lightly encrypted. */
178 for (;;) /* read data sections */
179 { sect
=next()-'0'; /* 1st digit of section number */
181 printf("Section %c",sect
+'0');
183 if ((ch
=next())!=LF
) /* is there a second digit? */
195 { case 0: /* finished reading database */
197 case 1: /* long form descriptions */
200 case 2: /* short form descriptions */
203 case 3: /* travel table */
205 case 4: /* vocabulary */
208 case 5: /* object descriptions */
211 case 6: /* arbitrary messages */
214 case 7: /* object locations */
216 case 8: /* action defaults */
218 case 9: /* liquid assets */
220 case 10: /* class messages */
225 case 12: /* magic messages */
229 printf("Invalid data section number: %d\n",sect
);
230 for (;;) putchar(next());
232 if (breakch
!=LF
) /* routines return after "-1" */
240 rnum() /* read initial location num */
242 tape
= iotape
; /* restart encryption tape */
243 for (s
=nbf
,*s
=0;; s
++)
244 if ((*s
=next())==TAB
|| *s
=='\n' || *s
==LF
)
246 breakch
= *s
; /* save char for rtrav() */
247 *s
=0; /* got the number as ascii */
248 if (nbf
[0]=='-') return(-1); /* end of data */
249 return(atoi(nbf
)); /* convert it to integer */
254 rdesc(sect
) /* read description-format msgs */
256 { register char *s
,*t
;
258 char *seekstart
, *maystart
, *adrstart
;
261 seekhere
= inptr
; /* Where are we in virtual file?*/
262 outsw
=1; /* these msgs go into tmp file */
263 for (oldloc
= -1, seekstart
=seekhere
;;)
264 { maystart
=inptr
; /* maybe starting new entry */
265 if ((locc
=rnum())!=oldloc
&& oldloc
>=0 /* finished msg */
266 && ! (sect
==5 && (locc
==0 || locc
>=100)))/* unless sect 5*/
267 { switch(sect
) /* now put it into right table */
268 { case 1: /* long descriptions */
269 ltext
[oldloc
].seekadr
=seekhere
;
270 ltext
[oldloc
].txtlen
=maystart
-seekstart
;
272 case 2: /* short descriptions */
273 stext
[oldloc
].seekadr
=seekhere
;
274 stext
[oldloc
].txtlen
=maystart
-seekstart
;
276 case 5: /* object descriptions */
277 ptext
[oldloc
].seekadr
=seekhere
;
278 ptext
[oldloc
].txtlen
=maystart
-seekstart
;
280 case 6: /* random messages */
282 { printf("Too many random msgs\n");
285 rtext
[oldloc
].seekadr
=seekhere
;
286 rtext
[oldloc
].txtlen
=maystart
-seekstart
;
288 case 10: /* class messages */
289 ctext
[clsses
].seekadr
=seekhere
;
290 ctext
[clsses
].txtlen
=maystart
-seekstart
;
291 cval
[clsses
++]=oldloc
;
293 case 12: /* magic messages */
295 { printf("Too many magic msgs\n");
298 mtext
[oldloc
].seekadr
=seekhere
;
299 mtext
[oldloc
].txtlen
=maystart
-seekstart
;
302 printf("rdesc called with bad section\n");
305 seekhere
+= maystart
-seekstart
;
308 { outsw
=0; /* turn off output */
309 seekhere
+= 3; /* -1<delimiter> */
312 if (sect
!=5 || (locc
>0 && locc
<100))
313 { if (oldloc
!=locc
)/* starting a new message */
317 FLUSHLF
; /* scan the line */
322 rtrav() /* read travel table */
324 register struct travlist
*t
;
328 for (oldloc
= -1;;) /* get another line */
329 { if ((locc
=rnum())!=oldloc
&& oldloc
>=0) /* end of entry */
331 t
->next
= 0; /* terminate the old entry */
332 /* printf("%d:%d entries\n",oldloc,entries); */
333 /* twrite(oldloc); */
335 if (locc
== -1) return;
336 if (locc
!=oldloc
) /* getting a new entry */
337 { t
=travel
[locc
]=(struct travlist
*) malloc(sizeof (struct travlist
));
338 /* printf("New travel list for %d\n",locc); */
342 for (s
=buf
;; *s
++) /* get the newloc number /ASCII */
343 if ((*s
=next())==TAB
|| *s
==LF
) break;
345 len
=length(buf
)-1; /* quad long number handling */
346 /* printf("Newloc: %s (%d chars)\n",buf,len); */
347 if (len
<4) /* no "m" conditions */
349 n
=atoi(buf
); /* newloc mod 1000 = newloc */
351 else /* a long integer */
353 buf
[len
-3]=0; /* terminate newloc/1000 */
356 while (breakch
!=LF
) /* only do one line at a time */
357 { if (entries
++) t
=t
->next
=(struct travlist
*) malloc(sizeof (struct travlist
));
358 t
->tverb
=rnum();/* get verb from the file */
359 t
->tloc
=n
; /* table entry mod 1000 */
360 t
->conditions
=m
;/* table entry / 1000 */
361 /* printf("entry %d for %d\n",entries,locc); */
368 twrite(loq
) /* travel options from this loc */
370 { register struct travlist
*t
;
374 for (t
=travel
[loq
]; t
!=0; t
=t
->next
)
375 { printf("verb %d takes you to ",t
->tverb
);
377 speak(<ext
[t
->tloc
]);
378 else if (t
->tloc
<=500)
379 printf("special code %d\n",t
->tloc
-300);
382 printf("under conditions %d\n",t
->conditions
);
389 { register char *s
; /* read the vocabulary */
395 for (s
=buf
,*s
=0;; s
++) /* get the word */
396 if ((*s
=next())==TAB
|| *s
=='\n' || *s
==LF
398 /* terminate word with newline, LF, tab, blank */
399 if (*s
!='\n' && *s
!=LF
) FLUSHLF
; /* can be comments */
401 /* printf("\"%s\"=%d\n",buf,index);*/
408 rlocs() /* initial object locations */
410 { if ((obj
=rnum())<0) break;
411 plac
[obj
]=rnum(); /* initial loc for this obj */
412 if (breakch
==TAB
) /* there's another entry */
418 rdflt() /* default verb messages */
420 { if ((verb
=rnum())<0) break;
425 rliq() /* liquid assets &c: cond bits */
426 { register int bitnum
;
427 for (;;) /* read new bit list */
428 { if ((bitnum
=rnum())<0) break;
429 for (;;) /* read locs for bits */
430 { cond
[rnum()] |= setbit
[bitnum
];
431 if (breakch
==LF
) break;
437 { register int hintnum
,i
;
440 { if ((hintnum
=rnum())<0) break;
442 hints
[hintnum
][i
]=rnum();
443 if (hintnum
>hntmax
) hntmax
=hintnum
;
450 { if (msg
!=0) speak(&rtext
[msg
]);
456 { if (msg
!=0) speak(&mtext
[msg
]);
460 speak(msg
) /* read, decrypt, and print a message (not ptext) */
461 struct text
*msg
;/* msg is a pointer to seek address and length of mess */
463 register char *s
, nonfirst
;
467 while (s
- msg
->seekadr
< msg
->txtlen
) /* read a line at a time */
468 { tape
=iotape
; /* restart decryption tape */
469 while ((*s
++ ^ *tape
++) != TAB
); /* read past loc num */
470 /* assume tape is longer than location number */
471 /* plus the lookahead put together */
472 if ((*s
^ *tape
) == '>' &&
473 (*(s
+1) ^ *(tape
+1)) == '$' &&
474 (*(s
+2) ^ *(tape
+2)) == '<') break;
475 if (blklin
&& !nonfirst
++) putchar('\n');
477 { if (*tape
== 0) tape
= iotape
;/* rewind decryp tape */
479 } while ((*s
++ ^ *tape
++) != LF
); /* better end with LF */
484 pspeak(m
,skip
) /* read, decrypt an print a ptext message */
485 int m
; /* msg is the number of all the p msgs for this place */
486 int skip
; /* assumes object 1 doesn't have prop 1, obj 2 no prop 2 &c*/
488 register char *s
,nonfirst
;
494 if ((tbuf
=(char *) malloc(msg
->txtlen
+ 1)) == 0) bug(108);
495 memcpy(tbuf
, msg
->seekadr
, msg
->txtlen
+ 1); /* Room to null */
499 while (s
- tbuf
< msg
->txtlen
) /* read line at a time */
500 { tape
=iotape
; /* restart decryption tape */
501 for (numst
=s
; (*s
^= *tape
++)!=TAB
; s
++); /* get number */
503 save
= *s
; /* Temporarily trash the string (cringe) */
504 *s
++ = 0; /* decrypting number within the string */
506 if (atoi(numst
) != 100 * skip
&& skip
>= 0)
507 { while ((*s
++^*tape
++)!=LF
) /* flush the line */
508 if (*tape
==0) tape
=iotape
;
511 if ((*s
^*tape
)=='>' && (*(s
+1)^*(tape
+1))=='$' &&
512 (*(s
+2)^*(tape
+2))=='<') break;
513 if (blklin
&& ! nonfirst
++) putchar('\n');
515 { if (*tape
==0) tape
=iotape
;
517 } while ((*s
++^*tape
++)!=LF
); /* better end with LF */