1 # include <curses.h> 2 # include <signal.h> 3 # include "deck.h" 4 # include "cribbage.h" 5 # include "cribcur.h" 6 7 8 # define LOGFILE "/usr/games/lib/criblog" 9 # define INSTRCMD "ul /usr/games/lib/crib.instr | more -f" 10 11 12 main(argc, argv) 13 int argc; 14 char *argv[]; 15 { 16 register char *p; 17 BOOLEAN playing; 18 char *s; /* for reading arguments */ 19 char bust; /* flag for arg reader */ 20 FILE *f; 21 FILE *fopen(); 22 char *getline(); 23 int bye(); 24 25 while (--argc > 0) { 26 if ((*++argv)[0] != '-') { 27 fprintf(stderr, "\n\ncribbage: usage is 'cribbage [-eqr]'\n"); 28 exit(1); 29 } 30 bust = FALSE; 31 for (s = argv[0] + 1; *s != NULL; s++) { 32 switch (*s) { 33 case 'e': 34 explain = TRUE; 35 break; 36 case 'q': 37 quiet = TRUE; 38 break; 39 case 'r': 40 rflag = TRUE; 41 break; 42 default: 43 fprintf(stderr, "\n\ncribbage: usage is 'cribbage [-eqr]'\n"); 44 exit(2); 45 break; 46 } 47 if (bust) 48 break; 49 } 50 } 51 52 initscr(); 53 signal(SIGINT, bye); 54 crmode(); 55 noecho(); 56 Playwin = subwin(stdscr, PLAY_Y, PLAY_X, 0, 0); 57 Tablewin = subwin(stdscr, TABLE_Y, TABLE_X, 0, PLAY_X); 58 Compwin = subwin(stdscr, COMP_Y, COMP_X, 0, TABLE_X + PLAY_X); 59 Msgwin = subwin(stdscr, MSG_Y, MSG_X, Y_MSG_START, SCORE_X + 1); 60 leaveok(Playwin, TRUE); 61 leaveok(Tablewin, TRUE); 62 leaveok(Compwin, TRUE); 63 clearok(stdscr, FALSE); 64 65 if (!quiet) { 66 msg("Do you need instructions for cribbage? "); 67 if (getuchar() == 'Y') { 68 endwin(); 69 fflush(stdout); 70 system(INSTRCMD); 71 crmode(); 72 noecho(); 73 clear(); 74 refresh(); 75 msg("For the rules of this program, do \"man cribbage\""); 76 } 77 } 78 playing = TRUE; 79 do { 80 wclrtobot(Msgwin); 81 msg(quiet ? "L or S? " : "Long (to 121) or Short (to 61)? "); 82 if (glimit == SGAME) 83 glimit = (getuchar() == 'L' ? LGAME : SGAME); 84 else 85 glimit = (getuchar() == 'S' ? SGAME : LGAME); 86 game(); 87 msg("Another game? "); 88 playing = (getuchar() == 'Y'); 89 } while (playing); 90 91 if ((f = fopen(LOGFILE, "a")) != NULL) { 92 fprintf(f, "Won %5.5d, Lost %5.5d\n", cgames, pgames); 93 fclose(f); 94 } 95 96 bye(); 97 } 98 99 /* 100 * bye: 101 * Leave the program, cleaning things up as we go. 102 */ 103 bye() 104 { 105 signal(SIGINT, SIG_IGN); 106 mvcur(0, COLS - 1, LINES - 1, 0); 107 fflush(stdout); 108 endwin(); 109 putchar('\n'); 110 exit(1); 111 } 112 113 /* 114 * makeboard: 115 * Print out the initial board on the screen 116 */ 117 makeboard() 118 { 119 mvaddstr(SCORE_Y + 0, SCORE_X, "+---------------------------------------+"); 120 mvaddstr(SCORE_Y + 1, SCORE_X, "| Score: 0 YOU |"); 121 mvaddstr(SCORE_Y + 2, SCORE_X, "| *.....:.....:.....:.....:.....:..... |"); 122 mvaddstr(SCORE_Y + 3, SCORE_X, "| *.....:.....:.....:.....:.....:..... |"); 123 mvaddstr(SCORE_Y + 4, SCORE_X, "| |"); 124 mvaddstr(SCORE_Y + 5, SCORE_X, "| *.....:.....:.....:.....:.....:..... |"); 125 mvaddstr(SCORE_Y + 6, SCORE_X, "| *.....:.....:.....:.....:.....:..... |"); 126 mvaddstr(SCORE_Y + 7, SCORE_X, "| Score: 0 ME |"); 127 mvaddstr(SCORE_Y + 8, SCORE_X, "+---------------------------------------+"); 128 gamescore(); 129 } 130 131 /* 132 * gamescore: 133 * Print out the current game score 134 */ 135 gamescore() 136 { 137 extern int Lastscore[]; 138 139 if (pgames || cgames) { 140 mvprintw(SCORE_Y + 1, SCORE_X + 28, "Games: %3d", pgames); 141 mvprintw(SCORE_Y + 7, SCORE_X + 28, "Games: %3d", cgames); 142 } 143 Lastscore[0] = -1; 144 Lastscore[1] = -1; 145 } 146 147 /* 148 * game: 149 * Play one game up to glimit points. Actually, we only ASK the 150 * player what card to turn. We do a random one, anyway. 151 */ 152 game() 153 { 154 register int i, j; 155 BOOLEAN flag; 156 BOOLEAN compcrib; 157 158 makeboard(); 159 refresh(); 160 makedeck(deck); 161 shuffle(deck); 162 if (gamecount == 0) { 163 flag = TRUE; 164 do { 165 if (!rflag) { /* player cuts deck */ 166 msg(quiet ? "Cut for crib? " : 167 "Cut to see whose crib it is -- low card wins? "); 168 getline(); 169 } 170 i = (rand() >> 4) % CARDS; /* random cut */ 171 do { /* comp cuts deck */ 172 j = (rand() >> 4) % CARDS; 173 } while (j == i); 174 addmsg(quiet ? "You cut " : "You cut the "); 175 msgcard(deck[i], FALSE); 176 endmsg(); 177 addmsg(quiet ? "I cut " : "I cut the "); 178 msgcard(deck[j], FALSE); 179 endmsg(); 180 flag = (deck[i].rank == deck[j].rank); 181 if (flag) { 182 msg(quiet ? "We tied..." : 183 "We tied and have to try again..."); 184 shuffle(deck); 185 continue; 186 } 187 else 188 compcrib = (deck[i].rank > deck[j].rank); 189 } while (flag); 190 } 191 else { 192 werase(Tablewin); 193 wrefresh(Tablewin); 194 werase(Compwin); 195 wrefresh(Compwin); 196 msg("Loser (%s) gets first crib", (iwon ? "you" : "me")); 197 compcrib = !iwon; 198 } 199 200 pscore = cscore = 0; 201 flag = TRUE; 202 do { 203 shuffle(deck); 204 flag = !playhand(compcrib); 205 compcrib = !compcrib; 206 } while (flag); 207 ++gamecount; 208 if (cscore < pscore) { 209 if (glimit - cscore > 60) { 210 msg("YOU DOUBLE SKUNKED ME!"); 211 pgames += 4; 212 } 213 else if (glimit - cscore > 30) { 214 msg("YOU SKUNKED ME!"); 215 pgames += 2; 216 } 217 else { 218 msg("YOU WON!"); 219 ++pgames; 220 } 221 iwon = FALSE; 222 } 223 else { 224 if (glimit - pscore > 60) { 225 msg("I DOUBLE SKUNKED YOU!"); 226 cgames += 4; 227 } 228 else if (glimit - pscore > 30) { 229 msg("I SKUNKED YOU!"); 230 cgames += 2; 231 } 232 else { 233 msg("I WON!"); 234 ++cgames; 235 } 236 iwon = TRUE; 237 } 238 gamescore(); 239 } 240 241 /* 242 * playhand: 243 * Do up one hand of the game 244 */ 245 playhand(mycrib) 246 BOOLEAN mycrib; 247 { 248 register int deckpos; 249 extern char Msgbuf[]; 250 251 werase(Compwin); 252 253 knownum = 0; 254 deckpos = deal(mycrib); 255 sorthand(chand, FULLHAND); 256 sorthand(phand, FULLHAND); 257 makeknown(chand, FULLHAND); 258 prhand(phand, FULLHAND, Playwin, FALSE); 259 discard(mycrib); 260 if (cut(mycrib, deckpos)) 261 return TRUE; 262 if (peg(mycrib)) 263 return TRUE; 264 werase(Tablewin); 265 wrefresh(Tablewin); 266 if (score(mycrib)) 267 return TRUE; 268 return FALSE; 269 } 270 271 272 273 /* 274 * deal cards to both players from deck 275 */ 276 277 deal( mycrib ) 278 { 279 register int i, j; 280 281 j = 0; 282 for( i = 0; i < FULLHAND; i++ ) { 283 if( mycrib ) { 284 phand[i] = deck[j++]; 285 chand[i] = deck[j++]; 286 } 287 else { 288 chand[i] = deck[j++]; 289 phand[i] = deck[j++]; 290 } 291 } 292 return( j ); 293 } 294 295 /* 296 * discard: 297 * Handle players discarding into the crib... 298 * Note: we call cdiscard() after prining first message so player doesn't wait 299 */ 300 discard(mycrib) 301 BOOLEAN mycrib; 302 { 303 register char *prompt; 304 CARD crd; 305 306 prcrib(mycrib, TRUE); 307 prompt = (quiet ? "Discard --> " : "Discard a card --> "); 308 cdiscard(mycrib); /* puts best discard at end */ 309 crd = phand[infrom(phand, FULLHAND, prompt)]; 310 remove(crd, phand, FULLHAND); 311 prhand(phand, FULLHAND, Playwin, FALSE); 312 crib[0] = crd; 313 /* next four lines same as last four except for cdiscard() */ 314 crd = phand[infrom(phand, FULLHAND - 1, prompt)]; 315 remove(crd, phand, FULLHAND - 1); 316 prhand(phand, FULLHAND, Playwin, FALSE); 317 crib[1] = crd; 318 crib[2] = chand[4]; 319 crib[3] = chand[5]; 320 chand[4].rank = chand[4].suit = chand[5].rank = chand[5].suit = EMPTY; 321 } 322 323 /* 324 * cut: 325 * Cut the deck and set turnover. Actually, we only ASK the 326 * player what card to turn. We do a random one, anyway. 327 */ 328 cut(mycrib, pos) 329 BOOLEAN mycrib; 330 int pos; 331 { 332 register int i, cardx; 333 BOOLEAN win = FALSE; 334 335 if (mycrib) { 336 if (!rflag) { /* random cut */ 337 msg(quiet ? "Cut the deck? " : 338 "How many cards down do you wish to cut the deck? "); 339 getline(); 340 } 341 i = (rand() >> 4) % (CARDS - pos); 342 turnover = deck[i + pos]; 343 addmsg(quiet ? "You cut " : "You cut the "); 344 msgcard(turnover, FALSE); 345 endmsg(); 346 if (turnover.rank == JACK) { 347 msg("I get two for his heels"); 348 win = chkscr(&cscore,2 ); 349 } 350 } 351 else { 352 i = (rand() >> 4) % (CARDS - pos) + pos; 353 turnover = deck[i]; 354 addmsg(quiet ? "I cut " : "I cut the "); 355 msgcard(turnover, FALSE); 356 endmsg(); 357 if (turnover.rank == JACK) { 358 msg("You get two for his heels"); 359 win = chkscr(&pscore, 2); 360 } 361 } 362 makeknown(&turnover, 1); 363 prcrib(mycrib, FALSE); 364 return win; 365 } 366 367 /* 368 * prcrib: 369 * Print out the turnover card with crib indicator 370 */ 371 prcrib(mycrib, blank) 372 BOOLEAN mycrib, blank; 373 { 374 register int y, cardx; 375 376 if (mycrib) 377 cardx = CRIB_X; 378 else 379 cardx = 0; 380 381 mvaddstr(CRIB_Y, cardx + 1, "CRIB"); 382 prcard(stdscr, CRIB_Y + 1, cardx, turnover, blank); 383 384 if (mycrib) 385 cardx = 0; 386 else 387 cardx = CRIB_X; 388 389 for (y = CRIB_Y; y <= CRIB_Y + 5; y++) 390 mvaddstr(y, cardx, " "); 391 } 392 393 /* 394 * peg: 395 * Handle all the pegging... 396 */ 397 398 static CARD Table[14]; 399 400 static int Tcnt; 401 402 peg(mycrib) 403 BOOLEAN mycrib; 404 { 405 static CARD ch[CINHAND], ph[CINHAND]; 406 CARD crd; 407 register int i, j, k; 408 register int l; 409 register int cnum, pnum, sum; 410 register BOOLEAN myturn, mego, ugo, last, played; 411 412 cnum = pnum = CINHAND; 413 for (i = 0; i < CINHAND; i++) { /* make copies of hands */ 414 ch[i] = chand[i]; 415 ph[i] = phand[i]; 416 } 417 Tcnt = 0; /* index to table of cards played */ 418 sum = 0; /* sum of cards played */ 419 mego = ugo = FALSE; 420 myturn = !mycrib; 421 for (;;) { 422 last = TRUE; /* enable last flag */ 423 prhand(ph, pnum, Playwin, FALSE); 424 prhand(ch, cnum, Compwin, TRUE); 425 prtable(sum); 426 if (myturn) { /* my tyrn to play */ 427 if (!anymove(ch, cnum, sum)) { /* if no card to play */ 428 if (!mego && cnum) { /* go for comp? */ 429 msg("GO"); 430 mego = TRUE; 431 } 432 if (anymove(ph, pnum, sum)) /* can player move? */ 433 myturn = !myturn; 434 else { /* give him his point */ 435 msg(quiet ? "You get one" : "You get one point"); 436 if (chkscr(&pscore, 1)) 437 return TRUE; 438 sum = 0; 439 mego = ugo = FALSE; 440 Tcnt = 0; 441 } 442 } 443 else { 444 played = TRUE; 445 j = -1; 446 k = 0; 447 for (i = 0; i < cnum; i++) { /* maximize score */ 448 l = pegscore(ch[i], Table, Tcnt, sum); 449 if (l > k) { 450 k = l; 451 j = i; 452 } 453 } 454 if (j < 0) /* if nothing scores */ 455 j = cchose(ch, cnum, sum); 456 crd = ch[j]; 457 remove(crd, ch, cnum--); 458 sum += VAL(crd.rank); 459 Table[Tcnt++] = crd; 460 if (k > 0) { 461 addmsg(quiet ? "I get %d playing " : 462 "I get %d points playing ", k); 463 msgcard(crd, FALSE); 464 endmsg(); 465 if (chkscr(&cscore, k)) 466 return TRUE; 467 } 468 myturn = !myturn; 469 } 470 } 471 else { 472 if (!anymove(ph, pnum, sum)) { /* can player move? */ 473 if (!ugo && pnum) { /* go for player */ 474 msg("You have a GO"); 475 ugo = TRUE; 476 } 477 if (anymove(ch, cnum, sum)) /* can computer play? */ 478 myturn = !myturn; 479 else { 480 msg(quiet ? "I get one" : "I get one point"); 481 do_wait(); 482 if (chkscr(&cscore, 1)) 483 return TRUE; 484 sum = 0; 485 mego = ugo = FALSE; 486 Tcnt = 0; 487 } 488 } 489 else { /* player plays */ 490 played = FALSE; 491 if (pnum == 1) { 492 crd = ph[0]; 493 msg("You play your last card"); 494 } 495 else 496 for (;;) { 497 prhand(ph, pnum, Playwin, FALSE); 498 crd = ph[infrom(ph, pnum, "Your play: ")]; 499 if (sum + VAL(crd.rank) <= 31) 500 break; 501 else 502 msg("Total > 31 -- try again"); 503 } 504 makeknown(&crd, 1); 505 remove(crd, ph, pnum--); 506 i = pegscore(crd, Table, Tcnt, sum); 507 sum += VAL(crd.rank); 508 Table[Tcnt++] = crd; 509 if (i > 0) { 510 msg(quiet ? "You got %d" : "You got %d points", i); 511 if (chkscr(&pscore, i)) 512 return TRUE; 513 } 514 myturn = !myturn; 515 } 516 } 517 if (sum >= 31) { 518 if (!myturn) 519 do_wait(); 520 sum = 0; 521 mego = ugo = FALSE; 522 Tcnt = 0; 523 last = FALSE; /* disable last flag */ 524 } 525 if (!pnum && !cnum) 526 break; /* both done */ 527 } 528 prhand(ph, pnum, Playwin, FALSE); 529 prhand(ch, cnum, Compwin, TRUE); 530 prtable(sum); 531 if (last) 532 if (played) { 533 msg(quiet ? "I get one for last" : "I get one point for last"); 534 do_wait(); 535 if (chkscr(&cscore, 1)) 536 return TRUE; 537 } 538 else { 539 msg(quiet ? "You get one for last" : 540 "You get one point for last"); 541 if (chkscr(&pscore, 1)) 542 return TRUE; 543 } 544 return FALSE; 545 } 546 547 /* 548 * prtable: 549 * Print out the table with the current score 550 */ 551 prtable(score) 552 int score; 553 { 554 prhand(Table, Tcnt, Tablewin, FALSE); 555 mvwprintw(Tablewin, (Tcnt + 2) * 2, Tcnt + 1, "%2d", score); 556 wrefresh(Tablewin); 557 } 558 559 /* 560 * score: 561 * Handle the scoring of the hands 562 */ 563 score(mycrib) 564 BOOLEAN mycrib; 565 { 566 sorthand(crib, CINHAND); 567 if (mycrib) { 568 if (plyrhand(phand, "hand")) 569 return TRUE; 570 if (comphand(chand, "hand")) 571 return TRUE; 572 do_wait(); 573 if (comphand(crib, "crib")) 574 return TRUE; 575 } 576 else { 577 if (comphand(chand, "hand")) 578 return TRUE; 579 if (plyrhand(phand, "hand")) 580 return TRUE; 581 if (plyrhand(crib, "crib")) 582 return TRUE; 583 } 584 return FALSE; 585 } 586