xref: /csrg-svn/games/atc/input.c (revision 32472)
132471Sbostic /*
232471Sbostic  * Copyright (c) 1987 by Ed James, UC Berkeley.  All rights reserved.
332471Sbostic  *
432471Sbostic  * Copy permission is hereby granted provided that this notice is
532471Sbostic  * retained on all partial or complete copies.
632471Sbostic  *
732471Sbostic  * For more info on this and all of my stuff, mail edjames@berkeley.edu.
832471Sbostic  */
932471Sbostic 
1032471Sbostic #ifndef lint
11*32472Sbostic static char sccsid[] = "@(#)input.c	5.2 (Berkeley) 10/22/87";
1232471Sbostic #endif not lint
1332471Sbostic 
1432471Sbostic #include "include.h"
1532471Sbostic 
1632471Sbostic #define MAXRULES	6
1732471Sbostic #define MAXDEPTH	15
1832471Sbostic 
1932471Sbostic #define RETTOKEN	'\n'
2032471Sbostic #ifdef SYSV
2132471Sbostic #define CRTOKEN		'\r'
2232471Sbostic #endif
2332471Sbostic #define REDRAWTOKEN	'\014'	/* CTRL(L) */
2432471Sbostic #define	SHELLTOKEN	'!'
2532471Sbostic #define HELPTOKEN	'?'
2632471Sbostic #define ALPHATOKEN	256
2732471Sbostic #define NUMTOKEN	257
2832471Sbostic 
2932471Sbostic typedef struct {
3032471Sbostic 	int	token;
3132471Sbostic 	int	to_state;
3232471Sbostic 	char	*str;
3332471Sbostic 	char	*(*func)();
3432471Sbostic } RULE;
3532471Sbostic 
3632471Sbostic typedef struct {
3732471Sbostic 	int	num_rules;
3832471Sbostic 	RULE	*rule;
3932471Sbostic } STATE;
4032471Sbostic 
4132471Sbostic typedef struct {
4232471Sbostic 	char	str[20];
4332471Sbostic 	int	state;
4432471Sbostic 	int	rule;
4532471Sbostic 	int	ch;
4632471Sbostic 	int	pos;
4732471Sbostic } STACK;
4832471Sbostic 
4932471Sbostic #define T_RULE		stack[level].rule
5032471Sbostic #define T_STATE		stack[level].state
5132471Sbostic #define T_STR		stack[level].str
5232471Sbostic #define T_POS		stack[level].pos
5332471Sbostic #define	T_CH		stack[level].ch
5432471Sbostic 
5532471Sbostic #define NUMELS(a)	(sizeof (a) / sizeof (*(a)))
5632471Sbostic 
5732471Sbostic #define NUMSTATES	NUMELS(st)
5832471Sbostic 
5932471Sbostic char	*setplane(), *circle(), *left(), *right(), *Left(), *Right(),
6032471Sbostic 	*beacon(), *ex_it(), *climb(), *descend(), *setalt(), *setrelalt(),
6132471Sbostic 	*benum(), *to_dir(), *rel_dir(), *delayb(), *mark(), *unmark(),
6232471Sbostic 	*airport(), *turn(), *ignore();
6332471Sbostic 
6432471Sbostic RULE	state0[] = {	{ ALPHATOKEN,	1,	"%c:",		setplane},
6532471Sbostic 			{ RETTOKEN,	-1,	"",		NULL	},
6632471Sbostic #ifdef SYSV
6732471Sbostic 			{ CRTOKEN,	-1,	"",		NULL	},
6832471Sbostic #endif
6932471Sbostic 			{ HELPTOKEN,	12,	" [a-z]<ret>",	NULL	}},
7032471Sbostic 	state1[] = {	{ 't',		2,	" turn",	turn	},
7132471Sbostic 			{ 'a',		3,	" altitude:",	NULL	},
7232471Sbostic 			{ 'c',		4,	" circle",	circle	},
7332471Sbostic 			{ 'm',		7,	" mark",	mark	},
7432471Sbostic 			{ 'u',		7,	" unmark",	unmark	},
7532471Sbostic 			{ 'i',		7,	" ignore",	ignore	},
7632471Sbostic 			{ HELPTOKEN,	12,	" tacmui",	NULL	}},
7732471Sbostic 	state2[] = {	{ 'l',		6,	" left",	left	},
7832471Sbostic 			{ 'r',		6,	" right",	right	},
7932471Sbostic 			{ 'L',		4,	" left 90",	Left	},
8032471Sbostic 			{ 'R',		4,	" right 90",	Right	},
8132471Sbostic 			{ 't',		11,	" towards",	NULL	},
8232471Sbostic 			{ 'w',		4,	" to 0",	to_dir	},
8332471Sbostic 			{ 'e',		4,	" to 45",	to_dir	},
8432471Sbostic 			{ 'd',		4,	" to 90",	to_dir	},
8532471Sbostic 			{ 'c',		4,	" to 135",	to_dir	},
8632471Sbostic 			{ 'x',		4,	" to 180",	to_dir	},
8732471Sbostic 			{ 'z',		4,	" to 225",	to_dir	},
8832471Sbostic 			{ 'a',		4,	" to 270",	to_dir	},
8932471Sbostic 			{ 'q',		4,	" to 315",	to_dir	},
9032471Sbostic 			{ HELPTOKEN,	12,	" lrLRt<dir>",	NULL	}},
9132471Sbostic 	state3[] = {	{ '+',		10,	" climb",	climb	},
9232471Sbostic 			{ 'c',		10,	" climb",	climb	},
9332471Sbostic 			{ '-',		10,	" descend",	descend	},
9432471Sbostic 			{ 'd',		10,	" descend",	descend	},
9532471Sbostic 			{ NUMTOKEN,	7,	" %c000 feet",	setalt	},
9632471Sbostic 			{ HELPTOKEN,	12,	" +-cd[0-9]",	NULL	}},
9732471Sbostic 	state4[] = {	{ '@',		9,	" at",		NULL	},
9832471Sbostic 			{ 'a',		9,	" at",		NULL	},
9932471Sbostic 			{ RETTOKEN,	-1,	"",		NULL	},
10032471Sbostic #ifdef SYSV
10132471Sbostic 			{ CRTOKEN,	-1,	"",		NULL	},
10232471Sbostic #endif
10332471Sbostic 			{ HELPTOKEN,	12,	" @a<ret>",	NULL	}},
10432471Sbostic 	state5[] = {	{ NUMTOKEN,	7,	"%c",		delayb	},
10532471Sbostic 			{ HELPTOKEN,	12,	" [0-9]",	NULL	}},
10632471Sbostic 	state6[] = {	{ '@',		9,	" at",		NULL	},
10732471Sbostic 			{ 'a',		9,	" at",		NULL	},
10832471Sbostic 			{ 'w',		4,	" 0",		rel_dir	},
10932471Sbostic 			{ 'e',		4,	" 45",		rel_dir	},
11032471Sbostic 			{ 'd',		4,	" 90",		rel_dir	},
11132471Sbostic 			{ 'c',		4,	" 135",		rel_dir	},
11232471Sbostic 			{ 'x',		4,	" 180",		rel_dir	},
11332471Sbostic 			{ 'z',		4,	" 225",		rel_dir	},
11432471Sbostic 			{ 'a',		4,	" 270",		rel_dir	},
11532471Sbostic 			{ 'q',		4,	" 315",		rel_dir	},
11632471Sbostic 			{ RETTOKEN,	-1,	"",		NULL	},
11732471Sbostic #ifdef SYSV
11832471Sbostic 			{ CRTOKEN,	-1,	"",		NULL	},
11932471Sbostic #endif
12032471Sbostic 			{ HELPTOKEN,	12,	" @a<dir><ret>",NULL	}},
12132471Sbostic 	state7[] = {	{ RETTOKEN,	-1,	"",		NULL	},
12232471Sbostic #ifdef SYSV
12332471Sbostic 	            	{ CRTOKEN,	-1,	"",		NULL	},
12432471Sbostic #endif
12532471Sbostic 			{ HELPTOKEN,	12,	" <ret>",	NULL	}},
12632471Sbostic 	state8[] = {	{ NUMTOKEN,	4,	"%c",		benum	},
12732471Sbostic 			{ HELPTOKEN,	12,	" [0-9]",	NULL	}},
12832471Sbostic 	state9[] = {	{ 'b',		5,	" beacon #",	NULL	},
12932471Sbostic 			{ '*',		5,	" beacon #",	NULL	},
13032471Sbostic 			{ HELPTOKEN,	12,	" b*",		NULL	}},
13132471Sbostic 	state10[] = {	{ NUMTOKEN,	7,	" %c000 ft",	setrelalt},
13232471Sbostic 			{ HELPTOKEN,	12,	" [0-9]",	NULL	}},
13332471Sbostic 	state11[] = {	{ 'b',		8,	" beacon #",	beacon	},
13432471Sbostic 			{ '*',		8,	" beacon #",	beacon	},
13532471Sbostic 			{ 'e',		8,	" exit #",	ex_it	},
13632471Sbostic 			{ 'a',		8,	" airport #",	airport	},
13732471Sbostic 			{ HELPTOKEN,	12,	" b*ea",	NULL	}},
13832471Sbostic 	state12[] = {	{ -1,		-1,	"",		NULL	}};
13932471Sbostic 
14032471Sbostic #define DEF_STATE(s)	{ NUMELS(s),	(s)	}
14132471Sbostic 
14232471Sbostic STATE	st[] = {
14332471Sbostic 	DEF_STATE(state0), DEF_STATE(state1), DEF_STATE(state2),
14432471Sbostic 	DEF_STATE(state3), DEF_STATE(state4), DEF_STATE(state5),
14532471Sbostic 	DEF_STATE(state6), DEF_STATE(state7), DEF_STATE(state8),
14632471Sbostic 	DEF_STATE(state9), DEF_STATE(state10), DEF_STATE(state11),
14732471Sbostic 	DEF_STATE(state12)
14832471Sbostic };
14932471Sbostic 
15032471Sbostic PLANE	p;
15132471Sbostic STACK	stack[MAXDEPTH];
15232471Sbostic int	level;
15332471Sbostic int	tval;
15432471Sbostic int	dest_type, dest_no, dir;
15532471Sbostic 
15632471Sbostic pop()
15732471Sbostic {
15832471Sbostic 	if (level == 0)
15932471Sbostic 		return (-1);
16032471Sbostic 	level--;
16132471Sbostic 
16232471Sbostic 	ioclrtoeol(T_POS);
16332471Sbostic 
16432471Sbostic 	strcpy(T_STR, "");
16532471Sbostic 	T_RULE = -1;
16632471Sbostic 	T_CH = -1;
16732471Sbostic 	return (0);
16832471Sbostic }
16932471Sbostic 
17032471Sbostic rezero()
17132471Sbostic {
17232471Sbostic 	iomove(0);
17332471Sbostic 
17432471Sbostic 	level = 0;
17532471Sbostic 	T_STATE = 0;
17632471Sbostic 	T_RULE = -1;
17732471Sbostic 	T_CH = -1;
17832471Sbostic 	T_POS = 0;
17932471Sbostic 	strcpy(T_STR, "");
18032471Sbostic }
18132471Sbostic 
18232471Sbostic push(ruleno, ch)
18332471Sbostic {
18432471Sbostic 	int	newstate, newpos;
18532471Sbostic 
186*32472Sbostic 	(void)sprintf(T_STR, st[T_STATE].rule[ruleno].str, tval);
18732471Sbostic 	T_RULE = ruleno;
18832471Sbostic 	T_CH = ch;
18932471Sbostic 	newstate = st[T_STATE].rule[ruleno].to_state;
19032471Sbostic 	newpos = T_POS + strlen(T_STR);
19132471Sbostic 
19232471Sbostic 	ioaddstr(T_POS, T_STR);
19332471Sbostic 
19432471Sbostic 	if (level == 0)
19532471Sbostic 		ioclrtobot();
19632471Sbostic 	level++;
19732471Sbostic 	T_STATE = newstate;
19832471Sbostic 	T_POS = newpos;
19932471Sbostic 	T_RULE = -1;
20032471Sbostic 	strcpy(T_STR, "");
20132471Sbostic }
20232471Sbostic 
20332471Sbostic getcommand()
20432471Sbostic {
20532471Sbostic 	int	c, i, done;
20632471Sbostic 	char	*s, *(*func)();
20732471Sbostic 	PLANE	*pp;
20832471Sbostic 
20932471Sbostic 	rezero();
21032471Sbostic 
21132471Sbostic 	do {
21232471Sbostic 		c = gettoken();
21332471Sbostic 		if (c == tty_new.sg_erase) {
21432471Sbostic 			if (pop() < 0)
21532471Sbostic 				noise();
21632471Sbostic 		} else if (c == tty_new.sg_kill) {
21732471Sbostic 			while (pop() >= 0)
21832471Sbostic 				;
21932471Sbostic 		} else {
22032471Sbostic 			done = 0;
22132471Sbostic 			for (i = 0; i < st[T_STATE].num_rules; i++) {
22232471Sbostic 				if (st[T_STATE].rule[i].token == c ||
22332471Sbostic 				    st[T_STATE].rule[i].token == tval) {
22432471Sbostic 					push(i, (c >= ALPHATOKEN) ? tval : c);
22532471Sbostic 					done = 1;
22632471Sbostic 					break;
22732471Sbostic 				}
22832471Sbostic 			}
22932471Sbostic 			if (!done)
23032471Sbostic 				noise();
23132471Sbostic 		}
23232471Sbostic 	} while (T_STATE != -1);
23332471Sbostic 
23432471Sbostic 	if (level == 1)
23532471Sbostic 		return (1);	/* forced update */
23632471Sbostic 
23732471Sbostic 	dest_type = T_NODEST;
23832471Sbostic 
23932471Sbostic 	for (i = 0; i < level; i++) {
24032471Sbostic 		func = st[stack[i].state].rule[stack[i].rule].func;
24132471Sbostic 		if (func != NULL)
24232471Sbostic 			if ((s = (*func)(stack[i].ch)) != NULL) {
24332471Sbostic 				ioerror(stack[i].pos, strlen(stack[i].str), s);
24432471Sbostic 				return (-1);
24532471Sbostic 			}
24632471Sbostic 	}
24732471Sbostic 
24832471Sbostic 	pp = findplane(p.plane_no);
24932471Sbostic 	if (pp->new_altitude != p.new_altitude)
25032471Sbostic 		pp->new_altitude = p.new_altitude;
25132471Sbostic 	else if (pp->status != p.status)
25232471Sbostic 		pp->status = p.status;
25332471Sbostic 	else {
25432471Sbostic 		pp->new_dir = p.new_dir;
25532471Sbostic 		pp->delayd = p.delayd;
25632471Sbostic 		pp->delayd_no = p.delayd_no;
25732471Sbostic 	}
25832471Sbostic 	return (0);
25932471Sbostic }
26032471Sbostic 
26132471Sbostic noise()
26232471Sbostic {
26332471Sbostic 	putchar('\07');
26432471Sbostic 	fflush(stdout);
26532471Sbostic }
26632471Sbostic 
26732471Sbostic gettoken()
26832471Sbostic {
26932471Sbostic 	while ((tval = getAChar()) == REDRAWTOKEN || tval == SHELLTOKEN)
27032471Sbostic 	{
27132471Sbostic 		if (tval == SHELLTOKEN)
27232471Sbostic 		{
27332471Sbostic #ifdef BSD
27432471Sbostic 			struct itimerval	itv;
27532471Sbostic 			itv.it_value.tv_sec = 0;
27632471Sbostic 			itv.it_value.tv_usec = 0;
27732471Sbostic 			setitimer(ITIMER_REAL, &itv, NULL);
27832471Sbostic #endif
27932471Sbostic #ifdef SYSV
28032471Sbostic 			int aval;
28132471Sbostic 			aval = alarm(0);
28232471Sbostic #endif
28332471Sbostic 			if (fork() == 0)	/* child */
28432471Sbostic 			{
28532471Sbostic 				char *shell, *base, *getenv(), *strrchr();
28632471Sbostic 
28732471Sbostic 				setuid(getuid()); /* turn off setuid bit */
28832471Sbostic 				done_screen();
28932471Sbostic 
29032471Sbostic 						 /* run user's favorite shell */
29132471Sbostic 				if ((shell = getenv("SHELL")) != NULL)
29232471Sbostic 				{
29332471Sbostic 					base = strrchr(shell, '/');
29432471Sbostic 					if (base == NULL)
29532471Sbostic 						base = shell;
29632471Sbostic 					else
29732471Sbostic 						base++;
29832471Sbostic 					execl(shell, base, 0);
29932471Sbostic 				}
30032471Sbostic 				else
30132471Sbostic 					execl("/bin/sh", "sh", 0);
30232471Sbostic 
30332471Sbostic 				exit(0);	/* oops */
30432471Sbostic 			}
30532471Sbostic 
30632471Sbostic 			wait(0);
30732471Sbostic #ifdef BSD
30832471Sbostic 			ioctl(fileno(stdin), TIOCSETP, &tty_new);
30932471Sbostic 			itv.it_value.tv_sec = 0;
31032471Sbostic 			itv.it_value.tv_usec = 1;
31132471Sbostic 			itv.it_interval.tv_sec = sp->update_secs;
31232471Sbostic 			itv.it_interval.tv_usec = 0;
31332471Sbostic 			setitimer(ITIMER_REAL, &itv, NULL);
31432471Sbostic #endif
31532471Sbostic #ifdef SYSV
31632471Sbostic 			ioctl(fileno(stdin), TCSETAW, &tty_new);
31732471Sbostic 			alarm(aval);
31832471Sbostic #endif
31932471Sbostic 		}
32032471Sbostic 		redraw();
32132471Sbostic 	}
32232471Sbostic 
32332471Sbostic 	if (isdigit(tval))
32432471Sbostic 		return (NUMTOKEN);
32532471Sbostic 	else if (isalpha(tval))
32632471Sbostic 		return (ALPHATOKEN);
32732471Sbostic 	else
32832471Sbostic 		return (tval);
32932471Sbostic }
33032471Sbostic 
33132471Sbostic char	*
33232471Sbostic setplane(c)
33332471Sbostic {
33432471Sbostic 	PLANE	*pp;
33532471Sbostic 
33632471Sbostic 	pp = findplane(number(c));
33732471Sbostic 	if (pp == NULL)
33832471Sbostic 		return ("Unknown Plane");
33932471Sbostic 	bcopy(pp, &p, sizeof (p));
34032471Sbostic 	p.delayd = 0;
34132471Sbostic 	return (NULL);
34232471Sbostic }
34332471Sbostic 
34432471Sbostic char	*
34532471Sbostic turn(c)
34632471Sbostic {
34732471Sbostic 	if (p.altitude == 0)
34832471Sbostic 		return ("Planes at airports may not change direction");
34932471Sbostic 	return (NULL);
35032471Sbostic }
35132471Sbostic 
35232471Sbostic char	*
35332471Sbostic circle(c)
35432471Sbostic {
35532471Sbostic 	if (p.altitude == 0)
35632471Sbostic 		return ("Planes cannot circle on the ground");
35732471Sbostic 	p.new_dir = MAXDIR;
35832471Sbostic 	return (NULL);
35932471Sbostic }
36032471Sbostic 
36132471Sbostic char	*
36232471Sbostic left(c)
36332471Sbostic {
36432471Sbostic 	dir = D_LEFT;
36532471Sbostic 	p.new_dir = p.dir - 1;
36632471Sbostic 	if (p.new_dir < 0)
36732471Sbostic 		p.new_dir += MAXDIR;
36832471Sbostic 	return (NULL);
36932471Sbostic }
37032471Sbostic 
37132471Sbostic char	*
37232471Sbostic right(c)
37332471Sbostic {
37432471Sbostic 	dir = D_RIGHT;
37532471Sbostic 	p.new_dir = p.dir + 1;
37632471Sbostic 	if (p.new_dir > MAXDIR)
37732471Sbostic 		p.new_dir -= MAXDIR;
37832471Sbostic 	return (NULL);
37932471Sbostic }
38032471Sbostic 
38132471Sbostic char	*
38232471Sbostic Left(c)
38332471Sbostic {
38432471Sbostic 	p.new_dir = p.dir - 2;
38532471Sbostic 	if (p.new_dir < 0)
38632471Sbostic 		p.new_dir += MAXDIR;
38732471Sbostic 	return (NULL);
38832471Sbostic }
38932471Sbostic 
39032471Sbostic char	*
39132471Sbostic Right(c)
39232471Sbostic {
39332471Sbostic 	p.new_dir = p.dir + 2;
39432471Sbostic 	if (p.new_dir > MAXDIR)
39532471Sbostic 		p.new_dir -= MAXDIR;
39632471Sbostic 	return (NULL);
39732471Sbostic }
39832471Sbostic 
39932471Sbostic char	*
40032471Sbostic delayb(c)
40132471Sbostic {
40232471Sbostic 	int	xdiff, ydiff;
40332471Sbostic 
40432471Sbostic 	c -= '0';
40532471Sbostic 
40632471Sbostic 	if (c >= sp->num_beacons)
40732471Sbostic 		return ("Unknown beacon");
40832471Sbostic 	xdiff = sp->beacon[c].x - p.xpos;
40932471Sbostic 	xdiff = SGN(xdiff);
41032471Sbostic 	ydiff = sp->beacon[c].y - p.ypos;
41132471Sbostic 	ydiff = SGN(ydiff);
41232471Sbostic 	if (xdiff != displacement[p.dir].dx || ydiff != displacement[p.dir].dy)
41332471Sbostic 		return ("Beacon is not in flight path");
41432471Sbostic 	p.delayd = 1;
41532471Sbostic 	p.delayd_no = c;
41632471Sbostic 
41732471Sbostic 	if (dest_type != T_NODEST) {
41832471Sbostic 		switch (dest_type) {
41932471Sbostic 		case T_BEACON:
42032471Sbostic 			xdiff = sp->beacon[dest_no].x - sp->beacon[c].x;
42132471Sbostic 			ydiff = sp->beacon[dest_no].y - sp->beacon[c].y;
42232471Sbostic 			break;
42332471Sbostic 		case T_EXIT:
42432471Sbostic 			xdiff = sp->exit[dest_no].x - sp->beacon[c].x;
42532471Sbostic 			ydiff = sp->exit[dest_no].y - sp->beacon[c].y;
42632471Sbostic 			break;
42732471Sbostic 		case T_AIRPORT:
42832471Sbostic 			xdiff = sp->airport[dest_no].x - sp->beacon[c].x;
42932471Sbostic 			ydiff = sp->airport[dest_no].y - sp->beacon[c].y;
43032471Sbostic 			break;
43132471Sbostic 		default:
43232471Sbostic 			return ("Bad case in delayb!  Get help!");
43332471Sbostic 			break;
43432471Sbostic 		}
43532471Sbostic 		if (xdiff == 0 && ydiff == 0)
43632471Sbostic 			return ("Would already be there");
43732471Sbostic 		p.new_dir = DIR_FROM_DXDY(xdiff, ydiff);
43832471Sbostic 		if (p.new_dir == p.dir)
43932471Sbostic 			return ("Already going in that direction");
44032471Sbostic 	}
44132471Sbostic 	return (NULL);
44232471Sbostic }
44332471Sbostic 
44432471Sbostic char	*
44532471Sbostic beacon(c)
44632471Sbostic {
44732471Sbostic 	dest_type = T_BEACON;
44832471Sbostic 	return (NULL);
44932471Sbostic }
45032471Sbostic 
45132471Sbostic char	*
45232471Sbostic ex_it(c)
45332471Sbostic {
45432471Sbostic 	dest_type = T_EXIT;
45532471Sbostic 	return (NULL);
45632471Sbostic }
45732471Sbostic 
45832471Sbostic char	*
45932471Sbostic airport(c)
46032471Sbostic {
46132471Sbostic 	dest_type = T_AIRPORT;
46232471Sbostic 	return (NULL);
46332471Sbostic }
46432471Sbostic 
46532471Sbostic char	*
46632471Sbostic climb(c)
46732471Sbostic {
46832471Sbostic 	dir = D_UP;
46932471Sbostic 	return (NULL);
47032471Sbostic }
47132471Sbostic 
47232471Sbostic char	*
47332471Sbostic descend(c)
47432471Sbostic {
47532471Sbostic 	dir = D_DOWN;
47632471Sbostic 	return (NULL);
47732471Sbostic }
47832471Sbostic 
47932471Sbostic char	*
48032471Sbostic setalt(c)
48132471Sbostic {
48232471Sbostic 	if ((p.altitude == c - '0') && (p.new_altitude == p.altitude))
48332471Sbostic 		return ("Already at that altitude");
48432471Sbostic 	p.new_altitude = c - '0';
48532471Sbostic 	return (NULL);
48632471Sbostic }
48732471Sbostic 
48832471Sbostic char	*
48932471Sbostic setrelalt(c)
49032471Sbostic {
49132471Sbostic 	if (c == 0)
49232471Sbostic 		return ("altitude not changed");
49332471Sbostic 
49432471Sbostic 	switch (dir) {
49532471Sbostic 	case D_UP:
49632471Sbostic 		p.new_altitude = p.altitude + c - '0';
49732471Sbostic 		break;
49832471Sbostic 	case D_DOWN:
49932471Sbostic 		p.new_altitude = p.altitude - (c - '0');
50032471Sbostic 		break;
50132471Sbostic 	default:
50232471Sbostic 		return ("Unknown case in setrelalt!  Get help!");
50332471Sbostic 		break;
50432471Sbostic 	}
50532471Sbostic 	if (p.new_altitude < 0)
50632471Sbostic 		return ("Altitude would be too low");
50732471Sbostic 	else if (p.new_altitude > 9)
50832471Sbostic 		return ("Altitude would be too high");
50932471Sbostic 	return (NULL);
51032471Sbostic }
51132471Sbostic 
51232471Sbostic char	*
51332471Sbostic benum(c)
51432471Sbostic {
51532471Sbostic 	dest_no = c -= '0';
51632471Sbostic 
51732471Sbostic 	switch (dest_type) {
51832471Sbostic 	case T_BEACON:
51932471Sbostic 		if (c >= sp->num_beacons)
52032471Sbostic 			return ("Unknown beacon");
52132471Sbostic 		p.new_dir = DIR_FROM_DXDY(sp->beacon[c].x - p.xpos,
52232471Sbostic 			sp->beacon[c].y - p.ypos);
52332471Sbostic 		break;
52432471Sbostic 	case T_EXIT:
52532471Sbostic 		if (c >= sp->num_exits)
52632471Sbostic 			return ("Unknown exit");
52732471Sbostic 		p.new_dir = DIR_FROM_DXDY(sp->exit[c].x - p.xpos,
52832471Sbostic 			sp->exit[c].y - p.ypos);
52932471Sbostic 		break;
53032471Sbostic 	case T_AIRPORT:
53132471Sbostic 		if (c >= sp->num_airports)
53232471Sbostic 			return ("Unknown airport");
53332471Sbostic 		p.new_dir = DIR_FROM_DXDY(sp->airport[c].x - p.xpos,
53432471Sbostic 			sp->airport[c].y - p.ypos);
53532471Sbostic 		break;
53632471Sbostic 	default:
53732471Sbostic 		return ("Unknown case in benum!  Get help!");
53832471Sbostic 		break;
53932471Sbostic 	}
54032471Sbostic 	return (NULL);
54132471Sbostic }
54232471Sbostic 
54332471Sbostic char	*
54432471Sbostic to_dir(c)
54532471Sbostic {
54632471Sbostic 	p.new_dir = dir_no(c);
54732471Sbostic 	return (NULL);
54832471Sbostic }
54932471Sbostic 
55032471Sbostic char	*
55132471Sbostic rel_dir(c)
55232471Sbostic {
55332471Sbostic 	int	angle;
55432471Sbostic 
55532471Sbostic 	angle = dir_no(c);
55632471Sbostic 	switch (dir) {
55732471Sbostic 	case D_LEFT:
55832471Sbostic 		p.new_dir = p.dir - angle;
55932471Sbostic 		if (p.new_dir < 0)
56032471Sbostic 			p.new_dir += MAXDIR;
56132471Sbostic 		break;
56232471Sbostic 	case D_RIGHT:
56332471Sbostic 		p.new_dir = p.dir + angle;
56432471Sbostic 		if (p.new_dir >= MAXDIR)
56532471Sbostic 			p.new_dir -= MAXDIR;
56632471Sbostic 		break;
56732471Sbostic 	default:
56832471Sbostic 		return ("Bizarre direction in rel_dir!  Get help!");
56932471Sbostic 		break;
57032471Sbostic 	}
57132471Sbostic 	return (NULL);
57232471Sbostic }
57332471Sbostic 
57432471Sbostic char	*
57532471Sbostic mark(c)
57632471Sbostic {
57732471Sbostic 	if (p.altitude == 0)
57832471Sbostic 		return ("Cannot mark planes on the ground");
57932471Sbostic 	if (p.status == S_MARKED)
58032471Sbostic 		return ("Already marked");
58132471Sbostic 	p.status = S_MARKED;
58232471Sbostic 	return (NULL);
58332471Sbostic }
58432471Sbostic 
58532471Sbostic char	*
58632471Sbostic unmark(c)
58732471Sbostic {
58832471Sbostic 	if (p.altitude == 0)
58932471Sbostic 		return ("Cannot unmark planes on the ground");
59032471Sbostic 	if (p.status == S_UNMARKED)
59132471Sbostic 		return ("Already unmarked");
59232471Sbostic 	p.status = S_UNMARKED;
59332471Sbostic 	return (NULL);
59432471Sbostic }
59532471Sbostic 
59632471Sbostic char	*
59732471Sbostic ignore(c)
59832471Sbostic {
59932471Sbostic 	if (p.altitude == 0)
60032471Sbostic 		return ("Cannot ignore planes on the ground");
60132471Sbostic 	if (p.status == S_IGNORED)
60232471Sbostic 		return ("Already ignored");
60332471Sbostic 	p.status = S_IGNORED;
60432471Sbostic 	return (NULL);
60532471Sbostic }
60632471Sbostic 
60732471Sbostic dir_no(ch)
60832471Sbostic 	char	ch;
60932471Sbostic {
61032471Sbostic 	int	dir;
61132471Sbostic 
61232471Sbostic 	switch (ch) {
61332471Sbostic 	case 'w':	dir = 0;	break;
61432471Sbostic 	case 'e':	dir = 1;	break;
61532471Sbostic 	case 'd':	dir = 2;	break;
61632471Sbostic 	case 'c':	dir = 3;	break;
61732471Sbostic 	case 'x':	dir = 4;	break;
61832471Sbostic 	case 'z':	dir = 5;	break;
61932471Sbostic 	case 'a':	dir = 6;	break;
62032471Sbostic 	case 'q':	dir = 7;	break;
62132471Sbostic 	default:
62232471Sbostic 		fprintf(stderr, "bad character in dir_no\n");
62332471Sbostic 		break;
62432471Sbostic 	}
62532471Sbostic 	return (dir);
62632471Sbostic }
627