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 register 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, strcmp(s, "crib"), explain); 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 do_wait(); 105 } 106 else 107 win = chkscr(&pscore, i); 108 return win; 109 } 110 111 /* 112 * comphand: 113 * Handle scoring and displaying the computers hand 114 */ 115 comphand(h, s) 116 CARD h[]; 117 char *s; 118 { 119 register int j; 120 121 j = scorehand(h, turnover, CINHAND, FALSE, FALSE); 122 prhand(h, CINHAND, Compwin, 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 and put the 154 * score up on the board. 155 */ 156 prpeg(score, peg, myturn) 157 register int score; 158 char peg; 159 BOOLEAN myturn; 160 { 161 register int y, x; 162 163 if (!myturn) 164 y = SCORE_Y + 2; 165 else 166 y = SCORE_Y + 5; 167 168 if (score <= 0 || score >= glimit) { 169 if (peg == '.') 170 peg = ' '; 171 if (score == 0) 172 x = SCORE_X + 2; 173 else { 174 x = SCORE_X + 2; 175 y++; 176 } 177 } 178 else { 179 x = (score - 1) % 30; 180 if (score > 90 || (score > 30 && score <= 60)) { 181 y++; 182 x = 29 - x; 183 } 184 x += x / 5; 185 x += SCORE_X + 3; 186 } 187 mvaddch(y, x, peg); 188 mvprintw(SCORE_Y + (myturn ? 7 : 1), SCORE_X + 10, "%3d", score); 189 } 190 191 /* 192 * cdiscard -- the computer figures out what is the best discard for 193 * the crib and puts the best two cards at the end 194 */ 195 196 cdiscard( mycrib ) 197 198 BOOLEAN mycrib; 199 { 200 CARD d[ CARDS ], h[ FULLHAND ], cb[ 2 ]; 201 register int i, j, k; 202 int nc, ns; 203 long sums[ 15 ]; 204 static int undo1[15] = {0,0,0,0,0,1,1,1,1,2,2,2,3,3,4}; 205 static int undo2[15] = {1,2,3,4,5,2,3,4,5,3,4,5,4,5,5}; 206 207 makedeck( d ); 208 nc = CARDS; 209 for( i = 0; i < knownum; i++ ) { /* get all other cards */ 210 remove( known[i], d, nc-- ); 211 } 212 for( i = 0; i < 15; i++ ) sums[i] = 0L; 213 ns = 0; 214 for( i = 0; i < (FULLHAND - 1); i++ ) { 215 cb[0] = chand[i]; 216 for( j = i + 1; j < FULLHAND; j++ ) { 217 cb[1] = chand[j]; 218 for( k = 0; k < FULLHAND; k++ ) h[k] = chand[k]; 219 remove( chand[i], h, FULLHAND ); 220 remove( chand[j], h, FULLHAND - 1 ); 221 for( k = 0; k < nc; k++ ) { 222 sums[ns] += scorehand( h, d[k], CINHAND, TRUE, FALSE ); 223 if( mycrib ) sums[ns] += adjust( cb, d[k] ); 224 else sums[ns] -= adjust( cb, d[k] ); 225 } 226 ++ns; 227 } 228 } 229 j = 0; 230 for( i = 1; i < 15; i++ ) if( sums[i] > sums[j] ) j = i; 231 for( k = 0; k < FULLHAND; k++ ) h[k] = chand[k]; 232 remove( h[ undo1[j] ], chand, FULLHAND ); 233 remove( h[ undo2[j] ], chand, FULLHAND - 1 ); 234 chand[4] = h[ undo1[j] ]; 235 chand[5] = h[ undo2[j] ]; 236 } 237 238 239 240 /* 241 * returns true if some card in hand can be played without exceeding 31 242 */ 243 244 anymove( hand, n, sum ) 245 246 CARD hand[]; 247 int n; 248 int sum; 249 { 250 register int i, j; 251 252 if( n < 1 ) return( FALSE ); 253 j = hand[0].rank; 254 for( i = 1; i < n; i++ ) { 255 if( hand[i].rank < j ) j = hand[i].rank; 256 } 257 return( sum + VAL( j ) <= 31 ); 258 } 259 260 261 262 /* 263 * anysumto returns the index (0 <= i < n) of the card in hand that brings 264 * the s up to t, or -1 if there is none 265 */ 266 267 anysumto( hand, n, s, t ) 268 269 CARD hand[]; 270 int n; 271 int s, t; 272 { 273 register int i; 274 275 for( i = 0; i < n; i++ ) { 276 if( s + VAL( hand[i].rank ) == t ) return( i ); 277 } 278 return( -1 ); 279 } 280 281 282 283 284 /* 285 * return the number of cards in h having the given rank value 286 */ 287 288 numofval( h, n, v ) 289 290 CARD h[]; 291 int n; 292 int v; 293 { 294 register int i, j; 295 296 j = 0; 297 for( i = 0; i < n; i++ ) { 298 if( VAL( h[i].rank ) == v ) ++j; 299 } 300 return( j ); 301 } 302 303 304 305 /* 306 * makeknown remembers all n cards in h for future recall 307 */ 308 309 makeknown( h, n ) 310 311 CARD h[]; 312 int n; 313 { 314 register int i; 315 316 for( i = 0; i < n; i++ ) { 317 known[ knownum++ ] = h[i]; 318 } 319 } 320 321