1 /*- 2 * Copyright (c) 1980, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 */ 7 8 #ifndef lint 9 static char sccsid[] = "@(#)support.c 8.1 (Berkeley) 05/31/93"; 10 #endif /* not lint */ 11 12 #include <curses.h> 13 #include <string.h> 14 15 #include "deck.h" 16 #include "cribbage.h" 17 #include "cribcur.h" 18 19 #define NTV 10 /* number scores to test */ 20 21 /* score to test reachability of, and order to test them in */ 22 int tv[NTV] = {8, 7, 9, 6, 11, 12, 13, 14, 10, 5}; 23 24 /* 25 * computer chooses what to play in pegging... 26 * only called if no playable card will score points 27 */ 28 int 29 cchose(h, n, s) 30 CARD h[]; 31 int n, s; 32 { 33 register int i, j, l; 34 35 if (n <= 1) 36 return (0); 37 if (s < 4) { /* try for good value */ 38 if ((j = anysumto(h, n, s, 4)) >= 0) 39 return (j); 40 if ((j = anysumto(h, n, s, 3)) >= 0 && s == 0) 41 return (j); 42 } 43 if (s > 0 && s < 20) { 44 /* try for retaliation to 31 */ 45 for (i = 1; i <= 10; i++) { 46 if ((j = anysumto(h, n, s, 21 - i)) >= 0) { 47 if ((l = numofval(h, n, i)) > 0) { 48 if (l > 1 || VAL(h[j].rank) != i) 49 return (j); 50 } 51 } 52 } 53 } 54 if (s < 15) { 55 /* for retaliation after 15 */ 56 for (i = 0; i < NTV; i++) { 57 if ((j = anysumto(h, n, s, tv[i])) >= 0) { 58 if ((l = numofval(h, n, 15 - tv[i])) > 0) { 59 if (l > 1 || 60 VAL(h[j].rank) != 15 - tv[i]) 61 return (j); 62 } 63 } 64 } 65 } 66 j = -1; 67 /* remember: h is sorted */ 68 for (i = n - 1; i >= 0; --i) { 69 l = s + VAL(h[i].rank); 70 if (l > 31) 71 continue; 72 if (l != 5 && l != 10 && l != 21) { 73 j = i; 74 break; 75 } 76 } 77 if (j >= 0) 78 return (j); 79 for (i = n - 1; i >= 0; --i) { 80 l = s + VAL(h[i].rank); 81 if (l > 31) 82 continue; 83 if (j < 0) 84 j = i; 85 if (l != 5 && l != 21) { 86 j = i; 87 break; 88 } 89 } 90 return (j); 91 } 92 93 /* 94 * plyrhand: 95 * Evaluate and score a player hand or crib 96 */ 97 int 98 plyrhand(hand, s) 99 CARD hand[]; 100 char *s; 101 { 102 static char prompt[BUFSIZ]; 103 register int i, j; 104 register BOOLEAN win; 105 106 prhand(hand, CINHAND, Playwin, FALSE); 107 (void) sprintf(prompt, "Your %s scores ", s); 108 i = scorehand(hand, turnover, CINHAND, strcmp(s, "crib") == 0, explain); 109 if ((j = number(0, 29, prompt)) == 19) 110 j = 0; 111 if (i != j) { 112 if (i < j) { 113 win = chkscr(&pscore, i); 114 msg("It's really only %d points; I get %d", i, 2); 115 if (!win) 116 win = chkscr(&cscore, 2); 117 } else { 118 win = chkscr(&pscore, j); 119 msg("You should have taken %d, not %d!", i, j); 120 } 121 if (explain) 122 msg("Explanation: %s", expl); 123 do_wait(); 124 } else 125 win = chkscr(&pscore, i); 126 return (win); 127 } 128 129 /* 130 * comphand: 131 * Handle scoring and displaying the computers hand 132 */ 133 int 134 comphand(h, s) 135 CARD h[]; 136 char *s; 137 { 138 register int j; 139 140 j = scorehand(h, turnover, CINHAND, strcmp(s, "crib") == 0, FALSE); 141 prhand(h, CINHAND, Compwin, FALSE); 142 msg("My %s scores %d", s, (j == 0 ? 19 : j)); 143 return (chkscr(&cscore, j)); 144 } 145 146 /* 147 * chkscr: 148 * Add inc to scr and test for > glimit, printing on the scoring 149 * board while we're at it. 150 */ 151 int Lastscore[2] = {-1, -1}; 152 153 int 154 chkscr(scr, inc) 155 int *scr, inc; 156 { 157 BOOLEAN myturn; 158 159 myturn = (scr == &cscore); 160 if (inc != 0) { 161 prpeg(Lastscore[myturn], '.', myturn); 162 Lastscore[myturn] = *scr; 163 *scr += inc; 164 prpeg(*scr, PEG, myturn); 165 refresh(); 166 } 167 return (*scr >= glimit); 168 } 169 170 /* 171 * prpeg: 172 * Put out the peg character on the score board and put the 173 * score up on the board. 174 */ 175 void 176 prpeg(score, peg, myturn) 177 register int score; 178 int peg; 179 BOOLEAN myturn; 180 { 181 register int y, x; 182 183 if (!myturn) 184 y = SCORE_Y + 2; 185 else 186 y = SCORE_Y + 5; 187 188 if (score <= 0 || score >= glimit) { 189 if (peg == '.') 190 peg = ' '; 191 if (score == 0) 192 x = SCORE_X + 2; 193 else { 194 x = SCORE_X + 2; 195 y++; 196 } 197 } else { 198 x = (score - 1) % 30; 199 if (score > 90 || (score > 30 && score <= 60)) { 200 y++; 201 x = 29 - x; 202 } 203 x += x / 5; 204 x += SCORE_X + 3; 205 } 206 mvaddch(y, x, peg); 207 mvprintw(SCORE_Y + (myturn ? 7 : 1), SCORE_X + 10, "%3d", score); 208 } 209 210 /* 211 * cdiscard -- the computer figures out what is the best discard for 212 * the crib and puts the best two cards at the end 213 */ 214 void 215 cdiscard(mycrib) 216 BOOLEAN mycrib; 217 { 218 CARD d[CARDS], h[FULLHAND], cb[2]; 219 register int i, j, k; 220 int nc, ns; 221 long sums[15]; 222 static int undo1[15] = {0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 3, 3, 4}; 223 static int undo2[15] = {1, 2, 3, 4, 5, 2, 3, 4, 5, 3, 4, 5, 4, 5, 5}; 224 225 makedeck(d); 226 nc = CARDS; 227 for (i = 0; i < knownum; i++) { /* get all other cards */ 228 cremove(known[i], d, nc--); 229 } 230 for (i = 0; i < 15; i++) 231 sums[i] = 0L; 232 ns = 0; 233 for (i = 0; i < (FULLHAND - 1); i++) { 234 cb[0] = chand[i]; 235 for (j = i + 1; j < FULLHAND; j++) { 236 cb[1] = chand[j]; 237 for (k = 0; k < FULLHAND; k++) 238 h[k] = chand[k]; 239 cremove(chand[i], h, FULLHAND); 240 cremove(chand[j], h, FULLHAND - 1); 241 for (k = 0; k < nc; k++) { 242 sums[ns] += 243 scorehand(h, d[k], CINHAND, TRUE, FALSE); 244 if (mycrib) 245 sums[ns] += adjust(cb, d[k]); 246 else 247 sums[ns] -= adjust(cb, d[k]); 248 } 249 ++ns; 250 } 251 } 252 j = 0; 253 for (i = 1; i < 15; i++) 254 if (sums[i] > sums[j]) 255 j = i; 256 for (k = 0; k < FULLHAND; k++) 257 h[k] = chand[k]; 258 cremove(h[undo1[j]], chand, FULLHAND); 259 cremove(h[undo2[j]], chand, FULLHAND - 1); 260 chand[4] = h[undo1[j]]; 261 chand[5] = h[undo2[j]]; 262 } 263 264 /* 265 * returns true if some card in hand can be played without exceeding 31 266 */ 267 int 268 anymove(hand, n, sum) 269 CARD hand[]; 270 int n, sum; 271 { 272 register int i, j; 273 274 if (n < 1) 275 return (FALSE); 276 j = hand[0].rank; 277 for (i = 1; i < n; i++) { 278 if (hand[i].rank < j) 279 j = hand[i].rank; 280 } 281 return (sum + VAL(j) <= 31); 282 } 283 284 /* 285 * anysumto returns the index (0 <= i < n) of the card in hand that brings 286 * the s up to t, or -1 if there is none 287 */ 288 int 289 anysumto(hand, n, s, t) 290 CARD hand[]; 291 int n, s, t; 292 { 293 register int i; 294 295 for (i = 0; i < n; i++) { 296 if (s + VAL(hand[i].rank) == t) 297 return (i); 298 } 299 return (-1); 300 } 301 302 /* 303 * return the number of cards in h having the given rank value 304 */ 305 int 306 numofval(h, n, v) 307 CARD h[]; 308 int n, v; 309 { 310 register int i, j; 311 312 j = 0; 313 for (i = 0; i < n; i++) { 314 if (VAL(h[i].rank) == v) 315 ++j; 316 } 317 return (j); 318 } 319 320 /* 321 * makeknown remembers all n cards in h for future recall 322 */ 323 void 324 makeknown(h, n) 325 CARD h[]; 326 int n; 327 { 328 register int i; 329 330 for (i = 0; i < n; i++) 331 known[knownum++] = h[i]; 332 } 333