]> git.cameronkatri.com Git - bsdgames-darwin.git/blob - atc/update.c
Abolish the foul practice of including every header in existence via a
[bsdgames-darwin.git] / atc / update.c
1 /* $NetBSD: update.c,v 1.26 2015/06/19 06:02:31 dholland Exp $ */
2
3 /*-
4 * Copyright (c) 1990, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * This code is derived from software contributed to Berkeley by
8 * Ed James.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of the University nor the names of its contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 */
34
35 /*
36 * Copyright (c) 1987 by Ed James, UC Berkeley. All rights reserved.
37 *
38 * Copy permission is hereby granted provided that this notice is
39 * retained on all partial or complete copies.
40 *
41 * For more info on this and all of my stuff, mail edjames@berkeley.edu.
42 */
43
44 #include <sys/cdefs.h>
45 #ifndef lint
46 #if 0
47 static char sccsid[] = "@(#)update.c 8.1 (Berkeley) 5/31/93";
48 #else
49 __RCSID("$NetBSD: update.c,v 1.26 2015/06/19 06:02:31 dholland Exp $");
50 #endif
51 #endif /* not lint */
52
53 #include <stdio.h>
54 #include <stdlib.h>
55 #include <string.h>
56 #include <ctype.h>
57
58 #include "def.h"
59 #include "struct.h"
60 #include "extern.h"
61 #include "tunable.h"
62
63 static int next_plane(void);
64 static int too_close(const PLANE *p1, const PLANE *p2, int);
65 static int dir_deg(int);
66
67 /* ARGSUSED */
68 void
69 update(int dummy __unused)
70 {
71 int dir_diff, unclean;
72 unsigned i;
73 PLANE *pp, *p1, *p2;
74
75 #ifdef SYSV
76 alarm(0);
77 signal(SIGALRM, update);
78 #endif
79
80 clck++;
81
82 erase_all();
83
84 /* put some planes in the air */
85 do {
86 unclean = 0;
87 for (pp = ground.head; pp != NULL; pp = pp->next) {
88 if (pp->new_altitude > 0) {
89 delete(&ground, pp);
90 append(&air, pp);
91 unclean = 1;
92 break;
93 }
94 }
95 } while (unclean);
96
97 /* do altitude change and basic movement */
98 for (pp = air.head; pp != NULL; pp = pp->next) {
99 /* type 0 only move every other turn */
100 if (pp->plane_type == 0 && clck & 1)
101 continue;
102
103 pp->fuel--;
104 if (pp->fuel < 0)
105 loser(pp, "ran out of fuel.");
106
107 pp->altitude += SGN(pp->new_altitude - pp->altitude);
108
109 if (!pp->delayd) {
110 dir_diff = pp->new_dir - pp->dir;
111 /*
112 * Allow for circle commands
113 */
114 if (pp->new_dir >= 0 && pp->new_dir < MAXDIR) {
115 if (dir_diff > MAXDIR/2)
116 dir_diff -= MAXDIR;
117 else if (dir_diff < -(MAXDIR/2))
118 dir_diff += MAXDIR;
119 }
120 if (dir_diff > 2)
121 dir_diff = 2;
122 else if (dir_diff < -2)
123 dir_diff = -2;
124 pp->dir += dir_diff;
125 if (pp->dir >= MAXDIR)
126 pp->dir -= MAXDIR;
127 else if (pp->dir < 0)
128 pp->dir += MAXDIR;
129 }
130 pp->xpos += displacement[pp->dir].dx;
131 pp->ypos += displacement[pp->dir].dy;
132
133 if (pp->delayd && pp->xpos == sp->beacon[pp->delayd_no].x &&
134 pp->ypos == sp->beacon[pp->delayd_no].y) {
135 pp->delayd = false;
136 if (pp->status == S_UNMARKED)
137 pp->status = S_MARKED;
138 }
139
140 switch (pp->dest_type) {
141 case T_AIRPORT:
142 if (pp->xpos == sp->airport[pp->dest_no].x &&
143 pp->ypos == sp->airport[pp->dest_no].y &&
144 pp->altitude == 0) {
145 if (pp->dir != sp->airport[pp->dest_no].dir)
146 loser(pp, "landed in the wrong direction.");
147 else {
148 pp->status = S_GONE;
149 continue;
150 }
151 }
152 break;
153 case T_EXIT:
154 if (pp->xpos == sp->exit[pp->dest_no].x &&
155 pp->ypos == sp->exit[pp->dest_no].y) {
156 if (pp->altitude != 9)
157 loser(pp, "exited at the wrong altitude.");
158 else {
159 pp->status = S_GONE;
160 continue;
161 }
162 }
163 break;
164 default:
165 loser(pp, "has a bizarre destination, get help!");
166 }
167 if (pp->altitude > 9)
168 /* "this is impossible" */
169 loser(pp, "exceeded flight ceiling.");
170 if (pp->altitude <= 0) {
171 for (i = 0; i < sp->num_airports; i++)
172 if (pp->xpos == sp->airport[i].x &&
173 pp->ypos == sp->airport[i].y) {
174 if (pp->dest_type == T_AIRPORT)
175 loser(pp,
176 "landed at the wrong airport.");
177 else
178 loser(pp,
179 "landed instead of exited.");
180 }
181 loser(pp, "crashed on the ground.");
182 }
183 if (pp->xpos < 1 || pp->xpos >= sp->width - 1 ||
184 pp->ypos < 1 || pp->ypos >= sp->height - 1) {
185 for (i = 0; i < sp->num_exits; i++)
186 if (pp->xpos == sp->exit[i].x &&
187 pp->ypos == sp->exit[i].y) {
188 if (pp->dest_type == T_EXIT)
189 loser(pp,
190 "exited via the wrong exit.");
191 else
192 loser(pp,
193 "exited instead of landed.");
194 }
195 loser(pp, "illegally left the flight arena.");
196 }
197 }
198
199 /*
200 * Traverse the list once, deleting the planes that are gone.
201 */
202 for (pp = air.head; pp != NULL; pp = p2) {
203 p2 = pp->next;
204 if (pp->status == S_GONE) {
205 safe_planes++;
206 delete(&air, pp);
207 }
208 }
209
210 draw_all();
211
212 for (p1 = air.head; p1 != NULL; p1 = p1->next)
213 for (p2 = p1->next; p2 != NULL; p2 = p2->next)
214 if (too_close(p1, p2, 1)) {
215 static char buf[80];
216
217 (void)snprintf(buf, sizeof(buf),
218 "collided with plane '%c'.",
219 name(p2));
220 loser(p1, buf);
221 }
222 /*
223 * Check every other update. Actually, only add on even updates.
224 * Otherwise, prop jobs show up *on* entrance. Remember that
225 * we don't update props on odd updates.
226 */
227 if ((rand() % sp->newplane_time) == 0)
228 addplane();
229
230 #ifdef SYSV
231 alarm(sp->update_secs);
232 #endif
233 }
234
235 const char *
236 command(const PLANE *pp)
237 {
238 static char buf[50], *bp, *comm_start;
239 size_t bpsize;
240
241 buf[0] = '\0';
242 bp = buf;
243 bpsize = sizeof(buf);
244 (void)snprintf(bp, bpsize, "%c%d%c%c%u: ", name(pp), pp->altitude,
245 (pp->fuel < LOWFUEL) ? '*' : ' ',
246 (pp->dest_type == T_AIRPORT) ? 'A' : 'E', pp->dest_no);
247
248 comm_start = bp = strchr(buf, '\0');
249 bpsize = buf + sizeof(buf) - bp;
250 if (pp->altitude == 0)
251 (void)snprintf(bp, bpsize, "Holding @ A%u", pp->orig_no);
252 else if (pp->new_dir >= MAXDIR || pp->new_dir < 0)
253 (void)snprintf(bp, bpsize, "Circle");
254 else if (pp->new_dir != pp->dir)
255 (void)snprintf(bp, bpsize, "%d", dir_deg(pp->new_dir));
256
257 bp = strchr(buf, '\0');
258 bpsize = buf + sizeof(buf) - bp;
259 if (pp->delayd)
260 (void)snprintf(bp, bpsize, " @ B%u", pp->delayd_no);
261
262 bp = strchr(buf, '\0');
263 bpsize = buf + sizeof(buf) - bp;
264 if (*comm_start == '\0' &&
265 (pp->status == S_UNMARKED || pp->status == S_IGNORED))
266 (void)snprintf(bp, bpsize, "---------");
267 return (buf);
268 }
269
270 char
271 name(const PLANE *p)
272 {
273 if (p->plane_type == 0)
274 return ('A' + p->plane_no);
275 else
276 return ('a' + p->plane_no);
277 }
278
279 int
280 number(int l)
281 {
282 if (islower((unsigned char)l))
283 return (l - 'a');
284 else if (isupper((unsigned char)l))
285 return (l - 'A');
286 else
287 return (-1);
288 }
289
290 static int
291 next_plane(void)
292 {
293 static int last_plane = -1;
294 PLANE *pp;
295 int found, start_plane = last_plane;
296
297 do {
298 found = 0;
299 last_plane++;
300 if (last_plane >= 26)
301 last_plane = 0;
302 for (pp = air.head; pp != NULL; pp = pp->next)
303 if (pp->plane_no == last_plane) {
304 found++;
305 break;
306 }
307 if (!found)
308 for (pp = ground.head; pp != NULL; pp = pp->next)
309 if (pp->plane_no == last_plane) {
310 found++;
311 break;
312 }
313 } while (found && last_plane != start_plane);
314 if (found)
315 return (-1);
316 return (last_plane);
317 }
318
319 void
320 addplane(void)
321 {
322 PLANE p, *pp, *p1;
323 int isclose, pnum;
324 unsigned num_starts, rnd, rnd2, i;
325
326 (void)memset(&p, 0, sizeof (p));
327
328 p.status = S_MARKED;
329 p.plane_type = random() % 2;
330
331 num_starts = sp->num_exits + sp->num_airports;
332 rnd = random() % num_starts;
333
334 if (rnd < sp->num_exits) {
335 p.dest_type = T_EXIT;
336 p.dest_no = rnd;
337 } else {
338 p.dest_type = T_AIRPORT;
339 p.dest_no = rnd - sp->num_exits;
340 }
341
342 /* loop until we get a plane not near another */
343 for (i = 0; i < num_starts; i++) {
344 /* loop till we get a different start point */
345 while ((rnd2 = random() % num_starts) == rnd)
346 ;
347 if (rnd2 < sp->num_exits) {
348 p.orig_type = T_EXIT;
349 p.orig_no = rnd2;
350 p.xpos = sp->exit[rnd2].x;
351 p.ypos = sp->exit[rnd2].y;
352 p.new_dir = p.dir = sp->exit[rnd2].dir;
353 p.altitude = p.new_altitude = 7;
354 isclose = 0;
355 for (p1 = air.head; p1 != NULL; p1 = p1->next)
356 if (too_close(p1, &p, 4)) {
357 isclose++;
358 break;
359 }
360 if (isclose)
361 continue;
362 } else {
363 p.orig_type = T_AIRPORT;
364 p.orig_no = rnd2 - sp->num_exits;
365 p.xpos = sp->airport[p.orig_no].x;
366 p.ypos = sp->airport[p.orig_no].y;
367 p.new_dir = p.dir = sp->airport[p.orig_no].dir;
368 p.altitude = p.new_altitude = 0;
369 }
370 p.fuel = sp->width + sp->height;
371 break;
372 }
373 if (i >= num_starts)
374 return;
375 pnum = next_plane();
376 if (pnum < 0)
377 return;
378 p.plane_no = pnum;
379
380 pp = newplane();
381 if (pp == NULL)
382 loser(NULL, "Out of memory!");
383 (void)memcpy(pp, &p, sizeof (p));
384
385 if (pp->orig_type == T_AIRPORT)
386 append(&ground, pp);
387 else
388 append(&air, pp);
389 }
390
391 PLANE *
392 findplane(int n)
393 {
394 PLANE *pp;
395
396 for (pp = air.head; pp != NULL; pp = pp->next)
397 if (pp->plane_no == n)
398 return (pp);
399 for (pp = ground.head; pp != NULL; pp = pp->next)
400 if (pp->plane_no == n)
401 return (pp);
402 return (NULL);
403 }
404
405 static int
406 too_close(const PLANE *p1, const PLANE *p2, int dist)
407 {
408 if (ABS(p1->altitude - p2->altitude) <= dist &&
409 ABS(p1->xpos - p2->xpos) <= dist &&
410 ABS(p1->ypos - p2->ypos) <= dist)
411 return (1);
412 else
413 return (0);
414 }
415
416 static int
417 dir_deg(int d)
418 {
419 switch (d) {
420 case 0: return (0);
421 case 1: return (45);
422 case 2: return (90);
423 case 3: return (135);
424 case 4: return (180);
425 case 5: return (225);
426 case 6: return (270);
427 case 7: return (315);
428 default:
429 return (-1);
430 }
431 }