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