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