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