1 /*- 2 * Copyright (c) 1990, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * Muffy Barkocy. 7 * 8 * %sccs.include.redist.c% 9 */ 10 11 #ifndef lint 12 static char copyright[] = 13 "@(#) Copyright (c) 1990, 1993\n\ 14 The Regents of the University of California. All rights reserved.\n"; 15 #endif /* not lint */ 16 17 #ifndef lint 18 static char sccsid[] = "@(#)fish.c 8.1 (Berkeley) 05/31/93"; 19 #endif /* not lint */ 20 21 #include <sys/types.h> 22 #include <sys/errno.h> 23 #include <fcntl.h> 24 #include <stdio.h> 25 #include <stdlib.h> 26 #include <string.h> 27 #include "pathnames.h" 28 29 #define RANKS 13 30 #define HANDSIZE 7 31 #define CARDS 4 32 33 #define USER 1 34 #define COMPUTER 0 35 #define OTHER(a) (1 - (a)) 36 37 char *cards[] = { 38 "A", "2", "3", "4", "5", "6", "7", 39 "8", "9", "10", "J", "Q", "K", NULL, 40 }; 41 #define PRC(card) (void)printf(" %s", cards[card]) 42 43 int promode; 44 int asked[RANKS], comphand[RANKS], deck[RANKS]; 45 int userasked[RANKS], userhand[RANKS]; 46 47 main(argc, argv) 48 int argc; 49 char **argv; 50 { 51 int ch, move; 52 53 while ((ch = getopt(argc, argv, "p")) != EOF) 54 switch(ch) { 55 case 'p': 56 promode = 1; 57 break; 58 case '?': 59 default: 60 (void)fprintf(stderr, "usage: fish [-p]\n"); 61 exit(1); 62 } 63 64 srandom(time((time_t *)NULL)); 65 instructions(); 66 init(); 67 68 if (nrandom(2) == 1) { 69 printplayer(COMPUTER); 70 (void)printf("get to start.\n"); 71 goto istart; 72 } 73 printplayer(USER); 74 (void)printf("get to start.\n"); 75 76 for (;;) { 77 move = usermove(); 78 if (!comphand[move]) { 79 if (gofish(move, USER, userhand)) 80 continue; 81 } else { 82 goodmove(USER, move, userhand, comphand); 83 continue; 84 } 85 86 istart: for (;;) { 87 move = compmove(); 88 if (!userhand[move]) { 89 if (!gofish(move, COMPUTER, comphand)) 90 break; 91 } else 92 goodmove(COMPUTER, move, comphand, userhand); 93 } 94 } 95 /* NOTREACHED */ 96 } 97 98 usermove() 99 { 100 register int n; 101 register char **p; 102 char buf[256]; 103 104 (void)printf("\nYour hand is:"); 105 printhand(userhand); 106 107 for (;;) { 108 (void)printf("You ask me for: "); 109 (void)fflush(stdout); 110 if (fgets(buf, BUFSIZ, stdin) == NULL) 111 exit(0); 112 if (buf[0] == '\0') 113 continue; 114 if (buf[0] == '\n') { 115 (void)printf("%d cards in my hand, %d in the pool.\n", 116 countcards(comphand), countcards(deck)); 117 (void)printf("My books:"); 118 (void)countbooks(comphand); 119 continue; 120 } 121 buf[strlen(buf) - 1] = '\0'; 122 if (!strcasecmp(buf, "p") && !promode) { 123 promode = 1; 124 (void)printf("Entering pro mode.\n"); 125 continue; 126 } 127 if (!strcasecmp(buf, "quit")) 128 exit(0); 129 for (p = cards; *p; ++p) 130 if (!strcasecmp(*p, buf)) 131 break; 132 if (!*p) { 133 (void)printf("I don't understand!\n"); 134 continue; 135 } 136 n = p - cards; 137 if (userhand[n]) { 138 userasked[n] = 1; 139 return(n); 140 } 141 if (nrandom(3) == 1) 142 (void)printf("You don't have any of those!\n"); 143 else 144 (void)printf("You don't have any %s's!\n", cards[n]); 145 if (nrandom(4) == 1) 146 (void)printf("No cheating!\n"); 147 (void)printf("Guess again.\n"); 148 } 149 /* NOTREACHED */ 150 } 151 152 compmove() 153 { 154 static int lmove; 155 156 if (promode) 157 lmove = promove(); 158 else { 159 do { 160 lmove = (lmove + 1) % RANKS; 161 } while (!comphand[lmove] || comphand[lmove] == CARDS); 162 } 163 asked[lmove] = 1; 164 165 (void)printf("I ask you for: %s.\n", cards[lmove]); 166 return(lmove); 167 } 168 169 promove() 170 { 171 register int i, max; 172 173 for (i = 0; i < RANKS; ++i) 174 if (userasked[i] && 175 comphand[i] > 0 && comphand[i] < CARDS) { 176 userasked[i] = 0; 177 return(i); 178 } 179 if (nrandom(3) == 1) { 180 for (i = 0;; ++i) 181 if (comphand[i] && comphand[i] != CARDS) { 182 max = i; 183 break; 184 } 185 while (++i < RANKS) 186 if (comphand[i] != CARDS && 187 comphand[i] > comphand[max]) 188 max = i; 189 return(max); 190 } 191 if (nrandom(1024) == 0723) { 192 for (i = 0; i < RANKS; ++i) 193 if (userhand[i] && comphand[i]) 194 return(i); 195 } 196 for (;;) { 197 for (i = 0; i < RANKS; ++i) 198 if (comphand[i] && comphand[i] != CARDS && 199 !asked[i]) 200 return(i); 201 for (i = 0; i < RANKS; ++i) 202 asked[i] = 0; 203 } 204 /* NOTREACHED */ 205 } 206 207 drawcard(player, hand) 208 int player; 209 int *hand; 210 { 211 int card; 212 213 while (deck[card = nrandom(RANKS)] == 0); 214 ++hand[card]; 215 --deck[card]; 216 if (player == USER || hand[card] == CARDS) { 217 printplayer(player); 218 (void)printf("drew %s", cards[card]); 219 if (hand[card] == CARDS) { 220 (void)printf(" and made a book of %s's!\n", 221 cards[card]); 222 chkwinner(player, hand); 223 } else 224 (void)printf(".\n"); 225 } 226 return(card); 227 } 228 229 gofish(askedfor, player, hand) 230 int askedfor, player; 231 int *hand; 232 { 233 printplayer(OTHER(player)); 234 (void)printf("say \"GO FISH!\"\n"); 235 if (askedfor == drawcard(player, hand)) { 236 printplayer(player); 237 (void)printf("drew the guess!\n"); 238 printplayer(player); 239 (void)printf("get to ask again!\n"); 240 return(1); 241 } 242 return(0); 243 } 244 245 goodmove(player, move, hand, opphand) 246 int player, move; 247 int *hand, *opphand; 248 { 249 printplayer(OTHER(player)); 250 (void)printf("have %d %s%s.\n", 251 opphand[move], cards[move], opphand[move] == 1 ? "": "'s"); 252 253 hand[move] += opphand[move]; 254 opphand[move] = 0; 255 256 if (hand[move] == CARDS) { 257 printplayer(player); 258 (void)printf("made a book of %s's!\n", cards[move]); 259 chkwinner(player, hand); 260 } 261 262 chkwinner(OTHER(player), opphand); 263 264 printplayer(player); 265 (void)printf("get another guess!\n"); 266 } 267 268 chkwinner(player, hand) 269 int player; 270 register int *hand; 271 { 272 register int cb, i, ub; 273 274 for (i = 0; i < RANKS; ++i) 275 if (hand[i] > 0 && hand[i] < CARDS) 276 return; 277 printplayer(player); 278 (void)printf("don't have any more cards!\n"); 279 (void)printf("My books:"); 280 cb = countbooks(comphand); 281 (void)printf("Your books:"); 282 ub = countbooks(userhand); 283 (void)printf("\nI have %d, you have %d.\n", cb, ub); 284 if (ub > cb) { 285 (void)printf("\nYou win!!!\n"); 286 if (nrandom(1024) == 0723) 287 (void)printf("Cheater, cheater, pumpkin eater!\n"); 288 } else if (cb > ub) { 289 (void)printf("\nI win!!!\n"); 290 if (nrandom(1024) == 0723) 291 (void)printf("Hah! Stupid peasant!\n"); 292 } else 293 (void)printf("\nTie!\n"); 294 exit(0); 295 } 296 297 printplayer(player) 298 int player; 299 { 300 switch (player) { 301 case COMPUTER: 302 (void)printf("I "); 303 break; 304 case USER: 305 (void)printf("You "); 306 break; 307 } 308 } 309 310 printhand(hand) 311 int *hand; 312 { 313 register int book, i, j; 314 315 for (book = i = 0; i < RANKS; i++) 316 if (hand[i] < CARDS) 317 for (j = hand[i]; --j >= 0;) 318 PRC(i); 319 else 320 ++book; 321 if (book) { 322 (void)printf(" + Book%s of", book > 1 ? "s" : ""); 323 for (i = 0; i < RANKS; i++) 324 if (hand[i] == CARDS) 325 PRC(i); 326 } 327 (void)putchar('\n'); 328 } 329 330 countcards(hand) 331 register int *hand; 332 { 333 register int i, count; 334 335 for (count = i = 0; i < RANKS; i++) 336 count += *hand++; 337 return(count); 338 } 339 340 countbooks(hand) 341 int *hand; 342 { 343 int i, count; 344 345 for (count = i = 0; i < RANKS; i++) 346 if (hand[i] == CARDS) { 347 ++count; 348 PRC(i); 349 } 350 if (!count) 351 (void)printf(" none"); 352 (void)putchar('\n'); 353 return(count); 354 } 355 356 init() 357 { 358 register int i, rank; 359 360 for (i = 0; i < RANKS; ++i) 361 deck[i] = CARDS; 362 for (i = 0; i < HANDSIZE; ++i) { 363 while (!deck[rank = nrandom(RANKS)]); 364 ++userhand[rank]; 365 --deck[rank]; 366 } 367 for (i = 0; i < HANDSIZE; ++i) { 368 while (!deck[rank = nrandom(RANKS)]); 369 ++comphand[rank]; 370 --deck[rank]; 371 } 372 } 373 374 nrandom(n) 375 int n; 376 { 377 long random(); 378 379 return((int)random() % n); 380 } 381 382 instructions() 383 { 384 int input; 385 char buf[1024]; 386 387 (void)printf("Would you like instructions (y or n)? "); 388 input = getchar(); 389 while (getchar() != '\n'); 390 if (input != 'y') 391 return; 392 393 (void)sprintf(buf, "%s %s", _PATH_MORE, _PATH_INSTR); 394 (void)system(buf); 395 (void)printf("Hit return to continue...\n"); 396 while ((input = getchar()) != EOF && input != '\n'); 397 } 398 399 usage() 400 { 401 (void)fprintf(stderr, "usage: fish [-p]\n"); 402 exit(1); 403 } 404