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