// CNTRLb0.CPP - "driver" function for RARS 
// By Bill Benedict, Feb. 1995
// This driver is much better than bill.cpp, even if it is slower ;)
// I haven't worked to much on making this one as fast as bill.cpp, but
// it makes up its time in handling traffic much better.  In tests, bill.cpp
// will lap this driver after 100 laps or so, but in a 200 lap race with
// 8 different cars, bill.cpp was down by 2 laps at the end :)
// This driver is also heavily modified from the fast 'Kernign' driver.
// This is also my 'working' copy, so there are various bits of code
// that were added and/or commented out along the way.  Feel free to
// play with and modify this all you want :)
// (see CNTRL0.CPP for better comments)
// adapted to ver. 0.39 3/6/95 by M. Timin

#include <string.h>
#include <stdlib.h>
#include <math.h>
#include "car.h"

extern double width;
extern const double CARWID;
extern char* glob_name;

con_vec cntrlb0(situation s)
{
   const char name[] = "BillyB1";
   static int init_flag = 1;
   con_vec result;
   double alpha, vc, rad;
   double steer_gain = .2;
   const double steer_damp = .48;
   const double normalane = 30.0;
   static double vc_mult = 1.0;
   static int lane_time = 0;
   static int lane_time2 = 0;
   static int lane_change = -15;
   static double lane = 30;    // determines right-left position on straigtaway
   const double corn_con = 6.8;
   static double corn_spd = 68.0;

   if(init_flag)  {
	  strcpy(glob_name, name);
	  init_flag = 0;
	  result.alpha = result.vc = 0;
	  return result;
   }

  if(stuck(s.backward, s.v,s.vn, s.to_lft,s.to_rgt, &result.alpha,&result.vc))
      return result;

   if(s.cur_rad == 0.0 && s.nex_rad != 0.0)
	  corn_spd = corn_con * sqrt(s.nex_rad > 0.0 ? s.nex_rad : -s.nex_rad);
   else
	  corn_spd = corn_con * sqrt(s.cur_rad > 0.0 ? s.cur_rad : -s.cur_rad);

   // maybe choose a different lane: (to help in passing)
   if(!s.dead_ahead) {
	  if (lane_time <= 0) {
	lane_time=-1;
	lane = normalane+45; //+ random(5)*15;
	  }
   }
   else if (lane_time2 <= 0){
	  // pick a different lane:
	  if(lane >= 75)               // pick a new lane somehow:
	 lane_change = -15;
	  else if(lane <= -75)
	 lane_change = 15;
	  lane += lane_change;
	  if (lane > 90) lane = 90;
	  else if (lane < -90) lane = -90;
	  lane_time2=20;
	  lane_time=100;
   }
   if (lane_time >=0 ){
	 lane_time--;
	 lane_time2--;
   }
// Audible buzz when the dead_ahead flag is set for this driver
//if(s.dead_ahead) {sound(20);delay(2);nosound();}
   vc_mult=1.0;

   if((s.cur_rad == 0) && ((s.to_end/s.cur_len > .2) || (s.v < corn_spd*.8))) {
	  // in the straight-away and not speeding near a turn
	  alpha = .25 * steer_gain * (s.to_lft - s.to_rgt - lane) / width;
	  if(s.dead_ahead)
	  alpha *= 4.0;
	}
   else {
	  if(s.cur_rad == 0) {
	rad=s.nex_rad;
	vc_mult = (s.to_lft < (width/2) ? (1.25-s.to_rgt/(2*width)) : 1.0);
	  }
	  else rad=s.cur_rad;

	  if(rad > 0.0)   {
	alpha = steer_gain * (3 * (s.to_lft -
			 (s.nex_rad < 0.0 ? width/3 : 1.6*CARWID)) / width +
			 (s.cur_rad == 0 ? 0 : .05 * width/s.to_rgt));
//      if(s.dead_ahead)
//   alpha *= .7;

	  }
	  else  {
	alpha = -steer_gain * (3 * (s.to_rgt -
			 (s.nex_rad > 0.0 ? width/3 : 1.6*CARWID)) / width +
			 (s.cur_rad == 0 ? 0 :.05 * width/s.to_lft));
//      if(s.dead_ahead)
//   alpha *= .7;
	  }
   }
   alpha -= steer_damp * s.vn / s.v;  // This is damping, to prevent oscillation

   if(s.cur_rad == 0)         // If we are on a straightaway,
	  if(s.to_end/s.cur_len > .13)      // if we are far from the end:
	 vc = s.v + 85/s.v;        // keep accellerating near full power
	  else  {                 // otherwise,
	 vc = corn_spd;           // maintain cornering speed, braking at first
	 // this next formula will not work if a rt. turn follows the straight:
//   alpha += .4 * (s.cur_len/(s.to_end + s.cur_len) - (1/1.25 ));
	  }
   else            // if we're in the curve, maintain speed, +
	  vc = corn_spd + 1.2 / (s.to_end + .6);

   result.vc = vc*vc_mult;   result.alpha = alpha;
   return result;
}                                                              // v;
