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