xref: /csrg-svn/games/atc/update.c (revision 33144)
132475Sbostic /*
232475Sbostic  * Copyright (c) 1987 by Ed James, UC Berkeley.  All rights reserved.
332475Sbostic  *
432475Sbostic  * Copy permission is hereby granted provided that this notice is
532475Sbostic  * retained on all partial or complete copies.
632475Sbostic  *
732475Sbostic  * For more info on this and all of my stuff, mail edjames@berkeley.edu.
832475Sbostic  */
932475Sbostic 
1032475Sbostic #ifndef lint
11*33144Sbostic static char sccsid[] = "@(#)update.c	5.3 (Berkeley) 12/26/87";
1232475Sbostic #endif not lint
1332475Sbostic 
1432475Sbostic #include "include.h"
1532475Sbostic 
1632475Sbostic update()
1732475Sbostic {
1832475Sbostic 	int	i, dir_diff, mask, unclean;
1932475Sbostic 	PLANE	*pp, *p1, *p2, *p;
2032475Sbostic 
2132475Sbostic #ifdef BSD
2232475Sbostic 	mask = sigblock(sigmask(SIGINT));
2332475Sbostic #endif
2432475Sbostic #ifdef SYSV
2532475Sbostic 	alarm(0);
2632475Sbostic 	signal(SIGALRM, update);
2732475Sbostic #endif
2832475Sbostic 
2932475Sbostic 	clock++;
3032475Sbostic 
3132475Sbostic 	erase_all();
3232475Sbostic 
3332475Sbostic 	/* put some planes in the air */
3432475Sbostic 	do {
3532475Sbostic 		unclean = 0;
3632475Sbostic 		for (pp = ground.head; pp != NULL; pp = pp->next) {
3732475Sbostic 			if (pp->new_altitude > 0) {
3832475Sbostic 				delete(&ground, pp);
3932475Sbostic 				append(&air, pp);
4032475Sbostic 				unclean = 1;
4132475Sbostic 				break;
4232475Sbostic 			}
4332475Sbostic 		}
4432475Sbostic 	} while (unclean);
4532475Sbostic 
4632475Sbostic 	/* do altitude change and basic movement */
4732475Sbostic 	for (pp = air.head; pp != NULL; pp = pp->next) {
4832475Sbostic 		/* type 0 only move every other turn */
4932475Sbostic 		if (pp->plane_type == 0 && clock & 1)
5032475Sbostic 			continue;
5132475Sbostic 
5232475Sbostic 		pp->fuel--;
5332475Sbostic 		if (pp->fuel < 0)
5432475Sbostic 			loser(pp, "ran out of fuel.");
5532475Sbostic 
5632475Sbostic 		pp->altitude += SGN(pp->new_altitude - pp->altitude);
5732475Sbostic 
5832475Sbostic 		if (!pp->delayd) {
5932475Sbostic 			dir_diff = pp->new_dir - pp->dir;
6032475Sbostic 			/*
6132475Sbostic 			 * Allow for circle commands
6232475Sbostic 			 */
6332475Sbostic 			if (pp->new_dir >= 0 && pp->new_dir < MAXDIR) {
6432475Sbostic 				if (dir_diff > MAXDIR/2)
6532475Sbostic 					dir_diff -= MAXDIR;
6632475Sbostic 				else if (dir_diff < -(MAXDIR/2))
6732475Sbostic 					dir_diff += MAXDIR;
6832475Sbostic 			}
6932475Sbostic 			if (dir_diff > 2)
7032475Sbostic 				dir_diff = 2;
7132475Sbostic 			else if (dir_diff < -2)
7232475Sbostic 				dir_diff = -2;
7332475Sbostic 			pp->dir += dir_diff;
7432475Sbostic 			if (pp->dir >= MAXDIR)
7532475Sbostic 				pp->dir -= MAXDIR;
7632475Sbostic 			else if (pp->dir < 0)
7732475Sbostic 				pp->dir += MAXDIR;
7832475Sbostic 		}
7932475Sbostic 		pp->xpos += displacement[pp->dir].dx;
8032475Sbostic 		pp->ypos += displacement[pp->dir].dy;
8132475Sbostic 
8232475Sbostic 		if (pp->delayd && pp->xpos == sp->beacon[pp->delayd_no].x &&
8332475Sbostic 		    pp->ypos == sp->beacon[pp->delayd_no].y) {
8432475Sbostic 			pp->delayd = 0;
8532475Sbostic 			if (pp->status == S_UNMARKED)
8632475Sbostic 				pp->status = S_MARKED;
8732475Sbostic 		}
8832475Sbostic 
8932475Sbostic 		switch (pp->dest_type) {
9032475Sbostic 		case T_AIRPORT:
9132475Sbostic 			if (pp->xpos == sp->airport[pp->dest_no].x &&
9232475Sbostic 			    pp->ypos == sp->airport[pp->dest_no].y &&
9332475Sbostic 			    pp->altitude == 0) {
9432475Sbostic 				if (pp->dir != sp->airport[pp->dest_no].dir)
9532475Sbostic 				    loser(pp, "landed in the wrong direction.");
9632475Sbostic 				else {
9732475Sbostic 				    pp->status = S_GONE;
9832475Sbostic 				    continue;
9932475Sbostic 				}
10032475Sbostic 			}
10132475Sbostic 			break;
10232475Sbostic 		case T_EXIT:
10332475Sbostic 			if (pp->xpos == sp->exit[pp->dest_no].x &&
10432475Sbostic 			    pp->ypos == sp->exit[pp->dest_no].y) {
10532475Sbostic 			    	if (pp->altitude != 9)
10632475Sbostic 				    loser(pp, "exited at the wrong altitude.");
10732475Sbostic 				else {
10832475Sbostic 				    pp->status = S_GONE;
10932475Sbostic 				    continue;
11032475Sbostic 				}
11132475Sbostic 			}
11232475Sbostic 			break;
11332475Sbostic 		default:
11432475Sbostic 			loser(pp, "has a bizarre destination, get help!");
11532475Sbostic 		}
11632475Sbostic 		if (pp->altitude > 9)
11732475Sbostic 			/* "this is impossible" */
11832475Sbostic 			loser(pp, "exceded flight ceiling.");
11932475Sbostic 		if (pp->altitude <= 0) {
12032475Sbostic 			for (i = 0; i < sp->num_airports; i++)
12132475Sbostic 				if (pp->xpos == sp->airport[i].x &&
12232475Sbostic 				    pp->ypos == sp->airport[i].y) {
12332475Sbostic 					if (pp->dest_type == T_AIRPORT)
12432475Sbostic 					    loser(pp,
12532475Sbostic 						"landed at the wrong airport.");
12632475Sbostic 					else
12732475Sbostic 					    loser(pp,
12832475Sbostic 						"landed instead of exited.");
12932475Sbostic 				}
13032475Sbostic 			loser(pp, "crashed on the ground.");
13132475Sbostic 		}
13232475Sbostic 		if (pp->xpos < 1 || pp->xpos >= sp->width - 1 ||
13332475Sbostic 		    pp->ypos < 1 || pp->ypos >= sp->height - 1) {
13432475Sbostic 			for (i = 0; i < sp->num_exits; i++)
13532475Sbostic 				if (pp->xpos == sp->exit[i].x &&
13632475Sbostic 				    pp->ypos == sp->exit[i].y) {
13732475Sbostic 					if (pp->dest_type == T_EXIT)
13832475Sbostic 					    loser(pp,
13932475Sbostic 						"exited via the wrong exit.");
14032475Sbostic 					else
14132475Sbostic 					    loser(pp,
14232475Sbostic 						"exited instead of landed.");
14332475Sbostic 				}
14432475Sbostic 			loser(pp, "illegally left the flight arena.");
14532475Sbostic 		}
14632475Sbostic 	}
14732475Sbostic 
14832475Sbostic 	/*
14932475Sbostic 	 * Traverse the list once, deleting the planes that are gone.
15032475Sbostic 	 */
15132475Sbostic 	for (pp = air.head; pp != NULL; pp = p2) {
15232475Sbostic 		p2 = pp->next;
15332475Sbostic 		if (pp->status == S_GONE) {
15432475Sbostic 			safe_planes++;
15532475Sbostic 			delete(&air, pp);
15632475Sbostic 		}
15732475Sbostic 	}
15832475Sbostic 
15932475Sbostic 	draw_all();
16032475Sbostic 
16132475Sbostic 	for (p1 = air.head; p1 != NULL; p1 = p1->next)
16232475Sbostic 		for (p2 = p1->next; p2 != NULL; p2 = p2->next)
16332475Sbostic 			if (too_close(p1, p2, 1)) {
16432475Sbostic 				static char	buf[80];
16532475Sbostic 
16632476Sbostic 				(void)sprintf(buf, "collided with plane '%c'.",
16732475Sbostic 					name(p2));
16832475Sbostic 				loser(p1, buf);
16932475Sbostic 			}
17032475Sbostic 	/*
17132475Sbostic 	 * Check every other update.  Actually, only add on even updates.
17232475Sbostic 	 * Otherwise, prop jobs show up *on* entrance.  Remember that
17332475Sbostic 	 * we don't update props on odd updates.
17432475Sbostic 	 */
17532475Sbostic 	if ((rand() % sp->newplane_time) == 0)
17632475Sbostic 		addplane();
17732475Sbostic 
17832475Sbostic #ifdef BSD
17932475Sbostic 	sigsetmask(mask);
18032475Sbostic #endif
18132475Sbostic #ifdef SYSV
18232475Sbostic 	alarm(sp->update_secs);
18332475Sbostic #endif
18432475Sbostic }
18532475Sbostic 
18632475Sbostic char *
18732475Sbostic command(pp)
18832475Sbostic 	PLANE	*pp;
18932475Sbostic {
19032475Sbostic 	static char	buf[50], *bp, *comm_start;
191*33144Sbostic 	char	*index();
19232475Sbostic 
19332475Sbostic 	buf[0] = '\0';
19432475Sbostic 	bp = buf;
19532476Sbostic 	(void)sprintf(bp, "%c%d%c%c%d: ", name(pp), pp->altitude,
19632475Sbostic 		(pp->fuel < LOWFUEL) ? '*' : ' ',
19732475Sbostic 		(pp->dest_type == T_AIRPORT) ? 'A' : 'E', pp->dest_no);
19832475Sbostic 
19932475Sbostic 	comm_start = bp = index(buf, '\0');
20032475Sbostic 	if (pp->altitude == 0)
20132476Sbostic 		(void)sprintf(bp, "Holding @ A%d", pp->orig_no);
20232475Sbostic 	else if (pp->new_dir >= MAXDIR || pp->new_dir < 0)
20332475Sbostic 		strcpy(bp, "Circle");
20432475Sbostic 	else if (pp->new_dir != pp->dir)
20532476Sbostic 		(void)sprintf(bp, "%d", dir_deg(pp->new_dir));
20632475Sbostic 
20732475Sbostic 	bp = index(buf, '\0');
20832475Sbostic 	if (pp->delayd)
20932476Sbostic 		(void)sprintf(bp, " @ B%d", pp->delayd_no);
21032475Sbostic 
21132475Sbostic 	bp = index(buf, '\0');
21232475Sbostic 	if (*comm_start == '\0' &&
21332475Sbostic 	    (pp->status == S_UNMARKED || pp->status == S_IGNORED))
21432475Sbostic 		strcpy(bp, "---------");
21532475Sbostic 	return (buf);
21632475Sbostic }
21732475Sbostic 
21832475Sbostic /* char */
21932475Sbostic name(p)
22032475Sbostic 	PLANE	*p;
22132475Sbostic {
22232475Sbostic 	if (p->plane_type == 0)
22332475Sbostic 		return ('A' + p->plane_no);
22432475Sbostic 	else
22532475Sbostic 		return ('a' + p->plane_no);
22632475Sbostic }
22732475Sbostic 
22832475Sbostic number(l)
22932475Sbostic {
23032475Sbostic 	if (l < 'a' && l > 'z' && l < 'A' && l > 'Z')
23132475Sbostic 		return (-1);
23232475Sbostic 	else if (l >= 'a' && l <= 'z')
23332475Sbostic 		return (l - 'a');
23432475Sbostic 	else
23532475Sbostic 		return (l - 'A');
23632475Sbostic }
23732475Sbostic 
23832475Sbostic next_plane()
23932475Sbostic {
24032475Sbostic 	static int	last_plane = -1;
24132475Sbostic 	PLANE		*pp;
24232475Sbostic 	int		found, start_plane = last_plane;
24332475Sbostic 
24432475Sbostic 	do {
24532475Sbostic 		found = 0;
24632475Sbostic 		last_plane++;
24732475Sbostic 		if (last_plane >= 26)
24832475Sbostic 			last_plane = 0;
24932475Sbostic 		for (pp = air.head; pp != NULL; pp = pp->next)
25032475Sbostic 			if (pp->plane_no == last_plane) {
25132475Sbostic 				found++;
25232475Sbostic 				break;
25332475Sbostic 			}
25432475Sbostic 		if (!found)
25532475Sbostic 			for (pp = ground.head; pp != NULL; pp = pp->next)
25632475Sbostic 				if (pp->plane_no == last_plane) {
25732475Sbostic 					found++;
25832475Sbostic 					break;
25932475Sbostic 				}
26032475Sbostic 	} while (found && last_plane != start_plane);
26132475Sbostic 	if (last_plane == start_plane)
26232475Sbostic 		return (-1);
26332475Sbostic 	return (last_plane);
26432475Sbostic }
26532475Sbostic 
26632475Sbostic addplane()
26732475Sbostic {
26832475Sbostic 	PLANE	p, *pp, *p1;
26932475Sbostic 	int	i, num_starts, close, rnd, rnd2, pnum;
27032475Sbostic 
27132475Sbostic 	bzero(&p, sizeof (p));
27232475Sbostic 
27332475Sbostic 	p.status = S_MARKED;
27432475Sbostic 	p.plane_type = random() % 2;
27532475Sbostic 
27632475Sbostic 	num_starts = sp->num_exits + sp->num_airports;
27732475Sbostic 	rnd = random() % num_starts;
27832475Sbostic 
27932475Sbostic 	if (rnd < sp->num_exits) {
28032475Sbostic 		p.dest_type = T_EXIT;
28132475Sbostic 		p.dest_no = rnd;
28232475Sbostic 	} else {
28332475Sbostic 		p.dest_type = T_AIRPORT;
28432475Sbostic 		p.dest_no = rnd - sp->num_exits;
28532475Sbostic 	}
28632475Sbostic 
28732475Sbostic 	/* loop until we get a plane not near another */
28832475Sbostic 	for (i = 0; i < num_starts; i++) {
28932475Sbostic 		/* loop till we get a different start point */
29032475Sbostic 		while ((rnd2 = random() % num_starts) == rnd)
29132475Sbostic 			;
29232475Sbostic 		if (rnd2 < sp->num_exits) {
29332475Sbostic 			p.orig_type = T_EXIT;
29432475Sbostic 			p.orig_no = rnd2;
29532475Sbostic 			p.xpos = sp->exit[rnd2].x;
29632475Sbostic 			p.ypos = sp->exit[rnd2].y;
29732475Sbostic 			p.new_dir = p.dir = sp->exit[rnd2].dir;
29832475Sbostic 			p.altitude = p.new_altitude = 7;
29932475Sbostic 			close = 0;
30032475Sbostic 			for (p1 = air.head; p1 != NULL; p1 = p1->next)
30132475Sbostic 				if (too_close(p1, &p, 4)) {
30232475Sbostic 					close++;
30332475Sbostic 					break;
30432475Sbostic 				}
30532475Sbostic 			if (close)
30632475Sbostic 				continue;
30732475Sbostic 		} else {
30832475Sbostic 			p.orig_type = T_AIRPORT;
30932475Sbostic 			p.orig_no = rnd2 - sp->num_exits;
31032475Sbostic 			p.xpos = sp->airport[p.orig_no].x;
31132475Sbostic 			p.ypos = sp->airport[p.orig_no].y;
31232475Sbostic 			p.new_dir = p.dir = sp->airport[p.orig_no].dir;
31332475Sbostic 			p.altitude = p.new_altitude = 0;
31432475Sbostic 		}
31532475Sbostic 		p.fuel = sp->width + sp->height;
31632475Sbostic 		break;
31732475Sbostic 	}
31832475Sbostic 	if (i >= num_starts)
31932475Sbostic 		return (-1);
32032475Sbostic 	pnum = next_plane();
32132475Sbostic 	if (pnum < 0)
32232475Sbostic 		return (-1);
32332475Sbostic 	p.plane_no = pnum;
32432475Sbostic 
32532475Sbostic 	pp = newplane();
32632475Sbostic 	bcopy(&p, pp, sizeof (p));
32732475Sbostic 
32832475Sbostic 	if (pp->orig_type == T_AIRPORT)
32932475Sbostic 		append(&ground, pp);
33032475Sbostic 	else
33132475Sbostic 		append(&air, pp);
33232475Sbostic 
33332475Sbostic 	return (pp->dest_type);
33432475Sbostic }
33532475Sbostic 
33632475Sbostic PLANE	*
33732475Sbostic findplane(n)
33832475Sbostic {
33932475Sbostic 	PLANE	*pp;
34032475Sbostic 
34132475Sbostic 	for (pp = air.head; pp != NULL; pp = pp->next)
34232475Sbostic 		if (pp->plane_no == n)
34332475Sbostic 			return (pp);
34432475Sbostic 	for (pp = ground.head; pp != NULL; pp = pp->next)
34532475Sbostic 		if (pp->plane_no == n)
34632475Sbostic 			return (pp);
34732475Sbostic 	return (NULL);
34832475Sbostic }
34932475Sbostic 
35032475Sbostic too_close(p1, p2, dist)
35132475Sbostic 	PLANE	*p1, *p2;
35232475Sbostic {
35332475Sbostic 	if (ABS(p1->altitude - p2->altitude) <= dist &&
35432475Sbostic 	    ABS(p1->xpos - p2->xpos) <= dist && ABS(p1->ypos - p2->ypos) <= dist)
35532475Sbostic 		return (1);
35632475Sbostic 	else
35732475Sbostic 		return (0);
35832475Sbostic }
35932475Sbostic 
36032475Sbostic dir_deg(d)
36132475Sbostic {
36232475Sbostic 	switch (d) {
36332475Sbostic 	case 0: return (0);
36432475Sbostic 	case 1: return (45);
36532475Sbostic 	case 2: return (90);
36632475Sbostic 	case 3: return (135);
36732475Sbostic 	case 4: return (180);
36832475Sbostic 	case 5: return (225);
36932475Sbostic 	case 6: return (270);
37032475Sbostic 	case 7: return (315);
37132475Sbostic 	default:
37232475Sbostic 		return (-1);
37332475Sbostic 	}
37432475Sbostic }
375