|
|
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.