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