121505Smckusick /* 221505Smckusick * Copyright (c) 1980 Regents of the University of California. 333707Sbostic * All rights reserved. 433707Sbostic * 5*42576Sbostic * %sccs.include.redist.c% 621505Smckusick */ 712572Sarnold 821505Smckusick #ifndef lint 9*42576Sbostic static char sccsid[] = "@(#)io.c 5.6 (Berkeley) 06/01/90"; 1033707Sbostic #endif /* not lint */ 1121505Smckusick 127872Sarnold # include <curses.h> 137872Sarnold # include <ctype.h> 1414910Sarnold # include <signal.h> 157872Sarnold # include "deck.h" 167872Sarnold # include "cribbage.h" 1712163Sarnold # include "cribcur.h" 187709Sarnold 197872Sarnold # define LINESIZE 128 207709Sarnold 2112163Sarnold # ifdef CTRL 2212163Sarnold # undef CTRL 2312163Sarnold # endif 247872Sarnold # define CTRL(X) ('X' - 'A' + 1) 257709Sarnold 2632355Sbostic # ifdef notdef /* defined in curses.h */ 277872Sarnold # define erasechar() _tty.sg_erase 287872Sarnold # define killchar() _tty.sg_kill 2932355Sbostic # endif 307872Sarnold 317709Sarnold char linebuf[ LINESIZE ]; 327709Sarnold 337709Sarnold char *rankname[ RANKS ] = { "ACE", "TWO", "THREE", "FOUR", 347872Sarnold "FIVE", "SIX", "SEVEN", "EIGHT", 357872Sarnold "NINE", "TEN", "JACK", "QUEEN", 367872Sarnold "KING" }; 377709Sarnold 387709Sarnold char *rankchar[ RANKS ] = { "A", "2", "3", "4", "5", "6", "7", 397872Sarnold "8", "9", "T", "J", "Q", "K" }; 407709Sarnold 417709Sarnold char *suitname[ SUITS ] = { "SPADES", "HEARTS", "DIAMONDS", 427872Sarnold "CLUBS" }; 437709Sarnold 447709Sarnold char *suitchar[ SUITS ] = { "S", "H", "D", "C" }; 457709Sarnold 467709Sarnold 477709Sarnold 487709Sarnold /* 497872Sarnold * msgcard: 507872Sarnold * Call msgcrd in one of two forms 517709Sarnold */ 527872Sarnold msgcard(c, brief) 537872Sarnold CARD c; 547872Sarnold BOOLEAN brief; 557709Sarnold { 567872Sarnold if (brief) 577872Sarnold return msgcrd(c, TRUE, (char *) NULL, TRUE); 587872Sarnold else 597872Sarnold return msgcrd(c, FALSE, " of ", FALSE); 607709Sarnold } 617709Sarnold 627709Sarnold 637709Sarnold 647709Sarnold /* 657872Sarnold * msgcrd: 667872Sarnold * Print the value of a card in ascii 677709Sarnold */ 687872Sarnold msgcrd(c, brfrank, mid, brfsuit) 697872Sarnold CARD c; 707872Sarnold char *mid; 717872Sarnold BOOLEAN brfrank, brfsuit; 727872Sarnold { 737872Sarnold if (c.rank == EMPTY || c.suit == EMPTY) 747872Sarnold return FALSE; 757872Sarnold if (brfrank) 767872Sarnold addmsg("%1.1s", rankchar[c.rank]); 777872Sarnold else 787872Sarnold addmsg(rankname[c.rank]); 797872Sarnold if (mid != NULL) 807872Sarnold addmsg(mid); 817872Sarnold if (brfsuit) 827872Sarnold addmsg("%1.1s", suitchar[c.suit]); 837872Sarnold else 847872Sarnold addmsg(suitname[c.suit]); 857872Sarnold return TRUE; 867872Sarnold } 877709Sarnold 887872Sarnold /* 897872Sarnold * printcard: 907872Sarnold * Print out a card. 917872Sarnold */ 928073Sarnold printcard(win, cardno, c, blank) 937872Sarnold WINDOW *win; 947872Sarnold int cardno; 957872Sarnold CARD c; 968073Sarnold BOOLEAN blank; 977872Sarnold { 988073Sarnold prcard(win, cardno * 2, cardno, c, blank); 997872Sarnold } 1007709Sarnold 1017872Sarnold /* 1027872Sarnold * prcard: 1037872Sarnold * Print out a card on the window at the specified location 1047872Sarnold */ 1057946Sarnold prcard(win, y, x, c, blank) 1067872Sarnold WINDOW *win; 1077872Sarnold int y, x; 1087872Sarnold CARD c; 1097946Sarnold BOOLEAN blank; 1107709Sarnold { 1117872Sarnold if (c.rank == EMPTY) 1127872Sarnold return; 1137872Sarnold mvwaddstr(win, y + 0, x, "+-----+"); 1147872Sarnold mvwaddstr(win, y + 1, x, "| |"); 1157872Sarnold mvwaddstr(win, y + 2, x, "| |"); 1167872Sarnold mvwaddstr(win, y + 3, x, "| |"); 1177872Sarnold mvwaddstr(win, y + 4, x, "+-----+"); 1187946Sarnold if (!blank) { 1197946Sarnold mvwaddch(win, y + 1, x + 1, rankchar[c.rank][0]); 1207946Sarnold waddch(win, suitchar[c.suit][0]); 1217946Sarnold mvwaddch(win, y + 3, x + 4, rankchar[c.rank][0]); 1227946Sarnold waddch(win, suitchar[c.suit][0]); 1237946Sarnold } 1247709Sarnold } 1257709Sarnold 1267709Sarnold /* 1277872Sarnold * prhand: 1287872Sarnold * Print a hand of n cards 1297709Sarnold */ 1308073Sarnold prhand(h, n, win, blank) 1317872Sarnold CARD h[]; 1327872Sarnold int n; 1337872Sarnold WINDOW *win; 1348073Sarnold BOOLEAN blank; 1357709Sarnold { 1367872Sarnold register int i; 1377709Sarnold 1387872Sarnold werase(win); 1397872Sarnold for (i = 0; i < n; i++) 1408073Sarnold printcard(win, i, *h++, blank); 1417872Sarnold wrefresh(win); 1427709Sarnold } 1437709Sarnold 1447709Sarnold 1457709Sarnold 1467709Sarnold /* 1477872Sarnold * infrom: 1487872Sarnold * reads a card, supposedly in hand, accepting unambigous brief 1497872Sarnold * input, returns the index of the card found... 1507709Sarnold */ 1517872Sarnold infrom(hand, n, prompt) 1527872Sarnold CARD hand[]; 1537872Sarnold int n; 1547872Sarnold char *prompt; 1557709Sarnold { 1567872Sarnold register int i, j; 1577872Sarnold CARD crd; 1587709Sarnold 1597872Sarnold if (n < 1) { 1607872Sarnold printf("\nINFROM: %d = n < 1!!\n", n); 1617872Sarnold exit(74); 1627872Sarnold } 1637872Sarnold for (;;) { 1647947Sarnold msg(prompt); 1657872Sarnold if (incard(&crd)) { /* if card is full card */ 1667872Sarnold if (!isone(crd, hand, n)) 1677872Sarnold msg("That's not in your hand"); 1687872Sarnold else { 1697872Sarnold for (i = 0; i < n; i++) 1707872Sarnold if (hand[i].rank == crd.rank && 1717872Sarnold hand[i].suit == crd.suit) 1727872Sarnold break; 1737872Sarnold if (i >= n) { 1747872Sarnold printf("\nINFROM: isone or something messed up\n"); 1757872Sarnold exit(77); 1767872Sarnold } 1777872Sarnold return i; 1787872Sarnold } 1797872Sarnold } 1807872Sarnold else /* if not full card... */ 1817872Sarnold if (crd.rank != EMPTY) { 1827872Sarnold for (i = 0; i < n; i++) 1837872Sarnold if (hand[i].rank == crd.rank) 1847872Sarnold break; 1857872Sarnold if (i >= n) 1867872Sarnold msg("No such rank in your hand"); 1877872Sarnold else { 1887872Sarnold for (j = i + 1; j < n; j++) 1897872Sarnold if (hand[j].rank == crd.rank) 1907872Sarnold break; 1917872Sarnold if (j < n) 1927872Sarnold msg("Ambiguous rank"); 1937872Sarnold else 1947872Sarnold return i; 1957872Sarnold } 1967872Sarnold } 1977872Sarnold else 1987872Sarnold msg("Sorry, I missed that"); 1997872Sarnold } 2007872Sarnold /* NOTREACHED */ 2017709Sarnold } 2027709Sarnold 2037709Sarnold 2047709Sarnold 2057709Sarnold /* 2067872Sarnold * incard: 2077872Sarnold * Inputs a card in any format. It reads a line ending with a CR 2087872Sarnold * and then parses it. 2097709Sarnold */ 2107872Sarnold incard(crd) 2117872Sarnold CARD *crd; 2127709Sarnold { 2137872Sarnold char *getline(); 2147872Sarnold register int i; 2157872Sarnold int rnk, sut; 2167872Sarnold char *line, *p, *p1; 2177872Sarnold BOOLEAN retval; 2187709Sarnold 2197872Sarnold retval = FALSE; 2207872Sarnold rnk = sut = EMPTY; 2217872Sarnold if (!(line = getline())) 2227872Sarnold goto gotit; 2237872Sarnold p = p1 = line; 2247872Sarnold while( *p1 != ' ' && *p1 != NULL ) ++p1; 2257872Sarnold *p1++ = NULL; 2267872Sarnold if( *p == NULL ) goto gotit; 2277872Sarnold /* IMPORTANT: no real card has 2 char first name */ 2287872Sarnold if( strlen(p) == 2 ) { /* check for short form */ 2297872Sarnold rnk = EMPTY; 2307872Sarnold for( i = 0; i < RANKS; i++ ) { 2317872Sarnold if( *p == *rankchar[i] ) { 2327872Sarnold rnk = i; 2337872Sarnold break; 2347872Sarnold } 2357872Sarnold } 2367872Sarnold if( rnk == EMPTY ) goto gotit; /* it's nothing... */ 2377872Sarnold ++p; /* advance to next char */ 2387872Sarnold sut = EMPTY; 2397872Sarnold for( i = 0; i < SUITS; i++ ) { 2407872Sarnold if( *p == *suitchar[i] ) { 2417872Sarnold sut = i; 2427872Sarnold break; 2437872Sarnold } 2447872Sarnold } 2457872Sarnold if( sut != EMPTY ) retval = TRUE; 2467872Sarnold goto gotit; 2477872Sarnold } 2487872Sarnold rnk = EMPTY; 2497872Sarnold for( i = 0; i < RANKS; i++ ) { 2507872Sarnold if( !strcmp( p, rankname[i] ) || !strcmp( p, rankchar[i] ) ) { 2517872Sarnold rnk = i; 2527872Sarnold break; 2537872Sarnold } 2547872Sarnold } 2557872Sarnold if( rnk == EMPTY ) goto gotit; 2567872Sarnold p = p1; 2577872Sarnold while( *p1 != ' ' && *p1 != NULL ) ++p1; 2587872Sarnold *p1++ = NULL; 2597872Sarnold if( *p == NULL ) goto gotit; 2607872Sarnold if( !strcmp( "OF", p ) ) { 2617872Sarnold p = p1; 2627872Sarnold while( *p1 != ' ' && *p1 != NULL ) ++p1; 2637872Sarnold *p1++ = NULL; 2647872Sarnold if( *p == NULL ) goto gotit; 2657872Sarnold } 2667872Sarnold sut = EMPTY; 2677872Sarnold for( i = 0; i < SUITS; i++ ) { 2687872Sarnold if( !strcmp( p, suitname[i] ) || !strcmp( p, suitchar[i] ) ) { 2697872Sarnold sut = i; 2707872Sarnold break; 2717872Sarnold } 2727872Sarnold } 2737872Sarnold if( sut != EMPTY ) retval = TRUE; 2747709Sarnold gotit: 2757872Sarnold (*crd).rank = rnk; 2767872Sarnold (*crd).suit = sut; 2777872Sarnold return( retval ); 2787709Sarnold } 2797709Sarnold 2807709Sarnold 2817709Sarnold 2827709Sarnold /* 2837872Sarnold * getuchar: 2847872Sarnold * Reads and converts to upper case 2857709Sarnold */ 2867709Sarnold getuchar() 2877709Sarnold { 2887872Sarnold register int c; 2897709Sarnold 2907872Sarnold c = readchar(); 2917872Sarnold if (islower(c)) 2927872Sarnold c = toupper(c); 29312163Sarnold waddch(Msgwin, c); 2947872Sarnold return c; 2957709Sarnold } 2967709Sarnold 2977709Sarnold /* 2987934Sarnold * number: 2997934Sarnold * Reads in a decimal number and makes sure it is between "lo" and 3007934Sarnold * "hi" inclusive. 3017709Sarnold */ 3027934Sarnold number(lo, hi, prompt) 3037934Sarnold int lo, hi; 3047934Sarnold char *prompt; 3057709Sarnold { 3067934Sarnold char *getline(); 3077934Sarnold register char *p; 3087934Sarnold register int sum; 3097709Sarnold 3107872Sarnold sum = 0; 3117934Sarnold for (;;) { 3127934Sarnold msg(prompt); 3137934Sarnold if(!(p = getline()) || *p == NULL) { 3147934Sarnold msg(quiet ? "Not a number" : "That doesn't look like a number"); 3157934Sarnold continue; 3167934Sarnold } 3177872Sarnold sum = 0; 3187934Sarnold 3197934Sarnold if (!isdigit(*p)) 3207872Sarnold sum = lo - 1; 3217934Sarnold else 3227934Sarnold while (isdigit(*p)) { 3237934Sarnold sum = 10 * sum + (*p - '0'); 3247872Sarnold ++p; 3257934Sarnold } 3267934Sarnold 3277934Sarnold if (*p != ' ' && *p != '\t' && *p != NULL) 3287934Sarnold sum = lo - 1; 3297934Sarnold if (sum >= lo && sum <= hi) 3307934Sarnold return sum; 3317934Sarnold if (sum == lo - 1) 3327934Sarnold msg("that doesn't look like a number, try again --> "); 3337934Sarnold else 3347934Sarnold msg("%d is not between %d and %d inclusive, try again --> ", 3357934Sarnold sum, lo, hi); 3367934Sarnold } 3377709Sarnold } 3387709Sarnold 3397872Sarnold /* 3407872Sarnold * msg: 3417872Sarnold * Display a message at the top of the screen. 3427872Sarnold */ 34312157Sarnold char Msgbuf[BUFSIZ] = { '\0' }; 3447709Sarnold 3457872Sarnold int Mpos = 0; 3467709Sarnold 3477872Sarnold static int Newpos = 0; 3487872Sarnold 3497872Sarnold /* VARARGS1 */ 3507872Sarnold msg(fmt, args) 3517872Sarnold char *fmt; 3527872Sarnold int args; 3537872Sarnold { 3547872Sarnold doadd(fmt, &args); 3557872Sarnold endmsg(); 3567872Sarnold } 3577872Sarnold 3587709Sarnold /* 3597872Sarnold * addmsg: 3607872Sarnold * Add things to the current message 3617709Sarnold */ 3627872Sarnold /* VARARGS1 */ 3637872Sarnold addmsg(fmt, args) 3647872Sarnold char *fmt; 3657872Sarnold int args; 3667872Sarnold { 3677872Sarnold doadd(fmt, &args); 3687872Sarnold } 3697709Sarnold 3707872Sarnold /* 3717872Sarnold * endmsg: 37212163Sarnold * Display a new msg. 3737872Sarnold */ 37412316Sarnold 37512316Sarnold int Lineno = 0; 37612316Sarnold 3777872Sarnold endmsg() 3787709Sarnold { 37912163Sarnold register int len; 38012163Sarnold register char *mp, *omp; 38112316Sarnold static int lastline = 0; 38212163Sarnold 3837872Sarnold /* 38412316Sarnold * All messages should start with uppercase 3857872Sarnold */ 38612316Sarnold mvaddch(lastline + Y_MSG_START, SCORE_X, ' '); 3877872Sarnold if (islower(Msgbuf[0]) && Msgbuf[1] != ')') 3887872Sarnold Msgbuf[0] = toupper(Msgbuf[0]); 38912163Sarnold mp = Msgbuf; 39012163Sarnold len = strlen(mp); 39112330Sarnold if (len / MSG_X + Lineno >= MSG_Y) { 39212330Sarnold while (Lineno < MSG_Y) { 39312330Sarnold wmove(Msgwin, Lineno++, 0); 39412330Sarnold wclrtoeol(Msgwin); 39512330Sarnold } 39612316Sarnold Lineno = 0; 39712330Sarnold } 39812316Sarnold mvaddch(Lineno + Y_MSG_START, SCORE_X, '*'); 39912316Sarnold lastline = Lineno; 40012163Sarnold do { 40112316Sarnold mvwaddstr(Msgwin, Lineno, 0, mp); 40212163Sarnold if ((len = strlen(mp)) > MSG_X) { 40312163Sarnold omp = mp; 40412163Sarnold for (mp = &mp[MSG_X-1]; *mp != ' '; mp--) 40512163Sarnold continue; 40612163Sarnold while (*mp == ' ') 40712163Sarnold mp--; 40812163Sarnold mp++; 40912316Sarnold wmove(Msgwin, Lineno, mp - omp); 41012163Sarnold wclrtoeol(Msgwin); 41112163Sarnold } 41212316Sarnold if (++Lineno >= MSG_Y) 41312316Sarnold Lineno = 0; 41412163Sarnold } while (len > MSG_X); 41512163Sarnold wclrtoeol(Msgwin); 41612330Sarnold Mpos = len; 4177872Sarnold Newpos = 0; 41812163Sarnold wrefresh(Msgwin); 4197872Sarnold refresh(); 42012163Sarnold wrefresh(Msgwin); 4217872Sarnold } 4227709Sarnold 4237872Sarnold /* 4247872Sarnold * doadd: 4257872Sarnold * Perform an add onto the message buffer 4267872Sarnold */ 4277872Sarnold doadd(fmt, args) 4287872Sarnold char *fmt; 4297872Sarnold int *args; 4307872Sarnold { 4317872Sarnold static FILE junk; 4327872Sarnold 4337872Sarnold /* 4347872Sarnold * Do the printf into Msgbuf 4357872Sarnold */ 4367872Sarnold junk._flag = _IOWRT + _IOSTRG; 4377872Sarnold junk._ptr = &Msgbuf[Newpos]; 4387872Sarnold junk._cnt = 32767; 4397872Sarnold _doprnt(fmt, args, &junk); 4407872Sarnold putc('\0', &junk); 4417872Sarnold Newpos = strlen(Msgbuf); 4427709Sarnold } 4437709Sarnold 4447872Sarnold /* 44512316Sarnold * do_wait: 44612316Sarnold * Wait for the user to type ' ' before doing anything else 44712316Sarnold */ 44812316Sarnold do_wait() 44912316Sarnold { 45012316Sarnold register int line; 45112316Sarnold static char prompt[] = { '-', '-', 'M', 'o', 'r', 'e', '-', '-', '\0' }; 45212316Sarnold 45312316Sarnold if (Mpos + sizeof prompt < MSG_X) 45412316Sarnold wmove(Msgwin, Lineno > 0 ? Lineno - 1 : MSG_Y - 1, Mpos); 45512316Sarnold else { 45612316Sarnold mvwaddch(Msgwin, Lineno, 0, ' '); 45712316Sarnold wclrtoeol(Msgwin); 45812316Sarnold if (++Lineno >= MSG_Y) 45912316Sarnold Lineno = 0; 46012316Sarnold } 46112316Sarnold waddstr(Msgwin, prompt); 46212316Sarnold wrefresh(Msgwin); 46312316Sarnold wait_for(' '); 46412316Sarnold } 46512316Sarnold 46612316Sarnold /* 4677872Sarnold * wait_for 4687872Sarnold * Sit around until the guy types the right key 4697872Sarnold */ 4707872Sarnold wait_for(ch) 4717872Sarnold register char ch; 4727872Sarnold { 4737872Sarnold register char c; 4747709Sarnold 4757872Sarnold if (ch == '\n') 4767872Sarnold while ((c = readchar()) != '\n') 4777872Sarnold continue; 4787872Sarnold else 4797872Sarnold while (readchar() != ch) 4807872Sarnold continue; 4817872Sarnold } 4827709Sarnold 4837872Sarnold /* 4847872Sarnold * readchar: 4857872Sarnold * Reads and returns a character, checking for gross input errors 4867872Sarnold */ 4877872Sarnold readchar() 4887872Sarnold { 4897872Sarnold register int cnt, y, x; 4907872Sarnold auto char c; 4917709Sarnold 4927872Sarnold over: 4937872Sarnold cnt = 0; 4947872Sarnold while (read(0, &c, 1) <= 0) 49541186Sbostic if (cnt++ > 100) { /* if we are getting infinite EOFs */ 49641186Sbostic bye(); /* quit the game */ 49741186Sbostic exit(1); 49841186Sbostic } 4997872Sarnold if (c == CTRL(L)) { 5007872Sarnold wrefresh(curscr); 5017872Sarnold goto over; 5027872Sarnold } 5037872Sarnold if (c == '\r') 5047872Sarnold return '\n'; 5057872Sarnold else 5067872Sarnold return c; 5077872Sarnold } 5087872Sarnold 5097872Sarnold /* 5107872Sarnold * getline: 5117872Sarnold * Reads the next line up to '\n' or EOF. Multiple spaces are 5127872Sarnold * compressed to one space; a space is inserted before a ',' 5137872Sarnold */ 5147872Sarnold char * 5157872Sarnold getline() 5167872Sarnold { 5177872Sarnold register char *sp; 5187872Sarnold register int c, oy, ox; 51912163Sarnold register WINDOW *oscr; 5207872Sarnold 52112163Sarnold oscr = stdscr; 52212163Sarnold stdscr = Msgwin; 5237872Sarnold getyx(stdscr, oy, ox); 5247872Sarnold refresh(); 5257872Sarnold /* 5267872Sarnold * loop reading in the string, and put it in a temporary buffer 5277872Sarnold */ 5287872Sarnold for (sp = linebuf; (c = readchar()) != '\n'; clrtoeol(), refresh()) { 5297872Sarnold if (c == -1) 5307872Sarnold continue; 5317872Sarnold else if (c == erasechar()) { /* process erase character */ 5327872Sarnold if (sp > linebuf) { 5337872Sarnold register int i; 5347872Sarnold 5357872Sarnold sp--; 5367872Sarnold for (i = strlen(unctrl(*sp)); i; i--) 5377872Sarnold addch('\b'); 5387872Sarnold } 5397872Sarnold continue; 5407872Sarnold } 5417872Sarnold else if (c == killchar()) { /* process kill character */ 5427872Sarnold sp = linebuf; 5437872Sarnold move(oy, ox); 5447872Sarnold continue; 5457872Sarnold } 5467872Sarnold else if (sp == linebuf && c == ' ') 5477872Sarnold continue; 5487872Sarnold if (sp >= &linebuf[LINESIZE-1] || !(isprint(c) || c == ' ')) 5497872Sarnold putchar(CTRL(G)); 5507872Sarnold else { 5517872Sarnold if (islower(c)) 5527872Sarnold c = toupper(c); 5537872Sarnold *sp++ = c; 5547872Sarnold addstr(unctrl(c)); 5557872Sarnold Mpos++; 5567872Sarnold } 5577872Sarnold } 5587872Sarnold *sp = '\0'; 55912163Sarnold stdscr = oscr; 5607872Sarnold return linebuf; 5617872Sarnold } 56214910Sarnold 56341186Sbostic rint() 56441186Sbostic { 56541186Sbostic bye(); 56641186Sbostic exit(1); 56741186Sbostic } 56841186Sbostic 56914910Sarnold /* 57014910Sarnold * bye: 57114910Sarnold * Leave the program, cleaning things up as we go. 57214910Sarnold */ 57314910Sarnold bye() 57414910Sarnold { 57514910Sarnold signal(SIGINT, SIG_IGN); 57614910Sarnold mvcur(0, COLS - 1, LINES - 1, 0); 57714910Sarnold fflush(stdout); 57814910Sarnold endwin(); 57914910Sarnold putchar('\n'); 58014910Sarnold } 581