17872Sarnold # include <curses.h> 27872Sarnold # include <ctype.h> 37872Sarnold # include <unctrl.h> 47872Sarnold # include "deck.h" 57872Sarnold # include "cribbage.h" 612163Sarnold # include "cribcur.h" 77709Sarnold 87872Sarnold # define LINESIZE 128 97709Sarnold 1012163Sarnold # ifdef CTRL 1112163Sarnold # undef CTRL 1212163Sarnold # endif 137872Sarnold # define CTRL(X) ('X' - 'A' + 1) 147709Sarnold 157872Sarnold # ifndef attron 167872Sarnold # define erasechar() _tty.sg_erase 177872Sarnold # define killchar() _tty.sg_kill 187872Sarnold # endif attron 197872Sarnold 207709Sarnold char linebuf[ LINESIZE ]; 217709Sarnold 227709Sarnold char *rankname[ RANKS ] = { "ACE", "TWO", "THREE", "FOUR", 237872Sarnold "FIVE", "SIX", "SEVEN", "EIGHT", 247872Sarnold "NINE", "TEN", "JACK", "QUEEN", 257872Sarnold "KING" }; 267709Sarnold 277709Sarnold char *rankchar[ RANKS ] = { "A", "2", "3", "4", "5", "6", "7", 287872Sarnold "8", "9", "T", "J", "Q", "K" }; 297709Sarnold 307709Sarnold char *suitname[ SUITS ] = { "SPADES", "HEARTS", "DIAMONDS", 317872Sarnold "CLUBS" }; 327709Sarnold 337709Sarnold char *suitchar[ SUITS ] = { "S", "H", "D", "C" }; 347709Sarnold 357709Sarnold 367709Sarnold 377709Sarnold /* 387872Sarnold * msgcard: 397872Sarnold * Call msgcrd in one of two forms 407709Sarnold */ 417872Sarnold msgcard(c, brief) 427872Sarnold CARD c; 437872Sarnold BOOLEAN brief; 447709Sarnold { 457872Sarnold if (brief) 467872Sarnold return msgcrd(c, TRUE, (char *) NULL, TRUE); 477872Sarnold else 487872Sarnold return msgcrd(c, FALSE, " of ", FALSE); 497709Sarnold } 507709Sarnold 517709Sarnold 527709Sarnold 537709Sarnold /* 547872Sarnold * msgcrd: 557872Sarnold * Print the value of a card in ascii 567709Sarnold */ 577872Sarnold msgcrd(c, brfrank, mid, brfsuit) 587872Sarnold CARD c; 597872Sarnold char *mid; 607872Sarnold BOOLEAN brfrank, brfsuit; 617872Sarnold { 627872Sarnold if (c.rank == EMPTY || c.suit == EMPTY) 637872Sarnold return FALSE; 647872Sarnold if (brfrank) 657872Sarnold addmsg("%1.1s", rankchar[c.rank]); 667872Sarnold else 677872Sarnold addmsg(rankname[c.rank]); 687872Sarnold if (mid != NULL) 697872Sarnold addmsg(mid); 707872Sarnold if (brfsuit) 717872Sarnold addmsg("%1.1s", suitchar[c.suit]); 727872Sarnold else 737872Sarnold addmsg(suitname[c.suit]); 747872Sarnold return TRUE; 757872Sarnold } 767709Sarnold 777872Sarnold /* 787872Sarnold * printcard: 797872Sarnold * Print out a card. 807872Sarnold */ 818073Sarnold printcard(win, cardno, c, blank) 827872Sarnold WINDOW *win; 837872Sarnold int cardno; 847872Sarnold CARD c; 858073Sarnold BOOLEAN blank; 867872Sarnold { 878073Sarnold prcard(win, cardno * 2, cardno, c, blank); 887872Sarnold } 897709Sarnold 907872Sarnold /* 917872Sarnold * prcard: 927872Sarnold * Print out a card on the window at the specified location 937872Sarnold */ 947946Sarnold prcard(win, y, x, c, blank) 957872Sarnold WINDOW *win; 967872Sarnold int y, x; 977872Sarnold CARD c; 987946Sarnold BOOLEAN blank; 997709Sarnold { 1007872Sarnold if (c.rank == EMPTY) 1017872Sarnold return; 1027872Sarnold mvwaddstr(win, y + 0, x, "+-----+"); 1037872Sarnold mvwaddstr(win, y + 1, x, "| |"); 1047872Sarnold mvwaddstr(win, y + 2, x, "| |"); 1057872Sarnold mvwaddstr(win, y + 3, x, "| |"); 1067872Sarnold mvwaddstr(win, y + 4, x, "+-----+"); 1077946Sarnold if (!blank) { 1087946Sarnold mvwaddch(win, y + 1, x + 1, rankchar[c.rank][0]); 1097946Sarnold waddch(win, suitchar[c.suit][0]); 1107946Sarnold mvwaddch(win, y + 3, x + 4, rankchar[c.rank][0]); 1117946Sarnold waddch(win, suitchar[c.suit][0]); 1127946Sarnold } 1137709Sarnold } 1147709Sarnold 1157709Sarnold /* 1167872Sarnold * prhand: 1177872Sarnold * Print a hand of n cards 1187709Sarnold */ 1198073Sarnold prhand(h, n, win, blank) 1207872Sarnold CARD h[]; 1217872Sarnold int n; 1227872Sarnold WINDOW *win; 1238073Sarnold BOOLEAN blank; 1247709Sarnold { 1257872Sarnold register int i; 1267709Sarnold 1277872Sarnold werase(win); 1287872Sarnold for (i = 0; i < n; i++) 1298073Sarnold printcard(win, i, *h++, blank); 1307872Sarnold wrefresh(win); 1317709Sarnold } 1327709Sarnold 1337709Sarnold 1347709Sarnold 1357709Sarnold /* 1367872Sarnold * infrom: 1377872Sarnold * reads a card, supposedly in hand, accepting unambigous brief 1387872Sarnold * input, returns the index of the card found... 1397709Sarnold */ 1407872Sarnold infrom(hand, n, prompt) 1417872Sarnold CARD hand[]; 1427872Sarnold int n; 1437872Sarnold char *prompt; 1447709Sarnold { 1457872Sarnold register int i, j; 1467872Sarnold CARD crd; 1477709Sarnold 1487872Sarnold if (n < 1) { 1497872Sarnold printf("\nINFROM: %d = n < 1!!\n", n); 1507872Sarnold exit(74); 1517872Sarnold } 1527872Sarnold for (;;) { 1537947Sarnold msg(prompt); 1547872Sarnold if (incard(&crd)) { /* if card is full card */ 1557872Sarnold if (!isone(crd, hand, n)) 1567872Sarnold msg("That's not in your hand"); 1577872Sarnold else { 1587872Sarnold for (i = 0; i < n; i++) 1597872Sarnold if (hand[i].rank == crd.rank && 1607872Sarnold hand[i].suit == crd.suit) 1617872Sarnold break; 1627872Sarnold if (i >= n) { 1637872Sarnold printf("\nINFROM: isone or something messed up\n"); 1647872Sarnold exit(77); 1657872Sarnold } 1667872Sarnold return i; 1677872Sarnold } 1687872Sarnold } 1697872Sarnold else /* if not full card... */ 1707872Sarnold if (crd.rank != EMPTY) { 1717872Sarnold for (i = 0; i < n; i++) 1727872Sarnold if (hand[i].rank == crd.rank) 1737872Sarnold break; 1747872Sarnold if (i >= n) 1757872Sarnold msg("No such rank in your hand"); 1767872Sarnold else { 1777872Sarnold for (j = i + 1; j < n; j++) 1787872Sarnold if (hand[j].rank == crd.rank) 1797872Sarnold break; 1807872Sarnold if (j < n) 1817872Sarnold msg("Ambiguous rank"); 1827872Sarnold else 1837872Sarnold return i; 1847872Sarnold } 1857872Sarnold } 1867872Sarnold else 1877872Sarnold msg("Sorry, I missed that"); 1887872Sarnold } 1897872Sarnold /* NOTREACHED */ 1907709Sarnold } 1917709Sarnold 1927709Sarnold 1937709Sarnold 1947709Sarnold /* 1957872Sarnold * incard: 1967872Sarnold * Inputs a card in any format. It reads a line ending with a CR 1977872Sarnold * and then parses it. 1987709Sarnold */ 1997872Sarnold incard(crd) 2007872Sarnold CARD *crd; 2017709Sarnold { 2027872Sarnold char *getline(); 2037872Sarnold register int i; 2047872Sarnold int rnk, sut; 2057872Sarnold char *line, *p, *p1; 2067872Sarnold BOOLEAN retval; 2077709Sarnold 2087872Sarnold retval = FALSE; 2097872Sarnold rnk = sut = EMPTY; 2107872Sarnold if (!(line = getline())) 2117872Sarnold goto gotit; 2127872Sarnold p = p1 = line; 2137872Sarnold while( *p1 != ' ' && *p1 != NULL ) ++p1; 2147872Sarnold *p1++ = NULL; 2157872Sarnold if( *p == NULL ) goto gotit; 2167872Sarnold /* IMPORTANT: no real card has 2 char first name */ 2177872Sarnold if( strlen(p) == 2 ) { /* check for short form */ 2187872Sarnold rnk = EMPTY; 2197872Sarnold for( i = 0; i < RANKS; i++ ) { 2207872Sarnold if( *p == *rankchar[i] ) { 2217872Sarnold rnk = i; 2227872Sarnold break; 2237872Sarnold } 2247872Sarnold } 2257872Sarnold if( rnk == EMPTY ) goto gotit; /* it's nothing... */ 2267872Sarnold ++p; /* advance to next char */ 2277872Sarnold sut = EMPTY; 2287872Sarnold for( i = 0; i < SUITS; i++ ) { 2297872Sarnold if( *p == *suitchar[i] ) { 2307872Sarnold sut = i; 2317872Sarnold break; 2327872Sarnold } 2337872Sarnold } 2347872Sarnold if( sut != EMPTY ) retval = TRUE; 2357872Sarnold goto gotit; 2367872Sarnold } 2377872Sarnold rnk = EMPTY; 2387872Sarnold for( i = 0; i < RANKS; i++ ) { 2397872Sarnold if( !strcmp( p, rankname[i] ) || !strcmp( p, rankchar[i] ) ) { 2407872Sarnold rnk = i; 2417872Sarnold break; 2427872Sarnold } 2437872Sarnold } 2447872Sarnold if( rnk == EMPTY ) goto gotit; 2457872Sarnold p = p1; 2467872Sarnold while( *p1 != ' ' && *p1 != NULL ) ++p1; 2477872Sarnold *p1++ = NULL; 2487872Sarnold if( *p == NULL ) goto gotit; 2497872Sarnold if( !strcmp( "OF", p ) ) { 2507872Sarnold p = p1; 2517872Sarnold while( *p1 != ' ' && *p1 != NULL ) ++p1; 2527872Sarnold *p1++ = NULL; 2537872Sarnold if( *p == NULL ) goto gotit; 2547872Sarnold } 2557872Sarnold sut = EMPTY; 2567872Sarnold for( i = 0; i < SUITS; i++ ) { 2577872Sarnold if( !strcmp( p, suitname[i] ) || !strcmp( p, suitchar[i] ) ) { 2587872Sarnold sut = i; 2597872Sarnold break; 2607872Sarnold } 2617872Sarnold } 2627872Sarnold if( sut != EMPTY ) retval = TRUE; 2637709Sarnold gotit: 2647872Sarnold (*crd).rank = rnk; 2657872Sarnold (*crd).suit = sut; 2667872Sarnold return( retval ); 2677709Sarnold } 2687709Sarnold 2697709Sarnold 2707709Sarnold 2717709Sarnold /* 2727872Sarnold * getuchar: 2737872Sarnold * Reads and converts to upper case 2747709Sarnold */ 2757709Sarnold getuchar() 2767709Sarnold { 2777872Sarnold register int c; 2787709Sarnold 2797872Sarnold c = readchar(); 2807872Sarnold if (islower(c)) 2817872Sarnold c = toupper(c); 28212163Sarnold waddch(Msgwin, c); 2837872Sarnold return c; 2847709Sarnold } 2857709Sarnold 2867709Sarnold /* 2877934Sarnold * number: 2887934Sarnold * Reads in a decimal number and makes sure it is between "lo" and 2897934Sarnold * "hi" inclusive. 2907709Sarnold */ 2917934Sarnold number(lo, hi, prompt) 2927934Sarnold int lo, hi; 2937934Sarnold char *prompt; 2947709Sarnold { 2957934Sarnold char *getline(); 2967934Sarnold register char *p; 2977934Sarnold register int sum; 2987709Sarnold 2997872Sarnold sum = 0; 3007934Sarnold for (;;) { 3017934Sarnold msg(prompt); 3027934Sarnold if(!(p = getline()) || *p == NULL) { 3037934Sarnold msg(quiet ? "Not a number" : "That doesn't look like a number"); 3047934Sarnold continue; 3057934Sarnold } 3067872Sarnold sum = 0; 3077934Sarnold 3087934Sarnold if (!isdigit(*p)) 3097872Sarnold sum = lo - 1; 3107934Sarnold else 3117934Sarnold while (isdigit(*p)) { 3127934Sarnold sum = 10 * sum + (*p - '0'); 3137872Sarnold ++p; 3147934Sarnold } 3157934Sarnold 3167934Sarnold if (*p != ' ' && *p != '\t' && *p != NULL) 3177934Sarnold sum = lo - 1; 3187934Sarnold if (sum >= lo && sum <= hi) 3197934Sarnold return sum; 3207934Sarnold if (sum == lo - 1) 3217934Sarnold msg("that doesn't look like a number, try again --> "); 3227934Sarnold else 3237934Sarnold msg("%d is not between %d and %d inclusive, try again --> ", 3247934Sarnold sum, lo, hi); 3257934Sarnold } 3267709Sarnold } 3277709Sarnold 3287872Sarnold /* 3297872Sarnold * msg: 3307872Sarnold * Display a message at the top of the screen. 3317872Sarnold */ 33212157Sarnold char Msgbuf[BUFSIZ] = { '\0' }; 3337709Sarnold 3347872Sarnold int Mpos = 0; 3357709Sarnold 3367872Sarnold static int Newpos = 0; 3377872Sarnold 3387872Sarnold /* VARARGS1 */ 3397872Sarnold msg(fmt, args) 3407872Sarnold char *fmt; 3417872Sarnold int args; 3427872Sarnold { 3437872Sarnold doadd(fmt, &args); 3447872Sarnold endmsg(); 3457872Sarnold } 3467872Sarnold 3477709Sarnold /* 3487872Sarnold * addmsg: 3497872Sarnold * Add things to the current message 3507709Sarnold */ 3517872Sarnold /* VARARGS1 */ 3527872Sarnold addmsg(fmt, args) 3537872Sarnold char *fmt; 3547872Sarnold int args; 3557872Sarnold { 3567872Sarnold doadd(fmt, &args); 3577872Sarnold } 3587709Sarnold 3597872Sarnold /* 3607872Sarnold * endmsg: 36112163Sarnold * Display a new msg. 3627872Sarnold */ 363*12316Sarnold 364*12316Sarnold int Lineno = 0; 365*12316Sarnold 3667872Sarnold endmsg() 3677709Sarnold { 36812163Sarnold register int len; 36912163Sarnold register char *mp, *omp; 370*12316Sarnold static int lastline = 0; 37112163Sarnold 3727872Sarnold /* 373*12316Sarnold * All messages should start with uppercase 3747872Sarnold */ 375*12316Sarnold mvaddch(lastline + Y_MSG_START, SCORE_X, ' '); 3767872Sarnold if (islower(Msgbuf[0]) && Msgbuf[1] != ')') 3777872Sarnold Msgbuf[0] = toupper(Msgbuf[0]); 37812163Sarnold mp = Msgbuf; 37912163Sarnold len = strlen(mp); 380*12316Sarnold if (len / MSG_X + Lineno >= MSG_Y) 381*12316Sarnold Lineno = 0; 382*12316Sarnold mvaddch(Lineno + Y_MSG_START, SCORE_X, '*'); 383*12316Sarnold lastline = Lineno; 38412163Sarnold do { 385*12316Sarnold mvwaddstr(Msgwin, Lineno, 0, mp); 38612163Sarnold if ((len = strlen(mp)) > MSG_X) { 38712163Sarnold omp = mp; 38812163Sarnold for (mp = &mp[MSG_X-1]; *mp != ' '; mp--) 38912163Sarnold continue; 39012163Sarnold while (*mp == ' ') 39112163Sarnold mp--; 39212163Sarnold mp++; 393*12316Sarnold wmove(Msgwin, Lineno, mp - omp); 39412163Sarnold wclrtoeol(Msgwin); 39512163Sarnold } 396*12316Sarnold if (++Lineno >= MSG_Y) 397*12316Sarnold Lineno = 0; 39812163Sarnold } while (len > MSG_X); 39912163Sarnold wclrtoeol(Msgwin); 400*12316Sarnold Mpos = Newpos % MSG_X; 4017872Sarnold Newpos = 0; 40212163Sarnold wrefresh(Msgwin); 4037872Sarnold refresh(); 40412163Sarnold wrefresh(Msgwin); 4057872Sarnold } 4067709Sarnold 4077872Sarnold /* 4087872Sarnold * doadd: 4097872Sarnold * Perform an add onto the message buffer 4107872Sarnold */ 4117872Sarnold doadd(fmt, args) 4127872Sarnold char *fmt; 4137872Sarnold int *args; 4147872Sarnold { 4157872Sarnold static FILE junk; 4167872Sarnold 4177872Sarnold /* 4187872Sarnold * Do the printf into Msgbuf 4197872Sarnold */ 4207872Sarnold junk._flag = _IOWRT + _IOSTRG; 4217872Sarnold junk._ptr = &Msgbuf[Newpos]; 4227872Sarnold junk._cnt = 32767; 4237872Sarnold _doprnt(fmt, args, &junk); 4247872Sarnold putc('\0', &junk); 4257872Sarnold Newpos = strlen(Msgbuf); 4267709Sarnold } 4277709Sarnold 4287872Sarnold /* 429*12316Sarnold * do_wait: 430*12316Sarnold * Wait for the user to type ' ' before doing anything else 431*12316Sarnold */ 432*12316Sarnold do_wait() 433*12316Sarnold { 434*12316Sarnold register int line; 435*12316Sarnold static char prompt[] = { '-', '-', 'M', 'o', 'r', 'e', '-', '-', '\0' }; 436*12316Sarnold 437*12316Sarnold if (Mpos + sizeof prompt < MSG_X) 438*12316Sarnold wmove(Msgwin, Lineno > 0 ? Lineno - 1 : MSG_Y - 1, Mpos); 439*12316Sarnold else { 440*12316Sarnold mvwaddch(Msgwin, Lineno, 0, ' '); 441*12316Sarnold wclrtoeol(Msgwin); 442*12316Sarnold if (++Lineno >= MSG_Y) 443*12316Sarnold Lineno = 0; 444*12316Sarnold } 445*12316Sarnold waddstr(Msgwin, prompt); 446*12316Sarnold wrefresh(Msgwin); 447*12316Sarnold wait_for(' '); 448*12316Sarnold } 449*12316Sarnold 450*12316Sarnold /* 4517872Sarnold * wait_for 4527872Sarnold * Sit around until the guy types the right key 4537872Sarnold */ 4547872Sarnold wait_for(ch) 4557872Sarnold register char ch; 4567872Sarnold { 4577872Sarnold register char c; 4587709Sarnold 4597872Sarnold if (ch == '\n') 4607872Sarnold while ((c = readchar()) != '\n') 4617872Sarnold continue; 4627872Sarnold else 4637872Sarnold while (readchar() != ch) 4647872Sarnold continue; 4657872Sarnold } 4667709Sarnold 4677872Sarnold /* 4687872Sarnold * readchar: 4697872Sarnold * Reads and returns a character, checking for gross input errors 4707872Sarnold */ 4717872Sarnold readchar() 4727872Sarnold { 4737872Sarnold register int cnt, y, x; 4747872Sarnold auto char c; 4757709Sarnold 4767872Sarnold over: 4777872Sarnold cnt = 0; 4787872Sarnold while (read(0, &c, 1) <= 0) 4797872Sarnold if (cnt++ > 100) /* if we are getting infinite EOFs */ 4807872Sarnold bye(); /* quit the game */ 4817872Sarnold if (c == CTRL(L)) { 4827872Sarnold wrefresh(curscr); 4837872Sarnold goto over; 4847872Sarnold } 4857872Sarnold if (c == '\r') 4867872Sarnold return '\n'; 4877872Sarnold else 4887872Sarnold return c; 4897872Sarnold } 4907872Sarnold 4917872Sarnold /* 4927872Sarnold * getline: 4937872Sarnold * Reads the next line up to '\n' or EOF. Multiple spaces are 4947872Sarnold * compressed to one space; a space is inserted before a ',' 4957872Sarnold */ 4967872Sarnold char * 4977872Sarnold getline() 4987872Sarnold { 4997872Sarnold register char *sp; 5007872Sarnold register int c, oy, ox; 50112163Sarnold register WINDOW *oscr; 5027872Sarnold 50312163Sarnold oscr = stdscr; 50412163Sarnold stdscr = Msgwin; 5057872Sarnold getyx(stdscr, oy, ox); 5067872Sarnold refresh(); 5077872Sarnold /* 5087872Sarnold * loop reading in the string, and put it in a temporary buffer 5097872Sarnold */ 5107872Sarnold for (sp = linebuf; (c = readchar()) != '\n'; clrtoeol(), refresh()) { 5117872Sarnold if (c == -1) 5127872Sarnold continue; 5137872Sarnold else if (c == erasechar()) { /* process erase character */ 5147872Sarnold if (sp > linebuf) { 5157872Sarnold register int i; 5167872Sarnold 5177872Sarnold sp--; 5187872Sarnold for (i = strlen(unctrl(*sp)); i; i--) 5197872Sarnold addch('\b'); 5207872Sarnold } 5217872Sarnold continue; 5227872Sarnold } 5237872Sarnold else if (c == killchar()) { /* process kill character */ 5247872Sarnold sp = linebuf; 5257872Sarnold move(oy, ox); 5267872Sarnold continue; 5277872Sarnold } 5287872Sarnold else if (sp == linebuf && c == ' ') 5297872Sarnold continue; 5307872Sarnold if (sp >= &linebuf[LINESIZE-1] || !(isprint(c) || c == ' ')) 5317872Sarnold putchar(CTRL(G)); 5327872Sarnold else { 5337872Sarnold if (islower(c)) 5347872Sarnold c = toupper(c); 5357872Sarnold *sp++ = c; 5367872Sarnold addstr(unctrl(c)); 5377872Sarnold Mpos++; 5387872Sarnold } 5397872Sarnold } 5407872Sarnold *sp = '\0'; 54112163Sarnold stdscr = oscr; 5427872Sarnold return linebuf; 5437872Sarnold } 544