home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / games / cribbage / io.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-04-08  |  12.3 KB  |  616 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. static char sccsid[] = "@(#)io.c    5.8 (Berkeley) 2/28/91";
  36. #endif /* not lint */
  37.  
  38. # include    <curses.h>
  39. # include    <ctype.h>
  40. # include    <signal.h>
  41. # include    <stdarg.h>
  42. # include    "deck.h"
  43. # include    "cribbage.h"
  44. # include    "cribcur.h"
  45.  
  46. # define    LINESIZE        128
  47.  
  48. # ifdef CTRL
  49. # undef CTRL
  50. # endif
  51. # define    CTRL(X)            ('X' - 'A' + 1)
  52.  
  53. # ifdef    notdef                /* defined in curses.h */
  54. #    define    erasechar()    _tty.sg_erase
  55. #    define    killchar()    _tty.sg_kill
  56. # endif
  57.  
  58. char        linebuf[ LINESIZE ];
  59.  
  60. char        *rankname[ RANKS ]    = { "ACE", "TWO", "THREE", "FOUR",
  61.                         "FIVE", "SIX", "SEVEN", "EIGHT",
  62.                         "NINE", "TEN", "JACK", "QUEEN",
  63.                         "KING" };
  64.  
  65. char            *rankchar[ RANKS ]      = { "A", "2", "3", "4", "5", "6", "7",
  66.                         "8", "9", "T", "J", "Q", "K" };
  67.  
  68. char            *suitname[ SUITS ]      = { "SPADES", "HEARTS", "DIAMONDS",
  69.                         "CLUBS" };
  70.  
  71. char            *suitchar[ SUITS ]      = { "S", "H", "D", "C" };
  72.  
  73.  
  74.  
  75. /*
  76.  * msgcard:
  77.  *    Call msgcrd in one of two forms
  78.  */
  79. msgcard(c, brief)
  80. CARD        c;
  81. BOOLEAN        brief;
  82. {
  83.     if (brief)
  84.         return msgcrd(c, TRUE, (char *) NULL, TRUE);
  85.     else
  86.         return msgcrd(c, FALSE, " of ", FALSE);
  87. }
  88.  
  89.  
  90.  
  91. /*
  92.  * msgcrd:
  93.  *    Print the value of a card in ascii
  94.  */
  95. msgcrd(c, brfrank, mid, brfsuit)
  96. CARD        c;
  97. char        *mid;
  98. BOOLEAN        brfrank,  brfsuit;
  99. {
  100.     if (c.rank == EMPTY || c.suit == EMPTY)
  101.         return FALSE;
  102.     if (brfrank)
  103.         addmsg("%1.1s", rankchar[c.rank]);
  104.     else
  105.         addmsg(rankname[c.rank]);
  106.     if (mid != NULL)
  107.         addmsg(mid);
  108.     if (brfsuit)
  109.         addmsg("%1.1s", suitchar[c.suit]);
  110.     else
  111.         addmsg(suitname[c.suit]);
  112.     return TRUE;
  113. }
  114.  
  115. /*
  116.  * printcard:
  117.  *    Print out a card.
  118.  */
  119. printcard(win, cardno, c, blank)
  120. WINDOW        *win;
  121. int        cardno;
  122. CARD        c;
  123. BOOLEAN        blank;
  124. {
  125.     prcard(win, cardno * 2, cardno, c, blank);
  126. }
  127.  
  128. /*
  129.  * prcard:
  130.  *    Print out a card on the window at the specified location
  131.  */
  132. prcard(win, y, x, c, blank)
  133. WINDOW        *win;
  134. int        y, x;
  135. CARD        c;
  136. BOOLEAN        blank;
  137. {
  138.     if (c.rank == EMPTY)
  139.         return;
  140.     mvwaddstr(win, y + 0, x, "+-----+");
  141.     mvwaddstr(win, y + 1, x, "|     |");
  142.     mvwaddstr(win, y + 2, x, "|     |");
  143.     mvwaddstr(win, y + 3, x, "|     |");
  144.     mvwaddstr(win, y + 4, x, "+-----+");
  145.     if (!blank) {
  146.         mvwaddch(win, y + 1, x + 1, rankchar[c.rank][0]);
  147.         waddch(win, suitchar[c.suit][0]);
  148.         mvwaddch(win, y + 3, x + 4, rankchar[c.rank][0]);
  149.         waddch(win, suitchar[c.suit][0]);
  150.     }
  151. }
  152.  
  153. /*
  154.  * prhand:
  155.  *    Print a hand of n cards
  156.  */
  157. prhand(h, n, win, blank)
  158. CARD        h[];
  159. int        n;
  160. WINDOW        *win;
  161. BOOLEAN        blank;
  162. {
  163.     register int    i;
  164.  
  165.     werase(win);
  166.     for (i = 0; i < n; i++)
  167.         printcard(win, i, *h++, blank);
  168.     wrefresh(win);
  169. }
  170.  
  171.  
  172.  
  173. /*
  174.  * infrom:
  175.  *    reads a card, supposedly in hand, accepting unambigous brief
  176.  *    input, returns the index of the card found...
  177.  */
  178. infrom(hand, n, prompt)
  179. CARD        hand[];
  180. int        n;
  181. char        *prompt;
  182. {
  183.     register int           i, j;
  184.     CARD                    crd;
  185.  
  186.     if (n < 1) {
  187.         printf("\nINFROM: %d = n < 1!!\n", n);
  188.         exit(74);
  189.     }
  190.     for (;;) {
  191.         msg(prompt);
  192.         if (incard(&crd)) {            /* if card is full card */
  193.         if (!isone(crd, hand, n))
  194.             msg("That's not in your hand");
  195.         else {
  196.             for (i = 0; i < n; i++)
  197.             if (hand[i].rank == crd.rank &&
  198.                 hand[i].suit == crd.suit)
  199.                 break;
  200.             if (i >= n) {
  201.             printf("\nINFROM: isone or something messed up\n");
  202.             exit(77);
  203.             }
  204.             return i;
  205.         }
  206.         }
  207.         else                /* if not full card... */
  208.         if (crd.rank != EMPTY) {
  209.             for (i = 0; i < n; i++)
  210.             if (hand[i].rank == crd.rank)
  211.                 break;
  212.             if (i >= n)
  213.             msg("No such rank in your hand");
  214.             else {
  215.             for (j = i + 1; j < n; j++)
  216.                 if (hand[j].rank == crd.rank)
  217.                 break;
  218.             if (j < n)
  219.                 msg("Ambiguous rank");
  220.             else
  221.                 return i;
  222.             }
  223.         }
  224.         else
  225.             msg("Sorry, I missed that");
  226.     }
  227.     /* NOTREACHED */
  228. }
  229.  
  230.  
  231.  
  232. /*
  233.  * incard:
  234.  *    Inputs a card in any format.  It reads a line ending with a CR
  235.  *    and then parses it.
  236.  */
  237. incard(crd)
  238. CARD        *crd;
  239. {
  240.     char        *getline();
  241.     register int    i;
  242.     int        rnk, sut;
  243.     char        *line, *p, *p1;
  244.     BOOLEAN        retval;
  245.  
  246.     retval = FALSE;
  247.     rnk = sut = EMPTY;
  248.     if (!(line = getline()))
  249.         goto gotit;
  250.     p = p1 = line;
  251.     while(  *p1 != ' '  &&  *p1 != NULL  )  ++p1;
  252.     *p1++ = NULL;
  253.     if(  *p == NULL  )  goto  gotit;
  254.             /* IMPORTANT: no real card has 2 char first name */
  255.     if(  strlen(p) == 2  )  {               /* check for short form */
  256.         rnk = EMPTY;
  257.         for( i = 0; i < RANKS; i++ )  {
  258.         if(  *p == *rankchar[i]  )  {
  259.             rnk = i;
  260.             break;
  261.         }
  262.         }
  263.         if(  rnk == EMPTY  )  goto  gotit;     /* it's nothing... */
  264.         ++p;                                /* advance to next char */
  265.         sut = EMPTY;
  266.         for( i = 0; i < SUITS; i++ )  {
  267.         if(  *p == *suitchar[i]  )  {
  268.             sut = i;
  269.             break;
  270.         }
  271.         }
  272.         if(  sut != EMPTY  )  retval = TRUE;
  273.         goto  gotit;
  274.     }
  275.     rnk = EMPTY;
  276.     for( i = 0; i < RANKS; i++ )  {
  277.         if(  !strcmp( p, rankname[i] )  ||  !strcmp( p, rankchar[i] )  )  {
  278.         rnk = i;
  279.         break;
  280.         }
  281.     }
  282.     if(  rnk == EMPTY  )  goto  gotit;
  283.     p = p1;
  284.     while(  *p1 != ' '  &&  *p1 != NULL  )  ++p1;
  285.     *p1++ = NULL;
  286.     if(  *p == NULL  )  goto  gotit;
  287.     if(  !strcmp( "OF", p )  )  {
  288.         p = p1;
  289.         while(  *p1 != ' '  &&  *p1 != NULL  )  ++p1;
  290.         *p1++ = NULL;
  291.         if(  *p == NULL  )  goto  gotit;
  292.     }
  293.     sut = EMPTY;
  294.     for( i = 0; i < SUITS; i++ )  {
  295.         if(  !strcmp( p, suitname[i] )  ||  !strcmp( p, suitchar[i] )  )  {
  296.         sut = i;
  297.         break;
  298.         }
  299.     }
  300.     if(  sut != EMPTY  )  retval = TRUE;
  301. gotit:
  302.     (*crd).rank = rnk;
  303.     (*crd).suit = sut;
  304.     return( retval );
  305. }
  306.  
  307.  
  308.  
  309. /*
  310.  * getuchar:
  311.  *    Reads and converts to upper case
  312.  */
  313. getuchar()
  314. {
  315.     register int        c;
  316.  
  317.     c = readchar();
  318.     if (islower(c))
  319.         c = toupper(c);
  320.     waddch(Msgwin, c);
  321.     return c;
  322. }
  323.  
  324. /*
  325.  * number:
  326.  *    Reads in a decimal number and makes sure it is between "lo" and
  327.  *    "hi" inclusive.
  328.  */
  329. number(lo, hi, prompt)
  330. int        lo, hi;
  331. char        *prompt;
  332. {
  333.     char            *getline();
  334.     register char        *p;
  335.     register int        sum;
  336.  
  337.     sum = 0;
  338.     for (;;) {
  339.         msg(prompt);
  340.         if(!(p = getline()) || *p == NULL) {
  341.         msg(quiet ? "Not a number" : "That doesn't look like a number");
  342.         continue;
  343.         }
  344.         sum = 0;
  345.  
  346.         if (!isdigit(*p))
  347.         sum = lo - 1;
  348.         else
  349.         while (isdigit(*p)) {
  350.             sum = 10 * sum + (*p - '0');
  351.             ++p;
  352.         }
  353.  
  354.         if (*p != ' ' && *p != '\t' && *p != NULL)
  355.         sum = lo - 1;
  356.         if (sum >= lo && sum <= hi)
  357.         return sum;
  358.         if (sum == lo - 1)
  359.         msg("that doesn't look like a number, try again --> ");
  360.         else
  361.         msg("%d is not between %d and %d inclusive, try again --> ",
  362.                                 sum, lo, hi);
  363.     }
  364. }
  365.  
  366. /*
  367.  * msg:
  368.  *    Display a message at the top of the screen.
  369.  */
  370. char        Msgbuf[BUFSIZ] = { '\0' };
  371.  
  372. int        Mpos = 0;
  373.  
  374. static int    Newpos = 0;
  375.  
  376. /* VARARGS1 */
  377. msg(fmt)
  378.     char *fmt;
  379. {
  380.     va_list ap;
  381.  
  382.     va_start(ap, fmt);
  383.     (void)vsprintf(&Msgbuf[Newpos], fmt, ap);
  384.     va_end(ap);
  385.     endmsg();
  386. }
  387.  
  388. /*
  389.  * addmsg:
  390.  *    Add things to the current message
  391.  */
  392. /* VARARGS1 */
  393. addmsg(fmt)
  394.     char *fmt;
  395. {
  396.     va_list ap;
  397.  
  398.     va_start(ap, fmt);
  399.     (void)vsprintf(&Msgbuf[Newpos], fmt, ap);
  400.     va_end(ap);
  401. }
  402.  
  403. /*
  404.  * endmsg:
  405.  *    Display a new msg.
  406.  */
  407.  
  408. int    Lineno = 0;
  409.  
  410. endmsg()
  411. {
  412.     register int    len;
  413.     register char    *mp, *omp;
  414.     static int        lastline = 0;
  415.  
  416.     /*
  417.      * All messages should start with uppercase
  418.      */
  419.     mvaddch(lastline + Y_MSG_START, SCORE_X, ' ');
  420.     if (islower(Msgbuf[0]) && Msgbuf[1] != ')')
  421.     Msgbuf[0] = toupper(Msgbuf[0]);
  422.     mp = Msgbuf;
  423.     len = strlen(mp);
  424.     if (len / MSG_X + Lineno >= MSG_Y) {
  425.     while (Lineno < MSG_Y) {
  426.         wmove(Msgwin, Lineno++, 0);
  427.         wclrtoeol(Msgwin);
  428.     }
  429.     Lineno = 0;
  430.     }
  431.     mvaddch(Lineno + Y_MSG_START, SCORE_X, '*');
  432.     lastline = Lineno;
  433.     do {
  434.     mvwaddstr(Msgwin, Lineno, 0, mp);
  435.     if ((len = strlen(mp)) > MSG_X) {
  436.         omp = mp;
  437.         for (mp = &mp[MSG_X-1]; *mp != ' '; mp--)
  438.             continue;
  439.         while (*mp == ' ')
  440.         mp--;
  441.         mp++;
  442.         wmove(Msgwin, Lineno, mp - omp);
  443.         wclrtoeol(Msgwin);
  444.     }
  445.     if (++Lineno >= MSG_Y)
  446.         Lineno = 0;
  447.     } while (len > MSG_X);
  448.     wclrtoeol(Msgwin);
  449.     Mpos = len;
  450.     Newpos = 0;
  451.     wrefresh(Msgwin);
  452.     refresh();
  453.     wrefresh(Msgwin);
  454. }
  455.  
  456. #ifdef notdef
  457. /*
  458.  * doadd:
  459.  *    Perform an add onto the message buffer
  460.  */
  461. doadd(fmt, args)
  462. char    *fmt;
  463. int    *args;
  464. {
  465.     static FILE    junk;
  466.  
  467.     /*
  468.      * Do the printf into Msgbuf
  469.      */
  470.     junk._flag = _IOWRT + _IOSTRG;
  471.     junk._ptr = &Msgbuf[Newpos];
  472.     junk._cnt = 32767;
  473.     _doprnt(fmt, args, &junk);
  474.     putc('\0', &junk);
  475.     Newpos = strlen(Msgbuf);
  476. }
  477. #endif
  478.  
  479. /*
  480.  * do_wait:
  481.  *    Wait for the user to type ' ' before doing anything else
  482.  */
  483. do_wait()
  484. {
  485.     register int line;
  486.     static char prompt[] = { '-', '-', 'M', 'o', 'r', 'e', '-', '-', '\0' };
  487.  
  488.     if (Mpos + sizeof prompt < MSG_X)
  489.     wmove(Msgwin, Lineno > 0 ? Lineno - 1 : MSG_Y - 1, Mpos);
  490.     else {
  491.     mvwaddch(Msgwin, Lineno, 0, ' ');
  492.     wclrtoeol(Msgwin);
  493.     if (++Lineno >= MSG_Y)
  494.         Lineno = 0;
  495.     }
  496.     waddstr(Msgwin, prompt);
  497.     wrefresh(Msgwin);
  498.     wait_for(' ');
  499. }
  500.  
  501. /*
  502.  * wait_for
  503.  *    Sit around until the guy types the right key
  504.  */
  505. wait_for(ch)
  506. register char    ch;
  507. {
  508.     register char    c;
  509.  
  510.     if (ch == '\n')
  511.     while ((c = readchar()) != '\n')
  512.         continue;
  513.     else
  514.     while (readchar() != ch)
  515.         continue;
  516. }
  517.  
  518. /*
  519.  * readchar:
  520.  *    Reads and returns a character, checking for gross input errors
  521.  */
  522. readchar()
  523. {
  524.     register int    cnt, y, x;
  525.     auto char        c;
  526.  
  527. over:
  528.     cnt = 0;
  529.     while (read(0, &c, 1) <= 0)
  530.     if (cnt++ > 100) {    /* if we are getting infinite EOFs */
  531.         bye();        /* quit the game */
  532.         exit(1);
  533.     }
  534.     if (c == CTRL(L)) {
  535.     wrefresh(curscr);
  536.     goto over;
  537.     }
  538.     if (c == '\r')
  539.     return '\n';
  540.     else
  541.     return c;
  542. }
  543.  
  544. /*
  545.  * getline:
  546.  *      Reads the next line up to '\n' or EOF.  Multiple spaces are
  547.  *    compressed to one space; a space is inserted before a ','
  548.  */
  549. char *
  550. getline()
  551. {
  552.     register char    *sp;
  553.     register int    c, oy, ox;
  554.     register WINDOW    *oscr;
  555.  
  556.     oscr = stdscr;
  557.     stdscr = Msgwin;
  558.     getyx(stdscr, oy, ox);
  559.     refresh();
  560.     /*
  561.      * loop reading in the string, and put it in a temporary buffer
  562.      */
  563.     for (sp = linebuf; (c = readchar()) != '\n'; clrtoeol(), refresh()) {
  564.     if (c == -1)
  565.         continue;
  566.     else if (c == erasechar()) {    /* process erase character */
  567.         if (sp > linebuf) {
  568.         register int i;
  569.  
  570.         sp--;
  571.         for (i = strlen(unctrl(*sp)); i; i--)
  572.             addch('\b');
  573.         }
  574.         continue;
  575.     }
  576.     else if (c == killchar()) {    /* process kill character */
  577.         sp = linebuf;
  578.         move(oy, ox);
  579.         continue;
  580.     }
  581.     else if (sp == linebuf && c == ' ')
  582.         continue;
  583.     if (sp >= &linebuf[LINESIZE-1] || !(isprint(c) || c == ' '))
  584.         putchar(CTRL(G));
  585.     else {
  586.         if (islower(c))
  587.         c = toupper(c);
  588.         *sp++ = c;
  589.         addstr(unctrl(c));
  590.         Mpos++;
  591.     }
  592.     }
  593.     *sp = '\0';
  594.     stdscr = oscr;
  595.     return linebuf;
  596. }
  597.  
  598. rint()
  599. {
  600.     bye();
  601.     exit(1);
  602. }
  603.  
  604. /*
  605.  * bye:
  606.  *    Leave the program, cleaning things up as we go.
  607.  */
  608. bye()
  609. {
  610.     signal(SIGINT, SIG_IGN);
  611.     mvcur(0, COLS - 1, LINES - 1, 0);
  612.     fflush(stdout);
  613.     endwin();
  614.     putchar('\n');
  615. }
  616.