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