1 2 static char sccsid[] = " quiz.c 4.1 82/10/24 "; 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 for(i=0;i<NF;i++) 295 tmp[i] = malloc(SL); 296 } 297 298 main(argc,argv) 299 char *argv[]; 300 { 301 register j; 302 int i; 303 int x; 304 int z; 305 char *info; 306 int tvec[2]; 307 char *t; 308 extern done(); 309 int count; 310 info = "/usr/games/lib/quiz.k/index"; 311 time(tvec); 312 inc = tvec[1]&077774|01; 313 loop: 314 if(argc>1&&*argv[1]=='-') { 315 switch(argv[1][1]) { 316 case 'i': 317 if(argc>2) 318 info = argv[2]; 319 argc -= 2; 320 argv += 2; 321 goto loop; 322 case 't': 323 tflag = 1; 324 argc--; 325 argv++; 326 goto loop; 327 } 328 } 329 input = fopen(info,"r"); 330 if(input==NULL) { 331 printf("No info\n"); 332 exit(0); 333 } 334 talloc(); 335 if(argc<=2) 336 instruct(info); 337 signal(SIGINT,done); 338 argv[argc] = 0; 339 if(find(&argv[1],argc-1)==0) 340 dunno(); 341 fclose(input); 342 input = fopen(tmp[0],"r"); 343 if(input==NULL) 344 dunno(); 345 readindex(); 346 if(!tflag || na>nl) 347 na = nl; 348 stdout->_flag |= _IONBF; 349 for(;;) { 350 i = next(); 351 fseek(input,xx[i]+0L,0); 352 z = xx[i+1]-xx[i]; 353 for(j=0;j<z;j++) 354 line[j] = getc(input); 355 segment(line,tmp); 356 if(*tmp[select[0]] == '\0' || *tmp[select[1]] == '\0') { 357 score[i] = 1; 358 continue; 359 } 360 publish(tmp[select[0]]); 361 printf("\n"); 362 for(count=0;;count++) { 363 if(query(response)==0) { 364 publish(tmp[select[1]]); 365 printf("\n"); 366 if(count==0) wrongs++; 367 score[i] = tflag?-1:1; 368 break; 369 } 370 x = cmp(response,tmp[select[1]]); 371 if(x>1) badinfo(); 372 if(x==1) { 373 printf("Right!\n"); 374 if(count==0) rights++; 375 if(++score[i]>=1 && na<nl) 376 na++; 377 break; 378 } 379 printf("What?\n"); 380 if(count==0) wrongs++; 381 score[i] = tflag?-1:1; 382 } 383 guesses += count; 384 } 385 } 386 387 query(r) 388 char *r; 389 { 390 char *t; 391 for(t=r;;t++) { 392 if(read(0,t,1)==0) 393 done(); 394 if(*t==' '&&(t==r||t[-1]==' ')) 395 t--; 396 if(*t=='\n') { 397 while(t>r&&t[-1]==' ') 398 *--t = '\n'; 399 break; 400 } 401 } 402 *t = 0; 403 return(t-r); 404 } 405 406 next() 407 { 408 int flag; 409 inc = inc*3125&077777; 410 ptr = (inc>>2)%na; 411 flag = 0; 412 while(score[ptr]>0) 413 if(++ptr>=na) { 414 ptr = 0; 415 if(flag) done(); 416 flag = 1; 417 } 418 return(ptr); 419 } 420 421 done() 422 { 423 printf("\nRights %d, wrongs %d, ", rights, wrongs); 424 if(guesses) 425 printf("extra guesses %d, ", guesses); 426 printf("score %d%%\n",100*rights/(rights+wrongs)); 427 exit(0); 428 } 429 instruct(info) 430 { 431 char *t; 432 int i, n; 433 printf("Subjects:\n\n"); 434 while(readline()) { 435 printf("-"); 436 n = segment(line,tmp); 437 for(i=1;i<n;i++) { 438 printf(" "); 439 publish(tmp[i]); 440 } 441 printf("\n"); 442 } 443 printf("\n"); 444 input = fopen(info,"r"); 445 if(input==NULL) 446 abort(); 447 readline(); 448 segment(line,tmp); 449 printf("For example,\n"); 450 printf(" quiz "); 451 publish(tmp[1]); 452 printf(" "); 453 publish(tmp[2]); 454 printf("\nasks you a "); 455 publish(tmp[1]); 456 printf(" and you answer the "); 457 publish(tmp[2]); 458 printf("\n quiz "); 459 publish(tmp[2]); 460 printf(" "); 461 publish(tmp[1]); 462 printf("\nworks the other way around\n"); 463 printf("\nType empty line to get correct answer.\n"); 464 exit(0); 465 } 466 467 badinfo(){ 468 printf("Bad info %s\n",line); 469 } 470 471 dunno() 472 { 473 printf("I don't know about that\n"); 474 exit(0); 475 } 476