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