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