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