xref: /csrg-svn/games/cribbage/io.c (revision 8073)
17872Sarnold # include	<curses.h>
27872Sarnold # include	<ctype.h>
37872Sarnold # include	<unctrl.h>
47872Sarnold # include	"deck.h"
57872Sarnold # include	"cribbage.h"
67709Sarnold 
77872Sarnold # define	LINESIZE		128
87709Sarnold 
97872Sarnold # define	CTRL(X)			('X' - 'A' + 1)
107709Sarnold 
117872Sarnold # ifndef	attron
127872Sarnold #	define	erasechar()	_tty.sg_erase
137872Sarnold #	define	killchar()	_tty.sg_kill
147872Sarnold # endif		attron
157872Sarnold 
167709Sarnold char		linebuf[ LINESIZE ];
177709Sarnold 
187709Sarnold char		*rankname[ RANKS ]	= { "ACE", "TWO", "THREE", "FOUR",
197872Sarnold 					    "FIVE", "SIX", "SEVEN", "EIGHT",
207872Sarnold 					    "NINE", "TEN", "JACK", "QUEEN",
217872Sarnold 					    "KING" };
227709Sarnold 
237709Sarnold char            *rankchar[ RANKS ]      = { "A", "2", "3", "4", "5", "6", "7",
247872Sarnold 					    "8", "9", "T", "J", "Q", "K" };
257709Sarnold 
267709Sarnold char            *suitname[ SUITS ]      = { "SPADES", "HEARTS", "DIAMONDS",
277872Sarnold 					    "CLUBS" };
287709Sarnold 
297709Sarnold char            *suitchar[ SUITS ]      = { "S", "H", "D", "C" };
307709Sarnold 
317709Sarnold 
327709Sarnold 
337709Sarnold /*
347872Sarnold  * msgcard:
357872Sarnold  *	Call msgcrd in one of two forms
367709Sarnold  */
377872Sarnold msgcard(c, brief)
387872Sarnold CARD		c;
397872Sarnold BOOLEAN		brief;
407709Sarnold {
417872Sarnold 	if (brief)
427872Sarnold 		return msgcrd(c, TRUE, (char *) NULL, TRUE);
437872Sarnold 	else
447872Sarnold 		return msgcrd(c, FALSE, " of ", FALSE);
457709Sarnold }
467709Sarnold 
477709Sarnold 
487709Sarnold 
497709Sarnold /*
507872Sarnold  * msgcrd:
517872Sarnold  *	Print the value of a card in ascii
527709Sarnold  */
537872Sarnold msgcrd(c, brfrank, mid, brfsuit)
547872Sarnold CARD		c;
557872Sarnold char		*mid;
567872Sarnold BOOLEAN		brfrank,  brfsuit;
577872Sarnold {
587872Sarnold 	if (c.rank == EMPTY || c.suit == EMPTY)
597872Sarnold 	    return FALSE;
607872Sarnold 	if (brfrank)
617872Sarnold 	    addmsg("%1.1s", rankchar[c.rank]);
627872Sarnold 	else
637872Sarnold 	    addmsg(rankname[c.rank]);
647872Sarnold 	if (mid != NULL)
657872Sarnold 	    addmsg(mid);
667872Sarnold 	if (brfsuit)
677872Sarnold 	    addmsg("%1.1s", suitchar[c.suit]);
687872Sarnold 	else
697872Sarnold 	    addmsg(suitname[c.suit]);
707872Sarnold 	return TRUE;
717872Sarnold }
727709Sarnold 
737872Sarnold /*
747872Sarnold  * printcard:
757872Sarnold  *	Print out a card.
767872Sarnold  */
77*8073Sarnold printcard(win, cardno, c, blank)
787872Sarnold WINDOW		*win;
797872Sarnold int		cardno;
807872Sarnold CARD		c;
81*8073Sarnold BOOLEAN		blank;
827872Sarnold {
83*8073Sarnold 	prcard(win, cardno * 2, cardno, c, blank);
847872Sarnold }
857709Sarnold 
867872Sarnold /*
877872Sarnold  * prcard:
887872Sarnold  *	Print out a card on the window at the specified location
897872Sarnold  */
907946Sarnold prcard(win, y, x, c, blank)
917872Sarnold WINDOW		*win;
927872Sarnold int		y, x;
937872Sarnold CARD		c;
947946Sarnold BOOLEAN		blank;
957709Sarnold {
967872Sarnold 	if (c.rank == EMPTY)
977872Sarnold 	    return;
987872Sarnold 	mvwaddstr(win, y + 0, x, "+-----+");
997872Sarnold 	mvwaddstr(win, y + 1, x, "|     |");
1007872Sarnold 	mvwaddstr(win, y + 2, x, "|     |");
1017872Sarnold 	mvwaddstr(win, y + 3, x, "|     |");
1027872Sarnold 	mvwaddstr(win, y + 4, x, "+-----+");
1037946Sarnold 	if (!blank) {
1047946Sarnold 		mvwaddch(win, y + 1, x + 1, rankchar[c.rank][0]);
1057946Sarnold 		waddch(win, suitchar[c.suit][0]);
1067946Sarnold 		mvwaddch(win, y + 3, x + 4, rankchar[c.rank][0]);
1077946Sarnold 		waddch(win, suitchar[c.suit][0]);
1087946Sarnold 	}
1097709Sarnold }
1107709Sarnold 
1117709Sarnold /*
1127872Sarnold  * prhand:
1137872Sarnold  *	Print a hand of n cards
1147709Sarnold  */
115*8073Sarnold prhand(h, n, win, blank)
1167872Sarnold CARD		h[];
1177872Sarnold int		n;
1187872Sarnold WINDOW		*win;
119*8073Sarnold BOOLEAN		blank;
1207709Sarnold {
1217872Sarnold 	register int	i;
1227709Sarnold 
1237872Sarnold 	werase(win);
1247872Sarnold 	for (i = 0; i < n; i++)
125*8073Sarnold 	    printcard(win, i, *h++, blank);
1267872Sarnold 	wrefresh(win);
1277709Sarnold }
1287709Sarnold 
1297709Sarnold 
1307709Sarnold 
1317709Sarnold /*
1327872Sarnold  * infrom:
1337872Sarnold  *	reads a card, supposedly in hand, accepting unambigous brief
1347872Sarnold  *	input, returns the index of the card found...
1357709Sarnold  */
1367872Sarnold infrom(hand, n, prompt)
1377872Sarnold CARD		hand[];
1387872Sarnold int		n;
1397872Sarnold char		*prompt;
1407709Sarnold {
1417872Sarnold 	register int           i, j;
1427872Sarnold 	CARD                    crd;
1437709Sarnold 
1447872Sarnold 	if (n < 1) {
1457872Sarnold 	    printf("\nINFROM: %d = n < 1!!\n", n);
1467872Sarnold 	    exit(74);
1477872Sarnold 	}
1487872Sarnold 	for (;;) {
1497947Sarnold 	    msg(prompt);
1507872Sarnold 	    if (incard(&crd)) {			/* if card is full card */
1517872Sarnold 		if (!isone(crd, hand, n))
1527872Sarnold 		    msg("That's not in your hand");
1537872Sarnold 		else {
1547872Sarnold 		    for (i = 0; i < n; i++)
1557872Sarnold 			if (hand[i].rank == crd.rank &&
1567872Sarnold 			    hand[i].suit == crd.suit)
1577872Sarnold 				break;
1587872Sarnold 		    if (i >= n) {
1597872Sarnold 			printf("\nINFROM: isone or something messed up\n");
1607872Sarnold 			exit(77);
1617872Sarnold 		    }
1627872Sarnold 		    return i;
1637872Sarnold 		}
1647872Sarnold 	    }
1657872Sarnold 	    else				/* if not full card... */
1667872Sarnold 		if (crd.rank != EMPTY) {
1677872Sarnold 		    for (i = 0; i < n; i++)
1687872Sarnold 			if (hand[i].rank == crd.rank)
1697872Sarnold 				break;
1707872Sarnold 		    if (i >= n)
1717872Sarnold 			msg("No such rank in your hand");
1727872Sarnold 		    else {
1737872Sarnold 			for (j = i + 1; j < n; j++)
1747872Sarnold 			    if (hand[j].rank == crd.rank)
1757872Sarnold 				break;
1767872Sarnold 			if (j < n)
1777872Sarnold 			    msg("Ambiguous rank");
1787872Sarnold 			else
1797872Sarnold 			    return i;
1807872Sarnold 		    }
1817872Sarnold 		}
1827872Sarnold 		else
1837872Sarnold 		    msg("Sorry, I missed that");
1847872Sarnold 	}
1857872Sarnold 	/* NOTREACHED */
1867709Sarnold }
1877709Sarnold 
1887709Sarnold 
1897709Sarnold 
1907709Sarnold /*
1917872Sarnold  * incard:
1927872Sarnold  *	Inputs a card in any format.  It reads a line ending with a CR
1937872Sarnold  *	and then parses it.
1947709Sarnold  */
1957872Sarnold incard(crd)
1967872Sarnold CARD		*crd;
1977709Sarnold {
1987872Sarnold 	char		*getline();
1997872Sarnold 	register int	i;
2007872Sarnold 	int		rnk, sut;
2017872Sarnold 	char		*line, *p, *p1;
2027872Sarnold 	BOOLEAN		retval;
2037709Sarnold 
2047872Sarnold 	retval = FALSE;
2057872Sarnold 	rnk = sut = EMPTY;
2067872Sarnold 	if (!(line = getline()))
2077872Sarnold 		goto gotit;
2087872Sarnold 	p = p1 = line;
2097872Sarnold 	while(  *p1 != ' '  &&  *p1 != NULL  )  ++p1;
2107872Sarnold 	*p1++ = NULL;
2117872Sarnold 	if(  *p == NULL  )  goto  gotit;
2127872Sarnold 			/* IMPORTANT: no real card has 2 char first name */
2137872Sarnold 	if(  strlen(p) == 2  )  {               /* check for short form */
2147872Sarnold 	    rnk = EMPTY;
2157872Sarnold 	    for( i = 0; i < RANKS; i++ )  {
2167872Sarnold 		if(  *p == *rankchar[i]  )  {
2177872Sarnold 		    rnk = i;
2187872Sarnold 		    break;
2197872Sarnold 		}
2207872Sarnold 	    }
2217872Sarnold 	    if(  rnk == EMPTY  )  goto  gotit;     /* it's nothing... */
2227872Sarnold 	    ++p;                                /* advance to next char */
2237872Sarnold 	    sut = EMPTY;
2247872Sarnold 	    for( i = 0; i < SUITS; i++ )  {
2257872Sarnold 		if(  *p == *suitchar[i]  )  {
2267872Sarnold 		    sut = i;
2277872Sarnold 		    break;
2287872Sarnold 		}
2297872Sarnold 	    }
2307872Sarnold 	    if(  sut != EMPTY  )  retval = TRUE;
2317872Sarnold 	    goto  gotit;
2327872Sarnold 	}
2337872Sarnold 	rnk = EMPTY;
2347872Sarnold 	for( i = 0; i < RANKS; i++ )  {
2357872Sarnold 	    if(  !strcmp( p, rankname[i] )  ||  !strcmp( p, rankchar[i] )  )  {
2367872Sarnold 		rnk = i;
2377872Sarnold 		break;
2387872Sarnold 	    }
2397872Sarnold 	}
2407872Sarnold 	if(  rnk == EMPTY  )  goto  gotit;
2417872Sarnold 	p = p1;
2427872Sarnold 	while(  *p1 != ' '  &&  *p1 != NULL  )  ++p1;
2437872Sarnold 	*p1++ = NULL;
2447872Sarnold 	if(  *p == NULL  )  goto  gotit;
2457872Sarnold 	if(  !strcmp( "OF", p )  )  {
2467872Sarnold 	    p = p1;
2477872Sarnold 	    while(  *p1 != ' '  &&  *p1 != NULL  )  ++p1;
2487872Sarnold 	    *p1++ = NULL;
2497872Sarnold 	    if(  *p == NULL  )  goto  gotit;
2507872Sarnold 	}
2517872Sarnold 	sut = EMPTY;
2527872Sarnold 	for( i = 0; i < SUITS; i++ )  {
2537872Sarnold 	    if(  !strcmp( p, suitname[i] )  ||  !strcmp( p, suitchar[i] )  )  {
2547872Sarnold 		sut = i;
2557872Sarnold 		break;
2567872Sarnold 	    }
2577872Sarnold 	}
2587872Sarnold 	if(  sut != EMPTY  )  retval = TRUE;
2597709Sarnold gotit:
2607872Sarnold 	(*crd).rank = rnk;
2617872Sarnold 	(*crd).suit = sut;
2627872Sarnold 	return( retval );
2637709Sarnold }
2647709Sarnold 
2657709Sarnold 
2667709Sarnold 
2677709Sarnold /*
2687872Sarnold  * getuchar:
2697872Sarnold  *	Reads and converts to upper case
2707709Sarnold  */
2717709Sarnold getuchar()
2727709Sarnold {
2737872Sarnold 	register int		c;
2747709Sarnold 
2757872Sarnold 	c = readchar();
2767872Sarnold 	if (islower(c))
2777872Sarnold 	    c = toupper(c);
2787872Sarnold 	addch(c);
2797872Sarnold 	return c;
2807709Sarnold }
2817709Sarnold 
2827709Sarnold /*
2837934Sarnold  * number:
2847934Sarnold  *	Reads in a decimal number and makes sure it is between "lo" and
2857934Sarnold  *	"hi" inclusive.
2867709Sarnold  */
2877934Sarnold number(lo, hi, prompt)
2887934Sarnold int		lo, hi;
2897934Sarnold char		*prompt;
2907709Sarnold {
2917934Sarnold 	char			*getline();
2927934Sarnold 	register char		*p;
2937934Sarnold 	register int		sum;
2947709Sarnold 
2957872Sarnold 	sum = 0;
2967934Sarnold 	for (;;) {
2977934Sarnold 	    msg(prompt);
2987934Sarnold 	    if(!(p = getline()) || *p == NULL) {
2997934Sarnold 		msg(quiet ? "Not a number" : "That doesn't look like a number");
3007934Sarnold 		continue;
3017934Sarnold 	    }
3027872Sarnold 	    sum = 0;
3037934Sarnold 
3047934Sarnold 	    if (!isdigit(*p))
3057872Sarnold 		sum = lo - 1;
3067934Sarnold 	    else
3077934Sarnold 		while (isdigit(*p)) {
3087934Sarnold 		    sum = 10 * sum + (*p - '0');
3097872Sarnold 		    ++p;
3107934Sarnold 		}
3117934Sarnold 
3127934Sarnold 	    if (*p != ' ' && *p != '\t' && *p != NULL)
3137934Sarnold 		sum = lo - 1;
3147934Sarnold 	    if (sum >= lo && sum <= hi)
3157934Sarnold 		return sum;
3167934Sarnold 	    if (sum == lo - 1)
3177934Sarnold 		msg("that doesn't look like a number, try again --> ");
3187934Sarnold 	    else
3197934Sarnold 		msg("%d is not between %d and %d inclusive, try again --> ",
3207934Sarnold 								sum, lo, hi);
3217934Sarnold 	}
3227709Sarnold }
3237709Sarnold 
3247872Sarnold /*
3257872Sarnold  * msg:
3267872Sarnold  *	Display a message at the top of the screen.
3277872Sarnold  */
3287872Sarnold char		Msgbuf[BUFSIZ] = "";
3297709Sarnold 
3307872Sarnold int		Mpos = 0;
3317709Sarnold 
3327872Sarnold static int	Newpos = 0;
3337872Sarnold 
3347872Sarnold /* VARARGS1 */
3357872Sarnold msg(fmt, args)
3367872Sarnold char	*fmt;
3377872Sarnold int	args;
3387872Sarnold {
3397872Sarnold     /*
3407872Sarnold      * if the string is "", just clear the line
3417872Sarnold      */
3427872Sarnold     if (*fmt == '\0') {
3437872Sarnold 	move(LINES - 1, 0);
3447872Sarnold 	clrtoeol();
3457872Sarnold 	Mpos = 0;
3467872Sarnold 	Hasread = TRUE;
3477872Sarnold 	return;
3487872Sarnold     }
3497872Sarnold     /*
3507872Sarnold      * otherwise add to the message and flush it out
3517872Sarnold      */
3527872Sarnold     doadd(fmt, &args);
3537872Sarnold     endmsg();
3547872Sarnold }
3557872Sarnold 
3567709Sarnold /*
3577872Sarnold  * addmsg:
3587872Sarnold  *	Add things to the current message
3597709Sarnold  */
3607872Sarnold /* VARARGS1 */
3617872Sarnold addmsg(fmt, args)
3627872Sarnold char	*fmt;
3637872Sarnold int	args;
3647872Sarnold {
3657872Sarnold     doadd(fmt, &args);
3667872Sarnold }
3677709Sarnold 
3687872Sarnold /*
3697872Sarnold  * endmsg:
3707872Sarnold  *	Display a new msg (giving him a chance to see the previous one
3717872Sarnold  *	if it is up there with the --More--)
3727872Sarnold  */
3737872Sarnold endmsg()
3747709Sarnold {
3757872Sarnold     if (!Hasread) {
3767872Sarnold 	move(LINES - 1, Mpos);
3777872Sarnold 	addstr("--More--");
3787872Sarnold 	refresh();
3797872Sarnold 	wait_for(' ');
3807872Sarnold     }
3817872Sarnold     /*
3827872Sarnold      * All messages should start with uppercase, except ones that
3837872Sarnold      * start with a pack addressing character
3847872Sarnold      */
3857872Sarnold     if (islower(Msgbuf[0]) && Msgbuf[1] != ')')
3867872Sarnold 	Msgbuf[0] = toupper(Msgbuf[0]);
3877872Sarnold     mvaddstr(LINES - 1, 0, Msgbuf);
3887872Sarnold     clrtoeol();
3897872Sarnold     Mpos = Newpos;
3907872Sarnold     Newpos = 0;
3917872Sarnold     refresh();
3927872Sarnold     Hasread = FALSE;
3937872Sarnold }
3947709Sarnold 
3957872Sarnold /*
3967872Sarnold  * doadd:
3977872Sarnold  *	Perform an add onto the message buffer
3987872Sarnold  */
3997872Sarnold doadd(fmt, args)
4007872Sarnold char	*fmt;
4017872Sarnold int	*args;
4027872Sarnold {
4037872Sarnold     static FILE	junk;
4047872Sarnold 
4057872Sarnold     /*
4067872Sarnold      * Do the printf into Msgbuf
4077872Sarnold      */
4087872Sarnold     junk._flag = _IOWRT + _IOSTRG;
4097872Sarnold     junk._ptr = &Msgbuf[Newpos];
4107872Sarnold     junk._cnt = 32767;
4117872Sarnold     _doprnt(fmt, args, &junk);
4127872Sarnold     putc('\0', &junk);
4137872Sarnold     Newpos = strlen(Msgbuf);
4147709Sarnold }
4157709Sarnold 
4167872Sarnold /*
4177872Sarnold  * wait_for
4187872Sarnold  *	Sit around until the guy types the right key
4197872Sarnold  */
4207872Sarnold wait_for(ch)
4217872Sarnold register char	ch;
4227872Sarnold {
4237872Sarnold     register char	c;
4247709Sarnold 
4257872Sarnold     if (ch == '\n')
4267872Sarnold 	while ((c = readchar()) != '\n')
4277872Sarnold 	    continue;
4287872Sarnold     else
4297872Sarnold 	while (readchar() != ch)
4307872Sarnold 	    continue;
4317872Sarnold }
4327709Sarnold 
4337872Sarnold /*
4347872Sarnold  * readchar:
4357872Sarnold  *	Reads and returns a character, checking for gross input errors
4367872Sarnold  */
4377872Sarnold readchar()
4387872Sarnold {
4397872Sarnold     register int	cnt, y, x;
4407872Sarnold     auto char		c;
4417709Sarnold 
4427872Sarnold over:
4437872Sarnold     cnt = 0;
4447872Sarnold     while (read(0, &c, 1) <= 0)
4457872Sarnold 	if (cnt++ > 100)	/* if we are getting infinite EOFs */
4467872Sarnold 	    bye();		/* quit the game */
4477872Sarnold     if (c == CTRL(L)) {
4487872Sarnold 	wrefresh(curscr);
4497872Sarnold 	goto over;
4507872Sarnold     }
4517872Sarnold     Hasread = TRUE;
4527872Sarnold     if (c == '\r')
4537872Sarnold 	return '\n';
4547872Sarnold     else
4557872Sarnold 	return c;
4567872Sarnold }
4577872Sarnold 
4587872Sarnold /*
4597872Sarnold  * getline:
4607872Sarnold  *      Reads the next line up to '\n' or EOF.  Multiple spaces are
4617872Sarnold  *	compressed to one space; a space is inserted before a ','
4627872Sarnold  */
4637872Sarnold char *
4647872Sarnold getline()
4657872Sarnold {
4667872Sarnold     register char	*sp;
4677872Sarnold     register int	c, oy, ox;
4687872Sarnold 
4697872Sarnold     getyx(stdscr, oy, ox);
4707872Sarnold     refresh();
4717872Sarnold     /*
4727872Sarnold      * loop reading in the string, and put it in a temporary buffer
4737872Sarnold      */
4747872Sarnold     for (sp = linebuf; (c = readchar()) != '\n'; clrtoeol(), refresh()) {
4757872Sarnold 	if (c == -1)
4767872Sarnold 	    continue;
4777872Sarnold 	else if (c == erasechar()) {	/* process erase character */
4787872Sarnold 	    if (sp > linebuf) {
4797872Sarnold 		register int i;
4807872Sarnold 
4817872Sarnold 		sp--;
4827872Sarnold 		for (i = strlen(unctrl(*sp)); i; i--)
4837872Sarnold 		    addch('\b');
4847872Sarnold 	    }
4857872Sarnold 	    continue;
4867872Sarnold 	}
4877872Sarnold 	else if (c == killchar()) {	/* process kill character */
4887872Sarnold 	    sp = linebuf;
4897872Sarnold 	    move(oy, ox);
4907872Sarnold 	    continue;
4917872Sarnold 	}
4927872Sarnold 	else if (sp == linebuf && c == ' ')
4937872Sarnold 	    continue;
4947872Sarnold 	if (sp >= &linebuf[LINESIZE-1] || !(isprint(c) || c == ' '))
4957872Sarnold 	    putchar(CTRL(G));
4967872Sarnold 	else {
4977872Sarnold 	    if (islower(c))
4987872Sarnold 		c = toupper(c);
4997872Sarnold 	    *sp++ = c;
5007872Sarnold 	    addstr(unctrl(c));
5017872Sarnold /*###366 [cc] Mpos undefined %%%*/
5027872Sarnold 	    Mpos++;
5037872Sarnold 	}
5047872Sarnold     }
5057872Sarnold     *sp = '\0';
5067872Sarnold     return linebuf;
5077872Sarnold }
508