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