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