xref: /csrg-svn/games/atc/update.c (revision 32475)
1*32475Sbostic /*
2*32475Sbostic  * Copyright (c) 1987 by Ed James, UC Berkeley.  All rights reserved.
3*32475Sbostic  *
4*32475Sbostic  * Copy permission is hereby granted provided that this notice is
5*32475Sbostic  * retained on all partial or complete copies.
6*32475Sbostic  *
7*32475Sbostic  * For more info on this and all of my stuff, mail edjames@berkeley.edu.
8*32475Sbostic  */
9*32475Sbostic 
10*32475Sbostic #ifndef lint
11*32475Sbostic static char sccsid[] = "@(#)update.c	5.1 (Berkeley) 10/22/87";
12*32475Sbostic #endif not lint
13*32475Sbostic 
14*32475Sbostic #include "include.h"
15*32475Sbostic 
16*32475Sbostic update()
17*32475Sbostic {
18*32475Sbostic 	int	i, dir_diff, mask, unclean;
19*32475Sbostic 	PLANE	*pp, *p1, *p2, *p;
20*32475Sbostic 
21*32475Sbostic #ifdef BSD
22*32475Sbostic 	mask = sigblock(sigmask(SIGINT));
23*32475Sbostic #endif
24*32475Sbostic #ifdef SYSV
25*32475Sbostic 	alarm(0);
26*32475Sbostic 	signal(SIGALRM, update);
27*32475Sbostic #endif
28*32475Sbostic 
29*32475Sbostic 	clock++;
30*32475Sbostic 
31*32475Sbostic 	erase_all();
32*32475Sbostic 
33*32475Sbostic 	/* put some planes in the air */
34*32475Sbostic 	do {
35*32475Sbostic 		unclean = 0;
36*32475Sbostic 		for (pp = ground.head; pp != NULL; pp = pp->next) {
37*32475Sbostic 			if (pp->new_altitude > 0) {
38*32475Sbostic 				delete(&ground, pp);
39*32475Sbostic 				append(&air, pp);
40*32475Sbostic 				unclean = 1;
41*32475Sbostic 				break;
42*32475Sbostic 			}
43*32475Sbostic 		}
44*32475Sbostic 	} while (unclean);
45*32475Sbostic 
46*32475Sbostic 	/* do altitude change and basic movement */
47*32475Sbostic 	for (pp = air.head; pp != NULL; pp = pp->next) {
48*32475Sbostic 		/* type 0 only move every other turn */
49*32475Sbostic 		if (pp->plane_type == 0 && clock & 1)
50*32475Sbostic 			continue;
51*32475Sbostic 
52*32475Sbostic 		pp->fuel--;
53*32475Sbostic 		if (pp->fuel < 0)
54*32475Sbostic 			loser(pp, "ran out of fuel.");
55*32475Sbostic 
56*32475Sbostic 		pp->altitude += SGN(pp->new_altitude - pp->altitude);
57*32475Sbostic 
58*32475Sbostic 		if (!pp->delayd) {
59*32475Sbostic 			dir_diff = pp->new_dir - pp->dir;
60*32475Sbostic 			/*
61*32475Sbostic 			 * Allow for circle commands
62*32475Sbostic 			 */
63*32475Sbostic 			if (pp->new_dir >= 0 && pp->new_dir < MAXDIR) {
64*32475Sbostic 				if (dir_diff > MAXDIR/2)
65*32475Sbostic 					dir_diff -= MAXDIR;
66*32475Sbostic 				else if (dir_diff < -(MAXDIR/2))
67*32475Sbostic 					dir_diff += MAXDIR;
68*32475Sbostic 			}
69*32475Sbostic 			if (dir_diff > 2)
70*32475Sbostic 				dir_diff = 2;
71*32475Sbostic 			else if (dir_diff < -2)
72*32475Sbostic 				dir_diff = -2;
73*32475Sbostic 			pp->dir += dir_diff;
74*32475Sbostic 			if (pp->dir >= MAXDIR)
75*32475Sbostic 				pp->dir -= MAXDIR;
76*32475Sbostic 			else if (pp->dir < 0)
77*32475Sbostic 				pp->dir += MAXDIR;
78*32475Sbostic 		}
79*32475Sbostic 		pp->xpos += displacement[pp->dir].dx;
80*32475Sbostic 		pp->ypos += displacement[pp->dir].dy;
81*32475Sbostic 
82*32475Sbostic 		if (pp->delayd && pp->xpos == sp->beacon[pp->delayd_no].x &&
83*32475Sbostic 		    pp->ypos == sp->beacon[pp->delayd_no].y) {
84*32475Sbostic 			pp->delayd = 0;
85*32475Sbostic 			if (pp->status == S_UNMARKED)
86*32475Sbostic 				pp->status = S_MARKED;
87*32475Sbostic 		}
88*32475Sbostic 
89*32475Sbostic 		switch (pp->dest_type) {
90*32475Sbostic 		case T_AIRPORT:
91*32475Sbostic 			if (pp->xpos == sp->airport[pp->dest_no].x &&
92*32475Sbostic 			    pp->ypos == sp->airport[pp->dest_no].y &&
93*32475Sbostic 			    pp->altitude == 0) {
94*32475Sbostic 				if (pp->dir != sp->airport[pp->dest_no].dir)
95*32475Sbostic 				    loser(pp, "landed in the wrong direction.");
96*32475Sbostic 				else {
97*32475Sbostic 				    pp->status = S_GONE;
98*32475Sbostic 				    continue;
99*32475Sbostic 				}
100*32475Sbostic 			}
101*32475Sbostic 			break;
102*32475Sbostic 		case T_EXIT:
103*32475Sbostic 			if (pp->xpos == sp->exit[pp->dest_no].x &&
104*32475Sbostic 			    pp->ypos == sp->exit[pp->dest_no].y) {
105*32475Sbostic 			    	if (pp->altitude != 9)
106*32475Sbostic 				    loser(pp, "exited at the wrong altitude.");
107*32475Sbostic 				else {
108*32475Sbostic 				    pp->status = S_GONE;
109*32475Sbostic 				    continue;
110*32475Sbostic 				}
111*32475Sbostic 			}
112*32475Sbostic 			break;
113*32475Sbostic 		default:
114*32475Sbostic 			loser(pp, "has a bizarre destination, get help!");
115*32475Sbostic 		}
116*32475Sbostic 		if (pp->altitude > 9)
117*32475Sbostic 			/* "this is impossible" */
118*32475Sbostic 			loser(pp, "exceded flight ceiling.");
119*32475Sbostic 		if (pp->altitude <= 0) {
120*32475Sbostic 			for (i = 0; i < sp->num_airports; i++)
121*32475Sbostic 				if (pp->xpos == sp->airport[i].x &&
122*32475Sbostic 				    pp->ypos == sp->airport[i].y) {
123*32475Sbostic 					if (pp->dest_type == T_AIRPORT)
124*32475Sbostic 					    loser(pp,
125*32475Sbostic 						"landed at the wrong airport.");
126*32475Sbostic 					else
127*32475Sbostic 					    loser(pp,
128*32475Sbostic 						"landed instead of exited.");
129*32475Sbostic 				}
130*32475Sbostic 			loser(pp, "crashed on the ground.");
131*32475Sbostic 		}
132*32475Sbostic 		if (pp->xpos < 1 || pp->xpos >= sp->width - 1 ||
133*32475Sbostic 		    pp->ypos < 1 || pp->ypos >= sp->height - 1) {
134*32475Sbostic 			for (i = 0; i < sp->num_exits; i++)
135*32475Sbostic 				if (pp->xpos == sp->exit[i].x &&
136*32475Sbostic 				    pp->ypos == sp->exit[i].y) {
137*32475Sbostic 					if (pp->dest_type == T_EXIT)
138*32475Sbostic 					    loser(pp,
139*32475Sbostic 						"exited via the wrong exit.");
140*32475Sbostic 					else
141*32475Sbostic 					    loser(pp,
142*32475Sbostic 						"exited instead of landed.");
143*32475Sbostic 				}
144*32475Sbostic 			loser(pp, "illegally left the flight arena.");
145*32475Sbostic 		}
146*32475Sbostic 	}
147*32475Sbostic 
148*32475Sbostic 	/*
149*32475Sbostic 	 * Traverse the list once, deleting the planes that are gone.
150*32475Sbostic 	 */
151*32475Sbostic 	for (pp = air.head; pp != NULL; pp = p2) {
152*32475Sbostic 		p2 = pp->next;
153*32475Sbostic 		if (pp->status == S_GONE) {
154*32475Sbostic 			safe_planes++;
155*32475Sbostic 			delete(&air, pp);
156*32475Sbostic 		}
157*32475Sbostic 	}
158*32475Sbostic 
159*32475Sbostic 	draw_all();
160*32475Sbostic 
161*32475Sbostic 	for (p1 = air.head; p1 != NULL; p1 = p1->next)
162*32475Sbostic 		for (p2 = p1->next; p2 != NULL; p2 = p2->next)
163*32475Sbostic 			if (too_close(p1, p2, 1)) {
164*32475Sbostic 				static char	buf[80];
165*32475Sbostic 
166*32475Sbostic 				sprintf(buf, "collided with plane '%c'.",
167*32475Sbostic 					name(p2));
168*32475Sbostic 				loser(p1, buf);
169*32475Sbostic 			}
170*32475Sbostic 	/*
171*32475Sbostic 	 * Check every other update.  Actually, only add on even updates.
172*32475Sbostic 	 * Otherwise, prop jobs show up *on* entrance.  Remember that
173*32475Sbostic 	 * we don't update props on odd updates.
174*32475Sbostic 	 */
175*32475Sbostic 	if ((rand() % sp->newplane_time) == 0)
176*32475Sbostic 		addplane();
177*32475Sbostic 
178*32475Sbostic #ifdef BSD
179*32475Sbostic 	sigsetmask(mask);
180*32475Sbostic #endif
181*32475Sbostic #ifdef SYSV
182*32475Sbostic 	alarm(sp->update_secs);
183*32475Sbostic #endif
184*32475Sbostic }
185*32475Sbostic 
186*32475Sbostic char *
187*32475Sbostic command(pp)
188*32475Sbostic 	PLANE	*pp;
189*32475Sbostic {
190*32475Sbostic 	static char	buf[50], *bp, *comm_start;
191*32475Sbostic 
192*32475Sbostic 	buf[0] = '\0';
193*32475Sbostic 	bp = buf;
194*32475Sbostic 	sprintf(bp, "%c%d%c%c%d: ", name(pp), pp->altitude,
195*32475Sbostic 		(pp->fuel < LOWFUEL) ? '*' : ' ',
196*32475Sbostic 		(pp->dest_type == T_AIRPORT) ? 'A' : 'E', pp->dest_no);
197*32475Sbostic 
198*32475Sbostic 	comm_start = bp = index(buf, '\0');
199*32475Sbostic 	if (pp->altitude == 0)
200*32475Sbostic 		sprintf(bp, "Holding @ A%d", pp->orig_no);
201*32475Sbostic 	else if (pp->new_dir >= MAXDIR || pp->new_dir < 0)
202*32475Sbostic 		strcpy(bp, "Circle");
203*32475Sbostic 	else if (pp->new_dir != pp->dir)
204*32475Sbostic 		sprintf(bp, "%d", dir_deg(pp->new_dir));
205*32475Sbostic 
206*32475Sbostic 	bp = index(buf, '\0');
207*32475Sbostic 	if (pp->delayd)
208*32475Sbostic 		sprintf(bp, " @ B%d", pp->delayd_no);
209*32475Sbostic 
210*32475Sbostic 	bp = index(buf, '\0');
211*32475Sbostic 	if (*comm_start == '\0' &&
212*32475Sbostic 	    (pp->status == S_UNMARKED || pp->status == S_IGNORED))
213*32475Sbostic 		strcpy(bp, "---------");
214*32475Sbostic 	return (buf);
215*32475Sbostic }
216*32475Sbostic 
217*32475Sbostic /* char */
218*32475Sbostic name(p)
219*32475Sbostic 	PLANE	*p;
220*32475Sbostic {
221*32475Sbostic 	if (p->plane_type == 0)
222*32475Sbostic 		return ('A' + p->plane_no);
223*32475Sbostic 	else
224*32475Sbostic 		return ('a' + p->plane_no);
225*32475Sbostic }
226*32475Sbostic 
227*32475Sbostic number(l)
228*32475Sbostic {
229*32475Sbostic 	if (l < 'a' && l > 'z' && l < 'A' && l > 'Z')
230*32475Sbostic 		return (-1);
231*32475Sbostic 	else if (l >= 'a' && l <= 'z')
232*32475Sbostic 		return (l - 'a');
233*32475Sbostic 	else
234*32475Sbostic 		return (l - 'A');
235*32475Sbostic }
236*32475Sbostic 
237*32475Sbostic next_plane()
238*32475Sbostic {
239*32475Sbostic 	static int	last_plane = -1;
240*32475Sbostic 	PLANE		*pp;
241*32475Sbostic 	int		found, start_plane = last_plane;
242*32475Sbostic 
243*32475Sbostic 	do {
244*32475Sbostic 		found = 0;
245*32475Sbostic 		last_plane++;
246*32475Sbostic 		if (last_plane >= 26)
247*32475Sbostic 			last_plane = 0;
248*32475Sbostic 		for (pp = air.head; pp != NULL; pp = pp->next)
249*32475Sbostic 			if (pp->plane_no == last_plane) {
250*32475Sbostic 				found++;
251*32475Sbostic 				break;
252*32475Sbostic 			}
253*32475Sbostic 		if (!found)
254*32475Sbostic 			for (pp = ground.head; pp != NULL; pp = pp->next)
255*32475Sbostic 				if (pp->plane_no == last_plane) {
256*32475Sbostic 					found++;
257*32475Sbostic 					break;
258*32475Sbostic 				}
259*32475Sbostic 	} while (found && last_plane != start_plane);
260*32475Sbostic 	if (last_plane == start_plane)
261*32475Sbostic 		return (-1);
262*32475Sbostic 	return (last_plane);
263*32475Sbostic }
264*32475Sbostic 
265*32475Sbostic addplane()
266*32475Sbostic {
267*32475Sbostic 	PLANE	p, *pp, *p1;
268*32475Sbostic 	int	i, num_starts, close, rnd, rnd2, pnum;
269*32475Sbostic 
270*32475Sbostic 	bzero(&p, sizeof (p));
271*32475Sbostic 
272*32475Sbostic 	p.status = S_MARKED;
273*32475Sbostic 	p.plane_type = random() % 2;
274*32475Sbostic 
275*32475Sbostic 	num_starts = sp->num_exits + sp->num_airports;
276*32475Sbostic 	rnd = random() % num_starts;
277*32475Sbostic 
278*32475Sbostic 	if (rnd < sp->num_exits) {
279*32475Sbostic 		p.dest_type = T_EXIT;
280*32475Sbostic 		p.dest_no = rnd;
281*32475Sbostic 	} else {
282*32475Sbostic 		p.dest_type = T_AIRPORT;
283*32475Sbostic 		p.dest_no = rnd - sp->num_exits;
284*32475Sbostic 	}
285*32475Sbostic 
286*32475Sbostic 	/* loop until we get a plane not near another */
287*32475Sbostic 	for (i = 0; i < num_starts; i++) {
288*32475Sbostic 		/* loop till we get a different start point */
289*32475Sbostic 		while ((rnd2 = random() % num_starts) == rnd)
290*32475Sbostic 			;
291*32475Sbostic 		if (rnd2 < sp->num_exits) {
292*32475Sbostic 			p.orig_type = T_EXIT;
293*32475Sbostic 			p.orig_no = rnd2;
294*32475Sbostic 			p.xpos = sp->exit[rnd2].x;
295*32475Sbostic 			p.ypos = sp->exit[rnd2].y;
296*32475Sbostic 			p.new_dir = p.dir = sp->exit[rnd2].dir;
297*32475Sbostic 			p.altitude = p.new_altitude = 7;
298*32475Sbostic 			close = 0;
299*32475Sbostic 			for (p1 = air.head; p1 != NULL; p1 = p1->next)
300*32475Sbostic 				if (too_close(p1, &p, 4)) {
301*32475Sbostic 					close++;
302*32475Sbostic 					break;
303*32475Sbostic 				}
304*32475Sbostic 			if (close)
305*32475Sbostic 				continue;
306*32475Sbostic 		} else {
307*32475Sbostic 			p.orig_type = T_AIRPORT;
308*32475Sbostic 			p.orig_no = rnd2 - sp->num_exits;
309*32475Sbostic 			p.xpos = sp->airport[p.orig_no].x;
310*32475Sbostic 			p.ypos = sp->airport[p.orig_no].y;
311*32475Sbostic 			p.new_dir = p.dir = sp->airport[p.orig_no].dir;
312*32475Sbostic 			p.altitude = p.new_altitude = 0;
313*32475Sbostic 		}
314*32475Sbostic 		p.fuel = sp->width + sp->height;
315*32475Sbostic 		break;
316*32475Sbostic 	}
317*32475Sbostic 	if (i >= num_starts)
318*32475Sbostic 		return (-1);
319*32475Sbostic 	pnum = next_plane();
320*32475Sbostic 	if (pnum < 0)
321*32475Sbostic 		return (-1);
322*32475Sbostic 	p.plane_no = pnum;
323*32475Sbostic 
324*32475Sbostic 	pp = newplane();
325*32475Sbostic 	bcopy(&p, pp, sizeof (p));
326*32475Sbostic 
327*32475Sbostic 	if (pp->orig_type == T_AIRPORT)
328*32475Sbostic 		append(&ground, pp);
329*32475Sbostic 	else
330*32475Sbostic 		append(&air, pp);
331*32475Sbostic 
332*32475Sbostic 	return (pp->dest_type);
333*32475Sbostic }
334*32475Sbostic 
335*32475Sbostic PLANE	*
336*32475Sbostic findplane(n)
337*32475Sbostic {
338*32475Sbostic 	PLANE	*pp;
339*32475Sbostic 
340*32475Sbostic 	for (pp = air.head; pp != NULL; pp = pp->next)
341*32475Sbostic 		if (pp->plane_no == n)
342*32475Sbostic 			return (pp);
343*32475Sbostic 	for (pp = ground.head; pp != NULL; pp = pp->next)
344*32475Sbostic 		if (pp->plane_no == n)
345*32475Sbostic 			return (pp);
346*32475Sbostic 	return (NULL);
347*32475Sbostic }
348*32475Sbostic 
349*32475Sbostic too_close(p1, p2, dist)
350*32475Sbostic 	PLANE	*p1, *p2;
351*32475Sbostic {
352*32475Sbostic 	if (ABS(p1->altitude - p2->altitude) <= dist &&
353*32475Sbostic 	    ABS(p1->xpos - p2->xpos) <= dist && ABS(p1->ypos - p2->ypos) <= dist)
354*32475Sbostic 		return (1);
355*32475Sbostic 	else
356*32475Sbostic 		return (0);
357*32475Sbostic }
358*32475Sbostic 
359*32475Sbostic dir_deg(d)
360*32475Sbostic {
361*32475Sbostic 	switch (d) {
362*32475Sbostic 	case 0: return (0);
363*32475Sbostic 	case 1: return (45);
364*32475Sbostic 	case 2: return (90);
365*32475Sbostic 	case 3: return (135);
366*32475Sbostic 	case 4: return (180);
367*32475Sbostic 	case 5: return (225);
368*32475Sbostic 	case 6: return (270);
369*32475Sbostic 	case 7: return (315);
370*32475Sbostic 	default:
371*32475Sbostic 		return (-1);
372*32475Sbostic 	}
373*32475Sbostic }
374