xref: /original-bsd/games/fish/fish.c (revision b5bcb3e5)
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