132475Sbostic /* 232475Sbostic * Copyright (c) 1987 by Ed James, UC Berkeley. All rights reserved. 332475Sbostic * 432475Sbostic * Copy permission is hereby granted provided that this notice is 532475Sbostic * retained on all partial or complete copies. 632475Sbostic * 732475Sbostic * For more info on this and all of my stuff, mail edjames@berkeley.edu. 832475Sbostic */ 932475Sbostic 1032475Sbostic #ifndef lint 11*33144Sbostic static char sccsid[] = "@(#)update.c 5.3 (Berkeley) 12/26/87"; 1232475Sbostic #endif not lint 1332475Sbostic 1432475Sbostic #include "include.h" 1532475Sbostic 1632475Sbostic update() 1732475Sbostic { 1832475Sbostic int i, dir_diff, mask, unclean; 1932475Sbostic PLANE *pp, *p1, *p2, *p; 2032475Sbostic 2132475Sbostic #ifdef BSD 2232475Sbostic mask = sigblock(sigmask(SIGINT)); 2332475Sbostic #endif 2432475Sbostic #ifdef SYSV 2532475Sbostic alarm(0); 2632475Sbostic signal(SIGALRM, update); 2732475Sbostic #endif 2832475Sbostic 2932475Sbostic clock++; 3032475Sbostic 3132475Sbostic erase_all(); 3232475Sbostic 3332475Sbostic /* put some planes in the air */ 3432475Sbostic do { 3532475Sbostic unclean = 0; 3632475Sbostic for (pp = ground.head; pp != NULL; pp = pp->next) { 3732475Sbostic if (pp->new_altitude > 0) { 3832475Sbostic delete(&ground, pp); 3932475Sbostic append(&air, pp); 4032475Sbostic unclean = 1; 4132475Sbostic break; 4232475Sbostic } 4332475Sbostic } 4432475Sbostic } while (unclean); 4532475Sbostic 4632475Sbostic /* do altitude change and basic movement */ 4732475Sbostic for (pp = air.head; pp != NULL; pp = pp->next) { 4832475Sbostic /* type 0 only move every other turn */ 4932475Sbostic if (pp->plane_type == 0 && clock & 1) 5032475Sbostic continue; 5132475Sbostic 5232475Sbostic pp->fuel--; 5332475Sbostic if (pp->fuel < 0) 5432475Sbostic loser(pp, "ran out of fuel."); 5532475Sbostic 5632475Sbostic pp->altitude += SGN(pp->new_altitude - pp->altitude); 5732475Sbostic 5832475Sbostic if (!pp->delayd) { 5932475Sbostic dir_diff = pp->new_dir - pp->dir; 6032475Sbostic /* 6132475Sbostic * Allow for circle commands 6232475Sbostic */ 6332475Sbostic if (pp->new_dir >= 0 && pp->new_dir < MAXDIR) { 6432475Sbostic if (dir_diff > MAXDIR/2) 6532475Sbostic dir_diff -= MAXDIR; 6632475Sbostic else if (dir_diff < -(MAXDIR/2)) 6732475Sbostic dir_diff += MAXDIR; 6832475Sbostic } 6932475Sbostic if (dir_diff > 2) 7032475Sbostic dir_diff = 2; 7132475Sbostic else if (dir_diff < -2) 7232475Sbostic dir_diff = -2; 7332475Sbostic pp->dir += dir_diff; 7432475Sbostic if (pp->dir >= MAXDIR) 7532475Sbostic pp->dir -= MAXDIR; 7632475Sbostic else if (pp->dir < 0) 7732475Sbostic pp->dir += MAXDIR; 7832475Sbostic } 7932475Sbostic pp->xpos += displacement[pp->dir].dx; 8032475Sbostic pp->ypos += displacement[pp->dir].dy; 8132475Sbostic 8232475Sbostic if (pp->delayd && pp->xpos == sp->beacon[pp->delayd_no].x && 8332475Sbostic pp->ypos == sp->beacon[pp->delayd_no].y) { 8432475Sbostic pp->delayd = 0; 8532475Sbostic if (pp->status == S_UNMARKED) 8632475Sbostic pp->status = S_MARKED; 8732475Sbostic } 8832475Sbostic 8932475Sbostic switch (pp->dest_type) { 9032475Sbostic case T_AIRPORT: 9132475Sbostic if (pp->xpos == sp->airport[pp->dest_no].x && 9232475Sbostic pp->ypos == sp->airport[pp->dest_no].y && 9332475Sbostic pp->altitude == 0) { 9432475Sbostic if (pp->dir != sp->airport[pp->dest_no].dir) 9532475Sbostic loser(pp, "landed in the wrong direction."); 9632475Sbostic else { 9732475Sbostic pp->status = S_GONE; 9832475Sbostic continue; 9932475Sbostic } 10032475Sbostic } 10132475Sbostic break; 10232475Sbostic case T_EXIT: 10332475Sbostic if (pp->xpos == sp->exit[pp->dest_no].x && 10432475Sbostic pp->ypos == sp->exit[pp->dest_no].y) { 10532475Sbostic if (pp->altitude != 9) 10632475Sbostic loser(pp, "exited at the wrong altitude."); 10732475Sbostic else { 10832475Sbostic pp->status = S_GONE; 10932475Sbostic continue; 11032475Sbostic } 11132475Sbostic } 11232475Sbostic break; 11332475Sbostic default: 11432475Sbostic loser(pp, "has a bizarre destination, get help!"); 11532475Sbostic } 11632475Sbostic if (pp->altitude > 9) 11732475Sbostic /* "this is impossible" */ 11832475Sbostic loser(pp, "exceded flight ceiling."); 11932475Sbostic if (pp->altitude <= 0) { 12032475Sbostic for (i = 0; i < sp->num_airports; i++) 12132475Sbostic if (pp->xpos == sp->airport[i].x && 12232475Sbostic pp->ypos == sp->airport[i].y) { 12332475Sbostic if (pp->dest_type == T_AIRPORT) 12432475Sbostic loser(pp, 12532475Sbostic "landed at the wrong airport."); 12632475Sbostic else 12732475Sbostic loser(pp, 12832475Sbostic "landed instead of exited."); 12932475Sbostic } 13032475Sbostic loser(pp, "crashed on the ground."); 13132475Sbostic } 13232475Sbostic if (pp->xpos < 1 || pp->xpos >= sp->width - 1 || 13332475Sbostic pp->ypos < 1 || pp->ypos >= sp->height - 1) { 13432475Sbostic for (i = 0; i < sp->num_exits; i++) 13532475Sbostic if (pp->xpos == sp->exit[i].x && 13632475Sbostic pp->ypos == sp->exit[i].y) { 13732475Sbostic if (pp->dest_type == T_EXIT) 13832475Sbostic loser(pp, 13932475Sbostic "exited via the wrong exit."); 14032475Sbostic else 14132475Sbostic loser(pp, 14232475Sbostic "exited instead of landed."); 14332475Sbostic } 14432475Sbostic loser(pp, "illegally left the flight arena."); 14532475Sbostic } 14632475Sbostic } 14732475Sbostic 14832475Sbostic /* 14932475Sbostic * Traverse the list once, deleting the planes that are gone. 15032475Sbostic */ 15132475Sbostic for (pp = air.head; pp != NULL; pp = p2) { 15232475Sbostic p2 = pp->next; 15332475Sbostic if (pp->status == S_GONE) { 15432475Sbostic safe_planes++; 15532475Sbostic delete(&air, pp); 15632475Sbostic } 15732475Sbostic } 15832475Sbostic 15932475Sbostic draw_all(); 16032475Sbostic 16132475Sbostic for (p1 = air.head; p1 != NULL; p1 = p1->next) 16232475Sbostic for (p2 = p1->next; p2 != NULL; p2 = p2->next) 16332475Sbostic if (too_close(p1, p2, 1)) { 16432475Sbostic static char buf[80]; 16532475Sbostic 16632476Sbostic (void)sprintf(buf, "collided with plane '%c'.", 16732475Sbostic name(p2)); 16832475Sbostic loser(p1, buf); 16932475Sbostic } 17032475Sbostic /* 17132475Sbostic * Check every other update. Actually, only add on even updates. 17232475Sbostic * Otherwise, prop jobs show up *on* entrance. Remember that 17332475Sbostic * we don't update props on odd updates. 17432475Sbostic */ 17532475Sbostic if ((rand() % sp->newplane_time) == 0) 17632475Sbostic addplane(); 17732475Sbostic 17832475Sbostic #ifdef BSD 17932475Sbostic sigsetmask(mask); 18032475Sbostic #endif 18132475Sbostic #ifdef SYSV 18232475Sbostic alarm(sp->update_secs); 18332475Sbostic #endif 18432475Sbostic } 18532475Sbostic 18632475Sbostic char * 18732475Sbostic command(pp) 18832475Sbostic PLANE *pp; 18932475Sbostic { 19032475Sbostic static char buf[50], *bp, *comm_start; 191*33144Sbostic char *index(); 19232475Sbostic 19332475Sbostic buf[0] = '\0'; 19432475Sbostic bp = buf; 19532476Sbostic (void)sprintf(bp, "%c%d%c%c%d: ", name(pp), pp->altitude, 19632475Sbostic (pp->fuel < LOWFUEL) ? '*' : ' ', 19732475Sbostic (pp->dest_type == T_AIRPORT) ? 'A' : 'E', pp->dest_no); 19832475Sbostic 19932475Sbostic comm_start = bp = index(buf, '\0'); 20032475Sbostic if (pp->altitude == 0) 20132476Sbostic (void)sprintf(bp, "Holding @ A%d", pp->orig_no); 20232475Sbostic else if (pp->new_dir >= MAXDIR || pp->new_dir < 0) 20332475Sbostic strcpy(bp, "Circle"); 20432475Sbostic else if (pp->new_dir != pp->dir) 20532476Sbostic (void)sprintf(bp, "%d", dir_deg(pp->new_dir)); 20632475Sbostic 20732475Sbostic bp = index(buf, '\0'); 20832475Sbostic if (pp->delayd) 20932476Sbostic (void)sprintf(bp, " @ B%d", pp->delayd_no); 21032475Sbostic 21132475Sbostic bp = index(buf, '\0'); 21232475Sbostic if (*comm_start == '\0' && 21332475Sbostic (pp->status == S_UNMARKED || pp->status == S_IGNORED)) 21432475Sbostic strcpy(bp, "---------"); 21532475Sbostic return (buf); 21632475Sbostic } 21732475Sbostic 21832475Sbostic /* char */ 21932475Sbostic name(p) 22032475Sbostic PLANE *p; 22132475Sbostic { 22232475Sbostic if (p->plane_type == 0) 22332475Sbostic return ('A' + p->plane_no); 22432475Sbostic else 22532475Sbostic return ('a' + p->plane_no); 22632475Sbostic } 22732475Sbostic 22832475Sbostic number(l) 22932475Sbostic { 23032475Sbostic if (l < 'a' && l > 'z' && l < 'A' && l > 'Z') 23132475Sbostic return (-1); 23232475Sbostic else if (l >= 'a' && l <= 'z') 23332475Sbostic return (l - 'a'); 23432475Sbostic else 23532475Sbostic return (l - 'A'); 23632475Sbostic } 23732475Sbostic 23832475Sbostic next_plane() 23932475Sbostic { 24032475Sbostic static int last_plane = -1; 24132475Sbostic PLANE *pp; 24232475Sbostic int found, start_plane = last_plane; 24332475Sbostic 24432475Sbostic do { 24532475Sbostic found = 0; 24632475Sbostic last_plane++; 24732475Sbostic if (last_plane >= 26) 24832475Sbostic last_plane = 0; 24932475Sbostic for (pp = air.head; pp != NULL; pp = pp->next) 25032475Sbostic if (pp->plane_no == last_plane) { 25132475Sbostic found++; 25232475Sbostic break; 25332475Sbostic } 25432475Sbostic if (!found) 25532475Sbostic for (pp = ground.head; pp != NULL; pp = pp->next) 25632475Sbostic if (pp->plane_no == last_plane) { 25732475Sbostic found++; 25832475Sbostic break; 25932475Sbostic } 26032475Sbostic } while (found && last_plane != start_plane); 26132475Sbostic if (last_plane == start_plane) 26232475Sbostic return (-1); 26332475Sbostic return (last_plane); 26432475Sbostic } 26532475Sbostic 26632475Sbostic addplane() 26732475Sbostic { 26832475Sbostic PLANE p, *pp, *p1; 26932475Sbostic int i, num_starts, close, rnd, rnd2, pnum; 27032475Sbostic 27132475Sbostic bzero(&p, sizeof (p)); 27232475Sbostic 27332475Sbostic p.status = S_MARKED; 27432475Sbostic p.plane_type = random() % 2; 27532475Sbostic 27632475Sbostic num_starts = sp->num_exits + sp->num_airports; 27732475Sbostic rnd = random() % num_starts; 27832475Sbostic 27932475Sbostic if (rnd < sp->num_exits) { 28032475Sbostic p.dest_type = T_EXIT; 28132475Sbostic p.dest_no = rnd; 28232475Sbostic } else { 28332475Sbostic p.dest_type = T_AIRPORT; 28432475Sbostic p.dest_no = rnd - sp->num_exits; 28532475Sbostic } 28632475Sbostic 28732475Sbostic /* loop until we get a plane not near another */ 28832475Sbostic for (i = 0; i < num_starts; i++) { 28932475Sbostic /* loop till we get a different start point */ 29032475Sbostic while ((rnd2 = random() % num_starts) == rnd) 29132475Sbostic ; 29232475Sbostic if (rnd2 < sp->num_exits) { 29332475Sbostic p.orig_type = T_EXIT; 29432475Sbostic p.orig_no = rnd2; 29532475Sbostic p.xpos = sp->exit[rnd2].x; 29632475Sbostic p.ypos = sp->exit[rnd2].y; 29732475Sbostic p.new_dir = p.dir = sp->exit[rnd2].dir; 29832475Sbostic p.altitude = p.new_altitude = 7; 29932475Sbostic close = 0; 30032475Sbostic for (p1 = air.head; p1 != NULL; p1 = p1->next) 30132475Sbostic if (too_close(p1, &p, 4)) { 30232475Sbostic close++; 30332475Sbostic break; 30432475Sbostic } 30532475Sbostic if (close) 30632475Sbostic continue; 30732475Sbostic } else { 30832475Sbostic p.orig_type = T_AIRPORT; 30932475Sbostic p.orig_no = rnd2 - sp->num_exits; 31032475Sbostic p.xpos = sp->airport[p.orig_no].x; 31132475Sbostic p.ypos = sp->airport[p.orig_no].y; 31232475Sbostic p.new_dir = p.dir = sp->airport[p.orig_no].dir; 31332475Sbostic p.altitude = p.new_altitude = 0; 31432475Sbostic } 31532475Sbostic p.fuel = sp->width + sp->height; 31632475Sbostic break; 31732475Sbostic } 31832475Sbostic if (i >= num_starts) 31932475Sbostic return (-1); 32032475Sbostic pnum = next_plane(); 32132475Sbostic if (pnum < 0) 32232475Sbostic return (-1); 32332475Sbostic p.plane_no = pnum; 32432475Sbostic 32532475Sbostic pp = newplane(); 32632475Sbostic bcopy(&p, pp, sizeof (p)); 32732475Sbostic 32832475Sbostic if (pp->orig_type == T_AIRPORT) 32932475Sbostic append(&ground, pp); 33032475Sbostic else 33132475Sbostic append(&air, pp); 33232475Sbostic 33332475Sbostic return (pp->dest_type); 33432475Sbostic } 33532475Sbostic 33632475Sbostic PLANE * 33732475Sbostic findplane(n) 33832475Sbostic { 33932475Sbostic PLANE *pp; 34032475Sbostic 34132475Sbostic for (pp = air.head; pp != NULL; pp = pp->next) 34232475Sbostic if (pp->plane_no == n) 34332475Sbostic return (pp); 34432475Sbostic for (pp = ground.head; pp != NULL; pp = pp->next) 34532475Sbostic if (pp->plane_no == n) 34632475Sbostic return (pp); 34732475Sbostic return (NULL); 34832475Sbostic } 34932475Sbostic 35032475Sbostic too_close(p1, p2, dist) 35132475Sbostic PLANE *p1, *p2; 35232475Sbostic { 35332475Sbostic if (ABS(p1->altitude - p2->altitude) <= dist && 35432475Sbostic ABS(p1->xpos - p2->xpos) <= dist && ABS(p1->ypos - p2->ypos) <= dist) 35532475Sbostic return (1); 35632475Sbostic else 35732475Sbostic return (0); 35832475Sbostic } 35932475Sbostic 36032475Sbostic dir_deg(d) 36132475Sbostic { 36232475Sbostic switch (d) { 36332475Sbostic case 0: return (0); 36432475Sbostic case 1: return (45); 36532475Sbostic case 2: return (90); 36632475Sbostic case 3: return (135); 36732475Sbostic case 4: return (180); 36832475Sbostic case 5: return (225); 36932475Sbostic case 6: return (270); 37032475Sbostic case 7: return (315); 37132475Sbostic default: 37232475Sbostic return (-1); 37332475Sbostic } 37432475Sbostic } 375