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