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