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