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