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