121505Smckusick /* 221505Smckusick * Copyright (c) 1980 Regents of the University of California. 321505Smckusick * All rights reserved. The Berkeley software License Agreement 421505Smckusick * specifies the terms and conditions for redistribution. 521505Smckusick */ 612572Sarnold 721505Smckusick #ifndef lint 8*32355Sbostic static char sccsid[] = "@(#)io.c 5.2 (Berkeley) 10/07/87"; 921505Smckusick #endif not lint 1021505Smckusick 117872Sarnold # include <curses.h> 127872Sarnold # include <ctype.h> 1314910Sarnold # include <signal.h> 147872Sarnold # include "deck.h" 157872Sarnold # include "cribbage.h" 1612163Sarnold # include "cribcur.h" 177709Sarnold 187872Sarnold # define LINESIZE 128 197709Sarnold 2012163Sarnold # ifdef CTRL 2112163Sarnold # undef CTRL 2212163Sarnold # endif 237872Sarnold # define CTRL(X) ('X' - 'A' + 1) 247709Sarnold 25*32355Sbostic # ifdef notdef /* defined in curses.h */ 267872Sarnold # define erasechar() _tty.sg_erase 277872Sarnold # define killchar() _tty.sg_kill 28*32355Sbostic # endif 297872Sarnold 307709Sarnold char linebuf[ LINESIZE ]; 317709Sarnold 327709Sarnold char *rankname[ RANKS ] = { "ACE", "TWO", "THREE", "FOUR", 337872Sarnold "FIVE", "SIX", "SEVEN", "EIGHT", 347872Sarnold "NINE", "TEN", "JACK", "QUEEN", 357872Sarnold "KING" }; 367709Sarnold 377709Sarnold char *rankchar[ RANKS ] = { "A", "2", "3", "4", "5", "6", "7", 387872Sarnold "8", "9", "T", "J", "Q", "K" }; 397709Sarnold 407709Sarnold char *suitname[ SUITS ] = { "SPADES", "HEARTS", "DIAMONDS", 417872Sarnold "CLUBS" }; 427709Sarnold 437709Sarnold char *suitchar[ SUITS ] = { "S", "H", "D", "C" }; 447709Sarnold 457709Sarnold 467709Sarnold 477709Sarnold /* 487872Sarnold * msgcard: 497872Sarnold * Call msgcrd in one of two forms 507709Sarnold */ 517872Sarnold msgcard(c, brief) 527872Sarnold CARD c; 537872Sarnold BOOLEAN brief; 547709Sarnold { 557872Sarnold if (brief) 567872Sarnold return msgcrd(c, TRUE, (char *) NULL, TRUE); 577872Sarnold else 587872Sarnold return msgcrd(c, FALSE, " of ", FALSE); 597709Sarnold } 607709Sarnold 617709Sarnold 627709Sarnold 637709Sarnold /* 647872Sarnold * msgcrd: 657872Sarnold * Print the value of a card in ascii 667709Sarnold */ 677872Sarnold msgcrd(c, brfrank, mid, brfsuit) 687872Sarnold CARD c; 697872Sarnold char *mid; 707872Sarnold BOOLEAN brfrank, brfsuit; 717872Sarnold { 727872Sarnold if (c.rank == EMPTY || c.suit == EMPTY) 737872Sarnold return FALSE; 747872Sarnold if (brfrank) 757872Sarnold addmsg("%1.1s", rankchar[c.rank]); 767872Sarnold else 777872Sarnold addmsg(rankname[c.rank]); 787872Sarnold if (mid != NULL) 797872Sarnold addmsg(mid); 807872Sarnold if (brfsuit) 817872Sarnold addmsg("%1.1s", suitchar[c.suit]); 827872Sarnold else 837872Sarnold addmsg(suitname[c.suit]); 847872Sarnold return TRUE; 857872Sarnold } 867709Sarnold 877872Sarnold /* 887872Sarnold * printcard: 897872Sarnold * Print out a card. 907872Sarnold */ 918073Sarnold printcard(win, cardno, c, blank) 927872Sarnold WINDOW *win; 937872Sarnold int cardno; 947872Sarnold CARD c; 958073Sarnold BOOLEAN blank; 967872Sarnold { 978073Sarnold prcard(win, cardno * 2, cardno, c, blank); 987872Sarnold } 997709Sarnold 1007872Sarnold /* 1017872Sarnold * prcard: 1027872Sarnold * Print out a card on the window at the specified location 1037872Sarnold */ 1047946Sarnold prcard(win, y, x, c, blank) 1057872Sarnold WINDOW *win; 1067872Sarnold int y, x; 1077872Sarnold CARD c; 1087946Sarnold BOOLEAN blank; 1097709Sarnold { 1107872Sarnold if (c.rank == EMPTY) 1117872Sarnold return; 1127872Sarnold mvwaddstr(win, y + 0, x, "+-----+"); 1137872Sarnold mvwaddstr(win, y + 1, x, "| |"); 1147872Sarnold mvwaddstr(win, y + 2, x, "| |"); 1157872Sarnold mvwaddstr(win, y + 3, x, "| |"); 1167872Sarnold mvwaddstr(win, y + 4, x, "+-----+"); 1177946Sarnold if (!blank) { 1187946Sarnold mvwaddch(win, y + 1, x + 1, rankchar[c.rank][0]); 1197946Sarnold waddch(win, suitchar[c.suit][0]); 1207946Sarnold mvwaddch(win, y + 3, x + 4, rankchar[c.rank][0]); 1217946Sarnold waddch(win, suitchar[c.suit][0]); 1227946Sarnold } 1237709Sarnold } 1247709Sarnold 1257709Sarnold /* 1267872Sarnold * prhand: 1277872Sarnold * Print a hand of n cards 1287709Sarnold */ 1298073Sarnold prhand(h, n, win, blank) 1307872Sarnold CARD h[]; 1317872Sarnold int n; 1327872Sarnold WINDOW *win; 1338073Sarnold BOOLEAN blank; 1347709Sarnold { 1357872Sarnold register int i; 1367709Sarnold 1377872Sarnold werase(win); 1387872Sarnold for (i = 0; i < n; i++) 1398073Sarnold printcard(win, i, *h++, blank); 1407872Sarnold wrefresh(win); 1417709Sarnold } 1427709Sarnold 1437709Sarnold 1447709Sarnold 1457709Sarnold /* 1467872Sarnold * infrom: 1477872Sarnold * reads a card, supposedly in hand, accepting unambigous brief 1487872Sarnold * input, returns the index of the card found... 1497709Sarnold */ 1507872Sarnold infrom(hand, n, prompt) 1517872Sarnold CARD hand[]; 1527872Sarnold int n; 1537872Sarnold char *prompt; 1547709Sarnold { 1557872Sarnold register int i, j; 1567872Sarnold CARD crd; 1577709Sarnold 1587872Sarnold if (n < 1) { 1597872Sarnold printf("\nINFROM: %d = n < 1!!\n", n); 1607872Sarnold exit(74); 1617872Sarnold } 1627872Sarnold for (;;) { 1637947Sarnold msg(prompt); 1647872Sarnold if (incard(&crd)) { /* if card is full card */ 1657872Sarnold if (!isone(crd, hand, n)) 1667872Sarnold msg("That's not in your hand"); 1677872Sarnold else { 1687872Sarnold for (i = 0; i < n; i++) 1697872Sarnold if (hand[i].rank == crd.rank && 1707872Sarnold hand[i].suit == crd.suit) 1717872Sarnold break; 1727872Sarnold if (i >= n) { 1737872Sarnold printf("\nINFROM: isone or something messed up\n"); 1747872Sarnold exit(77); 1757872Sarnold } 1767872Sarnold return i; 1777872Sarnold } 1787872Sarnold } 1797872Sarnold else /* if not full card... */ 1807872Sarnold if (crd.rank != EMPTY) { 1817872Sarnold for (i = 0; i < n; i++) 1827872Sarnold if (hand[i].rank == crd.rank) 1837872Sarnold break; 1847872Sarnold if (i >= n) 1857872Sarnold msg("No such rank in your hand"); 1867872Sarnold else { 1877872Sarnold for (j = i + 1; j < n; j++) 1887872Sarnold if (hand[j].rank == crd.rank) 1897872Sarnold break; 1907872Sarnold if (j < n) 1917872Sarnold msg("Ambiguous rank"); 1927872Sarnold else 1937872Sarnold return i; 1947872Sarnold } 1957872Sarnold } 1967872Sarnold else 1977872Sarnold msg("Sorry, I missed that"); 1987872Sarnold } 1997872Sarnold /* NOTREACHED */ 2007709Sarnold } 2017709Sarnold 2027709Sarnold 2037709Sarnold 2047709Sarnold /* 2057872Sarnold * incard: 2067872Sarnold * Inputs a card in any format. It reads a line ending with a CR 2077872Sarnold * and then parses it. 2087709Sarnold */ 2097872Sarnold incard(crd) 2107872Sarnold CARD *crd; 2117709Sarnold { 2127872Sarnold char *getline(); 2137872Sarnold register int i; 2147872Sarnold int rnk, sut; 2157872Sarnold char *line, *p, *p1; 2167872Sarnold BOOLEAN retval; 2177709Sarnold 2187872Sarnold retval = FALSE; 2197872Sarnold rnk = sut = EMPTY; 2207872Sarnold if (!(line = getline())) 2217872Sarnold goto gotit; 2227872Sarnold p = p1 = line; 2237872Sarnold while( *p1 != ' ' && *p1 != NULL ) ++p1; 2247872Sarnold *p1++ = NULL; 2257872Sarnold if( *p == NULL ) goto gotit; 2267872Sarnold /* IMPORTANT: no real card has 2 char first name */ 2277872Sarnold if( strlen(p) == 2 ) { /* check for short form */ 2287872Sarnold rnk = EMPTY; 2297872Sarnold for( i = 0; i < RANKS; i++ ) { 2307872Sarnold if( *p == *rankchar[i] ) { 2317872Sarnold rnk = i; 2327872Sarnold break; 2337872Sarnold } 2347872Sarnold } 2357872Sarnold if( rnk == EMPTY ) goto gotit; /* it's nothing... */ 2367872Sarnold ++p; /* advance to next char */ 2377872Sarnold sut = EMPTY; 2387872Sarnold for( i = 0; i < SUITS; i++ ) { 2397872Sarnold if( *p == *suitchar[i] ) { 2407872Sarnold sut = i; 2417872Sarnold break; 2427872Sarnold } 2437872Sarnold } 2447872Sarnold if( sut != EMPTY ) retval = TRUE; 2457872Sarnold goto gotit; 2467872Sarnold } 2477872Sarnold rnk = EMPTY; 2487872Sarnold for( i = 0; i < RANKS; i++ ) { 2497872Sarnold if( !strcmp( p, rankname[i] ) || !strcmp( p, rankchar[i] ) ) { 2507872Sarnold rnk = i; 2517872Sarnold break; 2527872Sarnold } 2537872Sarnold } 2547872Sarnold if( rnk == EMPTY ) goto gotit; 2557872Sarnold p = p1; 2567872Sarnold while( *p1 != ' ' && *p1 != NULL ) ++p1; 2577872Sarnold *p1++ = NULL; 2587872Sarnold if( *p == NULL ) goto gotit; 2597872Sarnold if( !strcmp( "OF", p ) ) { 2607872Sarnold p = p1; 2617872Sarnold while( *p1 != ' ' && *p1 != NULL ) ++p1; 2627872Sarnold *p1++ = NULL; 2637872Sarnold if( *p == NULL ) goto gotit; 2647872Sarnold } 2657872Sarnold sut = EMPTY; 2667872Sarnold for( i = 0; i < SUITS; i++ ) { 2677872Sarnold if( !strcmp( p, suitname[i] ) || !strcmp( p, suitchar[i] ) ) { 2687872Sarnold sut = i; 2697872Sarnold break; 2707872Sarnold } 2717872Sarnold } 2727872Sarnold if( sut != EMPTY ) retval = TRUE; 2737709Sarnold gotit: 2747872Sarnold (*crd).rank = rnk; 2757872Sarnold (*crd).suit = sut; 2767872Sarnold return( retval ); 2777709Sarnold } 2787709Sarnold 2797709Sarnold 2807709Sarnold 2817709Sarnold /* 2827872Sarnold * getuchar: 2837872Sarnold * Reads and converts to upper case 2847709Sarnold */ 2857709Sarnold getuchar() 2867709Sarnold { 2877872Sarnold register int c; 2887709Sarnold 2897872Sarnold c = readchar(); 2907872Sarnold if (islower(c)) 2917872Sarnold c = toupper(c); 29212163Sarnold waddch(Msgwin, c); 2937872Sarnold return c; 2947709Sarnold } 2957709Sarnold 2967709Sarnold /* 2977934Sarnold * number: 2987934Sarnold * Reads in a decimal number and makes sure it is between "lo" and 2997934Sarnold * "hi" inclusive. 3007709Sarnold */ 3017934Sarnold number(lo, hi, prompt) 3027934Sarnold int lo, hi; 3037934Sarnold char *prompt; 3047709Sarnold { 3057934Sarnold char *getline(); 3067934Sarnold register char *p; 3077934Sarnold register int sum; 3087709Sarnold 3097872Sarnold sum = 0; 3107934Sarnold for (;;) { 3117934Sarnold msg(prompt); 3127934Sarnold if(!(p = getline()) || *p == NULL) { 3137934Sarnold msg(quiet ? "Not a number" : "That doesn't look like a number"); 3147934Sarnold continue; 3157934Sarnold } 3167872Sarnold sum = 0; 3177934Sarnold 3187934Sarnold if (!isdigit(*p)) 3197872Sarnold sum = lo - 1; 3207934Sarnold else 3217934Sarnold while (isdigit(*p)) { 3227934Sarnold sum = 10 * sum + (*p - '0'); 3237872Sarnold ++p; 3247934Sarnold } 3257934Sarnold 3267934Sarnold if (*p != ' ' && *p != '\t' && *p != NULL) 3277934Sarnold sum = lo - 1; 3287934Sarnold if (sum >= lo && sum <= hi) 3297934Sarnold return sum; 3307934Sarnold if (sum == lo - 1) 3317934Sarnold msg("that doesn't look like a number, try again --> "); 3327934Sarnold else 3337934Sarnold msg("%d is not between %d and %d inclusive, try again --> ", 3347934Sarnold sum, lo, hi); 3357934Sarnold } 3367709Sarnold } 3377709Sarnold 3387872Sarnold /* 3397872Sarnold * msg: 3407872Sarnold * Display a message at the top of the screen. 3417872Sarnold */ 34212157Sarnold char Msgbuf[BUFSIZ] = { '\0' }; 3437709Sarnold 3447872Sarnold int Mpos = 0; 3457709Sarnold 3467872Sarnold static int Newpos = 0; 3477872Sarnold 3487872Sarnold /* VARARGS1 */ 3497872Sarnold msg(fmt, args) 3507872Sarnold char *fmt; 3517872Sarnold int args; 3527872Sarnold { 3537872Sarnold doadd(fmt, &args); 3547872Sarnold endmsg(); 3557872Sarnold } 3567872Sarnold 3577709Sarnold /* 3587872Sarnold * addmsg: 3597872Sarnold * Add things to the current message 3607709Sarnold */ 3617872Sarnold /* VARARGS1 */ 3627872Sarnold addmsg(fmt, args) 3637872Sarnold char *fmt; 3647872Sarnold int args; 3657872Sarnold { 3667872Sarnold doadd(fmt, &args); 3677872Sarnold } 3687709Sarnold 3697872Sarnold /* 3707872Sarnold * endmsg: 37112163Sarnold * Display a new msg. 3727872Sarnold */ 37312316Sarnold 37412316Sarnold int Lineno = 0; 37512316Sarnold 3767872Sarnold endmsg() 3777709Sarnold { 37812163Sarnold register int len; 37912163Sarnold register char *mp, *omp; 38012316Sarnold static int lastline = 0; 38112163Sarnold 3827872Sarnold /* 38312316Sarnold * All messages should start with uppercase 3847872Sarnold */ 38512316Sarnold mvaddch(lastline + Y_MSG_START, SCORE_X, ' '); 3867872Sarnold if (islower(Msgbuf[0]) && Msgbuf[1] != ')') 3877872Sarnold Msgbuf[0] = toupper(Msgbuf[0]); 38812163Sarnold mp = Msgbuf; 38912163Sarnold len = strlen(mp); 39012330Sarnold if (len / MSG_X + Lineno >= MSG_Y) { 39112330Sarnold while (Lineno < MSG_Y) { 39212330Sarnold wmove(Msgwin, Lineno++, 0); 39312330Sarnold wclrtoeol(Msgwin); 39412330Sarnold } 39512316Sarnold Lineno = 0; 39612330Sarnold } 39712316Sarnold mvaddch(Lineno + Y_MSG_START, SCORE_X, '*'); 39812316Sarnold lastline = Lineno; 39912163Sarnold do { 40012316Sarnold mvwaddstr(Msgwin, Lineno, 0, mp); 40112163Sarnold if ((len = strlen(mp)) > MSG_X) { 40212163Sarnold omp = mp; 40312163Sarnold for (mp = &mp[MSG_X-1]; *mp != ' '; mp--) 40412163Sarnold continue; 40512163Sarnold while (*mp == ' ') 40612163Sarnold mp--; 40712163Sarnold mp++; 40812316Sarnold wmove(Msgwin, Lineno, mp - omp); 40912163Sarnold wclrtoeol(Msgwin); 41012163Sarnold } 41112316Sarnold if (++Lineno >= MSG_Y) 41212316Sarnold Lineno = 0; 41312163Sarnold } while (len > MSG_X); 41412163Sarnold wclrtoeol(Msgwin); 41512330Sarnold Mpos = len; 4167872Sarnold Newpos = 0; 41712163Sarnold wrefresh(Msgwin); 4187872Sarnold refresh(); 41912163Sarnold wrefresh(Msgwin); 4207872Sarnold } 4217709Sarnold 4227872Sarnold /* 4237872Sarnold * doadd: 4247872Sarnold * Perform an add onto the message buffer 4257872Sarnold */ 4267872Sarnold doadd(fmt, args) 4277872Sarnold char *fmt; 4287872Sarnold int *args; 4297872Sarnold { 4307872Sarnold static FILE junk; 4317872Sarnold 4327872Sarnold /* 4337872Sarnold * Do the printf into Msgbuf 4347872Sarnold */ 4357872Sarnold junk._flag = _IOWRT + _IOSTRG; 4367872Sarnold junk._ptr = &Msgbuf[Newpos]; 4377872Sarnold junk._cnt = 32767; 4387872Sarnold _doprnt(fmt, args, &junk); 4397872Sarnold putc('\0', &junk); 4407872Sarnold Newpos = strlen(Msgbuf); 4417709Sarnold } 4427709Sarnold 4437872Sarnold /* 44412316Sarnold * do_wait: 44512316Sarnold * Wait for the user to type ' ' before doing anything else 44612316Sarnold */ 44712316Sarnold do_wait() 44812316Sarnold { 44912316Sarnold register int line; 45012316Sarnold static char prompt[] = { '-', '-', 'M', 'o', 'r', 'e', '-', '-', '\0' }; 45112316Sarnold 45212316Sarnold if (Mpos + sizeof prompt < MSG_X) 45312316Sarnold wmove(Msgwin, Lineno > 0 ? Lineno - 1 : MSG_Y - 1, Mpos); 45412316Sarnold else { 45512316Sarnold mvwaddch(Msgwin, Lineno, 0, ' '); 45612316Sarnold wclrtoeol(Msgwin); 45712316Sarnold if (++Lineno >= MSG_Y) 45812316Sarnold Lineno = 0; 45912316Sarnold } 46012316Sarnold waddstr(Msgwin, prompt); 46112316Sarnold wrefresh(Msgwin); 46212316Sarnold wait_for(' '); 46312316Sarnold } 46412316Sarnold 46512316Sarnold /* 4667872Sarnold * wait_for 4677872Sarnold * Sit around until the guy types the right key 4687872Sarnold */ 4697872Sarnold wait_for(ch) 4707872Sarnold register char ch; 4717872Sarnold { 4727872Sarnold register char c; 4737709Sarnold 4747872Sarnold if (ch == '\n') 4757872Sarnold while ((c = readchar()) != '\n') 4767872Sarnold continue; 4777872Sarnold else 4787872Sarnold while (readchar() != ch) 4797872Sarnold continue; 4807872Sarnold } 4817709Sarnold 4827872Sarnold /* 4837872Sarnold * readchar: 4847872Sarnold * Reads and returns a character, checking for gross input errors 4857872Sarnold */ 4867872Sarnold readchar() 4877872Sarnold { 4887872Sarnold register int cnt, y, x; 4897872Sarnold auto char c; 4907709Sarnold 4917872Sarnold over: 4927872Sarnold cnt = 0; 4937872Sarnold while (read(0, &c, 1) <= 0) 4947872Sarnold if (cnt++ > 100) /* if we are getting infinite EOFs */ 4957872Sarnold bye(); /* quit the game */ 4967872Sarnold if (c == CTRL(L)) { 4977872Sarnold wrefresh(curscr); 4987872Sarnold goto over; 4997872Sarnold } 5007872Sarnold if (c == '\r') 5017872Sarnold return '\n'; 5027872Sarnold else 5037872Sarnold return c; 5047872Sarnold } 5057872Sarnold 5067872Sarnold /* 5077872Sarnold * getline: 5087872Sarnold * Reads the next line up to '\n' or EOF. Multiple spaces are 5097872Sarnold * compressed to one space; a space is inserted before a ',' 5107872Sarnold */ 5117872Sarnold char * 5127872Sarnold getline() 5137872Sarnold { 5147872Sarnold register char *sp; 5157872Sarnold register int c, oy, ox; 51612163Sarnold register WINDOW *oscr; 5177872Sarnold 51812163Sarnold oscr = stdscr; 51912163Sarnold stdscr = Msgwin; 5207872Sarnold getyx(stdscr, oy, ox); 5217872Sarnold refresh(); 5227872Sarnold /* 5237872Sarnold * loop reading in the string, and put it in a temporary buffer 5247872Sarnold */ 5257872Sarnold for (sp = linebuf; (c = readchar()) != '\n'; clrtoeol(), refresh()) { 5267872Sarnold if (c == -1) 5277872Sarnold continue; 5287872Sarnold else if (c == erasechar()) { /* process erase character */ 5297872Sarnold if (sp > linebuf) { 5307872Sarnold register int i; 5317872Sarnold 5327872Sarnold sp--; 5337872Sarnold for (i = strlen(unctrl(*sp)); i; i--) 5347872Sarnold addch('\b'); 5357872Sarnold } 5367872Sarnold continue; 5377872Sarnold } 5387872Sarnold else if (c == killchar()) { /* process kill character */ 5397872Sarnold sp = linebuf; 5407872Sarnold move(oy, ox); 5417872Sarnold continue; 5427872Sarnold } 5437872Sarnold else if (sp == linebuf && c == ' ') 5447872Sarnold continue; 5457872Sarnold if (sp >= &linebuf[LINESIZE-1] || !(isprint(c) || c == ' ')) 5467872Sarnold putchar(CTRL(G)); 5477872Sarnold else { 5487872Sarnold if (islower(c)) 5497872Sarnold c = toupper(c); 5507872Sarnold *sp++ = c; 5517872Sarnold addstr(unctrl(c)); 5527872Sarnold Mpos++; 5537872Sarnold } 5547872Sarnold } 5557872Sarnold *sp = '\0'; 55612163Sarnold stdscr = oscr; 5577872Sarnold return linebuf; 5587872Sarnold } 55914910Sarnold 56014910Sarnold /* 56114910Sarnold * bye: 56214910Sarnold * Leave the program, cleaning things up as we go. 56314910Sarnold */ 56414910Sarnold bye() 56514910Sarnold { 56614910Sarnold signal(SIGINT, SIG_IGN); 56714910Sarnold mvcur(0, COLS - 1, LINES - 1, 0); 56814910Sarnold fflush(stdout); 56914910Sarnold endwin(); 57014910Sarnold putchar('\n'); 57114910Sarnold exit(1); 57214910Sarnold } 573