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: }

Defined functions

addmsg defined in line 362; used 10 times
bye defined in line 564; used 4 times
doadd defined in line 426; used 2 times
endmsg defined in line 376; used 6 times
getline defined in line 511; used 7 times
getuchar defined in line 285; used 4 times
incard defined in line 209; used 1 times
infrom defined in line 150; used 3 times
msg defined in line 349; used 38 times
msgcard defined in line 51; used 5 times
msgcrd defined in line 67; used 2 times
number defined in line 301; used 1 times
prcard defined in line 104; used 2 times
prhand defined in line 129; used 11 times
printcard defined in line 91; used 1 times
readchar defined in line 486; used 4 times
wait_for defined in line 469; used 1 times

Defined variables

Lineno defined in line 374; used 15 times
Mpos defined in line 344; used 4 times
Msgbuf defined in line 342; used 7 times
Newpos defined in line 346; used 3 times
linebuf defined in line 30; used 6 times
rankchar defined in line 37; used 5 times
rankname defined in line 32; used 2 times
sccsid defined in line 8; never used
suitchar defined in line 43; used 5 times
suitname defined in line 40; used 2 times

Defined macros

CTRL defined in line 23; used 4 times
LINESIZE defined in line 18; used 2 times
erasechar defined in line 26; used 1 times
killchar defined in line 27; used 1 times
Last modified: 1985-05-31
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 2242
Valid CSS Valid XHTML 1.0 Strict