|
|
1.1 root 1: # include <stdio.h>
2:
3: /* Through, `my' refers to the program, `your' to the player */
4:
5: # define CTYPE 13
6: # define CTSIZ (CTYPE+1)
7: # define DECK 52
8: # define NOMORE 0
9: # define DOUBTIT (-1);
10:
11: typedef char HAND[CTSIZ];
12:
13: /* data structures */
14:
15: short debug;
16:
17: HAND myhand;
18: HAND yourhand;
19: char deck[DECK];
20: short nextcd;
21: int proflag;
22:
23: /* utility and output programs */
24:
25: shuffle(){
26: /* shuffle the deck, and reset nextcd */
27: /* uses the random number generator `rand' in the C library */
28: /* assumes that `srand' has already been called */
29:
30: register i;
31:
32: for( i=0; i<DECK; ++i ) deck[i] = (i%13)+1; /* seed the deck */
33:
34: for( i=DECK; i>0; --i ){ /* select the next card at random */
35: deck[i-1] = choose( deck, i );
36: }
37:
38: nextcd = 0;
39: }
40:
41: choose( a, n ) char a[]; {
42: /* pick and return one at random from the n choices in a */
43: /* The last one is moved to replace the one chosen */
44: register j, t;
45:
46: if( n <= 0 ) error( "null choice" );
47:
48: j = rand() % n;
49: t = a[j];
50: a[j] = a[n-1];
51: return(t);
52: }
53:
54: draw() {
55: if( nextcd >= DECK ) return( NOMORE );
56: return( deck[nextcd++] );
57: }
58:
59: error( s ) char *s; {
60: fprintf( stderr, "error: " );
61: fprintf( stderr, s );
62: exit( 1 );
63: }
64:
65: empty( h ) HAND h; {
66: register i;
67:
68: for( i=1; i<=CTYPE; ++i ){
69: if( h[i] != 0 && h[i] != 4 ) return( 0 );
70: }
71: return( i );
72: }
73:
74: mark( cd, hand ) HAND hand; {
75: if( cd != NOMORE ){
76: ++hand[cd];
77: if( hand[cd] > 4 ){
78: error( "mark overflow" );
79: }
80: }
81: return( cd );
82: }
83:
84: deal( hand, n ) HAND hand; {
85: while( n-- ){
86: if( mark( hand, draw() ) == NOMORE ) error( "deck exhausted" );
87: }
88: }
89:
90: char *cname[] = {
91: "NOMORE!!!",
92: "A",
93: "2",
94: "3",
95: "4",
96: "5",
97: "6",
98: "7",
99: "8",
100: "9",
101: "10",
102: "J",
103: "Q",
104: "K",
105: };
106:
107: stats(){
108: register i, ct, b;
109:
110: if( proflag ) printf( "Pro level\n" );
111: b = ct = 0;
112:
113: for( i=1; i<=CTYPE; ++i ){
114: if( myhand[i] == 4 ) ++b;
115: else ct += myhand[i];
116: }
117:
118: if( b ){
119: printf( "My books: " );
120: for( i=1; i<=CTYPE; ++i ){
121: if( myhand[i] == 4 ) printf( "%s ", cname[i] );
122: }
123: printf( "\n" );
124: }
125:
126: if (ct == 1)
127: printf( "%d card in my hand, %d in the pool\n", ct, DECK-nextcd );
128: else
129: printf( "%d cards in my hand, %d in the pool\n", ct, DECK-nextcd );
130: printf( "You ask me for: " );
131: }
132:
133: phand( h ) HAND h; {
134: register i, j;
135:
136: j = 0;
137:
138: for( i = 1; i<= CTYPE; ++i ){
139: if( h[i] == 4 ) {
140: ++j;
141: continue;
142: }
143: if( h[i] ){
144: register k;
145: k = h[i];
146: while( k-- ) printf( "%s ", cname[i] );
147: }
148: }
149:
150: if( j ){
151: printf( "+ Books of " );
152: for( i=1; i<=CTYPE; ++i ){
153: if( h[i] == 4 ) printf( "%s ", cname[i] );
154: }
155: }
156:
157: printf( "\n" );
158: }
159:
160: main( argc, argv ) char * argv[]; {
161: /* initialize shuffling, ask for instructions, play game, die */
162: register c;
163:
164: if( argc > 1 && argv[1][0] == '-' ){
165: while( argv[1][0] == '-' ) { ++argv[1]; ++debug; }
166: argv++;
167: argc--;
168: }
169:
170: srand( getpid() );
171:
172: printf( "instructions?\n" );
173: if( (c=getchar()) != '\n' ){
174: if( c != 'n' ) instruct();
175: while( getchar() != '\n' );
176: }
177:
178: game();
179: }
180:
181: /* print instructions */
182:
183: char *inst[] = {
184: "`Go Fish' is a childrens' card game.",
185: "The Object is to accumulate `books' of 4 cards",
186: "with the same face value.",
187: "The players alternate turns; each turn begins with one",
188: "player selecting a card from his hand, and asking the",
189: "other player for all cards of that face value.",
190: "If the other player has one or more cards of that face value",
191: "in his hand, he gives them to the first player, and the",
192: "first player makes another request.",
193: "Eventually, the first player asks for a card which",
194: "is not in the second player's hand: he replies `GO FISH!'",
195: "The first player then draws a card from the `pool' of",
196: "undealt cards. If this is the card he had last requested, he",
197: "draws again.",
198: "When a book is made, either through drawing or requesting,",
199: "the cards are laid down and no further action takes",
200: "place with that face value.",
201: "To play the computer, simply make guesses by typing",
202: "a, 2, 3, 4, 5, 6, 7, 8, 9, 10, j, q, or k when asked.",
203: "Hitting return gives you information about the size of",
204: "my hand and the pool, and tells you about my books.",
205: "Saying `p' as a first guess puts you into `pro' level;",
206: "The default is pretty dumb!",
207: "Good Luck!",
208: "",
209: };
210:
211: instruct(){
212: register char **cpp;
213:
214: printf( "\n" );
215:
216: for( cpp = inst; **cpp != '\0'; ++cpp ){
217: printf( "%s\n", *cpp );
218: }
219: }
220:
221: game(){
222:
223: shuffle();
224:
225: deal( myhand, 7 );
226: deal( yourhand, 7 );
227:
228: start( myhand );
229:
230: for(;;){
231:
232: register g;
233:
234:
235: /* you make repeated guesses */
236:
237: for(;;) {
238: printf( "your hand is: " );
239: phand( yourhand );
240: printf( "you ask me for: " );
241: if( !move( yourhand, myhand, g=guess(), 0 ) ) break;
242: printf( "Guess again\n" );
243: }
244:
245: /* I make repeated guesses */
246:
247: for(;;) {
248: if( (g=myguess()) != NOMORE ){
249: printf( "I ask you for: %s\n", cname[g] );
250: }
251: if( !move( myhand, yourhand, g, 1 ) ) break;
252: printf( "I get another guess\n" );
253: }
254: }
255: }
256:
257: /* reflect the effect of a move on the hands */
258:
259: move( hs, ht, g, v ) HAND hs, ht; {
260: /* hand hs has made a guess, g, directed towards ht */
261: /* v on indicates that the guess was made by the machine */
262: register d;
263: char *sp, *tp;
264:
265: sp = tp = "I";
266: if( v ) tp = "You";
267: else sp = "You";
268:
269: if( g == NOMORE ){
270: d = draw();
271: if( d == NOMORE ) score();
272: else {
273:
274: printf( "Empty Hand\n" );
275: if( !v ) printf( "You draw %s\n", cname[d] );
276: mark( hs, d );
277: }
278: return( 0 );
279: }
280:
281: if( !v ) heguessed( g );
282:
283: if( hs[g] == 0 ){
284: if( v ) error( "Rotten Guess" );
285: printf( "You don't have any %s's\n", cname[g] );
286: return(1);
287: }
288:
289: if( ht[g] ){ /* successful guess */
290: printf( "%s have %d %s%s\n", tp, ht[g], cname[g], ht[g]>1?"'s":"" );
291: hs[g] += ht[g];
292: ht[g] = 0;
293: if( hs[g] == 4 ) madebook(g);
294: return(1);
295: }
296:
297: /* GO FISH! */
298:
299: printf( "%s say \"GO FISH!\"\n", tp );
300:
301: newdraw:
302: d = draw();
303: if( d == NOMORE ) {
304: printf( "No more cards\n" );
305: return(0);
306: }
307: mark( hs, d );
308: if( !v ) printf( "You draw %s\n", cname[d] );
309: if( hs[d] == 4 ) madebook(d);
310: if( d == g ){
311: printf( "%s drew the guess, so draw again\n", sp );
312: if( !v ) hedrew( d );
313: goto newdraw;
314: }
315: return( 0 );
316: }
317:
318: madebook( x ){
319: printf( "Made a book of %s's\n", cname[x] );
320: }
321:
322: score(){
323: register my, your, i;
324:
325: my = your = 0;
326:
327: printf( "The game is over.\nMy books: " );
328:
329: for( i=1; i<=CTYPE;++i ){
330: if( myhand[i] == 4 ){
331: ++my;
332: printf( "%s ", cname[i] );
333: }
334: }
335:
336: printf( "\nYour books: " );
337:
338: for( i=1; i<=CTYPE;++i ){
339: if( yourhand[i] == 4 ){
340: ++your;
341: printf( "%s ", cname[i] );
342: }
343: }
344:
345: printf( "\n\nI have %d, you have %d\n", my, your );
346:
347: printf( "\n%s win!!!\n", my>your?"I":"You" );
348: exit(0);
349: }
350:
351: # define G(x) { if(go) goto err; else go = x; }
352:
353: guess(){
354: /* get the guess from the tty and return it... */
355: register g, go;
356:
357: go = 0;
358:
359: for(;;) {
360: switch( g = getchar() ){
361:
362: case EOF:
363: score();
364: break;
365: case 'p':
366: case 'P':
367: ++proflag;
368: continue;
369:
370: case '2':
371: case '3':
372: case '4':
373: case '5':
374: case '6':
375: case '7':
376: case '8':
377: case '9':
378: G(g-'0');
379: continue;
380:
381: case 'a':
382: case 'A':
383: G(1);
384: continue;
385:
386: case '1':
387: G(10);
388: continue;
389:
390: case '0':
391: if( go != 10 ) goto err;
392: continue;
393:
394: case 'J':
395: case 'j':
396: G(11);
397: continue;
398:
399: case 'Q':
400: case 'q':
401: G(12);
402: continue;
403:
404: case 'K':
405: case 'k':
406: G(13);
407: continue;
408:
409: case '\n':
410: if( empty( yourhand ) ) return( NOMORE );
411: if( go == 0 ){
412: stats();
413: continue;
414: }
415: return( go );
416:
417: case ' ':
418: case '\t':
419: continue;
420:
421: default:
422: err:
423: while( g != '\n' ) g = getchar();
424: printf( "what?\n" );
425: continue;
426: }
427: }
428: }
429:
430: /* the program's strategy appears from here to the end */
431:
432: char try[100];
433: char ntry;
434: char haveguessed[CTSIZ];
435:
436: char hehas[CTSIZ];
437:
438: start( h ) HAND h; {
439: ;
440: }
441:
442: hedrew( d ){
443: ++hehas[d];
444: }
445:
446: heguessed( d ){
447: ++hehas[d];
448: }
449:
450: myguess(){
451:
452: register i, lg, t;
453:
454: if( empty( myhand ) ) return( NOMORE );
455:
456: /* make a list of those things which i have */
457: /* leave off any which are books */
458: /* if something is found that he has, guess it! */
459:
460: ntry = 0;
461: for( i=1; i<=CTYPE; ++i ){
462: if( myhand[i] == 0 || myhand[i] == 4 ) continue;
463: try[ntry++] = i;
464: }
465:
466: if( !proflag ) goto random;
467:
468: /* get ones he has, if any */
469:
470: for( i=0; i<ntry; ++i ){
471: if( hehas[try[i]] ) {
472: i = try[i];
473: goto gotguess;
474: }
475: }
476:
477: /* is there one that has never been guessed; if so, guess it */
478: lg = 101;
479: for( i=0; i<ntry; ++i ){
480: if( haveguessed[try[i]] < lg ) lg = haveguessed[try[i]];
481: }
482: /* remove all those not guessed longest ago */
483:
484: t = 0;
485: for( i=0; i<ntry; ++i ){
486: if( haveguessed[try[i]] == lg ) try[t++] = try[i];
487: }
488: ntry = t;
489: if( t <= 0 ) error( "bad guessing loop" );
490:
491: random:
492: i = choose( try, ntry ); /* make a random choice */
493:
494: gotguess: /* do bookkeeping */
495:
496: hehas[i] = 0; /* he won't anymore! */
497: for( t=1; t<=CTYPE; ++t ){
498: if( haveguessed[t] ) --haveguessed[t];
499: }
500: haveguessed[i] = 100; /* will have guessed it */
501: return(i);
502:
503: }
504:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.