1 /*-
2 * Copyright (c) 1980, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * %sccs.include.redist.c%
6 */
7
8 #ifndef lint
9 static char sccsid[] = "@(#)support.c 8.1 (Berkeley) 05/31/93";
10 #endif /* not lint */
11
12 #include <curses.h>
13 #include <string.h>
14
15 #include "deck.h"
16 #include "cribbage.h"
17 #include "cribcur.h"
18
19 #define NTV 10 /* number scores to test */
20
21 /* score to test reachability of, and order to test them in */
22 int tv[NTV] = {8, 7, 9, 6, 11, 12, 13, 14, 10, 5};
23
24 /*
25 * computer chooses what to play in pegging...
26 * only called if no playable card will score points
27 */
28 int
cchose(h,n,s)29 cchose(h, n, s)
30 CARD h[];
31 int n, s;
32 {
33 register int i, j, l;
34
35 if (n <= 1)
36 return (0);
37 if (s < 4) { /* try for good value */
38 if ((j = anysumto(h, n, s, 4)) >= 0)
39 return (j);
40 if ((j = anysumto(h, n, s, 3)) >= 0 && s == 0)
41 return (j);
42 }
43 if (s > 0 && s < 20) {
44 /* try for retaliation to 31 */
45 for (i = 1; i <= 10; i++) {
46 if ((j = anysumto(h, n, s, 21 - i)) >= 0) {
47 if ((l = numofval(h, n, i)) > 0) {
48 if (l > 1 || VAL(h[j].rank) != i)
49 return (j);
50 }
51 }
52 }
53 }
54 if (s < 15) {
55 /* for retaliation after 15 */
56 for (i = 0; i < NTV; i++) {
57 if ((j = anysumto(h, n, s, tv[i])) >= 0) {
58 if ((l = numofval(h, n, 15 - tv[i])) > 0) {
59 if (l > 1 ||
60 VAL(h[j].rank) != 15 - tv[i])
61 return (j);
62 }
63 }
64 }
65 }
66 j = -1;
67 /* remember: h is sorted */
68 for (i = n - 1; i >= 0; --i) {
69 l = s + VAL(h[i].rank);
70 if (l > 31)
71 continue;
72 if (l != 5 && l != 10 && l != 21) {
73 j = i;
74 break;
75 }
76 }
77 if (j >= 0)
78 return (j);
79 for (i = n - 1; i >= 0; --i) {
80 l = s + VAL(h[i].rank);
81 if (l > 31)
82 continue;
83 if (j < 0)
84 j = i;
85 if (l != 5 && l != 21) {
86 j = i;
87 break;
88 }
89 }
90 return (j);
91 }
92
93 /*
94 * plyrhand:
95 * Evaluate and score a player hand or crib
96 */
97 int
plyrhand(hand,s)98 plyrhand(hand, s)
99 CARD hand[];
100 char *s;
101 {
102 static char prompt[BUFSIZ];
103 register int i, j;
104 register BOOLEAN win;
105
106 prhand(hand, CINHAND, Playwin, FALSE);
107 (void) sprintf(prompt, "Your %s scores ", s);
108 i = scorehand(hand, turnover, CINHAND, strcmp(s, "crib") == 0, explain);
109 if ((j = number(0, 29, prompt)) == 19)
110 j = 0;
111 if (i != j) {
112 if (i < j) {
113 win = chkscr(&pscore, i);
114 msg("It's really only %d points; I get %d", i, 2);
115 if (!win)
116 win = chkscr(&cscore, 2);
117 } else {
118 win = chkscr(&pscore, j);
119 msg("You should have taken %d, not %d!", i, j);
120 }
121 if (explain)
122 msg("Explanation: %s", expl);
123 do_wait();
124 } else
125 win = chkscr(&pscore, i);
126 return (win);
127 }
128
129 /*
130 * comphand:
131 * Handle scoring and displaying the computers hand
132 */
133 int
comphand(h,s)134 comphand(h, s)
135 CARD h[];
136 char *s;
137 {
138 register int j;
139
140 j = scorehand(h, turnover, CINHAND, strcmp(s, "crib") == 0, FALSE);
141 prhand(h, CINHAND, Compwin, FALSE);
142 msg("My %s scores %d", s, (j == 0 ? 19 : j));
143 return (chkscr(&cscore, j));
144 }
145
146 /*
147 * chkscr:
148 * Add inc to scr and test for > glimit, printing on the scoring
149 * board while we're at it.
150 */
151 int Lastscore[2] = {-1, -1};
152
153 int
chkscr(scr,inc)154 chkscr(scr, inc)
155 int *scr, inc;
156 {
157 BOOLEAN myturn;
158
159 myturn = (scr == &cscore);
160 if (inc != 0) {
161 prpeg(Lastscore[myturn], '.', myturn);
162 Lastscore[myturn] = *scr;
163 *scr += inc;
164 prpeg(*scr, PEG, myturn);
165 refresh();
166 }
167 return (*scr >= glimit);
168 }
169
170 /*
171 * prpeg:
172 * Put out the peg character on the score board and put the
173 * score up on the board.
174 */
175 void
prpeg(score,peg,myturn)176 prpeg(score, peg, myturn)
177 register int score;
178 int peg;
179 BOOLEAN myturn;
180 {
181 register int y, x;
182
183 if (!myturn)
184 y = SCORE_Y + 2;
185 else
186 y = SCORE_Y + 5;
187
188 if (score <= 0 || score >= glimit) {
189 if (peg == '.')
190 peg = ' ';
191 if (score == 0)
192 x = SCORE_X + 2;
193 else {
194 x = SCORE_X + 2;
195 y++;
196 }
197 } else {
198 x = (score - 1) % 30;
199 if (score > 90 || (score > 30 && score <= 60)) {
200 y++;
201 x = 29 - x;
202 }
203 x += x / 5;
204 x += SCORE_X + 3;
205 }
206 mvaddch(y, x, peg);
207 mvprintw(SCORE_Y + (myturn ? 7 : 1), SCORE_X + 10, "%3d", score);
208 }
209
210 /*
211 * cdiscard -- the computer figures out what is the best discard for
212 * the crib and puts the best two cards at the end
213 */
214 void
cdiscard(mycrib)215 cdiscard(mycrib)
216 BOOLEAN mycrib;
217 {
218 CARD d[CARDS], h[FULLHAND], cb[2];
219 register int i, j, k;
220 int nc, ns;
221 long sums[15];
222 static int undo1[15] = {0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 3, 3, 4};
223 static int undo2[15] = {1, 2, 3, 4, 5, 2, 3, 4, 5, 3, 4, 5, 4, 5, 5};
224
225 makedeck(d);
226 nc = CARDS;
227 for (i = 0; i < knownum; i++) { /* get all other cards */
228 cremove(known[i], d, nc--);
229 }
230 for (i = 0; i < 15; i++)
231 sums[i] = 0L;
232 ns = 0;
233 for (i = 0; i < (FULLHAND - 1); i++) {
234 cb[0] = chand[i];
235 for (j = i + 1; j < FULLHAND; j++) {
236 cb[1] = chand[j];
237 for (k = 0; k < FULLHAND; k++)
238 h[k] = chand[k];
239 cremove(chand[i], h, FULLHAND);
240 cremove(chand[j], h, FULLHAND - 1);
241 for (k = 0; k < nc; k++) {
242 sums[ns] +=
243 scorehand(h, d[k], CINHAND, TRUE, FALSE);
244 if (mycrib)
245 sums[ns] += adjust(cb, d[k]);
246 else
247 sums[ns] -= adjust(cb, d[k]);
248 }
249 ++ns;
250 }
251 }
252 j = 0;
253 for (i = 1; i < 15; i++)
254 if (sums[i] > sums[j])
255 j = i;
256 for (k = 0; k < FULLHAND; k++)
257 h[k] = chand[k];
258 cremove(h[undo1[j]], chand, FULLHAND);
259 cremove(h[undo2[j]], chand, FULLHAND - 1);
260 chand[4] = h[undo1[j]];
261 chand[5] = h[undo2[j]];
262 }
263
264 /*
265 * returns true if some card in hand can be played without exceeding 31
266 */
267 int
anymove(hand,n,sum)268 anymove(hand, n, sum)
269 CARD hand[];
270 int n, sum;
271 {
272 register int i, j;
273
274 if (n < 1)
275 return (FALSE);
276 j = hand[0].rank;
277 for (i = 1; i < n; i++) {
278 if (hand[i].rank < j)
279 j = hand[i].rank;
280 }
281 return (sum + VAL(j) <= 31);
282 }
283
284 /*
285 * anysumto returns the index (0 <= i < n) of the card in hand that brings
286 * the s up to t, or -1 if there is none
287 */
288 int
anysumto(hand,n,s,t)289 anysumto(hand, n, s, t)
290 CARD hand[];
291 int n, s, t;
292 {
293 register int i;
294
295 for (i = 0; i < n; i++) {
296 if (s + VAL(hand[i].rank) == t)
297 return (i);
298 }
299 return (-1);
300 }
301
302 /*
303 * return the number of cards in h having the given rank value
304 */
305 int
numofval(h,n,v)306 numofval(h, n, v)
307 CARD h[];
308 int n, v;
309 {
310 register int i, j;
311
312 j = 0;
313 for (i = 0; i < n; i++) {
314 if (VAL(h[i].rank) == v)
315 ++j;
316 }
317 return (j);
318 }
319
320 /*
321 * makeknown remembers all n cards in h for future recall
322 */
323 void
makeknown(h,n)324 makeknown(h, n)
325 CARD h[];
326 int n;
327 {
328 register int i;
329
330 for (i = 0; i < n; i++)
331 known[knownum++] = h[i];
332 }
333