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