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