NGROUPS -> 8, u.u_groups
[unix-history] / usr / src / games / cribbage / support.c
CommitLineData
feeca497
KA
1
2#include <stdio.h>
3#include "deck.h"
4#include "cribbage.h"
5
6
7#define NTV 10 /* number scores to test */
8
9/* score to test reachability of, and order to test them in */
10int 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
18cchose( 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 * evaluate and score a player hand or crib
76 */
77
78plyrhand( hand, s )
79
80 CARD hand[];
81 char *s;
82{
83 register int i, j;
84 BOOLEAN win;
85
86 printf( "Your %s is: ", s );
87 prhand( hand, CINHAND, TRUE );
88 printf( " [" );
89 printcard( turnover, TRUE );
90 printf( "]. How many points? " );
91 i = scorehand( hand, turnover, CINHAND, FALSE ); /* count */
92 if( ( j = number(0, 29) ) == 19 ) j = 0;
93 if( i != j ) {
94 if( i < j ) {
95 win = chkscr( &pscore, i );
96 printf( "It's really only %d points, I get %d.\n", i, 2 );
97 if( !win ) win = chkscr( &cscore, 2 );
98 }
99 else {
100 win = chkscr( &pscore, j );
101 printf( "You should have taken %d, not %d!\n", i, j );
102 }
103 if( explain ) {
104 printf( "Explanation: %s\n", expl );
105 }
106 }
107 else {
108 win = chkscr( &pscore, i );
109 }
110 return( win );
111}
112
113
114
115/*
116 * handle scoring and displaying the computers hand
117 */
118
119comphand( h, s )
120
121 CARD h[];
122 char *s;
123{
124 register int j;
125
126 j = scorehand( h, turnover, CINHAND, FALSE );
127 printf( "My %s ( ", s );
128 prhand( h, CINHAND, TRUE );
129 printf( " [" );
130 printcard( turnover, TRUE );
131 printf( "] ) scores %d.\n", (j == 0 ? 19 : j) );
132 return( chkscr( &cscore, j ) );
133}
134
135
136
137/*
138 * add inc to scr and test for > glimit
139 */
140
141chkscr( scr, inc )
142
143 int *scr, inc;
144{
145 return( ( (*scr += inc) >= glimit ? TRUE : FALSE ) );
146}
147
148
149
150/*
151 * cdiscard -- the computer figures out what is the best discard for
152 * the crib and puts the best two cards at the end
153 */
154
155cdiscard( mycrib )
156
157 BOOLEAN mycrib;
158{
159 CARD d[ CARDS ], h[ FULLHAND ], cb[ 2 ];
160 register int i, j, k;
161 int nc, ns;
162 long sums[ 15 ];
163 static int undo1[15] = {0,0,0,0,0,1,1,1,1,2,2,2,3,3,4};
164 static int undo2[15] = {1,2,3,4,5,2,3,4,5,3,4,5,4,5,5};
165
166 makedeck( d );
167 nc = CARDS;
168 for( i = 0; i < knownum; i++ ) { /* get all other cards */
169 remove( known[i], d, nc-- );
170 }
171 for( i = 0; i < 15; i++ ) sums[i] = 0L;
172 ns = 0;
173 for( i = 0; i < (FULLHAND - 1); i++ ) {
174 cb[0] = chand[i];
175 for( j = i + 1; j < FULLHAND; j++ ) {
176 cb[1] = chand[j];
177 for( k = 0; k < FULLHAND; k++ ) h[k] = chand[k];
178 remove( chand[i], h, FULLHAND );
179 remove( chand[j], h, FULLHAND - 1 );
180 for( k = 0; k < nc; k++ ) {
181 sums[ns] += scorehand( h, d[k], CINHAND, TRUE );
182 if( mycrib ) sums[ns] += adjust( cb, d[k] );
183 else sums[ns] -= adjust( cb, d[k] );
184 }
185 ++ns;
186 }
187 }
188 j = 0;
189 for( i = 1; i < 15; i++ ) if( sums[i] > sums[j] ) j = i;
190 for( k = 0; k < FULLHAND; k++ ) h[k] = chand[k];
191 remove( h[ undo1[j] ], chand, FULLHAND );
192 remove( h[ undo2[j] ], chand, FULLHAND - 1 );
193 chand[4] = h[ undo1[j] ];
194 chand[5] = h[ undo2[j] ];
195}
196
197
198
199/*
200 * returns true if some card in hand can be played without exceeding 31
201 */
202
203anymove( hand, n, sum )
204
205 CARD hand[];
206 int n;
207 int sum;
208{
209 register int i, j;
210
211 if( n < 1 ) return( FALSE );
212 j = hand[0].rank;
213 for( i = 1; i < n; i++ ) {
214 if( hand[i].rank < j ) j = hand[i].rank;
215 }
216 return( sum + VAL( j ) <= 31 );
217}
218
219
220
221/*
222 * anysumto returns the index (0 <= i < n) of the card in hand that brings
223 * the s up to t, or -1 if there is none
224 */
225
226anysumto( hand, n, s, t )
227
228 CARD hand[];
229 int n;
230 int s, t;
231{
232 register int i;
233
234 for( i = 0; i < n; i++ ) {
235 if( s + VAL( hand[i].rank ) == t ) return( i );
236 }
237 return( -1 );
238}
239
240
241
242
243/*
244 * return the number of cards in h having the given rank value
245 */
246
247numofval( h, n, v )
248
249 CARD h[];
250 int n;
251 int v;
252{
253 register int i, j;
254
255 j = 0;
256 for( i = 0; i < n; i++ ) {
257 if( VAL( h[i].rank ) == v ) ++j;
258 }
259 return( j );
260}
261
262
263
264/*
265 * makeknown remembers all n cards in h for future recall
266 */
267
268makeknown( h, n )
269
270 CARD h[];
271 int n;
272{
273 register int i;
274
275 for( i = 0; i < n; i++ ) {
276 known[ knownum++ ] = h[i];
277 }
278}
279