home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / games / cribbage / support.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-04-08  |  8.0 KB  |  358 lines

  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.