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 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by the University of 19 * California, Berkeley and its contributors. 20 * 4. Neither the name of the University nor the names of its contributors 21 * may be used to endorse or promote products derived from this software 22 * without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 * 36 * $FreeBSD: src/games/fish/fish.c,v 1.9 1999/12/10 16:21:50 billf Exp $ 37 */ 38 39 #ifndef lint 40 static const char copyright[] = 41 "@(#) Copyright (c) 1990, 1993\n\ 42 The Regents of the University of California. All rights reserved.\n"; 43 #endif /* not lint */ 44 45 #ifndef lint 46 #if 0 47 static char sccsid[] = "@(#)fish.c 8.1 (Berkeley) 5/31/93"; 48 #endif 49 static const char rcsid[] = 50 "$FreeBSD: src/games/fish/fish.c,v 1.9 1999/12/10 16:21:50 billf Exp $"; 51 #endif /* not lint */ 52 53 #include <sys/types.h> 54 #include <sys/errno.h> 55 #include <fcntl.h> 56 #include <stdio.h> 57 #include <stdlib.h> 58 #include <string.h> 59 #include <unistd.h> 60 #include "pathnames.h" 61 62 #define RANKS 13 63 #define HANDSIZE 7 64 #define CARDS 4 65 66 #define USER 1 67 #define COMPUTER 0 68 #define OTHER(a) (1 - (a)) 69 70 char *cards[] = { 71 "A", "2", "3", "4", "5", "6", "7", 72 "8", "9", "10", "J", "Q", "K", NULL, 73 }; 74 #define PRC(card) (void)printf(" %s", cards[card]) 75 76 int promode; 77 int asked[RANKS], comphand[RANKS], deck[RANKS]; 78 int userasked[RANKS], userhand[RANKS]; 79 80 void chkwinner __P((int player, int *hand)); 81 int compmove __P((void)); 82 int countbooks __P((int *hand)); 83 int countcards __P((int *hand)); 84 int drawcard __P((int player, int *hand)); 85 int gofish __P((int askedfor, int player, int *hand)); 86 void goodmove __P((int player, int move, int *hand, int *opphand)); 87 void init __P((void)); 88 void instructions __P((void)); 89 int nrandom __P((int n)); 90 void printhand __P((int *hand)); 91 void printplayer __P((int player)); 92 int promove __P((void)); 93 void usage __P((void)); 94 int usermove __P((void)); 95 96 int 97 main(argc, argv) 98 int argc; 99 char **argv; 100 { 101 int ch, move; 102 103 while ((ch = getopt(argc, argv, "p")) != -1) 104 switch(ch) { 105 case 'p': 106 promode = 1; 107 break; 108 case '?': 109 default: 110 (void)fprintf(stderr, "usage: fish [-p]\n"); 111 exit(1); 112 } 113 114 srandomdev(); 115 instructions(); 116 init(); 117 118 if (nrandom(2) == 1) { 119 printplayer(COMPUTER); 120 (void)printf("get to start.\n"); 121 goto istart; 122 } 123 printplayer(USER); 124 (void)printf("get to start.\n"); 125 126 for (;;) { 127 move = usermove(); 128 if (!comphand[move]) { 129 if (gofish(move, USER, userhand)) 130 continue; 131 } else { 132 goodmove(USER, move, userhand, comphand); 133 continue; 134 } 135 136 istart: for (;;) { 137 move = compmove(); 138 if (!userhand[move]) { 139 if (!gofish(move, COMPUTER, comphand)) 140 break; 141 } else 142 goodmove(COMPUTER, move, comphand, userhand); 143 } 144 } 145 /* NOTREACHED */ 146 return(EXIT_FAILURE); 147 } 148 149 int 150 usermove() 151 { 152 int n; 153 char **p; 154 char buf[256]; 155 156 (void)printf("\nYour hand is:"); 157 printhand(userhand); 158 159 for (;;) { 160 (void)printf("You ask me for: "); 161 (void)fflush(stdout); 162 if (fgets(buf, sizeof(buf), stdin) == NULL) 163 exit(0); 164 if (buf[0] == '\0') 165 continue; 166 if (buf[0] == '\n') { 167 (void)printf("%d cards in my hand, %d in the pool.\n", 168 countcards(comphand), countcards(deck)); 169 (void)printf("My books:"); 170 (void)countbooks(comphand); 171 continue; 172 } 173 buf[strlen(buf) - 1] = '\0'; 174 if (!strcasecmp(buf, "p") && !promode) { 175 promode = 1; 176 (void)printf("Entering pro mode.\n"); 177 continue; 178 } 179 if (!strcasecmp(buf, "quit")) 180 exit(0); 181 for (p = cards; *p; ++p) 182 if (!strcasecmp(*p, buf)) 183 break; 184 if (!*p) { 185 (void)printf("I don't understand!\n"); 186 continue; 187 } 188 n = p - cards; 189 if (userhand[n]) { 190 userasked[n] = 1; 191 return(n); 192 } 193 if (nrandom(3) == 1) 194 (void)printf("You don't have any of those!\n"); 195 else 196 (void)printf("You don't have any %s's!\n", cards[n]); 197 if (nrandom(4) == 1) 198 (void)printf("No cheating!\n"); 199 (void)printf("Guess again.\n"); 200 } 201 /* NOTREACHED */ 202 } 203 204 int 205 compmove() 206 { 207 static int lmove; 208 209 if (promode) 210 lmove = promove(); 211 else { 212 do { 213 lmove = (lmove + 1) % RANKS; 214 } while (!comphand[lmove] || comphand[lmove] == CARDS); 215 } 216 asked[lmove] = 1; 217 218 (void)printf("I ask you for: %s.\n", cards[lmove]); 219 return(lmove); 220 } 221 222 int 223 promove() 224 { 225 int i, max; 226 227 for (i = 0; i < RANKS; ++i) 228 if (userasked[i] && 229 comphand[i] > 0 && comphand[i] < CARDS) { 230 userasked[i] = 0; 231 return(i); 232 } 233 if (nrandom(3) == 1) { 234 for (i = 0;; ++i) 235 if (comphand[i] && comphand[i] != CARDS) { 236 max = i; 237 break; 238 } 239 while (++i < RANKS) 240 if (comphand[i] != CARDS && 241 comphand[i] > comphand[max]) 242 max = i; 243 return(max); 244 } 245 if (nrandom(1024) == 0723) { 246 for (i = 0; i < RANKS; ++i) 247 if (userhand[i] && comphand[i]) 248 return(i); 249 } 250 for (;;) { 251 for (i = 0; i < RANKS; ++i) 252 if (comphand[i] && comphand[i] != CARDS && 253 !asked[i]) 254 return(i); 255 for (i = 0; i < RANKS; ++i) 256 asked[i] = 0; 257 } 258 /* NOTREACHED */ 259 } 260 261 int 262 drawcard(player, hand) 263 int player; 264 int *hand; 265 { 266 int card; 267 268 while (deck[card = nrandom(RANKS)] == 0); 269 ++hand[card]; 270 --deck[card]; 271 if (player == USER || hand[card] == CARDS) { 272 printplayer(player); 273 (void)printf("drew %s", cards[card]); 274 if (hand[card] == CARDS) { 275 (void)printf(" and made a book of %s's!\n", 276 cards[card]); 277 chkwinner(player, hand); 278 } else 279 (void)printf(".\n"); 280 } 281 return(card); 282 } 283 284 int 285 gofish(askedfor, player, hand) 286 int askedfor, player; 287 int *hand; 288 { 289 printplayer(OTHER(player)); 290 (void)printf("say \"GO FISH!\"\n"); 291 if (askedfor == drawcard(player, hand)) { 292 printplayer(player); 293 (void)printf("drew the guess!\n"); 294 printplayer(player); 295 (void)printf("get to ask again!\n"); 296 return(1); 297 } 298 return(0); 299 } 300 301 void 302 goodmove(player, move, hand, opphand) 303 int player, move; 304 int *hand, *opphand; 305 { 306 printplayer(OTHER(player)); 307 (void)printf("have %d %s%s.\n", 308 opphand[move], cards[move], opphand[move] == 1 ? "": "'s"); 309 310 hand[move] += opphand[move]; 311 opphand[move] = 0; 312 313 if (hand[move] == CARDS) { 314 printplayer(player); 315 (void)printf("made a book of %s's!\n", cards[move]); 316 chkwinner(player, hand); 317 } 318 319 chkwinner(OTHER(player), opphand); 320 321 printplayer(player); 322 (void)printf("get another guess!\n"); 323 } 324 325 void 326 chkwinner(player, hand) 327 int player; 328 int *hand; 329 { 330 int cb, i, ub; 331 332 for (i = 0; i < RANKS; ++i) 333 if (hand[i] > 0 && hand[i] < CARDS) 334 return; 335 printplayer(player); 336 (void)printf("don't have any more cards!\n"); 337 (void)printf("My books:"); 338 cb = countbooks(comphand); 339 (void)printf("Your books:"); 340 ub = countbooks(userhand); 341 (void)printf("\nI have %d, you have %d.\n", cb, ub); 342 if (ub > cb) { 343 (void)printf("\nYou win!!!\n"); 344 if (nrandom(1024) == 0723) 345 (void)printf("Cheater, cheater, pumpkin eater!\n"); 346 } else if (cb > ub) { 347 (void)printf("\nI win!!!\n"); 348 if (nrandom(1024) == 0723) 349 (void)printf("Hah! Stupid peasant!\n"); 350 } else 351 (void)printf("\nTie!\n"); 352 exit(0); 353 } 354 355 void 356 printplayer(player) 357 int player; 358 { 359 switch (player) { 360 case COMPUTER: 361 (void)printf("I "); 362 break; 363 case USER: 364 (void)printf("You "); 365 break; 366 } 367 } 368 369 void 370 printhand(hand) 371 int *hand; 372 { 373 int book, i, j; 374 375 for (book = i = 0; i < RANKS; i++) 376 if (hand[i] < CARDS) 377 for (j = hand[i]; --j >= 0;) 378 PRC(i); 379 else 380 ++book; 381 if (book) { 382 (void)printf(" + Book%s of", book > 1 ? "s" : ""); 383 for (i = 0; i < RANKS; i++) 384 if (hand[i] == CARDS) 385 PRC(i); 386 } 387 (void)putchar('\n'); 388 } 389 390 int 391 countcards(hand) 392 int *hand; 393 { 394 int i, count; 395 396 for (count = i = 0; i < RANKS; i++) 397 count += *hand++; 398 return(count); 399 } 400 401 int 402 countbooks(hand) 403 int *hand; 404 { 405 int i, count; 406 407 for (count = i = 0; i < RANKS; i++) 408 if (hand[i] == CARDS) { 409 ++count; 410 PRC(i); 411 } 412 if (!count) 413 (void)printf(" none"); 414 (void)putchar('\n'); 415 return(count); 416 } 417 418 void 419 init() 420 { 421 int i, rank; 422 423 for (i = 0; i < RANKS; ++i) 424 deck[i] = CARDS; 425 for (i = 0; i < HANDSIZE; ++i) { 426 while (!deck[rank = nrandom(RANKS)]); 427 ++userhand[rank]; 428 --deck[rank]; 429 } 430 for (i = 0; i < HANDSIZE; ++i) { 431 while (!deck[rank = nrandom(RANKS)]); 432 ++comphand[rank]; 433 --deck[rank]; 434 } 435 } 436 437 int 438 nrandom(n) 439 int n; 440 { 441 442 return((int)random() % n); 443 } 444 445 void 446 instructions() 447 { 448 int input; 449 char buf[1024]; 450 451 (void)printf("Would you like instructions (y or n)? "); 452 input = getchar(); 453 while (getchar() != '\n'); 454 if (input != 'y') 455 return; 456 457 (void)sprintf(buf, "%s %s", _PATH_MORE, _PATH_INSTR); 458 (void)system(buf); 459 (void)printf("Hit return to continue...\n"); 460 while ((input = getchar()) != EOF && input != '\n'); 461 } 462 463 void 464 usage() 465 { 466 (void)fprintf(stderr, "usage: fish [-p]\n"); 467 exit(1); 468 } 469