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