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