121505Smckusick /* 221505Smckusick * Copyright (c) 1980 Regents of the University of California. 333707Sbostic * All rights reserved. 433707Sbostic * 542576Sbostic * %sccs.include.redist.c% 621505Smckusick */ 712572Sarnold 821505Smckusick #ifndef lint 9*46743Sbostic static char sccsid[] = "@(#)io.c 5.8 (Berkeley) 02/28/91"; 1033707Sbostic #endif /* not lint */ 1121505Smckusick 127872Sarnold # include <curses.h> 137872Sarnold # include <ctype.h> 1414910Sarnold # include <signal.h> 1546264Sbostic # include <stdarg.h> 167872Sarnold # include "deck.h" 177872Sarnold # include "cribbage.h" 1812163Sarnold # include "cribcur.h" 197709Sarnold 207872Sarnold # define LINESIZE 128 217709Sarnold 2212163Sarnold # ifdef CTRL 2312163Sarnold # undef CTRL 2412163Sarnold # endif 257872Sarnold # define CTRL(X) ('X' - 'A' + 1) 267709Sarnold 2732355Sbostic # ifdef notdef /* defined in curses.h */ 287872Sarnold # define erasechar() _tty.sg_erase 297872Sarnold # define killchar() _tty.sg_kill 3032355Sbostic # endif 317872Sarnold 327709Sarnold char linebuf[ LINESIZE ]; 337709Sarnold 347709Sarnold char *rankname[ RANKS ] = { "ACE", "TWO", "THREE", "FOUR", 357872Sarnold "FIVE", "SIX", "SEVEN", "EIGHT", 367872Sarnold "NINE", "TEN", "JACK", "QUEEN", 377872Sarnold "KING" }; 387709Sarnold 397709Sarnold char *rankchar[ RANKS ] = { "A", "2", "3", "4", "5", "6", "7", 407872Sarnold "8", "9", "T", "J", "Q", "K" }; 417709Sarnold 427709Sarnold char *suitname[ SUITS ] = { "SPADES", "HEARTS", "DIAMONDS", 437872Sarnold "CLUBS" }; 447709Sarnold 457709Sarnold char *suitchar[ SUITS ] = { "S", "H", "D", "C" }; 467709Sarnold 477709Sarnold 487709Sarnold 497709Sarnold /* 507872Sarnold * msgcard: 517872Sarnold * Call msgcrd in one of two forms 527709Sarnold */ 537872Sarnold msgcard(c, brief) 547872Sarnold CARD c; 557872Sarnold BOOLEAN brief; 567709Sarnold { 577872Sarnold if (brief) 587872Sarnold return msgcrd(c, TRUE, (char *) NULL, TRUE); 597872Sarnold else 607872Sarnold return msgcrd(c, FALSE, " of ", FALSE); 617709Sarnold } 627709Sarnold 637709Sarnold 647709Sarnold 657709Sarnold /* 667872Sarnold * msgcrd: 677872Sarnold * Print the value of a card in ascii 687709Sarnold */ 697872Sarnold msgcrd(c, brfrank, mid, brfsuit) 707872Sarnold CARD c; 717872Sarnold char *mid; 727872Sarnold BOOLEAN brfrank, brfsuit; 737872Sarnold { 747872Sarnold if (c.rank == EMPTY || c.suit == EMPTY) 757872Sarnold return FALSE; 767872Sarnold if (brfrank) 777872Sarnold addmsg("%1.1s", rankchar[c.rank]); 787872Sarnold else 797872Sarnold addmsg(rankname[c.rank]); 807872Sarnold if (mid != NULL) 817872Sarnold addmsg(mid); 827872Sarnold if (brfsuit) 837872Sarnold addmsg("%1.1s", suitchar[c.suit]); 847872Sarnold else 857872Sarnold addmsg(suitname[c.suit]); 867872Sarnold return TRUE; 877872Sarnold } 887709Sarnold 897872Sarnold /* 907872Sarnold * printcard: 917872Sarnold * Print out a card. 927872Sarnold */ 938073Sarnold printcard(win, cardno, c, blank) 947872Sarnold WINDOW *win; 957872Sarnold int cardno; 967872Sarnold CARD c; 978073Sarnold BOOLEAN blank; 987872Sarnold { 998073Sarnold prcard(win, cardno * 2, cardno, c, blank); 1007872Sarnold } 1017709Sarnold 1027872Sarnold /* 1037872Sarnold * prcard: 1047872Sarnold * Print out a card on the window at the specified location 1057872Sarnold */ 1067946Sarnold prcard(win, y, x, c, blank) 1077872Sarnold WINDOW *win; 1087872Sarnold int y, x; 1097872Sarnold CARD c; 1107946Sarnold BOOLEAN blank; 1117709Sarnold { 1127872Sarnold if (c.rank == EMPTY) 1137872Sarnold return; 1147872Sarnold mvwaddstr(win, y + 0, x, "+-----+"); 1157872Sarnold mvwaddstr(win, y + 1, x, "| |"); 1167872Sarnold mvwaddstr(win, y + 2, x, "| |"); 1177872Sarnold mvwaddstr(win, y + 3, x, "| |"); 1187872Sarnold mvwaddstr(win, y + 4, x, "+-----+"); 1197946Sarnold if (!blank) { 1207946Sarnold mvwaddch(win, y + 1, x + 1, rankchar[c.rank][0]); 1217946Sarnold waddch(win, suitchar[c.suit][0]); 1227946Sarnold mvwaddch(win, y + 3, x + 4, rankchar[c.rank][0]); 1237946Sarnold waddch(win, suitchar[c.suit][0]); 1247946Sarnold } 1257709Sarnold } 1267709Sarnold 1277709Sarnold /* 1287872Sarnold * prhand: 1297872Sarnold * Print a hand of n cards 1307709Sarnold */ 1318073Sarnold prhand(h, n, win, blank) 1327872Sarnold CARD h[]; 1337872Sarnold int n; 1347872Sarnold WINDOW *win; 1358073Sarnold BOOLEAN blank; 1367709Sarnold { 1377872Sarnold register int i; 1387709Sarnold 1397872Sarnold werase(win); 1407872Sarnold for (i = 0; i < n; i++) 1418073Sarnold printcard(win, i, *h++, blank); 1427872Sarnold wrefresh(win); 1437709Sarnold } 1447709Sarnold 1457709Sarnold 1467709Sarnold 1477709Sarnold /* 1487872Sarnold * infrom: 1497872Sarnold * reads a card, supposedly in hand, accepting unambigous brief 1507872Sarnold * input, returns the index of the card found... 1517709Sarnold */ 1527872Sarnold infrom(hand, n, prompt) 1537872Sarnold CARD hand[]; 1547872Sarnold int n; 1557872Sarnold char *prompt; 1567709Sarnold { 1577872Sarnold register int i, j; 1587872Sarnold CARD crd; 1597709Sarnold 1607872Sarnold if (n < 1) { 1617872Sarnold printf("\nINFROM: %d = n < 1!!\n", n); 1627872Sarnold exit(74); 1637872Sarnold } 1647872Sarnold for (;;) { 1657947Sarnold msg(prompt); 1667872Sarnold if (incard(&crd)) { /* if card is full card */ 1677872Sarnold if (!isone(crd, hand, n)) 1687872Sarnold msg("That's not in your hand"); 1697872Sarnold else { 1707872Sarnold for (i = 0; i < n; i++) 1717872Sarnold if (hand[i].rank == crd.rank && 1727872Sarnold hand[i].suit == crd.suit) 1737872Sarnold break; 1747872Sarnold if (i >= n) { 1757872Sarnold printf("\nINFROM: isone or something messed up\n"); 1767872Sarnold exit(77); 1777872Sarnold } 1787872Sarnold return i; 1797872Sarnold } 1807872Sarnold } 1817872Sarnold else /* if not full card... */ 1827872Sarnold if (crd.rank != EMPTY) { 1837872Sarnold for (i = 0; i < n; i++) 1847872Sarnold if (hand[i].rank == crd.rank) 1857872Sarnold break; 1867872Sarnold if (i >= n) 1877872Sarnold msg("No such rank in your hand"); 1887872Sarnold else { 1897872Sarnold for (j = i + 1; j < n; j++) 1907872Sarnold if (hand[j].rank == crd.rank) 1917872Sarnold break; 1927872Sarnold if (j < n) 1937872Sarnold msg("Ambiguous rank"); 1947872Sarnold else 1957872Sarnold return i; 1967872Sarnold } 1977872Sarnold } 1987872Sarnold else 1997872Sarnold msg("Sorry, I missed that"); 2007872Sarnold } 2017872Sarnold /* NOTREACHED */ 2027709Sarnold } 2037709Sarnold 2047709Sarnold 2057709Sarnold 2067709Sarnold /* 2077872Sarnold * incard: 2087872Sarnold * Inputs a card in any format. It reads a line ending with a CR 2097872Sarnold * and then parses it. 2107709Sarnold */ 2117872Sarnold incard(crd) 2127872Sarnold CARD *crd; 2137709Sarnold { 2147872Sarnold char *getline(); 2157872Sarnold register int i; 2167872Sarnold int rnk, sut; 2177872Sarnold char *line, *p, *p1; 2187872Sarnold BOOLEAN retval; 2197709Sarnold 2207872Sarnold retval = FALSE; 2217872Sarnold rnk = sut = EMPTY; 2227872Sarnold if (!(line = getline())) 2237872Sarnold goto gotit; 2247872Sarnold p = p1 = line; 2257872Sarnold while( *p1 != ' ' && *p1 != NULL ) ++p1; 2267872Sarnold *p1++ = NULL; 2277872Sarnold if( *p == NULL ) goto gotit; 2287872Sarnold /* IMPORTANT: no real card has 2 char first name */ 2297872Sarnold if( strlen(p) == 2 ) { /* check for short form */ 2307872Sarnold rnk = EMPTY; 2317872Sarnold for( i = 0; i < RANKS; i++ ) { 2327872Sarnold if( *p == *rankchar[i] ) { 2337872Sarnold rnk = i; 2347872Sarnold break; 2357872Sarnold } 2367872Sarnold } 2377872Sarnold if( rnk == EMPTY ) goto gotit; /* it's nothing... */ 2387872Sarnold ++p; /* advance to next char */ 2397872Sarnold sut = EMPTY; 2407872Sarnold for( i = 0; i < SUITS; i++ ) { 2417872Sarnold if( *p == *suitchar[i] ) { 2427872Sarnold sut = i; 2437872Sarnold break; 2447872Sarnold } 2457872Sarnold } 2467872Sarnold if( sut != EMPTY ) retval = TRUE; 2477872Sarnold goto gotit; 2487872Sarnold } 2497872Sarnold rnk = EMPTY; 2507872Sarnold for( i = 0; i < RANKS; i++ ) { 2517872Sarnold if( !strcmp( p, rankname[i] ) || !strcmp( p, rankchar[i] ) ) { 2527872Sarnold rnk = i; 2537872Sarnold break; 2547872Sarnold } 2557872Sarnold } 2567872Sarnold if( rnk == EMPTY ) goto gotit; 2577872Sarnold p = p1; 2587872Sarnold while( *p1 != ' ' && *p1 != NULL ) ++p1; 2597872Sarnold *p1++ = NULL; 2607872Sarnold if( *p == NULL ) goto gotit; 2617872Sarnold if( !strcmp( "OF", p ) ) { 2627872Sarnold p = p1; 2637872Sarnold while( *p1 != ' ' && *p1 != NULL ) ++p1; 2647872Sarnold *p1++ = NULL; 2657872Sarnold if( *p == NULL ) goto gotit; 2667872Sarnold } 2677872Sarnold sut = EMPTY; 2687872Sarnold for( i = 0; i < SUITS; i++ ) { 2697872Sarnold if( !strcmp( p, suitname[i] ) || !strcmp( p, suitchar[i] ) ) { 2707872Sarnold sut = i; 2717872Sarnold break; 2727872Sarnold } 2737872Sarnold } 2747872Sarnold if( sut != EMPTY ) retval = TRUE; 2757709Sarnold gotit: 2767872Sarnold (*crd).rank = rnk; 2777872Sarnold (*crd).suit = sut; 2787872Sarnold return( retval ); 2797709Sarnold } 2807709Sarnold 2817709Sarnold 2827709Sarnold 2837709Sarnold /* 2847872Sarnold * getuchar: 2857872Sarnold * Reads and converts to upper case 2867709Sarnold */ 2877709Sarnold getuchar() 2887709Sarnold { 2897872Sarnold register int c; 2907709Sarnold 2917872Sarnold c = readchar(); 2927872Sarnold if (islower(c)) 2937872Sarnold c = toupper(c); 29412163Sarnold waddch(Msgwin, c); 2957872Sarnold return c; 2967709Sarnold } 2977709Sarnold 2987709Sarnold /* 2997934Sarnold * number: 3007934Sarnold * Reads in a decimal number and makes sure it is between "lo" and 3017934Sarnold * "hi" inclusive. 3027709Sarnold */ 3037934Sarnold number(lo, hi, prompt) 3047934Sarnold int lo, hi; 3057934Sarnold char *prompt; 3067709Sarnold { 3077934Sarnold char *getline(); 3087934Sarnold register char *p; 3097934Sarnold register int sum; 3107709Sarnold 3117872Sarnold sum = 0; 3127934Sarnold for (;;) { 3137934Sarnold msg(prompt); 3147934Sarnold if(!(p = getline()) || *p == NULL) { 3157934Sarnold msg(quiet ? "Not a number" : "That doesn't look like a number"); 3167934Sarnold continue; 3177934Sarnold } 3187872Sarnold sum = 0; 3197934Sarnold 3207934Sarnold if (!isdigit(*p)) 3217872Sarnold sum = lo - 1; 3227934Sarnold else 3237934Sarnold while (isdigit(*p)) { 3247934Sarnold sum = 10 * sum + (*p - '0'); 3257872Sarnold ++p; 3267934Sarnold } 3277934Sarnold 3287934Sarnold if (*p != ' ' && *p != '\t' && *p != NULL) 3297934Sarnold sum = lo - 1; 3307934Sarnold if (sum >= lo && sum <= hi) 3317934Sarnold return sum; 3327934Sarnold if (sum == lo - 1) 3337934Sarnold msg("that doesn't look like a number, try again --> "); 3347934Sarnold else 3357934Sarnold msg("%d is not between %d and %d inclusive, try again --> ", 3367934Sarnold sum, lo, hi); 3377934Sarnold } 3387709Sarnold } 3397709Sarnold 3407872Sarnold /* 3417872Sarnold * msg: 3427872Sarnold * Display a message at the top of the screen. 3437872Sarnold */ 34412157Sarnold char Msgbuf[BUFSIZ] = { '\0' }; 3457709Sarnold 3467872Sarnold int Mpos = 0; 3477709Sarnold 3487872Sarnold static int Newpos = 0; 3497872Sarnold 3507872Sarnold /* VARARGS1 */ 35146264Sbostic msg(fmt) 35246264Sbostic char *fmt; 3537872Sarnold { 35446264Sbostic va_list ap; 35546264Sbostic 35646264Sbostic va_start(ap, fmt); 357*46743Sbostic (void)vsprintf(&Msgbuf[Newpos], fmt, ap); 35846264Sbostic va_end(ap); 35946264Sbostic endmsg(); 3607872Sarnold } 3617872Sarnold 3627709Sarnold /* 3637872Sarnold * addmsg: 3647872Sarnold * Add things to the current message 3657709Sarnold */ 3667872Sarnold /* VARARGS1 */ 36746264Sbostic addmsg(fmt) 36846264Sbostic char *fmt; 3697872Sarnold { 37046264Sbostic va_list ap; 37146264Sbostic 37246264Sbostic va_start(ap, fmt); 373*46743Sbostic (void)vsprintf(&Msgbuf[Newpos], fmt, ap); 37446264Sbostic va_end(ap); 3757872Sarnold } 3767709Sarnold 3777872Sarnold /* 3787872Sarnold * endmsg: 37912163Sarnold * Display a new msg. 3807872Sarnold */ 38112316Sarnold 38212316Sarnold int Lineno = 0; 38312316Sarnold 3847872Sarnold endmsg() 3857709Sarnold { 38612163Sarnold register int len; 38712163Sarnold register char *mp, *omp; 38812316Sarnold static int lastline = 0; 38912163Sarnold 3907872Sarnold /* 39112316Sarnold * All messages should start with uppercase 3927872Sarnold */ 39312316Sarnold mvaddch(lastline + Y_MSG_START, SCORE_X, ' '); 3947872Sarnold if (islower(Msgbuf[0]) && Msgbuf[1] != ')') 3957872Sarnold Msgbuf[0] = toupper(Msgbuf[0]); 39612163Sarnold mp = Msgbuf; 39712163Sarnold len = strlen(mp); 39812330Sarnold if (len / MSG_X + Lineno >= MSG_Y) { 39912330Sarnold while (Lineno < MSG_Y) { 40012330Sarnold wmove(Msgwin, Lineno++, 0); 40112330Sarnold wclrtoeol(Msgwin); 40212330Sarnold } 40312316Sarnold Lineno = 0; 40412330Sarnold } 40512316Sarnold mvaddch(Lineno + Y_MSG_START, SCORE_X, '*'); 40612316Sarnold lastline = Lineno; 40712163Sarnold do { 40812316Sarnold mvwaddstr(Msgwin, Lineno, 0, mp); 40912163Sarnold if ((len = strlen(mp)) > MSG_X) { 41012163Sarnold omp = mp; 41112163Sarnold for (mp = &mp[MSG_X-1]; *mp != ' '; mp--) 41212163Sarnold continue; 41312163Sarnold while (*mp == ' ') 41412163Sarnold mp--; 41512163Sarnold mp++; 41612316Sarnold wmove(Msgwin, Lineno, mp - omp); 41712163Sarnold wclrtoeol(Msgwin); 41812163Sarnold } 41912316Sarnold if (++Lineno >= MSG_Y) 42012316Sarnold Lineno = 0; 42112163Sarnold } while (len > MSG_X); 42212163Sarnold wclrtoeol(Msgwin); 42312330Sarnold Mpos = len; 4247872Sarnold Newpos = 0; 42512163Sarnold wrefresh(Msgwin); 4267872Sarnold refresh(); 42712163Sarnold wrefresh(Msgwin); 4287872Sarnold } 4297709Sarnold 43046264Sbostic #ifdef notdef 4317872Sarnold /* 4327872Sarnold * doadd: 4337872Sarnold * Perform an add onto the message buffer 4347872Sarnold */ 4357872Sarnold doadd(fmt, args) 4367872Sarnold char *fmt; 4377872Sarnold int *args; 4387872Sarnold { 4397872Sarnold static FILE junk; 4407872Sarnold 4417872Sarnold /* 4427872Sarnold * Do the printf into Msgbuf 4437872Sarnold */ 4447872Sarnold junk._flag = _IOWRT + _IOSTRG; 4457872Sarnold junk._ptr = &Msgbuf[Newpos]; 4467872Sarnold junk._cnt = 32767; 4477872Sarnold _doprnt(fmt, args, &junk); 4487872Sarnold putc('\0', &junk); 4497872Sarnold Newpos = strlen(Msgbuf); 4507709Sarnold } 45146264Sbostic #endif 4527709Sarnold 4537872Sarnold /* 45412316Sarnold * do_wait: 45512316Sarnold * Wait for the user to type ' ' before doing anything else 45612316Sarnold */ 45712316Sarnold do_wait() 45812316Sarnold { 45912316Sarnold register int line; 46012316Sarnold static char prompt[] = { '-', '-', 'M', 'o', 'r', 'e', '-', '-', '\0' }; 46112316Sarnold 46212316Sarnold if (Mpos + sizeof prompt < MSG_X) 46312316Sarnold wmove(Msgwin, Lineno > 0 ? Lineno - 1 : MSG_Y - 1, Mpos); 46412316Sarnold else { 46512316Sarnold mvwaddch(Msgwin, Lineno, 0, ' '); 46612316Sarnold wclrtoeol(Msgwin); 46712316Sarnold if (++Lineno >= MSG_Y) 46812316Sarnold Lineno = 0; 46912316Sarnold } 47012316Sarnold waddstr(Msgwin, prompt); 47112316Sarnold wrefresh(Msgwin); 47212316Sarnold wait_for(' '); 47312316Sarnold } 47412316Sarnold 47512316Sarnold /* 4767872Sarnold * wait_for 4777872Sarnold * Sit around until the guy types the right key 4787872Sarnold */ 4797872Sarnold wait_for(ch) 4807872Sarnold register char ch; 4817872Sarnold { 4827872Sarnold register char c; 4837709Sarnold 4847872Sarnold if (ch == '\n') 4857872Sarnold while ((c = readchar()) != '\n') 4867872Sarnold continue; 4877872Sarnold else 4887872Sarnold while (readchar() != ch) 4897872Sarnold continue; 4907872Sarnold } 4917709Sarnold 4927872Sarnold /* 4937872Sarnold * readchar: 4947872Sarnold * Reads and returns a character, checking for gross input errors 4957872Sarnold */ 4967872Sarnold readchar() 4977872Sarnold { 4987872Sarnold register int cnt, y, x; 4997872Sarnold auto char c; 5007709Sarnold 5017872Sarnold over: 5027872Sarnold cnt = 0; 5037872Sarnold while (read(0, &c, 1) <= 0) 50441186Sbostic if (cnt++ > 100) { /* if we are getting infinite EOFs */ 50541186Sbostic bye(); /* quit the game */ 50641186Sbostic exit(1); 50741186Sbostic } 5087872Sarnold if (c == CTRL(L)) { 5097872Sarnold wrefresh(curscr); 5107872Sarnold goto over; 5117872Sarnold } 5127872Sarnold if (c == '\r') 5137872Sarnold return '\n'; 5147872Sarnold else 5157872Sarnold return c; 5167872Sarnold } 5177872Sarnold 5187872Sarnold /* 5197872Sarnold * getline: 5207872Sarnold * Reads the next line up to '\n' or EOF. Multiple spaces are 5217872Sarnold * compressed to one space; a space is inserted before a ',' 5227872Sarnold */ 5237872Sarnold char * 5247872Sarnold getline() 5257872Sarnold { 5267872Sarnold register char *sp; 5277872Sarnold register int c, oy, ox; 52812163Sarnold register WINDOW *oscr; 5297872Sarnold 53012163Sarnold oscr = stdscr; 53112163Sarnold stdscr = Msgwin; 5327872Sarnold getyx(stdscr, oy, ox); 5337872Sarnold refresh(); 5347872Sarnold /* 5357872Sarnold * loop reading in the string, and put it in a temporary buffer 5367872Sarnold */ 5377872Sarnold for (sp = linebuf; (c = readchar()) != '\n'; clrtoeol(), refresh()) { 5387872Sarnold if (c == -1) 5397872Sarnold continue; 5407872Sarnold else if (c == erasechar()) { /* process erase character */ 5417872Sarnold if (sp > linebuf) { 5427872Sarnold register int i; 5437872Sarnold 5447872Sarnold sp--; 5457872Sarnold for (i = strlen(unctrl(*sp)); i; i--) 5467872Sarnold addch('\b'); 5477872Sarnold } 5487872Sarnold continue; 5497872Sarnold } 5507872Sarnold else if (c == killchar()) { /* process kill character */ 5517872Sarnold sp = linebuf; 5527872Sarnold move(oy, ox); 5537872Sarnold continue; 5547872Sarnold } 5557872Sarnold else if (sp == linebuf && c == ' ') 5567872Sarnold continue; 5577872Sarnold if (sp >= &linebuf[LINESIZE-1] || !(isprint(c) || c == ' ')) 5587872Sarnold putchar(CTRL(G)); 5597872Sarnold else { 5607872Sarnold if (islower(c)) 5617872Sarnold c = toupper(c); 5627872Sarnold *sp++ = c; 5637872Sarnold addstr(unctrl(c)); 5647872Sarnold Mpos++; 5657872Sarnold } 5667872Sarnold } 5677872Sarnold *sp = '\0'; 56812163Sarnold stdscr = oscr; 5697872Sarnold return linebuf; 5707872Sarnold } 57114910Sarnold 57241186Sbostic rint() 57341186Sbostic { 57441186Sbostic bye(); 57541186Sbostic exit(1); 57641186Sbostic } 57741186Sbostic 57814910Sarnold /* 57914910Sarnold * bye: 58014910Sarnold * Leave the program, cleaning things up as we go. 58114910Sarnold */ 58214910Sarnold bye() 58314910Sarnold { 58414910Sarnold signal(SIGINT, SIG_IGN); 58514910Sarnold mvcur(0, COLS - 1, LINES - 1, 0); 58614910Sarnold fflush(stdout); 58714910Sarnold endwin(); 58814910Sarnold putchar('\n'); 58914910Sarnold } 590