|
|
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.