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