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