17872Sarnold # include <curses.h> 27872Sarnold # include <ctype.h> 37872Sarnold # include <unctrl.h> 47872Sarnold # include "deck.h" 57872Sarnold # include "cribbage.h" 67709Sarnold 77872Sarnold # define LINESIZE 128 87709Sarnold 97872Sarnold # define CTRL(X) ('X' - 'A' + 1) 107709Sarnold 117872Sarnold # ifndef attron 127872Sarnold # define erasechar() _tty.sg_erase 137872Sarnold # define killchar() _tty.sg_kill 147872Sarnold # endif attron 157872Sarnold 167709Sarnold char linebuf[ LINESIZE ]; 177709Sarnold 187709Sarnold char *rankname[ RANKS ] = { "ACE", "TWO", "THREE", "FOUR", 197872Sarnold "FIVE", "SIX", "SEVEN", "EIGHT", 207872Sarnold "NINE", "TEN", "JACK", "QUEEN", 217872Sarnold "KING" }; 227709Sarnold 237709Sarnold char *rankchar[ RANKS ] = { "A", "2", "3", "4", "5", "6", "7", 247872Sarnold "8", "9", "T", "J", "Q", "K" }; 257709Sarnold 267709Sarnold char *suitname[ SUITS ] = { "SPADES", "HEARTS", "DIAMONDS", 277872Sarnold "CLUBS" }; 287709Sarnold 297709Sarnold char *suitchar[ SUITS ] = { "S", "H", "D", "C" }; 307709Sarnold 317709Sarnold 327709Sarnold 337709Sarnold /* 347872Sarnold * msgcard: 357872Sarnold * Call msgcrd in one of two forms 367709Sarnold */ 377872Sarnold msgcard(c, brief) 387872Sarnold CARD c; 397872Sarnold BOOLEAN brief; 407709Sarnold { 417872Sarnold if (brief) 427872Sarnold return msgcrd(c, TRUE, (char *) NULL, TRUE); 437872Sarnold else 447872Sarnold return msgcrd(c, FALSE, " of ", FALSE); 457709Sarnold } 467709Sarnold 477709Sarnold 487709Sarnold 497709Sarnold /* 507872Sarnold * msgcrd: 517872Sarnold * Print the value of a card in ascii 527709Sarnold */ 537872Sarnold msgcrd(c, brfrank, mid, brfsuit) 547872Sarnold CARD c; 557872Sarnold char *mid; 567872Sarnold BOOLEAN brfrank, brfsuit; 577872Sarnold { 587872Sarnold if (c.rank == EMPTY || c.suit == EMPTY) 597872Sarnold return FALSE; 607872Sarnold if (brfrank) 617872Sarnold addmsg("%1.1s", rankchar[c.rank]); 627872Sarnold else 637872Sarnold addmsg(rankname[c.rank]); 647872Sarnold if (mid != NULL) 657872Sarnold addmsg(mid); 667872Sarnold if (brfsuit) 677872Sarnold addmsg("%1.1s", suitchar[c.suit]); 687872Sarnold else 697872Sarnold addmsg(suitname[c.suit]); 707872Sarnold return TRUE; 717872Sarnold } 727709Sarnold 737872Sarnold /* 747872Sarnold * printcard: 757872Sarnold * Print out a card. 767872Sarnold */ 77*8073Sarnold printcard(win, cardno, c, blank) 787872Sarnold WINDOW *win; 797872Sarnold int cardno; 807872Sarnold CARD c; 81*8073Sarnold BOOLEAN blank; 827872Sarnold { 83*8073Sarnold prcard(win, cardno * 2, cardno, c, blank); 847872Sarnold } 857709Sarnold 867872Sarnold /* 877872Sarnold * prcard: 887872Sarnold * Print out a card on the window at the specified location 897872Sarnold */ 907946Sarnold prcard(win, y, x, c, blank) 917872Sarnold WINDOW *win; 927872Sarnold int y, x; 937872Sarnold CARD c; 947946Sarnold BOOLEAN blank; 957709Sarnold { 967872Sarnold if (c.rank == EMPTY) 977872Sarnold return; 987872Sarnold mvwaddstr(win, y + 0, x, "+-----+"); 997872Sarnold mvwaddstr(win, y + 1, x, "| |"); 1007872Sarnold mvwaddstr(win, y + 2, x, "| |"); 1017872Sarnold mvwaddstr(win, y + 3, x, "| |"); 1027872Sarnold mvwaddstr(win, y + 4, x, "+-----+"); 1037946Sarnold if (!blank) { 1047946Sarnold mvwaddch(win, y + 1, x + 1, rankchar[c.rank][0]); 1057946Sarnold waddch(win, suitchar[c.suit][0]); 1067946Sarnold mvwaddch(win, y + 3, x + 4, rankchar[c.rank][0]); 1077946Sarnold waddch(win, suitchar[c.suit][0]); 1087946Sarnold } 1097709Sarnold } 1107709Sarnold 1117709Sarnold /* 1127872Sarnold * prhand: 1137872Sarnold * Print a hand of n cards 1147709Sarnold */ 115*8073Sarnold prhand(h, n, win, blank) 1167872Sarnold CARD h[]; 1177872Sarnold int n; 1187872Sarnold WINDOW *win; 119*8073Sarnold BOOLEAN blank; 1207709Sarnold { 1217872Sarnold register int i; 1227709Sarnold 1237872Sarnold werase(win); 1247872Sarnold for (i = 0; i < n; i++) 125*8073Sarnold printcard(win, i, *h++, blank); 1267872Sarnold wrefresh(win); 1277709Sarnold } 1287709Sarnold 1297709Sarnold 1307709Sarnold 1317709Sarnold /* 1327872Sarnold * infrom: 1337872Sarnold * reads a card, supposedly in hand, accepting unambigous brief 1347872Sarnold * input, returns the index of the card found... 1357709Sarnold */ 1367872Sarnold infrom(hand, n, prompt) 1377872Sarnold CARD hand[]; 1387872Sarnold int n; 1397872Sarnold char *prompt; 1407709Sarnold { 1417872Sarnold register int i, j; 1427872Sarnold CARD crd; 1437709Sarnold 1447872Sarnold if (n < 1) { 1457872Sarnold printf("\nINFROM: %d = n < 1!!\n", n); 1467872Sarnold exit(74); 1477872Sarnold } 1487872Sarnold for (;;) { 1497947Sarnold msg(prompt); 1507872Sarnold if (incard(&crd)) { /* if card is full card */ 1517872Sarnold if (!isone(crd, hand, n)) 1527872Sarnold msg("That's not in your hand"); 1537872Sarnold else { 1547872Sarnold for (i = 0; i < n; i++) 1557872Sarnold if (hand[i].rank == crd.rank && 1567872Sarnold hand[i].suit == crd.suit) 1577872Sarnold break; 1587872Sarnold if (i >= n) { 1597872Sarnold printf("\nINFROM: isone or something messed up\n"); 1607872Sarnold exit(77); 1617872Sarnold } 1627872Sarnold return i; 1637872Sarnold } 1647872Sarnold } 1657872Sarnold else /* if not full card... */ 1667872Sarnold if (crd.rank != EMPTY) { 1677872Sarnold for (i = 0; i < n; i++) 1687872Sarnold if (hand[i].rank == crd.rank) 1697872Sarnold break; 1707872Sarnold if (i >= n) 1717872Sarnold msg("No such rank in your hand"); 1727872Sarnold else { 1737872Sarnold for (j = i + 1; j < n; j++) 1747872Sarnold if (hand[j].rank == crd.rank) 1757872Sarnold break; 1767872Sarnold if (j < n) 1777872Sarnold msg("Ambiguous rank"); 1787872Sarnold else 1797872Sarnold return i; 1807872Sarnold } 1817872Sarnold } 1827872Sarnold else 1837872Sarnold msg("Sorry, I missed that"); 1847872Sarnold } 1857872Sarnold /* NOTREACHED */ 1867709Sarnold } 1877709Sarnold 1887709Sarnold 1897709Sarnold 1907709Sarnold /* 1917872Sarnold * incard: 1927872Sarnold * Inputs a card in any format. It reads a line ending with a CR 1937872Sarnold * and then parses it. 1947709Sarnold */ 1957872Sarnold incard(crd) 1967872Sarnold CARD *crd; 1977709Sarnold { 1987872Sarnold char *getline(); 1997872Sarnold register int i; 2007872Sarnold int rnk, sut; 2017872Sarnold char *line, *p, *p1; 2027872Sarnold BOOLEAN retval; 2037709Sarnold 2047872Sarnold retval = FALSE; 2057872Sarnold rnk = sut = EMPTY; 2067872Sarnold if (!(line = getline())) 2077872Sarnold goto gotit; 2087872Sarnold p = p1 = line; 2097872Sarnold while( *p1 != ' ' && *p1 != NULL ) ++p1; 2107872Sarnold *p1++ = NULL; 2117872Sarnold if( *p == NULL ) goto gotit; 2127872Sarnold /* IMPORTANT: no real card has 2 char first name */ 2137872Sarnold if( strlen(p) == 2 ) { /* check for short form */ 2147872Sarnold rnk = EMPTY; 2157872Sarnold for( i = 0; i < RANKS; i++ ) { 2167872Sarnold if( *p == *rankchar[i] ) { 2177872Sarnold rnk = i; 2187872Sarnold break; 2197872Sarnold } 2207872Sarnold } 2217872Sarnold if( rnk == EMPTY ) goto gotit; /* it's nothing... */ 2227872Sarnold ++p; /* advance to next char */ 2237872Sarnold sut = EMPTY; 2247872Sarnold for( i = 0; i < SUITS; i++ ) { 2257872Sarnold if( *p == *suitchar[i] ) { 2267872Sarnold sut = i; 2277872Sarnold break; 2287872Sarnold } 2297872Sarnold } 2307872Sarnold if( sut != EMPTY ) retval = TRUE; 2317872Sarnold goto gotit; 2327872Sarnold } 2337872Sarnold rnk = EMPTY; 2347872Sarnold for( i = 0; i < RANKS; i++ ) { 2357872Sarnold if( !strcmp( p, rankname[i] ) || !strcmp( p, rankchar[i] ) ) { 2367872Sarnold rnk = i; 2377872Sarnold break; 2387872Sarnold } 2397872Sarnold } 2407872Sarnold if( rnk == EMPTY ) goto gotit; 2417872Sarnold p = p1; 2427872Sarnold while( *p1 != ' ' && *p1 != NULL ) ++p1; 2437872Sarnold *p1++ = NULL; 2447872Sarnold if( *p == NULL ) goto gotit; 2457872Sarnold if( !strcmp( "OF", p ) ) { 2467872Sarnold p = p1; 2477872Sarnold while( *p1 != ' ' && *p1 != NULL ) ++p1; 2487872Sarnold *p1++ = NULL; 2497872Sarnold if( *p == NULL ) goto gotit; 2507872Sarnold } 2517872Sarnold sut = EMPTY; 2527872Sarnold for( i = 0; i < SUITS; i++ ) { 2537872Sarnold if( !strcmp( p, suitname[i] ) || !strcmp( p, suitchar[i] ) ) { 2547872Sarnold sut = i; 2557872Sarnold break; 2567872Sarnold } 2577872Sarnold } 2587872Sarnold if( sut != EMPTY ) retval = TRUE; 2597709Sarnold gotit: 2607872Sarnold (*crd).rank = rnk; 2617872Sarnold (*crd).suit = sut; 2627872Sarnold return( retval ); 2637709Sarnold } 2647709Sarnold 2657709Sarnold 2667709Sarnold 2677709Sarnold /* 2687872Sarnold * getuchar: 2697872Sarnold * Reads and converts to upper case 2707709Sarnold */ 2717709Sarnold getuchar() 2727709Sarnold { 2737872Sarnold register int c; 2747709Sarnold 2757872Sarnold c = readchar(); 2767872Sarnold if (islower(c)) 2777872Sarnold c = toupper(c); 2787872Sarnold addch(c); 2797872Sarnold return c; 2807709Sarnold } 2817709Sarnold 2827709Sarnold /* 2837934Sarnold * number: 2847934Sarnold * Reads in a decimal number and makes sure it is between "lo" and 2857934Sarnold * "hi" inclusive. 2867709Sarnold */ 2877934Sarnold number(lo, hi, prompt) 2887934Sarnold int lo, hi; 2897934Sarnold char *prompt; 2907709Sarnold { 2917934Sarnold char *getline(); 2927934Sarnold register char *p; 2937934Sarnold register int sum; 2947709Sarnold 2957872Sarnold sum = 0; 2967934Sarnold for (;;) { 2977934Sarnold msg(prompt); 2987934Sarnold if(!(p = getline()) || *p == NULL) { 2997934Sarnold msg(quiet ? "Not a number" : "That doesn't look like a number"); 3007934Sarnold continue; 3017934Sarnold } 3027872Sarnold sum = 0; 3037934Sarnold 3047934Sarnold if (!isdigit(*p)) 3057872Sarnold sum = lo - 1; 3067934Sarnold else 3077934Sarnold while (isdigit(*p)) { 3087934Sarnold sum = 10 * sum + (*p - '0'); 3097872Sarnold ++p; 3107934Sarnold } 3117934Sarnold 3127934Sarnold if (*p != ' ' && *p != '\t' && *p != NULL) 3137934Sarnold sum = lo - 1; 3147934Sarnold if (sum >= lo && sum <= hi) 3157934Sarnold return sum; 3167934Sarnold if (sum == lo - 1) 3177934Sarnold msg("that doesn't look like a number, try again --> "); 3187934Sarnold else 3197934Sarnold msg("%d is not between %d and %d inclusive, try again --> ", 3207934Sarnold sum, lo, hi); 3217934Sarnold } 3227709Sarnold } 3237709Sarnold 3247872Sarnold /* 3257872Sarnold * msg: 3267872Sarnold * Display a message at the top of the screen. 3277872Sarnold */ 3287872Sarnold char Msgbuf[BUFSIZ] = ""; 3297709Sarnold 3307872Sarnold int Mpos = 0; 3317709Sarnold 3327872Sarnold static int Newpos = 0; 3337872Sarnold 3347872Sarnold /* VARARGS1 */ 3357872Sarnold msg(fmt, args) 3367872Sarnold char *fmt; 3377872Sarnold int args; 3387872Sarnold { 3397872Sarnold /* 3407872Sarnold * if the string is "", just clear the line 3417872Sarnold */ 3427872Sarnold if (*fmt == '\0') { 3437872Sarnold move(LINES - 1, 0); 3447872Sarnold clrtoeol(); 3457872Sarnold Mpos = 0; 3467872Sarnold Hasread = TRUE; 3477872Sarnold return; 3487872Sarnold } 3497872Sarnold /* 3507872Sarnold * otherwise add to the message and flush it out 3517872Sarnold */ 3527872Sarnold doadd(fmt, &args); 3537872Sarnold endmsg(); 3547872Sarnold } 3557872Sarnold 3567709Sarnold /* 3577872Sarnold * addmsg: 3587872Sarnold * Add things to the current message 3597709Sarnold */ 3607872Sarnold /* VARARGS1 */ 3617872Sarnold addmsg(fmt, args) 3627872Sarnold char *fmt; 3637872Sarnold int args; 3647872Sarnold { 3657872Sarnold doadd(fmt, &args); 3667872Sarnold } 3677709Sarnold 3687872Sarnold /* 3697872Sarnold * endmsg: 3707872Sarnold * Display a new msg (giving him a chance to see the previous one 3717872Sarnold * if it is up there with the --More--) 3727872Sarnold */ 3737872Sarnold endmsg() 3747709Sarnold { 3757872Sarnold if (!Hasread) { 3767872Sarnold move(LINES - 1, Mpos); 3777872Sarnold addstr("--More--"); 3787872Sarnold refresh(); 3797872Sarnold wait_for(' '); 3807872Sarnold } 3817872Sarnold /* 3827872Sarnold * All messages should start with uppercase, except ones that 3837872Sarnold * start with a pack addressing character 3847872Sarnold */ 3857872Sarnold if (islower(Msgbuf[0]) && Msgbuf[1] != ')') 3867872Sarnold Msgbuf[0] = toupper(Msgbuf[0]); 3877872Sarnold mvaddstr(LINES - 1, 0, Msgbuf); 3887872Sarnold clrtoeol(); 3897872Sarnold Mpos = Newpos; 3907872Sarnold Newpos = 0; 3917872Sarnold refresh(); 3927872Sarnold Hasread = FALSE; 3937872Sarnold } 3947709Sarnold 3957872Sarnold /* 3967872Sarnold * doadd: 3977872Sarnold * Perform an add onto the message buffer 3987872Sarnold */ 3997872Sarnold doadd(fmt, args) 4007872Sarnold char *fmt; 4017872Sarnold int *args; 4027872Sarnold { 4037872Sarnold static FILE junk; 4047872Sarnold 4057872Sarnold /* 4067872Sarnold * Do the printf into Msgbuf 4077872Sarnold */ 4087872Sarnold junk._flag = _IOWRT + _IOSTRG; 4097872Sarnold junk._ptr = &Msgbuf[Newpos]; 4107872Sarnold junk._cnt = 32767; 4117872Sarnold _doprnt(fmt, args, &junk); 4127872Sarnold putc('\0', &junk); 4137872Sarnold Newpos = strlen(Msgbuf); 4147709Sarnold } 4157709Sarnold 4167872Sarnold /* 4177872Sarnold * wait_for 4187872Sarnold * Sit around until the guy types the right key 4197872Sarnold */ 4207872Sarnold wait_for(ch) 4217872Sarnold register char ch; 4227872Sarnold { 4237872Sarnold register char c; 4247709Sarnold 4257872Sarnold if (ch == '\n') 4267872Sarnold while ((c = readchar()) != '\n') 4277872Sarnold continue; 4287872Sarnold else 4297872Sarnold while (readchar() != ch) 4307872Sarnold continue; 4317872Sarnold } 4327709Sarnold 4337872Sarnold /* 4347872Sarnold * readchar: 4357872Sarnold * Reads and returns a character, checking for gross input errors 4367872Sarnold */ 4377872Sarnold readchar() 4387872Sarnold { 4397872Sarnold register int cnt, y, x; 4407872Sarnold auto char c; 4417709Sarnold 4427872Sarnold over: 4437872Sarnold cnt = 0; 4447872Sarnold while (read(0, &c, 1) <= 0) 4457872Sarnold if (cnt++ > 100) /* if we are getting infinite EOFs */ 4467872Sarnold bye(); /* quit the game */ 4477872Sarnold if (c == CTRL(L)) { 4487872Sarnold wrefresh(curscr); 4497872Sarnold goto over; 4507872Sarnold } 4517872Sarnold Hasread = TRUE; 4527872Sarnold if (c == '\r') 4537872Sarnold return '\n'; 4547872Sarnold else 4557872Sarnold return c; 4567872Sarnold } 4577872Sarnold 4587872Sarnold /* 4597872Sarnold * getline: 4607872Sarnold * Reads the next line up to '\n' or EOF. Multiple spaces are 4617872Sarnold * compressed to one space; a space is inserted before a ',' 4627872Sarnold */ 4637872Sarnold char * 4647872Sarnold getline() 4657872Sarnold { 4667872Sarnold register char *sp; 4677872Sarnold register int c, oy, ox; 4687872Sarnold 4697872Sarnold getyx(stdscr, oy, ox); 4707872Sarnold refresh(); 4717872Sarnold /* 4727872Sarnold * loop reading in the string, and put it in a temporary buffer 4737872Sarnold */ 4747872Sarnold for (sp = linebuf; (c = readchar()) != '\n'; clrtoeol(), refresh()) { 4757872Sarnold if (c == -1) 4767872Sarnold continue; 4777872Sarnold else if (c == erasechar()) { /* process erase character */ 4787872Sarnold if (sp > linebuf) { 4797872Sarnold register int i; 4807872Sarnold 4817872Sarnold sp--; 4827872Sarnold for (i = strlen(unctrl(*sp)); i; i--) 4837872Sarnold addch('\b'); 4847872Sarnold } 4857872Sarnold continue; 4867872Sarnold } 4877872Sarnold else if (c == killchar()) { /* process kill character */ 4887872Sarnold sp = linebuf; 4897872Sarnold move(oy, ox); 4907872Sarnold continue; 4917872Sarnold } 4927872Sarnold else if (sp == linebuf && c == ' ') 4937872Sarnold continue; 4947872Sarnold if (sp >= &linebuf[LINESIZE-1] || !(isprint(c) || c == ' ')) 4957872Sarnold putchar(CTRL(G)); 4967872Sarnold else { 4977872Sarnold if (islower(c)) 4987872Sarnold c = toupper(c); 4997872Sarnold *sp++ = c; 5007872Sarnold addstr(unctrl(c)); 5017872Sarnold /*###366 [cc] Mpos undefined %%%*/ 5027872Sarnold Mpos++; 5037872Sarnold } 5047872Sarnold } 5057872Sarnold *sp = '\0'; 5067872Sarnold return linebuf; 5077872Sarnold } 508