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