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