Home | History | Annotate | Line # | Download | only in cribbage
support.c revision 1.1
      1 /*
      2  * Copyright (c) 1980 Regents of the University of California.
      3  * All rights reserved.
      4  *
      5  * Redistribution and use in source and binary forms, with or without
      6  * modification, are permitted provided that the following conditions
      7  * are met:
      8  * 1. Redistributions of source code must retain the above copyright
      9  *    notice, this list of conditions and the following disclaimer.
     10  * 2. Redistributions in binary form must reproduce the above copyright
     11  *    notice, this list of conditions and the following disclaimer in the
     12  *    documentation and/or other materials provided with the distribution.
     13  * 3. All advertising materials mentioning features or use of this software
     14  *    must display the following acknowledgement:
     15  *	This product includes software developed by the University of
     16  *	California, Berkeley and its contributors.
     17  * 4. Neither the name of the University nor the names of its contributors
     18  *    may be used to endorse or promote products derived from this software
     19  *    without specific prior written permission.
     20  *
     21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     31  * SUCH DAMAGE.
     32  */
     33 
     34 #ifndef lint
     35 static char sccsid[] = "@(#)support.c	5.6 (Berkeley) 2/28/91";
     36 #endif /* not lint */
     37 
     38 #include	<curses.h>
     39 #include	"deck.h"
     40 #include	"cribbage.h"
     41 #include	"cribcur.h"
     42 
     43 
     44 #define		NTV		10		/* number scores to test */
     45 
     46 /* score to test reachability of, and order to test them in */
     47 int		tv[ NTV ]	= { 8, 7, 9, 6, 11, 12, 13, 14, 10, 5 };
     48 
     49 
     50 /*
     51  * computer chooses what to play in pegging...
     52  * only called if no playable card will score points
     53  */
     54 
     55 cchose( h, n, s )
     56 
     57     CARD		h[];
     58     int			n;
     59     int			s;
     60 {
     61 	register  int		i, j, l;
     62 
     63 	if(  n <= 1  )  return( 0 );
     64 	if(  s < 4  )  {		/* try for good value */
     65 	    if(  ( j = anysumto(h, n, s, 4) )  >=  0  )  return( j );
     66 	    if(  ( j = anysumto(h, n, s, 3) ) >= 0  &&  s == 0  )
     67 								return( j );
     68 	}
     69 	if(  s > 0  &&  s < 20  )  {
     70 	    for( i = 1; i <= 10; i++ )  {	/* try for retaliation to 31 */
     71 		if(  ( j = anysumto(h, n, s, 21-i) )  >=  0  )  {
     72 		    if(  ( l = numofval(h, n, i) )  >  0  )  {
     73 			if(  l > 1  ||  VAL( h[j].rank ) != i  )  return( j );
     74 		    }
     75 		}
     76 	    }
     77 	}
     78 	if(  s < 15  )  {
     79 	    for( i = 0; i < NTV; i++ )  {	/* for retaliation after 15 */
     80 		if(  ( j = anysumto(h, n, s, tv[i]) )  >=  0  )  {
     81 		    if(  ( l = numofval(h, n, 15-tv[i]) )  >  0  )  {
     82 			if(  l > 1  ||  VAL( h[j].rank ) != 15-tv[i]  )  return( j );
     83 		    }
     84 		}
     85 	    }
     86 	}
     87 	j = -1;
     88 	for( i = n - 1; i >= 0; --i )  {	/* remember: h is sorted */
     89 	    l = s + VAL( h[i].rank );
     90 	    if(  l > 31  )  continue;
     91 	    if(  l != 5  &&  l != 10  &&  l != 21  )  {
     92 		j = i;
     93 		break;
     94 	    }
     95 	}
     96 	if(  j >= 0  )  return( j );
     97 	for( i = n - 1; i >= 0; --i )  {
     98 	    l = s + VAL( h[i].rank );
     99 	    if(  l > 31  )  continue;
    100 	    if(  j < 0  )  j = i;
    101 	    if(  l != 5  &&  l != 21  )  {
    102 		j = i;
    103 		break;
    104 	    }
    105 	}
    106 	return( j );
    107 }
    108 
    109 
    110 
    111 /*
    112  * plyrhand:
    113  *	Evaluate and score a player hand or crib
    114  */
    115 plyrhand(hand, s)
    116 CARD		hand[];
    117 char		*s;
    118 {
    119     register int	i, j;
    120     register BOOLEAN	win;
    121     static char		prompt[BUFSIZ];
    122 
    123     prhand(hand, CINHAND, Playwin, FALSE);
    124     (void)sprintf(prompt, "Your %s scores ", s);
    125     i = scorehand(hand, turnover, CINHAND, strcmp(s, "crib") == 0, explain);
    126     if ((j = number(0, 29, prompt)) == 19)
    127 	j = 0;
    128     if (i != j) {
    129 	if (i < j) {
    130 	    win = chkscr(&pscore, i);
    131 	    msg("It's really only %d points; I get %d", i, 2);
    132 	    if (!win)
    133 		win = chkscr(&cscore, 2);
    134 	}
    135 	else {
    136 	    win = chkscr(&pscore, j);
    137 	    msg("You should have taken %d, not %d!", i, j);
    138 	}
    139 	if (explain)
    140 	    msg("Explanation: %s", expl);
    141 	do_wait();
    142     }
    143     else
    144 	win = chkscr(&pscore, i);
    145     return win;
    146 }
    147 
    148 /*
    149  * comphand:
    150  *	Handle scoring and displaying the computers hand
    151  */
    152 comphand(h, s)
    153 CARD		h[];
    154 char		*s;
    155 {
    156 	register int		j;
    157 
    158 	j = scorehand(h, turnover, CINHAND, strcmp(s, "crib") == 0, FALSE);
    159 	prhand(h, CINHAND, Compwin, FALSE);
    160 	msg("My %s scores %d", s, (j == 0 ? 19 : j));
    161 	return chkscr(&cscore, j);
    162 }
    163 
    164 /*
    165  * chkscr:
    166  *	Add inc to scr and test for > glimit, printing on the scoring
    167  *	board while we're at it.
    168  */
    169 
    170 int	Lastscore[2] = {-1, -1};
    171 
    172 chkscr(scr, inc)
    173 int		*scr, inc;
    174 {
    175 	BOOLEAN		myturn;
    176 
    177 	myturn = (scr == &cscore);
    178 	if (inc != 0) {
    179 		prpeg(Lastscore[myturn], '.', myturn);
    180 		Lastscore[myturn] = *scr;
    181 		*scr += inc;
    182 		prpeg(*scr, PEG, myturn);
    183 		refresh();
    184 	}
    185 	return (*scr >= glimit);
    186 }
    187 
    188 /*
    189  * prpeg:
    190  *	Put out the peg character on the score board and put the
    191  *	score up on the board.
    192  */
    193 prpeg(score, peg, myturn)
    194 register int	score;
    195 char		peg;
    196 BOOLEAN		myturn;
    197 {
    198 	register int	y, x;
    199 
    200 	if (!myturn)
    201 		y = SCORE_Y + 2;
    202 	else
    203 		y = SCORE_Y + 5;
    204 
    205 	if (score <= 0 || score >= glimit) {
    206 		if (peg == '.')
    207 			peg = ' ';
    208 		if (score == 0)
    209 			x = SCORE_X + 2;
    210 		else {
    211 			x = SCORE_X + 2;
    212 			y++;
    213 		}
    214 	}
    215 	else {
    216 		x = (score - 1) % 30;
    217 		if (score > 90 || (score > 30 && score <= 60)) {
    218 			y++;
    219 			x = 29 - x;
    220 		}
    221 		x += x / 5;
    222 		x += SCORE_X + 3;
    223 	}
    224 	mvaddch(y, x, peg);
    225 	mvprintw(SCORE_Y + (myturn ? 7 : 1), SCORE_X + 10, "%3d", score);
    226 }
    227 
    228 /*
    229  * cdiscard -- the computer figures out what is the best discard for
    230  * the crib and puts the best two cards at the end
    231  */
    232 
    233 cdiscard( mycrib )
    234 
    235     BOOLEAN		mycrib;
    236 {
    237 	CARD			d[ CARDS ],  h[ FULLHAND ],  cb[ 2 ];
    238 	register  int		i, j, k;
    239 	int			nc, ns;
    240 	long			sums[ 15 ];
    241 	static  int		undo1[15]   = {0,0,0,0,0,1,1,1,1,2,2,2,3,3,4};
    242 	static  int		undo2[15]   = {1,2,3,4,5,2,3,4,5,3,4,5,4,5,5};
    243 
    244 	makedeck( d );
    245 	nc = CARDS;
    246 	for( i = 0; i < knownum; i++ )  {	/* get all other cards */
    247 	    cremove( known[i], d, nc-- );
    248 	}
    249 	for( i = 0; i < 15; i++ )  sums[i] = 0L;
    250 	ns = 0;
    251 	for( i = 0; i < (FULLHAND - 1); i++ )  {
    252 	    cb[0] = chand[i];
    253 	    for( j = i + 1; j < FULLHAND; j++ )  {
    254 		cb[1] = chand[j];
    255 		for( k = 0; k < FULLHAND; k++ )  h[k] = chand[k];
    256 		cremove( chand[i], h, FULLHAND );
    257 		cremove( chand[j], h, FULLHAND - 1 );
    258 		for( k = 0; k < nc; k++ )  {
    259 		    sums[ns] += scorehand( h, d[k], CINHAND, TRUE, FALSE );
    260 		    if( mycrib )  sums[ns] += adjust( cb, d[k] );
    261 		    else	  sums[ns] -= adjust( cb, d[k] );
    262 		}
    263 		++ns;
    264 	    }
    265 	}
    266 	j = 0;
    267 	for( i = 1; i < 15; i++ )  if(  sums[i] > sums[j]  )  j = i;
    268 	for( k = 0; k < FULLHAND; k++ )  h[k] = chand[k];
    269 	cremove( h[ undo1[j] ], chand, FULLHAND );
    270 	cremove( h[ undo2[j] ], chand, FULLHAND - 1 );
    271 	chand[4] = h[ undo1[j] ];
    272 	chand[5] = h[ undo2[j] ];
    273 }
    274 
    275 
    276 
    277 /*
    278  * returns true if some card in hand can be played without exceeding 31
    279  */
    280 
    281 anymove( hand, n, sum )
    282 
    283     CARD		hand[];
    284     int			n;
    285     int			sum;
    286 {
    287 	register  int		i, j;
    288 
    289 	if(  n < 1  )  return( FALSE );
    290 	j = hand[0].rank;
    291 	for( i = 1; i < n; i++ )  {
    292 	    if(  hand[i].rank < j  )  j = hand[i].rank;
    293 	}
    294 	return(  sum + VAL( j )  <=  31  );
    295 }
    296 
    297 
    298 
    299 /*
    300  * anysumto returns the index (0 <= i < n) of the card in hand that brings
    301  * the s up to t, or -1 if there is none
    302  */
    303 
    304 anysumto( hand, n, s, t )
    305 
    306     CARD		hand[];
    307     int			n;
    308     int			s,  t;
    309 {
    310 	register  int		i;
    311 
    312 	for( i = 0; i < n; i++ )  {
    313 	    if(  s + VAL( hand[i].rank )  ==  t  )  return( i );
    314 	}
    315 	return( -1 );
    316 }
    317 
    318 
    319 
    320 
    321 /*
    322  * return the number of cards in h having the given rank value
    323  */
    324 
    325 numofval( h, n, v )
    326 
    327     CARD		h[];
    328     int			n;
    329     int			v;
    330 {
    331 	register  int		i, j;
    332 
    333 	j = 0;
    334 	for( i = 0; i < n; i++ )  {
    335 	    if(  VAL( h[i].rank )  ==  v  )  ++j;
    336 	}
    337 	return( j );
    338 }
    339 
    340 
    341 
    342 /*
    343  * makeknown remembers all n cards in h for future recall
    344  */
    345 
    346 makeknown( h, n )
    347 
    348     CARD		h[];
    349     int			n;
    350 {
    351 	register  int		i;
    352 
    353 	for( i = 0; i < n; i++ )  {
    354 	    known[ knownum++ ] = h[i];
    355 	}
    356 }
    357 
    358