]> git.cameronkatri.com Git - bsdgames-darwin.git/blob - cribbage/support.c
Both legs of the conditional operator must return the same type.
[bsdgames-darwin.git] / cribbage / support.c
1 /* $NetBSD: support.c,v 1.12 2006/03/20 12:32:21 rtr Exp $ */
2
3 /*-
4 * Copyright (c) 1980, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32 #include <sys/cdefs.h>
33 #ifndef lint
34 #if 0
35 static char sccsid[] = "@(#)support.c 8.1 (Berkeley) 5/31/93";
36 #else
37 __RCSID("$NetBSD: support.c,v 1.12 2006/03/20 12:32:21 rtr Exp $");
38 #endif
39 #endif /* not lint */
40
41 #include <curses.h>
42 #include <stdlib.h>
43 #include <string.h>
44
45 #include "deck.h"
46 #include "cribbage.h"
47 #include "cribcur.h"
48
49 #define NTV 10 /* number scores to test */
50
51 /* score to test reachability of, and order to test them in */
52 const int tv[NTV] = {8, 7, 9, 6, 11, 12, 13, 14, 10, 5};
53
54 /*
55 * computer chooses what to play in pegging...
56 * only called if no playable card will score points
57 */
58 int
59 cchose(const CARD h[], int n, int s)
60 {
61 int i, j, l;
62
63 if (n <= 1)
64 return (0);
65 if (s < 4) { /* try for good value */
66 if ((j = anysumto(h, n, s, 4)) >= 0)
67 return (j);
68 if ((j = anysumto(h, n, s, 3)) >= 0 && s == 0)
69 return (j);
70 }
71 if (s > 0 && s < 20) {
72 /* try for retaliation to 31 */
73 for (i = 1; i <= 10; i++) {
74 if ((j = anysumto(h, n, s, 21 - i)) >= 0) {
75 if ((l = numofval(h, n, i)) > 0) {
76 if (l > 1 || VAL(h[j].rank) != i)
77 return (j);
78 }
79 }
80 }
81 }
82 if (s < 15) {
83 /* for retaliation after 15 */
84 for (i = 0; i < NTV; i++) {
85 if ((j = anysumto(h, n, s, tv[i])) >= 0) {
86 if ((l = numofval(h, n, 15 - tv[i])) > 0) {
87 if (l > 1 ||
88 VAL(h[j].rank) != 15 - tv[i])
89 return (j);
90 }
91 }
92 }
93 }
94 j = -1;
95 /* remember: h is sorted */
96 for (i = n - 1; i >= 0; --i) {
97 l = s + VAL(h[i].rank);
98 if (l > 31)
99 continue;
100 if (l != 5 && l != 10 && l != 21) {
101 j = i;
102 break;
103 }
104 }
105 if (j >= 0)
106 return (j);
107 for (i = n - 1; i >= 0; --i) {
108 l = s + VAL(h[i].rank);
109 if (l > 31)
110 continue;
111 if (j < 0)
112 j = i;
113 if (l != 5 && l != 21) {
114 j = i;
115 break;
116 }
117 }
118 if (j < 0) {
119 printf("\ncchose: internal error %d %d\n", j, n);
120 exit(93);
121 }
122 return (j);
123 }
124
125 /*
126 * plyrhand:
127 * Evaluate and score a player hand or crib
128 */
129 int
130 plyrhand(const CARD hand[], const char *s)
131 {
132 static char prompt[BUFSIZ];
133 int i, j;
134 BOOLEAN win;
135
136 prhand(hand, CINHAND, Playwin, FALSE);
137 (void) sprintf(prompt, "Your %s scores ", s);
138 i = scorehand(hand, turnover, CINHAND, strcmp(s, "crib") == 0, explain);
139 if ((j = number(0, 29, prompt)) == 19)
140 j = 0;
141 if (i != j) {
142 if (i < j) {
143 win = chkscr(&pscore, i);
144 msg("It's really only %d points; I get %d", i, 2);
145 if (!win)
146 win = chkscr(&cscore, 2);
147 } else {
148 win = chkscr(&pscore, j);
149 msg("You should have taken %d, not %d!", i, j);
150 }
151 if (explain)
152 msg("Explanation: %s", explan);
153 do_wait();
154 } else
155 win = chkscr(&pscore, i);
156 return (win);
157 }
158
159 /*
160 * comphand:
161 * Handle scoring and displaying the computers hand
162 */
163 int
164 comphand(const CARD h[], const char *s)
165 {
166 int j;
167
168 j = scorehand(h, turnover, CINHAND, strcmp(s, "crib") == 0, FALSE);
169 prhand(h, CINHAND, Compwin, FALSE);
170 msg("My %s scores %d", s, (j == 0 ? 19 : j));
171 return (chkscr(&cscore, j));
172 }
173
174 /*
175 * chkscr:
176 * Add inc to scr and test for > glimit, printing on the scoring
177 * board while we're at it.
178 */
179 int Lastscore[2] = {-1, -1};
180
181 int
182 chkscr(int *scr, int inc)
183 {
184 BOOLEAN myturn;
185
186 myturn = (scr == &cscore);
187 if (inc != 0) {
188 prpeg(Lastscore[(int)myturn], '.', myturn);
189 Lastscore[(int)myturn] = *scr;
190 *scr += inc;
191 prpeg(*scr, PEG, myturn);
192 refresh();
193 }
194 return (*scr >= glimit);
195 }
196
197 /*
198 * prpeg:
199 * Put out the peg character on the score board and put the
200 * score up on the board.
201 */
202 void
203 prpeg(int curscore, int pegc, BOOLEAN myturn)
204 {
205 int y, x;
206
207 if (!myturn)
208 y = SCORE_Y + 2;
209 else
210 y = SCORE_Y + 5;
211
212 if (curscore <= 0 || curscore >= glimit) {
213 if (pegc == '.')
214 pegc = ' ';
215 if (curscore == 0)
216 x = SCORE_X + 2;
217 else {
218 x = SCORE_X + 2;
219 y++;
220 }
221 } else {
222 x = (curscore - 1) % 30;
223 if (curscore > 90 || (curscore > 30 && curscore <= 60)) {
224 y++;
225 x = 29 - x;
226 }
227 x += x / 5;
228 x += SCORE_X + 3;
229 }
230 mvaddch(y, x, pegc);
231 mvprintw(SCORE_Y + (myturn ? 7 : 1), SCORE_X + 10, "%3d", curscore);
232 }
233
234 /*
235 * cdiscard -- the computer figures out what is the best discard for
236 * the crib and puts the best two cards at the end
237 */
238 void
239 cdiscard(BOOLEAN mycrib)
240 {
241 CARD d[CARDS], h[FULLHAND], cb[2];
242 int i, j, k;
243 int nc, ns;
244 long sums[15];
245 static int undo1[15] = {0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 3, 3, 4};
246 static int undo2[15] = {1, 2, 3, 4, 5, 2, 3, 4, 5, 3, 4, 5, 4, 5, 5};
247
248 makedeck(d);
249 nc = CARDS;
250 for (i = 0; i < knownum; i++) { /* get all other cards */
251 cremove(known[i], d, nc--);
252 }
253 for (i = 0; i < 15; i++)
254 sums[i] = 0L;
255 ns = 0;
256 for (i = 0; i < (FULLHAND - 1); i++) {
257 cb[0] = chand[i];
258 for (j = i + 1; j < FULLHAND; j++) {
259 cb[1] = chand[j];
260 for (k = 0; k < FULLHAND; k++)
261 h[k] = chand[k];
262 cremove(chand[i], h, FULLHAND);
263 cremove(chand[j], h, FULLHAND - 1);
264 for (k = 0; k < nc; k++) {
265 sums[ns] +=
266 scorehand(h, d[k], CINHAND, TRUE, FALSE);
267 if (mycrib)
268 sums[ns] += adjust(cb, d[k]);
269 else
270 sums[ns] -= adjust(cb, d[k]);
271 }
272 ++ns;
273 }
274 }
275 j = 0;
276 for (i = 1; i < 15; i++)
277 if (sums[i] > sums[j])
278 j = i;
279 for (k = 0; k < FULLHAND; k++)
280 h[k] = chand[k];
281 cremove(h[undo1[j]], chand, FULLHAND);
282 cremove(h[undo2[j]], chand, FULLHAND - 1);
283 chand[4] = h[undo1[j]];
284 chand[5] = h[undo2[j]];
285 }
286
287 /*
288 * returns true if some card in hand can be played without exceeding 31
289 */
290 int
291 anymove(const CARD hand[], int n, int sum)
292 {
293 int i, j;
294
295 if (n < 1)
296 return (FALSE);
297 j = hand[0].rank;
298 for (i = 1; i < n; i++) {
299 if (hand[i].rank < j)
300 j = hand[i].rank;
301 }
302 return (sum + VAL(j) <= 31);
303 }
304
305 /*
306 * anysumto returns the index (0 <= i < n) of the card in hand that brings
307 * the s up to t, or -1 if there is none
308 */
309 int
310 anysumto(const CARD hand[], int n, int s, int t)
311 {
312 int i;
313
314 for (i = 0; i < n; i++) {
315 if (s + VAL(hand[i].rank) == t)
316 return (i);
317 }
318 return (-1);
319 }
320
321 /*
322 * return the number of cards in h having the given rank value
323 */
324 int
325 numofval(const CARD h[], int n, int v)
326 {
327 int i, j;
328
329 j = 0;
330 for (i = 0; i < n; i++) {
331 if (VAL(h[i].rank) == v)
332 ++j;
333 }
334 return (j);
335 }
336
337 /*
338 * makeknown remembers all n cards in h for future recall
339 */
340 void
341 makeknown(const CARD h[], int n)
342 {
343 int i;
344
345 for (i = 0; i < n; i++)
346 known[knownum++] = h[i];
347 }