16736Srrh # 26736Srrh /* Re-coding of advent in C: file i/o and user i/o */ 36736Srrh 4*35697Sbostic static char sccsid[] = " io.c 4.2 88/09/22 "; 56736Srrh 66736Srrh #include "hdr.h" 76736Srrh #include <stdio.h> 86736Srrh 96736Srrh 106736Srrh getin(wrd1,wrd2) /* get command from user */ 116736Srrh char **wrd1,**wrd2; /* no prompt, usually */ 126736Srrh { register char *s; 136736Srrh static char wd1buf[MAXSTR],wd2buf[MAXSTR]; 146736Srrh int first, numch; 156736Srrh 166736Srrh *wrd1=wd1buf; /* return ptr to internal string*/ 176736Srrh *wrd2=wd2buf; 186736Srrh wd2buf[0]=0; /* in case it isn't set here */ 196736Srrh for (s=wd1buf, first=1, numch=0;;) 206736Srrh { if ((*s=getchar())>='A' && *s <='Z') *s = *s - ('A' -'a'); 216736Srrh /* convert to upper case */ 226736Srrh switch(*s) /* start reading from user */ 236736Srrh { case '\n': 246736Srrh *s=0; 256736Srrh return; 266736Srrh case ' ': 276736Srrh if (s==wd1buf||s==wd2buf) /* initial blank */ 286736Srrh continue; 296736Srrh *s=0; 306736Srrh if (first) /* finished 1st wd; start 2nd */ 316736Srrh { first=numch=0; 326736Srrh s=wd2buf; 336736Srrh break; 346736Srrh } 356736Srrh else /* finished 2nd word */ 366736Srrh { FLUSHLINE; 376736Srrh *s=0; 386736Srrh return; 396736Srrh } 406736Srrh default: 416736Srrh if (++numch>=MAXSTR) /* string too long */ 426736Srrh { printf("Give me a break!!\n"); 436736Srrh wd1buf[0]=wd2buf[0]=0; 446736Srrh FLUSHLINE; 456736Srrh return; 466736Srrh } 476736Srrh s++; 486736Srrh } 496736Srrh } 506736Srrh } 516736Srrh 526736Srrh 536736Srrh confirm(mesg) /* confirm irreversible action */ 546736Srrh char *mesg; 556736Srrh { register int result; 566736Srrh printf("%s",mesg); /* tell him what he did */ 576736Srrh if (getchar()=='y') /* was his first letter a 'y'? */ 586736Srrh result=1; 596736Srrh else result=0; 606736Srrh FLUSHLINE; 616736Srrh return(result); 626736Srrh } 636736Srrh 646736Srrh yes(x,y,z) /* confirm with rspeak */ 656736Srrh int x,y,z; 666736Srrh { register int result; 676736Srrh register char ch; 686736Srrh for (;;) 696736Srrh { rspeak(x); /* tell him what we want*/ 706736Srrh if ((ch=getchar())=='y') 716736Srrh result=TRUE; 726736Srrh else if (ch=='n') result=FALSE; 736736Srrh FLUSHLINE; 746736Srrh if (ch=='y'|| ch=='n') break; 756736Srrh printf("Please answer the question.\n"); 766736Srrh } 776736Srrh if (result==TRUE) rspeak(y); 786736Srrh if (result==FALSE) rspeak(z); 796736Srrh return(result); 806736Srrh } 816736Srrh 826736Srrh yesm(x,y,z) /* confirm with mspeak */ 836736Srrh int x,y,z; 846736Srrh { register int result; 856736Srrh register char ch; 866736Srrh for (;;) 876736Srrh { mspeak(x); /* tell him what we want*/ 886736Srrh if ((ch=getchar())=='y') 896736Srrh result=TRUE; 906736Srrh else if (ch=='n') result=FALSE; 916736Srrh FLUSHLINE; 926736Srrh if (ch=='y'|| ch=='n') break; 936736Srrh printf("Please answer the question.\n"); 946736Srrh } 956736Srrh if (result==TRUE) mspeak(y); 966736Srrh if (result==FALSE) mspeak(z); 976736Srrh return(result); 986736Srrh } 996736Srrh 1006736Srrh FILE *inbuf,*outbuf; 1016736Srrh 1026736Srrh int adrptr; /* current seek adr ptr */ 1036736Srrh int outsw = 0; /* putting stuff to data file? */ 1046736Srrh 1056736Srrh char iotape[] = "Ax3F'tt$8hqer*hnGKrX:!l"; 1066736Srrh char *tape = iotape; /* pointer to encryption tape */ 1076736Srrh 1086736Srrh next() /* next char frm file, bump adr */ 1096736Srrh { register char ch,t; 1106736Srrh adrptr++; /* seek address in file */ 1116736Srrh ch=getc(inbuf); 1126736Srrh if (outsw) /* putting data in tmp file */ 1136736Srrh { if (*tape==0) tape=iotape; /* rewind encryption tape */ 1146736Srrh putc(ch ^ *tape++,outbuf); /* encrypt & output char */ 1156736Srrh } 1166736Srrh return(ch); 1176736Srrh } 1186736Srrh 1196736Srrh 1206736Srrh char breakch; /* tell which char ended rnum */ 1216736Srrh 1226736Srrh 1236736Srrh rdata() /* read all data from orig file */ 1246736Srrh { register int sect; 1256736Srrh register char ch; 1266736Srrh if ((inbuf=fopen(DATFILE,"r"))==NULL) /* all the data lives in here */ 1276736Srrh { printf("Cannot open data file %s\n",DATFILE); 1286736Srrh exit(0); 1296736Srrh } 1306736Srrh if ((outbuf=fopen(TMPFILE,"w"))==NULL) /* the text lines will go here */ 1316736Srrh { printf("Cannot create output file %s\n",TMPFILE); 1326736Srrh exit(0); 1336736Srrh } 1346736Srrh setup=clsses=1; 1356736Srrh for (;;) /* read data sections */ 1366736Srrh { sect=next()-'0'; /* 1st digit of section number */ 1376736Srrh printf("Section %c",sect+'0'); 1386736Srrh if ((ch=next())!=LF) /* is there a second digit? */ 1396736Srrh { FLUSHLF; 1406736Srrh putchar(ch); 1416736Srrh sect=10*sect+ch-'0'; 1426736Srrh } 1436736Srrh putchar('\n'); 1446736Srrh switch(sect) 1456736Srrh { case 0: /* finished reading database */ 1466736Srrh fclose(inbuf); 1476736Srrh fclose(outbuf); 1486736Srrh return; 1496736Srrh case 1: /* long form descriptions */ 1506736Srrh rdesc(1); 1516736Srrh break; 1526736Srrh case 2: /* short form descriptions */ 1536736Srrh rdesc(2); 1546736Srrh break; 1556736Srrh case 3: /* travel table */ 1566736Srrh rtrav(); break; 1576736Srrh case 4: /* vocabulary */ 1586736Srrh rvoc(); 1596736Srrh break; 1606736Srrh case 5: /* object descriptions */ 1616736Srrh rdesc(5); 1626736Srrh break; 1636736Srrh case 6: /* arbitrary messages */ 1646736Srrh rdesc(6); 1656736Srrh break; 1666736Srrh case 7: /* object locations */ 1676736Srrh rlocs(); break; 1686736Srrh case 8: /* action defaults */ 1696736Srrh rdflt(); break; 1706736Srrh case 9: /* liquid assets */ 1716736Srrh rliq(); break; 1726736Srrh case 10: /* class messages */ 1736736Srrh rdesc(10); 1746736Srrh break; 1756736Srrh case 11: /* hints */ 1766736Srrh rhints(); break; 1776736Srrh case 12: /* magic messages */ 1786736Srrh rdesc(12); 1796736Srrh break; 1806736Srrh default: 1816736Srrh printf("Invalid data section number: %d\n",sect); 1826736Srrh for (;;) putchar(next()); 1836736Srrh } 1846736Srrh if (breakch!=LF) /* routines return after "-1" */ 1856736Srrh FLUSHLF; 1866736Srrh } 1876736Srrh } 1886736Srrh 1896736Srrh char nbf[12]; 1906736Srrh 1916736Srrh 1926736Srrh rnum() /* read initial location num */ 1936736Srrh { register char *s; 1946736Srrh tape = iotape; /* restart encryption tape */ 1956736Srrh for (s=nbf,*s=0;; s++) 1966736Srrh if ((*s=next())==TAB || *s=='\n' || *s==LF) 1976736Srrh break; 1986736Srrh breakch= *s; /* save char for rtrav() */ 1996736Srrh *s=0; /* got the number as ascii */ 2006736Srrh if (nbf[0]=='-') return(-1); /* end of data */ 2016736Srrh return(atoi(nbf)); /* convert it to integer */ 2026736Srrh } 2036736Srrh 2046736Srrh int seekhere = 1; /* initial seek for output file */ 2056736Srrh 2066736Srrh rdesc(sect) /* read description-format msgs */ 2076736Srrh int sect; 2086736Srrh { register char *s,*t; 2096736Srrh register int locc; 2106736Srrh int seekstart, maystart, adrstart; 2116736Srrh char *entry; 2126736Srrh outsw=1; /* these msgs go into tmp file */ 2136736Srrh if (sect==1) putc('X',outbuf); /* so seekadr > 0 */ 2146736Srrh adrptr=0; 2156736Srrh for (oldloc= -1, seekstart=seekhere;;) 2166736Srrh { maystart=adrptr; /* maybe starting new entry */ 2176736Srrh if ((locc=rnum())!=oldloc && oldloc>=0 /* finished msg */ 2186736Srrh && ! (sect==5 && (locc==0 || locc>=100)))/* unless sect 5*/ 2196736Srrh { switch(sect) /* now put it into right table */ 2206736Srrh { case 1: /* long descriptions */ 2216736Srrh ltext[oldloc].seekadr=seekhere; 2226736Srrh ltext[oldloc].txtlen=maystart-seekstart; 2236736Srrh break; 2246736Srrh case 2: /* short descriptions */ 2256736Srrh stext[oldloc].seekadr=seekhere; 2266736Srrh stext[oldloc].txtlen=maystart-seekstart; 2276736Srrh break; 2286736Srrh case 5: /* object descriptions */ 2296736Srrh ptext[oldloc].seekadr=seekhere; 2306736Srrh ptext[oldloc].txtlen=maystart-seekstart; 2316736Srrh break; 2326736Srrh case 6: /* random messages */ 2336736Srrh if (oldloc>RTXSIZ) 2346736Srrh { printf("Too many random msgs\n"); 2356736Srrh exit(0); 2366736Srrh } 2376736Srrh rtext[oldloc].seekadr=seekhere; 2386736Srrh rtext[oldloc].txtlen=maystart-seekstart; 2396736Srrh break; 2406736Srrh case 10: /* class messages */ 2416736Srrh ctext[clsses].seekadr=seekhere; 2426736Srrh ctext[clsses].txtlen=maystart-seekstart; 2436736Srrh cval[clsses++]=oldloc; 2446736Srrh break; 2456736Srrh case 12: /* magic messages */ 2466736Srrh if (oldloc>MAGSIZ) 2476736Srrh { printf("Too many magic msgs\n"); 2486736Srrh exit(0); 2496736Srrh } 2506736Srrh mtext[oldloc].seekadr=seekhere; 2516736Srrh mtext[oldloc].txtlen=maystart-seekstart; 2526736Srrh break; 2536736Srrh default: 2546736Srrh printf("rdesc called with bad section\n"); 2556736Srrh exit(0); 2566736Srrh } 2576736Srrh seekhere += maystart-seekstart; 2586736Srrh } 2596736Srrh if (locc<0) 2606736Srrh { outsw=0; /* turn off output */ 2616736Srrh seekhere += 3; /* -1<delimiter> */ 2626736Srrh return; 2636736Srrh } 2646736Srrh if (sect!=5 || (locc>0 && locc<100)) 2656736Srrh { if (oldloc!=locc)/* starting a new message */ 2666736Srrh seekstart=maystart; 2676736Srrh oldloc=locc; 2686736Srrh } 2696736Srrh FLUSHLF; /* scan the line */ 2706736Srrh } 2716736Srrh } 2726736Srrh 2736736Srrh 2746736Srrh rtrav() /* read travel table */ 2756736Srrh { register int locc; 2766736Srrh register struct travlist *t; 2776736Srrh register char *s; 2786736Srrh char buf[12]; 2796736Srrh int len,m,n,entries; 2806736Srrh for (oldloc= -1;;) /* get another line */ 2816736Srrh { if ((locc=rnum())!=oldloc && oldloc>=0) /* end of entry */ 2826736Srrh { 2836736Srrh t->next = 0; /* terminate the old entry */ 2846736Srrh /* printf("%d:%d entries\n",oldloc,entries); */ 2856736Srrh /* twrite(oldloc); */ 2866736Srrh } 2876736Srrh if (locc== -1) return; 2886736Srrh if (locc!=oldloc) /* getting a new entry */ 2896736Srrh { t=travel[locc]=(struct travlist *) malloc(sizeof (struct travlist)); 2906736Srrh /* printf("New travel list for %d\n",locc); */ 2916736Srrh entries=0; 2926736Srrh oldloc=locc; 2936736Srrh } 2946736Srrh for (s=buf;; *s++) /* get the newloc number /ASCII */ 2956736Srrh if ((*s=next())==TAB || *s==LF) break; 2966736Srrh *s=0; 2976736Srrh len=length(buf)-1; /* quad long number handling */ 2986736Srrh /* printf("Newloc: %s (%d chars)\n",buf,len); */ 2996736Srrh if (len<4) /* no "m" conditions */ 3006736Srrh { m=0; 3016736Srrh n=atoi(buf); /* newloc mod 1000 = newloc */ 3026736Srrh } 3036736Srrh else /* a long integer */ 3046736Srrh { n=atoi(buf+len-3); 3056736Srrh buf[len-3]=0; /* terminate newloc/1000 */ 3066736Srrh m=atoi(buf); 3076736Srrh } 3086736Srrh while (breakch!=LF) /* only do one line at a time */ 3096736Srrh { if (entries++) t=t->next=(struct travlist *) malloc(sizeof (struct travlist)); 3106736Srrh t->tverb=rnum();/* get verb from the file */ 3116736Srrh t->tloc=n; /* table entry mod 1000 */ 3126736Srrh t->conditions=m;/* table entry / 1000 */ 3136736Srrh /* printf("entry %d for %d\n",entries,locc); */ 3146736Srrh } 3156736Srrh } 3166736Srrh } 3176736Srrh 3186736Srrh 3196736Srrh twrite(loq) /* travel options from this loc */ 3206736Srrh int loq; 3216736Srrh { register struct travlist *t; 3226736Srrh printf("If"); 3236736Srrh speak(<ext[loq]); 3246736Srrh printf("then\n"); 3256736Srrh for (t=travel[loq]; t!=0; t=t->next) 3266736Srrh { printf("verb %d takes you to ",t->tverb); 3276736Srrh if (t->tloc<=300) 3286736Srrh speak(<ext[t->tloc]); 3296736Srrh else if (t->tloc<=500) 3306736Srrh printf("special code %d\n",t->tloc-300); 3316736Srrh else 3326736Srrh rspeak(t->tloc-500); 3336736Srrh printf("under conditions %d\n",t->conditions); 3346736Srrh } 3356736Srrh } 3366736Srrh 3376736Srrh 3386736Srrh 3396736Srrh rvoc() 3406736Srrh { register char *s; /* read the vocabulary */ 3416736Srrh register int index; 3426736Srrh char buf[6]; 3436736Srrh for (;;) 3446736Srrh { index=rnum(); 3456736Srrh if (index<0) break; 3466736Srrh for (s=buf,*s=0;; s++) /* get the word */ 3476736Srrh if ((*s=next())==TAB || *s=='\n' || *s==LF 3486736Srrh || *s==' ') break; 3496736Srrh /* terminate word with newline, LF, tab, blank */ 3506736Srrh if (*s!='\n' && *s!=LF) FLUSHLF; /* can be comments */ 3516736Srrh *s=0; 3526736Srrh /* printf("\"%s\"=%d\n",buf,index);*/ 3536736Srrh vocab(buf,-2,index); 3546736Srrh } 3556736Srrh /* prht(); */ 3566736Srrh } 3576736Srrh 3586736Srrh 3596736Srrh rlocs() /* initial object locations */ 3606736Srrh { for (;;) 3616736Srrh { if ((obj=rnum())<0) break; 3626736Srrh plac[obj]=rnum(); /* initial loc for this obj */ 3636736Srrh if (breakch==TAB) /* there's another entry */ 3646736Srrh fixd[obj]=rnum(); 3656736Srrh else fixd[obj]=0; 3666736Srrh } 3676736Srrh } 3686736Srrh 3696736Srrh rdflt() /* default verb messages */ 3706736Srrh { for (;;) 3716736Srrh { if ((verb=rnum())<0) break; 3726736Srrh actspk[verb]=rnum(); 3736736Srrh } 3746736Srrh } 3756736Srrh 3766736Srrh rliq() /* liquid assets &c: cond bits */ 3776736Srrh { register int bitnum; 3786736Srrh for (;;) /* read new bit list */ 3796736Srrh { if ((bitnum=rnum())<0) break; 3806736Srrh for (;;) /* read locs for bits */ 3816736Srrh { cond[rnum()] |= setbit[bitnum]; 3826736Srrh if (breakch==LF) break; 3836736Srrh } 3846736Srrh } 3856736Srrh } 3866736Srrh 3876736Srrh rhints() 3886736Srrh { register int hintnum,i; 3896736Srrh hntmax=0; 3906736Srrh for (;;) 3916736Srrh { if ((hintnum=rnum())<0) break; 3926736Srrh for (i=1; i<5; i++) 3936736Srrh hints[hintnum][i]=rnum(); 3946736Srrh if (hintnum>hntmax) hntmax=hintnum; 3956736Srrh } 3966736Srrh } 3976736Srrh 3986736Srrh 3996736Srrh rspeak(msg) 4006736Srrh int msg; 4016736Srrh { if (msg!=0) speak(&rtext[msg]); 4026736Srrh } 4036736Srrh 4046736Srrh 4056736Srrh mspeak(msg) 4066736Srrh int msg; 4076736Srrh { if (msg!=0) speak(&mtext[msg]); 4086736Srrh } 4096736Srrh 4106736Srrh 4116736Srrh doseek(offset) /* do 2 seeks to get to right place in the file */ 4126736Srrh unsigned offset; 4136736Srrh { 4146736Srrh extern unsigned filesize; 4156736Srrh lseek(datfd,(long)offset+(long)filesize, 0); 4166736Srrh #ifdef notdef 4176736Srrh blockadr=chadr=0; 4186736Srrh if (offset<0) /* right place is offset+filesize*/ 4196736Srrh { blockadr += 64; /* take off 32768 bytes */ 4206736Srrh chadr += offset+32768; /* & make them into 64 blocks */ 4216736Srrh } 4226736Srrh else chadr += offset; 4236736Srrh if (filesize<0) /* data starts after file */ 4246736Srrh { blockadr += 64; /* which may also be large */ 4256736Srrh chadr += filesize+32768; 4266736Srrh } 4276736Srrh else chadr += filesize; 4286736Srrh if (chadr<0) /* and the leftovers may be lge */ 4296736Srrh { blockadr += 64; 4306736Srrh chadr += 32768; 4316736Srrh } 4326736Srrh seek(datfd,blockadr,3); /* get within 32767 */ 4336736Srrh seek(datfd,chadr,1); /* then the rest of the way */ 4346736Srrh #endif 4356736Srrh } 4366736Srrh 4376736Srrh 4386736Srrh speak(msg) /* read, decrypt, and print a message (not ptext) */ 4396736Srrh struct text *msg;/* msg is a pointer to seek address and length of mess */ 4406736Srrh { register char *s,nonfirst; 4416736Srrh register char *tbuf; 4426736Srrh doseek(msg->seekadr); 443*35697Sbostic if ((tbuf=(char *) malloc(msg->txtlen+1)) == 0) bug(109); 4446736Srrh read(datfd,tbuf,msg->txtlen); 4456736Srrh s=tbuf; 4466736Srrh nonfirst=0; 4476736Srrh while (s-tbuf<msg->txtlen) /* read a line at a time */ 4486736Srrh { tape=iotape; /* restart decryption tape */ 4496736Srrh while ((*s++^*tape++)!=TAB); /* read past loc num */ 4506736Srrh /* assume tape is longer than location number */ 4516736Srrh /* plus the lookahead put together */ 4526736Srrh if ((*s^*tape)=='>' && 4536736Srrh (*(s+1)^*(tape+1))=='$' && 4546736Srrh (*(s+2)^*(tape+2))=='<') break; 4556736Srrh if (blklin&&!nonfirst++) putchar('\n'); 4566736Srrh do 4576736Srrh { if (*tape==0) tape=iotape;/* rewind decryp tape */ 4586736Srrh putchar(*s^*tape); 4596736Srrh } while ((*s++^*tape++)!=LF); /* better end with LF */ 4606736Srrh } 4616736Srrh free(tbuf); 4626736Srrh } 4636736Srrh 4646736Srrh 4656736Srrh pspeak(msg,skip) /* read, decrypt an print a ptext message */ 4666736Srrh int msg; /* msg is the number of all the p msgs for this place */ 4676736Srrh int skip; /* assumes object 1 doesn't have prop 1, obj 2 no prop 2 &c*/ 4686736Srrh { register char *s,nonfirst; 4696736Srrh register char *tbuf; 4706736Srrh char *numst; 4716736Srrh int lstr; 4726736Srrh doseek(ptext[msg].seekadr); 473*35697Sbostic if ((tbuf=(char *) malloc((lstr=ptext[msg].txtlen)+1)) == 0) bug(108); 4746736Srrh read(datfd,tbuf,lstr); 4756736Srrh s=tbuf; 4766736Srrh nonfirst=0; 4776736Srrh while (s-tbuf<lstr) /* read a line at a time */ 4786736Srrh { tape=iotape; /* restart decryption tape */ 4796736Srrh for (numst=s; (*s^= *tape++)!=TAB; s++); /* get number */ 4806736Srrh *s++=0; /* decrypting number within the string */ 4816736Srrh if (atoi(numst)!=100*skip && skip>=0) 4826736Srrh { while ((*s++^*tape++)!=LF) /* flush the line */ 4836736Srrh if (*tape==0) tape=iotape; 4846736Srrh continue; 4856736Srrh } 4866736Srrh if ((*s^*tape)=='>' && (*(s+1)^*(tape+1))=='$' && 4876736Srrh (*(s+2)^*(tape+2))=='<') break; 4886736Srrh if (blklin && ! nonfirst++) putchar('\n'); 4896736Srrh do 4906736Srrh { if (*tape==0) tape=iotape; 4916736Srrh putchar(*s^*tape); 4926736Srrh } while ((*s++^*tape++)!=LF); /* better end with LF */ 4936736Srrh if (skip<0) break; 4946736Srrh } 4956736Srrh free(tbuf); 4966736Srrh } 4976736Srrh 498