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