[BACK]Return to support.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / games / cribbage

Annotation of src/games/cribbage/support.c, Revision 1.12

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

CVSweb <webmaster@jp.NetBSD.org>