home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / games / mille / comp.c next >
Encoding:
C/C++ Source or Header  |  1991-04-08  |  12.0 KB  |  487 lines

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