1 2 static char sccsid[] = " quiz.c 4.2 85/01/09 "; 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 char *t; 32 loop: 33 for(t=line;(*t=getc(input))!=-1;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 ev; 193 continue; 194 case ']': 195 case '}': 196 case 0: 197 return; 198 case '[': 199 case '{': 200 ev++; 201 pub1(s); 202 ev; 203 continue; 204 case '\\': 205 if(*++ev=='\n') 206 continue; 207 default: 208 if(s) 209 putchar(*ev); 210 } 211 } 212 } 213 214 segment(u,w) 215 char *u, *w[]; 216 { 217 char *s; 218 int i; 219 char *t; 220 s = u; 221 for(i=0;i<NF;i++) { 222 u = s; 223 t = w[i]; 224 while(*s!=':'&&*s!='\n'&&s-u<SL) { 225 if(*s=='\\') { 226 if(s[1] == '\n') { 227 s += 2; 228 continue; 229 } 230 *t++ = *s++; 231 } 232 *t++ = *s++; 233 } 234 235 while(*s!=':'&&*s!='\n') 236 s++; 237 *t = 0; 238 if(*s++=='\n') { 239 return(i+1); 240 } 241 } 242 printf("Too many facts about one thing\n"); 243 } 244 245 perm(u,m,v,n,p) 246 int p[]; 247 char *u[], *v[]; 248 { 249 int i, j; 250 int x; 251 for(i=0;i<m;i++) { 252 for(j=0;j<n;j++) { 253 x = cmp(u[i],v[j]); 254 if(x>1) badinfo(); 255 if(x==0) 256 continue; 257 p[i] = j; 258 goto uloop; 259 } 260 return(0); 261 uloop: ; 262 } 263 return(1); 264 } 265 266 find(u,m) 267 char *u[]; 268 { 269 int n; 270 while(readline()){ 271 n = segment(line,tmp); 272 if(perm(u,m,tmp+1,n-1,select)) 273 return(1); 274 } 275 return(0); 276 } 277 278 readindex() 279 { 280 xx[0] = nc = 0; 281 while(readline()) { 282 xx[++nl] = nc; 283 if(nl>=NL) { 284 printf("I've forgotten some of it;\n"); 285 printf("I remember %d items.\n", nl); 286 break; 287 } 288 } 289 } 290 291 talloc() 292 { 293 int i; 294 char *malloc(); 295 296 for(i=0;i<NF;i++) 297 tmp[i] = malloc(SL); 298 } 299 300 main(argc,argv) 301 char *argv[]; 302 { 303 register j; 304 int i; 305 int x; 306 int z; 307 char *info; 308 int tvec[2]; 309 char *t; 310 extern done(); 311 int count; 312 info = "/usr/games/lib/quiz.k/index"; 313 time(tvec); 314 inc = tvec[1]&077774|01; 315 loop: 316 if(argc>1&&*argv[1]=='-') { 317 switch(argv[1][1]) { 318 case 'i': 319 if(argc>2) 320 info = argv[2]; 321 argc -= 2; 322 argv += 2; 323 goto loop; 324 case 't': 325 tflag = 1; 326 argc--; 327 argv++; 328 goto loop; 329 } 330 } 331 input = fopen(info,"r"); 332 if(input==NULL) { 333 printf("No info\n"); 334 exit(0); 335 } 336 talloc(); 337 if(argc<=2) 338 instruct(info); 339 signal(SIGINT,done); 340 argv[argc] = 0; 341 if(find(&argv[1],argc-1)==0) 342 dunno(); 343 fclose(input); 344 input = fopen(tmp[0],"r"); 345 if(input==NULL) 346 dunno(); 347 readindex(); 348 if(!tflag || na>nl) 349 na = nl; 350 stdout->_flag |= _IONBF; 351 for(;;) { 352 i = next(); 353 fseek(input,xx[i]+0L,0); 354 z = xx[i+1]-xx[i]; 355 for(j=0;j<z;j++) 356 line[j] = getc(input); 357 segment(line,tmp); 358 if(*tmp[select[0]] == '\0' || *tmp[select[1]] == '\0') { 359 score[i] = 1; 360 continue; 361 } 362 publish(tmp[select[0]]); 363 printf("\n"); 364 for(count=0;;count++) { 365 if(query(response)==0) { 366 publish(tmp[select[1]]); 367 printf("\n"); 368 if(count==0) wrongs++; 369 score[i] = tflag?-1:1; 370 break; 371 } 372 x = cmp(response,tmp[select[1]]); 373 if(x>1) badinfo(); 374 if(x==1) { 375 printf("Right!\n"); 376 if(count==0) rights++; 377 if(++score[i]>=1 && na<nl) 378 na++; 379 break; 380 } 381 printf("What?\n"); 382 if(count==0) wrongs++; 383 score[i] = tflag?-1:1; 384 } 385 guesses += count; 386 } 387 } 388 389 query(r) 390 char *r; 391 { 392 char *t; 393 for(t=r;;t++) { 394 if(read(0,t,1)==0) 395 done(); 396 if(*t==' '&&(t==r||t[-1]==' ')) 397 t--; 398 if(*t=='\n') { 399 while(t>r&&t[-1]==' ') 400 *--t = '\n'; 401 break; 402 } 403 } 404 *t = 0; 405 return(t-r); 406 } 407 408 next() 409 { 410 int flag; 411 inc = inc*3125&077777; 412 ptr = (inc>>2)%na; 413 flag = 0; 414 while(score[ptr]>0) 415 if(++ptr>=na) { 416 ptr = 0; 417 if(flag) done(); 418 flag = 1; 419 } 420 return(ptr); 421 } 422 423 done() 424 { 425 printf("\nRights %d, wrongs %d, ", rights, wrongs); 426 if(guesses) 427 printf("extra guesses %d, ", guesses); 428 printf("score %d%%\n",100*rights/(rights+wrongs)); 429 exit(0); 430 } 431 instruct(info) 432 { 433 char *t; 434 int i, n; 435 printf("Subjects:\n\n"); 436 while(readline()) { 437 printf("-"); 438 n = segment(line,tmp); 439 for(i=1;i<n;i++) { 440 printf(" "); 441 publish(tmp[i]); 442 } 443 printf("\n"); 444 } 445 printf("\n"); 446 input = fopen(info,"r"); 447 if(input==NULL) 448 abort(); 449 readline(); 450 segment(line,tmp); 451 printf("For example,\n"); 452 printf(" quiz "); 453 publish(tmp[1]); 454 printf(" "); 455 publish(tmp[2]); 456 printf("\nasks you a "); 457 publish(tmp[1]); 458 printf(" and you answer the "); 459 publish(tmp[2]); 460 printf("\n quiz "); 461 publish(tmp[2]); 462 printf(" "); 463 publish(tmp[1]); 464 printf("\nworks the other way around\n"); 465 printf("\nType empty line to get correct answer.\n"); 466 exit(0); 467 } 468 469 badinfo(){ 470 printf("Bad info %s\n",line); 471 } 472 473 dunno() 474 { 475 printf("I don't know about that\n"); 476 exit(0); 477 } 478