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