fish(6): Suppress -Wdiscarded-qualifiers warning.
[dragonfly.git] / games / fish / fish.c
blobb31d4b068a555f6ab45fb07b6b0a855f7140a7cd
1 /*-
2 * Copyright (c) 1990, 1993
3 * The Regents of the University of California. All rights reserved.
5 * This code is derived from software contributed to Berkeley by
6 * Muffy Barkocy.
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. Neither the name of the University nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
32 * $FreeBSD: src/games/fish/fish.c,v 1.9 1999/12/10 16:21:50 billf Exp $
34 * @(#) Copyright (c) 1990, 1993 The Regents of the University of California. All rights reserved.
35 * @(#)fish.c 8.1 (Berkeley) 5/31/93
38 #include <sys/types.h>
39 #include <errno.h>
40 #include <fcntl.h>
41 #include <spawn.h>
42 #include <stdio.h>
43 #include <stdlib.h>
44 #include <string.h>
45 #include <unistd.h>
46 #include "pathnames.h"
48 #define RANKS 13
49 #define HANDSIZE 7
50 #define CARDS 4
52 #define USER 1
53 #define COMPUTER 0
54 #define OTHER(a) (1 - (a))
56 static const char *cards[] = {
57 "A", "2", "3", "4", "5", "6", "7",
58 "8", "9", "10", "J", "Q", "K", NULL,
60 #define PRC(card) printf(" %s", cards[card])
62 static int promode;
63 static int asked[RANKS], comphand[RANKS], deck[RANKS];
64 static int userasked[RANKS], userhand[RANKS];
66 extern char **environ;
68 static void chkwinner(int, int *);
69 static int compmove(void);
70 static int countbooks(int *);
71 static int countcards(int *);
72 static int drawcard(int, int *);
73 static int gofish(int, int, int *);
74 static void goodmove(int, int, int *, int *);
75 static void init(void);
76 static void instructions(void);
77 static int nrandom(int);
78 static void printhand(int *);
79 static void printplayer(int);
80 static int promove(void);
81 static void usage(void) __dead2;
82 static int usermove(void);
84 int
85 main(int argc, char **argv)
87 int ch, move;
89 while ((ch = getopt(argc, argv, "p")) != -1)
90 switch(ch) {
91 case 'p':
92 promode = 1;
93 break;
94 case '?':
95 default:
96 usage();
99 srandomdev();
100 instructions();
101 init();
103 if (nrandom(2) == 1) {
104 printplayer(COMPUTER);
105 printf("get to start.\n");
106 goto istart;
108 printplayer(USER);
109 printf("get to start.\n");
111 for (;;) {
112 move = usermove();
113 if (!comphand[move]) {
114 if (gofish(move, USER, userhand))
115 continue;
116 } else {
117 goodmove(USER, move, userhand, comphand);
118 continue;
121 istart: for (;;) {
122 move = compmove();
123 if (!userhand[move]) {
124 if (!gofish(move, COMPUTER, comphand))
125 break;
126 } else
127 goodmove(COMPUTER, move, comphand, userhand);
130 /* NOTREACHED */
131 return (EXIT_FAILURE);
134 static int
135 usermove(void)
137 int n;
138 const char **p;
139 char buf[256];
141 printf("\nYour hand is:");
142 printhand(userhand);
144 for (;;) {
145 printf("You ask me for: ");
146 fflush(stdout);
147 if (fgets(buf, sizeof(buf), stdin) == NULL)
148 exit(0);
149 if (buf[0] == '\0')
150 continue;
151 if (buf[0] == '\n') {
152 printf("%d cards in my hand, %d in the pool.\n",
153 countcards(comphand), countcards(deck));
154 printf("My books:");
155 countbooks(comphand);
156 continue;
158 buf[strlen(buf) - 1] = '\0';
159 if (!strcasecmp(buf, "p")) {
160 if (promode) {
161 printf("Already in pro mode.\n");
162 } else {
163 printf("Entering pro mode.\n");
164 promode = 1;
166 continue;
168 if (!strcasecmp(buf, "quit"))
169 exit(0);
170 for (p = cards; *p; ++p)
171 if (!strcasecmp(*p, buf))
172 break;
173 if (!*p) {
174 printf("I don't understand!\n");
175 continue;
177 n = p - cards;
178 if (userhand[n] <= 3) {
179 userasked[n] = 1;
180 return(n);
182 if (userhand[n] == 4) {
183 printf("You already have all of those.\n");
184 continue;
187 if (nrandom(3) == 1)
188 printf("You don't have any of those!\n");
189 else
190 printf("You don't have any %s's!\n", cards[n]);
191 if (nrandom(4) == 1)
192 printf("No cheating!\n");
193 printf("Guess again.\n");
195 /* NOTREACHED */
198 static int
199 compmove(void)
201 static int lmove;
203 if (promode)
204 lmove = promove();
205 else {
206 do {
207 lmove = (lmove + 1) % RANKS;
208 } while (!comphand[lmove] || comphand[lmove] == CARDS);
210 asked[lmove] = 1;
212 printf("I ask you for: %s.\n", cards[lmove]);
213 return(lmove);
216 static int
217 promove(void)
219 int i, max;
221 for (i = 0; i < RANKS; ++i)
222 if (userasked[i] && comphand[i] > 0 && comphand[i] < CARDS) {
223 userasked[i] = 0;
224 return(i);
226 if (nrandom(3) == 1) {
227 for (i = 0;; ++i)
228 if (comphand[i] && comphand[i] != CARDS) {
229 max = i;
230 break;
232 while (++i < RANKS)
233 if (comphand[i] != CARDS && comphand[i] > comphand[max])
234 max = i;
235 return(max);
237 if (nrandom(1024) == 0723) {
238 for (i = 0; i < RANKS; ++i)
239 if (userhand[i] && comphand[i])
240 return(i);
242 for (;;) {
243 for (i = 0; i < RANKS; ++i)
244 if (comphand[i] && comphand[i] != CARDS && !asked[i])
245 return(i);
246 for (i = 0; i < RANKS; ++i)
247 asked[i] = 0;
249 /* NOTREACHED */
252 static int
253 drawcard(int player, int *hand)
255 int card;
257 while (deck[card = nrandom(RANKS)] == 0)
258 ; /* nothing */
259 ++hand[card];
260 --deck[card];
261 if (player == USER || hand[card] == CARDS) {
262 printplayer(player);
263 printf("drew %s", cards[card]);
264 if (hand[card] == CARDS) {
265 printf(" and made a book of %s's!\n", cards[card]);
266 chkwinner(player, hand);
267 } else
268 printf(".\n");
270 return(card);
273 static int
274 gofish(int askedfor, int player, int *hand)
276 printplayer(OTHER(player));
277 printf("say \"GO FISH!\"\n");
278 if (askedfor == drawcard(player, hand)) {
279 printplayer(player);
280 printf("drew the guess!\n");
281 printplayer(player);
282 printf("get to ask again!\n");
283 return(1);
285 return(0);
288 static void
289 goodmove(int player, int move, int *hand, int *opphand)
291 printplayer(OTHER(player));
292 printf("have %d %s%s.\n",
293 opphand[move], cards[move], opphand[move] == 1 ? "": "'s");
295 hand[move] += opphand[move];
296 opphand[move] = 0;
298 if (hand[move] == CARDS) {
299 printplayer(player);
300 printf("made a book of %s's!\n", cards[move]);
301 chkwinner(player, hand);
304 chkwinner(OTHER(player), opphand);
306 printplayer(player);
307 printf("get another guess!\n");
310 static void
311 chkwinner(int player, int *hand)
313 int cb, i, ub;
315 for (i = 0; i < RANKS; ++i)
316 if (hand[i] > 0 && hand[i] < CARDS)
317 return;
318 printplayer(player);
319 printf("don't have any more cards!\n");
320 printf("My books:");
321 cb = countbooks(comphand);
322 printf("Your books:");
323 ub = countbooks(userhand);
324 printf("\nI have %d, you have %d.\n", cb, ub);
325 if (ub > cb) {
326 printf("\nYou win!!!\n");
327 if (nrandom(1024) == 0723)
328 printf("Cheater, cheater, pumpkin eater!\n");
329 } else if (cb > ub) {
330 printf("\nI win!!!\n");
331 if (nrandom(1024) == 0723)
332 printf("Hah! Stupid peasant!\n");
333 } else
334 printf("\nTie!\n");
335 exit(0);
338 static void
339 printplayer(int player)
341 switch (player) {
342 case COMPUTER:
343 printf("I ");
344 break;
345 case USER:
346 printf("You ");
347 break;
351 static void
352 printhand(int *hand)
354 int book, i, j;
356 for (book = i = 0; i < RANKS; i++)
357 if (hand[i] < CARDS)
358 for (j = hand[i]; --j >= 0;)
359 PRC(i);
360 else
361 ++book;
362 if (book) {
363 printf(" + Book%s of", book > 1 ? "s" : "");
364 for (i = 0; i < RANKS; i++)
365 if (hand[i] == CARDS)
366 PRC(i);
368 putchar('\n');
371 static int
372 countcards(int *hand)
374 int i, count;
376 for (count = i = 0; i < RANKS; i++)
377 count += *hand++;
378 return(count);
381 static int
382 countbooks(int *hand)
384 int i, count;
386 for (count = i = 0; i < RANKS; i++)
387 if (hand[i] == CARDS) {
388 ++count;
389 PRC(i);
391 if (!count)
392 printf(" none");
393 putchar('\n');
394 return(count);
397 static void
398 init(void)
400 int i, rank;
402 for (i = 0; i < RANKS; ++i)
403 deck[i] = CARDS;
404 for (i = 0; i < HANDSIZE; ++i) {
405 while (!deck[rank = nrandom(RANKS)])
406 ; /* nothing */
407 ++userhand[rank];
408 --deck[rank];
410 for (i = 0; i < HANDSIZE; ++i) {
411 while (!deck[rank = nrandom(RANKS)])
412 ; /* nothing */
413 ++comphand[rank];
414 --deck[rank];
418 static int
419 nrandom(int n)
422 return((int)random() % n);
425 static void
426 instructions(void)
428 int input, status, pid;
429 const char * const argv[] = {PATH_PAGER, PATH_INSTR, NULL};
431 printf("Would you like instructions (y or n)? ");
432 input = getchar();
433 while (getchar() != '\n');
434 if (input != 'y')
435 return;
437 status = posix_spawnp(&pid, PATH_PAGER, NULL, NULL,
438 __DECONST(char * const *, argv), environ);
439 if (status != 0) {
440 printf("Unable to spawn %s\n",PATH_PAGER);
442 printf("Hit return to continue...\n");
443 while ((input = getchar()) != EOF && input != '\n');
446 static void
447 usage(void)
449 fprintf(stderr, "usage: fish [-p]\n");
450 exit(1);