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