|
|
1.1 root 1: static char *sccsid = "@(#)io.c 1.13 (Berkeley) 9/26/83";
2:
3: # include <curses.h>
4: # include <ctype.h>
5: # include <signal.h>
6: # include "deck.h"
7: # include "cribbage.h"
8: # include "cribcur.h"
9:
10: # define LINESIZE 128
11:
12: # ifdef CTRL
13: # undef CTRL
14: # endif
15: # define CTRL(X) ('X' - 'A' + 1)
16:
17: # ifndef attron
18: # define erasechar() _tty.sg_erase
19: # define killchar() _tty.sg_kill
20: # endif attron
21:
22: char linebuf[ LINESIZE ];
23:
24: char *rankname[ RANKS ] = { "ACE", "TWO", "THREE", "FOUR",
25: "FIVE", "SIX", "SEVEN", "EIGHT",
26: "NINE", "TEN", "JACK", "QUEEN",
27: "KING" };
28:
29: char *rankchar[ RANKS ] = { "A", "2", "3", "4", "5", "6", "7",
30: "8", "9", "T", "J", "Q", "K" };
31:
32: char *suitname[ SUITS ] = { "SPADES", "HEARTS", "DIAMONDS",
33: "CLUBS" };
34:
35: char *suitchar[ SUITS ] = { "S", "H", "D", "C" };
36:
37:
38:
39: /*
40: * msgcard:
41: * Call msgcrd in one of two forms
42: */
43: msgcard(c, brief)
44: CARD c;
45: BOOLEAN brief;
46: {
47: if (brief)
48: return msgcrd(c, TRUE, (char *) NULL, TRUE);
49: else
50: return msgcrd(c, FALSE, " of ", FALSE);
51: }
52:
53:
54:
55: /*
56: * msgcrd:
57: * Print the value of a card in ascii
58: */
59: msgcrd(c, brfrank, mid, brfsuit)
60: CARD c;
61: char *mid;
62: BOOLEAN brfrank, brfsuit;
63: {
64: if (c.rank == EMPTY || c.suit == EMPTY)
65: return FALSE;
66: if (brfrank)
67: addmsg("%1.1s", rankchar[c.rank]);
68: else
69: addmsg(rankname[c.rank]);
70: if (mid != NULL)
71: addmsg(mid);
72: if (brfsuit)
73: addmsg("%1.1s", suitchar[c.suit]);
74: else
75: addmsg(suitname[c.suit]);
76: return TRUE;
77: }
78:
79: /*
80: * printcard:
81: * Print out a card.
82: */
83: printcard(win, cardno, c, blank)
84: WINDOW *win;
85: int cardno;
86: CARD c;
87: BOOLEAN blank;
88: {
89: prcard(win, cardno * 2, cardno, c, blank);
90: }
91:
92: /*
93: * prcard:
94: * Print out a card on the window at the specified location
95: */
96: prcard(win, y, x, c, blank)
97: WINDOW *win;
98: int y, x;
99: CARD c;
100: BOOLEAN blank;
101: {
102: if (c.rank == EMPTY)
103: return;
104: mvwaddstr(win, y + 0, x, "+-----+");
105: mvwaddstr(win, y + 1, x, "| |");
106: mvwaddstr(win, y + 2, x, "| |");
107: mvwaddstr(win, y + 3, x, "| |");
108: mvwaddstr(win, y + 4, x, "+-----+");
109: if (!blank) {
110: mvwaddch(win, y + 1, x + 1, rankchar[c.rank][0]);
111: waddch(win, suitchar[c.suit][0]);
112: mvwaddch(win, y + 3, x + 4, rankchar[c.rank][0]);
113: waddch(win, suitchar[c.suit][0]);
114: }
115: }
116:
117: /*
118: * prhand:
119: * Print a hand of n cards
120: */
121: prhand(h, n, win, blank)
122: CARD h[];
123: int n;
124: WINDOW *win;
125: BOOLEAN blank;
126: {
127: register int i;
128:
129: werase(win);
130: for (i = 0; i < n; i++)
131: printcard(win, i, *h++, blank);
132: wrefresh(win);
133: }
134:
135:
136:
137: /*
138: * infrom:
139: * reads a card, supposedly in hand, accepting unambigous brief
140: * input, returns the index of the card found...
141: */
142: infrom(hand, n, prompt)
143: CARD hand[];
144: int n;
145: char *prompt;
146: {
147: register int i, j;
148: CARD crd;
149:
150: if (n < 1) {
151: printf("\nINFROM: %d = n < 1!!\n", n);
152: exit(74);
153: }
154: for (;;) {
155: msg(prompt);
156: if (incard(&crd)) { /* if card is full card */
157: if (!isone(crd, hand, n))
158: msg("That's not in your hand");
159: else {
160: for (i = 0; i < n; i++)
161: if (hand[i].rank == crd.rank &&
162: hand[i].suit == crd.suit)
163: break;
164: if (i >= n) {
165: printf("\nINFROM: isone or something messed up\n");
166: exit(77);
167: }
168: return i;
169: }
170: }
171: else /* if not full card... */
172: if (crd.rank != EMPTY) {
173: for (i = 0; i < n; i++)
174: if (hand[i].rank == crd.rank)
175: break;
176: if (i >= n)
177: msg("No such rank in your hand");
178: else {
179: for (j = i + 1; j < n; j++)
180: if (hand[j].rank == crd.rank)
181: break;
182: if (j < n)
183: msg("Ambiguous rank");
184: else
185: return i;
186: }
187: }
188: else
189: msg("Sorry, I missed that");
190: }
191: /* NOTREACHED */
192: }
193:
194:
195:
196: /*
197: * incard:
198: * Inputs a card in any format. It reads a line ending with a CR
199: * and then parses it.
200: */
201: incard(crd)
202: CARD *crd;
203: {
204: char *getline();
205: register int i;
206: int rnk, sut;
207: char *line, *p, *p1;
208: BOOLEAN retval;
209:
210: retval = FALSE;
211: rnk = sut = EMPTY;
212: if (!(line = getline()))
213: goto gotit;
214: p = p1 = line;
215: while( *p1 != ' ' && *p1 != NULL ) ++p1;
216: *p1++ = NULL;
217: if( *p == NULL ) goto gotit;
218: /* IMPORTANT: no real card has 2 char first name */
219: if( strlen(p) == 2 ) { /* check for short form */
220: rnk = EMPTY;
221: for( i = 0; i < RANKS; i++ ) {
222: if( *p == *rankchar[i] ) {
223: rnk = i;
224: break;
225: }
226: }
227: if( rnk == EMPTY ) goto gotit; /* it's nothing... */
228: ++p; /* advance to next char */
229: sut = EMPTY;
230: for( i = 0; i < SUITS; i++ ) {
231: if( *p == *suitchar[i] ) {
232: sut = i;
233: break;
234: }
235: }
236: if( sut != EMPTY ) retval = TRUE;
237: goto gotit;
238: }
239: rnk = EMPTY;
240: for( i = 0; i < RANKS; i++ ) {
241: if( !strcmp( p, rankname[i] ) || !strcmp( p, rankchar[i] ) ) {
242: rnk = i;
243: break;
244: }
245: }
246: if( rnk == EMPTY ) goto gotit;
247: p = p1;
248: while( *p1 != ' ' && *p1 != NULL ) ++p1;
249: *p1++ = NULL;
250: if( *p == NULL ) goto gotit;
251: if( !strcmp( "OF", p ) ) {
252: p = p1;
253: while( *p1 != ' ' && *p1 != NULL ) ++p1;
254: *p1++ = NULL;
255: if( *p == NULL ) goto gotit;
256: }
257: sut = EMPTY;
258: for( i = 0; i < SUITS; i++ ) {
259: if( !strcmp( p, suitname[i] ) || !strcmp( p, suitchar[i] ) ) {
260: sut = i;
261: break;
262: }
263: }
264: if( sut != EMPTY ) retval = TRUE;
265: gotit:
266: (*crd).rank = rnk;
267: (*crd).suit = sut;
268: return( retval );
269: }
270:
271:
272:
273: /*
274: * getuchar:
275: * Reads and converts to upper case
276: */
277: getuchar()
278: {
279: register int c;
280:
281: c = readchar();
282: if (islower(c))
283: c = toupper(c);
284: waddch(Msgwin, c);
285: return c;
286: }
287:
288: /*
289: * number:
290: * Reads in a decimal number and makes sure it is between "lo" and
291: * "hi" inclusive.
292: */
293: number(lo, hi, prompt)
294: int lo, hi;
295: char *prompt;
296: {
297: char *getline();
298: register char *p;
299: register int sum;
300:
301: sum = 0;
302: for (;;) {
303: msg(prompt);
304: if(!(p = getline()) || *p == NULL) {
305: msg(quiet ? "Not a number" : "That doesn't look like a number");
306: continue;
307: }
308: sum = 0;
309:
310: if (!isdigit(*p))
311: sum = lo - 1;
312: else
313: while (isdigit(*p)) {
314: sum = 10 * sum + (*p - '0');
315: ++p;
316: }
317:
318: if (*p != ' ' && *p != '\t' && *p != NULL)
319: sum = lo - 1;
320: if (sum >= lo && sum <= hi)
321: return sum;
322: if (sum == lo - 1)
323: msg("that doesn't look like a number, try again --> ");
324: else
325: msg("%d is not between %d and %d inclusive, try again --> ",
326: sum, lo, hi);
327: }
328: }
329:
330: /*
331: * msg:
332: * Display a message at the top of the screen.
333: */
334: char Msgbuf[BUFSIZ] = { '\0' };
335:
336: int Mpos = 0;
337:
338: static int Newpos = 0;
339:
340: /* VARARGS1 */
341: msg(fmt, args)
342: char *fmt;
343: int args;
344: {
345: doadd(fmt, &args);
346: endmsg();
347: }
348:
349: /*
350: * addmsg:
351: * Add things to the current message
352: */
353: /* VARARGS1 */
354: addmsg(fmt, args)
355: char *fmt;
356: int args;
357: {
358: doadd(fmt, &args);
359: }
360:
361: /*
362: * endmsg:
363: * Display a new msg.
364: */
365:
366: int Lineno = 0;
367:
368: endmsg()
369: {
370: register int len;
371: register char *mp, *omp;
372: static int lastline = 0;
373:
374: /*
375: * All messages should start with uppercase
376: */
377: mvaddch(lastline + Y_MSG_START, SCORE_X, ' ');
378: if (islower(Msgbuf[0]) && Msgbuf[1] != ')')
379: Msgbuf[0] = toupper(Msgbuf[0]);
380: mp = Msgbuf;
381: len = strlen(mp);
382: if (len / MSG_X + Lineno >= MSG_Y) {
383: while (Lineno < MSG_Y) {
384: wmove(Msgwin, Lineno++, 0);
385: wclrtoeol(Msgwin);
386: }
387: Lineno = 0;
388: }
389: mvaddch(Lineno + Y_MSG_START, SCORE_X, '*');
390: lastline = Lineno;
391: do {
392: mvwaddstr(Msgwin, Lineno, 0, mp);
393: if ((len = strlen(mp)) > MSG_X) {
394: omp = mp;
395: for (mp = &mp[MSG_X-1]; *mp != ' '; mp--)
396: continue;
397: while (*mp == ' ')
398: mp--;
399: mp++;
400: wmove(Msgwin, Lineno, mp - omp);
401: wclrtoeol(Msgwin);
402: }
403: if (++Lineno >= MSG_Y)
404: Lineno = 0;
405: } while (len > MSG_X);
406: wclrtoeol(Msgwin);
407: Mpos = len;
408: Newpos = 0;
409: wrefresh(Msgwin);
410: refresh();
411: wrefresh(Msgwin);
412: }
413:
414: /*
415: * doadd:
416: * Perform an add onto the message buffer
417: */
418: doadd(fmt, args)
419: char *fmt;
420: int *args;
421: {
422: static FILE junk;
423:
424: /*
425: * Do the printf into Msgbuf
426: */
427: junk._flag = _IOWRT + _IOSTRG;
428: junk._ptr = &Msgbuf[Newpos];
429: junk._cnt = 32767;
430: _doprnt(fmt, args, &junk);
431: putc('\0', &junk);
432: Newpos = strlen(Msgbuf);
433: }
434:
435: /*
436: * do_wait:
437: * Wait for the user to type ' ' before doing anything else
438: */
439: do_wait()
440: {
441: register int line;
442: static char prompt[] = { '-', '-', 'M', 'o', 'r', 'e', '-', '-', '\0' };
443:
444: if (Mpos + sizeof prompt < MSG_X)
445: wmove(Msgwin, Lineno > 0 ? Lineno - 1 : MSG_Y - 1, Mpos);
446: else {
447: mvwaddch(Msgwin, Lineno, 0, ' ');
448: wclrtoeol(Msgwin);
449: if (++Lineno >= MSG_Y)
450: Lineno = 0;
451: }
452: waddstr(Msgwin, prompt);
453: wrefresh(Msgwin);
454: wait_for(' ');
455: }
456:
457: /*
458: * wait_for
459: * Sit around until the guy types the right key
460: */
461: wait_for(ch)
462: register char ch;
463: {
464: register char c;
465:
466: if (ch == '\n')
467: while ((c = readchar()) != '\n')
468: continue;
469: else
470: while (readchar() != ch)
471: continue;
472: }
473:
474: /*
475: * readchar:
476: * Reads and returns a character, checking for gross input errors
477: */
478: readchar()
479: {
480: register int cnt, y, x;
481: auto char c;
482:
483: over:
484: cnt = 0;
485: while (read(0, &c, 1) <= 0)
486: if (cnt++ > 100) /* if we are getting infinite EOFs */
487: bye(); /* quit the game */
488: if (c == CTRL(L)) {
489: wrefresh(curscr);
490: goto over;
491: }
492: if (c == '\r')
493: return '\n';
494: else
495: return c;
496: }
497:
498: /*
499: * getline:
500: * Reads the next line up to '\n' or EOF. Multiple spaces are
501: * compressed to one space; a space is inserted before a ','
502: */
503: char *
504: getline()
505: {
506: register char *sp;
507: register int c, oy, ox;
508: register WINDOW *oscr;
509:
510: oscr = stdscr;
511: stdscr = Msgwin;
512: getyx(stdscr, oy, ox);
513: refresh();
514: /*
515: * loop reading in the string, and put it in a temporary buffer
516: */
517: for (sp = linebuf; (c = readchar()) != '\n'; clrtoeol(), refresh()) {
518: if (c == -1)
519: continue;
520: else if (c == erasechar()) { /* process erase character */
521: if (sp > linebuf) {
522: register int i;
523:
524: sp--;
525: for (i = strlen(unctrl(*sp)); i; i--)
526: addch('\b');
527: }
528: continue;
529: }
530: else if (c == killchar()) { /* process kill character */
531: sp = linebuf;
532: move(oy, ox);
533: continue;
534: }
535: else if (sp == linebuf && c == ' ')
536: continue;
537: if (sp >= &linebuf[LINESIZE-1] || !(isprint(c) || c == ' '))
538: putchar(CTRL(G));
539: else {
540: if (islower(c))
541: c = toupper(c);
542: *sp++ = c;
543: addstr(unctrl(c));
544: Mpos++;
545: }
546: }
547: *sp = '\0';
548: stdscr = oscr;
549: return linebuf;
550: }
551:
552: /*
553: * bye:
554: * Leave the program, cleaning things up as we go.
555: */
556: bye()
557: {
558: signal(SIGINT, SIG_IGN);
559: mvcur(0, COLS - 1, LINES - 1, 0);
560: fflush(stdout);
561: endwin();
562: putchar('\n');
563: exit(1);
564: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.