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%
621507Smckusick */
712573Sarnold
821507Smckusick #ifndef lint
9*60777Sbostic static char sccsid[] = "@(#)support.c 8.1 (Berkeley) 05/31/93";
1033707Sbostic #endif /* not lint */
1121507Smckusick
1259264Sbostic #include <curses.h>
1359264Sbostic #include <string.h>
147711Sarnold
1559264Sbostic #include "deck.h"
1659264Sbostic #include "cribbage.h"
1759264Sbostic #include "cribcur.h"
187711Sarnold
1959264Sbostic #define NTV 10 /* number scores to test */
207711Sarnold
217711Sarnold /* score to test reachability of, and order to test them in */
2259264Sbostic int tv[NTV] = {8, 7, 9, 6, 11, 12, 13, 14, 10, 5};
237711Sarnold
247711Sarnold /*
257711Sarnold * computer chooses what to play in pegging...
267711Sarnold * only called if no playable card will score points
277711Sarnold */
2859264Sbostic int
cchose(h,n,s)2959264Sbostic cchose(h, n, s)
3059264Sbostic CARD h[];
3159264Sbostic int n, s;
327711Sarnold {
3359264Sbostic register int i, j, l;
347711Sarnold
3559264Sbostic if (n <= 1)
3659264Sbostic return (0);
3759264Sbostic if (s < 4) { /* try for good value */
3859264Sbostic if ((j = anysumto(h, n, s, 4)) >= 0)
3959264Sbostic return (j);
4059264Sbostic if ((j = anysumto(h, n, s, 3)) >= 0 && s == 0)
4159264Sbostic return (j);
427711Sarnold }
4359264Sbostic if (s > 0 && s < 20) {
4459264Sbostic /* try for retaliation to 31 */
4559264Sbostic for (i = 1; i <= 10; i++) {
4659264Sbostic if ((j = anysumto(h, n, s, 21 - i)) >= 0) {
4759264Sbostic if ((l = numofval(h, n, i)) > 0) {
4859264Sbostic if (l > 1 || VAL(h[j].rank) != i)
4959264Sbostic return (j);
5059264Sbostic }
5159264Sbostic }
527711Sarnold }
537711Sarnold }
5459264Sbostic if (s < 15) {
5559264Sbostic /* for retaliation after 15 */
5659264Sbostic for (i = 0; i < NTV; i++) {
5759264Sbostic if ((j = anysumto(h, n, s, tv[i])) >= 0) {
5859264Sbostic if ((l = numofval(h, n, 15 - tv[i])) > 0) {
5959264Sbostic if (l > 1 ||
6059264Sbostic VAL(h[j].rank) != 15 - tv[i])
6159264Sbostic return (j);
6259264Sbostic }
6359264Sbostic }
647711Sarnold }
657711Sarnold }
667711Sarnold j = -1;
6759264Sbostic /* remember: h is sorted */
6859264Sbostic for (i = n - 1; i >= 0; --i) {
6959264Sbostic l = s + VAL(h[i].rank);
7059264Sbostic if (l > 31)
7159264Sbostic continue;
7259264Sbostic if (l != 5 && l != 10 && l != 21) {
7359264Sbostic j = i;
7459264Sbostic break;
7559264Sbostic }
767711Sarnold }
7759264Sbostic if (j >= 0)
7859264Sbostic return (j);
7959264Sbostic for (i = n - 1; i >= 0; --i) {
8059264Sbostic l = s + VAL(h[i].rank);
8159264Sbostic if (l > 31)
8259264Sbostic continue;
8359264Sbostic if (j < 0)
8459264Sbostic j = i;
8559264Sbostic if (l != 5 && l != 21) {
8659264Sbostic j = i;
8759264Sbostic break;
8859264Sbostic }
897711Sarnold }
9059264Sbostic return (j);
917711Sarnold }
927711Sarnold
937711Sarnold /*
947873Sarnold * plyrhand:
957873Sarnold * Evaluate and score a player hand or crib
967711Sarnold */
9759264Sbostic int
plyrhand(hand,s)987873Sarnold plyrhand(hand, s)
9959264Sbostic CARD hand[];
10059264Sbostic char *s;
1017711Sarnold {
10259264Sbostic static char prompt[BUFSIZ];
10359264Sbostic register int i, j;
10459264Sbostic register BOOLEAN win;
1057711Sarnold
10659264Sbostic prhand(hand, CINHAND, Playwin, FALSE);
10759264Sbostic (void) sprintf(prompt, "Your %s scores ", s);
10859264Sbostic i = scorehand(hand, turnover, CINHAND, strcmp(s, "crib") == 0, explain);
10959264Sbostic if ((j = number(0, 29, prompt)) == 19)
11059264Sbostic j = 0;
11159264Sbostic if (i != j) {
11259264Sbostic if (i < j) {
11359264Sbostic win = chkscr(&pscore, i);
11459264Sbostic msg("It's really only %d points; I get %d", i, 2);
11559264Sbostic if (!win)
11659264Sbostic win = chkscr(&cscore, 2);
11759264Sbostic } else {
11859264Sbostic win = chkscr(&pscore, j);
11959264Sbostic msg("You should have taken %d, not %d!", i, j);
12059264Sbostic }
12159264Sbostic if (explain)
12259264Sbostic msg("Explanation: %s", expl);
12359264Sbostic do_wait();
12459264Sbostic } else
12559264Sbostic win = chkscr(&pscore, i);
12659264Sbostic return (win);
1277711Sarnold }
1287711Sarnold
1297873Sarnold /*
1307873Sarnold * comphand:
1317873Sarnold * Handle scoring and displaying the computers hand
1327873Sarnold */
13359264Sbostic int
comphand(h,s)1347873Sarnold comphand(h, s)
13559264Sbostic CARD h[];
13659264Sbostic char *s;
1377873Sarnold {
13859264Sbostic register int j;
1397711Sarnold
14014910Sarnold j = scorehand(h, turnover, CINHAND, strcmp(s, "crib") == 0, FALSE);
1418074Sarnold prhand(h, CINHAND, Compwin, FALSE);
1427873Sarnold msg("My %s scores %d", s, (j == 0 ? 19 : j));
14359264Sbostic return (chkscr(&cscore, j));
1447873Sarnold }
1457711Sarnold
1467711Sarnold /*
1477873Sarnold * chkscr:
1487873Sarnold * Add inc to scr and test for > glimit, printing on the scoring
1497873Sarnold * board while we're at it.
1507711Sarnold */
15159264Sbostic int Lastscore[2] = {-1, -1};
1527711Sarnold
15359264Sbostic int
chkscr(scr,inc)1547873Sarnold chkscr(scr, inc)
15559264Sbostic int *scr, inc;
1567711Sarnold {
15759264Sbostic BOOLEAN myturn;
1587711Sarnold
1597873Sarnold myturn = (scr == &cscore);
1607873Sarnold if (inc != 0) {
1617873Sarnold prpeg(Lastscore[myturn], '.', myturn);
1627873Sarnold Lastscore[myturn] = *scr;
1637938Sarnold *scr += inc;
1647938Sarnold prpeg(*scr, PEG, myturn);
1658136Sarnold refresh();
1667873Sarnold }
1677936Sarnold return (*scr >= glimit);
1687711Sarnold }
1697711Sarnold
1707711Sarnold /*
1717873Sarnold * prpeg:
17211398Sarnold * Put out the peg character on the score board and put the
17311398Sarnold * score up on the board.
1747711Sarnold */
17559264Sbostic void
prpeg(score,peg,myturn)1767873Sarnold prpeg(score, peg, myturn)
17759264Sbostic register int score;
17859264Sbostic int peg;
17959264Sbostic BOOLEAN myturn;
1807873Sarnold {
18159264Sbostic register int y, x;
1827711Sarnold
1837873Sarnold if (!myturn)
1847873Sarnold y = SCORE_Y + 2;
1857873Sarnold else
1867873Sarnold y = SCORE_Y + 5;
1877938Sarnold
1887938Sarnold if (score <= 0 || score >= glimit) {
1897938Sarnold if (peg == '.')
1907938Sarnold peg = ' ';
1917938Sarnold if (score == 0)
1927938Sarnold x = SCORE_X + 2;
1937938Sarnold else {
1947938Sarnold x = SCORE_X + 2;
1957938Sarnold y++;
1967938Sarnold }
19759264Sbostic } else {
1987938Sarnold x = (score - 1) % 30;
1997938Sarnold if (score > 90 || (score > 30 && score <= 60)) {
2007938Sarnold y++;
2017938Sarnold x = 29 - x;
2027938Sarnold }
2037938Sarnold x += x / 5;
2047938Sarnold x += SCORE_X + 3;
2057938Sarnold }
2067873Sarnold mvaddch(y, x, peg);
20711398Sarnold mvprintw(SCORE_Y + (myturn ? 7 : 1), SCORE_X + 10, "%3d", score);
2087711Sarnold }
2097711Sarnold
2107711Sarnold /*
2117711Sarnold * cdiscard -- the computer figures out what is the best discard for
2127711Sarnold * the crib and puts the best two cards at the end
2137711Sarnold */
21459264Sbostic void
cdiscard(mycrib)21559264Sbostic cdiscard(mycrib)
21659264Sbostic BOOLEAN mycrib;
2177711Sarnold {
21859264Sbostic CARD d[CARDS], h[FULLHAND], cb[2];
21959264Sbostic register int i, j, k;
22059264Sbostic int nc, ns;
22159264Sbostic long sums[15];
22259264Sbostic static int undo1[15] = {0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 3, 3, 4};
22359264Sbostic static int undo2[15] = {1, 2, 3, 4, 5, 2, 3, 4, 5, 3, 4, 5, 4, 5, 5};
2247711Sarnold
22559264Sbostic makedeck(d);
2267711Sarnold nc = CARDS;
22759264Sbostic for (i = 0; i < knownum; i++) { /* get all other cards */
22859264Sbostic cremove(known[i], d, nc--);
2297711Sarnold }
23059264Sbostic for (i = 0; i < 15; i++)
23159264Sbostic sums[i] = 0L;
2327711Sarnold ns = 0;
23359264Sbostic for (i = 0; i < (FULLHAND - 1); i++) {
23459264Sbostic cb[0] = chand[i];
23559264Sbostic for (j = i + 1; j < FULLHAND; j++) {
23659264Sbostic cb[1] = chand[j];
23759264Sbostic for (k = 0; k < FULLHAND; k++)
23859264Sbostic h[k] = chand[k];
23959264Sbostic cremove(chand[i], h, FULLHAND);
24059264Sbostic cremove(chand[j], h, FULLHAND - 1);
24159264Sbostic for (k = 0; k < nc; k++) {
24259264Sbostic sums[ns] +=
24359264Sbostic scorehand(h, d[k], CINHAND, TRUE, FALSE);
24459264Sbostic if (mycrib)
24559264Sbostic sums[ns] += adjust(cb, d[k]);
24659264Sbostic else
24759264Sbostic sums[ns] -= adjust(cb, d[k]);
24859264Sbostic }
24959264Sbostic ++ns;
2507711Sarnold }
2517711Sarnold }
2527711Sarnold j = 0;
25359264Sbostic for (i = 1; i < 15; i++)
25459264Sbostic if (sums[i] > sums[j])
25559264Sbostic j = i;
25659264Sbostic for (k = 0; k < FULLHAND; k++)
25759264Sbostic h[k] = chand[k];
25859264Sbostic cremove(h[undo1[j]], chand, FULLHAND);
25959264Sbostic cremove(h[undo2[j]], chand, FULLHAND - 1);
26059264Sbostic chand[4] = h[undo1[j]];
26159264Sbostic chand[5] = h[undo2[j]];
2627711Sarnold }
2637711Sarnold
2647711Sarnold /*
2657711Sarnold * returns true if some card in hand can be played without exceeding 31
2667711Sarnold */
26759264Sbostic int
anymove(hand,n,sum)26859264Sbostic anymove(hand, n, sum)
26959264Sbostic CARD hand[];
27059264Sbostic int n, sum;
2717711Sarnold {
27259264Sbostic register int i, j;
2737711Sarnold
27459264Sbostic if (n < 1)
27559264Sbostic return (FALSE);
2767711Sarnold j = hand[0].rank;
27759264Sbostic for (i = 1; i < n; i++) {
27859264Sbostic if (hand[i].rank < j)
27959264Sbostic j = hand[i].rank;
2807711Sarnold }
28159264Sbostic return (sum + VAL(j) <= 31);
2827711Sarnold }
2837711Sarnold
2847711Sarnold /*
2857711Sarnold * anysumto returns the index (0 <= i < n) of the card in hand that brings
2867711Sarnold * the s up to t, or -1 if there is none
2877711Sarnold */
28859264Sbostic int
anysumto(hand,n,s,t)28959264Sbostic anysumto(hand, n, s, t)
29059264Sbostic CARD hand[];
29159264Sbostic int n, s, t;
2927711Sarnold {
29359264Sbostic register int i;
2947711Sarnold
29559264Sbostic for (i = 0; i < n; i++) {
29659264Sbostic if (s + VAL(hand[i].rank) == t)
29759264Sbostic return (i);
2987711Sarnold }
29959264Sbostic return (-1);
3007711Sarnold }
3017711Sarnold
3027711Sarnold /*
3037711Sarnold * return the number of cards in h having the given rank value
3047711Sarnold */
30559264Sbostic int
numofval(h,n,v)30659264Sbostic numofval(h, n, v)
30759264Sbostic CARD h[];
30859264Sbostic int n, v;
3097711Sarnold {
31059264Sbostic register int i, j;
3117711Sarnold
3127711Sarnold j = 0;
31359264Sbostic for (i = 0; i < n; i++) {
31459264Sbostic if (VAL(h[i].rank) == v)
31559264Sbostic ++j;
3167711Sarnold }
31759264Sbostic return (j);
3187711Sarnold }
3197711Sarnold
3207711Sarnold /*
3217711Sarnold * makeknown remembers all n cards in h for future recall
3227711Sarnold */
32359264Sbostic void
makeknown(h,n)32459264Sbostic makeknown(h, n)
32559264Sbostic CARD h[];
32659264Sbostic int n;
3277711Sarnold {
32859264Sbostic register int i;
3297711Sarnold
33059264Sbostic for (i = 0; i < n; i++)
33159264Sbostic known[knownum++] = h[i];
3327711Sarnold }
333