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