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