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