|
|
1.1 root 1: /*
2: * Guess -- like 20 questions.
3: *
4: * (NOTE: /usr/games/guess should be setuid to `games'.
5: * /usr/games/lib/guess.db should be owned by `games')
6: */
7:
8: #include <stdio.h>
9:
10: #define NLINE 128 /* Length of various input buffers */
11:
12: struct node{
13: char *question;
14: struct node *yes, *no; /* if yes==NULL, this is a leaf node */
15: };
16: struct node cow = { "a cow", NULL };
17: struct node *game = { &cow };
18: char *dbname = "/usr/games/lib/guess.db";
19: char line[NLINE], question[NLINE];
20:
21: char *
22: copy(s)
23: register char *s;
24: {
25: register char *t, *v;
26: int l;
27: for(l=0,t=s;*t++;l++);
28: v=t=malloc(l+1);
29: if(v==NULL){
30: printf("Out of space in copy\n");
31: leave();
32: }
33: do;while(*t++ = *s++);
34: return(v);
35: }
36:
37: char *
38: freads(f, s)
39: FILE *f;
40: register char *s;
41: {
42: register char *v;
43: if(fgets(s, NLINE, f)==NULL)
44: return(NULL);
45: v=s;
46: while(*s!='\n' && *s!='\0')
47: s++;
48: *s='\0';
49: return(v);
50: }
51: readdb(){
52: register c;
53: register struct node *p;
54: FILE *f;
55: int message = 0;
56: if((f=fopen(dbname, "r"))==NULL)
57: return;
58: if(freads(f, line)==NULL){
59: fclose(f);
60: return;
61: }
62: game->question=copy(line);
63: for(;;){
64: p=game;
65: while((c=getc(f))=='y' || c=='n'){
66: if(p->yes==NULL){
67: p->yes=malloc(sizeof(struct node));
68: p->no=malloc(sizeof(struct node));
69: if(p->yes==NULL || p->no==NULL){
70: printf("Out of space in dbread\n");
71: exit(1);
72: }
73: p->yes->question="a corrupt database";
74: p->yes->yes=NULL;
75: p->no->question="a corrupt database";
76: p->no->yes=NULL;
77: }
78: if(c=='y')
79: p=p->yes;
80: else
81: p=p->no;
82: }
83: if(c==EOF)
84: break;
85: if(c!=':' && !message){
86: printf("Invalid database\n");
87: message++;
88: }
89: freads(f, line);
90: p->question=copy(line);
91: }
92: fclose(f);
93: }
94: writedb(p, f, level)
95: struct node *p;
96: FILE *f;
97: {
98: fprintf(f, "%s\n", p->question);
99: if(p->yes){
100: line[level]='y';
101: line[level+1]='\0';
102: fprintf(f, "%s:", line);
103: writedb(p->yes, f, level+1);
104: line[level]='n';
105: line[level+1]='\0';
106: fprintf(f, "%s:", line);
107: writedb(p->no, f, level+1);
108: }
109: }
110: leave(){
111: FILE *f;
112: if((f=fopen(dbname, "w"))==NULL){
113: printf("Can't create the database\n");
114: exit(1);
115: }
116: writedb(game, f, 0);
117: exit(0);
118: }
119: main(argc, argv)
120: char *argv[];
121: {
122: register struct node *p;
123: register c;
124: if(argc>1)
125: dbname=argv[1];
126: readdb();
127: for(;;){
128: printf("Think of something.\n");
129: p=game;
130: while(p->yes){
131: for(;;){
132: printf("%s? ", p->question);
133: c=answer();
134: if(c=='y'){
135: p=p->yes;
136: break;
137: }
138: if(c=='n'){
139: p=p->no;
140: break;
141: }
142: printf("Answer yes or no.\n");
143: }
144: }
145: for(;;){
146: printf("Is %s what you're thinking of? ", p->question);
147: c=answer();
148: if(c=='y')
149: break;
150: if(c=='n'){
151: printf("I give up. What are you thinking of? ");
152: if(gets(line)==NULL)
153: leave();
154: printf("What is a yes-or-no answer question to distinguish %s from %s? ", p->question, line);
155: if(gets(question)==NULL)
156: leave();
157: for(;;){
158: printf("What is the answer for %s? ", line);
159: c=answer();
160: if(c=='y' || c=='n')
161: break;
162: printf("Answer yes or no.\n");
163: }
164: p->yes=malloc(sizeof(struct node));
165: p->no=malloc(sizeof(struct node));
166: if(p->yes==NULL || p->no==NULL){
167: printf("Out of space\n");
168: leave();
169: }
170: if(c=='y'){
171: p->yes->question=copy(line);
172: p->no->question=p->question;
173: }
174: else{
175: p->yes->question=p->question;
176: p->no->question=copy(line);
177: }
178: p->question=copy(question);
179: p->yes->yes=NULL;
180: p->no->yes=NULL;
181: break;
182: }
183: printf("Answer yes or no.\n");
184: }
185: }
186: }
187:
188: answer()
189: {
190: char buf[NLINE];
191:
192: if(gets(buf)==NULL)
193: leave();
194: return(buf[0]);
195: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.