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