Commit | Line | Data |
---|---|---|
495d41aa KB |
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 | * %sccs.include.redist.c% | |
e0bbfbf9 DF |
9 | */ |
10 | ||
11 | #ifndef lint | |
12 | char copyright[] = | |
495d41aa | 13 | "@(#) Copyright (c) 1990 The Regents of the University of California.\n\ |
e0bbfbf9 | 14 | All rights reserved.\n"; |
495d41aa | 15 | #endif /* not lint */ |
e0bbfbf9 DF |
16 | |
17 | #ifndef lint | |
adccc0d2 | 18 | static char sccsid[] = "@(#)fish.c 5.4 (Berkeley) %G%"; |
495d41aa KB |
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); | |
32029695 KM |
62 | } |
63 | ||
495d41aa KB |
64 | srandom(time((time_t *)NULL)); |
65 | instructions(); | |
66 | init(); | |
32029695 | 67 | |
495d41aa KB |
68 | if (nrandom(2) == 1) { |
69 | printplayer(COMPUTER); | |
70 | (void)printf("get to start.\n"); | |
71 | goto istart; | |
32029695 | 72 | } |
495d41aa KB |
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; | |
32029695 | 84 | } |
32029695 | 85 | |
495d41aa KB |
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); | |
32029695 KM |
93 | } |
94 | } | |
495d41aa KB |
95 | /* NOTREACHED */ |
96 | } | |
97 | ||
98 | usermove() | |
99 | { | |
100 | register int n; | |
101 | register char **p; | |
102 | char buf[256]; | |
103 | ||
adccc0d2 | 104 | (void)printf("\nYour hand is:"); |
495d41aa KB |
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; | |
32029695 | 120 | } |
495d41aa KB |
121 | buf[strlen(buf) - 1] = '\0'; |
122 | if (!strcasecmp(buf, "p") && !promode) { | |
123 | promode = 1; | |
124 | (void)printf("Entering pro mode.\n"); | |
125 | continue; | |
32029695 | 126 | } |
495d41aa KB |
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"); | |
32029695 | 134 | continue; |
32029695 | 135 | } |
495d41aa KB |
136 | n = p - cards; |
137 | if (userhand[n]) { | |
138 | userasked[n] = 1; | |
139 | return(n); | |
32029695 | 140 | } |
495d41aa KB |
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"); | |
32029695 | 148 | } |
495d41aa KB |
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; | |
32029695 | 164 | |
495d41aa KB |
165 | (void)printf("I ask you for: %s.\n", cards[lmove]); |
166 | return(lmove); | |
167 | } | |
32029695 | 168 | |
495d41aa KB |
169 | promove() |
170 | { | |
171 | register int i, max; | |
32029695 | 172 | |
495d41aa KB |
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); | |
32029695 | 178 | } |
495d41aa KB |
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); | |
32029695 | 195 | } |
495d41aa KB |
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; | |
32029695 | 203 | } |
495d41aa KB |
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"); | |
32029695 | 225 | } |
495d41aa KB |
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"); | |
32029695 | 240 | return(1); |
32029695 | 241 | } |
495d41aa KB |
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); | |
32029695 KM |
260 | } |
261 | ||
495d41aa KB |
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"); | |
32029695 | 294 | exit(0); |
495d41aa KB |
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; | |
32029695 | 307 | } |
495d41aa KB |
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); | |
32029695 | 326 | } |
495d41aa KB |
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); | |
32029695 | 349 | } |
495d41aa KB |
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]; | |
32029695 | 366 | } |
495d41aa KB |
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 | } |