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