1*8867Smckusick 2*8867Smckusick static char sccsid[] = " quiz.c 4.1 82/10/24 "; 3*8867Smckusick 4*8867Smckusick #include <stdio.h> 5*8867Smckusick #include <signal.h> 6*8867Smckusick #define NF 10 7*8867Smckusick #define NL 300 8*8867Smckusick #define NC 200 9*8867Smckusick #define SL 100 10*8867Smckusick #define NA 10 11*8867Smckusick 12*8867Smckusick int tflag; 13*8867Smckusick int xx[NL]; 14*8867Smckusick char score[NL]; 15*8867Smckusick int rights; 16*8867Smckusick int wrongs; 17*8867Smckusick int guesses; 18*8867Smckusick FILE *input; 19*8867Smckusick int nl = 0; 20*8867Smckusick int na = NA; 21*8867Smckusick int inc; 22*8867Smckusick int ptr = 0; 23*8867Smckusick int nc = 0; 24*8867Smckusick char line[150]; 25*8867Smckusick char response[100]; 26*8867Smckusick char *tmp[NF]; 27*8867Smckusick int select[NF]; 28*8867Smckusick 29*8867Smckusick readline() 30*8867Smckusick { 31*8867Smckusick char *t; 32*8867Smckusick loop: 33*8867Smckusick for(t=line;(*t=getc(input))!=-1;t++) { 34*8867Smckusick nc++; 35*8867Smckusick if(*t==' '&&(t==line||t[-1]==' ')) 36*8867Smckusick t--; 37*8867Smckusick if(*t=='\n') { 38*8867Smckusick if(t[-1]=='\\') /*inexact test*/ 39*8867Smckusick continue; 40*8867Smckusick while(t>line&&t[-1]==' ') 41*8867Smckusick *--t = '\n'; 42*8867Smckusick *++t = 0; 43*8867Smckusick return(1); 44*8867Smckusick } 45*8867Smckusick if(t-line>=NC) { 46*8867Smckusick printf("Too hard for me\n"); 47*8867Smckusick do { 48*8867Smckusick *line = getc(input); 49*8867Smckusick if(*line==0377) 50*8867Smckusick return(0); 51*8867Smckusick } while(*line!='\n'); 52*8867Smckusick goto loop; 53*8867Smckusick } 54*8867Smckusick } 55*8867Smckusick return(0); 56*8867Smckusick } 57*8867Smckusick 58*8867Smckusick char *eu; 59*8867Smckusick char *ev; 60*8867Smckusick cmp(u,v) 61*8867Smckusick char *u,*v; 62*8867Smckusick { 63*8867Smckusick int x; 64*8867Smckusick eu = u; 65*8867Smckusick ev = v; 66*8867Smckusick x = disj(1); 67*8867Smckusick if(x!=1) 68*8867Smckusick return(x); 69*8867Smckusick return(eat(1,0)); 70*8867Smckusick } 71*8867Smckusick 72*8867Smckusick disj(s) 73*8867Smckusick { 74*8867Smckusick int t, x; 75*8867Smckusick char *u; 76*8867Smckusick u = eu; 77*8867Smckusick t = 0; 78*8867Smckusick for(;;) { 79*8867Smckusick x = string(s); 80*8867Smckusick if(x>1) 81*8867Smckusick return(x); 82*8867Smckusick switch(*ev) { 83*8867Smckusick case 0: 84*8867Smckusick case ']': 85*8867Smckusick case '}': 86*8867Smckusick return(t|x&s); 87*8867Smckusick case '|': 88*8867Smckusick ev++; 89*8867Smckusick t |= s; 90*8867Smckusick s = 0; 91*8867Smckusick continue; 92*8867Smckusick } 93*8867Smckusick if(s) eu = u; 94*8867Smckusick if(string(0)>1) 95*8867Smckusick return(2); 96*8867Smckusick switch(*ev) { 97*8867Smckusick case 0: 98*8867Smckusick case ']': 99*8867Smckusick return(0); 100*8867Smckusick case '}': 101*8867Smckusick return(1); 102*8867Smckusick case '|': 103*8867Smckusick ev++; 104*8867Smckusick continue; 105*8867Smckusick default: 106*8867Smckusick return(2); 107*8867Smckusick } 108*8867Smckusick } 109*8867Smckusick } 110*8867Smckusick 111*8867Smckusick string(s) 112*8867Smckusick { 113*8867Smckusick int x; 114*8867Smckusick for(;;) { 115*8867Smckusick switch(*ev) { 116*8867Smckusick case 0: 117*8867Smckusick case '|': 118*8867Smckusick case ']': 119*8867Smckusick case '}': 120*8867Smckusick return(1); 121*8867Smckusick case '\\': 122*8867Smckusick ev++; 123*8867Smckusick if(*ev==0) 124*8867Smckusick return(2); 125*8867Smckusick if(*ev=='\n') { 126*8867Smckusick ev++; 127*8867Smckusick continue; 128*8867Smckusick } 129*8867Smckusick default: 130*8867Smckusick if(eat(s,*ev)==1) 131*8867Smckusick continue; 132*8867Smckusick return(0); 133*8867Smckusick case '[': 134*8867Smckusick ev++; 135*8867Smckusick x = disj(s); 136*8867Smckusick if(*ev!=']' || x>1) 137*8867Smckusick return(2); 138*8867Smckusick ev++; 139*8867Smckusick if(s==0) 140*8867Smckusick continue; 141*8867Smckusick if(x==0) 142*8867Smckusick return(0); 143*8867Smckusick continue; 144*8867Smckusick case '{': 145*8867Smckusick ev++; 146*8867Smckusick x = disj(s); 147*8867Smckusick if(*ev!='}'||x>1) 148*8867Smckusick return(2); 149*8867Smckusick ev++; 150*8867Smckusick continue; 151*8867Smckusick } 152*8867Smckusick } 153*8867Smckusick } 154*8867Smckusick 155*8867Smckusick eat(s,c) 156*8867Smckusick char c; 157*8867Smckusick { 158*8867Smckusick if(*ev!=c) 159*8867Smckusick return(2); 160*8867Smckusick if(s==0) { 161*8867Smckusick ev++; 162*8867Smckusick return(1); 163*8867Smckusick } 164*8867Smckusick if(fold(*eu)!=fold(c)) 165*8867Smckusick return(0); 166*8867Smckusick eu++; 167*8867Smckusick ev++; 168*8867Smckusick return(1); 169*8867Smckusick } 170*8867Smckusick 171*8867Smckusick fold(c) 172*8867Smckusick char c; 173*8867Smckusick { 174*8867Smckusick if(c<'A'||c>'Z') 175*8867Smckusick return(c); 176*8867Smckusick return(c|040); 177*8867Smckusick } 178*8867Smckusick 179*8867Smckusick publish(t) 180*8867Smckusick char *t; 181*8867Smckusick { 182*8867Smckusick ev = t; 183*8867Smckusick pub1(1); 184*8867Smckusick } 185*8867Smckusick 186*8867Smckusick pub1(s) 187*8867Smckusick { 188*8867Smckusick for(;;ev++){ 189*8867Smckusick switch(*ev) { 190*8867Smckusick case '|': 191*8867Smckusick s = 0; 192*8867Smckusick ev; 193*8867Smckusick continue; 194*8867Smckusick case ']': 195*8867Smckusick case '}': 196*8867Smckusick case 0: 197*8867Smckusick return; 198*8867Smckusick case '[': 199*8867Smckusick case '{': 200*8867Smckusick ev++; 201*8867Smckusick pub1(s); 202*8867Smckusick ev; 203*8867Smckusick continue; 204*8867Smckusick case '\\': 205*8867Smckusick if(*++ev=='\n') 206*8867Smckusick continue; 207*8867Smckusick default: 208*8867Smckusick if(s) 209*8867Smckusick putchar(*ev); 210*8867Smckusick } 211*8867Smckusick } 212*8867Smckusick } 213*8867Smckusick 214*8867Smckusick segment(u,w) 215*8867Smckusick char *u, *w[]; 216*8867Smckusick { 217*8867Smckusick char *s; 218*8867Smckusick int i; 219*8867Smckusick char *t; 220*8867Smckusick s = u; 221*8867Smckusick for(i=0;i<NF;i++) { 222*8867Smckusick u = s; 223*8867Smckusick t = w[i]; 224*8867Smckusick while(*s!=':'&&*s!='\n'&&s-u<SL) { 225*8867Smckusick if(*s=='\\') { 226*8867Smckusick if(s[1] == '\n') { 227*8867Smckusick s += 2; 228*8867Smckusick continue; 229*8867Smckusick } 230*8867Smckusick *t++ = *s++; 231*8867Smckusick } 232*8867Smckusick *t++ = *s++; 233*8867Smckusick } 234*8867Smckusick 235*8867Smckusick while(*s!=':'&&*s!='\n') 236*8867Smckusick s++; 237*8867Smckusick *t = 0; 238*8867Smckusick if(*s++=='\n') { 239*8867Smckusick return(i+1); 240*8867Smckusick } 241*8867Smckusick } 242*8867Smckusick printf("Too many facts about one thing\n"); 243*8867Smckusick } 244*8867Smckusick 245*8867Smckusick perm(u,m,v,n,p) 246*8867Smckusick int p[]; 247*8867Smckusick char *u[], *v[]; 248*8867Smckusick { 249*8867Smckusick int i, j; 250*8867Smckusick int x; 251*8867Smckusick for(i=0;i<m;i++) { 252*8867Smckusick for(j=0;j<n;j++) { 253*8867Smckusick x = cmp(u[i],v[j]); 254*8867Smckusick if(x>1) badinfo(); 255*8867Smckusick if(x==0) 256*8867Smckusick continue; 257*8867Smckusick p[i] = j; 258*8867Smckusick goto uloop; 259*8867Smckusick } 260*8867Smckusick return(0); 261*8867Smckusick uloop: ; 262*8867Smckusick } 263*8867Smckusick return(1); 264*8867Smckusick } 265*8867Smckusick 266*8867Smckusick find(u,m) 267*8867Smckusick char *u[]; 268*8867Smckusick { 269*8867Smckusick int n; 270*8867Smckusick while(readline()){ 271*8867Smckusick n = segment(line,tmp); 272*8867Smckusick if(perm(u,m,tmp+1,n-1,select)) 273*8867Smckusick return(1); 274*8867Smckusick } 275*8867Smckusick return(0); 276*8867Smckusick } 277*8867Smckusick 278*8867Smckusick readindex() 279*8867Smckusick { 280*8867Smckusick xx[0] = nc = 0; 281*8867Smckusick while(readline()) { 282*8867Smckusick xx[++nl] = nc; 283*8867Smckusick if(nl>=NL) { 284*8867Smckusick printf("I've forgotten some of it;\n"); 285*8867Smckusick printf("I remember %d items.\n", nl); 286*8867Smckusick break; 287*8867Smckusick } 288*8867Smckusick } 289*8867Smckusick } 290*8867Smckusick 291*8867Smckusick talloc() 292*8867Smckusick { 293*8867Smckusick int i; 294*8867Smckusick for(i=0;i<NF;i++) 295*8867Smckusick tmp[i] = malloc(SL); 296*8867Smckusick } 297*8867Smckusick 298*8867Smckusick main(argc,argv) 299*8867Smckusick char *argv[]; 300*8867Smckusick { 301*8867Smckusick register j; 302*8867Smckusick int i; 303*8867Smckusick int x; 304*8867Smckusick int z; 305*8867Smckusick char *info; 306*8867Smckusick int tvec[2]; 307*8867Smckusick char *t; 308*8867Smckusick extern done(); 309*8867Smckusick int count; 310*8867Smckusick info = "/usr/games/lib/quiz.k/index"; 311*8867Smckusick time(tvec); 312*8867Smckusick inc = tvec[1]&077774|01; 313*8867Smckusick loop: 314*8867Smckusick if(argc>1&&*argv[1]=='-') { 315*8867Smckusick switch(argv[1][1]) { 316*8867Smckusick case 'i': 317*8867Smckusick if(argc>2) 318*8867Smckusick info = argv[2]; 319*8867Smckusick argc -= 2; 320*8867Smckusick argv += 2; 321*8867Smckusick goto loop; 322*8867Smckusick case 't': 323*8867Smckusick tflag = 1; 324*8867Smckusick argc--; 325*8867Smckusick argv++; 326*8867Smckusick goto loop; 327*8867Smckusick } 328*8867Smckusick } 329*8867Smckusick input = fopen(info,"r"); 330*8867Smckusick if(input==NULL) { 331*8867Smckusick printf("No info\n"); 332*8867Smckusick exit(0); 333*8867Smckusick } 334*8867Smckusick talloc(); 335*8867Smckusick if(argc<=2) 336*8867Smckusick instruct(info); 337*8867Smckusick signal(SIGINT,done); 338*8867Smckusick argv[argc] = 0; 339*8867Smckusick if(find(&argv[1],argc-1)==0) 340*8867Smckusick dunno(); 341*8867Smckusick fclose(input); 342*8867Smckusick input = fopen(tmp[0],"r"); 343*8867Smckusick if(input==NULL) 344*8867Smckusick dunno(); 345*8867Smckusick readindex(); 346*8867Smckusick if(!tflag || na>nl) 347*8867Smckusick na = nl; 348*8867Smckusick stdout->_flag |= _IONBF; 349*8867Smckusick for(;;) { 350*8867Smckusick i = next(); 351*8867Smckusick fseek(input,xx[i]+0L,0); 352*8867Smckusick z = xx[i+1]-xx[i]; 353*8867Smckusick for(j=0;j<z;j++) 354*8867Smckusick line[j] = getc(input); 355*8867Smckusick segment(line,tmp); 356*8867Smckusick if(*tmp[select[0]] == '\0' || *tmp[select[1]] == '\0') { 357*8867Smckusick score[i] = 1; 358*8867Smckusick continue; 359*8867Smckusick } 360*8867Smckusick publish(tmp[select[0]]); 361*8867Smckusick printf("\n"); 362*8867Smckusick for(count=0;;count++) { 363*8867Smckusick if(query(response)==0) { 364*8867Smckusick publish(tmp[select[1]]); 365*8867Smckusick printf("\n"); 366*8867Smckusick if(count==0) wrongs++; 367*8867Smckusick score[i] = tflag?-1:1; 368*8867Smckusick break; 369*8867Smckusick } 370*8867Smckusick x = cmp(response,tmp[select[1]]); 371*8867Smckusick if(x>1) badinfo(); 372*8867Smckusick if(x==1) { 373*8867Smckusick printf("Right!\n"); 374*8867Smckusick if(count==0) rights++; 375*8867Smckusick if(++score[i]>=1 && na<nl) 376*8867Smckusick na++; 377*8867Smckusick break; 378*8867Smckusick } 379*8867Smckusick printf("What?\n"); 380*8867Smckusick if(count==0) wrongs++; 381*8867Smckusick score[i] = tflag?-1:1; 382*8867Smckusick } 383*8867Smckusick guesses += count; 384*8867Smckusick } 385*8867Smckusick } 386*8867Smckusick 387*8867Smckusick query(r) 388*8867Smckusick char *r; 389*8867Smckusick { 390*8867Smckusick char *t; 391*8867Smckusick for(t=r;;t++) { 392*8867Smckusick if(read(0,t,1)==0) 393*8867Smckusick done(); 394*8867Smckusick if(*t==' '&&(t==r||t[-1]==' ')) 395*8867Smckusick t--; 396*8867Smckusick if(*t=='\n') { 397*8867Smckusick while(t>r&&t[-1]==' ') 398*8867Smckusick *--t = '\n'; 399*8867Smckusick break; 400*8867Smckusick } 401*8867Smckusick } 402*8867Smckusick *t = 0; 403*8867Smckusick return(t-r); 404*8867Smckusick } 405*8867Smckusick 406*8867Smckusick next() 407*8867Smckusick { 408*8867Smckusick int flag; 409*8867Smckusick inc = inc*3125&077777; 410*8867Smckusick ptr = (inc>>2)%na; 411*8867Smckusick flag = 0; 412*8867Smckusick while(score[ptr]>0) 413*8867Smckusick if(++ptr>=na) { 414*8867Smckusick ptr = 0; 415*8867Smckusick if(flag) done(); 416*8867Smckusick flag = 1; 417*8867Smckusick } 418*8867Smckusick return(ptr); 419*8867Smckusick } 420*8867Smckusick 421*8867Smckusick done() 422*8867Smckusick { 423*8867Smckusick printf("\nRights %d, wrongs %d, ", rights, wrongs); 424*8867Smckusick if(guesses) 425*8867Smckusick printf("extra guesses %d, ", guesses); 426*8867Smckusick printf("score %d%%\n",100*rights/(rights+wrongs)); 427*8867Smckusick exit(0); 428*8867Smckusick } 429*8867Smckusick instruct(info) 430*8867Smckusick { 431*8867Smckusick char *t; 432*8867Smckusick int i, n; 433*8867Smckusick printf("Subjects:\n\n"); 434*8867Smckusick while(readline()) { 435*8867Smckusick printf("-"); 436*8867Smckusick n = segment(line,tmp); 437*8867Smckusick for(i=1;i<n;i++) { 438*8867Smckusick printf(" "); 439*8867Smckusick publish(tmp[i]); 440*8867Smckusick } 441*8867Smckusick printf("\n"); 442*8867Smckusick } 443*8867Smckusick printf("\n"); 444*8867Smckusick input = fopen(info,"r"); 445*8867Smckusick if(input==NULL) 446*8867Smckusick abort(); 447*8867Smckusick readline(); 448*8867Smckusick segment(line,tmp); 449*8867Smckusick printf("For example,\n"); 450*8867Smckusick printf(" quiz "); 451*8867Smckusick publish(tmp[1]); 452*8867Smckusick printf(" "); 453*8867Smckusick publish(tmp[2]); 454*8867Smckusick printf("\nasks you a "); 455*8867Smckusick publish(tmp[1]); 456*8867Smckusick printf(" and you answer the "); 457*8867Smckusick publish(tmp[2]); 458*8867Smckusick printf("\n quiz "); 459*8867Smckusick publish(tmp[2]); 460*8867Smckusick printf(" "); 461*8867Smckusick publish(tmp[1]); 462*8867Smckusick printf("\nworks the other way around\n"); 463*8867Smckusick printf("\nType empty line to get correct answer.\n"); 464*8867Smckusick exit(0); 465*8867Smckusick } 466*8867Smckusick 467*8867Smckusick badinfo(){ 468*8867Smckusick printf("Bad info %s\n",line); 469*8867Smckusick } 470*8867Smckusick 471*8867Smckusick dunno() 472*8867Smckusick { 473*8867Smckusick printf("I don't know about that\n"); 474*8867Smckusick exit(0); 475*8867Smckusick } 476