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