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