Commit | Line | Data |
---|---|---|
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 | 19 | static 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 | ||
34 | long 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 | ||
55 | long 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 | ||
77 | static int ichoose2[ 5 ] = { 0, 0, 2, 6, 12 }; | |
78 | static 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 |
86 | scorehand(hand, starter, n, crb, do_explain) |
87 | register CARD hand[]; | |
88 | CARD starter; | |
89 | int n; | |
90 | BOOLEAN crb; /* true if scoring crib */ | |
91 | BOOLEAN 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 |
161 | fifteens(hand, n) |
162 | register CARD hand[]; | |
163 | int 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 | ||
206 | pairuns( 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 | ||
281 | pegscore( 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 | ||
324 | adjust( 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 |