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