|
|
1.1 root 1: #
2: /* Re-coding of advent in C: file i/o and user i/o */
3:
4: static char sccsid[] = " io.c 4.1 82/05/11 ";
5:
6: #include "hdr.h"
7: #include <stdio.h>
8:
9:
10: getin(wrd1,wrd2) /* get command from user */
11: char **wrd1,**wrd2; /* no prompt, usually */
12: { register char *s;
13: static char wd1buf[MAXSTR],wd2buf[MAXSTR];
14: int first, numch;
15:
16: *wrd1=wd1buf; /* return ptr to internal string*/
17: *wrd2=wd2buf;
18: wd2buf[0]=0; /* in case it isn't set here */
19: for (s=wd1buf, first=1, numch=0;;)
20: { if ((*s=getchar())>='A' && *s <='Z') *s = *s - ('A' -'a');
21: /* convert to upper case */
22: switch(*s) /* start reading from user */
23: { case '\n':
24: *s=0;
25: return;
26: case ' ':
27: if (s==wd1buf||s==wd2buf) /* initial blank */
28: continue;
29: *s=0;
30: if (first) /* finished 1st wd; start 2nd */
31: { first=numch=0;
32: s=wd2buf;
33: break;
34: }
35: else /* finished 2nd word */
36: { FLUSHLINE;
37: *s=0;
38: return;
39: }
40: default:
41: if (++numch>=MAXSTR) /* string too long */
42: { printf("Give me a break!!\n");
43: wd1buf[0]=wd2buf[0]=0;
44: FLUSHLINE;
45: return;
46: }
47: s++;
48: }
49: }
50: }
51:
52:
53: confirm(mesg) /* confirm irreversible action */
54: char *mesg;
55: { register int result;
56: printf("%s",mesg); /* tell him what he did */
57: if (getchar()=='y') /* was his first letter a 'y'? */
58: result=1;
59: else result=0;
60: FLUSHLINE;
61: return(result);
62: }
63:
64: yes(x,y,z) /* confirm with rspeak */
65: int x,y,z;
66: { register int result;
67: register char ch;
68: for (;;)
69: { rspeak(x); /* tell him what we want*/
70: if ((ch=getchar())=='y')
71: result=TRUE;
72: else if (ch=='n') result=FALSE;
73: FLUSHLINE;
74: if (ch=='y'|| ch=='n') break;
75: printf("Please answer the question.\n");
76: }
77: if (result==TRUE) rspeak(y);
78: if (result==FALSE) rspeak(z);
79: return(result);
80: }
81:
82: yesm(x,y,z) /* confirm with mspeak */
83: int x,y,z;
84: { register int result;
85: register char ch;
86: for (;;)
87: { mspeak(x); /* tell him what we want*/
88: if ((ch=getchar())=='y')
89: result=TRUE;
90: else if (ch=='n') result=FALSE;
91: FLUSHLINE;
92: if (ch=='y'|| ch=='n') break;
93: printf("Please answer the question.\n");
94: }
95: if (result==TRUE) mspeak(y);
96: if (result==FALSE) mspeak(z);
97: return(result);
98: }
99:
100: FILE *inbuf,*outbuf;
101:
102: int adrptr; /* current seek adr ptr */
103: int outsw = 0; /* putting stuff to data file? */
104:
105: char iotape[] = "Ax3F'tt$8hqer*hnGKrX:!l";
106: char *tape = iotape; /* pointer to encryption tape */
107:
108: next() /* next char frm file, bump adr */
109: { register char ch,t;
110: adrptr++; /* seek address in file */
111: ch=getc(inbuf);
112: if (outsw) /* putting data in tmp file */
113: { if (*tape==0) tape=iotape; /* rewind encryption tape */
114: putc(ch ^ *tape++,outbuf); /* encrypt & output char */
115: }
116: return(ch);
117: }
118:
119:
120: char breakch; /* tell which char ended rnum */
121:
122:
123: rdata() /* read all data from orig file */
124: { register int sect;
125: register char ch;
126: if ((inbuf=fopen(DATFILE,"r"))==NULL) /* all the data lives in here */
127: { printf("Cannot open data file %s\n",DATFILE);
128: exit(0);
129: }
130: if ((outbuf=fopen(TMPFILE,"w"))==NULL) /* the text lines will go here */
131: { printf("Cannot create output file %s\n",TMPFILE);
132: exit(0);
133: }
134: setup=clsses=1;
135: for (;;) /* read data sections */
136: { sect=next()-'0'; /* 1st digit of section number */
137: printf("Section %c",sect+'0');
138: if ((ch=next())!=LF) /* is there a second digit? */
139: { FLUSHLF;
140: putchar(ch);
141: sect=10*sect+ch-'0';
142: }
143: putchar('\n');
144: switch(sect)
145: { case 0: /* finished reading database */
146: fclose(inbuf);
147: fclose(outbuf);
148: return;
149: case 1: /* long form descriptions */
150: rdesc(1);
151: break;
152: case 2: /* short form descriptions */
153: rdesc(2);
154: break;
155: case 3: /* travel table */
156: rtrav(); break;
157: case 4: /* vocabulary */
158: rvoc();
159: break;
160: case 5: /* object descriptions */
161: rdesc(5);
162: break;
163: case 6: /* arbitrary messages */
164: rdesc(6);
165: break;
166: case 7: /* object locations */
167: rlocs(); break;
168: case 8: /* action defaults */
169: rdflt(); break;
170: case 9: /* liquid assets */
171: rliq(); break;
172: case 10: /* class messages */
173: rdesc(10);
174: break;
175: case 11: /* hints */
176: rhints(); break;
177: case 12: /* magic messages */
178: rdesc(12);
179: break;
180: default:
181: printf("Invalid data section number: %d\n",sect);
182: for (;;) putchar(next());
183: }
184: if (breakch!=LF) /* routines return after "-1" */
185: FLUSHLF;
186: }
187: }
188:
189: char nbf[12];
190:
191:
192: rnum() /* read initial location num */
193: { register char *s;
194: tape = iotape; /* restart encryption tape */
195: for (s=nbf,*s=0;; s++)
196: if ((*s=next())==TAB || *s=='\n' || *s==LF)
197: break;
198: breakch= *s; /* save char for rtrav() */
199: *s=0; /* got the number as ascii */
200: if (nbf[0]=='-') return(-1); /* end of data */
201: return(atoi(nbf)); /* convert it to integer */
202: }
203:
204: int seekhere = 1; /* initial seek for output file */
205:
206: rdesc(sect) /* read description-format msgs */
207: int sect;
208: { register char *s,*t;
209: register int locc;
210: int seekstart, maystart, adrstart;
211: char *entry;
212: outsw=1; /* these msgs go into tmp file */
213: if (sect==1) putc('X',outbuf); /* so seekadr > 0 */
214: adrptr=0;
215: for (oldloc= -1, seekstart=seekhere;;)
216: { maystart=adrptr; /* maybe starting new entry */
217: if ((locc=rnum())!=oldloc && oldloc>=0 /* finished msg */
218: && ! (sect==5 && (locc==0 || locc>=100)))/* unless sect 5*/
219: { switch(sect) /* now put it into right table */
220: { case 1: /* long descriptions */
221: ltext[oldloc].seekadr=seekhere;
222: ltext[oldloc].txtlen=maystart-seekstart;
223: break;
224: case 2: /* short descriptions */
225: stext[oldloc].seekadr=seekhere;
226: stext[oldloc].txtlen=maystart-seekstart;
227: break;
228: case 5: /* object descriptions */
229: ptext[oldloc].seekadr=seekhere;
230: ptext[oldloc].txtlen=maystart-seekstart;
231: break;
232: case 6: /* random messages */
233: if (oldloc>RTXSIZ)
234: { printf("Too many random msgs\n");
235: exit(0);
236: }
237: rtext[oldloc].seekadr=seekhere;
238: rtext[oldloc].txtlen=maystart-seekstart;
239: break;
240: case 10: /* class messages */
241: ctext[clsses].seekadr=seekhere;
242: ctext[clsses].txtlen=maystart-seekstart;
243: cval[clsses++]=oldloc;
244: break;
245: case 12: /* magic messages */
246: if (oldloc>MAGSIZ)
247: { printf("Too many magic msgs\n");
248: exit(0);
249: }
250: mtext[oldloc].seekadr=seekhere;
251: mtext[oldloc].txtlen=maystart-seekstart;
252: break;
253: default:
254: printf("rdesc called with bad section\n");
255: exit(0);
256: }
257: seekhere += maystart-seekstart;
258: }
259: if (locc<0)
260: { outsw=0; /* turn off output */
261: seekhere += 3; /* -1<delimiter> */
262: return;
263: }
264: if (sect!=5 || (locc>0 && locc<100))
265: { if (oldloc!=locc)/* starting a new message */
266: seekstart=maystart;
267: oldloc=locc;
268: }
269: FLUSHLF; /* scan the line */
270: }
271: }
272:
273:
274: rtrav() /* read travel table */
275: { register int locc;
276: register struct travlist *t;
277: register char *s;
278: char buf[12];
279: int len,m,n,entries;
280: for (oldloc= -1;;) /* get another line */
281: { if ((locc=rnum())!=oldloc && oldloc>=0) /* end of entry */
282: {
283: t->next = 0; /* terminate the old entry */
284: /* printf("%d:%d entries\n",oldloc,entries); */
285: /* twrite(oldloc); */
286: }
287: if (locc== -1) return;
288: if (locc!=oldloc) /* getting a new entry */
289: { t=travel[locc]=(struct travlist *) malloc(sizeof (struct travlist));
290: /* printf("New travel list for %d\n",locc); */
291: entries=0;
292: oldloc=locc;
293: }
294: for (s=buf;; *s++) /* get the newloc number /ASCII */
295: if ((*s=next())==TAB || *s==LF) break;
296: *s=0;
297: len=length(buf)-1; /* quad long number handling */
298: /* printf("Newloc: %s (%d chars)\n",buf,len); */
299: if (len<4) /* no "m" conditions */
300: { m=0;
301: n=atoi(buf); /* newloc mod 1000 = newloc */
302: }
303: else /* a long integer */
304: { n=atoi(buf+len-3);
305: buf[len-3]=0; /* terminate newloc/1000 */
306: m=atoi(buf);
307: }
308: while (breakch!=LF) /* only do one line at a time */
309: { if (entries++) t=t->next=(struct travlist *) malloc(sizeof (struct travlist));
310: t->tverb=rnum();/* get verb from the file */
311: t->tloc=n; /* table entry mod 1000 */
312: t->conditions=m;/* table entry / 1000 */
313: /* printf("entry %d for %d\n",entries,locc); */
314: }
315: }
316: }
317:
318:
319: twrite(loq) /* travel options from this loc */
320: int loq;
321: { register struct travlist *t;
322: printf("If");
323: speak(<ext[loq]);
324: printf("then\n");
325: for (t=travel[loq]; t!=0; t=t->next)
326: { printf("verb %d takes you to ",t->tverb);
327: if (t->tloc<=300)
328: speak(<ext[t->tloc]);
329: else if (t->tloc<=500)
330: printf("special code %d\n",t->tloc-300);
331: else
332: rspeak(t->tloc-500);
333: printf("under conditions %d\n",t->conditions);
334: }
335: }
336:
337:
338:
339: rvoc()
340: { register char *s; /* read the vocabulary */
341: register int index;
342: char buf[6];
343: for (;;)
344: { index=rnum();
345: if (index<0) break;
346: for (s=buf,*s=0;; s++) /* get the word */
347: if ((*s=next())==TAB || *s=='\n' || *s==LF
348: || *s==' ') break;
349: /* terminate word with newline, LF, tab, blank */
350: if (*s!='\n' && *s!=LF) FLUSHLF; /* can be comments */
351: *s=0;
352: /* printf("\"%s\"=%d\n",buf,index);*/
353: vocab(buf,-2,index);
354: }
355: /* prht(); */
356: }
357:
358:
359: rlocs() /* initial object locations */
360: { for (;;)
361: { if ((obj=rnum())<0) break;
362: plac[obj]=rnum(); /* initial loc for this obj */
363: if (breakch==TAB) /* there's another entry */
364: fixd[obj]=rnum();
365: else fixd[obj]=0;
366: }
367: }
368:
369: rdflt() /* default verb messages */
370: { for (;;)
371: { if ((verb=rnum())<0) break;
372: actspk[verb]=rnum();
373: }
374: }
375:
376: rliq() /* liquid assets &c: cond bits */
377: { register int bitnum;
378: for (;;) /* read new bit list */
379: { if ((bitnum=rnum())<0) break;
380: for (;;) /* read locs for bits */
381: { cond[rnum()] |= setbit[bitnum];
382: if (breakch==LF) break;
383: }
384: }
385: }
386:
387: rhints()
388: { register int hintnum,i;
389: hntmax=0;
390: for (;;)
391: { if ((hintnum=rnum())<0) break;
392: for (i=1; i<5; i++)
393: hints[hintnum][i]=rnum();
394: if (hintnum>hntmax) hntmax=hintnum;
395: }
396: }
397:
398:
399: rspeak(msg)
400: int msg;
401: { if (msg!=0) speak(&rtext[msg]);
402: }
403:
404:
405: mspeak(msg)
406: int msg;
407: { if (msg!=0) speak(&mtext[msg]);
408: }
409:
410:
411: doseek(offset) /* do 2 seeks to get to right place in the file */
412: unsigned offset;
413: {
414: extern unsigned filesize;
415: lseek(datfd,(long)offset+(long)filesize, 0);
416: #ifdef notdef
417: blockadr=chadr=0;
418: if (offset<0) /* right place is offset+filesize*/
419: { blockadr += 64; /* take off 32768 bytes */
420: chadr += offset+32768; /* & make them into 64 blocks */
421: }
422: else chadr += offset;
423: if (filesize<0) /* data starts after file */
424: { blockadr += 64; /* which may also be large */
425: chadr += filesize+32768;
426: }
427: else chadr += filesize;
428: if (chadr<0) /* and the leftovers may be lge */
429: { blockadr += 64;
430: chadr += 32768;
431: }
432: seek(datfd,blockadr,3); /* get within 32767 */
433: seek(datfd,chadr,1); /* then the rest of the way */
434: #endif
435: }
436:
437:
438: speak(msg) /* read, decrypt, and print a message (not ptext) */
439: struct text *msg;/* msg is a pointer to seek address and length of mess */
440: { register char *s,nonfirst;
441: register char *tbuf;
442: doseek(msg->seekadr);
443: if ((tbuf=(char *) malloc(msg->txtlen+1))<0) bug(109);
444: read(datfd,tbuf,msg->txtlen);
445: s=tbuf;
446: nonfirst=0;
447: while (s-tbuf<msg->txtlen) /* read a line at a time */
448: { tape=iotape; /* restart decryption tape */
449: while ((*s++^*tape++)!=TAB); /* read past loc num */
450: /* assume tape is longer than location number */
451: /* plus the lookahead put together */
452: if ((*s^*tape)=='>' &&
453: (*(s+1)^*(tape+1))=='$' &&
454: (*(s+2)^*(tape+2))=='<') break;
455: if (blklin&&!nonfirst++) putchar('\n');
456: do
457: { if (*tape==0) tape=iotape;/* rewind decryp tape */
458: putchar(*s^*tape);
459: } while ((*s++^*tape++)!=LF); /* better end with LF */
460: }
461: free(tbuf);
462: }
463:
464:
465: pspeak(msg,skip) /* read, decrypt an print a ptext message */
466: int msg; /* msg is the number of all the p msgs for this place */
467: int skip; /* assumes object 1 doesn't have prop 1, obj 2 no prop 2 &c*/
468: { register char *s,nonfirst;
469: register char *tbuf;
470: char *numst;
471: int lstr;
472: doseek(ptext[msg].seekadr);
473: if ((tbuf=(char *) malloc((lstr=ptext[msg].txtlen)+1))<0) bug(108);
474: read(datfd,tbuf,lstr);
475: s=tbuf;
476: nonfirst=0;
477: while (s-tbuf<lstr) /* read a line at a time */
478: { tape=iotape; /* restart decryption tape */
479: for (numst=s; (*s^= *tape++)!=TAB; s++); /* get number */
480: *s++=0; /* decrypting number within the string */
481: if (atoi(numst)!=100*skip && skip>=0)
482: { while ((*s++^*tape++)!=LF) /* flush the line */
483: if (*tape==0) tape=iotape;
484: continue;
485: }
486: if ((*s^*tape)=='>' && (*(s+1)^*(tape+1))=='$' &&
487: (*(s+2)^*(tape+2))=='<') break;
488: if (blklin && ! nonfirst++) putchar('\n');
489: do
490: { if (*tape==0) tape=iotape;
491: putchar(*s^*tape);
492: } while ((*s++^*tape++)!=LF); /* better end with LF */
493: if (skip<0) break;
494: }
495: free(tbuf);
496: }
497:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.