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