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