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