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. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by the University of 16 * California, Berkeley and its contributors. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 * 33 * @(#)support.c 8.1 (Berkeley) 5/31/93 34 * $FreeBSD: src/games/cribbage/support.c,v 1.5 1999/12/12 03:04:15 billf Exp $ 35 * $DragonFly: src/games/cribbage/support.c,v 1.2 2003/06/17 04:25:23 dillon Exp $ 36 */ 37 38 #include <curses.h> 39 #include <string.h> 40 41 #include "deck.h" 42 #include "cribbage.h" 43 #include "cribcur.h" 44 45 #define NTV 10 /* number scores to test */ 46 47 /* score to test reachability of, and order to test them in */ 48 int tv[NTV] = {8, 7, 9, 6, 11, 12, 13, 14, 10, 5}; 49 50 /* 51 * computer chooses what to play in pegging... 52 * only called if no playable card will score points 53 */ 54 int 55 cchose(h, n, s) 56 CARD h[]; 57 int n, s; 58 { 59 int i, j, l; 60 61 if (n <= 1) 62 return (0); 63 if (s < 4) { /* try for good value */ 64 if ((j = anysumto(h, n, s, 4)) >= 0) 65 return (j); 66 if ((j = anysumto(h, n, s, 3)) >= 0 && s == 0) 67 return (j); 68 } 69 if (s > 0 && s < 20) { 70 /* try for retaliation to 31 */ 71 for (i = 1; i <= 10; i++) { 72 if ((j = anysumto(h, n, s, 21 - i)) >= 0) { 73 if ((l = numofval(h, n, i)) > 0) { 74 if (l > 1 || VAL(h[j].rank) != i) 75 return (j); 76 } 77 } 78 } 79 } 80 if (s < 15) { 81 /* for retaliation after 15 */ 82 for (i = 0; i < NTV; i++) { 83 if ((j = anysumto(h, n, s, tv[i])) >= 0) { 84 if ((l = numofval(h, n, 15 - tv[i])) > 0) { 85 if (l > 1 || 86 VAL(h[j].rank) != 15 - tv[i]) 87 return (j); 88 } 89 } 90 } 91 } 92 j = -1; 93 /* remember: h is sorted */ 94 for (i = n - 1; i >= 0; --i) { 95 l = s + VAL(h[i].rank); 96 if (l > 31) 97 continue; 98 if (l != 5 && l != 10 && l != 21) { 99 j = i; 100 break; 101 } 102 } 103 if (j >= 0) 104 return (j); 105 for (i = n - 1; i >= 0; --i) { 106 l = s + VAL(h[i].rank); 107 if (l > 31) 108 continue; 109 if (j < 0) 110 j = i; 111 if (l != 5 && l != 21) { 112 j = i; 113 break; 114 } 115 } 116 return (j); 117 } 118 119 /* 120 * plyrhand: 121 * Evaluate and score a player hand or crib 122 */ 123 int 124 plyrhand(hand, s) 125 CARD hand[]; 126 char *s; 127 { 128 static char prompt[BUFSIZ]; 129 int i, j; 130 BOOLEAN win; 131 132 prhand(hand, CINHAND, Playwin, FALSE); 133 (void) sprintf(prompt, "Your %s scores ", s); 134 i = scorehand(hand, turnover, CINHAND, strcmp(s, "crib") == 0, explain); 135 if ((j = number(0, 29, prompt)) == 19) 136 j = 0; 137 if (i != j) { 138 if (i < j) { 139 win = chkscr(&pscore, i); 140 msg("It's really only %d points; I get %d", i, 2); 141 if (!win) 142 win = chkscr(&cscore, 2); 143 } else { 144 win = chkscr(&pscore, j); 145 msg("You should have taken %d, not %d!", i, j); 146 } 147 if (explain) 148 msg("Explanation: %s", expl); 149 do_wait(); 150 } else 151 win = chkscr(&pscore, i); 152 return (win); 153 } 154 155 /* 156 * comphand: 157 * Handle scoring and displaying the computers hand 158 */ 159 int 160 comphand(h, s) 161 CARD h[]; 162 char *s; 163 { 164 int j; 165 166 j = scorehand(h, turnover, CINHAND, strcmp(s, "crib") == 0, FALSE); 167 prhand(h, CINHAND, Compwin, FALSE); 168 msg("My %s scores %d", s, (j == 0 ? 19 : j)); 169 return (chkscr(&cscore, j)); 170 } 171 172 /* 173 * chkscr: 174 * Add inc to scr and test for > glimit, printing on the scoring 175 * board while we're at it. 176 */ 177 int Lastscore[2] = {-1, -1}; 178 179 int 180 chkscr(scr, inc) 181 int *scr, inc; 182 { 183 BOOLEAN myturn; 184 185 myturn = (scr == &cscore); 186 if (inc != 0) { 187 prpeg(Lastscore[myturn ? 1 : 0], '.', myturn); 188 Lastscore[myturn ? 1 : 0] = *scr; 189 *scr += inc; 190 prpeg(*scr, PEG, myturn); 191 refresh(); 192 } 193 return (*scr >= glimit); 194 } 195 196 /* 197 * prpeg: 198 * Put out the peg character on the score board and put the 199 * score up on the board. 200 */ 201 void 202 prpeg(score, peg, myturn) 203 int score; 204 int peg; 205 BOOLEAN myturn; 206 { 207 int y, x; 208 209 if (!myturn) 210 y = SCORE_Y + 2; 211 else 212 y = SCORE_Y + 5; 213 214 if (score <= 0 || score >= glimit) { 215 if (peg == '.') 216 peg = ' '; 217 if (score == 0) 218 x = SCORE_X + 2; 219 else { 220 x = SCORE_X + 2; 221 y++; 222 } 223 } else { 224 x = (score - 1) % 30; 225 if (score > 90 || (score > 30 && score <= 60)) { 226 y++; 227 x = 29 - x; 228 } 229 x += x / 5; 230 x += SCORE_X + 3; 231 } 232 mvaddch(y, x, peg); 233 mvprintw(SCORE_Y + (myturn ? 7 : 1), SCORE_X + 10, "%3d", score); 234 } 235 236 /* 237 * cdiscard -- the computer figures out what is the best discard for 238 * the crib and puts the best two cards at the end 239 */ 240 void 241 cdiscard(mycrib) 242 BOOLEAN mycrib; 243 { 244 CARD d[CARDS], h[FULLHAND], cb[2]; 245 int i, j, k; 246 int nc, ns; 247 long sums[15]; 248 static int undo1[15] = {0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 3, 3, 4}; 249 static int undo2[15] = {1, 2, 3, 4, 5, 2, 3, 4, 5, 3, 4, 5, 4, 5, 5}; 250 251 makedeck(d); 252 nc = CARDS; 253 for (i = 0; i < knownum; i++) { /* get all other cards */ 254 cremove(known[i], d, nc--); 255 } 256 for (i = 0; i < 15; i++) 257 sums[i] = 0L; 258 ns = 0; 259 for (i = 0; i < (FULLHAND - 1); i++) { 260 cb[0] = chand[i]; 261 for (j = i + 1; j < FULLHAND; j++) { 262 cb[1] = chand[j]; 263 for (k = 0; k < FULLHAND; k++) 264 h[k] = chand[k]; 265 cremove(chand[i], h, FULLHAND); 266 cremove(chand[j], h, FULLHAND - 1); 267 for (k = 0; k < nc; k++) { 268 sums[ns] += 269 scorehand(h, d[k], CINHAND, TRUE, FALSE); 270 if (mycrib) 271 sums[ns] += adjust(cb, d[k]); 272 else 273 sums[ns] -= adjust(cb, d[k]); 274 } 275 ++ns; 276 } 277 } 278 j = 0; 279 for (i = 1; i < 15; i++) 280 if (sums[i] > sums[j]) 281 j = i; 282 for (k = 0; k < FULLHAND; k++) 283 h[k] = chand[k]; 284 cremove(h[undo1[j]], chand, FULLHAND); 285 cremove(h[undo2[j]], chand, FULLHAND - 1); 286 chand[4] = h[undo1[j]]; 287 chand[5] = h[undo2[j]]; 288 } 289 290 /* 291 * returns true if some card in hand can be played without exceeding 31 292 */ 293 int 294 anymove(hand, n, sum) 295 CARD hand[]; 296 int n, sum; 297 { 298 int i, j; 299 300 if (n < 1) 301 return (FALSE); 302 j = hand[0].rank; 303 for (i = 1; i < n; i++) { 304 if (hand[i].rank < j) 305 j = hand[i].rank; 306 } 307 return (sum + VAL(j) <= 31); 308 } 309 310 /* 311 * anysumto returns the index (0 <= i < n) of the card in hand that brings 312 * the s up to t, or -1 if there is none 313 */ 314 int 315 anysumto(hand, n, s, t) 316 CARD hand[]; 317 int n, s, t; 318 { 319 int i; 320 321 for (i = 0; i < n; i++) { 322 if (s + VAL(hand[i].rank) == t) 323 return (i); 324 } 325 return (-1); 326 } 327 328 /* 329 * return the number of cards in h having the given rank value 330 */ 331 int 332 numofval(h, n, v) 333 CARD h[]; 334 int n, v; 335 { 336 int i, j; 337 338 j = 0; 339 for (i = 0; i < n; i++) { 340 if (VAL(h[i].rank) == v) 341 ++j; 342 } 343 return (j); 344 } 345 346 /* 347 * makeknown remembers all n cards in h for future recall 348 */ 349 void 350 makeknown(h, n) 351 CARD h[]; 352 int n; 353 { 354 int i; 355 356 for (i = 0; i < n; i++) 357 known[knownum++] = h[i]; 358 } 359