con_vec drive(situation& s) { con_vec result; if( s.starting ) { result.fuel_amount = MAX_FUEL; RequestedPitStop = false; result.alpha = 0.0; result.vc = s.v + 50; return result; } if( JoyStick.GetStatus(js) ) { // steering if( js.x > 5000 ) // right result.alpha = -0.1; else if( js.x < -5000 ) // left result.alpha = 0.1; else // straight result.alpha = 0.0; // speed if( js.button1 ) // accelerate result.vc = s.v + 50; else // hold speed result.vc = s.v; if( js.button2 ) // brake { // simple ABS if( result.alpha == 0.0 ) result.vc = 0.0; else result.vc = s.v * 0.9; } // pit stop if( js.button3 ) { RequestedPitStop = true; } if( RequestedPitStop ) { // if is comming out of pits if( s.out_pits == 1) { RequestedPitStop = false; } else { // Request pit stop result.request_pit = 1; result.fuel_amount = MAX_FUEL; result.repair_amount = MAX_DAMAGE; } } } // use an internal function to get back on track when stuck if( s.out_pits!=1 && stuck( s.backward, s.v, s.vn, s.to_lft, s.to_rgt, &result.alpha, &result.vc ) ) { return result; } return result; }
void BaseCreatureEntity::animatePhysics(float delay) { velocity.x *= viscosity; velocity.y *= viscosity; float velx = velocity.x; float vely = velocity.y; if (specialState[SpecialStateSlow].active) { velx *= specialState[SpecialStateSlow].param1; vely *= specialState[SpecialStateSlow].param1; } if (recoil.active) { if (recoil.stun) { velx = 0.0f; vely = 0.0f; } velx += recoil.velocity.x; vely += recoil.velocity.y; } spin *= viscosity; angle += spin * delay; if (isCollidingWithMap()) { stuck(); } else { if ((int)velx > 0) { x += velx * delay; if (collideWithMap(DIRECTION_LEFT)) { x = (float)((int)x); while (collideWithMap(DIRECTION_LEFT)) x--; collideMapRight(); } else if (x > map->getWidth() * tileWidth + offsetX) { exitMap(DIRECTION_RIGHT); } } else if ((int)velx < 0) { x += velx * delay; if (collideWithMap(DIRECTION_RIGHT)) { x = (float)((int)x); while (collideWithMap(DIRECTION_RIGHT)) x++; collideMapLeft(); } else if (x < offsetX) { exitMap(DIRECTION_LEFT); } } } vely += weight * delay; if ( vely > maxY) vely = maxY; if ((int)vely > 0) { y += vely * delay; if (collideWithMap(DIRECTION_BOTTOM)) { y = (float)((int)y); while (collideWithMap(DIRECTION_BOTTOM)) y--; collideMapBottom(); } } else if ((int)vely < 0) { y += vely * delay; if (collideWithMap(DIRECTION_TOP)) { y = (float)((int)y); while (collideWithMap(DIRECTION_TOP)) y++; collideMapTop(); } } if (lifetime > 0) { if (age >= lifetime) dyingFromAge(); } age += delay; }
void CollidingSpriteEntity::animate(float delay) { velocity.x *= viscosity; velocity.y *= viscosity; spin *= viscosity; angle += spin * delay; velocity.y += weight * delay; if ((int)velocity.x > 0) { x += velocity.x * delay; if (collideWithMap(DIRECTION_LEFT)) { x = (float)((int)x); while (collideWithMap(DIRECTION_LEFT)) x--; collideMapRight(); } else if (x > map->getWidth() * tileWidth + offsetX) { exitMap(DIRECTION_RIGHT); } } else if ((int)velocity.x < 0) { x += velocity.x * delay; if (collideWithMap(DIRECTION_RIGHT)) { x = (float)((int)x); while (collideWithMap(DIRECTION_RIGHT)) x++; collideMapLeft(); } else if (x < offsetX) { exitMap(DIRECTION_LEFT); } } velocity.y += weight * delay; if ( velocity.y > maxY) velocity.y = maxY; if (isCollidingWithMap()) { stuck(); } else { if ((int)velocity.y > 0) { y += velocity.y * delay; if (collideWithMap(DIRECTION_BOTTOM)) { y = (float)((int)y); while (collideWithMap(DIRECTION_BOTTOM)) y--; collideMapBottom(); } } else if ((int)velocity.y < 0) { y += velocity.y * delay; if (collideWithMap(DIRECTION_TOP)) { y = (float)((int)y); while (collideWithMap(DIRECTION_TOP)) y++; collideMapTop(); } } } // for platforming /* if ((int)weight == 0) { if (!(isOnGround())) { makeFall(); } }*/ if (lifetime > 0) { if (age >= lifetime) isDying = true; } age += delay; }
con_vec Ralph2(situation &s) { static int firstcall = 1; con_vec result = CON_VEC_EMPTY; // This is what is returned. double ideal_alpha; int segnum, nxtseg, nxtnxtseg; if (firstcall) { // this is the very first call my_name_is("Ralph2"); // this lets everyone know who // we are. firstcall = 0; // theres only one first call return result; // must return an answer } if (s.starting) { track = get_track_description(); } if(stuck(s.backward, s.v,s.vn, s.to_lft,s.to_rgt, &result.alpha,&result.vc)) return result; getabsxy(s.seg_ID, s.to_lft, s.to_rgt, s.to_end); // point A segnum = s.seg_ID; nxtseg = (segnum+1)%track.NSEG; nxtnxtseg = (nxtseg+1)%track.NSEG; if (s.cur_rad == 0.0) ideal_alpha = angleforcurve(nxtseg, s.v); else { // look for either an s curve or a situation where we have // an s curve with a straight in the middle ideal_alpha = angleforcurve(segnum, s.v); if (curveradiuslow(nxtseg) != 0) { // one curve following another. // now we look to see if we have an s-curve situation if (curveradiuslow(segnum) * curveradiuslow(nxtseg) < 0) { double nextcurvealpha = angleforcurve(nxtseg, s.v); // can we see next curve if ( (curveradiuslow(segnum) > 0 && nextcurvealpha < ideal_alpha) || (curveradiuslow(segnum) < 0 && nextcurvealpha > ideal_alpha) ) ideal_alpha = nextcurvealpha; } } else { // not an s curve, check for opposite direction curves with // an intervening straight if (curveradiuslow(segnum) * curveradiuslow(nxtnxtseg) < 0) { double nextcurvealpha = angleforcurve(nxtnxtseg, s.v); // can we see next curve if ( (curveradiuslow(segnum) > 0 && nextcurvealpha < ideal_alpha) || (curveradiuslow(segnum) < 0 && nextcurvealpha > ideal_alpha) ) ideal_alpha = nextcurvealpha; } } } result.alpha = ideal_alpha - gc_dot; // point B getspeed(s, result); link_alpha_and_vc(s, result); avoidcars2(s, result); if(s.starting) result.fuel_amount = MAX_FUEL; result.request_pit = 0; if (s.stage != QUALIFYING && (s.damage > 25000 || s.fuel < 10)) { result.request_pit = 1; result.repair_amount=s.damage; result.fuel_amount = MAX_FUEL; } return result; }
char Agent::percept() { int x = head().X; int y = head().Y; //cout << "head : " << x << " , " << y << endl; string moves; if(Team()==1) moves="drul"; //harkat da jahate padsaat gard else moves="uldr"; // harkat da jahate saat gard for (int i =0;i<map->MapSize.X;i++) for (int j =0;j<map->MapSize.Y;j++) mark[i][j]=false; //hameye mark haro false mikone! hamaro pak mikone for (int i =0;i<map->MapSize.X;i++) for (int j =0;j<map->MapSize.Y;j++) enemy_mark[i][j]=false; //hameye enemy_mark haro false mikone! hamaro pak mikone for (int i =0;i<4;i++) for (int j =0;j<4;j++) score[i][j]=0; //hameye score haro 0 mikone for (int move=0;move<4;move++) // emtiaz dehi be har harekat { Point here_now; here_now.X=nextX(x,moves[move]); here_now.Y=nextY(y,moves[move]); //mark[here_now.X][here_now.Y]=true;//jaii ke mire! if (isEmpty(here_now.X,here_now.Y)) // age por bood ke hichi! { //cout << "x and y now :" << here_now.X << " , "<<here_now.Y; score[move][1]=painting(here_now,'m')+1; //chand ta khoone mitoone bere //cout << "painting of " << moves[move] <<" is : "<< score[move][1] << endl; Point enemy_head=ehead(); //sare yaroo ro mirize to enemy_head int enemy_score[4]={0}; // emtiaz haro hame 0 mokine! enemy_mark[here_now.X][here_now.Y]=true; //injaii ro ke alan hast mark mikone! for (int enemy_move=0;enemy_move<4;enemy_move++) //baraye har harekat harif mikhad emtiaz hesab bokone { Point enemy_pos; enemy_pos.X=nextX(enemy_head.X,moves[enemy_move]); enemy_pos.Y=nextY(enemy_head.Y,moves[enemy_move]); enemy_mark[enemy_pos.X][enemy_pos.Y]=true; if (isEmpty(enemy_pos.X,enemy_pos.Y)) { enemy_score[enemy_move]=painting(enemy_pos,'e'); //cout << "\t painting enemy " << moves[enemy_move] << " is : "<< enemy_score[enemy_move] << endl; //cout << "\t"<< "enemy pos: "<< enemy_pos.X << " , " << enemy_pos.Y << endl; for (int i =0;i<map->MapSize.Y;i++) //enemy mark ro 0 mikone for (int j =0;j<map->MapSize.X;j++) enemy_mark[i][j]=false; //hameye enemy_mark haro false mikone! hamaro pak mikone } } int minus=findmin(enemy_score,4,0); for (int i=0;i<4;i++) { if (enemy_score[i]!=0) enemy_score[i]=enemy_score[i]-minus; score[move][2]+=enemy_score[i]; //cout << "\t now enemy score of " << moves[i] <<" is " << enemy_score[i] <<endl; } score[move][3]=getdistance(here_now,ehead()); if (score[move][3] <= 1) {/*cout << "nazdiiiiiiiiiiik!"<<endl;*/ stuck(); } for (int i =0;i<map->MapSize.Y;i++) for (int j =0;j<map->MapSize.X;j++) mark[i][j]=false; //hameye mark haro false mikone! } } int min=10000; for (int i=0;i<4;i++) if (score[i][1]<min && score[i][1]!=0) min = score[i][1]; for (int i=0;i<4;i++) if (score[i][1]!=0) { score[i][1]=score[i][1]-min; //cout << "now the painting of " <<moves[i] << " is : " << score[i][1] <<"and the min is " << min <<endl; } min=10000; int min_id; for (int i=0;i<4;i++) if (score[i][3]<min && score[i][3]!=0) { min = score[i][3]; min_id=i; } for (int i=0;i<4;i++) { if (i!=min_id) score[i][3]=0; else score[i][3]=2; /////////////////////////////////////////////////////////////////////////////////////////////////// } //cout << "now the closest is : "<< moves[min_id] << " Point : " << score[min_id][3] << endl; //jamm score ha for (int move=0;move<4;move++) { score[move][0]+=score[move][1]+score[move][3]-score[move][2]; } int max_char_id=0; int max_score=0; for (int move=0;move<4;move++) { if (max_score<score[move][0]) { //cout <<"score move "<< moves[move] <<" is bigger than previouse :"<< score[move][0] <<endl; max_score = score[move][0]; max_char_id = move; } } cout << "our algorithm output: "<< moves[max_char_id] <<endl << "\t and the score is " << max_score<<endl ; if (max_score!=0) return moves[max_char_id]; return stuck(); //return stuck(); }
con_vec drive(situation &s) // This is the robot "driver" function: { con_vec result = CON_VEC_EMPTY; // This is what is returned. double alpha, vc; // components of result double bias; // added to servo's alpha result when entering curve double speed; // target speed for curve (next curve if straightaway) double speed_next = 0.0; // target speed for next curve when in a curve, fps. double width; // track width, feet double to_end; // distance to end of present segment in feet. static double lane; // target distance from left wall, feet static double lane0; // value of lane during early part of straightaway static int rad_was = 0; // 0, 1, or -1 to indicate type of previous segment static double lane_inc = 0.0; // an adjustment to "lane", for passing // service routine in the host software to handle getting unstuck from // from crashes and pileups: if(stuck(s.backward, s.v,s.vn, s.to_lft,s.to_rgt, &result.alpha,&result.vc)) return result; width = s.to_lft + s.to_rgt; // compute width of track // This is a little trick so that the car will not try to change lanes // during the "dragout" at the start of the race. We set "lane" to // whatever position we have been placed by the host. if(s.starting) // will be true only once lane = lane0 = s.to_lft; // better not to change lanes during "dragout" // Set "lane" during curves. This robot sets "lane" during curves to // try to maintain a small fixed distance to the inner rail. if(s.cur_rad > 0.0) // turning left { lane = MARGIN; rad_was = 1; // set this appropriate to curve. } else if(s.cur_rad < 0.0) // turning right { lane = width - MARGIN; rad_was = -1; // set this appropriate to curve. } else // straightaway: { // We will let the car go down the straigtaway in whatever "lane" it // comes out of the turn. if(rad_was) // If we just came out of a turn, then: { lane = s.to_lft; // set "lane" where we are now. if(lane < .5 * width) // but maybe push it a little more to right? lane += MARG2; // (add MARG2 if we were to left of center) lane0 = lane; // save a copy of the new "lane" value. rad_was = 0; // set this appropriate to straightaway. } // This is for the transition from straight to left turn. If we are // in a transition zone near the end of the straight, then set lane to // a linear function of s.to_end. During this zone, "lane" will change // from "lane0" upon entering the zone to MARG2 upon reaching the end // of the straightaway. ENT_SLOPE is the change in lane per change in // s.to_end. if(s.to_end < (lane0 - MARG2) / ENT_SLOPE) lane = MARG2 + ENT_SLOPE * s.to_end; } // set the bias: // Bias is an additive term in the steering servo, so that the servo // doesn't have to "hunt" much for the correct alpha value. It is an // estimate of the alpha value that would be found by the servo if there // was plenty of settling time. It is zero for straightaways. // Also, for convenience, we call the corn_spd() function here. On // the straightaway, we call it to find out the correct speed for the // corner ahead, using s.nex_rad for the radius. In the curve we of // course use the radius of the curve we are in. But also, we call it // for the next segment, to find out our target speed for the end of // the current segment, which we call speed_next. if(s.cur_rad == 0.0) { bias = 0.0; if(s.nex_rad > 0.0) speed = corn_spd(s.nex_rad + MARGIN); else if(s.nex_rad < 0.0) speed = corn_spd(-s.nex_rad + MARGIN); else speed = 250.0; // This should not execute, for a normal track file } else // we are in a curve: { if(s.nex_rad == 0.0) speed_next = 250.0; else speed_next = corn_spd(fabs(s.nex_rad) + MARGIN); speed = corn_spd(fabs(s.cur_rad) + MARGIN + fabs(lane_inc)); bias = (s.v*s.v/(speed*speed)) * atan(BIG_SLIP / speed); if(s.cur_rad < 0.0) // bias must be negative for right turn bias = -bias; } // set alpha: (This line is the complete steering servo.) alpha = STEER_GAIN * (s.to_lft - lane)/width - DAMP_GAIN * s.vn/s.v + bias; // set vc: if(s.cur_rad == 0.0) // If we are on a straightaway, { // if we are far from the end, if(s.to_end > CritDist(s.v, speed, BRAKE_ACCEL)) vc = s.v + 50.0; // pedal to the metal! else // otherwise, adjust speed for the coming turn: { if(s.v > TOO_FAST * speed) // if we're a little too fast, vc = s.v - BRAKE_SLIP; // brake hard. else if(s.v < speed/TOO_FAST) // if we're a little too slow, vc = 1.1 * speed; // accelerate hard. else // if we are very close to speed, vc = .5 * (s.v + speed); // approach the speed gently. } } else // This is when we are in a curve: (seek correct speed) { // calculate distance to end of curve: if(s.cur_rad > 0.0) to_end = s.to_end * (s.cur_rad + MARGIN); else to_end = -s.to_end * (s.cur_rad - MARGIN); // compute required braking distance and compare: // This is to slow us down for then next curve, if necessary: if(to_end <= CritDist(s.v, speed_next, BRK_CRV_ACC)) vc = s.v - BRK_CRV_SLIP; // but if there is a straight, or a faster curve next, then // we may want to accelerate: else if(to_end/width < CURVE_END && speed_next > speed) vc = .5 * (s.v + speed_next)/cos(alpha); else // normally, just calculate vc to maintain speed in corner vc = .5 * (s.v + speed)/cos(alpha); } // Passing and anti-collision code: // This code first tries to predict a collision; if no collision is // predicted, it does nothing. Collision prediction is approximate, and // is based on linear extrapolation. This can work because it is // repeated eighteen times per second of simulated time. // If a collision is predicted, then it gradually changes the // lane_inc static variable which changes alpha. // The hope is to steer around the car. When no collision is // predicted then lane_inc is gradually brought back to zero. // If a crash is about to occur, medium hard braking occurs. double x, y, vx, vy, dot, vsqr, c_time, y_close, x_close; int kount; // counts cars that are in danger of collision kount = 0; for(int i=0;i<3;i++) if (s.nearby[i].who<16) // if there is a close car { y=s.nearby[i].rel_y; // get forward distance (center-to-center) x=s.nearby[i].rel_x; // get right distance vx=s.nearby[i].rel_xdot; // get forward relative speed vy=s.nearby[i].rel_ydot; // get lateral relative speed // if the cars are getting closer, then the dot product of the relative // position and velocity vectors will be negative. dot = x * vx + y * vy; // compute dot product of vectors if(dot > -0.1) // no action if car is not approaching. continue; vsqr = vx*vx + vy*vy; // compute relative speed squared // Time to closest approach is dot product divided by speed squared: c_time = -dot / vsqr; // compute time to closest approach if(c_time > 3.0) // ignore if over three seconds continue; /* If the execution gets this far, it means that there is a car ahead of you, and getting closer, and less than 3.0 seconds away. Evaluate the situation more carefully to decide if evasive action is warranted: */ x_close = x + c_time * vx; // x coord at closest approach y_close = y + c_time * vy; // y coord at closest approach /* Due to the length of the cars, a collision will occur if x changes sign while y is less than CARLEN. This can happen before the center-to-center distance reaches its point of closest approach. */ // check if collision would occur prior to closest approach // if so, reduce c_time, re-calculate x_close and y_close: if(x_close * x < 0.0 && y < 1.1 * CARLEN) { c_time = (fabs(x) - CARWID) / fabs(vx); x_close = x + c_time * vx; // x coord at closest approach y_close = y + c_time * vy; // y coord at closest approach } // Will it be a hit or a miss? if(fabs(x_close) > 2 * CARWID || fabs(y_close) > 1.25 * CARLEN) continue; // this when a miss is predicted // If we get here there is a collision predicted ++kount; // This counts how many cars are in the way. if(kount > 1 || c_time < .85) // if more than one problem car, or if vc = s.v - BRK_CRV_SLIP; // car within .85 sec of collision, brake! // steer to avoid the other car: // if there is room, we try to pass with least x deviation if(s.cur_rad > 0.0) if(x_close < 0.0 || s.to_lft < MARGIN) // avoid scraping the inside lane_inc += DELTA_LANE; else lane_inc -= DELTA_LANE; else if(s.cur_rad < 0.0) if(x_close > 0.0 || s.to_rgt < MARGIN) lane_inc -= DELTA_LANE; else lane_inc += DELTA_LANE; else if(x_close < 0.0) // on straights, pass with least x deviation lane_inc += DELTA_LANE; else lane_inc -= DELTA_LANE; if(lane_inc > .25 * width) // limit the lane alteration to 1/4 width: lane_inc = .25 * width; else if(lane_inc < -.25 * width) lane_inc = -.25 * width; } // Here we gradually reduce lane_inc to zero if no collision is predicted: if(!kount) if(lane_inc > .1) lane_inc -= .5*DELTA_LANE; else if(lane_inc < -.001) lane_inc += .5*DELTA_LANE; // lane_inc represents an adjustment to the lane variable. This is // accomplished by changing alpha an amount equal to that which the // steering servo would have done had lane actually been changed. result.vc = vc; result.alpha = alpha - STEER_GAIN * lane_inc / width; // Pit: if the fuel is too low // Fuel: full // Damage: repair all if( s.fuel<10.0 ) { result.request_pit = 1; result.repair_amount = s.damage; result.fuel_amount = MAX_FUEL; } return result; }
con_vec drive(situation &s) { con_vec result = CON_VEC_EMPTY; // This is what is returned. double alpha, vc; // components of result static double lane = -10000; // an absurd value to show not initialized double bias, speed, width; if( s.starting ) { result.fuel_amount = MAX_FUEL; // fuel when starting } // service routine in the host software to handle getting unstuck from // from crashes and pileups: if(stuck(s.backward, s.v,s.vn, s.to_lft,s.to_rgt, &result.alpha,&result.vc)) return result; width = s.to_lft + s.to_rgt; // compute width of track // This is a little trick so that the car will not try to change lanes // during the "dragout" at the start of the race. We set "lane" to // whatever position we have been placed by the host. if(lane < -9000) // will be true only once lane = s.to_lft; // better not to change lanes at the start // Set "lane" during curves. This robot sets "lane" during curves to // try to maintain a fixed distance to the inner rail. // For straightaways, we leave "lane" unchanged until later. if(s.cur_rad > 0.0) // turning left lane = DIST_FROM_INSIDE; else if(s.cur_rad < 0.0) // turning right lane = width - DIST_FROM_INSIDE; // set the bias: // Bias is an additive term in the steering servo, so that the servo // doesn't have to "hunt" much for the correct alpha value. It is an // estimate of the alpha value that would be found by the servo if there // was plenty of settling time. It is zero for straightaways. // Also, for convenience, we call the corn_spd() function here. On // the straightaway, we call it to find out the correct speed for the // corner ahead, using s.nex_rad for the radius. In the curve we of // course use the radius of the curve we are in. if(s.cur_rad == 0.0) { bias = 0.0; speed = corn_spd(s.nex_rad + DIST_FROM_INSIDE); } else { speed = corn_spd(s.cur_rad + DIST_FROM_INSIDE); // See initial paragraphs for discussion of this formula. bias = (s.v*s.v/(speed*speed)) * atan(BIG_SLIP / speed); if(s.cur_rad < 0.0) // bias must be negative for right turn bias = -bias; } // set alpha: (This line is the complete steering servo.) alpha = STEER_GAIN * (s.to_lft - lane)/width - DAMP_GAIN * s.vn/s.v + bias; // set vc: When nearing end of straight, change "lane" for the turn, also. if(s.cur_rad == 0.0) // If we are on a straightaway, { if(s.to_end > ACCEL_FRACTION * s.cur_len) // if we are far from the end, { vc = s.v + 50.0; // pedal to the metal! } else // otherwise, adjust speed for the coming turn: { if(s.v > 1.02 * speed) // if we're 2% too fast, vc = .95 * s.v; // brake hard. else if(s.v < .98 * speed) // if we're 2% too slow, vc = 1.05 * speed; // accelerate hard. else // if we are very close to speed, vc = .5 * (s.v + speed); // approach the speed gently. // approach the lane you want for the turn: if(s.nex_rad > 0.0) lane = DIST_FROM_INSIDE; else lane = width - DIST_FROM_INSIDE; } } else // This is when we are in a curve: (seek correct speed) { vc = .5 * (s.v + speed)/cos(alpha); // to maintain speed in corner } // During the acceleration portion of a straightaway, the lane variable // is not changed by the code above. Hence the code below changes it a // little at a time until there is no car dead_ahead. This code here has // no affect at all in the turns, nor in the braking portion // of the straight. if(s.dead_ahead) // Change the lane a little if someone's if(s.to_lft > s.to_rgt) // in your way. lane -= DELTA_LANE; // lane must be a static variable else lane += DELTA_LANE; result.vc = vc; result.alpha = alpha; // Pit: if the fuel is too low // Fuel: full // Damage: repair all if( s.fuel<10.0 ) { result.request_pit = 1; result.repair_amount = s.damage; result.fuel_amount = MAX_FUEL; } return result; }
con_vec Djoefe (situation & s) { const char name[] = "Djoefe"; // This is the robot driver's name! static int init_flag = 1; // cleared by first call con_vec result; // This is what is returned. double alpha, vc; // components of result static double lane = -10000; // an absurd value to show not initialized double bias, speed, width, to_end; double speed_next= 0.0; static double fuel_total = 0; static double fuel_last; double aftaft_bd, after_bd, bd_now; // Load the optimization stuff for this track #ifdef OPTIMIZE static int optinit = 0; if(optinit==0) { // Reload the population from the data file const char* optfile = "djoefe.opt"; data.load(optfile,Population,GeneticLength,SetTrackData); cout << "\nOptimizing for track in " << optfile << endl; optinit = 1; } #endif //OPTIMIZE if (init_flag == 1) { // first time only, copy name: my_name_is (name); // copy the name string into the host program init_flag = 0; result.alpha = result.vc = 0; return result; } // set fuel for qualifications if (s.starting && s.stage == QUALIFYING) result.fuel_amount = 20; // estimate available friction: useful_friction = 0.975 * my_friction - 0.2 * s.damage * s.damage / 9e8; // drive carefully on first laps: // if(lap_count - s.laps_to_go < 2 && s.position >= 4) // useful_friction *= .9*my_friction; // service routine in the host software to handle getting unstuck from // from crashes and pileups: #ifndef OPTIMIZE if (stuck (s.backward, s.v, s.vn, s.to_lft, s.to_rgt, &result.alpha, &result.vc)) return result; #endif //OPTIMIZE width = s.to_lft + s.to_rgt; // compute width of track // This is a little trick so that the car will not try to change lanes // during the "dragout" at the start of the race. We set "lane" to // whatever position we have been placed by the host. if (lane < -9000) // will be true only once { fuel_last = s.fuel; // setup fuel counter #ifndef OPTIMIZE set_track_data (); #endif lane = s.to_lft; // better not to change lanes at the start slip = BIG_SLIP; t = get_track_description (); if( !args.m_iSurface ) // friction model 0: my_friction = slip / (slip + 2.5); else // friction model 1: my_friction = 1.05 * (1.0 - exp (-slip / 2.5)); } #ifdef OPTIMIZE if(s.starting) { // Figure out a nice estimate of the MPH, or how far we // got around the track double mph = optimizedata::mph(lastlaptime,t.length,lastdamage,lastdistance); if(no_display) { cout << " Mph: " << mph << endl; } // Tell the optimizer what the last MPH was data.step(mph); AbortRace = 0; } #endif //OPTIMIZE // Curve control 1 // a) If we are in a curve, go to the inside // b) If we are exiting the curve into a straight then "slide" out of the curve // Sharp left if (s.cur_rad > 0.0 && s.cur_rad < straight_radius) { if (is_nex_straight (s) && s.to_end <= s.cur_len * (1 - out_of_curve)) { lane = width - dist_from_outside; } else { lane = dist_from_inside; } } // Sharp right else if (s.cur_rad < 0.0 && s.cur_rad > -straight_radius) { if (is_nex_straight (s) && s.to_end <= s.cur_len * (1 - out_of_curve)) { lane = dist_from_outside; } else { lane = width - dist_from_inside; } } // set the bias: // Bias is an additive term in the steering servo, so that the servo // doesn't have to "hunt" much for the correct alpha value. It is an // estimate of the alpha value that would be found by the servo if there // was plenty of settling time. It is zero for straightaways. // Also, for convenience, we call the corn_spd() function here. On // the straightaway, we call it to find out the correct speed for the // corner ahead, using s.nex_rad for the radius. In the curve we of // course use the radius of the curve we are in. But also, we call it // for the next segment, to find out our target speed for the end of // the current segment, which we call speed_next. if (s.cur_rad == 0.0) { bias = 0.0; if (!is_nex_straight (s)) speed = curvespeed (s, fabs(s.nex_rad) + width * predict_width); else speed = 250.0; } else { if (is_nex_straight(s)) speed_next = 250.0; else speed_next = curvespeed (s, fabs (s.nex_rad) + width * predict_width); if(!is_curr_straight(s)) speed = curvespeed (s, fabs (s.cur_rad) + width * predict_width); else speed = 250; bias = (s.v * s.v / (speed * speed)) * atan (BIG_SLIP / speed); if (s.cur_rad < 0.0) // bias must be negative for right turn bias = -bias; } // set alpha: (This line is the complete steering servo.) alpha = steer_gain * (s.to_lft - lane) / width - damp_gain * s.vn / s.v + bias; // set vc: When nearing end of straight, change "lane" for the turn, also. if (s.cur_rad == 0.0) { // If we are on a straightaway, // if we are far from the end, if (s.to_end * ignore_slowdown > find_bd (s, speed)) { vc = s.v + 50.0; // pedal to the metal! } else { // otherwise, adjust speed for the coming turn: if (s.v > 1.02 * speed) // if we're 2% too fast, vc = brake_ratio * s.v; // brake hard. else if (s.v < .98 * speed) // if we're 2% too slow, vc = 1.1 * speed; // accelerate hard. 1.1 else // if we are very close to speed, vc = .5 * (s.v + speed); // approach the speed gently. } // Start diving into the corner if(s.to_end < (start_dive * s.v * width)) { if (s.nex_rad > 0.0) // left lane = dist_from_inside; else lane = width - dist_from_inside; } else { if (!is_nex_straight(s) && ((s.cur_len * dive_setup_dist) >= s.to_end)) { if (s.nex_rad > 0.0) lane = width - dist_for_dive; else if (s.nex_rad < 0.0) lane = dist_for_dive; } } } else { // This is when we are in a curve: (seek correct speed) // calculate vc to maintain speed in corner speed = curvespeed (s, fabs (s.cur_rad) + width * predict_width); vc = .5 * (s.v + speed); // calculate distance to end of curve if (s.cur_rad > 0.0) to_end = s.to_end * (s.cur_rad + width * predict_width); else to_end = -s.to_end * (s.cur_rad - width * predict_width); // compute required braking distance and compare: if (to_end <= find_bd (s, speed_next)) { vc = s.v - brake_curve_slip; } if (is_nex_straight (s) && s.to_end <= s.cur_len * (1 - out_of_curve)) { vc = s.v * 1.1; } } // New speed limiter if curve after next is tricky // calculate the braking distance we will need to slow down from the // speed we now have to the speed in the segment after the next aftaft_bd = find_bd(s, crvspeed(s.aftaft_rad)); after_bd = find_bd(s, crvspeed(s.after_rad)); if (aftaft_bd > (curve_length(s.nex_len, s.nex_rad) + curve_length(s.after_len, s.after_rad))) { bd_now = aftaft_bd - (curve_length(s.nex_len, s.nex_rad) + curve_length(s.after_len, s.after_rad)); if (bd_now > curve_length(s.to_end, s.cur_rad)) { vc = s.v * brake_ratio; } } // else here ? not sure... if (after_bd > (curve_length(s.nex_len, s.nex_rad))) { // We will have to start braking in this segment. // When = Total - lenght of next curve bd_now = after_bd - curve_length(s.nex_len, s.nex_rad); if (bd_now > curve_length(s.to_end, s.cur_rad)) { vc = s.v * brake_ratio; } } #ifndef BFOPT // Gotta love this passing code... ;-) if (s.dead_ahead) // Change the lane a little if someone's if (s.to_lft > s.to_rgt) // in your way. lane -= DELTA_LANE; // lane must be a static variable else lane += DELTA_LANE; if (s.lap_flag) { if (s.fuel > fuel_last) { // we refueled...use previous as estimate fuel_total += fuel_total / (s.laps_done - 1); } else { fuel_total += fuel_last - s.fuel; } fuel_last = s.fuel; } result.request_pit = 0; if (s.stage != QUALIFYING && (s.damage > 20000) && (s.laps_to_go > 5)) { result.request_pit = 1; result.repair_amount = max(s.damage, (unsigned)s.laps_to_go * 1000); result.fuel_amount = max(0,((fuel_total / s.laps_done) * (s.laps_to_go + 1)) - s.fuel); } if (s.stage != QUALIFYING && s.fuel < (fuel_total / (s.laps_done - 1)) && s.laps_done > 1) { result.request_pit = 1; result.fuel_amount = (fuel_total / s.laps_done) * (s.laps_to_go + 1); result.repair_amount = (int)result.fuel_amount * 10; } #endif result.alpha = alpha; result.vc = vc; traction_control(s, result); #ifdef OPTIMIZE // Pitting during optimizing is done differently // Keep track of the data from the last lap lastlaptime = s.lap_time; lastdamage = s.damage; lastdistance = s.distance; // result.fuel_amount = 150; result.request_pit = 0; // If we are damaged or are too close to the edge, abort the // race by deliberate crashing /* if((s.damage)|| (s.to_lft<EdgeLimit)|| (s.to_rgt<EdgeLimit)) AbortRace = 1;*/ if(AbortRace) { result.vc = 250.; result.alpha = 0.; } #endif //OPTIMIZE #ifdef SKIDMARKS extern int skidmarks; skidmarks = 1; extern int designated; designated = 0; #endif return result; }