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