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