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: }