|
|
1.1 ! root 1: static char *sccsid = "@(#)crib.c 1.17 (Berkeley) 9/6/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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.