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