void update(int dummy) { int i, dir_diff, unclean; PLANE *pp, *p1, *p2; clck++; erase_all(); /* put some planes in the air */ do { unclean = 0; for (pp = ground.head; pp != NULL; pp = pp->next) { if (pp->new_altitude > 0) { delete(&ground, pp); append(&air, pp); unclean = 1; break; } } } while (unclean); /* do altitude change and basic movement */ for (pp = air.head; pp != NULL; pp = pp->next) { /* type 0 only move every other turn */ if (pp->plane_type == 0 && clck & 1) continue; pp->fuel--; if (pp->fuel < 0) loser(pp, "ran out of fuel."); pp->altitude += SGN(pp->new_altitude - pp->altitude); if (!pp->delayd) { dir_diff = pp->new_dir - pp->dir; /* * Allow for circle commands */ if (pp->new_dir >= 0 && pp->new_dir < MAXDIR) { if (dir_diff > MAXDIR/2) dir_diff -= MAXDIR; else if (dir_diff < -(MAXDIR/2)) dir_diff += MAXDIR; } if (dir_diff > 2) dir_diff = 2; else if (dir_diff < -2) dir_diff = -2; pp->dir += dir_diff; if (pp->dir >= MAXDIR) pp->dir -= MAXDIR; else if (pp->dir < 0) pp->dir += MAXDIR; } pp->xpos += displacement[pp->dir].dx; pp->ypos += displacement[pp->dir].dy; if (pp->delayd && pp->xpos == sp->beacon[pp->delayd_no].x && pp->ypos == sp->beacon[pp->delayd_no].y) { pp->delayd = 0; if (pp->status == S_UNMARKED) pp->status = S_MARKED; } switch (pp->dest_type) { case T_AIRPORT: if (pp->xpos == sp->airport[pp->dest_no].x && pp->ypos == sp->airport[pp->dest_no].y && pp->altitude == 0) { if (pp->dir != sp->airport[pp->dest_no].dir) loser(pp, "landed in the wrong direction."); else { pp->status = S_GONE; continue; } } break; case T_EXIT: if (pp->xpos == sp->exit[pp->dest_no].x && pp->ypos == sp->exit[pp->dest_no].y) { if (pp->altitude != 9) loser(pp, "exited at the wrong altitude."); else { pp->status = S_GONE; continue; } } break; default: loser(pp, "has a bizarre destination, get help!"); } if (pp->altitude > 9) /* "this is impossible" */ loser(pp, "exceeded flight ceiling."); if (pp->altitude <= 0) { for (i = 0; i < sp->num_airports; i++) if (pp->xpos == sp->airport[i].x && pp->ypos == sp->airport[i].y) { if (pp->dest_type == T_AIRPORT) loser(pp, "landed at the wrong airport."); else loser(pp, "landed instead of exited."); } loser(pp, "crashed on the ground."); } if (pp->xpos < 1 || pp->xpos >= sp->width - 1 || pp->ypos < 1 || pp->ypos >= sp->height - 1) { for (i = 0; i < sp->num_exits; i++) if (pp->xpos == sp->exit[i].x && pp->ypos == sp->exit[i].y) { if (pp->dest_type == T_EXIT) loser(pp, "exited via the wrong exit."); else loser(pp, "exited instead of landed."); } loser(pp, "illegally left the flight arena."); } } /* * Traverse the list once, deleting the planes that are gone. */ for (pp = air.head; pp != NULL; pp = p2) { p2 = pp->next; if (pp->status == S_GONE) { safe_planes++; delete(&air, pp); } } draw_all(); for (p1 = air.head; p1 != NULL; p1 = p1->next) for (p2 = p1->next; p2 != NULL; p2 = p2->next) if (too_close(p1, p2, 1)) { static char buf[80]; (void)snprintf(buf, sizeof buf, "collided with plane '%c'.", name(p2)); loser(p1, buf); } /* * Check every other update. Actually, only add on even updates. * Otherwise, prop jobs show up *on* entrance. Remember that * we don't update props on odd updates. */ if ((atcrandom() % sp->newplane_time) == 0) addplane(); }
local void line_minimize ( double vect[], double direction[], double *pval_min, double *psave_x0, double *psave_a, double (*pfunction)(double vect[]) ) { double ax,bx,cx,x0,fa,fb,fc,fx0; double a,b; double old_x0,old_a; int code; if(wn_conj_direction_debug >= WN_CONJ_DIR_DBG_LINESEARCH) { printf("start line minimize.\n"); } last_line_function_x_valid = FALSE; wn_copy_vect(buffer_vect,vect,num_vars); save_vect = vect; save_direction = direction; save_pfunction = pfunction; old_x0 = *psave_x0; old_a = *psave_a; bx = 0.0; fb = *pval_min; if(wn_conj_direction_debug >= WN_CONJ_DIR_DBG_ALL) { printf("First point at %lg, function value = %lg\n", bx, fb); } if(old_x0 == 0.0) { old_x0 = 1.0; } ax = old_x0*wn_random_double_between(0.9,1.1); if(wn_conj_direction_debug >= WN_CONJ_DIR_DBG_ALL) { printf("Second point at %lg (old_x0 = %lg)\n", ax, old_x0); } fa = line_function(ax); if(!(old_a > 0.0)) { goto simple_parabola_fit; } /* the curvature along a search direction is constant for a quadratic function, therefore, try to use the curvature from the last search */ fit_parabola_2pa(&code,&x0,&b,old_a,ax,fa,bx,fb); if( (code != WN_SUCCESS) || (!(wn_abs(x0)<MAX_EXPAND*wn_abs(old_x0)) && (*psave_x0 != 0.0)) || too_close(x0, ax) || too_close(x0, bx) || !is_valid_number(x0) || !is_valid_number(ax) || !is_valid_number(bx) ) { goto simple_parabola_fit; } cx = x0; if(wn_conj_direction_debug >= WN_CONJ_DIR_DBG_ALL) { printf("Third point at %lg\n", cx); } fc = line_function(cx); wn_fit_parabola_3p(&code,&a,&x0,&b,ax,fa,bx,fb,cx,fc); if((code != WN_SUCCESS)||(!(a > 0.0))|| (!(wn_abs(x0)<MAX_EXPAND*wn_abs(old_x0))&&(*psave_x0 != 0.0))) { goto full_linesearch; } if(!(b < fb)) { if(wn_conj_direction_debug >= WN_CONJ_DIR_DBG_ALL) { printf("Doing slow line search (parabola fit returned suspect min value).\n"); } goto full_linesearch; } if((!(fc < fb))||(!(fc < fa))) { /* evaluate one more point */ goto evaluate_x0; } /* is it economical to evaluate one more point? */ if((fb-b) <= 1.5*(fb-fc)) { /* do not evaluate one more point */ wn_swap(fb,fc,double); wn_swap(bx,cx,double); goto finish; } else { /* evaluate one more point */ goto evaluate_x0; } simple_parabola_fit: if(fa < fb) { cx = 2.0*ax*wn_random_double_between(0.8,1.2); } else { cx = -1.0*ax*wn_random_double_between(0.8,1.2); } fc = line_function(cx); wn_fit_parabola_3p(&code,&a,&x0,&b,ax,fa,bx,fb,cx,fc); if((code != WN_SUCCESS)||(!(a > 0.0))|| (!(wn_abs(x0)<MAX_EXPAND*wn_abs(old_x0))&&(*psave_x0 != 0.0))) { if(wn_conj_direction_debug >= WN_CONJ_DIR_DBG_ALL) { printf("Parabola fit failed. Switching to slow line search mode.\n"); } goto full_linesearch; } evaluate_x0: fx0 = line_function(x0); if(!(fx0 <= fb)) { if(wn_conj_direction_debug >= WN_CONJ_DIR_DBG_ALL) { printf("Doing a slow line search because f(x0) is too large (x0 = %lg).\n", x0); } goto full_linesearch; } fb = fx0; bx = x0; if(!(fa <= fc)) { wn_swap(fa,fc,double); wn_swap(ax,cx,double); } if(!(fb <= fa)) { wn_swap(fb,fa,double); wn_swap(bx,ax,double); } goto finish; full_linesearch: ; /* printf("now.\n"); */ do { if(ax == bx) { if(wn_random_bit()) { ax += wn_random_double_between(-1.0,1.0); fa = line_function(ax); } else { bx += wn_random_double_between(-1.0,1.0); fb = line_function(bx); } } if(ax == cx) { if(wn_random_bit()) { ax += wn_random_double_between(-1.0,1.0); fa = line_function(ax); } else { cx += wn_random_double_between(-1.0,1.0); fc = line_function(cx); } } if(bx == cx) { if(wn_random_bit()) { bx += wn_random_double_between(-1.0,1.0); fb = line_function(bx); } else { cx += wn_random_double_between(-1.0,1.0); fc = line_function(cx); } } } while((ax == bx)||(ax == cx)||(bx == cx)); wn_minimize_1d_raw(&code,&fa,&fb,&fc,&ax,&bx,&cx,fb,&line_function,1,20); /* printf("l = %lf\n",bx); */ finish: ; /* if(show_linesearch) { printf("ax=%lg,bx=%lg,cx=%lg,old_x0=%lg\n",ax,bx,cx,old_x0); } */ wn_copy_vect(vect,buffer_vect,num_vars); /* compute *psave_x0 */ if(wn_abs(bx) < MIN_CONTRACT*wn_abs(old_x0)) { if(bx < 0.0) { *psave_x0 = -MIN_CONTRACT*wn_abs(old_x0); } else { *psave_x0 = MIN_CONTRACT*wn_abs(old_x0); } } else { *psave_x0 = bx; } /* compute *psave_a */ wn_fit_parabola_3p(&code,&a,&x0,&b,ax,fa,bx,fb,cx,fc); if((code != WN_SUCCESS)||(!(a > 0.0))) { *psave_a = 0.0; } else { *psave_a = a; } if(*pval_min == fb) { if(wn_conj_direction_debug >= WN_CONJ_DIR_DBG_LINESEARCH) { printf("finish line minimize.\n"); fflush(stdout); } return; /* do not move if no improvement */ } wn_add_scaled_vect(vect,direction,bx,num_vars); *pval_min = fb; if(wn_conj_direction_debug >= WN_CONJ_DIR_DBG_LINESEARCH) { printf("finish line minimize.\n"); fflush(stdout); } }
int addplane(void) { PLANE p, *pp, *p1; int i, num_starts, close, rnd, rnd2, pnum; memset(&p, 0, sizeof (p)); p.status = S_MARKED; p.plane_type = atcrandom() % 2; num_starts = sp->num_exits + sp->num_airports; rnd = atcrandom() % num_starts; if (rnd < sp->num_exits) { p.dest_type = T_EXIT; p.dest_no = rnd; } else { p.dest_type = T_AIRPORT; p.dest_no = rnd - sp->num_exits; } /* loop until we get a plane not near another */ for (i = 0; i < num_starts; i++) { /* loop till we get a different start point */ while ((rnd2 = atcrandom() % num_starts) == rnd) ; if (rnd2 < sp->num_exits) { p.orig_type = T_EXIT; p.orig_no = rnd2; p.xpos = sp->exit[rnd2].x; p.ypos = sp->exit[rnd2].y; p.new_dir = p.dir = sp->exit[rnd2].dir; p.altitude = p.new_altitude = 7; close = 0; for (p1 = air.head; p1 != NULL; p1 = p1->next) if (too_close(p1, &p, 4)) { close++; break; } if (close) continue; } else { p.orig_type = T_AIRPORT; p.orig_no = rnd2 - sp->num_exits; p.xpos = sp->airport[p.orig_no].x; p.ypos = sp->airport[p.orig_no].y; p.new_dir = p.dir = sp->airport[p.orig_no].dir; p.altitude = p.new_altitude = 0; } p.fuel = sp->width + sp->height; break; } if (i >= num_starts) return (-1); pnum = next_plane(); if (pnum < 0) return (-1); p.plane_no = pnum; pp = newplane(); memcpy(pp, &p, sizeof (p)); if (pp->orig_type == T_AIRPORT) append(&ground, pp); else append(&air, pp); return (pp->dest_type); }