1*12572Sarnold static char *sccsid = "@(#)io.c 1.11 (Berkeley) 05/19/83"; 2*12572Sarnold 37872Sarnold # include <curses.h> 47872Sarnold # include <ctype.h> 57872Sarnold # include <unctrl.h> 67872Sarnold # include "deck.h" 77872Sarnold # include "cribbage.h" 812163Sarnold # include "cribcur.h" 97709Sarnold 107872Sarnold # define LINESIZE 128 117709Sarnold 1212163Sarnold # ifdef CTRL 1312163Sarnold # undef CTRL 1412163Sarnold # endif 157872Sarnold # define CTRL(X) ('X' - 'A' + 1) 167709Sarnold 177872Sarnold # ifndef attron 187872Sarnold # define erasechar() _tty.sg_erase 197872Sarnold # define killchar() _tty.sg_kill 207872Sarnold # endif attron 217872Sarnold 227709Sarnold char linebuf[ LINESIZE ]; 237709Sarnold 247709Sarnold char *rankname[ RANKS ] = { "ACE", "TWO", "THREE", "FOUR", 257872Sarnold "FIVE", "SIX", "SEVEN", "EIGHT", 267872Sarnold "NINE", "TEN", "JACK", "QUEEN", 277872Sarnold "KING" }; 287709Sarnold 297709Sarnold char *rankchar[ RANKS ] = { "A", "2", "3", "4", "5", "6", "7", 307872Sarnold "8", "9", "T", "J", "Q", "K" }; 317709Sarnold 327709Sarnold char *suitname[ SUITS ] = { "SPADES", "HEARTS", "DIAMONDS", 337872Sarnold "CLUBS" }; 347709Sarnold 357709Sarnold char *suitchar[ SUITS ] = { "S", "H", "D", "C" }; 367709Sarnold 377709Sarnold 387709Sarnold 397709Sarnold /* 407872Sarnold * msgcard: 417872Sarnold * Call msgcrd in one of two forms 427709Sarnold */ 437872Sarnold msgcard(c, brief) 447872Sarnold CARD c; 457872Sarnold BOOLEAN brief; 467709Sarnold { 477872Sarnold if (brief) 487872Sarnold return msgcrd(c, TRUE, (char *) NULL, TRUE); 497872Sarnold else 507872Sarnold return msgcrd(c, FALSE, " of ", FALSE); 517709Sarnold } 527709Sarnold 537709Sarnold 547709Sarnold 557709Sarnold /* 567872Sarnold * msgcrd: 577872Sarnold * Print the value of a card in ascii 587709Sarnold */ 597872Sarnold msgcrd(c, brfrank, mid, brfsuit) 607872Sarnold CARD c; 617872Sarnold char *mid; 627872Sarnold BOOLEAN brfrank, brfsuit; 637872Sarnold { 647872Sarnold if (c.rank == EMPTY || c.suit == EMPTY) 657872Sarnold return FALSE; 667872Sarnold if (brfrank) 677872Sarnold addmsg("%1.1s", rankchar[c.rank]); 687872Sarnold else 697872Sarnold addmsg(rankname[c.rank]); 707872Sarnold if (mid != NULL) 717872Sarnold addmsg(mid); 727872Sarnold if (brfsuit) 737872Sarnold addmsg("%1.1s", suitchar[c.suit]); 747872Sarnold else 757872Sarnold addmsg(suitname[c.suit]); 767872Sarnold return TRUE; 777872Sarnold } 787709Sarnold 797872Sarnold /* 807872Sarnold * printcard: 817872Sarnold * Print out a card. 827872Sarnold */ 838073Sarnold printcard(win, cardno, c, blank) 847872Sarnold WINDOW *win; 857872Sarnold int cardno; 867872Sarnold CARD c; 878073Sarnold BOOLEAN blank; 887872Sarnold { 898073Sarnold prcard(win, cardno * 2, cardno, c, blank); 907872Sarnold } 917709Sarnold 927872Sarnold /* 937872Sarnold * prcard: 947872Sarnold * Print out a card on the window at the specified location 957872Sarnold */ 967946Sarnold prcard(win, y, x, c, blank) 977872Sarnold WINDOW *win; 987872Sarnold int y, x; 997872Sarnold CARD c; 1007946Sarnold BOOLEAN blank; 1017709Sarnold { 1027872Sarnold if (c.rank == EMPTY) 1037872Sarnold return; 1047872Sarnold mvwaddstr(win, y + 0, x, "+-----+"); 1057872Sarnold mvwaddstr(win, y + 1, x, "| |"); 1067872Sarnold mvwaddstr(win, y + 2, x, "| |"); 1077872Sarnold mvwaddstr(win, y + 3, x, "| |"); 1087872Sarnold mvwaddstr(win, y + 4, x, "+-----+"); 1097946Sarnold if (!blank) { 1107946Sarnold mvwaddch(win, y + 1, x + 1, rankchar[c.rank][0]); 1117946Sarnold waddch(win, suitchar[c.suit][0]); 1127946Sarnold mvwaddch(win, y + 3, x + 4, rankchar[c.rank][0]); 1137946Sarnold waddch(win, suitchar[c.suit][0]); 1147946Sarnold } 1157709Sarnold } 1167709Sarnold 1177709Sarnold /* 1187872Sarnold * prhand: 1197872Sarnold * Print a hand of n cards 1207709Sarnold */ 1218073Sarnold prhand(h, n, win, blank) 1227872Sarnold CARD h[]; 1237872Sarnold int n; 1247872Sarnold WINDOW *win; 1258073Sarnold BOOLEAN blank; 1267709Sarnold { 1277872Sarnold register int i; 1287709Sarnold 1297872Sarnold werase(win); 1307872Sarnold for (i = 0; i < n; i++) 1318073Sarnold printcard(win, i, *h++, blank); 1327872Sarnold wrefresh(win); 1337709Sarnold } 1347709Sarnold 1357709Sarnold 1367709Sarnold 1377709Sarnold /* 1387872Sarnold * infrom: 1397872Sarnold * reads a card, supposedly in hand, accepting unambigous brief 1407872Sarnold * input, returns the index of the card found... 1417709Sarnold */ 1427872Sarnold infrom(hand, n, prompt) 1437872Sarnold CARD hand[]; 1447872Sarnold int n; 1457872Sarnold char *prompt; 1467709Sarnold { 1477872Sarnold register int i, j; 1487872Sarnold CARD crd; 1497709Sarnold 1507872Sarnold if (n < 1) { 1517872Sarnold printf("\nINFROM: %d = n < 1!!\n", n); 1527872Sarnold exit(74); 1537872Sarnold } 1547872Sarnold for (;;) { 1557947Sarnold msg(prompt); 1567872Sarnold if (incard(&crd)) { /* if card is full card */ 1577872Sarnold if (!isone(crd, hand, n)) 1587872Sarnold msg("That's not in your hand"); 1597872Sarnold else { 1607872Sarnold for (i = 0; i < n; i++) 1617872Sarnold if (hand[i].rank == crd.rank && 1627872Sarnold hand[i].suit == crd.suit) 1637872Sarnold break; 1647872Sarnold if (i >= n) { 1657872Sarnold printf("\nINFROM: isone or something messed up\n"); 1667872Sarnold exit(77); 1677872Sarnold } 1687872Sarnold return i; 1697872Sarnold } 1707872Sarnold } 1717872Sarnold else /* if not full card... */ 1727872Sarnold if (crd.rank != EMPTY) { 1737872Sarnold for (i = 0; i < n; i++) 1747872Sarnold if (hand[i].rank == crd.rank) 1757872Sarnold break; 1767872Sarnold if (i >= n) 1777872Sarnold msg("No such rank in your hand"); 1787872Sarnold else { 1797872Sarnold for (j = i + 1; j < n; j++) 1807872Sarnold if (hand[j].rank == crd.rank) 1817872Sarnold break; 1827872Sarnold if (j < n) 1837872Sarnold msg("Ambiguous rank"); 1847872Sarnold else 1857872Sarnold return i; 1867872Sarnold } 1877872Sarnold } 1887872Sarnold else 1897872Sarnold msg("Sorry, I missed that"); 1907872Sarnold } 1917872Sarnold /* NOTREACHED */ 1927709Sarnold } 1937709Sarnold 1947709Sarnold 1957709Sarnold 1967709Sarnold /* 1977872Sarnold * incard: 1987872Sarnold * Inputs a card in any format. It reads a line ending with a CR 1997872Sarnold * and then parses it. 2007709Sarnold */ 2017872Sarnold incard(crd) 2027872Sarnold CARD *crd; 2037709Sarnold { 2047872Sarnold char *getline(); 2057872Sarnold register int i; 2067872Sarnold int rnk, sut; 2077872Sarnold char *line, *p, *p1; 2087872Sarnold BOOLEAN retval; 2097709Sarnold 2107872Sarnold retval = FALSE; 2117872Sarnold rnk = sut = EMPTY; 2127872Sarnold if (!(line = getline())) 2137872Sarnold goto gotit; 2147872Sarnold p = p1 = line; 2157872Sarnold while( *p1 != ' ' && *p1 != NULL ) ++p1; 2167872Sarnold *p1++ = NULL; 2177872Sarnold if( *p == NULL ) goto gotit; 2187872Sarnold /* IMPORTANT: no real card has 2 char first name */ 2197872Sarnold if( strlen(p) == 2 ) { /* check for short form */ 2207872Sarnold rnk = EMPTY; 2217872Sarnold for( i = 0; i < RANKS; i++ ) { 2227872Sarnold if( *p == *rankchar[i] ) { 2237872Sarnold rnk = i; 2247872Sarnold break; 2257872Sarnold } 2267872Sarnold } 2277872Sarnold if( rnk == EMPTY ) goto gotit; /* it's nothing... */ 2287872Sarnold ++p; /* advance to next char */ 2297872Sarnold sut = EMPTY; 2307872Sarnold for( i = 0; i < SUITS; i++ ) { 2317872Sarnold if( *p == *suitchar[i] ) { 2327872Sarnold sut = i; 2337872Sarnold break; 2347872Sarnold } 2357872Sarnold } 2367872Sarnold if( sut != EMPTY ) retval = TRUE; 2377872Sarnold goto gotit; 2387872Sarnold } 2397872Sarnold rnk = EMPTY; 2407872Sarnold for( i = 0; i < RANKS; i++ ) { 2417872Sarnold if( !strcmp( p, rankname[i] ) || !strcmp( p, rankchar[i] ) ) { 2427872Sarnold rnk = i; 2437872Sarnold break; 2447872Sarnold } 2457872Sarnold } 2467872Sarnold if( rnk == EMPTY ) goto gotit; 2477872Sarnold p = p1; 2487872Sarnold while( *p1 != ' ' && *p1 != NULL ) ++p1; 2497872Sarnold *p1++ = NULL; 2507872Sarnold if( *p == NULL ) goto gotit; 2517872Sarnold if( !strcmp( "OF", p ) ) { 2527872Sarnold p = p1; 2537872Sarnold while( *p1 != ' ' && *p1 != NULL ) ++p1; 2547872Sarnold *p1++ = NULL; 2557872Sarnold if( *p == NULL ) goto gotit; 2567872Sarnold } 2577872Sarnold sut = EMPTY; 2587872Sarnold for( i = 0; i < SUITS; i++ ) { 2597872Sarnold if( !strcmp( p, suitname[i] ) || !strcmp( p, suitchar[i] ) ) { 2607872Sarnold sut = i; 2617872Sarnold break; 2627872Sarnold } 2637872Sarnold } 2647872Sarnold if( sut != EMPTY ) retval = TRUE; 2657709Sarnold gotit: 2667872Sarnold (*crd).rank = rnk; 2677872Sarnold (*crd).suit = sut; 2687872Sarnold return( retval ); 2697709Sarnold } 2707709Sarnold 2717709Sarnold 2727709Sarnold 2737709Sarnold /* 2747872Sarnold * getuchar: 2757872Sarnold * Reads and converts to upper case 2767709Sarnold */ 2777709Sarnold getuchar() 2787709Sarnold { 2797872Sarnold register int c; 2807709Sarnold 2817872Sarnold c = readchar(); 2827872Sarnold if (islower(c)) 2837872Sarnold c = toupper(c); 28412163Sarnold waddch(Msgwin, c); 2857872Sarnold return c; 2867709Sarnold } 2877709Sarnold 2887709Sarnold /* 2897934Sarnold * number: 2907934Sarnold * Reads in a decimal number and makes sure it is between "lo" and 2917934Sarnold * "hi" inclusive. 2927709Sarnold */ 2937934Sarnold number(lo, hi, prompt) 2947934Sarnold int lo, hi; 2957934Sarnold char *prompt; 2967709Sarnold { 2977934Sarnold char *getline(); 2987934Sarnold register char *p; 2997934Sarnold register int sum; 3007709Sarnold 3017872Sarnold sum = 0; 3027934Sarnold for (;;) { 3037934Sarnold msg(prompt); 3047934Sarnold if(!(p = getline()) || *p == NULL) { 3057934Sarnold msg(quiet ? "Not a number" : "That doesn't look like a number"); 3067934Sarnold continue; 3077934Sarnold } 3087872Sarnold sum = 0; 3097934Sarnold 3107934Sarnold if (!isdigit(*p)) 3117872Sarnold sum = lo - 1; 3127934Sarnold else 3137934Sarnold while (isdigit(*p)) { 3147934Sarnold sum = 10 * sum + (*p - '0'); 3157872Sarnold ++p; 3167934Sarnold } 3177934Sarnold 3187934Sarnold if (*p != ' ' && *p != '\t' && *p != NULL) 3197934Sarnold sum = lo - 1; 3207934Sarnold if (sum >= lo && sum <= hi) 3217934Sarnold return sum; 3227934Sarnold if (sum == lo - 1) 3237934Sarnold msg("that doesn't look like a number, try again --> "); 3247934Sarnold else 3257934Sarnold msg("%d is not between %d and %d inclusive, try again --> ", 3267934Sarnold sum, lo, hi); 3277934Sarnold } 3287709Sarnold } 3297709Sarnold 3307872Sarnold /* 3317872Sarnold * msg: 3327872Sarnold * Display a message at the top of the screen. 3337872Sarnold */ 33412157Sarnold char Msgbuf[BUFSIZ] = { '\0' }; 3357709Sarnold 3367872Sarnold int Mpos = 0; 3377709Sarnold 3387872Sarnold static int Newpos = 0; 3397872Sarnold 3407872Sarnold /* VARARGS1 */ 3417872Sarnold msg(fmt, args) 3427872Sarnold char *fmt; 3437872Sarnold int args; 3447872Sarnold { 3457872Sarnold doadd(fmt, &args); 3467872Sarnold endmsg(); 3477872Sarnold } 3487872Sarnold 3497709Sarnold /* 3507872Sarnold * addmsg: 3517872Sarnold * Add things to the current message 3527709Sarnold */ 3537872Sarnold /* VARARGS1 */ 3547872Sarnold addmsg(fmt, args) 3557872Sarnold char *fmt; 3567872Sarnold int args; 3577872Sarnold { 3587872Sarnold doadd(fmt, &args); 3597872Sarnold } 3607709Sarnold 3617872Sarnold /* 3627872Sarnold * endmsg: 36312163Sarnold * Display a new msg. 3647872Sarnold */ 36512316Sarnold 36612316Sarnold int Lineno = 0; 36712316Sarnold 3687872Sarnold endmsg() 3697709Sarnold { 37012163Sarnold register int len; 37112163Sarnold register char *mp, *omp; 37212316Sarnold static int lastline = 0; 37312163Sarnold 3747872Sarnold /* 37512316Sarnold * All messages should start with uppercase 3767872Sarnold */ 37712316Sarnold mvaddch(lastline + Y_MSG_START, SCORE_X, ' '); 3787872Sarnold if (islower(Msgbuf[0]) && Msgbuf[1] != ')') 3797872Sarnold Msgbuf[0] = toupper(Msgbuf[0]); 38012163Sarnold mp = Msgbuf; 38112163Sarnold len = strlen(mp); 38212330Sarnold if (len / MSG_X + Lineno >= MSG_Y) { 38312330Sarnold while (Lineno < MSG_Y) { 38412330Sarnold wmove(Msgwin, Lineno++, 0); 38512330Sarnold wclrtoeol(Msgwin); 38612330Sarnold } 38712316Sarnold Lineno = 0; 38812330Sarnold } 38912316Sarnold mvaddch(Lineno + Y_MSG_START, SCORE_X, '*'); 39012316Sarnold lastline = Lineno; 39112163Sarnold do { 39212316Sarnold mvwaddstr(Msgwin, Lineno, 0, mp); 39312163Sarnold if ((len = strlen(mp)) > MSG_X) { 39412163Sarnold omp = mp; 39512163Sarnold for (mp = &mp[MSG_X-1]; *mp != ' '; mp--) 39612163Sarnold continue; 39712163Sarnold while (*mp == ' ') 39812163Sarnold mp--; 39912163Sarnold mp++; 40012316Sarnold wmove(Msgwin, Lineno, mp - omp); 40112163Sarnold wclrtoeol(Msgwin); 40212163Sarnold } 40312316Sarnold if (++Lineno >= MSG_Y) 40412316Sarnold Lineno = 0; 40512163Sarnold } while (len > MSG_X); 40612163Sarnold wclrtoeol(Msgwin); 40712330Sarnold Mpos = len; 4087872Sarnold Newpos = 0; 40912163Sarnold wrefresh(Msgwin); 4107872Sarnold refresh(); 41112163Sarnold wrefresh(Msgwin); 4127872Sarnold } 4137709Sarnold 4147872Sarnold /* 4157872Sarnold * doadd: 4167872Sarnold * Perform an add onto the message buffer 4177872Sarnold */ 4187872Sarnold doadd(fmt, args) 4197872Sarnold char *fmt; 4207872Sarnold int *args; 4217872Sarnold { 4227872Sarnold static FILE junk; 4237872Sarnold 4247872Sarnold /* 4257872Sarnold * Do the printf into Msgbuf 4267872Sarnold */ 4277872Sarnold junk._flag = _IOWRT + _IOSTRG; 4287872Sarnold junk._ptr = &Msgbuf[Newpos]; 4297872Sarnold junk._cnt = 32767; 4307872Sarnold _doprnt(fmt, args, &junk); 4317872Sarnold putc('\0', &junk); 4327872Sarnold Newpos = strlen(Msgbuf); 4337709Sarnold } 4347709Sarnold 4357872Sarnold /* 43612316Sarnold * do_wait: 43712316Sarnold * Wait for the user to type ' ' before doing anything else 43812316Sarnold */ 43912316Sarnold do_wait() 44012316Sarnold { 44112316Sarnold register int line; 44212316Sarnold static char prompt[] = { '-', '-', 'M', 'o', 'r', 'e', '-', '-', '\0' }; 44312316Sarnold 44412316Sarnold if (Mpos + sizeof prompt < MSG_X) 44512316Sarnold wmove(Msgwin, Lineno > 0 ? Lineno - 1 : MSG_Y - 1, Mpos); 44612316Sarnold else { 44712316Sarnold mvwaddch(Msgwin, Lineno, 0, ' '); 44812316Sarnold wclrtoeol(Msgwin); 44912316Sarnold if (++Lineno >= MSG_Y) 45012316Sarnold Lineno = 0; 45112316Sarnold } 45212316Sarnold waddstr(Msgwin, prompt); 45312316Sarnold wrefresh(Msgwin); 45412316Sarnold wait_for(' '); 45512316Sarnold } 45612316Sarnold 45712316Sarnold /* 4587872Sarnold * wait_for 4597872Sarnold * Sit around until the guy types the right key 4607872Sarnold */ 4617872Sarnold wait_for(ch) 4627872Sarnold register char ch; 4637872Sarnold { 4647872Sarnold register char c; 4657709Sarnold 4667872Sarnold if (ch == '\n') 4677872Sarnold while ((c = readchar()) != '\n') 4687872Sarnold continue; 4697872Sarnold else 4707872Sarnold while (readchar() != ch) 4717872Sarnold continue; 4727872Sarnold } 4737709Sarnold 4747872Sarnold /* 4757872Sarnold * readchar: 4767872Sarnold * Reads and returns a character, checking for gross input errors 4777872Sarnold */ 4787872Sarnold readchar() 4797872Sarnold { 4807872Sarnold register int cnt, y, x; 4817872Sarnold auto char c; 4827709Sarnold 4837872Sarnold over: 4847872Sarnold cnt = 0; 4857872Sarnold while (read(0, &c, 1) <= 0) 4867872Sarnold if (cnt++ > 100) /* if we are getting infinite EOFs */ 4877872Sarnold bye(); /* quit the game */ 4887872Sarnold if (c == CTRL(L)) { 4897872Sarnold wrefresh(curscr); 4907872Sarnold goto over; 4917872Sarnold } 4927872Sarnold if (c == '\r') 4937872Sarnold return '\n'; 4947872Sarnold else 4957872Sarnold return c; 4967872Sarnold } 4977872Sarnold 4987872Sarnold /* 4997872Sarnold * getline: 5007872Sarnold * Reads the next line up to '\n' or EOF. Multiple spaces are 5017872Sarnold * compressed to one space; a space is inserted before a ',' 5027872Sarnold */ 5037872Sarnold char * 5047872Sarnold getline() 5057872Sarnold { 5067872Sarnold register char *sp; 5077872Sarnold register int c, oy, ox; 50812163Sarnold register WINDOW *oscr; 5097872Sarnold 51012163Sarnold oscr = stdscr; 51112163Sarnold stdscr = Msgwin; 5127872Sarnold getyx(stdscr, oy, ox); 5137872Sarnold refresh(); 5147872Sarnold /* 5157872Sarnold * loop reading in the string, and put it in a temporary buffer 5167872Sarnold */ 5177872Sarnold for (sp = linebuf; (c = readchar()) != '\n'; clrtoeol(), refresh()) { 5187872Sarnold if (c == -1) 5197872Sarnold continue; 5207872Sarnold else if (c == erasechar()) { /* process erase character */ 5217872Sarnold if (sp > linebuf) { 5227872Sarnold register int i; 5237872Sarnold 5247872Sarnold sp--; 5257872Sarnold for (i = strlen(unctrl(*sp)); i; i--) 5267872Sarnold addch('\b'); 5277872Sarnold } 5287872Sarnold continue; 5297872Sarnold } 5307872Sarnold else if (c == killchar()) { /* process kill character */ 5317872Sarnold sp = linebuf; 5327872Sarnold move(oy, ox); 5337872Sarnold continue; 5347872Sarnold } 5357872Sarnold else if (sp == linebuf && c == ' ') 5367872Sarnold continue; 5377872Sarnold if (sp >= &linebuf[LINESIZE-1] || !(isprint(c) || c == ' ')) 5387872Sarnold putchar(CTRL(G)); 5397872Sarnold else { 5407872Sarnold if (islower(c)) 5417872Sarnold c = toupper(c); 5427872Sarnold *sp++ = c; 5437872Sarnold addstr(unctrl(c)); 5447872Sarnold Mpos++; 5457872Sarnold } 5467872Sarnold } 5477872Sarnold *sp = '\0'; 54812163Sarnold stdscr = oscr; 5497872Sarnold return linebuf; 5507872Sarnold } 551