Home | History | Annotate | Line # | Download | only in fish
fish.c revision 1.4
      1 /*	$NetBSD: fish.c,v 1.4 1997/10/10 12:58:32 lukem Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 1990, 1993
      5  *	The Regents of the University of California.  All rights reserved.
      6  *
      7  * This code is derived from software contributed to Berkeley by
      8  * Muffy Barkocy.
      9  *
     10  * Redistribution and use in source and binary forms, with or without
     11  * modification, are permitted provided that the following conditions
     12  * are met:
     13  * 1. Redistributions of source code must retain the above copyright
     14  *    notice, this list of conditions and the following disclaimer.
     15  * 2. Redistributions in binary form must reproduce the above copyright
     16  *    notice, this list of conditions and the following disclaimer in the
     17  *    documentation and/or other materials provided with the distribution.
     18  * 3. All advertising materials mentioning features or use of this software
     19  *    must display the following acknowledgement:
     20  *	This product includes software developed by the University of
     21  *	California, Berkeley and its contributors.
     22  * 4. Neither the name of the University nor the names of its contributors
     23  *    may be used to endorse or promote products derived from this software
     24  *    without specific prior written permission.
     25  *
     26  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     27  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     28  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     29  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     30  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     31  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     32  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     33  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     34  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     35  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     36  * SUCH DAMAGE.
     37  */
     38 
     39 #include <sys/cdefs.h>
     40 #ifndef lint
     41 __COPYRIGHT("@(#) 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 #else
     49 __RCSID("$NetBSD: fish.c,v 1.4 1997/10/10 12:58:32 lukem Exp $");
     50 #endif
     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 <time.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, int *));
     81 int	compmove __P((void));
     82 int	countbooks __P((int *));
     83 int	countcards __P((int *));
     84 int	drawcard __P((int, int *));
     85 int	gofish __P((int, int, int *));
     86 void	goodmove __P((int, int, int *, int *));
     87 void	init __P((void));
     88 void	instructions __P((void));
     89 int	main __P((int, char *[]));
     90 int	nrandom __P((int));
     91 void	printhand __P((int *));
     92 void	printplayer __P((int));
     93 int	promove __P((void));
     94 void	usage __P((void));
     95 int	usermove __P((void));
     96 
     97 int
     98 main(argc, argv)
     99 	int argc;
    100 	char **argv;
    101 {
    102 	int ch, move;
    103 
    104 	while ((ch = getopt(argc, argv, "p")) != -1)
    105 		switch(ch) {
    106 		case 'p':
    107 			promode = 1;
    108 			break;
    109 		case '?':
    110 		default:
    111 			(void)fprintf(stderr, "usage: fish [-p]\n");
    112 			exit(1);
    113 		}
    114 
    115 	srandom(time((time_t *)NULL));
    116 	instructions();
    117 	init();
    118 
    119 	if (nrandom(2) == 1) {
    120 		printplayer(COMPUTER);
    121 		(void)printf("get to start.\n");
    122 		goto istart;
    123 	}
    124 	printplayer(USER);
    125 	(void)printf("get to start.\n");
    126 
    127 	for (;;) {
    128 		move = usermove();
    129 		if (!comphand[move]) {
    130 			if (gofish(move, USER, userhand))
    131 				continue;
    132 		} else {
    133 			goodmove(USER, move, userhand, comphand);
    134 			continue;
    135 		}
    136 
    137 istart:		for (;;) {
    138 			move = compmove();
    139 			if (!userhand[move]) {
    140 				if (!gofish(move, COMPUTER, comphand))
    141 					break;
    142 			} else
    143 				goodmove(COMPUTER, move, comphand, userhand);
    144 		}
    145 	}
    146 	/* NOTREACHED */
    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, BUFSIZ, 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