1 /*- 2 * Copyright (c) 1980, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. Neither the name of the University nor the names of its contributors 14 * may be used to endorse or promote products derived from this software 15 * without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 * 29 * @(#)score.c 8.1 (Berkeley) 5/31/93 30 * $FreeBSD: src/games/cribbage/score.c,v 1.6 1999/11/30 03:48:47 billf Exp $ 31 * $DragonFly: src/games/cribbage/score.c,v 1.3 2005/08/03 13:31:00 eirikn Exp $ 32 */ 33 34 #include <curses.h> 35 #include <stdio.h> 36 #include <stdlib.h> 37 #include <string.h> 38 39 #include "deck.h" 40 #include "cribbage.h" 41 42 static int fifteens(CARD[], int); 43 static int pairuns(CARD[], int); 44 /* 45 * the following arrays give the sum of the scores of the (50 2)*48 = 58800 46 * hands obtainable for the crib given the two cards whose ranks index the 47 * array. the two arrays are for the case where the suits are equal and 48 * not equal respectively 49 */ 50 const long crbescr[169] = { 51 -10000, 271827, 278883, 332319, 347769, 261129, 250653, 253203, 248259, 52 243435, 256275, 237435, 231051, -10000, -10000, 412815, 295707, 349497, 53 267519, 262521, 259695, 254019, 250047, 262887, 244047, 237663, -10000, 54 -10000, -10000, 333987, 388629, 262017, 266787, 262971, 252729, 254475, 55 267315, 248475, 242091, -10000, -10000, -10000, -10000, 422097, 302787, 56 256437, 263751, 257883, 254271, 267111, 248271, 241887, -10000, -10000, 57 -10000, -10000, -10000, 427677, 387837, 349173, 347985, 423861, 436701, 58 417861, 411477, -10000, -10000, -10000, -10000, -10000, -10000, 336387, 59 298851, 338667, 236487, 249327, 230487, 224103, -10000, -10000, -10000, 60 -10000, -10000, -10000, -10000, 408483, 266691, 229803, 246195, 227355, 61 220971, -10000, -10000, -10000, -10000, -10000, -10000, -10000, -10000, 62 300675, 263787, 241695, 226407, 220023, -10000, -10000, -10000, -10000, 63 -10000, -10000, -10000, -10000, -10000, 295635, 273543, 219771, 216939, 64 -10000, -10000, -10000, -10000, -10000, -10000, -10000, -10000, -10000, 65 -10000, 306519, 252747, 211431, -10000, -10000, -10000, -10000, -10000, 66 -10000, -10000, -10000, -10000, -10000, -10000, 304287, 262971, -10000, 67 -10000, -10000, -10000, -10000, -10000, -10000, -10000, -10000, -10000, 68 -10000, -10000, 244131, -10000, -10000, -10000, -10000, -10000, -10000, 69 -10000, -10000, -10000, -10000, -10000, -10000, -10000 70 }; 71 72 const long crbnescr[169] = { 73 325272, 260772, 267828, 321264, 336714, 250074, 239598, 242148, 237204, 74 232380, 246348, 226380, 219996, -10000, 342528, 401760, 284652, 338442, 75 256464, 251466, 248640, 242964, 238992, 252960, 232992, 226608, -10000, 76 -10000, 362280, 322932, 377574, 250962, 255732, 251916, 241674, 243420, 77 257388, 237420, 231036, -10000, -10000, -10000, 360768, 411042, 291732, 78 245382, 252696, 246828, 243216, 257184, 237216, 230832, -10000, -10000, 79 -10000, -10000, 528768, 416622, 376782, 338118, 336930, 412806, 426774, 80 406806, 400422, -10000, -10000, -10000, -10000, -10000, 369864, 325332, 81 287796, 327612, 225432, 239400, 219432, 213048, -10000, -10000, -10000, 82 -10000, -10000, -10000, 359160, 397428, 255636, 218748, 236268, 216300, 83 209916, -10000, -10000, -10000, -10000, -10000, -10000, -10000, 331320, 84 289620, 252732, 231768, 215352, 208968, -10000, -10000, -10000, -10000, 85 -10000, -10000, -10000, -10000, 325152, 284580, 263616, 208716, 205884, 86 -10000, -10000, -10000, -10000, -10000, -10000, -10000, -10000, -10000, 87 321240, 296592, 241692, 200376, -10000, -10000, -10000, -10000, -10000, 88 -10000, -10000, -10000, -10000, -10000, 348600, 294360, 253044, -10000, 89 -10000, -10000, -10000, -10000, -10000, -10000, -10000, -10000, -10000, 90 -10000, 308664, 233076, -10000, -10000, -10000, -10000, -10000, -10000, 91 -10000, -10000, -10000, -10000, -10000, -10000, 295896 92 }; 93 94 static const int ichoose2[5] = { 0, 0, 2, 6, 12 }; 95 static int pairpoints, runpoints; /* Globals from pairuns. */ 96 97 /* 98 * scorehand: 99 * Score the given hand of n cards and the starter card. 100 * n must be <= 4 101 * crb is true if scoring crib 102 * do_explain is true if must explain this hand 103 */ 104 int 105 scorehand(CARD hand[], CARD starter, int n, bool crb, bool do_explain) 106 { 107 int i, k; 108 int score; 109 bool flag; 110 CARD h[(CINHAND + 1)]; 111 char buf[32]; 112 113 explstr[0] = '\0'; /* initialize explanation */ 114 score = 0; 115 flag = true; 116 k = hand[0].suit; 117 for (i = 0; i < n; i++) { /* check for flush */ 118 flag = (flag && (hand[i].suit == k)); 119 if (hand[i].rank == JACK) /* check for his nibs */ 120 if (hand[i].suit == starter.suit) { 121 score++; 122 if (do_explain) 123 strcat(explstr, "His Nobs"); 124 } 125 h[i] = hand[i]; 126 } 127 128 if (flag && n >= CINHAND) { 129 if (do_explain && explstr[0] != '\0') 130 strcat(explstr, ", "); 131 if (starter.suit == k) { 132 score += 5; 133 if (do_explain) 134 strcat(explstr, "Five-flush"); 135 } else 136 if (!crb) { 137 score += 4; 138 if (do_explain && explstr[0] != '\0') 139 strcat(explstr, ", Four-flush"); 140 else 141 strcpy(explstr, "Four-flush"); 142 } 143 } 144 if (do_explain && explstr[0] != '\0') 145 strcat(explstr, ", "); 146 h[n] = starter; 147 sorthand(h, n + 1); /* sort by rank */ 148 i = 2 * fifteens(h, n + 1); 149 score += i; 150 if (do_explain) { 151 if (i > 0) { 152 sprintf(buf, "%d points in fifteens", i); 153 strcat(explstr, buf); 154 } else 155 strcat(explstr, "No fifteens"); 156 } 157 i = pairuns(h, n + 1); 158 score += i; 159 if (do_explain) { 160 if (i > 0) { 161 sprintf(buf, ", %d points in pairs, %d in runs", 162 pairpoints, runpoints); 163 strcat(explstr, buf); 164 } else 165 strcat(explstr, ", No pairs/runs"); 166 } 167 return (score); 168 } 169 170 /* 171 * fifteens: 172 * Return number of fifteens in hand of n cards 173 */ 174 static int 175 fifteens(CARD hand[], int n) 176 { 177 int *sp, *np; 178 int i; 179 CARD *endp; 180 static int sums[15], nsums[15]; 181 182 np = nsums; 183 sp = sums; 184 i = 16; 185 while (--i) { 186 *np++ = 0; 187 *sp++ = 0; 188 } 189 for (endp = &hand[n]; hand < endp; hand++) { 190 i = hand->rank + 1; 191 if (i > 10) 192 i = 10; 193 np = &nsums[i]; 194 np[-1]++; /* one way to make this */ 195 sp = sums; 196 while (i < 15) { 197 *np++ += *sp++; 198 i++; 199 } 200 sp = sums; 201 np = nsums; 202 i = 16; 203 while (--i) 204 *sp++ = *np++; 205 } 206 return sums[14]; 207 } 208 209 /* 210 * pairuns returns the number of points in the n card sorted hand 211 * due to pairs and runs 212 * this routine only works if n is strictly less than 6 213 * sets the globals pairpoints and runpoints appropriately 214 */ 215 static int 216 pairuns(CARD h[], int n) 217 { 218 int i; 219 int runlength, runmult, lastmult, curmult; 220 int mult1, mult2, pair1, pair2; 221 bool run; 222 223 run = true; 224 runlength = 1; 225 mult1 = 1; 226 pair1 = -1; 227 mult2 = 1; 228 pair2 = -1; 229 curmult = runmult = 1; 230 for (i = 1; i < n; i++) { 231 lastmult = curmult; 232 if (h[i].rank == h[i - 1].rank) { 233 if (pair1 < 0) { 234 pair1 = h[i].rank; 235 mult1 = curmult = 2; 236 } else { 237 if (h[i].rank == pair1) { 238 curmult = ++mult1; 239 } else { 240 if (pair2 < 0) { 241 pair2 = h[i].rank; 242 mult2 = curmult = 2; 243 } else { 244 curmult = ++mult2; 245 } 246 } 247 } 248 if (i == (n - 1) && run) { 249 runmult *= curmult; 250 } 251 } else { 252 curmult = 1; 253 if (h[i].rank == h[i - 1].rank + 1) { 254 if (run) { 255 ++runlength; 256 } else { 257 /* only if old short */ 258 if (runlength < 3) { 259 run = true; 260 runlength = 2; 261 runmult = 1; 262 } 263 } 264 runmult *= lastmult; 265 } else { 266 /* if just ended */ 267 if (run) 268 runmult *= lastmult; 269 run = false; 270 } 271 } 272 } 273 pairpoints = ichoose2[mult1] + ichoose2[mult2]; 274 runpoints = (runlength >= 3 ? runlength * runmult : 0); 275 return (pairpoints + runpoints); 276 } 277 278 /* 279 * pegscore tells how many points crd would get if played after 280 * the n cards in tbl during pegging 281 */ 282 int 283 pegscore(CARD crd, CARD tbl[], int n, int sum) 284 { 285 bool got[RANKS]; 286 int i, j, scr; 287 int k, lo, hi; 288 289 sum += VAL(crd.rank); 290 if (sum > 31) 291 return (-1); 292 if (sum == 31 || sum == 15) 293 scr = 2; 294 else 295 scr = 0; 296 if (!n) 297 return (scr); 298 j = 1; 299 while ((crd.rank == tbl[n - j].rank) && (n - j >= 0)) 300 ++j; 301 if (j > 1) 302 return (scr + ichoose2[j]); 303 if (n < 2) 304 return (scr); 305 lo = hi = crd.rank; 306 for (i = 0; i < RANKS; i++) 307 got[i] = false; 308 got[crd.rank] = true; 309 k = -1; 310 for (i = n - 1; i >= 0; --i) { 311 if (got[tbl[i].rank]) 312 break; 313 got[tbl[i].rank] = true; 314 if (tbl[i].rank < lo) 315 lo = tbl[i].rank; 316 if (tbl[i].rank > hi) 317 hi = tbl[i].rank; 318 for (j = lo; j <= hi; j++) 319 if (!got[j]) 320 break; 321 if (j > hi) 322 k = hi - lo + 1; 323 } 324 if (k >= 3) 325 return (scr + k); 326 else 327 return (scr); 328 } 329 330 /* 331 * adjust takes a two card hand that will be put in the crib 332 * and returns an adjusted normalized score for the number of 333 * points such a crib will get. 334 */ 335 int 336 adjust(CARD cb[]) 337 { 338 long scr; 339 int i, c0, c1; 340 341 c0 = cb[0].rank; 342 c1 = cb[1].rank; 343 if (c0 > c1) { 344 i = c0; 345 c0 = c1; 346 c1 = i; 347 } 348 if (cb[0].suit != cb[1].suit) 349 scr = crbnescr[RANKS * c0 + c1]; 350 else 351 scr = crbescr[RANKS * c0 + c1]; 352 if (scr <= 0) { 353 printf("\nADJUST: internal error %d %d\n", c0, c1); 354 exit(93); 355 } 356 return ((scr + 29400) / 58800); 357 } 358