score.c 10 KB

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