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