1*7872Sarnold # include <curses.h> 2*7872Sarnold # include <ctype.h> 3*7872Sarnold # include <unctrl.h> 4*7872Sarnold # include "deck.h" 5*7872Sarnold # include "cribbage.h" 67709Sarnold 7*7872Sarnold # define LINESIZE 128 87709Sarnold 9*7872Sarnold # define CTRL(X) ('X' - 'A' + 1) 107709Sarnold 11*7872Sarnold # ifndef attron 12*7872Sarnold # define erasechar() _tty.sg_erase 13*7872Sarnold # define killchar() _tty.sg_kill 14*7872Sarnold # endif attron 15*7872Sarnold 167709Sarnold char linebuf[ LINESIZE ]; 177709Sarnold 187709Sarnold char *rankname[ RANKS ] = { "ACE", "TWO", "THREE", "FOUR", 19*7872Sarnold "FIVE", "SIX", "SEVEN", "EIGHT", 20*7872Sarnold "NINE", "TEN", "JACK", "QUEEN", 21*7872Sarnold "KING" }; 227709Sarnold 237709Sarnold char *rankchar[ RANKS ] = { "A", "2", "3", "4", "5", "6", "7", 24*7872Sarnold "8", "9", "T", "J", "Q", "K" }; 257709Sarnold 267709Sarnold char *suitname[ SUITS ] = { "SPADES", "HEARTS", "DIAMONDS", 27*7872Sarnold "CLUBS" }; 287709Sarnold 297709Sarnold char *suitchar[ SUITS ] = { "S", "H", "D", "C" }; 307709Sarnold 317709Sarnold 327709Sarnold 337709Sarnold /* 34*7872Sarnold * msgcard: 35*7872Sarnold * Call msgcrd in one of two forms 367709Sarnold */ 37*7872Sarnold msgcard(c, brief) 38*7872Sarnold CARD c; 39*7872Sarnold BOOLEAN brief; 407709Sarnold { 41*7872Sarnold if (brief) 42*7872Sarnold return msgcrd(c, TRUE, (char *) NULL, TRUE); 43*7872Sarnold else 44*7872Sarnold return msgcrd(c, FALSE, " of ", FALSE); 457709Sarnold } 467709Sarnold 477709Sarnold 487709Sarnold 497709Sarnold /* 50*7872Sarnold * msgcrd: 51*7872Sarnold * Print the value of a card in ascii 527709Sarnold */ 53*7872Sarnold msgcrd(c, brfrank, mid, brfsuit) 54*7872Sarnold CARD c; 55*7872Sarnold char *mid; 56*7872Sarnold BOOLEAN brfrank, brfsuit; 57*7872Sarnold { 58*7872Sarnold if (c.rank == EMPTY || c.suit == EMPTY) 59*7872Sarnold return FALSE; 60*7872Sarnold if (brfrank) 61*7872Sarnold addmsg("%1.1s", rankchar[c.rank]); 62*7872Sarnold else 63*7872Sarnold addmsg(rankname[c.rank]); 64*7872Sarnold if (mid != NULL) 65*7872Sarnold addmsg(mid); 66*7872Sarnold if (brfsuit) 67*7872Sarnold addmsg("%1.1s", suitchar[c.suit]); 68*7872Sarnold else 69*7872Sarnold addmsg(suitname[c.suit]); 70*7872Sarnold return TRUE; 71*7872Sarnold } 727709Sarnold 73*7872Sarnold /* 74*7872Sarnold * printcard: 75*7872Sarnold * Print out a card. 76*7872Sarnold */ 77*7872Sarnold printcard(win, cardno, c) 78*7872Sarnold WINDOW *win; 79*7872Sarnold int cardno; 80*7872Sarnold CARD c; 81*7872Sarnold { 82*7872Sarnold prcard(win, cardno * 2, cardno, c); 83*7872Sarnold } 847709Sarnold 85*7872Sarnold /* 86*7872Sarnold * prcard: 87*7872Sarnold * Print out a card on the window at the specified location 88*7872Sarnold */ 89*7872Sarnold prcard(win, y, x, c) 90*7872Sarnold WINDOW *win; 91*7872Sarnold int y, x; 92*7872Sarnold CARD c; 937709Sarnold { 94*7872Sarnold if (c.rank == EMPTY) 95*7872Sarnold return; 96*7872Sarnold mvwaddstr(win, y + 0, x, "+-----+"); 97*7872Sarnold mvwaddstr(win, y + 1, x, "| |"); 98*7872Sarnold mvwaddstr(win, y + 2, x, "| |"); 99*7872Sarnold mvwaddstr(win, y + 3, x, "| |"); 100*7872Sarnold mvwaddstr(win, y + 4, x, "+-----+"); 101*7872Sarnold mvwaddch(win, y + 1, x + 1, rankchar[c.rank][0]); 102*7872Sarnold waddch(win, suitchar[c.suit][0]); 103*7872Sarnold mvwaddch(win, y + 3, x + 4, rankchar[c.rank][0]); 104*7872Sarnold waddch(win, suitchar[c.suit][0]); 1057709Sarnold } 1067709Sarnold 1077709Sarnold /* 108*7872Sarnold * prhand: 109*7872Sarnold * Print a hand of n cards 1107709Sarnold */ 111*7872Sarnold prhand(h, n, win) 112*7872Sarnold CARD h[]; 113*7872Sarnold int n; 114*7872Sarnold WINDOW *win; 1157709Sarnold { 116*7872Sarnold register int i; 1177709Sarnold 118*7872Sarnold werase(win); 119*7872Sarnold for (i = 0; i < n; i++) 120*7872Sarnold printcard(win, i, h[i]); 121*7872Sarnold wrefresh(win); 1227709Sarnold } 1237709Sarnold 1247709Sarnold 1257709Sarnold 1267709Sarnold /* 127*7872Sarnold * infrom: 128*7872Sarnold * reads a card, supposedly in hand, accepting unambigous brief 129*7872Sarnold * input, returns the index of the card found... 1307709Sarnold */ 131*7872Sarnold infrom(hand, n, prompt) 132*7872Sarnold CARD hand[]; 133*7872Sarnold int n; 134*7872Sarnold char *prompt; 1357709Sarnold { 136*7872Sarnold register int i, j; 137*7872Sarnold CARD crd; 1387709Sarnold 139*7872Sarnold if (n < 1) { 140*7872Sarnold printf("\nINFROM: %d = n < 1!!\n", n); 141*7872Sarnold exit(74); 142*7872Sarnold } 143*7872Sarnold for (;;) { 144*7872Sarnold if (incard(&crd)) { /* if card is full card */ 145*7872Sarnold if (!isone(crd, hand, n)) 146*7872Sarnold msg("That's not in your hand"); 147*7872Sarnold else { 148*7872Sarnold for (i = 0; i < n; i++) 149*7872Sarnold if (hand[i].rank == crd.rank && 150*7872Sarnold hand[i].suit == crd.suit) 151*7872Sarnold break; 152*7872Sarnold if (i >= n) { 153*7872Sarnold printf("\nINFROM: isone or something messed up\n"); 154*7872Sarnold exit(77); 155*7872Sarnold } 156*7872Sarnold return i; 157*7872Sarnold } 158*7872Sarnold } 159*7872Sarnold else /* if not full card... */ 160*7872Sarnold if (crd.rank != EMPTY) { 161*7872Sarnold for (i = 0; i < n; i++) 162*7872Sarnold if (hand[i].rank == crd.rank) 163*7872Sarnold break; 164*7872Sarnold if (i >= n) 165*7872Sarnold msg("No such rank in your hand"); 166*7872Sarnold else { 167*7872Sarnold for (j = i + 1; j < n; j++) 168*7872Sarnold if (hand[j].rank == crd.rank) 169*7872Sarnold break; 170*7872Sarnold if (j < n) 171*7872Sarnold msg("Ambiguous rank"); 172*7872Sarnold else 173*7872Sarnold return i; 174*7872Sarnold } 175*7872Sarnold } 176*7872Sarnold else 177*7872Sarnold msg("Sorry, I missed that"); 178*7872Sarnold msg(prompt); 179*7872Sarnold } 180*7872Sarnold /* NOTREACHED */ 1817709Sarnold } 1827709Sarnold 1837709Sarnold 1847709Sarnold 1857709Sarnold /* 186*7872Sarnold * incard: 187*7872Sarnold * Inputs a card in any format. It reads a line ending with a CR 188*7872Sarnold * and then parses it. 1897709Sarnold */ 190*7872Sarnold incard(crd) 191*7872Sarnold CARD *crd; 1927709Sarnold { 193*7872Sarnold char *getline(); 194*7872Sarnold register int i; 195*7872Sarnold int rnk, sut; 196*7872Sarnold char *line, *p, *p1; 197*7872Sarnold BOOLEAN retval; 1987709Sarnold 199*7872Sarnold retval = FALSE; 200*7872Sarnold rnk = sut = EMPTY; 201*7872Sarnold if (!(line = getline())) 202*7872Sarnold goto gotit; 203*7872Sarnold p = p1 = line; 204*7872Sarnold while( *p1 != ' ' && *p1 != NULL ) ++p1; 205*7872Sarnold *p1++ = NULL; 206*7872Sarnold if( *p == NULL ) goto gotit; 207*7872Sarnold /* IMPORTANT: no real card has 2 char first name */ 208*7872Sarnold if( strlen(p) == 2 ) { /* check for short form */ 209*7872Sarnold rnk = EMPTY; 210*7872Sarnold for( i = 0; i < RANKS; i++ ) { 211*7872Sarnold if( *p == *rankchar[i] ) { 212*7872Sarnold rnk = i; 213*7872Sarnold break; 214*7872Sarnold } 215*7872Sarnold } 216*7872Sarnold if( rnk == EMPTY ) goto gotit; /* it's nothing... */ 217*7872Sarnold ++p; /* advance to next char */ 218*7872Sarnold sut = EMPTY; 219*7872Sarnold for( i = 0; i < SUITS; i++ ) { 220*7872Sarnold if( *p == *suitchar[i] ) { 221*7872Sarnold sut = i; 222*7872Sarnold break; 223*7872Sarnold } 224*7872Sarnold } 225*7872Sarnold if( sut != EMPTY ) retval = TRUE; 226*7872Sarnold goto gotit; 227*7872Sarnold } 228*7872Sarnold rnk = EMPTY; 229*7872Sarnold for( i = 0; i < RANKS; i++ ) { 230*7872Sarnold if( !strcmp( p, rankname[i] ) || !strcmp( p, rankchar[i] ) ) { 231*7872Sarnold rnk = i; 232*7872Sarnold break; 233*7872Sarnold } 234*7872Sarnold } 235*7872Sarnold if( rnk == EMPTY ) goto gotit; 236*7872Sarnold p = p1; 237*7872Sarnold while( *p1 != ' ' && *p1 != NULL ) ++p1; 238*7872Sarnold *p1++ = NULL; 239*7872Sarnold if( *p == NULL ) goto gotit; 240*7872Sarnold if( !strcmp( "OF", p ) ) { 241*7872Sarnold p = p1; 242*7872Sarnold while( *p1 != ' ' && *p1 != NULL ) ++p1; 243*7872Sarnold *p1++ = NULL; 244*7872Sarnold if( *p == NULL ) goto gotit; 245*7872Sarnold } 246*7872Sarnold sut = EMPTY; 247*7872Sarnold for( i = 0; i < SUITS; i++ ) { 248*7872Sarnold if( !strcmp( p, suitname[i] ) || !strcmp( p, suitchar[i] ) ) { 249*7872Sarnold sut = i; 250*7872Sarnold break; 251*7872Sarnold } 252*7872Sarnold } 253*7872Sarnold if( sut != EMPTY ) retval = TRUE; 2547709Sarnold gotit: 255*7872Sarnold (*crd).rank = rnk; 256*7872Sarnold (*crd).suit = sut; 257*7872Sarnold return( retval ); 2587709Sarnold } 2597709Sarnold 2607709Sarnold 2617709Sarnold 2627709Sarnold /* 263*7872Sarnold * getuchar: 264*7872Sarnold * Reads and converts to upper case 2657709Sarnold */ 2667709Sarnold getuchar() 2677709Sarnold { 268*7872Sarnold register int c; 2697709Sarnold 270*7872Sarnold c = readchar(); 271*7872Sarnold if (islower(c)) 272*7872Sarnold c = toupper(c); 273*7872Sarnold addch(c); 274*7872Sarnold return c; 2757709Sarnold } 2767709Sarnold 2777709Sarnold 2787709Sarnold 2797709Sarnold /* 2807709Sarnold * number reads in a decimal number and makes sure it is between 2817709Sarnold * lo and hi inclusive 2827709Sarnold * a cr counts as lo 2837709Sarnold */ 2847709Sarnold 2857709Sarnold number( lo, hi ) 2867709Sarnold 2877709Sarnold int lo, hi; 2887709Sarnold { 289*7872Sarnold char *getline(); 290*7872Sarnold register char *p; 291*7872Sarnold register int sum; 2927709Sarnold 293*7872Sarnold sum = 0; 294*7872Sarnold do { 295*7872Sarnold if( !( p = getline() ) ) return( lo ); /* no line = lo */ 296*7872Sarnold if( *p == NULL ) return( lo ); 297*7872Sarnold sum = 0; 298*7872Sarnold while( *p == ' ' || *p == '\t' ) ++p; 299*7872Sarnold if( *p < '0' || *p > '9' ) { 300*7872Sarnold sum = lo - 1; 301*7872Sarnold } 302*7872Sarnold else { 303*7872Sarnold do { 304*7872Sarnold sum = 10*sum + (*p - '0'); 305*7872Sarnold ++p; 306*7872Sarnold } while( '0' <= *p && *p <= '9' ); 307*7872Sarnold } 308*7872Sarnold if( *p != ' ' && *p != '\t' && *p != NULL ) sum = lo - 1; 309*7872Sarnold if( sum >= lo && sum <= hi ) break; 310*7872Sarnold if( sum == lo - 1 ) { 311*7872Sarnold printf( "that doesn't look like a number, try again --> " ); 312*7872Sarnold } 313*7872Sarnold else { 314*7872Sarnold printf( "%d is not between %d and %d inclusive, try again --> ", 315*7872Sarnold sum, lo, hi ); 316*7872Sarnold } 317*7872Sarnold } while( TRUE ); 318*7872Sarnold return( sum ); 3197709Sarnold } 3207709Sarnold 321*7872Sarnold /* 322*7872Sarnold * msg: 323*7872Sarnold * Display a message at the top of the screen. 324*7872Sarnold */ 325*7872Sarnold char Msgbuf[BUFSIZ] = ""; 3267709Sarnold 327*7872Sarnold int Mpos = 0; 3287709Sarnold 329*7872Sarnold static int Newpos = 0; 330*7872Sarnold 331*7872Sarnold /* VARARGS1 */ 332*7872Sarnold msg(fmt, args) 333*7872Sarnold char *fmt; 334*7872Sarnold int args; 335*7872Sarnold { 336*7872Sarnold /* 337*7872Sarnold * if the string is "", just clear the line 338*7872Sarnold */ 339*7872Sarnold if (*fmt == '\0') { 340*7872Sarnold move(LINES - 1, 0); 341*7872Sarnold clrtoeol(); 342*7872Sarnold Mpos = 0; 343*7872Sarnold Hasread = TRUE; 344*7872Sarnold return; 345*7872Sarnold } 346*7872Sarnold /* 347*7872Sarnold * otherwise add to the message and flush it out 348*7872Sarnold */ 349*7872Sarnold doadd(fmt, &args); 350*7872Sarnold endmsg(); 351*7872Sarnold } 352*7872Sarnold 3537709Sarnold /* 354*7872Sarnold * addmsg: 355*7872Sarnold * Add things to the current message 3567709Sarnold */ 357*7872Sarnold /* VARARGS1 */ 358*7872Sarnold addmsg(fmt, args) 359*7872Sarnold char *fmt; 360*7872Sarnold int args; 361*7872Sarnold { 362*7872Sarnold doadd(fmt, &args); 363*7872Sarnold } 3647709Sarnold 365*7872Sarnold /* 366*7872Sarnold * endmsg: 367*7872Sarnold * Display a new msg (giving him a chance to see the previous one 368*7872Sarnold * if it is up there with the --More--) 369*7872Sarnold */ 370*7872Sarnold endmsg() 3717709Sarnold { 372*7872Sarnold if (!Hasread) { 373*7872Sarnold move(LINES - 1, Mpos); 374*7872Sarnold addstr("--More--"); 375*7872Sarnold refresh(); 376*7872Sarnold wait_for(' '); 377*7872Sarnold } 378*7872Sarnold /* 379*7872Sarnold * All messages should start with uppercase, except ones that 380*7872Sarnold * start with a pack addressing character 381*7872Sarnold */ 382*7872Sarnold if (islower(Msgbuf[0]) && Msgbuf[1] != ')') 383*7872Sarnold Msgbuf[0] = toupper(Msgbuf[0]); 384*7872Sarnold mvaddstr(LINES - 1, 0, Msgbuf); 385*7872Sarnold clrtoeol(); 386*7872Sarnold Mpos = Newpos; 387*7872Sarnold Newpos = 0; 388*7872Sarnold refresh(); 389*7872Sarnold Hasread = FALSE; 390*7872Sarnold } 3917709Sarnold 392*7872Sarnold /* 393*7872Sarnold * doadd: 394*7872Sarnold * Perform an add onto the message buffer 395*7872Sarnold */ 396*7872Sarnold doadd(fmt, args) 397*7872Sarnold char *fmt; 398*7872Sarnold int *args; 399*7872Sarnold { 400*7872Sarnold static FILE junk; 401*7872Sarnold 402*7872Sarnold /* 403*7872Sarnold * Do the printf into Msgbuf 404*7872Sarnold */ 405*7872Sarnold junk._flag = _IOWRT + _IOSTRG; 406*7872Sarnold junk._ptr = &Msgbuf[Newpos]; 407*7872Sarnold junk._cnt = 32767; 408*7872Sarnold _doprnt(fmt, args, &junk); 409*7872Sarnold putc('\0', &junk); 410*7872Sarnold Newpos = strlen(Msgbuf); 4117709Sarnold } 4127709Sarnold 413*7872Sarnold /* 414*7872Sarnold * wait_for 415*7872Sarnold * Sit around until the guy types the right key 416*7872Sarnold */ 417*7872Sarnold wait_for(ch) 418*7872Sarnold register char ch; 419*7872Sarnold { 420*7872Sarnold register char c; 4217709Sarnold 422*7872Sarnold if (ch == '\n') 423*7872Sarnold while ((c = readchar()) != '\n') 424*7872Sarnold continue; 425*7872Sarnold else 426*7872Sarnold while (readchar() != ch) 427*7872Sarnold continue; 428*7872Sarnold } 4297709Sarnold 430*7872Sarnold /* 431*7872Sarnold * readchar: 432*7872Sarnold * Reads and returns a character, checking for gross input errors 433*7872Sarnold */ 434*7872Sarnold readchar() 435*7872Sarnold { 436*7872Sarnold register int cnt, y, x; 437*7872Sarnold auto char c; 4387709Sarnold 439*7872Sarnold over: 440*7872Sarnold cnt = 0; 441*7872Sarnold while (read(0, &c, 1) <= 0) 442*7872Sarnold if (cnt++ > 100) /* if we are getting infinite EOFs */ 443*7872Sarnold bye(); /* quit the game */ 444*7872Sarnold if (c == CTRL(L)) { 445*7872Sarnold wrefresh(curscr); 446*7872Sarnold goto over; 447*7872Sarnold } 448*7872Sarnold Hasread = TRUE; 449*7872Sarnold if (c == '\r') 450*7872Sarnold return '\n'; 451*7872Sarnold else 452*7872Sarnold return c; 453*7872Sarnold } 454*7872Sarnold 455*7872Sarnold /* 456*7872Sarnold * getline: 457*7872Sarnold * Reads the next line up to '\n' or EOF. Multiple spaces are 458*7872Sarnold * compressed to one space; a space is inserted before a ',' 459*7872Sarnold */ 460*7872Sarnold char * 461*7872Sarnold getline() 462*7872Sarnold { 463*7872Sarnold register char *sp; 464*7872Sarnold register int c, oy, ox; 465*7872Sarnold 466*7872Sarnold getyx(stdscr, oy, ox); 467*7872Sarnold refresh(); 468*7872Sarnold /* 469*7872Sarnold * loop reading in the string, and put it in a temporary buffer 470*7872Sarnold */ 471*7872Sarnold for (sp = linebuf; (c = readchar()) != '\n'; clrtoeol(), refresh()) { 472*7872Sarnold if (c == -1) 473*7872Sarnold continue; 474*7872Sarnold else if (c == erasechar()) { /* process erase character */ 475*7872Sarnold if (sp > linebuf) { 476*7872Sarnold register int i; 477*7872Sarnold 478*7872Sarnold sp--; 479*7872Sarnold for (i = strlen(unctrl(*sp)); i; i--) 480*7872Sarnold addch('\b'); 481*7872Sarnold } 482*7872Sarnold continue; 483*7872Sarnold } 484*7872Sarnold else if (c == killchar()) { /* process kill character */ 485*7872Sarnold sp = linebuf; 486*7872Sarnold move(oy, ox); 487*7872Sarnold continue; 488*7872Sarnold } 489*7872Sarnold else if (sp == linebuf && c == ' ') 490*7872Sarnold continue; 491*7872Sarnold if (sp >= &linebuf[LINESIZE-1] || !(isprint(c) || c == ' ')) 492*7872Sarnold putchar(CTRL(G)); 493*7872Sarnold else { 494*7872Sarnold if (islower(c)) 495*7872Sarnold c = toupper(c); 496*7872Sarnold *sp++ = c; 497*7872Sarnold addstr(unctrl(c)); 498*7872Sarnold /*###366 [cc] Mpos undefined %%%*/ 499*7872Sarnold Mpos++; 500*7872Sarnold } 501*7872Sarnold } 502*7872Sarnold *sp = '\0'; 503*7872Sarnold return linebuf; 504*7872Sarnold } 505