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