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