Annotation of src/games/cribbage/support.c, Revision 1.12
1.12 ! rtr 1: /* $NetBSD: support.c,v 1.11 2006/03/19 12:09:39 he Exp $ */
1.3 cgd 2:
3: /*-
4: * Copyright (c) 1980, 1993
5: * The Regents of the University of California. All rights reserved.
1.1 cgd 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.
1.7 agc 15: * 3. Neither the name of the University nor the names of its contributors
1.1 cgd 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:
1.4 lukem 32: #include <sys/cdefs.h>
1.1 cgd 33: #ifndef lint
1.3 cgd 34: #if 0
35: static char sccsid[] = "@(#)support.c 8.1 (Berkeley) 5/31/93";
36: #else
1.12 ! rtr 37: __RCSID("$NetBSD: support.c,v 1.11 2006/03/19 12:09:39 he Exp $");
1.3 cgd 38: #endif
1.1 cgd 39: #endif /* not lint */
40:
1.3 cgd 41: #include <curses.h>
1.11 he 42: #include <stdlib.h>
1.3 cgd 43: #include <string.h>
1.1 cgd 44:
1.3 cgd 45: #include "deck.h"
46: #include "cribbage.h"
47: #include "cribcur.h"
1.1 cgd 48:
1.3 cgd 49: #define NTV 10 /* number scores to test */
1.1 cgd 50:
51: /* score to test reachability of, and order to test them in */
1.5 jsm 52: const int tv[NTV] = {8, 7, 9, 6, 11, 12, 13, 14, 10, 5};
1.1 cgd 53:
54: /*
55: * computer chooses what to play in pegging...
56: * only called if no playable card will score points
57: */
1.3 cgd 58: int
1.8 jmc 59: cchose(const CARD h[], int n, int s)
1.1 cgd 60: {
1.4 lukem 61: int i, j, l;
1.1 cgd 62:
1.3 cgd 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: }
1.1 cgd 80: }
81: }
1.3 cgd 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: }
1.1 cgd 92: }
93: }
94: j = -1;
1.3 cgd 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: }
1.1 cgd 117: }
1.9 christos 118: if (j < 0) {
119: printf("\ncchose: internal error %d %d\n", j, n);
120: exit(93);
121: }
1.3 cgd 122: return (j);
1.1 cgd 123: }
124:
125: /*
126: * plyrhand:
127: * Evaluate and score a player hand or crib
128: */
1.3 cgd 129: int
1.8 jmc 130: plyrhand(const CARD hand[], const char *s)
1.1 cgd 131: {
1.3 cgd 132: static char prompt[BUFSIZ];
1.4 lukem 133: int i, j;
134: BOOLEAN win;
1.3 cgd 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)
1.6 thorpej 152: msg("Explanation: %s", explan);
1.3 cgd 153: do_wait();
154: } else
155: win = chkscr(&pscore, i);
156: return (win);
1.1 cgd 157: }
158:
159: /*
160: * comphand:
161: * Handle scoring and displaying the computers hand
162: */
1.3 cgd 163: int
1.8 jmc 164: comphand(const CARD h[], const char *s)
1.1 cgd 165: {
1.4 lukem 166: int j;
1.1 cgd 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));
1.3 cgd 171: return (chkscr(&cscore, j));
1.1 cgd 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: */
1.3 cgd 179: int Lastscore[2] = {-1, -1};
1.1 cgd 180:
1.3 cgd 181: int
1.8 jmc 182: chkscr(int *scr, int inc)
1.1 cgd 183: {
1.3 cgd 184: BOOLEAN myturn;
1.1 cgd 185:
186: myturn = (scr == &cscore);
187: if (inc != 0) {
1.4 lukem 188: prpeg(Lastscore[(int)myturn], '.', myturn);
189: Lastscore[(int)myturn] = *scr;
1.1 cgd 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: */
1.3 cgd 202: void
1.8 jmc 203: prpeg(int curscore, int pegc, BOOLEAN myturn)
1.1 cgd 204: {
1.4 lukem 205: int y, x;
1.1 cgd 206:
207: if (!myturn)
208: y = SCORE_Y + 2;
209: else
210: y = SCORE_Y + 5;
211:
1.8 jmc 212: if (curscore <= 0 || curscore >= glimit) {
213: if (pegc == '.')
214: pegc = ' ';
215: if (curscore == 0)
1.1 cgd 216: x = SCORE_X + 2;
217: else {
218: x = SCORE_X + 2;
219: y++;
220: }
1.3 cgd 221: } else {
1.8 jmc 222: x = (curscore - 1) % 30;
223: if (curscore > 90 || (curscore > 30 && curscore <= 60)) {
1.1 cgd 224: y++;
225: x = 29 - x;
226: }
227: x += x / 5;
228: x += SCORE_X + 3;
229: }
1.8 jmc 230: mvaddch(y, x, pegc);
231: mvprintw(SCORE_Y + (myturn ? 7 : 1), SCORE_X + 10, "%3d", curscore);
1.1 cgd 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: */
1.3 cgd 238: void
1.8 jmc 239: cdiscard(BOOLEAN mycrib)
1.1 cgd 240: {
1.3 cgd 241: CARD d[CARDS], h[FULLHAND], cb[2];
1.4 lukem 242: int i, j, k;
1.3 cgd 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};
1.1 cgd 247:
1.3 cgd 248: makedeck(d);
1.1 cgd 249: nc = CARDS;
1.3 cgd 250: for (i = 0; i < knownum; i++) { /* get all other cards */
251: cremove(known[i], d, nc--);
1.1 cgd 252: }
1.3 cgd 253: for (i = 0; i < 15; i++)
254: sums[i] = 0L;
1.1 cgd 255: ns = 0;
1.3 cgd 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;
1.1 cgd 273: }
274: }
275: j = 0;
1.3 cgd 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]];
1.1 cgd 285: }
286:
287: /*
288: * returns true if some card in hand can be played without exceeding 31
289: */
1.3 cgd 290: int
1.8 jmc 291: anymove(const CARD hand[], int n, int sum)
1.1 cgd 292: {
1.4 lukem 293: int i, j;
1.1 cgd 294:
1.3 cgd 295: if (n < 1)
296: return (FALSE);
1.1 cgd 297: j = hand[0].rank;
1.3 cgd 298: for (i = 1; i < n; i++) {
299: if (hand[i].rank < j)
300: j = hand[i].rank;
1.1 cgd 301: }
1.3 cgd 302: return (sum + VAL(j) <= 31);
1.1 cgd 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: */
1.3 cgd 309: int
1.8 jmc 310: anysumto(const CARD hand[], int n, int s, int t)
1.1 cgd 311: {
1.4 lukem 312: int i;
1.1 cgd 313:
1.3 cgd 314: for (i = 0; i < n; i++) {
315: if (s + VAL(hand[i].rank) == t)
316: return (i);
1.1 cgd 317: }
1.3 cgd 318: return (-1);
1.1 cgd 319: }
320:
321: /*
322: * return the number of cards in h having the given rank value
323: */
1.3 cgd 324: int
1.8 jmc 325: numofval(const CARD h[], int n, int v)
1.1 cgd 326: {
1.4 lukem 327: int i, j;
1.1 cgd 328:
329: j = 0;
1.3 cgd 330: for (i = 0; i < n; i++) {
331: if (VAL(h[i].rank) == v)
332: ++j;
1.1 cgd 333: }
1.3 cgd 334: return (j);
1.1 cgd 335: }
336:
337: /*
338: * makeknown remembers all n cards in h for future recall
339: */
1.3 cgd 340: void
1.8 jmc 341: makeknown(const CARD h[], int n)
1.1 cgd 342: {
1.4 lukem 343: int i;
1.1 cgd 344:
1.3 cgd 345: for (i = 0; i < n; i++)
346: known[knownum++] = h[i];
1.1 cgd 347: }
CVSweb <webmaster@jp.NetBSD.org>