Annotation of 43BSD/games/cribbage/io.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.