xref: /csrg-svn/games/cribbage/score.c (revision 60777)
159264Sbostic /*-
2*60777Sbostic  * Copyright (c) 1980, 1993
3*60777Sbostic  *	The Regents of the University of California.  All rights reserved.
433707Sbostic  *
542577Sbostic  * %sccs.include.redist.c%
621506Smckusick  */
77710Sarnold 
821506Smckusick #ifndef lint
9*60777Sbostic static char sccsid[] = "@(#)score.c	8.1 (Berkeley) 05/31/93";
1033707Sbostic #endif /* not lint */
1121506Smckusick 
1259264Sbostic #include <curses.h>
1359264Sbostic #include <stdio.h>
1459264Sbostic #include <stdlib.h>
1559264Sbostic #include <string.h>
167710Sarnold 
1759264Sbostic #include "deck.h"
1859264Sbostic #include "cribbage.h"
197710Sarnold 
207710Sarnold /*
217710Sarnold  * the following arrays give the sum of the scores of the (50 2)*48 = 58800
227710Sarnold  * hands obtainable for the crib given the two cards whose ranks index the
237710Sarnold  * array.  the two arrays are for the case where the suits are equal and
247710Sarnold  * not equal respectively
257710Sarnold  */
2659264Sbostic long crbescr[169] = {
277710Sarnold     -10000, 271827, 278883, 332319, 347769, 261129, 250653, 253203, 248259,
287710Sarnold     243435, 256275, 237435, 231051, -10000, -10000, 412815, 295707, 349497,
297710Sarnold     267519, 262521, 259695, 254019, 250047, 262887, 244047, 237663, -10000,
307710Sarnold     -10000, -10000, 333987, 388629, 262017, 266787, 262971, 252729, 254475,
317710Sarnold     267315, 248475, 242091, -10000, -10000, -10000, -10000, 422097, 302787,
327710Sarnold     256437, 263751, 257883, 254271, 267111, 248271, 241887, -10000, -10000,
337710Sarnold     -10000, -10000, -10000, 427677, 387837, 349173, 347985, 423861, 436701,
347710Sarnold     417861, 411477, -10000, -10000, -10000, -10000, -10000, -10000, 336387,
357710Sarnold     298851, 338667, 236487, 249327, 230487, 224103, -10000, -10000, -10000,
367710Sarnold     -10000, -10000, -10000, -10000, 408483, 266691, 229803, 246195, 227355,
377710Sarnold     220971, -10000, -10000, -10000, -10000, -10000, -10000, -10000, -10000,
387710Sarnold     300675, 263787, 241695, 226407, 220023, -10000, -10000, -10000, -10000,
397710Sarnold     -10000, -10000, -10000, -10000, -10000, 295635, 273543, 219771, 216939,
407710Sarnold     -10000, -10000, -10000, -10000, -10000, -10000, -10000, -10000, -10000,
417710Sarnold     -10000, 306519, 252747, 211431, -10000, -10000, -10000, -10000, -10000,
427710Sarnold     -10000, -10000, -10000, -10000, -10000, -10000, 304287, 262971, -10000,
437710Sarnold     -10000, -10000, -10000, -10000, -10000, -10000, -10000, -10000, -10000,
447710Sarnold     -10000, -10000, 244131, -10000, -10000, -10000, -10000, -10000, -10000,
4559264Sbostic     -10000, -10000, -10000, -10000, -10000, -10000, -10000
4659264Sbostic };
477710Sarnold 
4859264Sbostic long crbnescr[169] = {
497710Sarnold     325272, 260772, 267828, 321264, 336714, 250074, 239598, 242148, 237204,
507710Sarnold     232380, 246348, 226380, 219996, -10000, 342528, 401760, 284652, 338442,
517710Sarnold     256464, 251466, 248640, 242964, 238992, 252960, 232992, 226608, -10000,
527710Sarnold     -10000, 362280, 322932, 377574, 250962, 255732, 251916, 241674, 243420,
537710Sarnold     257388, 237420, 231036, -10000, -10000, -10000, 360768, 411042, 291732,
547710Sarnold     245382, 252696, 246828, 243216, 257184, 237216, 230832, -10000, -10000,
557710Sarnold     -10000, -10000, 528768, 416622, 376782, 338118, 336930, 412806, 426774,
567710Sarnold     406806, 400422, -10000, -10000, -10000, -10000, -10000, 369864, 325332,
577710Sarnold     287796, 327612, 225432, 239400, 219432, 213048, -10000, -10000, -10000,
587710Sarnold     -10000, -10000, -10000, 359160, 397428, 255636, 218748, 236268, 216300,
597710Sarnold     209916, -10000, -10000, -10000, -10000, -10000, -10000, -10000, 331320,
607710Sarnold     289620, 252732, 231768, 215352, 208968, -10000, -10000, -10000, -10000,
617710Sarnold     -10000, -10000, -10000, -10000, 325152, 284580, 263616, 208716, 205884,
627710Sarnold     -10000, -10000, -10000, -10000, -10000, -10000, -10000, -10000, -10000,
637710Sarnold     321240, 296592, 241692, 200376, -10000, -10000, -10000, -10000, -10000,
647710Sarnold     -10000, -10000, -10000, -10000, -10000, 348600, 294360, 253044, -10000,
657710Sarnold     -10000, -10000, -10000, -10000, -10000, -10000, -10000, -10000, -10000,
667710Sarnold     -10000, 308664, 233076, -10000, -10000, -10000, -10000, -10000, -10000,
6759264Sbostic     -10000, -10000, -10000, -10000, -10000, -10000, 295896
6859264Sbostic };
697710Sarnold 
7059264Sbostic static int ichoose2[5] = { 0, 0, 2, 6, 12 };
7159264Sbostic static int pairpoints, runpoints;		/* Globals from pairuns. */
727710Sarnold 
737710Sarnold /*
748009Sarnold  * scorehand:
758009Sarnold  *	Score the given hand of n cards and the starter card.
768009Sarnold  *	n must be <= 4
777710Sarnold  */
7859264Sbostic int
scorehand(hand,starter,n,crb,do_explain)798009Sarnold scorehand(hand, starter, n, crb, do_explain)
8059264Sbostic 	register CARD hand[];
8159264Sbostic 	CARD starter;
8259264Sbostic 	int n;
8359264Sbostic 	BOOLEAN crb;		/* true if scoring crib */
8459264Sbostic 	BOOLEAN do_explain;	/* true if must explain this hand */
857710Sarnold {
8659264Sbostic 	register int i, k;
8759264Sbostic 	register int score;
8859264Sbostic 	register BOOLEAN flag;
8959264Sbostic 	CARD h[(CINHAND + 1)];
9059264Sbostic 	char buf[32];
917710Sarnold 
927710Sarnold 	expl[0] = NULL;		/* initialize explanation */
937710Sarnold 	score = 0;
9414910Sarnold 	flag = TRUE;
957710Sarnold 	k = hand[0].suit;
9659264Sbostic 	for (i = 0; i < n; i++) {	/* check for flush */
9759264Sbostic 		flag = (flag && (hand[i].suit == k));
9859264Sbostic 		if (hand[i].rank == JACK)	/* check for his nibs */
9959264Sbostic 			if (hand[i].suit == starter.suit) {
10059264Sbostic 				score++;
10159264Sbostic 				if (do_explain)
10259264Sbostic 					strcat(expl, "His Nobs");
10359264Sbostic 			}
10459264Sbostic 		h[i] = hand[i];
1057710Sarnold 	}
1068009Sarnold 
1078009Sarnold 	if (flag && n >= CINHAND) {
1088009Sarnold 		if (do_explain && expl[0] != NULL)
10959264Sbostic 			strcat(expl, ", ");
11059264Sbostic 		if (starter.suit == k) {
11159264Sbostic 			score += 5;
11259264Sbostic 			if (do_explain)
11359264Sbostic 				strcat(expl, "Five-flush");
11459264Sbostic 		} else
11559264Sbostic 			if (!crb) {
11659264Sbostic 				score += 4;
11759264Sbostic 				if (do_explain && expl[0] != NULL)
11859264Sbostic 					strcat(expl, ", Four-flush");
11959264Sbostic 				else
12059264Sbostic 					strcpy(expl, "Four-flush");
12159264Sbostic 			}
1227710Sarnold 	}
1238009Sarnold 	if (do_explain && expl[0] != NULL)
12459264Sbostic 		strcat(expl, ", ");
1258009Sarnold 	h[n] = starter;
12659264Sbostic 	sorthand(h, n + 1);	/* sort by rank */
1278009Sarnold 	i = 2 * fifteens(h, n + 1);
1287710Sarnold 	score += i;
1298009Sarnold 	if (do_explain)
13059264Sbostic 		if (i > 0) {
13159264Sbostic 			(void) sprintf(buf, "%d points in fifteens", i);
13259264Sbostic 			strcat(expl, buf);
13359264Sbostic 		} else
13459264Sbostic 			strcat(expl, "No fifteens");
1358009Sarnold 	i = pairuns(h, n + 1);
1367710Sarnold 	score += i;
1378009Sarnold 	if (do_explain)
13859264Sbostic 		if (i > 0) {
13959264Sbostic 			(void) sprintf(buf, ", %d points in pairs, %d in runs",
14059264Sbostic 			    pairpoints, runpoints);
14159264Sbostic 			strcat(expl, buf);
14259264Sbostic 		} else
14359264Sbostic 			strcat(expl, ", No pairs/runs");
14459264Sbostic 	return (score);
1457710Sarnold }
1467710Sarnold 
1477710Sarnold /*
1488009Sarnold  * fifteens:
1498009Sarnold  *	Return number of fifteens in hand of n cards
1507710Sarnold  */
15159264Sbostic int
fifteens(hand,n)1528009Sarnold fifteens(hand, n)
15359264Sbostic 	register CARD hand[];
15459264Sbostic 	int n;
1557710Sarnold {
15659264Sbostic 	register int *sp, *np;
15759264Sbostic 	register int i;
15859264Sbostic 	register CARD *endp;
15959264Sbostic 	static int sums[15], nsums[15];
1607710Sarnold 
1618009Sarnold 	np = nsums;
1628009Sarnold 	sp = sums;
1638009Sarnold 	i = 16;
1648009Sarnold 	while (--i) {
16559264Sbostic 		*np++ = 0;
16659264Sbostic 		*sp++ = 0;
1678009Sarnold 	}
1688009Sarnold 	for (endp = &hand[n]; hand < endp; hand++) {
16959264Sbostic 		i = hand->rank + 1;
17059264Sbostic 		if (i > 10)
17159264Sbostic 			i = 10;
17259264Sbostic 		np = &nsums[i];
17359264Sbostic 		np[-1]++;	/* one way to make this */
17459264Sbostic 		sp = sums;
17559264Sbostic 		while (i < 15) {
17659264Sbostic 			*np++ += *sp++;
17759264Sbostic 			i++;
17859264Sbostic 		}
17959264Sbostic 		sp = sums;
18059264Sbostic 		np = nsums;
18159264Sbostic 		i = 16;
18259264Sbostic 		while (--i)
18359264Sbostic 			*sp++ = *np++;
1847710Sarnold 	}
1858009Sarnold 	return sums[14];
1867710Sarnold }
1877710Sarnold 
1887710Sarnold /*
1897710Sarnold  * pairuns returns the number of points in the n card sorted hand
1907710Sarnold  * due to pairs and runs
1917710Sarnold  * this routine only works if n is strictly less than 6
1927710Sarnold  * sets the globals pairpoints and runpoints appropriately
1937710Sarnold  */
19459264Sbostic int
pairuns(h,n)19559264Sbostic pairuns(h, n)
19659264Sbostic 	CARD h[];
19759264Sbostic 	int n;
1987710Sarnold {
19959264Sbostic 	register int i;
20059264Sbostic 	int runlength, runmult, lastmult, curmult;
20159264Sbostic 	int mult1, mult2, pair1, pair2;
20259264Sbostic 	BOOLEAN run;
2037710Sarnold 
2047710Sarnold 	run = TRUE;
2057710Sarnold 	runlength = 1;
2067710Sarnold 	mult1 = 1;
2077710Sarnold 	pair1 = -1;
2087710Sarnold 	mult2 = 1;
2097710Sarnold 	pair2 = -1;
2107710Sarnold 	curmult = runmult = 1;
21159264Sbostic 	for (i = 1; i < n; i++) {
21259264Sbostic 		lastmult = curmult;
21359264Sbostic 		if (h[i].rank == h[i - 1].rank) {
21459264Sbostic 			if (pair1 < 0) {
21559264Sbostic 				pair1 = h[i].rank;
21659264Sbostic 				mult1 = curmult = 2;
21759264Sbostic 			} else {
21859264Sbostic 				if (h[i].rank == pair1) {
21959264Sbostic 					curmult = ++mult1;
22059264Sbostic 				} else {
22159264Sbostic 					if (pair2 < 0) {
22259264Sbostic 						pair2 = h[i].rank;
22359264Sbostic 						mult2 = curmult = 2;
22459264Sbostic 					} else {
22559264Sbostic 						curmult = ++mult2;
22659264Sbostic 					}
22759264Sbostic 				}
2287710Sarnold 			}
22959264Sbostic 			if (i == (n - 1) && run) {
23059264Sbostic 				runmult *= curmult;
2317710Sarnold 			}
23259264Sbostic 		} else {
23359264Sbostic 			curmult = 1;
23459264Sbostic 			if (h[i].rank == h[i - 1].rank + 1) {
23559264Sbostic 				if (run) {
23659264Sbostic 					++runlength;
23759264Sbostic 				} else {
23859264Sbostic 							/* only if old short */
23959264Sbostic 					if (runlength < 3) {
24059264Sbostic 						run = TRUE;
24159264Sbostic 						runlength = 2;
24259264Sbostic 						runmult = 1;
24359264Sbostic 					}
24459264Sbostic 				}
24559264Sbostic 				runmult *= lastmult;
24659264Sbostic 			} else {
24759264Sbostic 							/* if just ended */
24859264Sbostic 				if (run)
24959264Sbostic 					runmult *= lastmult;
25059264Sbostic 				run = FALSE;
2517710Sarnold 			}
2527710Sarnold 		}
2537710Sarnold 	}
25459264Sbostic 	pairpoints = ichoose2[mult1] + ichoose2[mult2];
25559264Sbostic 	runpoints = (runlength >= 3 ? runlength * runmult : 0);
25659264Sbostic 	return (pairpoints + runpoints);
2577710Sarnold }
2587710Sarnold 
2597710Sarnold /*
2607710Sarnold  * pegscore tells how many points crd would get if played after
2617710Sarnold  * the n cards in tbl during pegging
2627710Sarnold  */
26359264Sbostic int
pegscore(crd,tbl,n,sum)26459264Sbostic pegscore(crd, tbl, n, sum)
26559264Sbostic 	CARD crd, tbl[];
26659264Sbostic 	int n, sum;
2677710Sarnold {
26859264Sbostic 	BOOLEAN got[RANKS];
26959264Sbostic 	register int i, j, scr;
27059264Sbostic 	int k, lo, hi;
2717710Sarnold 
27259264Sbostic 	sum += VAL(crd.rank);
27359264Sbostic 	if (sum > 31)
27459264Sbostic 		return (-1);
27559264Sbostic 	if (sum == 31 || sum == 15)
27659264Sbostic 		scr = 2;
27759264Sbostic 	else
27859264Sbostic 		scr = 0;
27959264Sbostic 	if (!n)
28059264Sbostic 		return (scr);
2817710Sarnold 	j = 1;
28259264Sbostic 	while ((crd.rank == tbl[n - j].rank) && (n - j >= 0))
28359264Sbostic 		++j;
28459264Sbostic 	if (j > 1)
28559264Sbostic 		return (scr + ichoose2[j]);
28659264Sbostic 	if (n < 2)
28759264Sbostic 		return (scr);
2887710Sarnold 	lo = hi = crd.rank;
28959264Sbostic 	for (i = 0; i < RANKS; i++)
29059264Sbostic 		got[i] = FALSE;
29159264Sbostic 	got[crd.rank] = TRUE;
2927710Sarnold 	k = -1;
29359264Sbostic 	for (i = n - 1; i >= 0; --i) {
29459264Sbostic 		if (got[tbl[i].rank])
29559264Sbostic 			break;
29659264Sbostic 		got[tbl[i].rank] = TRUE;
29759264Sbostic 		if (tbl[i].rank < lo)
29859264Sbostic 			lo = tbl[i].rank;
29959264Sbostic 		if (tbl[i].rank > hi)
30059264Sbostic 			hi = tbl[i].rank;
30159264Sbostic 		for (j = lo; j <= hi; j++)
30259264Sbostic 			if (!got[j])
30359264Sbostic 				break;
30459264Sbostic 		if (j > hi)
30559264Sbostic 			k = hi - lo + 1;
3067710Sarnold 	}
30759264Sbostic 	if (k >= 3)
30859264Sbostic 		return (scr + k);
30959264Sbostic 	else
31059264Sbostic 		return (scr);
3117710Sarnold }
3127710Sarnold 
3137710Sarnold /*
3147710Sarnold  * adjust takes a two card hand that will be put in the crib
3157710Sarnold  * and returns an adjusted normalized score for the number of
3167710Sarnold  * points such a crib will get.
3177710Sarnold  */
31859264Sbostic int
adjust(cb,tnv)31959264Sbostic adjust(cb, tnv)
32059264Sbostic 	CARD cb[], tnv;
3217710Sarnold {
32259264Sbostic 	long scr;
32359264Sbostic 	int i, c0, c1;
3247710Sarnold 
3257710Sarnold 	c0 = cb[0].rank;
3267710Sarnold 	c1 = cb[1].rank;
32759264Sbostic 	if (c0 > c1) {
32859264Sbostic 		i = c0;
32959264Sbostic 		c0 = c1;
33059264Sbostic 		c1 = i;
3317710Sarnold 	}
33259264Sbostic 	if (cb[0].suit != cb[1].suit)
33359264Sbostic 		scr = crbnescr[RANKS * c0 + c1];
33459264Sbostic 	else
33559264Sbostic 		scr = crbescr[RANKS * c0 + c1];
33659264Sbostic 	if (scr <= 0) {
33759264Sbostic 		printf("\nADJUST: internal error %d %d\n", c0, c1);
33859264Sbostic 		exit(93);
3397710Sarnold 	}
34059264Sbostic 	return ((scr + 29400) / 58800);
3417710Sarnold }
342