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