| 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 | |