18867Smckusick 2*33196Sbostic static char sccsid[] = " quiz.c 4.4 88/01/02 "; 38867Smckusick 48867Smckusick #include <stdio.h> 58867Smckusick #include <signal.h> 68867Smckusick #define NF 10 78867Smckusick #define NL 300 88867Smckusick #define NC 200 98867Smckusick #define SL 100 108867Smckusick #define NA 10 118867Smckusick 128867Smckusick int tflag; 138867Smckusick int xx[NL]; 148867Smckusick char score[NL]; 158867Smckusick int rights; 168867Smckusick int wrongs; 178867Smckusick int guesses; 188867Smckusick FILE *input; 198867Smckusick int nl = 0; 208867Smckusick int na = NA; 218867Smckusick int inc; 228867Smckusick int ptr = 0; 238867Smckusick int nc = 0; 248867Smckusick char line[150]; 258867Smckusick char response[100]; 268867Smckusick char *tmp[NF]; 278867Smckusick int select[NF]; 288867Smckusick 298867Smckusick readline() 308867Smckusick { 31*33196Sbostic register int ch; 328867Smckusick char *t; 338867Smckusick loop: 34*33196Sbostic for(t=line;(ch=getc(input))!=-1;t++) { 35*33196Sbostic *t = ch; 368867Smckusick nc++; 378867Smckusick if(*t==' '&&(t==line||t[-1]==' ')) 388867Smckusick t--; 398867Smckusick if(*t=='\n') { 408867Smckusick if(t[-1]=='\\') /*inexact test*/ 418867Smckusick continue; 428867Smckusick while(t>line&&t[-1]==' ') 438867Smckusick *--t = '\n'; 448867Smckusick *++t = 0; 458867Smckusick return(1); 468867Smckusick } 478867Smckusick if(t-line>=NC) { 488867Smckusick printf("Too hard for me\n"); 498867Smckusick do { 50*33196Sbostic if ((ch = getc(input)) == EOF) 518867Smckusick return(0); 52*33196Sbostic } while(ch!='\n'); 53*33196Sbostic *line = '\n'; 548867Smckusick goto loop; 558867Smckusick } 568867Smckusick } 578867Smckusick return(0); 588867Smckusick } 598867Smckusick 608867Smckusick char *eu; 618867Smckusick char *ev; 628867Smckusick cmp(u,v) 638867Smckusick char *u,*v; 648867Smckusick { 658867Smckusick int x; 668867Smckusick eu = u; 678867Smckusick ev = v; 688867Smckusick x = disj(1); 698867Smckusick if(x!=1) 708867Smckusick return(x); 718867Smckusick return(eat(1,0)); 728867Smckusick } 738867Smckusick 748867Smckusick disj(s) 758867Smckusick { 768867Smckusick int t, x; 778867Smckusick char *u; 788867Smckusick u = eu; 798867Smckusick t = 0; 808867Smckusick for(;;) { 818867Smckusick x = string(s); 828867Smckusick if(x>1) 838867Smckusick return(x); 848867Smckusick switch(*ev) { 858867Smckusick case 0: 868867Smckusick case ']': 878867Smckusick case '}': 888867Smckusick return(t|x&s); 898867Smckusick case '|': 908867Smckusick ev++; 918867Smckusick t |= s; 928867Smckusick s = 0; 938867Smckusick continue; 948867Smckusick } 958867Smckusick if(s) eu = u; 968867Smckusick if(string(0)>1) 978867Smckusick return(2); 988867Smckusick switch(*ev) { 998867Smckusick case 0: 1008867Smckusick case ']': 1018867Smckusick return(0); 1028867Smckusick case '}': 1038867Smckusick return(1); 1048867Smckusick case '|': 1058867Smckusick ev++; 1068867Smckusick continue; 1078867Smckusick default: 1088867Smckusick return(2); 1098867Smckusick } 1108867Smckusick } 1118867Smckusick } 1128867Smckusick 1138867Smckusick string(s) 1148867Smckusick { 1158867Smckusick int x; 1168867Smckusick for(;;) { 1178867Smckusick switch(*ev) { 1188867Smckusick case 0: 1198867Smckusick case '|': 1208867Smckusick case ']': 1218867Smckusick case '}': 1228867Smckusick return(1); 1238867Smckusick case '\\': 1248867Smckusick ev++; 1258867Smckusick if(*ev==0) 1268867Smckusick return(2); 1278867Smckusick if(*ev=='\n') { 1288867Smckusick ev++; 1298867Smckusick continue; 1308867Smckusick } 1318867Smckusick default: 1328867Smckusick if(eat(s,*ev)==1) 1338867Smckusick continue; 1348867Smckusick return(0); 1358867Smckusick case '[': 1368867Smckusick ev++; 1378867Smckusick x = disj(s); 1388867Smckusick if(*ev!=']' || x>1) 1398867Smckusick return(2); 1408867Smckusick ev++; 1418867Smckusick if(s==0) 1428867Smckusick continue; 1438867Smckusick if(x==0) 1448867Smckusick return(0); 1458867Smckusick continue; 1468867Smckusick case '{': 1478867Smckusick ev++; 1488867Smckusick x = disj(s); 1498867Smckusick if(*ev!='}'||x>1) 1508867Smckusick return(2); 1518867Smckusick ev++; 1528867Smckusick continue; 1538867Smckusick } 1548867Smckusick } 1558867Smckusick } 1568867Smckusick 1578867Smckusick eat(s,c) 1588867Smckusick char c; 1598867Smckusick { 1608867Smckusick if(*ev!=c) 1618867Smckusick return(2); 1628867Smckusick if(s==0) { 1638867Smckusick ev++; 1648867Smckusick return(1); 1658867Smckusick } 1668867Smckusick if(fold(*eu)!=fold(c)) 1678867Smckusick return(0); 1688867Smckusick eu++; 1698867Smckusick ev++; 1708867Smckusick return(1); 1718867Smckusick } 1728867Smckusick 1738867Smckusick fold(c) 1748867Smckusick char c; 1758867Smckusick { 1768867Smckusick if(c<'A'||c>'Z') 1778867Smckusick return(c); 1788867Smckusick return(c|040); 1798867Smckusick } 1808867Smckusick 1818867Smckusick publish(t) 1828867Smckusick char *t; 1838867Smckusick { 1848867Smckusick ev = t; 1858867Smckusick pub1(1); 1868867Smckusick } 1878867Smckusick 1888867Smckusick pub1(s) 1898867Smckusick { 1908867Smckusick for(;;ev++){ 1918867Smckusick switch(*ev) { 1928867Smckusick case '|': 1938867Smckusick s = 0; 1948867Smckusick ev; 1958867Smckusick continue; 1968867Smckusick case ']': 1978867Smckusick case '}': 1988867Smckusick case 0: 1998867Smckusick return; 2008867Smckusick case '[': 2018867Smckusick case '{': 2028867Smckusick ev++; 2038867Smckusick pub1(s); 2048867Smckusick ev; 2058867Smckusick continue; 2068867Smckusick case '\\': 2078867Smckusick if(*++ev=='\n') 2088867Smckusick continue; 2098867Smckusick default: 2108867Smckusick if(s) 2118867Smckusick putchar(*ev); 2128867Smckusick } 2138867Smckusick } 2148867Smckusick } 2158867Smckusick 2168867Smckusick segment(u,w) 2178867Smckusick char *u, *w[]; 2188867Smckusick { 2198867Smckusick char *s; 2208867Smckusick int i; 2218867Smckusick char *t; 2228867Smckusick s = u; 2238867Smckusick for(i=0;i<NF;i++) { 2248867Smckusick u = s; 2258867Smckusick t = w[i]; 2268867Smckusick while(*s!=':'&&*s!='\n'&&s-u<SL) { 2278867Smckusick if(*s=='\\') { 2288867Smckusick if(s[1] == '\n') { 2298867Smckusick s += 2; 2308867Smckusick continue; 2318867Smckusick } 2328867Smckusick *t++ = *s++; 2338867Smckusick } 2348867Smckusick *t++ = *s++; 2358867Smckusick } 2368867Smckusick 2378867Smckusick while(*s!=':'&&*s!='\n') 2388867Smckusick s++; 2398867Smckusick *t = 0; 2408867Smckusick if(*s++=='\n') { 2418867Smckusick return(i+1); 2428867Smckusick } 2438867Smckusick } 2448867Smckusick printf("Too many facts about one thing\n"); 2458867Smckusick } 2468867Smckusick 2478867Smckusick perm(u,m,v,n,p) 2488867Smckusick int p[]; 2498867Smckusick char *u[], *v[]; 2508867Smckusick { 2518867Smckusick int i, j; 2528867Smckusick int x; 2538867Smckusick for(i=0;i<m;i++) { 2548867Smckusick for(j=0;j<n;j++) { 2558867Smckusick x = cmp(u[i],v[j]); 2568867Smckusick if(x>1) badinfo(); 2578867Smckusick if(x==0) 2588867Smckusick continue; 2598867Smckusick p[i] = j; 2608867Smckusick goto uloop; 2618867Smckusick } 2628867Smckusick return(0); 2638867Smckusick uloop: ; 2648867Smckusick } 2658867Smckusick return(1); 2668867Smckusick } 2678867Smckusick 2688867Smckusick find(u,m) 2698867Smckusick char *u[]; 2708867Smckusick { 2718867Smckusick int n; 2728867Smckusick while(readline()){ 2738867Smckusick n = segment(line,tmp); 2748867Smckusick if(perm(u,m,tmp+1,n-1,select)) 2758867Smckusick return(1); 2768867Smckusick } 2778867Smckusick return(0); 2788867Smckusick } 2798867Smckusick 2808867Smckusick readindex() 2818867Smckusick { 2828867Smckusick xx[0] = nc = 0; 2838867Smckusick while(readline()) { 2848867Smckusick xx[++nl] = nc; 2858867Smckusick if(nl>=NL) { 2868867Smckusick printf("I've forgotten some of it;\n"); 2878867Smckusick printf("I remember %d items.\n", nl); 2888867Smckusick break; 2898867Smckusick } 2908867Smckusick } 2918867Smckusick } 2928867Smckusick 2938867Smckusick talloc() 2948867Smckusick { 2958867Smckusick int i; 29617680Sralph char *malloc(); 29717680Sralph 2988867Smckusick for(i=0;i<NF;i++) 2998867Smckusick tmp[i] = malloc(SL); 3008867Smckusick } 3018867Smckusick 3028867Smckusick main(argc,argv) 3038867Smckusick char *argv[]; 3048867Smckusick { 3058867Smckusick register j; 3068867Smckusick int i; 3078867Smckusick int x; 3088867Smckusick int z; 3098867Smckusick char *info; 3108867Smckusick int tvec[2]; 3118867Smckusick char *t; 3128867Smckusick extern done(); 3138867Smckusick int count; 3148867Smckusick info = "/usr/games/lib/quiz.k/index"; 3158867Smckusick time(tvec); 3168867Smckusick inc = tvec[1]&077774|01; 3178867Smckusick loop: 3188867Smckusick if(argc>1&&*argv[1]=='-') { 3198867Smckusick switch(argv[1][1]) { 3208867Smckusick case 'i': 3218867Smckusick if(argc>2) 3228867Smckusick info = argv[2]; 3238867Smckusick argc -= 2; 3248867Smckusick argv += 2; 3258867Smckusick goto loop; 3268867Smckusick case 't': 3278867Smckusick tflag = 1; 3288867Smckusick argc--; 3298867Smckusick argv++; 3308867Smckusick goto loop; 3318867Smckusick } 3328867Smckusick } 3338867Smckusick input = fopen(info,"r"); 3348867Smckusick if(input==NULL) { 3358867Smckusick printf("No info\n"); 3368867Smckusick exit(0); 3378867Smckusick } 3388867Smckusick talloc(); 3398867Smckusick if(argc<=2) 3408867Smckusick instruct(info); 3418867Smckusick signal(SIGINT,done); 3428867Smckusick argv[argc] = 0; 3438867Smckusick if(find(&argv[1],argc-1)==0) 3448867Smckusick dunno(); 3458867Smckusick fclose(input); 3468867Smckusick input = fopen(tmp[0],"r"); 3478867Smckusick if(input==NULL) 3488867Smckusick dunno(); 3498867Smckusick readindex(); 3508867Smckusick if(!tflag || na>nl) 3518867Smckusick na = nl; 3528867Smckusick stdout->_flag |= _IONBF; 3538867Smckusick for(;;) { 3548867Smckusick i = next(); 3558867Smckusick fseek(input,xx[i]+0L,0); 3568867Smckusick z = xx[i+1]-xx[i]; 3578867Smckusick for(j=0;j<z;j++) 3588867Smckusick line[j] = getc(input); 3598867Smckusick segment(line,tmp); 3608867Smckusick if(*tmp[select[0]] == '\0' || *tmp[select[1]] == '\0') { 3618867Smckusick score[i] = 1; 3628867Smckusick continue; 3638867Smckusick } 3648867Smckusick publish(tmp[select[0]]); 3658867Smckusick printf("\n"); 3668867Smckusick for(count=0;;count++) { 3678867Smckusick if(query(response)==0) { 3688867Smckusick publish(tmp[select[1]]); 3698867Smckusick printf("\n"); 3708867Smckusick if(count==0) wrongs++; 3718867Smckusick score[i] = tflag?-1:1; 3728867Smckusick break; 3738867Smckusick } 3748867Smckusick x = cmp(response,tmp[select[1]]); 3758867Smckusick if(x>1) badinfo(); 3768867Smckusick if(x==1) { 3778867Smckusick printf("Right!\n"); 3788867Smckusick if(count==0) rights++; 3798867Smckusick if(++score[i]>=1 && na<nl) 3808867Smckusick na++; 3818867Smckusick break; 3828867Smckusick } 3838867Smckusick printf("What?\n"); 3848867Smckusick if(count==0) wrongs++; 3858867Smckusick score[i] = tflag?-1:1; 3868867Smckusick } 3878867Smckusick guesses += count; 3888867Smckusick } 3898867Smckusick } 3908867Smckusick 3918867Smckusick query(r) 3928867Smckusick char *r; 3938867Smckusick { 3948867Smckusick char *t; 3958867Smckusick for(t=r;;t++) { 3968867Smckusick if(read(0,t,1)==0) 3978867Smckusick done(); 3988867Smckusick if(*t==' '&&(t==r||t[-1]==' ')) 3998867Smckusick t--; 4008867Smckusick if(*t=='\n') { 4018867Smckusick while(t>r&&t[-1]==' ') 4028867Smckusick *--t = '\n'; 4038867Smckusick break; 4048867Smckusick } 4058867Smckusick } 4068867Smckusick *t = 0; 4078867Smckusick return(t-r); 4088867Smckusick } 4098867Smckusick 4108867Smckusick next() 4118867Smckusick { 4128867Smckusick int flag; 4138867Smckusick inc = inc*3125&077777; 4148867Smckusick ptr = (inc>>2)%na; 4158867Smckusick flag = 0; 4168867Smckusick while(score[ptr]>0) 4178867Smckusick if(++ptr>=na) { 4188867Smckusick ptr = 0; 4198867Smckusick if(flag) done(); 4208867Smckusick flag = 1; 4218867Smckusick } 4228867Smckusick return(ptr); 4238867Smckusick } 4248867Smckusick 4258867Smckusick done() 4268867Smckusick { 42731539Sbostic if (rights + wrongs) { 42831539Sbostic printf("\nRights %d, wrongs %d, ", rights, wrongs); 42931539Sbostic if (guesses) 43031539Sbostic printf("extra guesses %d, ", guesses); 43131539Sbostic printf("score %d%%\n",100 * rights / (rights + wrongs)); 43231539Sbostic } 4338867Smckusick exit(0); 4348867Smckusick } 4358867Smckusick instruct(info) 4368867Smckusick { 4378867Smckusick char *t; 4388867Smckusick int i, n; 4398867Smckusick printf("Subjects:\n\n"); 4408867Smckusick while(readline()) { 4418867Smckusick printf("-"); 4428867Smckusick n = segment(line,tmp); 4438867Smckusick for(i=1;i<n;i++) { 4448867Smckusick printf(" "); 4458867Smckusick publish(tmp[i]); 4468867Smckusick } 4478867Smckusick printf("\n"); 4488867Smckusick } 4498867Smckusick printf("\n"); 4508867Smckusick input = fopen(info,"r"); 4518867Smckusick if(input==NULL) 4528867Smckusick abort(); 4538867Smckusick readline(); 4548867Smckusick segment(line,tmp); 4558867Smckusick printf("For example,\n"); 4568867Smckusick printf(" quiz "); 4578867Smckusick publish(tmp[1]); 4588867Smckusick printf(" "); 4598867Smckusick publish(tmp[2]); 4608867Smckusick printf("\nasks you a "); 4618867Smckusick publish(tmp[1]); 4628867Smckusick printf(" and you answer the "); 4638867Smckusick publish(tmp[2]); 4648867Smckusick printf("\n quiz "); 4658867Smckusick publish(tmp[2]); 4668867Smckusick printf(" "); 4678867Smckusick publish(tmp[1]); 4688867Smckusick printf("\nworks the other way around\n"); 4698867Smckusick printf("\nType empty line to get correct answer.\n"); 4708867Smckusick exit(0); 4718867Smckusick } 4728867Smckusick 4738867Smckusick badinfo(){ 4748867Smckusick printf("Bad info %s\n",line); 4758867Smckusick } 4768867Smckusick 4778867Smckusick dunno() 4788867Smckusick { 4798867Smckusick printf("I don't know about that\n"); 4808867Smckusick exit(0); 4818867Smckusick } 482