(linenum→info "unix/slp.c:2238")

bsd-games/2.17/mille/comp.c

    1: /*      $NetBSD: comp.c,v 1.9 2003/08/07 09:37:24 agc Exp $  */
    2: 
    3: /*
    4:  * Copyright (c) 1982, 1993
    5:  *      The Regents of the University of California.  All rights reserved.
    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.
   15:  * 3. Neither the name of the University nor the names of its contributors
   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: 
   32: #include <sys/cdefs.h>
   33: #ifndef lint
   34: #if 0
   35: static char sccsid[] = "@(#)comp.c      8.1 (Berkeley) 5/31/93";
   36: #else
   37: __RCSID("$NetBSD: comp.c,v 1.9 2003/08/07 09:37:24 agc Exp $");
   38: #endif
   39: #endif /* not lint */
   40: 
   41: # include       "mille.h"
   42: 
   43: /*
   44:  * @(#)comp.c   1.1 (Berkeley) 4/1/82
   45:  */
   46: 
   47: # define        V_VALUABLE     40
   48: 
   49: void
   50: calcmove()
   51: {
   52:         CARD           card;
   53:         int            *value;
   54:         PLAY           *pp, *op;
   55:         bool           foundend, cango, canstop, foundlow;
   56:         unsgn int      i, count200, badcount, nummin, nummax, diff;
   57:         int            curmin, curmax;
   58:         CARD           safe, oppos;
   59:         int            valbuf[HAND_SZ], count[NUM_CARDS];
   60:         bool           playit[HAND_SZ];
   61: 
   62:         wmove(Score, ERR_Y, ERR_X);    /* get rid of error messages       */
   63:         wclrtoeol(Score);
   64:         pp = &Player[COMP];
   65:         op = &Player[PLAYER];
   66:         safe = 0;
   67:         cango = 0;
   68:         canstop = FALSE;
   69:         foundend = FALSE;
   70: 
   71:         /* Try for a Coup Forre, and see what we have. */
   72:         for (i = 0; i < NUM_CARDS; i++)
   73:                 count[i] = 0;
   74:         for (i = 0; i < HAND_SZ; i++) {
   75:                 card = pp->hand[i];
   76:                 switch (card) {
   77:                   case C_STOP:        case C_CRASH:
   78:                   case C_FLAT:        case C_EMPTY:
   79:                         if ((playit[i] = canplay(pp, op, card)) != 0)
   80:                                 canstop = TRUE;
   81:                         goto norm;
   82:                   case C_LIMIT:
   83:                         if ((playit[i] = canplay(pp, op, card))
   84:                             && Numseen[C_25] == Numcards[C_25]
   85:                             && Numseen[C_50] == Numcards[C_50])
   86:                                 canstop = TRUE;
   87:                         goto norm;
   88:                   case C_25:  case C_50:       case C_75:
   89:                   case C_100: case C_200:
   90:                         if ((playit[i] = canplay(pp, op, card))
   91:                             && pp->mileage + Value[card] == End)
   92:                                 foundend = TRUE;
   93:                         goto norm;
   94:                   default:
   95:                         playit[i] = canplay(pp, op, card);
   96: norm:
   97:                         if (playit[i])
   98:                                 ++cango;
   99:                         break;
  100:                   case C_GAS_SAFE:    case C_DRIVE_SAFE:
  101:                   case C_SPARE_SAFE:  case C_RIGHT_WAY:
  102:                         if (pp->battle == opposite(card) ||
  103:                             (pp->speed == C_LIMIT && card == C_RIGHT_WAY)) {
  104:                                 Movetype = M_PLAY;
  105:                                 Card_no = i;
  106:                                 return;
  107:                         }
  108:                         ++safe;
  109:                         playit[i] = TRUE;
  110:                         break;
  111:                 }
  112:                 if (card >= 0)
  113:                         ++count[card];
  114:         }
  115: 
  116:         /* No Coup Forre.  Draw to fill hand, then restart, as needed. */
  117:         if (pp->hand[0] == C_INIT && Topcard > Deck) {
  118:                 Movetype = M_DRAW;
  119:                 return;
  120:         }
  121: 
  122: #ifdef DEBUG
  123:         if (Debug)
  124:                 fprintf(outf, "CALCMOVE: cango = %d, canstop = %d, safe = %d\n",
  125:                         cango, canstop, safe);
  126: #endif
  127:         if (foundend)
  128:                 foundend = !check_ext(TRUE);
  129:         for (i = 0; safe && i < HAND_SZ; i++) {
  130:                 if (is_safety(pp->hand[i])) {
  131:                         if (onecard(op) || (foundend && cango && !canstop)) {
  132: #ifdef DEBUG
  133:                                 if (Debug)
  134:                                         fprintf(outf,
  135:                                                 "CALCMOVE: onecard(op) = %d, foundend = %d\n",
  136:                                                 onecard(op), foundend);
  137: #endif
  138: playsafe:
  139:                                 Movetype = M_PLAY;
  140:                                 Card_no = i;
  141:                                 return;
  142:                         }
  143:                         oppos = opposite(pp->hand[i]);
  144:                         if (Numseen[oppos] == Numcards[oppos] &&
  145:                             !(pp->hand[i] == C_RIGHT_WAY &&
  146:                               Numseen[C_LIMIT] != Numcards[C_LIMIT]))
  147:                                 goto playsafe;
  148:                         else if (!cango
  149:                             && (op->can_go || !pp->can_go || Topcard < Deck)) {
  150:                                 card = (Topcard - Deck) - roll(1, 10);
  151:                                 if ((!pp->mileage) != (!op->mileage))
  152:                                         card -= 7;
  153: #ifdef DEBUG
  154:                                 if (Debug)
  155:                                         fprintf(outf,
  156:                                                 "CALCMOVE: card = %d, DECK_SZ / 4 = %d\n",
  157:                                                 card, DECK_SZ / 4);
  158: #endif
  159:                                 if (card < DECK_SZ / 4)
  160:                                         goto playsafe;
  161:                         }
  162:                         safe--;
  163:                         playit[i] = cango;
  164:                 }
  165:         }
  166:         if (!pp->can_go && !is_repair(pp->battle))
  167:                 Numneed[opposite(pp->battle)]++;
  168: redoit:
  169:         foundlow = (cango || count[C_END_LIMIT] != 0
  170:                           || Numseen[C_LIMIT] == Numcards[C_LIMIT]
  171:                           || pp->safety[S_RIGHT_WAY] != S_UNKNOWN);
  172:         foundend = FALSE;
  173:         count200 = pp->nummiles[C_200];
  174:         badcount = 0;
  175:         curmax = -1;
  176:         curmin = 101;
  177:         nummin = -1;
  178:         nummax = -1;
  179:         value = valbuf;
  180:         for (i = 0; i < HAND_SZ; i++) {
  181:                 card = pp->hand[i];
  182:                 if (is_safety(card) || playit[i] == (cango != 0)) {
  183: #ifdef DEBUG
  184:                         if (Debug)
  185:                                 fprintf(outf, "CALCMOVE: switch(\"%s\")\n",
  186:                                         C_name[card]);
  187: #endif
  188:                         switch (card) {
  189:                           case C_25: case C_50:
  190:                                 diff = End - pp->mileage;
  191:                                 /* avoid getting too close */
  192:                                 if (Topcard > Deck && cango && diff <= 100
  193:                                     && (int)diff / Value[card] > count[card]
  194:                                     && (card == C_25 || diff % 50 == 0)) {
  195:                                         if (card == C_50 && diff - 50 == 25
  196:                                             && count[C_25] > 0)
  197:                                                 goto okay;
  198:                                         *value = 0;
  199:                                         if (--cango <= 0)
  200:                                                 goto redoit;
  201:                                         break;
  202:                                 }
  203: okay:
  204:                                 *value = (Value[card] >> 3);
  205:                                 if (pp->speed == C_LIMIT)
  206:                                         ++*value;
  207:                                 else
  208:                                         --*value;
  209:                                 if (!foundlow
  210:                                    && (card == C_50 || count[C_50] == 0)) {
  211:                                         *value = (pp->mileage ? 10 : 20);
  212:                                         foundlow = TRUE;
  213:                                 }
  214:                                 goto miles;
  215:                           case C_200:
  216:                                 if (++count200 > 2) {
  217:                                         *value = 0;
  218:                                         break;
  219:                                 }
  220:                           case C_75: case C_100:
  221:                                 *value = (Value[card] >> 3);
  222:                                 if (pp->speed == C_LIMIT)
  223:                                         --*value;
  224:                                 else
  225:                                         ++*value;
  226: miles:
  227:                                 if (pp->mileage + Value[card] > End)
  228:                                         *value = (End == 700 ? card : 0);
  229:                                 else if (pp->mileage + Value[card] == End) {
  230:                                         *value = (foundend ? card : V_VALUABLE);
  231:                                         foundend = TRUE;
  232:                                 }
  233:                                 break;
  234:                           case C_END_LIMIT:
  235:                                 if (pp->safety[S_RIGHT_WAY] != S_UNKNOWN)
  236:                                         *value = (pp->safety[S_RIGHT_WAY] ==
  237:                                                   S_PLAYED ? -1 : 1);
  238:                                 else if (pp->speed == C_LIMIT &&
  239:                                          End - pp->mileage <= 50)
  240:                                         *value = 1;
  241:                                 else if (pp->speed == C_LIMIT
  242:                                     || Numseen[C_LIMIT] != Numcards[C_LIMIT]) {
  243:                                         safe = S_RIGHT_WAY;
  244:                                         oppos = C_LIMIT;
  245:                                         goto repair;
  246:                                 }
  247:                                 else {
  248:                                         *value = 0;
  249:                                         --count[C_END_LIMIT];
  250:                                 }
  251:                                 break;
  252:                           case C_REPAIRS:    case C_SPARE:      case C_GAS:
  253:                                 safe = safety(card) - S_CONV;
  254:                                 oppos = opposite(card);
  255:                                 if (pp->safety[safe] != S_UNKNOWN)
  256:                                         *value = (pp->safety[safe] ==
  257:                                                   S_PLAYED ? -1 : 1);
  258:                                 else if (pp->battle != oppos
  259:                                     && (Numseen[oppos] == Numcards[oppos] ||
  260:                                         Numseen[oppos] + count[card] >
  261:                                         Numcards[oppos])) {
  262:                                         *value = 0;
  263:                                         --count[card];
  264:                                 }
  265:                                 else {
  266: repair:
  267:                                         *value = Numcards[oppos] * 6;
  268:                                         *value += Numseen[card] -
  269:                                                   Numseen[oppos];
  270:                                         if (!cango)
  271:                                             *value /= (count[card]*count[card]);
  272:                                         count[card]--;
  273:                                 }
  274:                                 break;
  275:                           case C_GO:
  276:                                 if (pp->safety[S_RIGHT_WAY] != S_UNKNOWN)
  277:                                         *value = (pp->safety[S_RIGHT_WAY] ==
  278:                                                   S_PLAYED ? -1 : 2);
  279:                                 else if (pp->can_go
  280:                                  && Numgos + count[C_GO] == Numneed[C_GO]) {
  281:                                         *value = 0;
  282:                                         --count[C_GO];
  283:                                 }
  284:                                 else {
  285:                                         *value = Numneed[C_GO] * 3;
  286:                                         *value += (Numseen[C_GO] - Numgos);
  287:                                         *value /= (count[C_GO] * count[C_GO]);
  288:                                         count[C_GO]--;
  289:                                 }
  290:                                 break;
  291:                           case C_LIMIT:
  292:                                 if (op->mileage + 50 >= End) {
  293:                                         *value = (End == 700 && !cango);
  294:                                         break;
  295:                                 }
  296:                                 if (canstop || (cango && !op->can_go))
  297:                                         *value = 1;
  298:                                 else {
  299:                                         *value = (pp->safety[S_RIGHT_WAY] !=
  300:                                                   S_UNKNOWN ? 2 : 3);
  301:                                         safe = S_RIGHT_WAY;
  302:                                         oppos = C_END_LIMIT;
  303:                                         goto normbad;
  304:                                 }
  305:                                 break;
  306:                           case C_CRASH:      case C_EMPTY:        case C_FLAT:
  307:                                 safe = safety(card) - S_CONV;
  308:                                 oppos = opposite(card);
  309:                                 *value = (pp->safety[safe]!=S_UNKNOWN ? 3 : 4);
  310: normbad:
  311:                                 if (op->safety[safe] == S_PLAYED)
  312:                                         *value = -1;
  313:                                 else {
  314:                                         *value *= Numneed[oppos] +
  315:                                                   Numseen[oppos] + 2;
  316:                                         if (!pp->mileage || foundend ||
  317:                                             onecard(op))
  318:                                                 *value += 5;
  319:                                         if (op->mileage == 0 || onecard(op))
  320:                                                 *value += 5;
  321:                                         if (op->speed == C_LIMIT)
  322:                                                 *value -= 3;
  323:                                         if (cango &&
  324:                                             pp->safety[safe] != S_UNKNOWN)
  325:                                                 *value += 3;
  326:                                         if (!cango)
  327:                                                 *value /= ++badcount;
  328:                                 }
  329:                                 break;
  330:                           case C_STOP:
  331:                                 if (op->safety[S_RIGHT_WAY] == S_PLAYED)
  332:                                         *value = -1;
  333:                                 else {
  334:                                         *value = (pp->safety[S_RIGHT_WAY] !=
  335:                                                   S_UNKNOWN ? 3 : 4);
  336:                                         *value *= Numcards[C_STOP] +
  337:                                                   Numseen[C_GO];
  338:                                         if (!pp->mileage || foundend ||
  339:                                             onecard(op))
  340:                                                 *value += 5;
  341:                                         if (!cango)
  342:                                                 *value /= ++badcount;
  343:                                         if (op->mileage == 0)
  344:                                                 *value += 5;
  345:                                         if ((card == C_LIMIT &&
  346:                                              op->speed == C_LIMIT) ||
  347:                                             !op->can_go)
  348:                                                 *value -= 5;
  349:                                         if (cango && pp->safety[S_RIGHT_WAY] !=
  350:                                                      S_UNKNOWN)
  351:                                                 *value += 5;
  352:                                 }
  353:                                 break;
  354:                           case C_GAS_SAFE:   case C_DRIVE_SAFE:
  355:                           case C_SPARE_SAFE: case C_RIGHT_WAY:
  356:                                 *value = cango ? 0 : 101;
  357:                                 break;
  358:                           case C_INIT:
  359:                                 *value = 0;
  360:                                 break;
  361:                         }
  362:                 }
  363:                 else
  364:                         *value = cango ? 0 : 101;
  365:                 if (card != C_INIT) {
  366:                         if (*value >= curmax) {
  367:                                 nummax = i;
  368:                                 curmax = *value;
  369:                         }
  370:                         if (*value <= curmin) {
  371:                                 nummin = i;
  372:                                 curmin = *value;
  373:                         }
  374:                 }
  375: #ifdef DEBUG
  376:                 if (Debug)
  377:                         mvprintw(i + 6, 2, "%3d %-14s", *value,
  378:                                  C_name[pp->hand[i]]);
  379: #endif
  380:                 value++;
  381:         }
  382:         if (!pp->can_go && !is_repair(pp->battle))
  383:                 Numneed[opposite(pp->battle)]++;
  384:         if (cango) {
  385: play_it:
  386:                 mvaddstr(MOVE_Y + 1, MOVE_X, "PLAY\n");
  387:                 Movetype = M_PLAY;
  388:                 Card_no = nummax;
  389:         }
  390:         else {
  391:                 if (is_safety(pp->hand[nummin])) { /* NEVER discard a safety */
  392:                         nummax = nummin;
  393:                         goto play_it;
  394:                 }
  395:                 mvaddstr(MOVE_Y + 1, MOVE_X, "DISCARD\n");
  396:                 Movetype = M_DISCARD;
  397:                 Card_no = nummin;
  398:         }
  399:         mvprintw(MOVE_Y + 2, MOVE_X, "%16s", C_name[pp->hand[Card_no]]);
  400: }
  401: 
  402: /*
  403:  * Return true if the given player could conceivably win with his next card.
  404:  */
  405: int
  406: onecard(pp)
  407:         const PLAY     *pp;
  408: {
  409:         CARD   bat, spd, card;
  410: 
  411:         bat = pp->battle;
  412:         spd = pp->speed;
  413:         card = -1;
  414:         if (pp->can_go || ((is_repair(bat) || bat == C_STOP || spd == C_LIMIT) &&
  415:                            Numseen[S_RIGHT_WAY] != 0) ||
  416:             (bat >= 0 && Numseen[safety(bat)] != 0))
  417:                 switch (End - pp->mileage) {
  418:                   case 200:
  419:                         if (pp->nummiles[C_200] == 2)
  420:                                 return FALSE;
  421:                         card = C_200;
  422:                         /* FALLTHROUGH */
  423:                   case 100:
  424:                   case 75:
  425:                         if (card == -1)
  426:                                 card = (End - pp->mileage == 75 ? C_75 : C_100);
  427:                         if (spd == C_LIMIT)
  428:                                 return Numseen[S_RIGHT_WAY] == 0;
  429:                   case 50:
  430:                   case 25:
  431:                         if (card == -1)
  432:                                 card = (End - pp->mileage == 25 ? C_25 : C_50);
  433:                         return Numseen[card] != Numcards[card];
  434:                 }
  435:         return FALSE;
  436: }
  437: 
  438: int
  439: canplay(pp, op, card)
  440:         const PLAY     *pp, *op;
  441:         CARD   card;
  442: {
  443:         switch (card) {
  444:           case C_200:
  445:                 if (pp->nummiles[C_200] == 2)
  446:                         break;
  447:                 /* FALLTHROUGH */
  448:           case C_75:   case C_100:
  449:                 if (pp->speed == C_LIMIT)
  450:                         break;
  451:                 /* FALLTHROUGH */
  452:           case C_50:
  453:                 if (pp->mileage + Value[card] > End)
  454:                         break;
  455:                 /* FALLTHROUGH */
  456:           case C_25:
  457:                 if (pp->can_go)
  458:                         return TRUE;
  459:                 break;
  460:           case C_EMPTY:        case C_FLAT:   case C_CRASH:
  461:           case C_STOP:
  462:                 if (op->can_go && op->safety[safety(card) - S_CONV] != S_PLAYED)
  463:                         return TRUE;
  464:                 break;
  465:           case C_LIMIT:
  466:                 if (op->speed != C_LIMIT &&
  467:                     op->safety[S_RIGHT_WAY] != S_PLAYED &&
  468:                     op->mileage + 50 < End)
  469:                         return TRUE;
  470:                 break;
  471:           case C_GAS:  case C_SPARE:    case C_REPAIRS:
  472:                 if (pp->battle == opposite(card))
  473:                         return TRUE;
  474:                 break;
  475:           case C_GO:
  476:                 if (!pp->can_go &&
  477:                     (is_repair(pp->battle) || pp->battle == C_STOP))
  478:                         return TRUE;
  479:                 break;
  480:           case C_END_LIMIT:
  481:                 if (pp->speed == C_LIMIT)
  482:                         return TRUE;
  483:         }
  484:         return FALSE;
  485: }
Syntax (Markdown)