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: }

Defined functions

cut defined in line 330; used 1 times
deal defined in line 279; used 1 times
discard defined in line 302; used 1 times
game defined in line 154; used 1 times
gamescore defined in line 137; used 2 times
main defined in line 28; never used
makeboard defined in line 119; used 1 times
peg defined in line 404; used 1 times
playhand defined in line 247; used 1 times
prcrib defined in line 373; used 2 times
prtable defined in line 553; used 2 times
score defined in line 565; used 4 times

Defined variables

Tcnt defined in line 402; used 11 times
copyright defined in line 8; never used
sccsid defined in line 14; never used

Defined macros

INSTRCMD defined in line 25; used 1 times
  • in line 86
LOGFILE defined in line 24; used 1 times
Last modified: 1985-05-31
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 2158
Valid CSS Valid XHTML 1.0 Strict