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