xref: /csrg-svn/games/cribbage/io.c (revision 7872)
1*7872Sarnold # include	<curses.h>
2*7872Sarnold # include	<ctype.h>
3*7872Sarnold # include	<unctrl.h>
4*7872Sarnold # include	"deck.h"
5*7872Sarnold # include	"cribbage.h"
67709Sarnold 
7*7872Sarnold # define	LINESIZE		128
87709Sarnold 
9*7872Sarnold # define	CTRL(X)			('X' - 'A' + 1)
107709Sarnold 
11*7872Sarnold # ifndef	attron
12*7872Sarnold #	define	erasechar()	_tty.sg_erase
13*7872Sarnold #	define	killchar()	_tty.sg_kill
14*7872Sarnold # endif		attron
15*7872Sarnold 
167709Sarnold char		linebuf[ LINESIZE ];
177709Sarnold 
187709Sarnold char		*rankname[ RANKS ]	= { "ACE", "TWO", "THREE", "FOUR",
19*7872Sarnold 					    "FIVE", "SIX", "SEVEN", "EIGHT",
20*7872Sarnold 					    "NINE", "TEN", "JACK", "QUEEN",
21*7872Sarnold 					    "KING" };
227709Sarnold 
237709Sarnold char            *rankchar[ RANKS ]      = { "A", "2", "3", "4", "5", "6", "7",
24*7872Sarnold 					    "8", "9", "T", "J", "Q", "K" };
257709Sarnold 
267709Sarnold char            *suitname[ SUITS ]      = { "SPADES", "HEARTS", "DIAMONDS",
27*7872Sarnold 					    "CLUBS" };
287709Sarnold 
297709Sarnold char            *suitchar[ SUITS ]      = { "S", "H", "D", "C" };
307709Sarnold 
317709Sarnold 
327709Sarnold 
337709Sarnold /*
34*7872Sarnold  * msgcard:
35*7872Sarnold  *	Call msgcrd in one of two forms
367709Sarnold  */
37*7872Sarnold msgcard(c, brief)
38*7872Sarnold CARD		c;
39*7872Sarnold BOOLEAN		brief;
407709Sarnold {
41*7872Sarnold 	if (brief)
42*7872Sarnold 		return msgcrd(c, TRUE, (char *) NULL, TRUE);
43*7872Sarnold 	else
44*7872Sarnold 		return msgcrd(c, FALSE, " of ", FALSE);
457709Sarnold }
467709Sarnold 
477709Sarnold 
487709Sarnold 
497709Sarnold /*
50*7872Sarnold  * msgcrd:
51*7872Sarnold  *	Print the value of a card in ascii
527709Sarnold  */
53*7872Sarnold msgcrd(c, brfrank, mid, brfsuit)
54*7872Sarnold CARD		c;
55*7872Sarnold char		*mid;
56*7872Sarnold BOOLEAN		brfrank,  brfsuit;
57*7872Sarnold {
58*7872Sarnold 	if (c.rank == EMPTY || c.suit == EMPTY)
59*7872Sarnold 	    return FALSE;
60*7872Sarnold 	if (brfrank)
61*7872Sarnold 	    addmsg("%1.1s", rankchar[c.rank]);
62*7872Sarnold 	else
63*7872Sarnold 	    addmsg(rankname[c.rank]);
64*7872Sarnold 	if (mid != NULL)
65*7872Sarnold 	    addmsg(mid);
66*7872Sarnold 	if (brfsuit)
67*7872Sarnold 	    addmsg("%1.1s", suitchar[c.suit]);
68*7872Sarnold 	else
69*7872Sarnold 	    addmsg(suitname[c.suit]);
70*7872Sarnold 	return TRUE;
71*7872Sarnold }
727709Sarnold 
73*7872Sarnold /*
74*7872Sarnold  * printcard:
75*7872Sarnold  *	Print out a card.
76*7872Sarnold  */
77*7872Sarnold printcard(win, cardno, c)
78*7872Sarnold WINDOW		*win;
79*7872Sarnold int		cardno;
80*7872Sarnold CARD		c;
81*7872Sarnold {
82*7872Sarnold 	prcard(win, cardno * 2, cardno, c);
83*7872Sarnold }
847709Sarnold 
85*7872Sarnold /*
86*7872Sarnold  * prcard:
87*7872Sarnold  *	Print out a card on the window at the specified location
88*7872Sarnold  */
89*7872Sarnold prcard(win, y, x, c)
90*7872Sarnold WINDOW		*win;
91*7872Sarnold int		y, x;
92*7872Sarnold CARD		c;
937709Sarnold {
94*7872Sarnold 	if (c.rank == EMPTY)
95*7872Sarnold 	    return;
96*7872Sarnold 	mvwaddstr(win, y + 0, x, "+-----+");
97*7872Sarnold 	mvwaddstr(win, y + 1, x, "|     |");
98*7872Sarnold 	mvwaddstr(win, y + 2, x, "|     |");
99*7872Sarnold 	mvwaddstr(win, y + 3, x, "|     |");
100*7872Sarnold 	mvwaddstr(win, y + 4, x, "+-----+");
101*7872Sarnold 	mvwaddch(win, y + 1, x + 1, rankchar[c.rank][0]);
102*7872Sarnold 	waddch(win, suitchar[c.suit][0]);
103*7872Sarnold 	mvwaddch(win, y + 3, x + 4, rankchar[c.rank][0]);
104*7872Sarnold 	waddch(win, suitchar[c.suit][0]);
1057709Sarnold }
1067709Sarnold 
1077709Sarnold /*
108*7872Sarnold  * prhand:
109*7872Sarnold  *	Print a hand of n cards
1107709Sarnold  */
111*7872Sarnold prhand(h, n, win)
112*7872Sarnold CARD		h[];
113*7872Sarnold int		n;
114*7872Sarnold WINDOW		*win;
1157709Sarnold {
116*7872Sarnold 	register int	i;
1177709Sarnold 
118*7872Sarnold 	werase(win);
119*7872Sarnold 	for (i = 0; i < n; i++)
120*7872Sarnold 	    printcard(win, i, h[i]);
121*7872Sarnold 	wrefresh(win);
1227709Sarnold }
1237709Sarnold 
1247709Sarnold 
1257709Sarnold 
1267709Sarnold /*
127*7872Sarnold  * infrom:
128*7872Sarnold  *	reads a card, supposedly in hand, accepting unambigous brief
129*7872Sarnold  *	input, returns the index of the card found...
1307709Sarnold  */
131*7872Sarnold infrom(hand, n, prompt)
132*7872Sarnold CARD		hand[];
133*7872Sarnold int		n;
134*7872Sarnold char		*prompt;
1357709Sarnold {
136*7872Sarnold 	register int           i, j;
137*7872Sarnold 	CARD                    crd;
1387709Sarnold 
139*7872Sarnold 	if (n < 1) {
140*7872Sarnold 	    printf("\nINFROM: %d = n < 1!!\n", n);
141*7872Sarnold 	    exit(74);
142*7872Sarnold 	}
143*7872Sarnold 	for (;;) {
144*7872Sarnold 	    if (incard(&crd)) {			/* if card is full card */
145*7872Sarnold 		if (!isone(crd, hand, n))
146*7872Sarnold 		    msg("That's not in your hand");
147*7872Sarnold 		else {
148*7872Sarnold 		    for (i = 0; i < n; i++)
149*7872Sarnold 			if (hand[i].rank == crd.rank &&
150*7872Sarnold 			    hand[i].suit == crd.suit)
151*7872Sarnold 				break;
152*7872Sarnold 		    if (i >= n) {
153*7872Sarnold 			printf("\nINFROM: isone or something messed up\n");
154*7872Sarnold 			exit(77);
155*7872Sarnold 		    }
156*7872Sarnold 		    return i;
157*7872Sarnold 		}
158*7872Sarnold 	    }
159*7872Sarnold 	    else				/* if not full card... */
160*7872Sarnold 		if (crd.rank != EMPTY) {
161*7872Sarnold 		    for (i = 0; i < n; i++)
162*7872Sarnold 			if (hand[i].rank == crd.rank)
163*7872Sarnold 				break;
164*7872Sarnold 		    if (i >= n)
165*7872Sarnold 			msg("No such rank in your hand");
166*7872Sarnold 		    else {
167*7872Sarnold 			for (j = i + 1; j < n; j++)
168*7872Sarnold 			    if (hand[j].rank == crd.rank)
169*7872Sarnold 				break;
170*7872Sarnold 			if (j < n)
171*7872Sarnold 			    msg("Ambiguous rank");
172*7872Sarnold 			else
173*7872Sarnold 			    return i;
174*7872Sarnold 		    }
175*7872Sarnold 		}
176*7872Sarnold 		else
177*7872Sarnold 		    msg("Sorry, I missed that");
178*7872Sarnold 	    msg(prompt);
179*7872Sarnold 	}
180*7872Sarnold 	/* NOTREACHED */
1817709Sarnold }
1827709Sarnold 
1837709Sarnold 
1847709Sarnold 
1857709Sarnold /*
186*7872Sarnold  * incard:
187*7872Sarnold  *	Inputs a card in any format.  It reads a line ending with a CR
188*7872Sarnold  *	and then parses it.
1897709Sarnold  */
190*7872Sarnold incard(crd)
191*7872Sarnold CARD		*crd;
1927709Sarnold {
193*7872Sarnold 	char		*getline();
194*7872Sarnold 	register int	i;
195*7872Sarnold 	int		rnk, sut;
196*7872Sarnold 	char		*line, *p, *p1;
197*7872Sarnold 	BOOLEAN		retval;
1987709Sarnold 
199*7872Sarnold 	retval = FALSE;
200*7872Sarnold 	rnk = sut = EMPTY;
201*7872Sarnold 	if (!(line = getline()))
202*7872Sarnold 		goto gotit;
203*7872Sarnold 	p = p1 = line;
204*7872Sarnold 	while(  *p1 != ' '  &&  *p1 != NULL  )  ++p1;
205*7872Sarnold 	*p1++ = NULL;
206*7872Sarnold 	if(  *p == NULL  )  goto  gotit;
207*7872Sarnold 			/* IMPORTANT: no real card has 2 char first name */
208*7872Sarnold 	if(  strlen(p) == 2  )  {               /* check for short form */
209*7872Sarnold 	    rnk = EMPTY;
210*7872Sarnold 	    for( i = 0; i < RANKS; i++ )  {
211*7872Sarnold 		if(  *p == *rankchar[i]  )  {
212*7872Sarnold 		    rnk = i;
213*7872Sarnold 		    break;
214*7872Sarnold 		}
215*7872Sarnold 	    }
216*7872Sarnold 	    if(  rnk == EMPTY  )  goto  gotit;     /* it's nothing... */
217*7872Sarnold 	    ++p;                                /* advance to next char */
218*7872Sarnold 	    sut = EMPTY;
219*7872Sarnold 	    for( i = 0; i < SUITS; i++ )  {
220*7872Sarnold 		if(  *p == *suitchar[i]  )  {
221*7872Sarnold 		    sut = i;
222*7872Sarnold 		    break;
223*7872Sarnold 		}
224*7872Sarnold 	    }
225*7872Sarnold 	    if(  sut != EMPTY  )  retval = TRUE;
226*7872Sarnold 	    goto  gotit;
227*7872Sarnold 	}
228*7872Sarnold 	rnk = EMPTY;
229*7872Sarnold 	for( i = 0; i < RANKS; i++ )  {
230*7872Sarnold 	    if(  !strcmp( p, rankname[i] )  ||  !strcmp( p, rankchar[i] )  )  {
231*7872Sarnold 		rnk = i;
232*7872Sarnold 		break;
233*7872Sarnold 	    }
234*7872Sarnold 	}
235*7872Sarnold 	if(  rnk == EMPTY  )  goto  gotit;
236*7872Sarnold 	p = p1;
237*7872Sarnold 	while(  *p1 != ' '  &&  *p1 != NULL  )  ++p1;
238*7872Sarnold 	*p1++ = NULL;
239*7872Sarnold 	if(  *p == NULL  )  goto  gotit;
240*7872Sarnold 	if(  !strcmp( "OF", p )  )  {
241*7872Sarnold 	    p = p1;
242*7872Sarnold 	    while(  *p1 != ' '  &&  *p1 != NULL  )  ++p1;
243*7872Sarnold 	    *p1++ = NULL;
244*7872Sarnold 	    if(  *p == NULL  )  goto  gotit;
245*7872Sarnold 	}
246*7872Sarnold 	sut = EMPTY;
247*7872Sarnold 	for( i = 0; i < SUITS; i++ )  {
248*7872Sarnold 	    if(  !strcmp( p, suitname[i] )  ||  !strcmp( p, suitchar[i] )  )  {
249*7872Sarnold 		sut = i;
250*7872Sarnold 		break;
251*7872Sarnold 	    }
252*7872Sarnold 	}
253*7872Sarnold 	if(  sut != EMPTY  )  retval = TRUE;
2547709Sarnold gotit:
255*7872Sarnold 	(*crd).rank = rnk;
256*7872Sarnold 	(*crd).suit = sut;
257*7872Sarnold 	return( retval );
2587709Sarnold }
2597709Sarnold 
2607709Sarnold 
2617709Sarnold 
2627709Sarnold /*
263*7872Sarnold  * getuchar:
264*7872Sarnold  *	Reads and converts to upper case
2657709Sarnold  */
2667709Sarnold getuchar()
2677709Sarnold {
268*7872Sarnold 	register int		c;
2697709Sarnold 
270*7872Sarnold 	c = readchar();
271*7872Sarnold 	if (islower(c))
272*7872Sarnold 	    c = toupper(c);
273*7872Sarnold 	addch(c);
274*7872Sarnold 	return c;
2757709Sarnold }
2767709Sarnold 
2777709Sarnold 
2787709Sarnold 
2797709Sarnold /*
2807709Sarnold  * number reads in a decimal number and makes sure it is between
2817709Sarnold  * lo and hi inclusive
2827709Sarnold  * a cr counts as lo
2837709Sarnold  */
2847709Sarnold 
2857709Sarnold number( lo, hi )
2867709Sarnold 
2877709Sarnold     int         lo, hi;
2887709Sarnold {
289*7872Sarnold 	char                    *getline();
290*7872Sarnold 	register  char          *p;
291*7872Sarnold 	register  int            sum;
2927709Sarnold 
293*7872Sarnold 	sum = 0;
294*7872Sarnold 	do  {
295*7872Sarnold 	    if(  !( p = getline() )  )  return( lo );   /* no line = lo */
296*7872Sarnold 	    if(  *p == NULL  )  return( lo );
297*7872Sarnold 	    sum = 0;
298*7872Sarnold 	    while(  *p == ' '  ||  *p == '\t'  )  ++p;
299*7872Sarnold 	    if(  *p < '0'  ||  *p > '9'  )  {
300*7872Sarnold 		sum = lo - 1;
301*7872Sarnold 	    }
302*7872Sarnold 	    else  {
303*7872Sarnold 		do  {
304*7872Sarnold 		    sum = 10*sum + (*p - '0');
305*7872Sarnold 		    ++p;
306*7872Sarnold 		}  while(  '0' <= *p  &&  *p <= '9'  );
307*7872Sarnold 	    }
308*7872Sarnold 	    if(  *p != ' '  &&  *p != '\t'  &&  *p != NULL  )  sum = lo - 1;
309*7872Sarnold 	    if(  sum >= lo  &&  sum <= hi  )  break;
310*7872Sarnold 	    if(  sum == lo - 1  )  {
311*7872Sarnold 		printf( "that doesn't look like a number, try again --> " );
312*7872Sarnold 	    }
313*7872Sarnold 	    else  {
314*7872Sarnold 		printf( "%d is not between %d and %d inclusive, try again --> ",
315*7872Sarnold 								sum, lo, hi );
316*7872Sarnold 	    }
317*7872Sarnold 	}  while( TRUE );
318*7872Sarnold 	return( sum );
3197709Sarnold }
3207709Sarnold 
321*7872Sarnold /*
322*7872Sarnold  * msg:
323*7872Sarnold  *	Display a message at the top of the screen.
324*7872Sarnold  */
325*7872Sarnold char		Msgbuf[BUFSIZ] = "";
3267709Sarnold 
327*7872Sarnold int		Mpos = 0;
3287709Sarnold 
329*7872Sarnold static int	Newpos = 0;
330*7872Sarnold 
331*7872Sarnold /* VARARGS1 */
332*7872Sarnold msg(fmt, args)
333*7872Sarnold char	*fmt;
334*7872Sarnold int	args;
335*7872Sarnold {
336*7872Sarnold     /*
337*7872Sarnold      * if the string is "", just clear the line
338*7872Sarnold      */
339*7872Sarnold     if (*fmt == '\0') {
340*7872Sarnold 	move(LINES - 1, 0);
341*7872Sarnold 	clrtoeol();
342*7872Sarnold 	Mpos = 0;
343*7872Sarnold 	Hasread = TRUE;
344*7872Sarnold 	return;
345*7872Sarnold     }
346*7872Sarnold     /*
347*7872Sarnold      * otherwise add to the message and flush it out
348*7872Sarnold      */
349*7872Sarnold     doadd(fmt, &args);
350*7872Sarnold     endmsg();
351*7872Sarnold }
352*7872Sarnold 
3537709Sarnold /*
354*7872Sarnold  * addmsg:
355*7872Sarnold  *	Add things to the current message
3567709Sarnold  */
357*7872Sarnold /* VARARGS1 */
358*7872Sarnold addmsg(fmt, args)
359*7872Sarnold char	*fmt;
360*7872Sarnold int	args;
361*7872Sarnold {
362*7872Sarnold     doadd(fmt, &args);
363*7872Sarnold }
3647709Sarnold 
365*7872Sarnold /*
366*7872Sarnold  * endmsg:
367*7872Sarnold  *	Display a new msg (giving him a chance to see the previous one
368*7872Sarnold  *	if it is up there with the --More--)
369*7872Sarnold  */
370*7872Sarnold endmsg()
3717709Sarnold {
372*7872Sarnold     if (!Hasread) {
373*7872Sarnold 	move(LINES - 1, Mpos);
374*7872Sarnold 	addstr("--More--");
375*7872Sarnold 	refresh();
376*7872Sarnold 	wait_for(' ');
377*7872Sarnold     }
378*7872Sarnold     /*
379*7872Sarnold      * All messages should start with uppercase, except ones that
380*7872Sarnold      * start with a pack addressing character
381*7872Sarnold      */
382*7872Sarnold     if (islower(Msgbuf[0]) && Msgbuf[1] != ')')
383*7872Sarnold 	Msgbuf[0] = toupper(Msgbuf[0]);
384*7872Sarnold     mvaddstr(LINES - 1, 0, Msgbuf);
385*7872Sarnold     clrtoeol();
386*7872Sarnold     Mpos = Newpos;
387*7872Sarnold     Newpos = 0;
388*7872Sarnold     refresh();
389*7872Sarnold     Hasread = FALSE;
390*7872Sarnold }
3917709Sarnold 
392*7872Sarnold /*
393*7872Sarnold  * doadd:
394*7872Sarnold  *	Perform an add onto the message buffer
395*7872Sarnold  */
396*7872Sarnold doadd(fmt, args)
397*7872Sarnold char	*fmt;
398*7872Sarnold int	*args;
399*7872Sarnold {
400*7872Sarnold     static FILE	junk;
401*7872Sarnold 
402*7872Sarnold     /*
403*7872Sarnold      * Do the printf into Msgbuf
404*7872Sarnold      */
405*7872Sarnold     junk._flag = _IOWRT + _IOSTRG;
406*7872Sarnold     junk._ptr = &Msgbuf[Newpos];
407*7872Sarnold     junk._cnt = 32767;
408*7872Sarnold     _doprnt(fmt, args, &junk);
409*7872Sarnold     putc('\0', &junk);
410*7872Sarnold     Newpos = strlen(Msgbuf);
4117709Sarnold }
4127709Sarnold 
413*7872Sarnold /*
414*7872Sarnold  * wait_for
415*7872Sarnold  *	Sit around until the guy types the right key
416*7872Sarnold  */
417*7872Sarnold wait_for(ch)
418*7872Sarnold register char	ch;
419*7872Sarnold {
420*7872Sarnold     register char	c;
4217709Sarnold 
422*7872Sarnold     if (ch == '\n')
423*7872Sarnold 	while ((c = readchar()) != '\n')
424*7872Sarnold 	    continue;
425*7872Sarnold     else
426*7872Sarnold 	while (readchar() != ch)
427*7872Sarnold 	    continue;
428*7872Sarnold }
4297709Sarnold 
430*7872Sarnold /*
431*7872Sarnold  * readchar:
432*7872Sarnold  *	Reads and returns a character, checking for gross input errors
433*7872Sarnold  */
434*7872Sarnold readchar()
435*7872Sarnold {
436*7872Sarnold     register int	cnt, y, x;
437*7872Sarnold     auto char		c;
4387709Sarnold 
439*7872Sarnold over:
440*7872Sarnold     cnt = 0;
441*7872Sarnold     while (read(0, &c, 1) <= 0)
442*7872Sarnold 	if (cnt++ > 100)	/* if we are getting infinite EOFs */
443*7872Sarnold 	    bye();		/* quit the game */
444*7872Sarnold     if (c == CTRL(L)) {
445*7872Sarnold 	wrefresh(curscr);
446*7872Sarnold 	goto over;
447*7872Sarnold     }
448*7872Sarnold     Hasread = TRUE;
449*7872Sarnold     if (c == '\r')
450*7872Sarnold 	return '\n';
451*7872Sarnold     else
452*7872Sarnold 	return c;
453*7872Sarnold }
454*7872Sarnold 
455*7872Sarnold /*
456*7872Sarnold  * getline:
457*7872Sarnold  *      Reads the next line up to '\n' or EOF.  Multiple spaces are
458*7872Sarnold  *	compressed to one space; a space is inserted before a ','
459*7872Sarnold  */
460*7872Sarnold char *
461*7872Sarnold getline()
462*7872Sarnold {
463*7872Sarnold     register char	*sp;
464*7872Sarnold     register int	c, oy, ox;
465*7872Sarnold 
466*7872Sarnold     getyx(stdscr, oy, ox);
467*7872Sarnold     refresh();
468*7872Sarnold     /*
469*7872Sarnold      * loop reading in the string, and put it in a temporary buffer
470*7872Sarnold      */
471*7872Sarnold     for (sp = linebuf; (c = readchar()) != '\n'; clrtoeol(), refresh()) {
472*7872Sarnold 	if (c == -1)
473*7872Sarnold 	    continue;
474*7872Sarnold 	else if (c == erasechar()) {	/* process erase character */
475*7872Sarnold 	    if (sp > linebuf) {
476*7872Sarnold 		register int i;
477*7872Sarnold 
478*7872Sarnold 		sp--;
479*7872Sarnold 		for (i = strlen(unctrl(*sp)); i; i--)
480*7872Sarnold 		    addch('\b');
481*7872Sarnold 	    }
482*7872Sarnold 	    continue;
483*7872Sarnold 	}
484*7872Sarnold 	else if (c == killchar()) {	/* process kill character */
485*7872Sarnold 	    sp = linebuf;
486*7872Sarnold 	    move(oy, ox);
487*7872Sarnold 	    continue;
488*7872Sarnold 	}
489*7872Sarnold 	else if (sp == linebuf && c == ' ')
490*7872Sarnold 	    continue;
491*7872Sarnold 	if (sp >= &linebuf[LINESIZE-1] || !(isprint(c) || c == ' '))
492*7872Sarnold 	    putchar(CTRL(G));
493*7872Sarnold 	else {
494*7872Sarnold 	    if (islower(c))
495*7872Sarnold 		c = toupper(c);
496*7872Sarnold 	    *sp++ = c;
497*7872Sarnold 	    addstr(unctrl(c));
498*7872Sarnold /*###366 [cc] Mpos undefined %%%*/
499*7872Sarnold 	    Mpos++;
500*7872Sarnold 	}
501*7872Sarnold     }
502*7872Sarnold     *sp = '\0';
503*7872Sarnold     return linebuf;
504*7872Sarnold }
505