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