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