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