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