|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.