|
|
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.1 (Berkeley) 5/29/85";
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( cd, hand ) 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: start( myhand );
237:
238: for(;;){
239:
240: register g;
241:
242:
243: /* you make repeated guesses */
244:
245: for(;;) {
246: printf( "your hand is: " );
247: phand( yourhand );
248: printf( "you ask me for: " );
249: if( !move( yourhand, myhand, g=guess(), 0 ) ) break;
250: printf( "Guess again\n" );
251: }
252:
253: /* I make repeated guesses */
254:
255: for(;;) {
256: if( (g=myguess()) != NOMORE ){
257: printf( "I ask you for: %s\n", cname[g] );
258: }
259: if( !move( myhand, yourhand, g, 1 ) ) break;
260: printf( "I get another guess\n" );
261: }
262: }
263: }
264:
265: /* reflect the effect of a move on the hands */
266:
267: move( hs, ht, g, v ) HAND hs, ht; {
268: /* hand hs has made a guess, g, directed towards ht */
269: /* v on indicates that the guess was made by the machine */
270: register d;
271: char *sp, *tp;
272:
273: sp = tp = "I";
274: if( v ) tp = "You";
275: else sp = "You";
276:
277: if( g == NOMORE ){
278: d = draw();
279: if( d == NOMORE ) score();
280: else {
281:
282: printf( "Empty Hand\n" );
283: if( !v ) printf( "You draw %s\n", cname[d] );
284: mark( hs, d );
285: }
286: return( 0 );
287: }
288:
289: if( !v ) heguessed( g );
290:
291: if( hs[g] == 0 ){
292: if( v ) error( "Rotten Guess" );
293: printf( "You don't have any %s's\n", cname[g] );
294: return(1);
295: }
296:
297: if( ht[g] ){ /* successful guess */
298: printf( "%s have %d %s%s\n", tp, ht[g], cname[g], ht[g]>1?"'s":"" );
299: hs[g] += ht[g];
300: ht[g] = 0;
301: if( hs[g] == 4 ) madebook(g);
302: return(1);
303: }
304:
305: /* GO FISH! */
306:
307: printf( "%s say \"GO FISH!\"\n", tp );
308:
309: newdraw:
310: d = draw();
311: if( d == NOMORE ) {
312: printf( "No more cards\n" );
313: return(0);
314: }
315: mark( hs, d );
316: if( !v ) printf( "You draw %s\n", cname[d] );
317: if( hs[d] == 4 ) madebook(d);
318: if( d == g ){
319: printf( "%s drew the guess, so draw again\n", sp );
320: if( !v ) hedrew( d );
321: goto newdraw;
322: }
323: return( 0 );
324: }
325:
326: madebook( x ){
327: printf( "Made a book of %s's\n", cname[x] );
328: }
329:
330: score(){
331: register my, your, i;
332:
333: my = your = 0;
334:
335: printf( "The game is over.\nMy books: " );
336:
337: for( i=1; i<=CTYPE;++i ){
338: if( myhand[i] == 4 ){
339: ++my;
340: printf( "%s ", cname[i] );
341: }
342: }
343:
344: printf( "\nYour books: " );
345:
346: for( i=1; i<=CTYPE;++i ){
347: if( yourhand[i] == 4 ){
348: ++your;
349: printf( "%s ", cname[i] );
350: }
351: }
352:
353: printf( "\n\nI have %d, you have %d\n", my, your );
354:
355: printf( "\n%s win!!!\n", my>your?"I":"You" );
356: exit(0);
357: }
358:
359: # define G(x) { if(go) goto err; else go = x; }
360:
361: guess(){
362: /* get the guess from the tty and return it... */
363: register g, go;
364:
365: go = 0;
366:
367: for(;;) {
368: switch( g = getchar() ){
369:
370: case 'p':
371: case 'P':
372: ++proflag;
373: continue;
374:
375: case '2':
376: case '3':
377: case '4':
378: case '5':
379: case '6':
380: case '7':
381: case '8':
382: case '9':
383: G(g-'0');
384: continue;
385:
386: case 'a':
387: case 'A':
388: G(1);
389: continue;
390:
391: case '1':
392: G(10);
393: continue;
394:
395: case '0':
396: if( go != 10 ) goto err;
397: continue;
398:
399: case 'J':
400: case 'j':
401: G(11);
402: continue;
403:
404: case 'Q':
405: case 'q':
406: G(12);
407: continue;
408:
409: case 'K':
410: case 'k':
411: G(13);
412: continue;
413:
414: case '\n':
415: if( empty( yourhand ) ) return( NOMORE );
416: if( go == 0 ){
417: stats();
418: continue;
419: }
420: return( go );
421:
422: case ' ':
423: case '\t':
424: continue;
425:
426: default:
427: err:
428: while( g != '\n' ) g = getchar();
429: printf( "what?\n" );
430: continue;
431: }
432: }
433: }
434:
435: /* the program's strategy appears from here to the end */
436:
437: char try[100];
438: char ntry;
439: char haveguessed[CTSIZ];
440:
441: char hehas[CTSIZ];
442:
443: start( h ) HAND h; {
444: ;
445: }
446:
447: hedrew( d ){
448: ++hehas[d];
449: }
450:
451: heguessed( d ){
452: ++hehas[d];
453: }
454:
455: myguess(){
456:
457: register i, lg, t;
458:
459: if( empty( myhand ) ) return( NOMORE );
460:
461: /* make a list of those things which i have */
462: /* leave off any which are books */
463: /* if something is found that he has, guess it! */
464:
465: ntry = 0;
466: for( i=1; i<=CTYPE; ++i ){
467: if( myhand[i] == 0 || myhand[i] == 4 ) continue;
468: try[ntry++] = i;
469: }
470:
471: if( !proflag ) goto random;
472:
473: /* get ones he has, if any */
474:
475: for( i=0; i<ntry; ++i ){
476: if( hehas[try[i]] ) {
477: i = try[i];
478: goto gotguess;
479: }
480: }
481:
482: /* is there one that has never been guessed; if so, guess it */
483: lg = 101;
484: for( i=0; i<ntry; ++i ){
485: if( haveguessed[try[i]] < lg ) lg = haveguessed[try[i]];
486: }
487: /* remove all those not guessed longest ago */
488:
489: t = 0;
490: for( i=0; i<ntry; ++i ){
491: if( haveguessed[try[i]] == lg ) try[t++] = try[i];
492: }
493: ntry = t;
494: if( t <= 0 ) error( "bad guessing loop" );
495:
496: random:
497: i = choose( try, ntry ); /* make a random choice */
498:
499: gotguess: /* do bookkeeping */
500:
501: hehas[i] = 0; /* he won't anymore! */
502: for( t=1; t<=CTYPE; ++t ){
503: if( haveguessed[t] ) --haveguessed[t];
504: }
505: haveguessed[i] = 100; /* will have guessed it */
506: return(i);
507:
508: }
509:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.