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

  1. /*
  2.  * Copyright (c) 1980 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. char copyright[] =
  36. "@(#) Copyright (c) 1980 Regents of the University of California.\n\
  37.  All rights reserved.\n";
  38. #endif /* not lint */
  39.  
  40. #ifndef lint
  41. static char sccsid[] = "@(#)crib.c    5.6 (Berkeley) 2/28/91";
  42. #endif /* not lint */
  43.  
  44. # include    <sys/signal.h>
  45. # include    <curses.h>
  46. # include    "deck.h"
  47. # include    "cribbage.h"
  48. # include    "cribcur.h"
  49. # include    "pathnames.h"
  50.  
  51. main(argc, argv)
  52. int    argc;
  53. char    *argv[];
  54. {
  55.     extern char *optarg;
  56.     extern int optind;
  57.     register  char        *p;
  58.     int ch;
  59.     BOOLEAN            playing;
  60.     char            *s;        /* for reading arguments */
  61.     FILE            *f;
  62.     FILE            *fopen();
  63.     char            *getline(), *getlogin();
  64.     void            rint();
  65.  
  66.     while ((ch = getopt(argc, argv, "eqr")) != EOF)
  67.         switch(ch) {
  68.         case 'e':
  69.             explain = TRUE;
  70.             break;
  71.         case 'q':
  72.             quiet = TRUE;
  73.             break;
  74.         case 'r':
  75.             rflag = TRUE;
  76.             break;
  77.         case '?':
  78.         default:
  79.             (void) fprintf(stderr, "usage: cribbage [-eqr]\n");
  80.             exit(1);
  81.         }
  82.  
  83.     initscr();
  84.     signal(SIGINT, rint);
  85.     crmode();
  86.     noecho();
  87.     Playwin = subwin(stdscr, PLAY_Y, PLAY_X, 0, 0);
  88.     Tablewin = subwin(stdscr, TABLE_Y, TABLE_X, 0, PLAY_X);
  89.     Compwin = subwin(stdscr, COMP_Y, COMP_X, 0, TABLE_X + PLAY_X);
  90.     Msgwin = subwin(stdscr, MSG_Y, MSG_X, Y_MSG_START, SCORE_X + 1);
  91.     leaveok(Playwin, TRUE);
  92.     leaveok(Tablewin, TRUE);
  93.     leaveok(Compwin, TRUE);
  94.     clearok(stdscr, FALSE);
  95.  
  96.     if (!quiet) {
  97.         msg("Do you need instructions for cribbage? ");
  98.         if (getuchar() == 'Y') {
  99.         endwin();
  100.         clear();
  101.         mvcur(0, COLS - 1, LINES - 1, 0);
  102.         fflush(stdout);
  103.         instructions();
  104.         crmode();
  105.         noecho();
  106.         clear();
  107.         refresh();
  108.         msg("For the rules of this program, do \"man cribbage\"");
  109.         }
  110.     }
  111.     playing = TRUE;
  112.     do {
  113.         wclrtobot(Msgwin);
  114.         msg(quiet ? "L or S? " : "Long (to 121) or Short (to 61)? ");
  115.         if (glimit == SGAME)
  116.         glimit = (getuchar() == 'L' ? LGAME : SGAME);
  117.         else
  118.         glimit = (getuchar() == 'S' ? SGAME : LGAME);
  119.         game();
  120.         msg("Another game? ");
  121.         playing = (getuchar() == 'Y');
  122.     } while (playing);
  123.  
  124.     if (f = fopen(_PATH_LOG, "a")) {
  125.         (void)fprintf(f, "%s: won %5.5d, lost %5.5d\n",
  126.            getlogin(), cgames, pgames);
  127.         (void)fclose(f);
  128.     }
  129.     bye();
  130.     if (!f) {
  131.         (void)fprintf(stderr, "\ncribbage: can't open %s.\n",
  132.             _PATH_LOG);
  133.         exit(1);
  134.     }
  135.     exit(0);
  136. }
  137.  
  138. /*
  139.  * makeboard:
  140.  *    Print out the initial board on the screen
  141.  */
  142. makeboard()
  143. {
  144.     mvaddstr(SCORE_Y + 0, SCORE_X, "+---------------------------------------+");
  145.     mvaddstr(SCORE_Y + 1, SCORE_X, "|  Score:   0     YOU                   |");
  146.     mvaddstr(SCORE_Y + 2, SCORE_X, "| *.....:.....:.....:.....:.....:.....  |");
  147.     mvaddstr(SCORE_Y + 3, SCORE_X, "| *.....:.....:.....:.....:.....:.....  |");
  148.     mvaddstr(SCORE_Y + 4, SCORE_X, "|                                       |");
  149.     mvaddstr(SCORE_Y + 5, SCORE_X, "| *.....:.....:.....:.....:.....:.....  |");
  150.     mvaddstr(SCORE_Y + 6, SCORE_X, "| *.....:.....:.....:.....:.....:.....  |");
  151.     mvaddstr(SCORE_Y + 7, SCORE_X, "|  Score:   0      ME                   |");
  152.     mvaddstr(SCORE_Y + 8, SCORE_X, "+---------------------------------------+");
  153.     gamescore();
  154. }
  155.  
  156. /*
  157.  * gamescore:
  158.  *    Print out the current game score
  159.  */
  160. gamescore()
  161. {
  162.     extern int    Lastscore[];
  163.  
  164.     if (pgames || cgames) {
  165.         mvprintw(SCORE_Y + 1, SCORE_X + 28, "Games: %3d", pgames);
  166.         mvprintw(SCORE_Y + 7, SCORE_X + 28, "Games: %3d", cgames);
  167.     }
  168.     Lastscore[0] = -1;
  169.     Lastscore[1] = -1;
  170. }
  171.  
  172. /*
  173.  * game:
  174.  *    Play one game up to glimit points.  Actually, we only ASK the
  175.  *    player what card to turn.  We do a random one, anyway.
  176.  */
  177. game()
  178. {
  179.     register int        i, j;
  180.     BOOLEAN            flag;
  181.     BOOLEAN            compcrib;
  182.  
  183.     makeboard();
  184.     refresh();
  185.     makedeck(deck);
  186.     shuffle(deck);
  187.     if (gamecount == 0) {
  188.         flag = TRUE;
  189.         do {
  190.         if (!rflag) {                /* player cuts deck */
  191.             msg(quiet ? "Cut for crib? " :
  192.             "Cut to see whose crib it is -- low card wins? ");
  193.             getline();
  194.         }
  195.         i = (rand() >> 4) % CARDS;        /* random cut */
  196.         do {                    /* comp cuts deck */
  197.             j = (rand() >> 4) % CARDS;
  198.         } while (j == i);
  199.         addmsg(quiet ? "You cut " : "You cut the ");
  200.         msgcard(deck[i], FALSE);
  201.         endmsg();
  202.         addmsg(quiet ? "I cut " : "I cut the ");
  203.         msgcard(deck[j], FALSE);
  204.         endmsg();
  205.         flag = (deck[i].rank == deck[j].rank);
  206.         if (flag) {
  207.             msg(quiet ? "We tied..." :
  208.             "We tied and have to try again...");
  209.             shuffle(deck);
  210.             continue;
  211.         }
  212.         else
  213.             compcrib = (deck[i].rank > deck[j].rank);
  214.         } while (flag);
  215.     }
  216.     else {
  217.         werase(Tablewin);
  218.         wrefresh(Tablewin);
  219.         werase(Compwin);
  220.         wrefresh(Compwin);
  221.         msg("Loser (%s) gets first crib",  (iwon ? "you" : "me"));
  222.         compcrib = !iwon;
  223.     }
  224.  
  225.     pscore = cscore = 0;
  226.     flag = TRUE;
  227.     do {
  228.         shuffle(deck);
  229.         flag = !playhand(compcrib);
  230.         compcrib = !compcrib;
  231.     } while (flag);
  232.     ++gamecount;
  233.     if (cscore < pscore) {
  234.         if (glimit - cscore > 60) {
  235.         msg("YOU DOUBLE SKUNKED ME!");
  236.         pgames += 4;
  237.         }
  238.         else if (glimit - cscore > 30) {
  239.         msg("YOU SKUNKED ME!");
  240.         pgames += 2;
  241.         }
  242.         else {
  243.         msg("YOU WON!");
  244.         ++pgames;
  245.         }
  246.         iwon = FALSE;
  247.     }
  248.     else {
  249.         if (glimit - pscore > 60) {
  250.         msg("I DOUBLE SKUNKED YOU!");
  251.         cgames += 4;
  252.         }
  253.         else if (glimit - pscore > 30) {
  254.         msg("I SKUNKED YOU!");
  255.         cgames += 2;
  256.         }
  257.         else {
  258.         msg("I WON!");
  259.         ++cgames;
  260.         }
  261.         iwon = TRUE;
  262.     }
  263.     gamescore();
  264. }
  265.  
  266. /*
  267.  * playhand:
  268.  *    Do up one hand of the game
  269.  */
  270. playhand(mycrib)
  271. BOOLEAN        mycrib;
  272. {
  273.     register int        deckpos;
  274.     extern char        Msgbuf[];
  275.  
  276.     werase(Compwin);
  277.  
  278.     knownum = 0;
  279.     deckpos = deal(mycrib);
  280.     sorthand(chand, FULLHAND);
  281.     sorthand(phand, FULLHAND);
  282.     makeknown(chand, FULLHAND);
  283.     prhand(phand, FULLHAND, Playwin, FALSE);
  284.     discard(mycrib);
  285.     if (cut(mycrib, deckpos))
  286.         return TRUE;
  287.     if (peg(mycrib))
  288.         return TRUE;
  289.     werase(Tablewin);
  290.     wrefresh(Tablewin);
  291.     if (score(mycrib))
  292.         return TRUE;
  293.     return FALSE;
  294. }
  295.  
  296.  
  297.  
  298. /*
  299.  * deal cards to both players from deck
  300.  */
  301.  
  302. deal( mycrib )
  303. {
  304.     register  int        i, j;
  305.  
  306.     j = 0;
  307.     for( i = 0; i < FULLHAND; i++ )  {
  308.         if( mycrib )  {
  309.         phand[i] = deck[j++];
  310.         chand[i] = deck[j++];
  311.         }
  312.         else  {
  313.         chand[i] = deck[j++];
  314.         phand[i] = deck[j++];
  315.         }
  316.     }
  317.     return( j );
  318. }
  319.  
  320. /*
  321.  * discard:
  322.  *    Handle players discarding into the crib...
  323.  * Note: we call cdiscard() after prining first message so player doesn't wait
  324.  */
  325. discard(mycrib)
  326. BOOLEAN        mycrib;
  327. {
  328.     register char    *prompt;
  329.     CARD        crd;
  330.  
  331.     prcrib(mycrib, TRUE);
  332.     prompt = (quiet ? "Discard --> " : "Discard a card --> ");
  333.     cdiscard(mycrib);            /* puts best discard at end */
  334.     crd = phand[infrom(phand, FULLHAND, prompt)];
  335.     cremove(crd, phand, FULLHAND);
  336.     prhand(phand, FULLHAND, Playwin, FALSE);
  337.     crib[0] = crd;
  338. /* next four lines same as last four except for cdiscard() */
  339.     crd = phand[infrom(phand, FULLHAND - 1, prompt)];
  340.     cremove(crd, phand, FULLHAND - 1);
  341.     prhand(phand, FULLHAND, Playwin, FALSE);
  342.     crib[1] = crd;
  343.     crib[2] = chand[4];
  344.     crib[3] = chand[5];
  345.     chand[4].rank = chand[4].suit = chand[5].rank = chand[5].suit = EMPTY;
  346. }
  347.  
  348. /*
  349.  * cut:
  350.  *    Cut the deck and set turnover.  Actually, we only ASK the
  351.  *    player what card to turn.  We do a random one, anyway.
  352.  */
  353. cut(mycrib, pos)
  354. BOOLEAN        mycrib;
  355. int        pos;
  356. {
  357.     register int        i, cardx;
  358.     BOOLEAN            win = FALSE;
  359.  
  360.     if (mycrib) {
  361.         if (!rflag) {            /* random cut */
  362.         msg(quiet ? "Cut the deck? " :
  363.             "How many cards down do you wish to cut the deck? ");
  364.         getline();
  365.         }
  366.         i = (rand() >> 4) % (CARDS - pos);
  367.         turnover = deck[i + pos];
  368.         addmsg(quiet ? "You cut " : "You cut the ");
  369.         msgcard(turnover, FALSE);
  370.         endmsg();
  371.         if (turnover.rank == JACK) {
  372.         msg("I get two for his heels");
  373.         win = chkscr(&cscore,2 );
  374.         }
  375.     }
  376.     else {
  377.         i = (rand() >> 4) % (CARDS - pos) + pos;
  378.         turnover = deck[i];
  379.         addmsg(quiet ? "I cut " : "I cut the ");
  380.         msgcard(turnover, FALSE);
  381.         endmsg();
  382.         if (turnover.rank == JACK) {
  383.         msg("You get two for his heels");
  384.         win = chkscr(&pscore, 2);
  385.         }
  386.     }
  387.     makeknown(&turnover, 1);
  388.     prcrib(mycrib, FALSE);
  389.     return win;
  390. }
  391.  
  392. /*
  393.  * prcrib:
  394.  *    Print out the turnover card with crib indicator
  395.  */
  396. prcrib(mycrib, blank)
  397. BOOLEAN        mycrib, blank;
  398. {
  399.     register int    y, cardx;
  400.  
  401.     if (mycrib)
  402.         cardx = CRIB_X;
  403.     else
  404.         cardx = 0;
  405.  
  406.     mvaddstr(CRIB_Y, cardx + 1, "CRIB");
  407.     prcard(stdscr, CRIB_Y + 1, cardx, turnover, blank);
  408.  
  409.     if (mycrib)
  410.         cardx = 0;
  411.     else
  412.         cardx = CRIB_X;
  413.  
  414.     for (y = CRIB_Y; y <= CRIB_Y + 5; y++)
  415.         mvaddstr(y, cardx, "       ");
  416. }
  417.  
  418. /*
  419.  * peg:
  420.  *    Handle all the pegging...
  421.  */
  422.  
  423. static CARD        Table[14];
  424.  
  425. static int        Tcnt;
  426.  
  427. peg(mycrib)
  428. BOOLEAN        mycrib;
  429. {
  430.     static CARD        ch[CINHAND], ph[CINHAND];
  431.     CARD            crd;
  432.     register int        i, j, k;
  433.     register int        l;
  434.     register int        cnum, pnum, sum;
  435.     register BOOLEAN    myturn, mego, ugo, last, played;
  436.  
  437.     cnum = pnum = CINHAND;
  438.     for (i = 0; i < CINHAND; i++) {        /* make copies of hands */
  439.         ch[i] = chand[i];
  440.         ph[i] = phand[i];
  441.     }
  442.     Tcnt = 0;            /* index to table of cards played */
  443.     sum = 0;            /* sum of cards played */
  444.     mego = ugo = FALSE;
  445.     myturn = !mycrib;
  446.     for (;;) {
  447.         last = TRUE;                /* enable last flag */
  448.         prhand(ph, pnum, Playwin, FALSE);
  449.         prhand(ch, cnum, Compwin, TRUE);
  450.         prtable(sum);
  451.         if (myturn) {                /* my tyrn to play */
  452.         if (!anymove(ch, cnum, sum)) {        /* if no card to play */
  453.             if (!mego && cnum) {        /* go for comp? */
  454.             msg("GO");
  455.             mego = TRUE;
  456.             }
  457.             if (anymove(ph, pnum, sum))        /* can player move? */
  458.             myturn = !myturn;
  459.             else {                /* give him his point */
  460.             msg(quiet ? "You get one" : "You get one point");
  461.             if (chkscr(&pscore, 1))
  462.                 return TRUE;
  463.             sum = 0;
  464.             mego = ugo = FALSE;
  465.             Tcnt = 0;
  466.             }
  467.         }
  468.         else {
  469.             played = TRUE;
  470.             j = -1;
  471.             k = 0;
  472.             for (i = 0; i < cnum; i++) {    /* maximize score */
  473.             l = pegscore(ch[i], Table, Tcnt, sum);
  474.             if (l > k) {
  475.                 k = l;
  476.                 j = i;
  477.             }
  478.             }
  479.             if (j < 0)                /* if nothing scores */
  480.             j = cchose(ch, cnum, sum);
  481.             crd = ch[j];
  482.             cremove(crd, ch, cnum--);
  483.             sum += VAL(crd.rank);
  484.             Table[Tcnt++] = crd;
  485.             if (k > 0) {
  486.             addmsg(quiet ? "I get %d playing " :
  487.                 "I get %d points playing ", k);
  488.             msgcard(crd, FALSE);
  489.             endmsg();
  490.             if (chkscr(&cscore, k))
  491.                 return TRUE;
  492.             }
  493.             myturn = !myturn;
  494.         }
  495.         }
  496.         else {
  497.         if (!anymove(ph, pnum, sum)) {        /* can player move? */
  498.             if (!ugo && pnum) {            /* go for player */
  499.             msg("You have a GO");
  500.             ugo = TRUE;
  501.             }
  502.             if (anymove(ch, cnum, sum))        /* can computer play? */
  503.             myturn = !myturn;
  504.             else {
  505.             msg(quiet ? "I get one" : "I get one point");
  506.             do_wait();
  507.             if (chkscr(&cscore, 1))
  508.                 return TRUE;
  509.             sum = 0;
  510.             mego = ugo = FALSE;
  511.             Tcnt = 0;
  512.             }
  513.         }
  514.         else {                    /* player plays */
  515.             played = FALSE;
  516.             if (pnum == 1) {
  517.             crd = ph[0];
  518.             msg("You play your last card");
  519.             }
  520.             else
  521.             for (;;) {
  522.                 prhand(ph, pnum, Playwin, FALSE);
  523.                 crd = ph[infrom(ph, pnum, "Your play: ")];
  524.                 if (sum + VAL(crd.rank) <= 31)
  525.                 break;
  526.                 else
  527.                 msg("Total > 31 -- try again");
  528.             }
  529.             makeknown(&crd, 1);
  530.             cremove(crd, ph, pnum--);
  531.             i = pegscore(crd, Table, Tcnt, sum);
  532.             sum += VAL(crd.rank);
  533.             Table[Tcnt++] = crd;
  534.             if (i > 0) {
  535.             msg(quiet ? "You got %d" : "You got %d points", i);
  536.             if (chkscr(&pscore, i))
  537.                 return TRUE;
  538.             }
  539.             myturn = !myturn;
  540.         }
  541.         }
  542.         if (sum >= 31) {
  543.         if (!myturn)
  544.             do_wait();
  545.         sum = 0;
  546.         mego = ugo = FALSE;
  547.         Tcnt = 0;
  548.         last = FALSE;                /* disable last flag */
  549.         }
  550.         if (!pnum && !cnum)
  551.         break;                    /* both done */
  552.     }
  553.     prhand(ph, pnum, Playwin, FALSE);
  554.     prhand(ch, cnum, Compwin, TRUE);
  555.     prtable(sum);
  556.     if (last)
  557.         if (played) {
  558.         msg(quiet ? "I get one for last" : "I get one point for last");
  559.         do_wait();
  560.         if (chkscr(&cscore, 1))
  561.             return TRUE;
  562.         }
  563.         else {
  564.         msg(quiet ? "You get one for last" :
  565.                 "You get one point for last");
  566.         if (chkscr(&pscore, 1))
  567.             return TRUE;
  568.         }
  569.     return FALSE;
  570. }
  571.  
  572. /*
  573.  * prtable:
  574.  *    Print out the table with the current score
  575.  */
  576. prtable(score)
  577. int    score;
  578. {
  579.     prhand(Table, Tcnt, Tablewin, FALSE);
  580.     mvwprintw(Tablewin, (Tcnt + 2) * 2, Tcnt + 1, "%2d", score);
  581.     wrefresh(Tablewin);
  582. }
  583.  
  584. /*
  585.  * score:
  586.  *    Handle the scoring of the hands
  587.  */
  588. score(mycrib)
  589. BOOLEAN        mycrib;
  590. {
  591.     sorthand(crib, CINHAND);
  592.     if (mycrib) {
  593.         if (plyrhand(phand, "hand"))
  594.         return TRUE;
  595.         if (comphand(chand, "hand"))
  596.         return TRUE;
  597.         do_wait();
  598.         if (comphand(crib, "crib"))
  599.         return TRUE;
  600.     }
  601.     else {
  602.         if (comphand(chand, "hand"))
  603.         return TRUE;
  604.         if (plyrhand(phand, "hand"))
  605.         return TRUE;
  606.         if (plyrhand(crib, "crib"))
  607.         return TRUE;
  608.     }
  609.     return FALSE;
  610. }
  611.