[BACK]Return to io.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / games / cribbage

Annotation of src/games/cribbage/io.c, Revision 1.6

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

CVSweb <webmaster@jp.NetBSD.org>