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