date and time created 82/08/11 16:36:06 by arnold
authorKen Arnold <arnold@ucbvax.Berkeley.EDU>
Thu, 12 Aug 1982 07:36:06 +0000 (23:36 -0800)
committerKen Arnold <arnold@ucbvax.Berkeley.EDU>
Thu, 12 Aug 1982 07:36:06 +0000 (23:36 -0800)
SCCS-vsn: games/cribbage/support.c 1.1

usr/src/games/cribbage/support.c [new file with mode: 0644]

diff --git a/usr/src/games/cribbage/support.c b/usr/src/games/cribbage/support.c
new file mode 100644 (file)
index 0000000..3369626
--- /dev/null
@@ -0,0 +1,279 @@
+
+#include       <stdio.h>
+#include       "deck.h"
+#include       "cribbage.h"
+
+
+#define                NTV             10              /* number scores to test */
+
+/* score to test reachability of, and order to test them in */
+int            tv[ NTV ]       = { 8, 7, 9, 6, 11, 12, 13, 14, 10, 5 };
+
+
+/*
+ * computer chooses what to play in pegging...
+ * only called if no playable card will score points
+ */
+
+cchose( h, n, s )
+
+    CARD               h[];
+    int                        n;
+    int                        s;
+{
+       register  int           i, j, l;
+
+       if(  n <= 1  )  return( 0 );
+       if(  s < 4  )  {                /* try for good value */
+           if(  ( j = anysumto(h, n, s, 4) )  >=  0  )  return( j );
+           if(  ( j = anysumto(h, n, s, 3) ) >= 0  &&  s == 0  )
+                                                               return( j );
+       }
+       if(  s > 0  &&  s < 20  )  {
+           for( i = 1; i <= 10; i++ )  {       /* try for retaliation to 31 */
+               if(  ( j = anysumto(h, n, s, 21-i) )  >=  0  )  {
+                   if(  ( l = numofval(h, n, i) )  >  0  )  {
+                       if(  l > 1  ||  VAL( h[j].rank ) != i  )  return( j );
+                   }
+               }
+           }
+       }
+       if(  s < 15  )  {
+           for( i = 0; i < NTV; i++ )  {       /* for retaliation after 15 */
+               if(  ( j = anysumto(h, n, s, tv[i]) )  >=  0  )  {
+                   if(  ( l = numofval(h, n, 15-tv[i]) )  >  0  )  {
+                       if(  l > 1  ||  VAL( h[j].rank ) != 15-tv[i]  )  return( j );
+                   }
+               }
+           }
+       }
+       j = -1;
+       for( i = n - 1; i >= 0; --i )  {        /* remember: h is sorted */
+           l = s + VAL( h[i].rank );
+           if(  l > 31  )  continue;
+           if(  l != 5  &&  l != 10  &&  l != 21  )  {
+               j = i;
+               break;
+           }
+       }
+       if(  j >= 0  )  return( j );
+       for( i = n - 1; i >= 0; --i )  {
+           l = s + VAL( h[i].rank );
+           if(  l > 31  )  continue;
+           if(  j < 0  )  j = i;
+           if(  l != 5  &&  l != 21  )  {
+               j = i;
+               break;
+           }
+       }
+       return( j );
+}
+
+
+
+/*
+ * evaluate and score a player hand or crib
+ */
+
+plyrhand( hand, s )
+
+    CARD               hand[];
+    char               *s;
+{
+       register  int           i, j;
+       BOOLEAN                 win;
+
+       printf( "Your %s is: ", s );
+       prhand( hand, CINHAND, TRUE );
+       printf( "  [" );
+       printcard( turnover, TRUE );
+       printf( "].   How many points? " );
+       i = scorehand( hand, turnover, CINHAND, FALSE );        /* count */
+       if(  ( j = number(0, 29) )  ==  19  )  j = 0;
+       if(  i != j  )  {
+           if( i < j )  {
+               win = chkscr( &pscore, i );
+               printf( "It's really only %d points, I get %d.\n", i, 2 );
+               if( !win )  win = chkscr( &cscore, 2 );
+           }
+           else  {
+               win = chkscr( &pscore, j );
+               printf( "You should have taken %d, not %d!\n", i, j );
+           }
+           if( explain )  {
+               printf( "Explanation: %s\n", expl );
+           }
+       }
+       else  {
+           win = chkscr( &pscore, i );
+       }
+       return(  win  );
+}
+
+
+
+/*
+ * handle scoring and displaying the computers hand
+ */
+
+comphand( h, s )
+
+    CARD               h[];
+    char               *s;
+{
+       register  int           j;
+
+       j = scorehand( h, turnover, CINHAND, FALSE );
+       printf( "My %s ( ", s );
+       prhand( h, CINHAND, TRUE );
+       printf( "  [" );
+       printcard( turnover, TRUE );
+       printf( "] ) scores %d.\n", (j == 0 ? 19 : j) );
+       return(  chkscr( &cscore, j )  );
+}
+
+
+
+/*
+ * add inc to scr and test for > glimit
+ */
+
+chkscr( scr, inc )
+
+    int                        *scr, inc;
+{
+       return(  ( (*scr += inc) >= glimit ? TRUE : FALSE )  );
+}
+
+
+
+/*
+ * cdiscard -- the computer figures out what is the best discard for
+ * the crib and puts the best two cards at the end
+ */
+
+cdiscard( mycrib )
+
+    BOOLEAN            mycrib;
+{
+       CARD                    d[ CARDS ],  h[ FULLHAND ],  cb[ 2 ];
+       register  int           i, j, k;
+       int                     nc, ns;
+       long                    sums[ 15 ];
+       static  int             undo1[15]   = {0,0,0,0,0,1,1,1,1,2,2,2,3,3,4};
+       static  int             undo2[15]   = {1,2,3,4,5,2,3,4,5,3,4,5,4,5,5};
+
+       makedeck( d );
+       nc = CARDS;
+       for( i = 0; i < knownum; i++ )  {       /* get all other cards */
+           remove( known[i], d, nc-- );
+       }
+       for( i = 0; i < 15; i++ )  sums[i] = 0L;
+       ns = 0;
+       for( i = 0; i < (FULLHAND - 1); i++ )  {
+           cb[0] = chand[i];
+           for( j = i + 1; j < FULLHAND; j++ )  {
+               cb[1] = chand[j];
+               for( k = 0; k < FULLHAND; k++ )  h[k] = chand[k];
+               remove( chand[i], h, FULLHAND );
+               remove( chand[j], h, FULLHAND - 1 );
+               for( k = 0; k < nc; k++ )  {
+                   sums[ns] += scorehand( h, d[k], CINHAND, TRUE );
+                   if( mycrib )  sums[ns] += adjust( cb, d[k] );
+                   else          sums[ns] -= adjust( cb, d[k] );
+               }
+               ++ns;
+           }
+       }
+       j = 0;
+       for( i = 1; i < 15; i++ )  if(  sums[i] > sums[j]  )  j = i;
+       for( k = 0; k < FULLHAND; k++ )  h[k] = chand[k];
+       remove( h[ undo1[j] ], chand, FULLHAND );
+       remove( h[ undo2[j] ], chand, FULLHAND - 1 );
+       chand[4] = h[ undo1[j] ];
+       chand[5] = h[ undo2[j] ];
+}
+
+
+
+/*
+ * returns true if some card in hand can be played without exceeding 31
+ */
+
+anymove( hand, n, sum )
+
+    CARD               hand[];
+    int                        n;
+    int                        sum;
+{
+       register  int           i, j;
+
+       if(  n < 1  )  return( FALSE );
+       j = hand[0].rank;
+       for( i = 1; i < n; i++ )  {
+           if(  hand[i].rank < j  )  j = hand[i].rank;
+       }
+       return(  sum + VAL( j )  <=  31  );
+}
+
+
+
+/*
+ * anysumto returns the index (0 <= i < n) of the card in hand that brings
+ * the s up to t, or -1 if there is none
+ */
+
+anysumto( hand, n, s, t )
+
+    CARD               hand[];
+    int                        n;
+    int                        s,  t;
+{
+       register  int           i;
+
+       for( i = 0; i < n; i++ )  {
+           if(  s + VAL( hand[i].rank )  ==  t  )  return( i );
+       }
+       return( -1 );
+}
+
+
+
+
+/*
+ * return the number of cards in h having the given rank value
+ */
+
+numofval( h, n, v )
+
+    CARD               h[];
+    int                        n;
+    int                        v;
+{
+       register  int           i, j;
+
+       j = 0;
+       for( i = 0; i < n; i++ )  {
+           if(  VAL( h[i].rank )  ==  v  )  ++j;
+       }
+       return( j );
+}
+
+
+
+/*
+ * makeknown remembers all n cards in h for future recall
+ */
+
+makeknown( h, n )
+
+    CARD               h[];
+    int                        n;
+{
+       register  int           i;
+
+       for( i = 0; i < n; i++ )  {
+           known[ knownum++ ] = h[i];
+       }
+}
+