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