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

  1. /*
  2.  * Copyright (c) 1983 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[] = "@(#)move.c    5.4 (Berkeley) 6/1/90";
  36. #endif /* not lint */
  37.  
  38. #include    "mille.h"
  39. #ifndef    unctrl
  40. #include    "unctrl.h"
  41. #endif
  42.  
  43. # ifdef    attron
  44. #    include    <term.h>
  45. #    define    _tty    cur_term->Nttyb
  46. # endif    attron
  47.  
  48. /*
  49.  * @(#)move.c    1.2 (Berkeley) 3/28/83
  50.  */
  51.  
  52. #undef    CTRL
  53. #define    CTRL(c)        (c - 'A' + 1)
  54.  
  55. char    *Movenames[] = {
  56.         "M_DISCARD", "M_DRAW", "M_PLAY", "M_ORDER"
  57.     };
  58.  
  59. domove()
  60. {
  61.     reg PLAY    *pp;
  62.     reg int        i, j;
  63.     reg bool    goodplay;
  64.  
  65.     pp = &Player[Play];
  66.     if (Play == PLAYER)
  67.         getmove();
  68.     else
  69.         calcmove();
  70.     Next = FALSE;
  71.     goodplay = TRUE;
  72.     switch (Movetype) {
  73.       case M_DISCARD:
  74.         if (haspicked(pp)) {
  75.             if (pp->hand[Card_no] == C_INIT)
  76.                 if (Card_no == 6)
  77.                     Finished = TRUE;
  78.                 else
  79.                     error("no card there");
  80.             else {
  81.                 if (issafety(pp->hand[Card_no])) {
  82.                     error("discard a safety?");
  83.                     goodplay = FALSE;
  84.                     break;
  85.                 }
  86.                 Discard = pp->hand[Card_no];
  87.                 pp->hand[Card_no] = C_INIT;
  88.                 Next = TRUE;
  89.                 if (Play == PLAYER)
  90.                     account(Discard);
  91.             }
  92.         }
  93.         else
  94.             error("must pick first");
  95.         break;
  96.       case M_PLAY:
  97.         goodplay = playcard(pp);
  98.         break;
  99.       case M_DRAW:
  100.         Card_no = 0;
  101.         if (Topcard <= Deck)
  102.             error("no more cards");
  103.         else if (haspicked(pp))
  104.             error("already picked");
  105.         else {
  106.             pp->hand[0] = *--Topcard;
  107. #ifdef DEBUG
  108.             if (Debug)
  109.                 fprintf(outf, "DOMOVE: Draw %s\n", C_name[*Topcard]);
  110. #endif
  111. acc:
  112.             if (Play == COMP) {
  113.                 account(*Topcard);
  114.                 if (issafety(*Topcard))
  115.                     pp->safety[*Topcard-S_CONV] = S_IN_HAND;
  116.             }
  117.             if (pp->hand[1] == C_INIT && Topcard > Deck) {
  118.                 Card_no = 1;
  119.                 pp->hand[1] = *--Topcard;
  120. #ifdef DEBUG
  121.                 if (Debug)
  122.                     fprintf(outf, "DOMOVE: Draw %s\n", C_name[*Topcard]);
  123. #endif
  124.                 goto acc;
  125.             }
  126.             pp->new_battle = FALSE;
  127.             pp->new_speed = FALSE;
  128.         }
  129.         break;
  130.  
  131.       case M_ORDER:
  132.         break;
  133.     }
  134.     /*
  135.      * move blank card to top by one of two methods.  If the
  136.      * computer's hand was sorted, the randomness for picking
  137.      * between equally valued cards would be lost
  138.      */
  139.     if (Order && Movetype != M_DRAW && goodplay && pp == &Player[PLAYER])
  140.         sort(pp->hand);
  141.     else
  142.         for (i = 1; i < HAND_SZ; i++)
  143.             if (pp->hand[i] == C_INIT) {
  144.                 for (j = 0; pp->hand[j] == C_INIT; j++)
  145.                     if (j >= HAND_SZ) {
  146.                         j = 0;
  147.                         break;
  148.                     }
  149.                 pp->hand[i] = pp->hand[j];
  150.                 pp->hand[j] = C_INIT;
  151.             }
  152.     if (Topcard <= Deck)
  153.         check_go();
  154.     if (Next)
  155.         nextplay();
  156. }
  157.  
  158. /*
  159.  *    Check and see if either side can go.  If they cannot,
  160.  * the game is over
  161.  */
  162. check_go() {
  163.  
  164.     reg CARD    card;
  165.     reg PLAY    *pp, *op;
  166.     reg int        i;
  167.  
  168.     for (pp = Player; pp < &Player[2]; pp++) {
  169.         op = (pp == &Player[COMP] ? &Player[PLAYER] : &Player[COMP]);
  170.         for (i = 0; i < HAND_SZ; i++) {
  171.             card = pp->hand[i];
  172.             if (issafety(card) || canplay(pp, op, card)) {
  173. #ifdef DEBUG
  174.                 if (Debug) {
  175.                     fprintf(outf, "CHECK_GO: can play %s (%d), ", C_name[card], card);
  176.                     fprintf(outf, "issafety(card) = %d, ", issafety(card));
  177.                     fprintf(outf, "canplay(pp, op, card) = %d\n", canplay(pp, op, card));
  178.                 }
  179. #endif
  180.                 return;
  181.             }
  182. #ifdef DEBUG
  183.             else if (Debug)
  184.                 fprintf(outf, "CHECK_GO: cannot play %s\n",
  185.                     C_name[card]);
  186. #endif
  187.         }
  188.     }
  189.     Finished = TRUE;
  190. }
  191.  
  192. playcard(pp)
  193. reg PLAY    *pp;
  194. {
  195.     reg int        v;
  196.     reg CARD    card;
  197.  
  198.     /*
  199.      * check and see if player has picked
  200.      */
  201.     switch (pp->hand[Card_no]) {
  202.       default:
  203.         if (!haspicked(pp))
  204. mustpick:
  205.             return error("must pick first");
  206.       case C_GAS_SAFE:    case C_SPARE_SAFE:
  207.       case C_DRIVE_SAFE:    case C_RIGHT_WAY:
  208.         break;
  209.     }
  210.  
  211.     card = pp->hand[Card_no];
  212. #ifdef DEBUG
  213.     if (Debug)
  214.         fprintf(outf, "PLAYCARD: Card = %s\n", C_name[card]);
  215. #endif
  216.     Next = FALSE;
  217.     switch (card) {
  218.       case C_200:
  219.         if (pp->nummiles[C_200] == 2)
  220.             return error("only two 200's per hand");
  221.       case C_100:    case C_75:
  222.         if (pp->speed == C_LIMIT)
  223.             return error("limit of 50");
  224.       case C_50:
  225.         if (pp->mileage + Value[card] > End)
  226.             return error("puts you over %d", End);
  227.       case C_25:
  228.         if (!pp->can_go)
  229.             return error("cannot move now");
  230.         pp->nummiles[card]++;
  231.         v = Value[card];
  232.         pp->total += v;
  233.         pp->hand_tot += v;
  234.         if ((pp->mileage += v) == End)
  235.             check_ext(FALSE);
  236.         break;
  237.  
  238.       case C_GAS:    case C_SPARE:    case C_REPAIRS:
  239.         if (pp->battle != opposite(card))
  240.             return error("can't play \"%s\"", C_name[card]);
  241.         pp->battle = card;
  242.         if (pp->safety[S_RIGHT_WAY] == S_PLAYED)
  243.             pp->can_go = TRUE;
  244.         break;
  245.  
  246.       case C_GO:
  247.         if (pp->battle != C_INIT && pp->battle != C_STOP
  248.             && !isrepair(pp->battle))
  249.             return error("cannot play \"Go\" on a \"%s\"",
  250.                 C_name[pp->battle]);
  251.         pp->battle = C_GO;
  252.         pp->can_go = TRUE;
  253.         break;
  254.  
  255.       case C_END_LIMIT:
  256.         if (pp->speed != C_LIMIT)
  257.             return error("not limited");
  258.         pp->speed = C_END_LIMIT;
  259.         break;
  260.  
  261.       case C_EMPTY:    case C_FLAT:    case C_CRASH:
  262.       case C_STOP:
  263.         pp = &Player[other(Play)];
  264.         if (!pp->can_go)
  265.             return error("opponent cannot go");
  266.         else if (pp->safety[safety(card) - S_CONV] == S_PLAYED)
  267. protected:
  268.             return error("opponent is protected");
  269.         pp->battle = card;
  270.         pp->new_battle = TRUE;
  271.         pp->can_go = FALSE;
  272.         pp = &Player[Play];
  273.         break;
  274.  
  275.       case C_LIMIT:
  276.         pp = &Player[other(Play)];
  277.         if (pp->speed == C_LIMIT)
  278.             return error("opponent has limit");
  279.         if (pp->safety[S_RIGHT_WAY] == S_PLAYED)
  280.             goto protected;
  281.         pp->speed = C_LIMIT;
  282.         pp->new_speed = TRUE;
  283.         pp = &Player[Play];
  284.         break;
  285.  
  286.       case C_GAS_SAFE:    case C_SPARE_SAFE:
  287.       case C_DRIVE_SAFE:    case C_RIGHT_WAY:
  288.         if (pp->battle == opposite(card)
  289.             || (card == C_RIGHT_WAY && pp->speed == C_LIMIT)) {
  290.             if (!(card == C_RIGHT_WAY && !isrepair(pp->battle))) {
  291.                 pp->battle = C_GO;
  292.                 pp->can_go = TRUE;
  293.             }
  294.             if (card == C_RIGHT_WAY && pp->speed == C_LIMIT)
  295.                 pp->speed = C_INIT;
  296.             if (pp->new_battle
  297.                 || (pp->new_speed && card == C_RIGHT_WAY)) {
  298.                 pp->coups[card - S_CONV] = TRUE;
  299.                 pp->total += SC_COUP;
  300.                 pp->hand_tot += SC_COUP;
  301.                 pp->coupscore += SC_COUP;
  302.             }
  303.         }
  304.         /*
  305.          * if not coup, must pick first
  306.          */
  307.         else if (pp->hand[0] == C_INIT && Topcard > Deck)
  308.             goto mustpick;
  309.         pp->safety[card - S_CONV] = S_PLAYED;
  310.         pp->total += SC_SAFETY;
  311.         pp->hand_tot += SC_SAFETY;
  312.         if ((pp->safescore += SC_SAFETY) == NUM_SAFE * SC_SAFETY) {
  313.             pp->total += SC_ALL_SAFE;
  314.             pp->hand_tot += SC_ALL_SAFE;
  315.         }
  316.         if (card == C_RIGHT_WAY) {
  317.             if (pp->speed == C_LIMIT)
  318.                 pp->speed = C_INIT;
  319.             if (pp->battle == C_STOP || pp->battle == C_INIT) {
  320.                 pp->can_go = TRUE;
  321.                 pp->battle = C_INIT;
  322.             }
  323.             if (!pp->can_go && isrepair(pp->battle))
  324.                 pp->can_go = TRUE;
  325.         }
  326.         Next = -1;
  327.         break;
  328.  
  329.       case C_INIT:
  330.         error("no card there");
  331.         Next = -1;
  332.         break;
  333.     }
  334.     if (pp == &Player[PLAYER])
  335.         account(card);
  336.     pp->hand[Card_no] = C_INIT;
  337.     Next = (Next == -1 ? FALSE : TRUE);
  338.     return TRUE;
  339. }
  340.  
  341. getmove()
  342. {
  343.     reg char    c, *sp;
  344. #ifdef EXTRAP
  345.     static bool    last_ex = FALSE;    /* set if last command was E */
  346.  
  347.     if (last_ex) {
  348.         undoex();
  349.         prboard();
  350.         last_ex = FALSE;
  351.     }
  352. #endif
  353.     for (;;) {
  354.         prompt(MOVEPROMPT);
  355.         leaveok(Board, FALSE);
  356.         refresh();
  357.         while ((c = readch()) == killchar() || c == erasechar())
  358.             continue;
  359.         if (islower(c))
  360.             c = toupper(c);
  361.         if (isprint(c) && !isspace(c)) {
  362.             addch(c);
  363.             refresh();
  364.         }
  365.         switch (c) {
  366.           case 'P':        /* Pick */
  367.             Movetype = M_DRAW;
  368.             goto ret;
  369.           case 'U':        /* Use Card */
  370.           case 'D':        /* Discard Card */
  371.             if ((Card_no = getcard()) < 0)
  372.                 break;
  373.             Movetype = (c == 'U' ? M_PLAY : M_DISCARD);
  374.             goto ret;
  375.           case 'O':        /* Order */
  376.             Order = !Order;
  377.             if (Window == W_SMALL) {
  378.                 if (!Order)
  379.                     mvwaddstr(Score, 12, 21,
  380.                           "o: order hand");
  381.                 else
  382.                     mvwaddstr(Score, 12, 21,
  383.                           "o: stop ordering");
  384.                 wclrtoeol(Score);
  385.             }
  386.             Movetype = M_ORDER;
  387.             goto ret;
  388.           case 'Q':        /* Quit */
  389.             rub();        /* Same as a rubout */
  390.             break;
  391.           case 'W':        /* Window toggle */
  392.             Window = nextwin(Window);
  393.             newscore();
  394.             prscore(TRUE);
  395.             wrefresh(Score);
  396.             break;
  397.           case 'R':        /* Redraw screen */
  398.           case CTRL('L'):
  399.             wrefresh(curscr);
  400.             break;
  401.           case 'S':        /* Save game */
  402.             On_exit = FALSE;
  403.             save();
  404.             break;
  405.           case 'E':        /* Extrapolate */
  406. #ifdef EXTRAP
  407.             if (last_ex)
  408.                 break;
  409.             Finished = TRUE;
  410.             if (Window != W_FULL)
  411.                 newscore();
  412.             prscore(FALSE);
  413.             wrefresh(Score);
  414.             last_ex = TRUE;
  415.             Finished = FALSE;
  416. #else
  417.             error("%c: command not implemented", c);
  418. #endif
  419.             break;
  420.           case '\r':        /* Ignore RETURNs and    */
  421.           case '\n':        /* Line Feeds        */
  422.           case ' ':        /* Spaces        */
  423.           case '\0':        /* and nulls        */
  424.             break;
  425. #ifdef DEBUG
  426.           case 'Z':        /* Debug code */
  427.             if (!Debug && outf == NULL) {
  428.                 char    buf[MAXPATHLEN];
  429.  
  430.                 prompt(FILEPROMPT);
  431.                 leaveok(Board, FALSE);
  432.                 refresh();
  433.                 sp = buf;
  434.                 while ((*sp = readch()) != '\n') {
  435.                     if (*sp == killchar())
  436.                         goto over;
  437.                     else if (*sp == erasechar()) {
  438.                         if (--sp < buf)
  439.                             sp = buf;
  440.                         else {
  441.                             addch('\b');
  442.                             if (*sp < ' ')
  443.                                 addch('\b');
  444.                             clrtoeol();
  445.                         }
  446.                     }
  447.                     else
  448.                         addstr(unctrl(*sp++));
  449.                     refresh();
  450.                 }
  451.                 *sp = '\0';
  452.                 leaveok(Board, TRUE);
  453.                 if ((outf = fopen(buf, "w")) == NULL)
  454.                     perror(buf);
  455.                 setbuf(outf, (char *)NULL);
  456.             }
  457.             Debug = !Debug;
  458.             break;
  459. #endif
  460.           default:
  461.             error("unknown command: %s", unctrl(c));
  462.             break;
  463.         }
  464.     }
  465. ret:
  466.     leaveok(Board, TRUE);
  467. }
  468. /*
  469.  * return whether or not the player has picked
  470.  */
  471. haspicked(pp)
  472. reg PLAY    *pp; {
  473.  
  474.     reg int    card;
  475.  
  476.     if (Topcard <= Deck)
  477.         return TRUE;
  478.     switch (pp->hand[Card_no]) {
  479.       case C_GAS_SAFE:    case C_SPARE_SAFE:
  480.       case C_DRIVE_SAFE:    case C_RIGHT_WAY:
  481.         card = 1;
  482.         break;
  483.       default:
  484.         card = 0;
  485.         break;
  486.     }
  487.     return (pp->hand[card] != C_INIT);
  488. }
  489.  
  490. account(card)
  491. reg CARD    card; {
  492.  
  493.     reg CARD    oppos;
  494.  
  495.     if (card == C_INIT)
  496.         return;
  497.     ++Numseen[card];
  498.     if (Play == COMP)
  499.         switch (card) {
  500.           case C_GAS_SAFE:
  501.           case C_SPARE_SAFE:
  502.           case C_DRIVE_SAFE:
  503.             oppos = opposite(card);
  504.             Numgos += Numcards[oppos] - Numseen[oppos];
  505.             break;
  506.           case C_CRASH:
  507.           case C_FLAT:
  508.           case C_EMPTY:
  509.           case C_STOP:
  510.             Numgos++;
  511.             break;
  512.         }
  513. }
  514.  
  515. prompt(promptno)
  516. int    promptno;
  517. {
  518.     static char    *names[] = {
  519.                 ">>:Move:",
  520.                 "Really?",
  521.                 "Another hand?",
  522.                 "Another game?",
  523.                 "Save game?",
  524.                 "Same file?",
  525.                 "file:",
  526.                 "Extension?",
  527.                 "Overwrite file?",
  528.             };
  529.     static int    last_prompt = -1;
  530.  
  531.     if (promptno == last_prompt)
  532.         move(MOVE_Y, MOVE_X + strlen(names[promptno]) + 1);
  533.     else {
  534.         move(MOVE_Y, MOVE_X);
  535.         if (promptno == MOVEPROMPT)
  536.             standout();
  537.         addstr(names[promptno]);
  538.         if (promptno == MOVEPROMPT)
  539.             standend();
  540.         addch(' ');
  541.         last_prompt = promptno;
  542.     }
  543.     clrtoeol();
  544. }
  545.  
  546. sort(hand)
  547. reg CARD    *hand;
  548. {
  549.     reg CARD    *cp, *tp;
  550.     reg CARD    temp;
  551.  
  552.     cp = hand;
  553.     hand += HAND_SZ;
  554.     for ( ; cp < &hand[-1]; cp++)
  555.         for (tp = cp + 1; tp < hand; tp++)
  556.             if (*cp > *tp) {
  557.                 temp = *cp;
  558.                 *cp = *tp;
  559.                 *tp = temp;
  560.             }
  561. }
  562.  
  563.