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: #if 0
35: static char sccsid[] = "@(#)io.c 8.1 (Berkeley) 5/31/93";
36: #else
37: __RCSID("$NetBSD: io.c,v 1.18 2004/11/05 21:30:31 dsl Exp $");
38: #endif
39: #endif
40:
41: #include <ctype.h>
42: #include <curses.h>
43: #include <signal.h>
44: #include <stdarg.h>
45: #include <stdlib.h>
46: #include <string.h>
47: #include <termios.h>
48: #include <unistd.h>
49:
50: #include "deck.h"
51: #include "cribbage.h"
52: #include "cribcur.h"
53:
54: #define LINESIZE 128
55:
56: #ifdef CTRL
57: #undef CTRL
58: #endif
59: #define CTRL(X) (X - 'A' + 1)
60:
61: char linebuf[LINESIZE];
62:
63: const char *const rankname[RANKS] = {
64: "ACE", "TWO", "THREE", "FOUR", "FIVE", "SIX", "SEVEN",
65: "EIGHT", "NINE", "TEN", "JACK", "QUEEN", "KING"
66: };
67:
68: const char *const rankchar[RANKS] = {
69: "A", "2", "3", "4", "5", "6", "7", "8", "9", "T", "J", "Q", "K"
70: };
71:
72: const char *const suitname[SUITS] = {"SPADES", "HEARTS", "DIAMONDS", "CLUBS"};
73:
74: const char *const suitchar[SUITS] = {"S", "H", "D", "C"};
75:
76:
77:
78:
79:
80: int
81: msgcard(c, brief)
82: CARD c;
83: BOOLEAN brief;
84: {
85: if (brief)
86: return (msgcrd(c, TRUE, NULL, TRUE));
87: else
88: return (msgcrd(c, FALSE, " of ", FALSE));
89: }
90:
91:
92:
93:
94:
95: int
96: msgcrd(c, brfrank, mid, brfsuit)
97: CARD c;
98: BOOLEAN brfrank, brfsuit;
99: const char *mid;
100: {
101: if (c.rank == EMPTY || c.suit == EMPTY)
102: return (FALSE);
103: if (brfrank)
104: addmsg("%1.1s", rankchar[c.rank]);
105: else
106: addmsg(rankname[c.rank]);
107: if (mid != NULL)
108: addmsg(mid);
109: if (brfsuit)
110: addmsg("%1.1s", suitchar[c.suit]);
111: else
112: addmsg(suitname[c.suit]);
113: return (TRUE);
114: }
115:
116:
117:
118:
119:
120: void
121: printcard(win, cardno, c, blank)
122: WINDOW *win;
123: int cardno;
124: CARD c;
125: BOOLEAN blank;
126: {
127: prcard(win, cardno * 2, cardno, c, blank);
128: }
129:
130:
131:
132:
133:
134: void
135: prcard(win, y, x, c, blank)
136: WINDOW *win;
137: int y, x;
138: CARD c;
139: BOOLEAN blank;
140: {
141: if (c.rank == EMPTY)
142: return;
143:
144: mvwaddstr(win, y + 0, x, "+-----+");
145: mvwaddstr(win, y + 1, x, "| |");
146: mvwaddstr(win, y + 2, x, "| |");
147: mvwaddstr(win, y + 3, x, "| |");
148: mvwaddstr(win, y + 4, x, "+-----+");
149: if (!blank) {
150: mvwaddch(win, y + 1, x + 1, rankchar[c.rank][0]);
151: waddch(win, suitchar[c.suit][0]);
152: mvwaddch(win, y + 3, x + 4, rankchar[c.rank][0]);
153: waddch(win, suitchar[c.suit][0]);
154: }
155: }
156:
157:
158:
159:
160:
161: void
162: prhand(h, n, win, blank)
163: const CARD h[];
164: int n;
165: WINDOW *win;
166: BOOLEAN blank;
167: {
168: int i;
169:
170: werase(win);
171: for (i = 0; i < n; i++)
172: printcard(win, i, *h++, blank);
173: wrefresh(win);
174: }
175:
176:
177:
178:
179:
180:
181: int
182: infrom(hand, n, prompt)
183: const CARD hand[];
184: int n;
185: const char *prompt;
186: {
187: int i, j;
188: CARD crd;
189:
190: if (n < 1) {
191: printf("\nINFROM: %d = n < 1!!\n", n);
192: exit(74);
193: }
194: for (;;) {
195: msg(prompt);
196: if (incard(&crd)) {
197: if (!is_one(crd, hand, n))
198: msg("That's not in your hand");
199: else {
200: for (i = 0; i < n; i++)
201: if (hand[i].rank == crd.rank &&
202: hand[i].suit == crd.suit)
203: break;
204: if (i >= n) {
205: printf("\nINFROM: is_one or something messed up\n");
206: exit(77);
207: }
208: return (i);
209: }
210: } else
211: if (crd.rank != EMPTY) {
212: for (i = 0; i < n; i++)
213: if (hand[i].rank == crd.rank)
214: break;
215: if (i >= n)
216: msg("No such rank in your hand");
217: else {
218: for (j = i + 1; j < n; j++)
219: if (hand[j].rank == crd.rank)
220: break;
221: if (j < n)
222: msg("Ambiguous rank");
223: else
224: return (i);
225: }
226: } else
227: msg("Sorry, I missed that");
228: }
229:
230: }
231:
232:
233:
234:
235:
236:
237: int
238: incard(crd)
239: CARD *crd;
240: {
241: int i;
242: int rnk, sut;
243: char *line, *p, *p1;
244: BOOLEAN retval;
245:
246: retval = FALSE;
247: rnk = sut = EMPTY;
248: if (!(line = getline()))
249: goto gotit;
250: p = p1 = line;
251: while (*p1 != ' ' && *p1 != '\0')
252: ++p1;
253: *p1++ = '\0';
254: if (*p == '\0')
255: goto gotit;
256:
257:
258: if (strlen(p) == 2) {
259: rnk = EMPTY;
260: for (i = 0; i < RANKS; i++) {
261: if (*p == *rankchar[i]) {
262: rnk = i;
263: break;
264: }
265: }
266: if (rnk == EMPTY)
267: goto gotit;
268: ++p;
269: sut = EMPTY;
270: for (i = 0; i < SUITS; i++) {
271: if (*p == *suitchar[i]) {
272: sut = i;
273: break;
274: }
275: }
276: if (sut != EMPTY)
277: retval = TRUE;
278: goto gotit;
279: }
280: rnk = EMPTY;
281: for (i = 0; i < RANKS; i++) {
282: if (!strcmp(p, rankname[i]) || !strcmp(p, rankchar[i])) {
283: rnk = i;
284: break;
285: }
286: }
287: if (rnk == EMPTY)
288: goto gotit;
289: p = p1;
290: while (*p1 != ' ' && *p1 != '\0')
291: ++p1;
292: *p1++ = '\0';
293: if (*p == '\0')
294: goto gotit;
295: if (!strcmp("OF", p)) {
296: p = p1;
297: while (*p1 != ' ' && *p1 != '\0')
298: ++p1;
299: *p1++ = '\0';
300: if (*p == '\0')
301: goto gotit;
302: }
303: sut = EMPTY;
304: for (i = 0; i < SUITS; i++) {
305: if (!strcmp(p, suitname[i]) || !strcmp(p, suitchar[i])) {
306: sut = i;
307: break;
308: }
309: }
310: if (sut != EMPTY)
311: retval = TRUE;
312: gotit:
313: (*crd).rank = rnk;
314: (*crd).suit = sut;
315: return (retval);
316: }
317:
318:
319:
320:
321:
322: int
323: getuchar()
324: {
325: int c;
326:
327: c = readchar();
328: if (islower(c))
329: c = toupper(c);
330: waddch(Msgwin, c);
331: return (c);
332: }
333:
334:
335:
336:
337:
338:
339: int
340: number(lo, hi, prompt)
341: int lo, hi;
342: const char *prompt;
343: {
344: char *p;
345: int sum;
346:
347: for (sum = 0;;) {
348: msg(prompt);
349: if (!(p = getline()) || *p == '\0') {
350: msg(quiet ? "Not a number" :
351: "That doesn't look like a number");
352: continue;
353: }
354: sum = 0;
355:
356: if (!isdigit((unsigned char)*p))
357: sum = lo - 1;
358: else
359: while (isdigit((unsigned char)*p)) {
360: sum = 10 * sum + (*p - '0');
361: ++p;
362: }
363:
364: if (*p != ' ' && *p != '\t' && *p != '\0')
365: sum = lo - 1;
366: if (sum >= lo && sum <= hi)
367: break;
368: if (sum == lo - 1)
369: msg("that doesn't look like a number, try again --> ");
370: else
371: msg("%d is not between %d and %d inclusive, try again --> ",
372: sum, lo, hi);
373: }
374: return (sum);
375: }
376:
377:
378:
379:
380:
381: char Msgbuf[BUFSIZ] = {'\0'};
382: int Mpos = 0;
383: static int Newpos = 0;
384:
385: void
386: msg(const char *fmt, ...)
387: {
388: va_list ap;
389:
390: va_start(ap, fmt);
391: (void)vsprintf(&Msgbuf[Newpos], fmt, ap);
392: Newpos = strlen(Msgbuf);
393: va_end(ap);
394: endmsg();
395: }
396:
397:
398:
399:
400:
401: void
402: addmsg(const char *fmt, ...)
403: {
404: va_list ap;
405:
406: va_start(ap, fmt);
407: (void)vsprintf(&Msgbuf[Newpos], fmt, ap);
408: Newpos = strlen(Msgbuf);
409: va_end(ap);
410: }
411:
412:
413:
414:
415:
416: int Lineno = 0;
417:
418: void
419: endmsg()
420: {
421: static int lastline = 0;
422: int len;
423: char *mp, *omp;
424:
425:
426: mvaddch(lastline + Y_MSG_START, SCORE_X, ' ');
427: if (islower((unsigned char)Msgbuf[0]) && Msgbuf[1] != ')')
428: Msgbuf[0] = toupper((unsigned char)Msgbuf[0]);
429: mp = Msgbuf;
430: len = strlen(mp);
431: if (len / MSG_X + Lineno >= MSG_Y) {
432: while (Lineno < MSG_Y) {
433: wmove(Msgwin, Lineno++, 0);
434: wclrtoeol(Msgwin);
435: }
436: Lineno = 0;
437: }
438: mvaddch(Lineno + Y_MSG_START, SCORE_X, '*');
439: lastline = Lineno;
440: do {
441: mvwaddstr(Msgwin, Lineno, 0, mp);
442: if ((len = strlen(mp)) > MSG_X) {
443: omp = mp;
444: for (mp = &mp[MSG_X - 1]; *mp != ' '; mp--)
445: continue;
446: while (*mp == ' ')
447: mp--;
448: mp++;
449: wmove(Msgwin, Lineno, mp - omp);
450: wclrtoeol(Msgwin);
451: }
452: if (++Lineno >= MSG_Y)
453: Lineno = 0;
454: } while (len > MSG_X);
455: wclrtoeol(Msgwin);
456: Mpos = len;
457: Newpos = 0;
458: wrefresh(Msgwin);
459: refresh();
460: wrefresh(Msgwin);
461: }
462:
463:
464:
465:
466:
467: void
468: do_wait()
469: {
470: static const char prompt[] = {'-', '-', 'M', 'o', 'r', 'e', '-', '-', '\0'};
471:
472: if ((int)(Mpos + sizeof prompt) < MSG_X)
473: wmove(Msgwin, Lineno > 0 ? Lineno - 1 : MSG_Y - 1, Mpos);
474: else {
475: mvwaddch(Msgwin, Lineno, 0, ' ');
476: wclrtoeol(Msgwin);
477: if (++Lineno >= MSG_Y)
478: Lineno = 0;
479: }
480: waddstr(Msgwin, prompt);
481: wrefresh(Msgwin);
482: wait_for(' ');
483: }
484:
485:
486:
487:
488:
489: void
490: wait_for(ch)
491: int ch;
492: {
493: char c;
494:
495: if (ch == '\n')
496: while ((c = readchar()) != '\n')
497: continue;
498: else
499: while (readchar() != ch)
500: continue;
501: }
502:
503:
504:
505:
506:
507: int
508: readchar()
509: {
510: int cnt;
511: char c;
512:
513: over:
514: cnt = 0;
515: while (read(STDIN_FILENO, &c, sizeof(char)) <= 0)
516: if (cnt++ > 100) {
517: bye();
518: exit(1);
519: }
520: if (c == CTRL('L')) {
521: wrefresh(curscr);
522: goto over;
523: }
524: if (c == '\r')
525: return ('\n');
526: else
527: return (c);
528: }
529:
530:
531:
532:
533:
534:
535: char *
536: getline()
537: {
538: char *sp;
539: int c, oy, ox;
540: WINDOW *oscr;
541:
542: oscr = stdscr;
543: stdscr = Msgwin;
544: getyx(stdscr, oy, ox);
545: refresh();
546:
547: for (sp = linebuf; (c = readchar()) != '\n'; clrtoeol(), refresh()) {
548: if (c == -1)
549: continue;
550: else
551: if (c == erasechar()) {
552: if (sp > linebuf) {
553: int i;
554:
555: sp--;
556: for (i = strlen(unctrl(*sp)); i; i--)
557: addch('\b');
558: }
559: continue;
560: } else
561: if (c == killchar()) {
562:
563: sp = linebuf;
564: move(oy, ox);
565: continue;
566: } else
567: if (sp == linebuf && c == ' ')
568: continue;
569: if (sp >= &linebuf[LINESIZE - 1] || !(isprint(c) || c == ' '))
570: putchar(CTRL('G'));
571: else {
572: if (islower(c))
573: c = toupper(c);
574: *sp++ = c;
575: addstr(unctrl(c));
576: Mpos++;
577: }
578: }
579: *sp = '\0';
580: stdscr = oscr;