don't format on the fly, just print it out
[unix-history] / usr / src / games / cribbage / score.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
b8c620d6
KB
6 * provided that the above copyright notice and this paragraph are
7 * duplicated in all such forms and that any documentation,
8 * advertising materials, and other materials related to such
9 * distribution and use acknowledge that the software was developed
10 * by the University of California, Berkeley. The name of the
11 * University may not be used to endorse or promote products derived
12 * from this software without specific prior written permission.
13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
6cca9b39
KM
16 */
17
18#ifndef lint
b8c620d6 19static char sccsid[] = "@(#)score.c 5.4 (Berkeley) %G%";
bf870064 20#endif /* not lint */
36235584
KA
21
22#include <stdio.h>
23#include "deck.h"
24#include "cribbage.h"
25
26
27/*
28 * the following arrays give the sum of the scores of the (50 2)*48 = 58800
29 * hands obtainable for the crib given the two cards whose ranks index the
30 * array. the two arrays are for the case where the suits are equal and
31 * not equal respectively
32 */
33
34long crbescr[ 169 ] = {
35 -10000, 271827, 278883, 332319, 347769, 261129, 250653, 253203, 248259,
36 243435, 256275, 237435, 231051, -10000, -10000, 412815, 295707, 349497,
37 267519, 262521, 259695, 254019, 250047, 262887, 244047, 237663, -10000,
38 -10000, -10000, 333987, 388629, 262017, 266787, 262971, 252729, 254475,
39 267315, 248475, 242091, -10000, -10000, -10000, -10000, 422097, 302787,
40 256437, 263751, 257883, 254271, 267111, 248271, 241887, -10000, -10000,
41 -10000, -10000, -10000, 427677, 387837, 349173, 347985, 423861, 436701,
42 417861, 411477, -10000, -10000, -10000, -10000, -10000, -10000, 336387,
43 298851, 338667, 236487, 249327, 230487, 224103, -10000, -10000, -10000,
44 -10000, -10000, -10000, -10000, 408483, 266691, 229803, 246195, 227355,
45 220971, -10000, -10000, -10000, -10000, -10000, -10000, -10000, -10000,
46 300675, 263787, 241695, 226407, 220023, -10000, -10000, -10000, -10000,
47 -10000, -10000, -10000, -10000, -10000, 295635, 273543, 219771, 216939,
48 -10000, -10000, -10000, -10000, -10000, -10000, -10000, -10000, -10000,
49 -10000, 306519, 252747, 211431, -10000, -10000, -10000, -10000, -10000,
50 -10000, -10000, -10000, -10000, -10000, -10000, 304287, 262971, -10000,
51 -10000, -10000, -10000, -10000, -10000, -10000, -10000, -10000, -10000,
52 -10000, -10000, 244131, -10000, -10000, -10000, -10000, -10000, -10000,
53 -10000, -10000, -10000, -10000, -10000, -10000, -10000 };
54
55long crbnescr[ 169 ] = {
56 325272, 260772, 267828, 321264, 336714, 250074, 239598, 242148, 237204,
57 232380, 246348, 226380, 219996, -10000, 342528, 401760, 284652, 338442,
58 256464, 251466, 248640, 242964, 238992, 252960, 232992, 226608, -10000,
59 -10000, 362280, 322932, 377574, 250962, 255732, 251916, 241674, 243420,
60 257388, 237420, 231036, -10000, -10000, -10000, 360768, 411042, 291732,
61 245382, 252696, 246828, 243216, 257184, 237216, 230832, -10000, -10000,
62 -10000, -10000, 528768, 416622, 376782, 338118, 336930, 412806, 426774,
63 406806, 400422, -10000, -10000, -10000, -10000, -10000, 369864, 325332,
64 287796, 327612, 225432, 239400, 219432, 213048, -10000, -10000, -10000,
65 -10000, -10000, -10000, 359160, 397428, 255636, 218748, 236268, 216300,
66 209916, -10000, -10000, -10000, -10000, -10000, -10000, -10000, 331320,
67 289620, 252732, 231768, 215352, 208968, -10000, -10000, -10000, -10000,
68 -10000, -10000, -10000, -10000, 325152, 284580, 263616, 208716, 205884,
69 -10000, -10000, -10000, -10000, -10000, -10000, -10000, -10000, -10000,
70 321240, 296592, 241692, 200376, -10000, -10000, -10000, -10000, -10000,
71 -10000, -10000, -10000, -10000, -10000, 348600, 294360, 253044, -10000,
72 -10000, -10000, -10000, -10000, -10000, -10000, -10000, -10000, -10000,
73 -10000, 308664, 233076, -10000, -10000, -10000, -10000, -10000, -10000,
74 -10000, -10000, -10000, -10000, -10000, -10000, 295896 };
75
76
77static int ichoose2[ 5 ] = { 0, 0, 2, 6, 12 };
78static int pairpoints, runpoints; /* globals from pairuns */
79
80
81/*
56b49d73
KA
82 * scorehand:
83 * Score the given hand of n cards and the starter card.
84 * n must be <= 4
36235584 85 */
56b49d73
KA
86scorehand(hand, starter, n, crb, do_explain)
87register CARD hand[];
88CARD starter;
89int n;
90BOOLEAN crb; /* true if scoring crib */
91BOOLEAN do_explain; /* true if must explain this hand */
36235584 92{
56b49d73
KA
93 CARD h[(CINHAND + 1)];
94 register int i, k;
95 register int score;
f870d435 96 register BOOLEAN flag;
36235584
KA
97 char buf[32];
98
99 expl[0] = NULL; /* initialize explanation */
100 score = 0;
f870d435 101 flag = TRUE;
36235584 102 k = hand[0].suit;
56b49d73
KA
103 for (i = 0; i < n; i++) { /* check for flush */
104 flag = (flag && (hand[i].suit == k));
105 if (hand[i].rank == JACK) /* check for his nibs */
106 if (hand[i].suit == starter.suit) {
107 score++;
108 if (do_explain)
109 strcat(expl, "His Nobs");
36235584 110 }
36235584
KA
111 h[i] = hand[i];
112 }
56b49d73
KA
113
114 if (flag && n >= CINHAND) {
115 if (do_explain && expl[0] != NULL)
116 strcat(expl, ", ");
117 if (starter.suit == k) {
36235584 118 score += 5;
56b49d73
KA
119 if (do_explain)
120 strcat(expl, "Five-flush");
36235584 121 }
56b49d73 122 else if (!crb) {
36235584 123 score += 4;
56b49d73
KA
124 if (do_explain && expl[0] != NULL)
125 strcat(expl, ", Four-flush");
126 else
127 strcpy(expl, "Four-flush");
36235584
KA
128 }
129 }
56b49d73
KA
130
131 if (do_explain && expl[0] != NULL)
132 strcat(expl, ", ");
133 h[n] = starter;
134 sorthand(h, n + 1); /* sort by rank */
135 i = 2 * fifteens(h, n + 1);
36235584 136 score += i;
56b49d73
KA
137 if (do_explain)
138 if (i > 0) {
9bd38ba8 139 (void)sprintf(buf, "%d points in fifteens", i);
56b49d73
KA
140 strcat(expl, buf);
141 }
142 else
143 strcat(expl, "No fifteens");
144 i = pairuns(h, n + 1);
36235584 145 score += i;
56b49d73
KA
146 if (do_explain)
147 if (i > 0) {
9bd38ba8
KB
148 (void)sprintf(buf, ", %d points in pairs, %d in runs",
149 pairpoints, runpoints);
56b49d73
KA
150 strcat(expl, buf);
151 }
152 else
153 strcat(expl, ", No pairs/runs");
154 return score;
36235584
KA
155}
156
36235584 157/*
56b49d73
KA
158 * fifteens:
159 * Return number of fifteens in hand of n cards
36235584 160 */
56b49d73
KA
161fifteens(hand, n)
162register CARD hand[];
163int n;
36235584 164{
56b49d73
KA
165 register int *sp, *np;
166 register int i;
167 register CARD *endp;
168 static int sums[15], nsums[15];
169
170 np = nsums;
171 sp = sums;
172 i = 16;
173 while (--i) {
174 *np++ = 0;
175 *sp++ = 0;
176 }
177 for (endp = &hand[n]; hand < endp; hand++) {
178 i = hand->rank + 1;
179 if (i > 10)
180 i = 10;
181 np = &nsums[i];
182 np[-1]++; /* one way to make this */
183 sp = sums;
184 while (i < 15) {
185 *np++ += *sp++;
186 i++;
36235584 187 }
56b49d73
KA
188 sp = sums;
189 np = nsums;
190 i = 16;
191 while (--i)
192 *sp++ = *np++;
36235584 193 }
56b49d73 194 return sums[14];
36235584
KA
195}
196
197
198
199/*
200 * pairuns returns the number of points in the n card sorted hand
201 * due to pairs and runs
202 * this routine only works if n is strictly less than 6
203 * sets the globals pairpoints and runpoints appropriately
204 */
205
206pairuns( h, n )
207
208 CARD h[];
209 int n;
210{
211 register int i;
212 int runlength, runmult, lastmult, curmult;
213 int mult1, mult2, pair1, pair2;
214 BOOLEAN run;
215
216 run = TRUE;
217 runlength = 1;
218 mult1 = 1;
219 pair1 = -1;
220 mult2 = 1;
221 pair2 = -1;
222 curmult = runmult = 1;
223 for( i = 1; i < n; i++ ) {
224 lastmult = curmult;
225 if( h[i].rank == h[i - 1].rank ) {
226 if( pair1 < 0 ) {
227 pair1 = h[i].rank;
228 mult1 = curmult = 2;
229 }
230 else {
231 if( h[i].rank == pair1 ) {
232 curmult = ++mult1;
233 }
234 else {
235 if( pair2 < 0 ) {
236 pair2 = h[i].rank;
237 mult2 = curmult = 2;
238 }
239 else {
240 curmult = ++mult2;
241 }
242 }
243 }
244 if( i == (n - 1) && run ) {
245 runmult *= curmult;
246 }
247 }
248 else {
249 curmult = 1;
250 if( h[i].rank == h[i - 1].rank + 1 ) {
251 if( run ) {
252 ++runlength;
253 }
254 else {
255 if( runlength < 3 ) { /* only if old short */
256 run = TRUE;
257 runlength = 2;
258 runmult = 1;
259 }
260 }
261 runmult *= lastmult;
262 }
263 else {
264 if( run ) runmult *= lastmult; /* if just ended */
265 run = FALSE;
266 }
267 }
268 }
269 pairpoints = ichoose2[ mult1 ] + ichoose2[ mult2 ];
270 runpoints = ( runlength >= 3 ? runlength*runmult : 0 );
271 return( pairpoints + runpoints );
272}
273
274
275
276/*
277 * pegscore tells how many points crd would get if played after
278 * the n cards in tbl during pegging
279 */
280
281pegscore( crd, tbl, n, sum )
282
283 CARD crd, tbl[];
284 int n;
285 int sum;
286{
287 BOOLEAN got[ RANKS ];
288 register int i, j, scr;
289 int k, lo, hi;
290
291 sum += VAL( crd.rank );
292 if( sum > 31 ) return( -1 );
293 if( sum == 31 || sum == 15 ) scr = 2;
294 else scr = 0;
295 if( !n ) return( scr );
296 j = 1;
297 while( ( crd.rank == tbl[n - j].rank ) && ( n - j >= 0 ) ) ++j;
298 if( j > 1 ) return( scr + ichoose2[j] );
299 if( n < 2 ) return( scr );
300 lo = hi = crd.rank;
301 for( i = 0; i < RANKS; i++ ) got[i] = FALSE;
302 got[ crd.rank ] = TRUE;
303 k = -1;
304 for( i = n - 1; i >= 0; --i ) {
305 if( got[ tbl[i].rank ] ) break;
306 got[ tbl[i].rank ] = TRUE;
307 if( tbl[i].rank < lo ) lo = tbl[i].rank;
308 if( tbl[i].rank > hi ) hi = tbl[i].rank;
309 for( j = lo; j <= hi; j++ ) if( !got[j] ) break;
310 if( j > hi ) k = hi - lo + 1;
311 }
312 if( k >= 3 ) return( scr + k );
313 else return( scr );
314}
315
316
317
318/*
319 * adjust takes a two card hand that will be put in the crib
320 * and returns an adjusted normalized score for the number of
321 * points such a crib will get.
322 */
323
324adjust( cb, tnv )
325
326 CARD cb[], tnv;
327{
328 int i, c0, c1;
329 long scr;
330
331 c0 = cb[0].rank;
332 c1 = cb[1].rank;
333 if( c0 > c1 ) {
334 i = c0;
335 c0 = c1;
336 c1 = i;
337 }
338 if( cb[0].suit != cb[1].suit ) scr = crbnescr[ RANKS*c0 + c1 ];
339 else scr = crbescr[ RANKS*c0 + c1 ];
340 if( scr <= 0 ) {
341 printf( "\nADJUST: internal error %d %d\n", c0, c1 );
342 exit( 93 );
343 }
344 return( (scr + 29400)/58800 );
345}
346
347
348