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