Styled code consistently,

based on Google C++ style guide. Re #183.

git-svn-id: https://svn.code.sf.net/p/speed-dreams/code/trunk@3115 30fe4595-0a0c-4342-8851-515496e4dcbd

Former-commit-id: 7cf19bbb7bfcc767975d5bceec053d0158de249b
Former-commit-id: d4b766544d33e0bd5ace939461b6cfe7c0033d67
This commit is contained in:
kmetykog 2010-11-08 23:42:00 +00:00
parent 3061980a7a
commit 017d1d3e54
10 changed files with 1540 additions and 1531 deletions

File diff suppressed because it is too large Load diff

View file

@ -81,65 +81,68 @@ class KDriver {
void endRace(tSituation * s);
std::string bot; // to make it possible to differentiate between Kilo & Dots
// Used by Opponents
tCarElt *getCarPtr() { return m_car;}
tTrack *getTrackPtr() { return m_track;}
double getSpeed() { return m_mycardata->getSpeedInTrackDirection(); }
// Used by Opponents & Pit
tCarElt *car_ptr() const { return car_;}
tTrack *track_ptr() const { return track_;}
double speed() const { return my_cardata_->getSpeedInTrackDirection(); }
protected:
// Initialize
void initCa();
void initCw();
void initTireMu();
void initTCLFilter();
double initSkill(tSituation * s);
void InitCa();
void InitCw();
void InitTireMu();
void InitTCLFilter();
double InitSkill(tSituation * s);
// Driving aids
double filterTCL_RWD();
double filterTCL_FWD();
double filterTCL_4WD();
double filterTCL(const double accel);
double filterTrk(double accel);
double brakeDist(double allowedspeed, double mu);
double filterABS(double brake);
double filterBPit(double brake);
double FilterTCL_RWD();
double FilterTCL_FWD();
double FilterTCL_4WD();
double FilterTCL(double accel);
double FilterTrk(double accel);
double FilterABS(double brake);
double FilterBPit(double brake);
// Steering
double getSteer(tSituation * s);
double calcSteer(double targetAngle, int rl);
double correctSteering(double avoidsteer, double racesteer);
double smoothSteering(double steercmd);
vec2f getTargetPoint();
double GetSteer(tSituation * s);
double CalcSteer(double targetAngle, int rl);
double CorrectSteering(double avoidsteer, double racesteer);
double SmoothSteering(double steercmd);
double GetOffset();
vec2f TargetPoint();
// Throttle/brake handling
void CalcSpeed();
double GetAccel();
double GetBrake();
double BrakeDist(double allowedspeed, double mu) const;
double FilterBrakeSpeed(double brake);
double FilterBColl(double brake);
double FilterOverlap(double accel);
// Gear/clutch
int GetGear();
double GetClutch();
// 'own' utilities
void update(tSituation * s);
double filterBrakeSpeed(double brake);
double filterBColl(double brake);
double filterOverlap(double accel);
void calcSpeed();
void setAvoidRight() {m_avoidmode |= AVOIDRIGHT;}
void setAvoidLeft() {m_avoidmode |= AVOIDLEFT;}
void setMode(int newmode);
bool oppTooFarOnSide(tCarElt *ocar);
bool isStuck();
double getDistToSegEnd();
double getOffset();
double getAccel();
double getBrake();
int getGear();
double getClutch();
double getWidth() { return m_mycardata->getWidthOnTrack();}
void checkPitStatus(tSituation *s);
void * loadDefaultSetup() const;
void mergeCarSetups(void **oldHandle, void *newHandle);
void Update(tSituation * s);
bool IsStuck();
inline double GetDistToSegEnd() const;
void CheckPitStatus(tSituation *s);
void * LoadDefaultSetup() const;
void MergeCarSetups(void **oldHandle, void *newHandle) const;
void set_avoid_right() { avoid_mode_ |= AVOIDRIGHT; }
void set_avoid_left() { avoid_mode_ |= AVOIDLEFT; }
double width() const { return my_cardata_->getWidthOnTrack(); }
double mass() const { return CARMASS + car_->_fuel; }
double current_speed_sqr() const { return car_->_speed_x * car_->_speed_x; }
void set_mode(int newmode);
// Opponent handling
Opponent * getOverlappingOpp();
Opponent * getTakeoverOpp();
Opponent * getSidecollOpp();
double filterOverlappedOffset(Opponent *o);
double filterTakeoverOffset(Opponent *o);
double filterSidecollOffset(Opponent *o, const double);
Opponent * GetTakeoverOpp();
double FilterOverlappedOffset(const Opponent *o);
double FilterTakeoverOffset(const Opponent *o);
double FilterSidecollOffset(const Opponent *o, const double incfactor);
// Constants.
@ -147,65 +150,74 @@ class KDriver {
enum { TEAM_FRIEND = 1, TEAM_FOE };
enum { AVOIDLEFT = 1, AVOIDRIGHT = 2, AVOIDSIDE = 4 };
tCarElt *m_car; // Pointer to tCarElt struct.
LRaceLine *m_raceline;
Opponents *m_opponents; // The container for opponents.
Pit *m_pit; // Pointer to the pit instance.
KStrategy *m_strategy; // Pit stop strategy.
tTrack *m_track; // Track variables.
// Pointers to other classes
tCarElt *car_; // Pointer to tCarElt struct.
LRaceLine *raceline_; // The racing line
Opponents *opponents_; // The container for opponents.
Pit *pit_; // Pointer to the pit instance.
KStrategy *strategy_; // Pit stop strategy.
tTrack *track_; // Track variables.
static Cardata *m_cardata; // Data about all cars shared by all instances.
SingleCardata *m_mycardata; // Pointer to "global" data about my car.
static Cardata *cardata_; // Data about all cars shared by all instances.
SingleCardata *my_cardata_; // Pointer to "global" data about my car.
static double m_currentSimTime; // Store time to avoid useless updates.
static double current_sim_time_; // Store time to avoid useless updates.
// Per robot global data
int m_mode;
int m_avoidmode;
int m_lastmode;
int m_stuckCounter;
double m_speedangle; // the angle of the speed vector
// relative to trackangle, > 0.0 points to right.
double m_angle;
double m_mass; // Mass of car + fuel.
double m_myoffset; // Offset to the track middle.
double m_laststeer;
double m_lastNSasteer;
double m_simTime; // how long since the race started
double m_avoidTime; // how long since we began avoiding
double m_correctTimer; // how long we've been correcting
double m_correctLimit; // level of divergence with raceline steering
double m_brakeDelay;
double m_currentSpeedSqr; // Square of the current speed_x.
double m_clutchTime; // Clutch timer.
double m_oldLookahead; // Lookahead for steering in the previous step.
double m_raceSteer; // steer command to get to raceline
double m_rLookahead; // how far ahead on the track we look for steering
double m_raceOffset; // offset from middle of track towards which
int car_index_;
std::string car_type_;
// Driving modes
int mode_;
int avoid_mode_;
int last_mode_;
// Timers
double sim_time_; // how long since the race started
double avoid_time_; // how long since we began avoiding
double correct_timer_; // how long we've been correcting
double correct_limit_; // level of divergence with raceline steering
double clutch_time_; // clutch timer
int stuck_counter_; // to determine if we are stuck
// Car state
double angle_;
double speed_angle_; // the angle of the speed vector
// relative to trackangle, > 0.0 points to right.
double my_offset_; // Offset to the track middle.
// Raceline data
double old_lookahead_; // Lookahead for steering in the previous step.
double race_offset_; // offset from middle of track towards which
// raceline is steering
double m_avoidLftOffset; // closest opponent on the left
double m_avoidRgtOffset; // closest opponent on the right
double m_raceSpeed; // how fast raceline code says we should be going
double m_avoidSpeed; // how fast we should go if avoiding
double m_accelCmd;
double m_brakeCmd;
double m_pitOffset;
v2d m_raceTarget; // the 2d point the raceline is driving at.
double m_mincatchdist;
double m_rgtinc;
double m_lftinc;
double m_maxoffset;
double m_minoffset;
double m_rInverse;
std::string m_carType;
int m_carIndex;
double race_speed_; // how fast raceline code says we should be going
double avoid_speed_; // how fast we should go if avoiding
double brake_delay_; // configurable, brake a wee bit late
double pit_offset_; // configurable, pit lane can start late/early
// Commands
double accel_cmd_; // throttle pedal command [0..1]
double brake_cmd_; // brake pedal command [0..1]
double race_steer_; // steer command to get to raceline
double last_steer_; // previous steer command
double last_nsa_steer_;
// Handling traffic
double min_catch_dist_; // used in considering takeover
double avoid_lft_offset_; // closest opponent on the left
double avoid_rgt_offset_; // closest opponent on the right
double rgt_inc_;
double lft_inc_;
double max_offset_;
double min_offset_;
double r_inverse_;
// Skilling
double m_skill;
double m_filterBrakeSkill;
double m_filterAccelSkill;
double m_filterLookaheadSkill;
double m_filterSideSkill;
double skill_;
double brake_skill_;
double accel_skill_;
double lookahead_skill_;
double side_skill_;
// Data that should stay constant after first initialization.
int MAX_UNSTUCK_COUNT;
@ -234,6 +246,7 @@ class KDriver {
static const double LOOKAHEAD_FACTOR;
static const double WIDTHDIV;
static const double BORDER_OVERTAKE_MARGIN;
static const double SIDECOLL_MARGIN;
static const double OVERTAKE_OFFSET_SPEED;
static const double PIT_LOOKAHEAD;
static const double PIT_BRAKE_AHEAD;
@ -246,9 +259,6 @@ class KDriver {
static const double CATCH_FACTOR;
static const double TEAM_REAR_DIST;
static const double LET_OVERTAKE_FACTOR;
public:
static const int TEAM_DAMAGE_CHANGE_LEAD; // Used in opponent.cpp too
};
#endif // SRC_DRIVERS_KILO2008_KDRIVER_H_

View file

@ -35,8 +35,6 @@
using std::string;
using std::list;
// class variables and constants.
tTrack * Opponent::m_track;
// [m] distance on the track ahead to check other cars.
const double Opponent::FRONTCOLLDIST = 200.0;
// [m] distance on the track behind to check other cars.
@ -53,58 +51,62 @@ const double Opponent::LAP_BACK_TIME_PENALTY = -30.0;
const double Opponent::OVERLAP_WAIT_TIME = 5.0;
// [m/s] avoid overlapping opponents to stuck behind me.
const double Opponent::SPEED_PASS_MARGIN = 5.0;
// When to change position in the team?
const int Opponent::TEAM_DAMAGE_CHANGE_LEAD = 800;
const double Opponents::TEAM_REAR_DIST = 50.0;
// Constructor
Opponent::Opponent(tCarElt *car, SingleCardata * cardata, int index) {
m_car = car;
m_cardata = cardata;
m_index = index;
m_teammate = false;
car_ = car;
cardata_ = cardata;
index_ = index;
teammate_ = false;
}
void Opponent::update(tSituation *s, KDriver *driver) {
void Opponent::Update(tSituation *s, KDriver *driver) {
// Init state of opponent to ignore.
m_state = OPP_IGNORE;
state_ = OPP_IGNORE;
// If this car is out of the simulation or is in pits, ignore it.
if ((m_car->_state & RM_CAR_STATE_NO_SIMU)
|| (m_car->_state & RM_CAR_STATE_PIT))
if ((car_->_state & RM_CAR_STATE_NO_SIMU)
|| (car_->_state & RM_CAR_STATE_PIT))
return;
// Updating distance along the middle.
tCarElt *mycar = driver->getCarPtr();
double oppToStart = m_car->_trkPos.seg->lgfromstart + getDistToSegStart();
m_distance = oppToStart - mycar->_distFromStartLine;
if (m_distance > m_track->length / 2.0) {
m_distance -= m_track->length;
} else if (m_distance < -m_track->length / 2.0) {
m_distance += m_track->length;
tCarElt *mycar = driver->car_ptr();
tTrack *track = driver->track_ptr();
double oppToStart = car_->_trkPos.seg->lgfromstart + DistToSegStart();
distance_ = oppToStart - mycar->_distFromStartLine;
if (distance_ > track->length / 2.0) {
distance_ -= track->length;
} else if (distance_ < -track->length / 2.0) {
distance_ += track->length;
}
const double SIDECOLLDIST = MAX(m_car->_dimension_x, mycar->_dimension_x);
const double SIDECOLLDIST = MAX(car_->_dimension_x, mycar->_dimension_x);
// Is opponent in relevant range BACKCOLLDIST..FRONTCOLLDIST?
if (BetweenStrict(m_distance, BACKCOLLDIST, FRONTCOLLDIST)) {
if (BetweenStrict(distance_, BACKCOLLDIST, FRONTCOLLDIST)) {
// Is opponent aside?
if (BetweenStrict(m_distance, -SIDECOLLDIST, SIDECOLLDIST)) {
m_sidedist = m_car->_trkPos.toMiddle - mycar->_trkPos.toMiddle;
m_state |= OPP_SIDE;
if (BetweenStrict(distance_, -SIDECOLLDIST, SIDECOLLDIST)) {
state_ |= OPP_SIDE;
}
// Is opponent in front and slower?
if (m_distance > SIDECOLLDIST && getSpeed() <= driver->getSpeed()) {
m_state |= OPP_FRONT;
if (distance_ > SIDECOLLDIST && speed() <= driver->speed()) {
state_ |= OPP_FRONT;
if (isQuickerTeammate(mycar))
m_state |= OPP_FRONT_FOLLOW;
if (IsQuickerTeammate(mycar))
state_ |= OPP_FRONT_FOLLOW;
m_distance -= SIDECOLLDIST;
m_distance -= LENGTH_MARGIN;
distance_ -= SIDECOLLDIST;
distance_ -= LENGTH_MARGIN;
// If the distance is small we compute it more accurate.
if (m_distance < EXACT_DIST) {
if (distance_ < EXACT_DIST) {
straight2f carFrontLine(
mycar->_corner_x(FRNT_LFT),
mycar->_corner_y(FRNT_LFT),
@ -114,96 +116,75 @@ void Opponent::update(tSituation *s, KDriver *driver) {
mycar->_corner_y(FRNT_LFT));
double mindist = FLT_MAX;
for (int i = 0; i < 4; i++) {
vec2f corner(m_car->_corner_x(i), m_car->_corner_y(i));
for (int i = 0; i < 4; ++i) {
vec2f corner(car_->_corner_x(i), car_->_corner_y(i));
double dist = carFrontLine.dist(corner);
mindist = MIN(dist, mindist);
}
m_distance = MIN(m_distance, mindist);
distance_ = MIN(distance_, mindist);
} // if small distance
m_catchdist = driver->getSpeed() * m_distance
/ (driver->getSpeed() - getSpeed());
m_sidedist = m_car->_trkPos.toMiddle - mycar->_trkPos.toMiddle;
double cardist = fabs(m_sidedist) - fabs(getWidth() / 2.0) -
double side_dist = car_->_trkPos.toMiddle - mycar->_trkPos.toMiddle;
double cardist = fabs(side_dist) - fabs(width() / 2.0) -
mycar->_dimension_y / 2.0;
if (cardist < SIDE_MARGIN)
m_state |= OPP_COLL;
} else if (m_distance < -SIDECOLLDIST
&& getSpeed() > driver->getSpeed() - SPEED_PASS_MARGIN) {
state_ |= OPP_COLL;
} else if (distance_ < -SIDECOLLDIST
&& speed() > driver->speed() - SPEED_PASS_MARGIN) {
// Is opponent behind and faster.
m_catchdist = driver->getSpeed() * m_distance
/ (getSpeed() - driver->getSpeed());
m_state |= OPP_BACK;
m_distance -= SIDECOLLDIST;
m_distance -= LENGTH_MARGIN;
} else if (m_distance > SIDECOLLDIST && getSpeed() > driver->getSpeed()) {
state_ |= OPP_BACK;
distance_ -= SIDECOLLDIST;
distance_ -= LENGTH_MARGIN;
} else if (distance_ > SIDECOLLDIST && speed() > driver->speed()) {
// Opponent is in front and faster.
m_state |= OPP_FRONT_FAST;
if (isQuickerTeammate(mycar))
m_state |= OPP_FRONT_FOLLOW;
m_distance -= SIDECOLLDIST;
if (m_distance < 20.0 - (getSpeed() - driver->getSpeed()) * 4)
m_state |= OPP_FRONT;
state_ |= OPP_FRONT_FAST;
if (IsQuickerTeammate(mycar))
state_ |= OPP_FRONT_FOLLOW;
distance_ -= SIDECOLLDIST;
if (distance_ < 20.0 - (speed() - driver->speed()) * 4)
state_ |= OPP_FRONT;
}
}
// Check if we should let overtake the opponent.
updateOverlapTimer(s, mycar);
if (m_overlaptimer > OVERLAP_WAIT_TIME)
m_state |= OPP_LETPASS;
m_brakedistance = m_distance - m_car->_dimension_x;
} // update
UpdateOverlapTimer(s, mycar);
} // Update
// Compute the length to the start of the segment.
double Opponent::getDistToSegStart() const {
double ret = (m_car->_trkPos.seg->type == TR_STR)
? m_car->_trkPos.toStart
: m_car->_trkPos.toStart * m_car->_trkPos.seg->radius;
inline double Opponent::DistToSegStart() const {
double ret = (car_->_trkPos.seg->type == TR_STR)
? car_->_trkPos.toStart
: car_->_trkPos.toStart * car_->_trkPos.seg->radius;
return ret;
} // getDistToSegStart
// Update overlaptimers of opponents.
void Opponent::updateOverlapTimer(tSituation * const s, tCarElt * const mycar) {
if ((m_car->race.laps > mycar->race.laps) || isQuickerTeammate(mycar)) {
if (isState(OPP_BACK | OPP_SIDE)) {
m_overlaptimer += s->deltaTime;
} else if (isState(OPP_FRONT)) {
m_overlaptimer = LAP_BACK_TIME_PENALTY;
void Opponent::UpdateOverlapTimer(tSituation * const s, tCarElt * const mycar) {
if ((car_->race.laps > mycar->race.laps) || IsQuickerTeammate(mycar)) {
if (HasState(OPP_BACK | OPP_SIDE)) {
overlap_timer_ += s->deltaTime;
} else if (HasState(OPP_FRONT)) {
overlap_timer_ = LAP_BACK_TIME_PENALTY;
} else {
if (m_overlaptimer > 0.0) {
if (isState(OPP_FRONT_FAST)) {
m_overlaptimer = MIN(0.0, m_overlaptimer);
if (overlap_timer_ > 0.0) {
if (HasState(OPP_FRONT_FAST)) {
overlap_timer_ = MIN(0.0, overlap_timer_);
} else {
m_overlaptimer -= s->deltaTime;
overlap_timer_ -= s->deltaTime;
}
} else {
m_overlaptimer += s->deltaTime;
overlap_timer_ += s->deltaTime;
}
}
} else {
m_overlaptimer = 0.0;
overlap_timer_ = 0.0;
}
} // updateOverlapTimer
/**
* Returns true, if the other car is our teammate
* and has significantly less damage
* (defined in KDriver::TEAM_DAMAGE_CHANGE_LEAD)
*
* @param mycar pointer to the other car
* @return true, if the opponent is our teammate
*/
bool
Opponent::isQuickerTeammate(tCarElt * const mycar) {
return (isTeammate()
&& (mycar->_dammage - m_car->_dammage > KDriver::TEAM_DAMAGE_CHANGE_LEAD));
} // isQuickerTeammate
if (overlap_timer_ > OVERLAP_WAIT_TIME)
state_ |= OPP_LETPASS;
} // UpdateOverlapTimer
/**
@ -216,11 +197,11 @@ Opponent::isQuickerTeammate(tCarElt * const mycar) {
* @param c Opponent car data
*/
Opponents::Opponents(tSituation *s, KDriver *driver, Cardata *c) {
m_opps = new list<Opponent>;
const tCarElt *ownCar = driver->getCarPtr();
opps_ = new list<Opponent>;
const tCarElt *ownCar = driver->car_ptr();
// Step through all the cars
for (int i = 0; i < s->_ncars; i++) {
for (int i = 0; i < s->_ncars; ++i) {
// If it is not our own car
if (s->cars[i] != ownCar) {
// Create and set up new opponent
@ -228,46 +209,44 @@ Opponents::Opponents(tSituation *s, KDriver *driver, Cardata *c) {
s->cars[i], // car ptr
c->findCar(s->cars[i]), // car data ptr
i); // index
m_opps->push_back(opp); // Store it in list
opps_->push_back(opp); // Store it in list
} // if s->cars[i]
} // for i
Opponent::setTrackPtr(driver->getTrackPtr());
} // Opponents::Opponents
/**
* update
* Update
* Makes every opponent update its own data.
*
* @param s Situation provided by TORCS
* @param driver Our own robot
*/
void Opponents::update(tSituation *s, KDriver *driver) {
void Opponents::Update(tSituation *s, KDriver *driver) {
// for_each(begin(), end(), update);
for (list<Opponent>::iterator it = begin(); it != end(); it++)
it->update(s, driver);
} // update
for (list<Opponent>::iterator it = begin(); it != end(); ++it)
it->Update(s, driver);
} // Update
// for find()
inline bool operator==(const Opponent& o, const std::string s)
{ return !s.compare(o.getCarPtr()->_name); }
{ return !s.compare(o.car_ptr()->_name); }
/**
* setTeamMate
* SetTeamMate
* Search the opponent list for our own teammate,
* based on the teammate name given in the config as "teammate".
*
* @param car Our own car, to read its config
*/
void Opponents::setTeamMate(const tCarElt *car) {
void Opponents::SetTeamMate(const tCarElt *car) {
string teammate(
GfParmGetStr(car->_paramsHandle, KILO_SECT_PRIV, KILO_ATT_TEAMMATE, ""));
list<Opponent>::iterator found = find(begin(), end(), teammate);
if (found != end())
found->markAsTeamMate();
} // setTeamMate
found->set_teammate();
} // SetTeamMate
/**
@ -276,13 +255,102 @@ void Opponents::setTeamMate(const tCarElt *car) {
* @param [in] state: we only care for an opponent in this state
* @return pointer to the opponent we've found, or NULL
*/
Opponent * Opponents::getOppByState(const int state) {
Opponent * Opponents::GetOppByState(const int state) {
Opponent *ret = NULL;
for (list<Opponent>::iterator it = begin(); it != end(); it++) {
if (it->isState(state)) {
for (list<Opponent>::iterator it = begin(); it != end(); ++it) {
if (it->HasState(state)) {
ret = &(*it);
break;
}
} // for it
return ret;
} // getOppByState
} // GetOppByState
/**
* Decide if there is a car on the side we are to collide with...
*
* @param[in] car Our own car
* @return Side collision car pointer or NULL
*/
Opponent * Opponents::GetSidecollOpp(const tCarElt *car) {
Opponent *ret = NULL;
for (list<Opponent>::iterator it = begin(); it != end(); ++it) {
tCarElt *ocar = it->car_ptr();
if (ocar->_state > RM_CAR_STATE_PIT) // Dont care for opponents in the pit
continue;
// if opp is too far on side
if (it->IsTooFarOnSide(car))
continue;
if (it->HasState(OPP_SIDE)) { // If opponent is on our side
ret = &(*it);
break;
} // if OPP_SIDE
} // for it
return ret;
} // GetSidecollOpp
/**
* Decide if there is a car behind overlapping us.
*
* A1) Teammate behind with more laps should overtake.
* A2) Slipstreaming: the less damaged teammate is also allowed to pass
* if on the same lap.
* The position change happens when the damage difference is greater
* than TEAM_DAMAGE_CHANGE_LEAD.
* B) Let other, overlapping opponents get by.
* @return overlapping car pointer or NULL
*/
Opponent * Opponents::GetOverlappingOpp(const tCarElt *car) {
Opponent *ret = NULL;
double mindist = -1000.0;
for (list<Opponent>::iterator it = begin(); it != end(); ++it) {
tCarElt *ocar = it->car_ptr();
double oppDistance = it->distance();
if (( // If teammate has more laps under his belt,
(it->teammate() && ocar->race.laps > car->race.laps)
|| // or teammate is less damaged, let him go
it->IsQuickerTeammate(car))
&& (oppDistance > -TEAM_REAR_DIST) // if close enough
&& (oppDistance < -car->_dimension_x)) {
// Behind, larger distances are smaller ("more negative").
if (oppDistance > mindist) {
mindist = oppDistance;
ret = &(*it);
}
} else if (it->HasState(OPP_LETPASS)) {
// Behind, larger distances are smaller ("more negative").
if (oppDistance > mindist) {
mindist = oppDistance;
ret = &(*it);
}
} // else if
} // for i
return ret;
} // GetOverlappingOpp
/**
* Checks if opponent is too much on either side of the track,
* (doesn't occupy center part of the segment)
* and whether we are 5+ metres far.
*
* @param [in] ocar the opponent car
* @return true if the opp. is too far on either side
*/
bool Opponent::IsTooFarOnSide(const tCarElt *mycar) const {
bool ret = false;
if (fabs(car_->_trkPos.toMiddle) > mycar->_trkPos.seg->width / 2 + 3.0
&& fabs(mycar->_trkPos.toMiddle - car_->_trkPos.toMiddle) >= 5.0)
ret = true;
return ret;
} // IsTooFarOnSide

View file

@ -50,49 +50,45 @@ class Opponent {
public:
Opponent(tCarElt *car, SingleCardata *cardata, int index);
static void setTrackPtr(tTrack * const track) {Opponent::m_track = track;}
tCarElt *getCarPtr() const {return m_car;}
double getDistance() const {return m_distance;}
double getWidth() const {return m_cardata->getWidthOnTrack();}
double getSpeed() const {return m_cardata->getSpeedInTrackDirection();}
int getIndex() const {return m_index;}
// Accessors
inline tCarElt *car_ptr() const { return car_; }
inline double distance() const { return distance_; }
inline double width() const { return cardata_->getWidthOnTrack(); }
inline double speed() const { return cardata_->getSpeedInTrackDirection(); }
inline int index() const { return index_; }
inline bool teammate() const { return teammate_; }
inline bool isState(const int state) const
{ return static_cast<bool>(m_state & state); }
inline bool isTeammate() const {return m_teammate;}
bool isQuickerTeammate(tCarElt * const mycar);
inline bool isOnRight(const double dMiddle)
{ return (dMiddle > m_car->_trkPos.toMiddle) ? true : false; }
// State queries
inline bool HasState(const int state) const
{ return static_cast<bool>(state_ & state); }
inline bool IsQuickerTeammate(const tCarElt *mycar) const
{ return (teammate_
&& (mycar->_dammage - car_->_dammage > TEAM_DAMAGE_CHANGE_LEAD));}
inline bool IsOnRight(const double dMiddle) const
{ return (dMiddle > car_->_trkPos.toMiddle) ? true : false; }
bool IsTooFarOnSide(const tCarElt *mycar) const;
// Mutators
inline void set_teammate() {teammate_ = true;}
void Update(tSituation *s, KDriver *driver);
inline void markAsTeamMate() {m_teammate = true;}
void update(tSituation *s, KDriver *driver);
private:
double getDistToSegStart() const;
void updateOverlapTimer(tSituation * const s, tCarElt * const mycar);
// distance minus opponent car length
inline double brake_distance() const {return distance_ - car_->_dimension_x;}
inline double DistToSegStart() const;
void UpdateOverlapTimer(tSituation * const s, tCarElt * const mycar);
// approximation of the real distance, negative if the opponent is behind.
double m_distance;
// distance minus opponent car length
double m_brakedistance;
// distance needed to catch the opponent (linear estimate).
double m_catchdist;
// approx distance of center of gravity of the cars.
double m_sidedist;
// State variable to characterize the relation to the opponent,
// e. g. opponent is behind.
int m_state;
int m_index;
double m_overlaptimer;
double distance_;
tCarElt *m_car;
SingleCardata *m_cardata; // Pointer to global data about this opponent.
bool m_teammate; // Is this opponent a team mate of me
// TODO(kilo): configure it in setup XML?
// class variables.
static tTrack *m_track;
int state_; // State describes the relation to the opp, eg. opp is behind
int index_;
double overlap_timer_;
tCarElt *car_;
SingleCardata *cardata_; // Pointer to global data about this opponent.
bool teammate_; // Is this opponent a team mate of me
// constants.
static const double FRONTCOLLDIST;
@ -103,6 +99,7 @@ class Opponent {
static const double LAP_BACK_TIME_PENALTY;
static const double OVERLAP_WAIT_TIME;
static const double SPEED_PASS_MARGIN;
static const int TEAM_DAMAGE_CHANGE_LEAD;
};
@ -111,17 +108,20 @@ class Opponent {
class Opponents {
public:
Opponents(tSituation *s, KDriver *driver, Cardata *cardata);
~Opponents() {delete m_opps;}
~Opponents() { if (opps_ != NULL) delete opps_;}
void update(tSituation *s, KDriver *driver);
void setTeamMate(const tCarElt *car);
Opponent *getOppByState(const int state);
void Update(tSituation *s, KDriver *driver);
void SetTeamMate(const tCarElt *car);
Opponent *GetOppByState(const int state);
Opponent *GetSidecollOpp(const tCarElt *car);
Opponent *GetOverlappingOpp(const tCarElt *car);
inline std::list<Opponent>::iterator begin() {return m_opps->begin();}
inline std::list<Opponent>::iterator end() {return m_opps->end();}
inline std::list<Opponent>::iterator begin() {return opps_->begin();}
inline std::list<Opponent>::iterator end() {return opps_->end();}
private:
std::list<Opponent> *m_opps;
std::list<Opponent> *opps_;
static const double TEAM_REAR_DIST;
};

View file

@ -32,160 +32,160 @@ const double Pit::SPEED_LIMIT_MARGIN = 0.5;
Pit::Pit(const tSituation * s, KDriver * driver, const double pitoffset) {
m_track = driver->getTrackPtr();
m_car = driver->getCarPtr();
m_mypit = driver->getCarPtr()->_pit;
m_pitinfo = &m_track->pits;
m_pitstop = m_inpitlane = false;
m_pittimer = 0.0;
track_ = driver->track_ptr();
car_ = driver->car_ptr();
mypit_ = driver->car_ptr()->_pit;
pitinfo_ = &track_->pits;
pit_planned_ = in_pitlane_ = false;
pit_timer_ = 0.0;
if (m_mypit != NULL) {
m_speedlimit = m_pitinfo->speedLimit - SPEED_LIMIT_MARGIN;
m_speedlimitsqr = pow(m_speedlimit, 2);
m_pitspeedlimitsqr = pow(m_pitinfo->speedLimit, 2);
if (mypit_ != NULL) {
speed_limit_ = pitinfo_->speedLimit - SPEED_LIMIT_MARGIN;
pit_speed_limit_sqr_ = pow(pitinfo_->speedLimit, 2);
// Compute pit spline points along the track.
m_p[3].x = m_mypit->pos.seg->lgfromstart + m_mypit->pos.toStart;
m_p[2].x = m_p[3].x - m_pitinfo->len;
m_p[4].x = m_p[3].x + m_pitinfo->len;
m_p[0].x = m_pitinfo->pitEntry->lgfromstart + pitoffset;
m_p[1].x = m_pitinfo->pitStart->lgfromstart;
points_[3].x = mypit_->pos.seg->lgfromstart + mypit_->pos.toStart;
points_[2].x = points_[3].x - pitinfo_->len;
points_[4].x = points_[3].x + pitinfo_->len;
points_[0].x = pitinfo_->pitEntry->lgfromstart + pitoffset;
points_[1].x = pitinfo_->pitStart->lgfromstart;
// Use nPitSeg to respect the pit speed limit on Migrants e.a.
m_p[5].x = m_pitinfo->pitStart->lgfromstart
+ m_pitinfo->nPitSeg * m_pitinfo->len;
m_p[6].x = m_pitinfo->pitExit->lgfromstart;
points_[5].x = pitinfo_->pitStart->lgfromstart
+ pitinfo_->nPitSeg * pitinfo_->len;
points_[6].x = pitinfo_->pitExit->lgfromstart;
m_pitentry = m_p[0].x;
m_pitexit = m_p[6].x;
pit_entry_ = points_[0].x;
pit_exit_ = points_[6].x;
// Normalizing spline segments to >= 0.0.
for (int i = 0; i < NPOINTS; i++) {
m_p[i].s = 0.0;
m_p[i].x = toSplineCoord(m_p[i].x);
points_[i].s = 0.0;
points_[i].x = ToSplineCoord(points_[i].x);
} // for i
// Fix broken pit exit.
if (m_p[6].x < m_p[5].x)
m_p[6].x = m_p[5].x + 50.0;
if (points_[6].x < points_[5].x)
points_[6].x = points_[5].x + 50.0;
// Fix point for first pit if necessary.
if (m_p[1].x > m_p[2].x)
m_p[1].x = m_p[2].x;
if (points_[1].x > points_[2].x)
points_[1].x = points_[2].x;
// Fix point for last pit if necessary.
if (m_p[4].x > m_p[5].x)
m_p[5].x = m_p[4].x;
if (points_[4].x > points_[5].x)
points_[5].x = points_[4].x;
double sign = (m_pitinfo->side == TR_LFT) ? 1.0 : -1.0;
m_p[0].y = 0.0;
m_p[6].y = 0.0;
double sign = (pitinfo_->side == TR_LFT) ? 1.0 : -1.0;
points_[0].y = 0.0;
points_[6].y = 0.0;
for (int i = 1; i < NPOINTS - 1; i++) {
m_p[i].y = fabs(m_pitinfo->driversPits->pos.toMiddle) - m_pitinfo->width;
m_p[i].y *= sign;
points_[i].y = fabs(pitinfo_->driversPits->pos.toMiddle)
- pitinfo_->width;
points_[i].y *= sign;
} // for i
m_p[3].y = fabs(m_pitinfo->driversPits->pos.toMiddle + 1.0) * sign;
m_spline = new Spline(NPOINTS, m_p);
points_[3].y = fabs(pitinfo_->driversPits->pos.toMiddle + 1.0) * sign;
spline_ = new Spline(NPOINTS, points_);
} // if pit not null
} // Pit::Pit
Pit::~Pit() {
if (m_mypit != NULL)
delete m_spline;
if (mypit_ != NULL)
delete spline_;
} // Pit::~Pit
// Transforms track coordinates to spline parameter coordinates.
double Pit::toSplineCoord(const double x) const {
double ret = x - m_pitentry;
double Pit::ToSplineCoord(const double x) const {
double ret = x - pit_entry_;
while (ret < 0.0)
ret += m_track->length;
ret += track_->length;
return ret;
} // toSplineCoord
} // ToSplineCoord
// Computes offset to track middle for trajectory.
double Pit::getPitOffset(const double offset, double fromstart) {
if (m_mypit != NULL) {
if (getInPit() || (getPitstop() && isBetween(fromstart))) {
fromstart = toSplineCoord(fromstart);
return m_spline->evaluate(fromstart);
double Pit::CalcPitOffset(const double offset, double fromstart) {
if (mypit_ != NULL) {
if (in_pitlane() || (pit_planned() && is_between(fromstart))) {
fromstart = ToSplineCoord(fromstart);
return spline_->evaluate(fromstart);
}
}
return offset;
} // getPitOffset
} // CalcPitOffset
// Sets the pitstop flag if we are not in the pit range.
void Pit::setPitstop(bool pitstop) {
if (m_mypit != NULL) {
double fromstart = m_car->_distFromStartLine;
void Pit::set_pitstop(bool pitstop) {
if (mypit_ != NULL) {
double fromstart = car_->_distFromStartLine;
if (!isBetween(fromstart)) {
m_pitstop = pitstop;
if (!is_between(fromstart)) {
pit_planned_ = pitstop;
} else {
if (!pitstop) {
m_pitstop = pitstop;
m_pittimer = 0.0;
pit_planned_ = pitstop;
pit_timer_ = 0.0;
}
}
}
} // setPitstop
} // set_pitstop
// Check if the argument fromstart is in the range of the pit.
bool Pit::isBetween(const double fromstart) const {
bool Pit::is_between(const double fromstart) const {
bool ret = false;
if (m_pitentry <= m_pitexit) {
if (fromstart >= m_pitentry && fromstart <= m_pitexit) {
if (pit_entry_ <= pit_exit_) {
if (fromstart >= pit_entry_ && fromstart <= pit_exit_) {
ret = true;
}
} else {
// Warning: TORCS reports sometimes negative values for "fromstart"!
if (fromstart <= m_pitexit || fromstart >= m_pitentry) {
if (fromstart <= pit_exit_ || fromstart >= pit_entry_) {
ret = true;
}
} // if pitentry <= pitexit
return ret;
} // isBetween
} // is_between
// Checks if we stay too long without getting captured by the pit.
// Distance is the distance to the pit along the track, when the pit is
// ahead it is > 0, if we overshoot the pit it is < 0.
bool Pit::isTimeout(const double distance) {
bool Pit::is_timeout(const double distance) {
bool ret = false;
if (m_car->_speed_x > 1.0 || distance > 3.0 || !getPitstop()) {
m_pittimer = 0.0;
if (car_->_speed_x > 1.0 || distance > 3.0 || !pit_planned()) {
pit_timer_ = 0.0;
} else {
m_pittimer += RCM_MAX_DT_ROBOTS;
if (m_pittimer > 3.0) {
m_pittimer = 0.0;
pit_timer_ += RCM_MAX_DT_ROBOTS;
if (pit_timer_ > 3.0) {
pit_timer_ = 0.0;
ret = true;
}
}
return ret;
} // isTimeout
} // is_timeout
// Update pit data and strategy.
void Pit::update() {
if (m_mypit != NULL) {
if (isBetween(m_car->_distFromStartLine)) {
if (getPitstop()) {
setInPit(true);
void Pit::Update() {
if (mypit_ != NULL) {
if (is_between(car_->_distFromStartLine)) {
if (pit_planned()) {
in_pitlane_ = true;
}
} else {
setInPit(false);
in_pitlane_ = false;
}
if (getPitstop())
m_car->_raceCmd = RM_CMD_PIT_ASKED;
if (pit_planned())
car_->_raceCmd = RM_CMD_PIT_ASKED;
}
} // update
} // Update

View file

@ -36,52 +36,47 @@ class Pit {
Pit(const tSituation * s, KDriver * driver, const double PitOffset);
~Pit();
void setPitstop(const bool pitstop);
inline bool getPitstop() const {return m_pitstop;}
inline void setInPit(const bool inpitlane) {m_inpitlane = inpitlane;}
inline bool getInPit() const {return m_inpitlane;}
inline bool pit_planned() const { return pit_planned_; }
inline bool in_pitlane() const { return in_pitlane_; }
inline double speed_limit() const { return speed_limit_; }
inline double speed_limit_sqr() const { return pow(speed_limit_, 2); }
double getPitOffset(const double offset, double fromstart);
inline double n_start() const { return points_[1].x; }
inline double n_loc() const { return points_[3].x; }
inline double n_end() const { return points_[5].x; }
inline double n_entry() const { return points_[0].x; }
bool isBetween(const double fromstart) const;
bool isTimeout(const double distance);
inline double speed_limit_brake(const double speedsqr) const
{ return (speedsqr - speed_limit_sqr())
/ (pit_speed_limit_sqr_ - speed_limit_sqr()); }
inline double getNPitStart() const {return m_p[1].x;}
inline double getNPitLoc() const {return m_p[3].x;}
inline double getNPitEnd() const {return m_p[5].x;}
inline double getNPitEntry() const {return m_p[0].x;}
double toSplineCoord(double x) const;
inline double getSpeedlimitSqr() const {return m_speedlimitsqr;}
inline double getSpeedlimit() const {return m_speedlimit;}
inline double getSpeedLimitBrake(const double speedsqr) const
{return (speedsqr - m_speedlimitsqr)
/ (m_pitspeedlimitsqr - m_speedlimitsqr);}
void update();
void set_pitstop(const bool pitstop);
bool is_timeout(const double distance);
double CalcPitOffset(const double offset, double fromstart);
double ToSplineCoord(double x) const;
void Update();
private:
tTrack *m_track;
tCarElt *m_car;
tTrackOwnPit *m_mypit; // Pointer to my pit.
tTrackPitInfo *m_pitinfo; // General pit info.
bool is_between(const double fromstart) const;
enum
{ NPOINTS = 7 };
SplinePoint m_p[NPOINTS]; // Spline points.
Spline *m_spline; // Spline.
tTrack *track_;
tCarElt *car_;
tTrackOwnPit *mypit_; // Pointer to my pit.
tTrackPitInfo *pitinfo_; // General pit info.
bool m_pitstop; // Pitstop planned.
bool m_inpitlane; // We are still in the pit lane.
double m_pitentry; // Distance to start line of the pit entry.
double m_pitexit; // Distance to the start line of the pit exit.
enum { NPOINTS = 7 };
SplinePoint points_[NPOINTS]; // Spline points.
Spline *spline_; // Spline.
double m_speedlimitsqr; // Pit speed limit squared.
double m_speedlimit; // Pit speed limit.
double m_pitspeedlimitsqr; // The original speedlimit squared.
bool pit_planned_; // Pitstop planned.
bool in_pitlane_; // We are still in the pit lane.
double pit_entry_; // Distance to start line of the pit entry.
double pit_exit_; // Distance to the start line of the pit exit.
double m_pittimer; // Timer for pit timeouts.
double speed_limit_; // Pit speed limit.
double pit_speed_limit_sqr_; // The original speedlimit squared.
double pit_timer_; // Timer for pit timeouts.
static const double SPEED_LIMIT_MARGIN;
};

View file

@ -77,7 +77,7 @@ void LRaceLine::SetSegmentInfo(const tTrackSeg * pseg,
const int i, const double l) {
if (pseg) {
std::pair<int, double> info(i, l);
m_SegInfo.push_back(info);
seg_info_.push_back(info);
}
}
@ -89,7 +89,7 @@ void LRaceLine::SetSegmentInfo(const tTrackSeg * pseg,
void LRaceLine::SplitTrack(const tTrack * const ptrack,
const int rl,
const tSituation *s) {
m_lDivLength = 3; // Length of path elements in meters
div_length_ = 3; // Length of path elements in meters
const tTrackSeg *psegCurrent = ptrack->seg;
double dAngle = psegCurrent->angle[TR_ZS];
@ -115,10 +115,10 @@ void LRaceLine::SplitTrack(const tTrack * const ptrack,
} // if pits.type
m_SegInfo.reserve(ptrack->nseg);
seg_info_.reserve(ptrack->nseg);
unsigned int i = 0;
do {
int Divisions = static_cast<int>(psegCurrent->length / m_lDivLength) + 1;
int Divisions = static_cast<int>(psegCurrent->length / div_length_) + 1;
double Step = psegCurrent->length / Divisions;
SetSegmentInfo(psegCurrent, i, Step);
@ -220,30 +220,30 @@ void LRaceLine::SplitTrack(const tTrack * const ptrack,
double dx = -psegCurrent->width * sin(dAngle) / 2;
double dy = psegCurrent->width * cos(dAngle) / 2;
if (m_Seg.size() <= i) { // if it is the first run
if (seg_.size() <= i) { // if it is the first run
// Create & store new segment
rlSegment *newSeg = new rlSegment;
m_Seg.push_back(*newSeg);
seg_.push_back(*newSeg);
delete newSeg;
}
// We can be quite sure m_Seg[i] exists as we created it just above
m_Seg[i].txLeft = dXPos + dx;
m_Seg[i].tyLeft = dYPos + dy;
m_Seg[i].txRight = dXPos - dx;
m_Seg[i].tyRight = dYPos - dy;
m_Seg[i].tLane = 0.5;
m_Seg[i].tLaneLMargin = lft_margin;
m_Seg[i].tLaneRMargin = rgt_margin;
m_Seg[i].tFriction = psegCurrent->surface->kFriction;
SetSegCamber(psegCurrent, i);
// We can be quite sure seg_[i] exists as we created it just above
seg_[i].txLeft = dXPos + dx;
seg_[i].tyLeft = dYPos + dy;
seg_[i].txRight = dXPos - dx;
seg_[i].tyRight = dYPos - dy;
seg_[i].tLane = 0.5;
seg_[i].tLaneLMargin = lft_margin;
seg_[i].tLaneRMargin = rgt_margin;
seg_[i].tFriction = psegCurrent->surface->kFriction;
SetSegmentCamber(psegCurrent, i);
// cerr << i << " " << psegCurrent->name << endl;
// ??? ugly trick for dirt
// if (m_Seg[i].tFriction < 1)
// m_Seg[i].tFriction *= 0.90;
// if (seg_[i].tFriction < 1)
// seg_[i].tFriction *= 0.90;
m_Seg[i].UpdateTxTy(rl);
seg_[i].UpdateTxTy(rl);
i++;
} // for j
@ -251,26 +251,26 @@ void LRaceLine::SplitTrack(const tTrack * const ptrack,
psegCurrent = psegCurrent->next;
} while (psegCurrent != ptrack->seg);
m_cDivs = i - 1; // m_Seg.size-1!
m_dWidth = psegCurrent->width;
divs_ = i - 1; // seg_.size-1!
width_ = psegCurrent->width;
} // SplitTrack
/////////////////////////////////////////////////////////////////////////////
// Compute the inverse of the radius
/////////////////////////////////////////////////////////////////////////////
double LRaceLine::getRInverse(const int prev,
double LRaceLine::rinverse(const int prev,
const double x,
const double y,
const int next,
const int rl) const {
// vector<rlSegment>::iterator itNext = m_Seg[next];
double x1 = m_Seg[next].tx[rl] - x;
double y1 = m_Seg[next].ty[rl] - y;
double x2 = m_Seg[prev].tx[rl] - x;
double y2 = m_Seg[prev].ty[rl] - y;
double x3 = m_Seg[next].tx[rl] - m_Seg[prev].tx[rl];
double y3 = m_Seg[next].ty[rl] - m_Seg[prev].ty[rl];
// vector<rlSegment>::iterator itNext = seg_[next];
double x1 = seg_[next].tx[rl] - x;
double y1 = seg_[next].ty[rl] - y;
double x2 = seg_[prev].tx[rl] - x;
double y2 = seg_[prev].ty[rl] - y;
double x3 = seg_[next].tx[rl] - seg_[prev].tx[rl];
double y3 = seg_[next].ty[rl] - seg_[prev].ty[rl];
double det = x1 * y2 - x2 * y1;
double n1 = x1 * x1 + y1 * y1;
@ -279,7 +279,7 @@ double LRaceLine::getRInverse(const int prev,
double nnn = sqrt(n1 * n2 * n3);
return 2 * det / nnn;
} // getRInverse
} // rinverse
/////////////////////////////////////////////////////////////////////////////
@ -288,53 +288,53 @@ double LRaceLine::getRInverse(const int prev,
void LRaceLine::AdjustRadius(int prev, int i, int next,
double TargetRInverse, int rl,
double Security) {
double OldLane = m_Seg[i].tLane;
double OldLane = seg_[i].tLane;
// Start by aligning points for a reasonable initial lane
m_Seg[i].tLane = (-(m_Seg[next].ty[rl] - m_Seg[prev].ty[rl])
* (m_Seg[i].txLeft - m_Seg[prev].tx[rl])
+ (m_Seg[next].tx[rl] - m_Seg[prev].tx[rl])
* (m_Seg[i].tyLeft - m_Seg[prev].ty[rl])) /
((m_Seg[next].ty[rl] - m_Seg[prev].ty[rl])
* (m_Seg[i].txRight - m_Seg[i].txLeft)
- (m_Seg[next].tx[rl] - m_Seg[prev].tx[rl])
* (m_Seg[i].tyRight - m_Seg[i].tyLeft));
seg_[i].tLane = (-(seg_[next].ty[rl] - seg_[prev].ty[rl])
* (seg_[i].txLeft - seg_[prev].tx[rl])
+ (seg_[next].tx[rl] - seg_[prev].tx[rl])
* (seg_[i].tyLeft - seg_[prev].ty[rl])) /
((seg_[next].ty[rl] - seg_[prev].ty[rl])
* (seg_[i].txRight - seg_[i].txLeft)
- (seg_[next].tx[rl] - seg_[prev].tx[rl])
* (seg_[i].tyRight - seg_[i].tyLeft));
if (rl == LINE_RL) {
m_Seg[i].tLane = MAX(m_Seg[i].tLane, -1.2 - m_Seg[i].tLaneLMargin);
m_Seg[i].tLane = MIN(m_Seg[i].tLane, 1.2 + m_Seg[i].tLaneRMargin);
seg_[i].tLane = MAX(seg_[i].tLane, -1.2 - seg_[i].tLaneLMargin);
seg_[i].tLane = MIN(seg_[i].tLane, 1.2 + seg_[i].tLaneRMargin);
} // if rl
m_Seg[i].UpdateTxTy(rl);
seg_[i].UpdateTxTy(rl);
//
// Newton-like resolution method
//
const double dLane = 0.0001;
double dx = dLane * (m_Seg[i].txRight - m_Seg[i].txLeft);
double dy = dLane * (m_Seg[i].tyRight - m_Seg[i].tyLeft);
double dx = dLane * (seg_[i].txRight - seg_[i].txLeft);
double dy = dLane * (seg_[i].tyRight - seg_[i].tyLeft);
double dRInverse =
getRInverse(prev, m_Seg[i].tx[rl] + dx, m_Seg[i].ty[rl] + dy, next, rl);
rinverse(prev, seg_[i].tx[rl] + dx, seg_[i].ty[rl] + dy, next, rl);
if (dRInverse > 0.000000001) {
m_Seg[i].tLane += (dLane / dRInverse) * TargetRInverse;
seg_[i].tLane += (dLane / dRInverse) * TargetRInverse;
double ExtLane = MIN((m_dExtMargin + Security) / m_dWidth, 0.5);
double IntLane = MIN((m_dIntMargin + Security) / m_dWidth, 0.5);
double ExtLane = MIN((ext_margin_ + Security) / width_, 0.5);
double IntLane = MIN((int_margin_ + Security) / width_, 0.5);
// ~ //kilo HACK E-track-1
// ~ if(BetweenLoose(i, 1077, 1112)) //bus-stop
// ~ {
// ~ //ExtLane = MIN((m_dExtMargin + 20.0) / m_dWidth, 0.5);
// ~ //IntLane = MIN((m_dIntMargin + 0.0) / m_dWidth, 0.5);
// ~ //ExtLane = MIN((ext_margin_ + 20.0) / width_, 0.5);
// ~ //IntLane = MIN((int_margin_ + 0.0) / width_, 0.5);
// ~ IntLane = 0.27;
// ~ }
// ~ //end kilo HACK
// ~ //kilo HACK Alpine-2
// ~ if(BetweenLoose(i, 1470, 1490)) //left-right bump after tunnel
// ~ {
// ExtLane = MIN((m_dExtMargin + 20.0) / m_dWidth, 0.5);
// IntLane = MIN((m_dIntMargin + 0.0) / m_dWidth, 0.5);
// ExtLane = MIN((ext_margin_ + 20.0) / width_, 0.5);
// IntLane = MIN((int_margin_ + 0.0) / width_, 0.5);
// ExtLane = 4.0;
// IntLane = 0.3;
// ~ }
@ -342,64 +342,64 @@ void LRaceLine::AdjustRadius(int prev, int i, int next,
if (rl == LINE_RL) {
if (TargetRInverse >= 0.0) {
IntLane -= m_Seg[i].tLaneLMargin;
ExtLane -= m_Seg[i].tLaneRMargin;
IntLane -= seg_[i].tLaneLMargin;
ExtLane -= seg_[i].tLaneRMargin;
} else {
ExtLane -= m_Seg[i].tLaneLMargin;
IntLane -= m_Seg[i].tLaneRMargin;
ExtLane -= seg_[i].tLaneLMargin;
IntLane -= seg_[i].tLaneRMargin;
}
} // if rl
if (TargetRInverse >= 0.0) {
if (m_Seg[i].tLane < IntLane)
m_Seg[i].tLane = IntLane;
if (seg_[i].tLane < IntLane)
seg_[i].tLane = IntLane;
if (1 - m_Seg[i].tLane < ExtLane) {
if (1 - seg_[i].tLane < ExtLane) {
if (1 - OldLane < ExtLane) {
m_Seg[i].tLane = MIN(OldLane, m_Seg[i].tLane);
seg_[i].tLane = MIN(OldLane, seg_[i].tLane);
} else {
m_Seg[i].tLane = 1 - ExtLane;
seg_[i].tLane = 1 - ExtLane;
}
}
} else {
if (m_Seg[i].tLane < ExtLane) {
if (seg_[i].tLane < ExtLane) {
if (OldLane < ExtLane) {
m_Seg[i].tLane = MAX(OldLane, m_Seg[i].tLane);
seg_[i].tLane = MAX(OldLane, seg_[i].tLane);
} else {
m_Seg[i].tLane = ExtLane;
seg_[i].tLane = ExtLane;
}
}
if (1 - m_Seg[i].tLane < IntLane)
m_Seg[i].tLane = 1 - IntLane;
if (1 - seg_[i].tLane < IntLane)
seg_[i].tLane = 1 - IntLane;
}
}
m_Seg[i].UpdateTxTy(rl);
seg_[i].UpdateTxTy(rl);
}
/////////////////////////////////////////////////////////////////////////////
// Smooth path
/////////////////////////////////////////////////////////////////////////////
void LRaceLine::Smooth(const int Step, const int rl) {
int prev = ((m_cDivs - Step) / Step) * Step;
int prev = ((divs_ - Step) / Step) * Step;
int prevprev = prev - Step;
int next = Step;
int nextnext = next + Step;
for (int i = 0; i <= m_cDivs - Step; i += Step) {
double ri0 = getRInverse(prevprev, m_Seg[prev].tx[rl],
m_Seg[prev].ty[rl], i, rl);
double ri1 = getRInverse(i, m_Seg[next].tx[rl],
m_Seg[next].ty[rl], nextnext, rl);
double lPrev = Mag(m_Seg[i].tx[rl] - m_Seg[prev].tx[rl],
m_Seg[i].ty[rl] - m_Seg[prev].ty[rl]);
double lNext = Mag(m_Seg[i].tx[rl] - m_Seg[next].tx[rl],
m_Seg[i].ty[rl] - m_Seg[next].ty[rl]);
for (int i = 0; i <= divs_ - Step; i += Step) {
double ri0 = rinverse(prevprev, seg_[prev].tx[rl],
seg_[prev].ty[rl], i, rl);
double ri1 = rinverse(i, seg_[next].tx[rl],
seg_[next].ty[rl], nextnext, rl);
double lPrev = Mag(seg_[i].tx[rl] - seg_[prev].tx[rl],
seg_[i].ty[rl] - seg_[prev].ty[rl]);
double lNext = Mag(seg_[i].tx[rl] - seg_[next].tx[rl],
seg_[i].ty[rl] - seg_[next].ty[rl]);
double TargetRInverse = (lNext * ri0 + lPrev * ri1) / (lNext + lPrev);
double Security = lPrev * lNext / (8 * m_dSecurityRadius);
double Security = lPrev * lNext / (8 * security_radius_);
if (rl == LINE_RL) {
if (ri0 * ri1 > 0) {
@ -422,7 +422,7 @@ void LRaceLine::Smooth(const int Step, const int rl) {
prev = i;
next = nextnext;
nextnext = next + Step;
if (nextnext > m_cDivs - Step)
if (nextnext > divs_ - Step)
nextnext = 0;
}
} // Smooth
@ -432,22 +432,22 @@ void LRaceLine::Smooth(const int Step, const int rl) {
// Interpolate between two control points
/////////////////////////////////////////////////////////////////////////////
void LRaceLine::StepInterpolate(int iMin, int iMax, int Step, int rl) {
int next = (iMax + Step) % m_cDivs;
if (next > m_cDivs - Step)
int next = (iMax + Step) % divs_;
if (next > divs_ - Step)
next = 0;
int prev = (((m_cDivs + iMin - Step) % m_cDivs) / Step) * Step;
if (prev > m_cDivs - Step)
int prev = (((divs_ + iMin - Step) % divs_) / Step) * Step;
if (prev > divs_ - Step)
prev -= Step;
double ir0 = getRInverse(prev, m_Seg[iMin].tx[rl],
m_Seg[iMin].ty[rl], iMax % m_cDivs, rl);
double ir1 = getRInverse(iMin, m_Seg[iMax % m_cDivs].tx[rl],
m_Seg[iMax % m_cDivs].ty[rl], next, rl);
double ir0 = rinverse(prev, seg_[iMin].tx[rl],
seg_[iMin].ty[rl], iMax % divs_, rl);
double ir1 = rinverse(iMin, seg_[iMax % divs_].tx[rl],
seg_[iMax % divs_].ty[rl], next, rl);
for (int k = iMax; --k > iMin;) {
double x = static_cast<double>(k - iMin) / static_cast<double>(iMax - iMin);
double TargetRInverse = x * ir1 + (1 - x) * ir0;
AdjustRadius(iMin, k, iMax % m_cDivs, TargetRInverse, rl);
AdjustRadius(iMin, k, iMax % divs_, TargetRInverse, rl);
}
}
@ -458,41 +458,41 @@ void LRaceLine::StepInterpolate(int iMin, int iMax, int Step, int rl) {
void LRaceLine::Interpolate(int Step, int rl) {
if (Step > 1) {
int i;
for (i = Step; i <= m_cDivs - Step; i += Step)
for (i = Step; i <= divs_ - Step; i += Step)
StepInterpolate(i - Step, i, Step, rl);
StepInterpolate(i - Step, m_cDivs, Step, rl);
StepInterpolate(i - Step, divs_, Step, rl);
}
}
void LRaceLine::InitTrack(const tTrack * const track, void **parm_handle,
const tSituation *s, const double filterSideSkill) {
m_dMinCornerInverse = GfParmGetNum(*parm_handle, KILO_SECT_PRIV,
min_corner_inverse_ = GfParmGetNum(*parm_handle, KILO_SECT_PRIV,
KILO_ATT_MINCORNER, NULL, 0.002);
m_dCornerSpeed = GfParmGetNum(*parm_handle, KILO_SECT_PRIV,
corner_speed_ = GfParmGetNum(*parm_handle, KILO_SECT_PRIV,
KILO_ATT_CORNERSP, NULL, 15.0);
m_dAvoidSpeedAdjust = GfParmGetNum(*parm_handle, KILO_SECT_PRIV,
avoid_speed_adjust_ = GfParmGetNum(*parm_handle, KILO_SECT_PRIV,
KILO_ATT_AVOIDSP, NULL, 2.0);
m_dCornerAccel = GfParmGetNum(*parm_handle, KILO_SECT_PRIV,
corner_accel_ = GfParmGetNum(*parm_handle, KILO_SECT_PRIV,
KILO_ATT_CORNERACC, NULL, 1.0);
m_dIntMargin = GfParmGetNum(*parm_handle, KILO_SECT_PRIV,
int_margin_ = GfParmGetNum(*parm_handle, KILO_SECT_PRIV,
KILO_ATT_INTMARG, NULL, 1.0);
m_dExtMargin = GfParmGetNum(*parm_handle, KILO_SECT_PRIV,
ext_margin_ = GfParmGetNum(*parm_handle, KILO_SECT_PRIV,
KILO_ATT_EXTMARG, NULL, 2.0);
m_dBrakeDelay = GfParmGetNum(*parm_handle, KILO_SECT_PRIV,
brake_delay_ = GfParmGetNum(*parm_handle, KILO_SECT_PRIV,
KILO_ATT_BRDELAY, NULL, 10.0);
m_dSecurityRadius = GfParmGetNum(*parm_handle, KILO_SECT_PRIV,
security_radius_ = GfParmGetNum(*parm_handle, KILO_SECT_PRIV,
KILO_ATT_SECRAD, NULL, 100.0);
if (s->_raceType != RM_TYPE_PRACTICE) {
m_dExtMargin *= filterSideSkill;
m_dIntMargin *= filterSideSkill;
ext_margin_ *= filterSideSkill;
int_margin_ *= filterSideSkill;
} // if not practice
// split track
for (int rl = LINE_MID; rl <= LINE_RL; rl++) {
g_rl = rl;
std::for_each(m_Seg.begin(), m_Seg.end(), Nullify);
std::for_each(seg_.begin(), seg_.end(), Nullify);
SplitTrack(track, rl, s);
@ -507,28 +507,28 @@ void LRaceLine::InitTrack(const tTrack * const track, void **parm_handle,
}
// Compute curvature and speed along the path
for (int i = m_cDivs; --i >= 0;) {
double TireAccel = m_dCornerSpeed * m_Seg[i].tFriction;
for (int i = divs_; --i >= 0;) {
double TireAccel = corner_speed_ * seg_[i].tFriction;
if (rl == LINE_MID)
TireAccel += m_dAvoidSpeedAdjust;
int next = (i + 1) % m_cDivs;
int prev = (i - 1 + m_cDivs) % m_cDivs;
TireAccel += avoid_speed_adjust_;
int next = (i + 1) % divs_;
int prev = (i - 1 + divs_) % divs_;
double rInverse = getRInverse(prev,
m_Seg[i].tx[rl],
m_Seg[i].ty[rl],
double rInverse = rinverse(prev,
seg_[i].tx[rl],
seg_[i].ty[rl],
next,
rl);
m_Seg[i].tRInverse = rInverse;
seg_[i].tRInverse = rInverse;
double MaxSpeed = 10000.0;
double dAbsInverse = fabs(rInverse);
if (dAbsInverse > m_dMinCornerInverse * 1.01)
MaxSpeed = sqrt(TireAccel / (dAbsInverse - m_dMinCornerInverse));
if (dAbsInverse > min_corner_inverse_ * 1.01)
MaxSpeed = sqrt(TireAccel / (dAbsInverse - min_corner_inverse_));
// Increase or decrease speed depending on track camber
if (dAbsInverse > 0.002) {
double camber = m_Seg[i].dCamber;
double camber = seg_[i].dCamber;
if (camber < -0.02) { // bad camber. slow us down.
MaxSpeed -= MIN(MaxSpeed/4, fabs(camber) * 20);
@ -541,34 +541,34 @@ void LRaceLine::InitTrack(const tTrack * const track, void **parm_handle,
// TODO(kilo): increase or decrease speed depending on approaching bumps
m_Seg[i].tSpeed[rl] = m_Seg[i].tMaxSpeed = MaxSpeed;
seg_[i].tSpeed[rl] = seg_[i].tMaxSpeed = MaxSpeed;
} // for i
// Anticipate braking
for (int j = 32; --j >= 0;) {
for (int i = m_cDivs; --i >= 0;) {
double TireAccel = m_dCornerSpeed * m_Seg[i].tFriction;
int prev = (i - 1 + m_cDivs) % m_cDivs;
for (int i = divs_; --i >= 0;) {
double TireAccel = corner_speed_ * seg_[i].tFriction;
int prev = (i - 1 + divs_) % divs_;
double dx = m_Seg[i].tx[rl] - m_Seg[prev].tx[rl];
double dy = m_Seg[i].ty[rl] - m_Seg[prev].ty[rl];
double dx = seg_[i].tx[rl] - seg_[prev].tx[rl];
double dy = seg_[i].ty[rl] - seg_[prev].ty[rl];
double dist = Mag(dx, dy);
double Speed = (m_Seg[i].tSpeed[rl] + m_Seg[prev].tSpeed[rl]) / 2;
double Speed = (seg_[i].tSpeed[rl] + seg_[prev].tSpeed[rl]) / 2;
double LatA = m_Seg[i].tSpeed[rl] * m_Seg[i].tSpeed[rl] *
(fabs(m_Seg[prev].tRInverse) + fabs(m_Seg[i].tRInverse)) / 2;
double LatA = seg_[i].tSpeed[rl] * seg_[i].tSpeed[rl] *
(fabs(seg_[prev].tRInverse) + fabs(seg_[i].tRInverse)) / 2;
double TanA = TireAccel * TireAccel +
m_dMinCornerInverse * Speed * Speed - LatA * LatA;
min_corner_inverse_ * Speed * Speed - LatA * LatA;
double brakedelay =
m_dBrakeDelay + (rl == LINE_MID ? m_dAvoidSpeedAdjust : 0.0);
brake_delay_ + (rl == LINE_MID ? avoid_speed_adjust_ : 0.0);
TanA = MAX(TanA, 0.0);
TanA = MIN(TanA, brakedelay * m_Seg[i].tFriction);
TanA = MIN(TanA, brakedelay * seg_[i].tFriction);
double Time = dist / Speed;
double MaxSpeed = m_Seg[i].tSpeed[rl] + TanA * Time;
m_Seg[prev].tSpeed[rl] = MIN(MaxSpeed, m_Seg[prev].tMaxSpeed);
double MaxSpeed = seg_[i].tSpeed[rl] + TanA * Time;
seg_[prev].tSpeed[rl] = MIN(MaxSpeed, seg_[prev].tMaxSpeed);
} // for i
} // for j
} // for rl
@ -579,13 +579,13 @@ void LRaceLine::InitTrack(const tTrack * const track, void **parm_handle,
// New race
////////////////////////////////////////////////////////////////////////////
void LRaceLine::NewRace() {
const tPrivCar * const cp = &m_pCar->priv;
m_dWheelBase = (cp->wheel[FRNT_RGT].relPos.x +
const tPrivCar * const cp = &car_->priv;
wheel_base_ = (cp->wheel[FRNT_RGT].relPos.x +
cp->wheel[FRNT_LFT].relPos.x -
cp->wheel[REAR_RGT].relPos.x -
cp->wheel[REAR_LFT].relPos.x) / 2;
m_dWheelTrack = (cp->wheel[FRNT_LFT].relPos.y +
wheel_track_ = (cp->wheel[FRNT_LFT].relPos.y +
cp->wheel[REAR_LFT].relPos.y -
cp->wheel[FRNT_RGT].relPos.y -
cp->wheel[REAR_RGT].relPos.y) / 2;
@ -604,110 +604,110 @@ LRaceLine::GetRaceLineData(const tSituation * const s,
double *lookahead,
double *racesteer) {
// Find index in data arrays
tTrackSeg *pSeg = m_pCar->_trkPos.seg;
double dist = MAX(m_pCar->_trkPos.toStart, 0.0);
tTrackSeg *pSeg = car_->_trkPos.seg;
double dist = MAX(car_->_trkPos.toStart, 0.0);
if (pSeg->type != TR_STR)
dist *= pSeg->radius;
int Index = m_SegInfo[pSeg->id].first
+ static_cast<int>(dist / m_SegInfo[pSeg->id].second);
This = Index;
int Index = seg_info_[pSeg->id].first
+ static_cast<int>(dist / seg_info_[pSeg->id].second);
this_ = Index;
Index = (Index + m_cDivs - 5) % m_cDivs;
static const double Time = s->deltaTime * 9 + m_dCornerAccel / 80.0;
// ??? 0.50 + m_dCornerAccel/80;
double X = m_pCar->_pos_X + m_pCar->_speed_X * Time / 2;
double Y = m_pCar->_pos_Y + m_pCar->_speed_Y * Time / 2;
Index = (Index + divs_ - 5) % divs_;
static const double Time = s->deltaTime * 9 + corner_accel_ / 80.0;
// ??? 0.50 + corner_accel_/80;
double X = car_->_pos_X + car_->_speed_X * Time / 2;
double Y = car_->_pos_Y + car_->_speed_Y * Time / 2;
// *lookahead = 0.0;
while (1) {
Next = (Index + 1) % m_cDivs;
double dx = m_Seg[Next].tx[LINE_RL] - m_pCar->_pos_X;
double dy = m_Seg[Next].ty[LINE_RL] - m_pCar->_pos_Y;
next_ = (Index + 1) % divs_;
double dx = seg_[next_].tx[LINE_RL] - car_->_pos_X;
double dy = seg_[next_].ty[LINE_RL] - car_->_pos_Y;
*lookahead = Mag(dx, dy);
if (*lookahead > 10.0 &&
(m_Seg[Next].tx[LINE_RL] - m_Seg[Index].tx[LINE_RL])
* (X - m_Seg[Next].tx[LINE_RL]) +
(m_Seg[Next].ty[LINE_RL] - m_Seg[Index].ty[LINE_RL])
* (Y - m_Seg[Next].ty[LINE_RL]) < 0.1)
(seg_[next_].tx[LINE_RL] - seg_[Index].tx[LINE_RL])
* (X - seg_[next_].tx[LINE_RL]) +
(seg_[next_].ty[LINE_RL] - seg_[Index].ty[LINE_RL])
* (Y - seg_[next_].ty[LINE_RL]) < 0.1)
break;
Index = Next;
Index = next_;
}
double toMiddle = m_pCar->_trkPos.toMiddle;
if ((m_Seg[Next].tRInverse > 0.0 && toMiddle < 0.0)
|| (m_Seg[Next].tRInverse < 0.0 && toMiddle > 0.0)) {
double toMiddle = car_->_trkPos.toMiddle;
if ((seg_[next_].tRInverse > 0.0 && toMiddle < 0.0)
|| (seg_[next_].tRInverse < 0.0 && toMiddle > 0.0)) {
*lookahead *= MIN(4.0, 1.5 + fabs(toMiddle * 0.3));
} else {
*lookahead *= MAX(0.7, 1.5 - fabs(toMiddle * 0.2));
}
if ((m_Seg[Next].tRInverse < 0.0 && toMiddle > 0.0)
|| (m_Seg[Next].tRInverse > 0.0 && toMiddle < 0.0)) {
if ((seg_[next_].tRInverse < 0.0 && toMiddle > 0.0)
|| (seg_[next_].tRInverse > 0.0 && toMiddle < 0.0)) {
*lookahead *= MAX(1.0, MIN(3.6, 1.0 +
(MIN(2.6, fabs(toMiddle) / (pSeg->width / 2)) / 2)
* (1.0 + fabs(m_Seg[Next].tRInverse) * 65.0 +
m_pCar->_speed_x / 120.0)));
} else if ((m_Seg[Next].tRInverse < 0.0 && m_pCar->_trkPos.toRight < 5.0)
|| (m_Seg[Next].tRInverse > 0.0 && m_pCar->_trkPos.toLeft < 5.0)) {
* (1.0 + fabs(seg_[next_].tRInverse) * 65.0 +
car_->_speed_x / 120.0)));
} else if ((seg_[next_].tRInverse < 0.0 && car_->_trkPos.toRight < 5.0)
|| (seg_[next_].tRInverse > 0.0 && car_->_trkPos.toLeft < 5.0)) {
*lookahead *= MAX(0.8, MIN(1.0, 1.0 -
fabs(m_Seg[Next].tRInverse) * 200.0 *
((5.0 - MIN(m_pCar->_trkPos.toRight, m_pCar->_trkPos.toLeft)) / 5.0)));
fabs(seg_[next_].tRInverse) * 200.0 *
((5.0 - MIN(car_->_trkPos.toRight, car_->_trkPos.toLeft)) / 5.0)));
}
target->x = m_Seg[Next].tx[LINE_RL];
target->y = m_Seg[Next].ty[LINE_RL];
target->x = seg_[next_].tx[LINE_RL];
target->y = seg_[next_].ty[LINE_RL];
//
// Find target speed
//
double c0 =
(m_Seg[Next].tx[LINE_RL] - m_Seg[Index].tx[LINE_RL])
* (m_Seg[Next].tx[LINE_RL] - X) +
(m_Seg[Next].ty[LINE_RL] - m_Seg[Index].ty[LINE_RL])
* (m_Seg[Next].ty[LINE_RL] - Y);
(seg_[next_].tx[LINE_RL] - seg_[Index].tx[LINE_RL])
* (seg_[next_].tx[LINE_RL] - X) +
(seg_[next_].ty[LINE_RL] - seg_[Index].ty[LINE_RL])
* (seg_[next_].ty[LINE_RL] - Y);
double c1 =
(m_Seg[Next].tx[LINE_RL] - m_Seg[Index].tx[LINE_RL])
* (X - m_Seg[Index].tx[LINE_RL]) +
(m_Seg[Next].ty[LINE_RL] - m_Seg[Index].ty[LINE_RL])
* (Y - m_Seg[Index].ty[LINE_RL]);
(seg_[next_].tx[LINE_RL] - seg_[Index].tx[LINE_RL])
* (X - seg_[Index].tx[LINE_RL]) +
(seg_[next_].ty[LINE_RL] - seg_[Index].ty[LINE_RL])
* (Y - seg_[Index].ty[LINE_RL]);
double sum = c0 + c1;
c0 /= sum;
c1 /= sum;
m_dTargetSpeed =
(1 - c0) * m_Seg[Next].tSpeed[LINE_RL] + c0 * m_Seg[Index].tSpeed[LINE_RL];
*avspeed = MAX(10.0, m_Seg[Next].tSpeed[LINE_MID]);
*speed = MAX(*avspeed, m_dTargetSpeed);
target_speed_ =
(1 - c0) * seg_[next_].tSpeed[LINE_RL] + c0 * seg_[Index].tSpeed[LINE_RL];
*avspeed = MAX(10.0, seg_[next_].tSpeed[LINE_MID]);
*speed = MAX(*avspeed, target_speed_);
if ((m_Seg[Next].tRInverse > 0.0 && m_Seg[Next].tLane > m_Seg[Index].tLane
&& m_pCar->_trkPos.toLeft <= m_Seg[Next].tLane * m_dWidth + 1.0)
|| (m_Seg[Next].tRInverse < 0.0 && m_Seg[Next].tLane < m_Seg[Index].tLane
&& m_pCar->_trkPos.toLeft >= m_Seg[Next].tLane * m_dWidth - 1.0)) {
if ((seg_[next_].tRInverse > 0.0 && seg_[next_].tLane > seg_[Index].tLane
&& car_->_trkPos.toLeft <= seg_[next_].tLane * width_ + 1.0)
|| (seg_[next_].tRInverse < 0.0 && seg_[next_].tLane < seg_[Index].tLane
&& car_->_trkPos.toLeft >= seg_[next_].tLane * width_ - 1.0)) {
*avspeed = MAX(*speed, *avspeed);
} else if ((m_Seg[Next].tRInverse > 0.001
&& m_Seg[Next].tLane < m_Seg[Index].tLane
&& m_pCar->_trkPos.toLeft < m_Seg[Next].tLane * m_dWidth - 1.0)
|| (m_Seg[Next].tRInverse < -0.001
&& m_Seg[Next].tLane > m_Seg[Index].tLane
&& m_pCar->_trkPos.toLeft > m_Seg[Next].tLane * m_dWidth + 1.0)) {
*avspeed *= MAX(0.7, 1.0 - fabs(m_Seg[Next].tRInverse) * 100);
} else if ((seg_[next_].tRInverse > 0.001
&& seg_[next_].tLane < seg_[Index].tLane
&& car_->_trkPos.toLeft < seg_[next_].tLane * width_ - 1.0)
|| (seg_[next_].tRInverse < -0.001
&& seg_[next_].tLane > seg_[Index].tLane
&& car_->_trkPos.toLeft > seg_[next_].tLane * width_ + 1.0)) {
*avspeed *= MAX(0.7, 1.0 - fabs(seg_[next_].tRInverse) * 100);
}
double laneoffset = m_dWidth / 2 - (m_Seg[Next].tLane * m_dWidth);
double laneoffset = width_ / 2 - (seg_[next_].tLane * width_);
*raceoffset = laneoffset;
//
// Find target curveture (for the inside wheel)
//
double TargetCurvature = (1 - c0) * m_Seg[Next].tRInverse
+ c0 * m_Seg[Index].tRInverse;
double TargetCurvature = (1 - c0) * seg_[next_].tRInverse
+ c0 * seg_[Index].tRInverse;
if (fabs(TargetCurvature) > 0.01) {
double r = 1 / TargetCurvature;
if (r > 0) {
r -= m_dWheelTrack / 2;
r -= wheel_track_ / 2;
} else {
r += m_dWheelTrack / 2;
r += wheel_track_ / 2;
}
TargetCurvature = 1 / r;
}
@ -717,30 +717,30 @@ LRaceLine::GetRaceLineData(const tSituation * const s,
//
double Error = 0;
double VnError = 0;
double carspeed = Mag(m_pCar->_speed_X, m_pCar->_speed_Y);
double carspeed = Mag(car_->_speed_X, car_->_speed_Y);
//
// Ideal value
//
double steer = atan(m_dWheelBase * TargetCurvature) / m_pCar->_steerLock;
double steer = atan(wheel_base_ * TargetCurvature) / car_->_steerLock;
//
// Servo system to stay on the pre-computed path
//
{
double dx = m_Seg[Next].tx[LINE_RL] - m_Seg[Index].tx[LINE_RL];
double dy = m_Seg[Next].ty[LINE_RL] - m_Seg[Index].ty[LINE_RL];
double dx = seg_[next_].tx[LINE_RL] - seg_[Index].tx[LINE_RL];
double dy = seg_[next_].ty[LINE_RL] - seg_[Index].ty[LINE_RL];
Error =
(dx * (Y - m_Seg[Index].ty[LINE_RL]) -
dy * (X - m_Seg[Index].tx[LINE_RL])) / Mag(dx, dy);
(dx * (Y - seg_[Index].ty[LINE_RL]) -
dy * (X - seg_[Index].tx[LINE_RL])) / Mag(dx, dy);
}
int Prev = (Index + m_cDivs - 1) % m_cDivs;
int NextNext = (Next + 1) % m_cDivs;
double Prevdx = m_Seg[Next].tx[LINE_RL] - m_Seg[Prev].tx[LINE_RL];
double Prevdy = m_Seg[Next].ty[LINE_RL] - m_Seg[Prev].ty[LINE_RL];
double Nextdx = m_Seg[NextNext].tx[LINE_RL] - m_Seg[Index].tx[LINE_RL];
double Nextdy = m_Seg[NextNext].ty[LINE_RL] - m_Seg[Index].ty[LINE_RL];
int Prev = (Index + divs_ - 1) % divs_;
int NextNext = (next_ + 1) % divs_;
double Prevdx = seg_[next_].tx[LINE_RL] - seg_[Prev].tx[LINE_RL];
double Prevdy = seg_[next_].ty[LINE_RL] - seg_[Prev].ty[LINE_RL];
double Nextdx = seg_[NextNext].tx[LINE_RL] - seg_[Index].tx[LINE_RL];
double Nextdy = seg_[NextNext].ty[LINE_RL] - seg_[Index].ty[LINE_RL];
double dx = c0 * Prevdx + (1 - c0) * Nextdx;
double dy = c0 * Prevdy + (1 - c0) * Nextdy;
double n = Mag(dx, dy);
@ -748,34 +748,34 @@ LRaceLine::GetRaceLineData(const tSituation * const s,
dy /= n;
double sError =
(dx * m_pCar->_speed_Y - dy * m_pCar->_speed_X) / (carspeed + 0.01);
(dx * car_->_speed_Y - dy * car_->_speed_X) / (carspeed + 0.01);
double cError =
(dx * m_pCar->_speed_X + dy * m_pCar->_speed_Y) / (carspeed + 0.01);
(dx * car_->_speed_X + dy * car_->_speed_Y) / (carspeed + 0.01);
VnError = asin(sError);
if (cError < 0)
VnError = PI - VnError;
steer -= (atan(Error * (300 / (carspeed + 300)) / 15) + VnError)
/ m_pCar->_steerLock;
/ car_->_steerLock;
//
// Steer into the skid
//
double vx = m_pCar->_speed_X;
double vy = m_pCar->_speed_Y;
double dirx = cos(m_pCar->_yaw);
double diry = sin(m_pCar->_yaw);
double vx = car_->_speed_X;
double vy = car_->_speed_Y;
double dirx = cos(car_->_yaw);
double diry = sin(car_->_yaw);
double Skid = (dirx * vy - vx * diry) / (carspeed + 0.1);
if (Skid > 0.9) Skid = 0.9;
if (Skid < -0.9) Skid = -0.9;
steer += (asin(Skid) / m_pCar->_steerLock) * 0.9;
steer += (asin(Skid) / car_->_steerLock) * 0.9;
double yr = carspeed * TargetCurvature;
double diff = m_pCar->_yaw_rate - yr;
steer -= (0.06 * (100 / (carspeed + 100)) * diff) / m_pCar->_steerLock;
double diff = car_->_yaw_rate - yr;
steer -= (0.06 * (100 / (carspeed + 100)) * diff) / car_->_steerLock;
double trackangle = RtTrackSideTgAngleL(&(m_pCar->_trkPos));
double angle = trackangle - m_pCar->_yaw;
double trackangle = RtTrackSideTgAngleL(&(car_->_trkPos));
double angle = trackangle - car_->_yaw;
NORM_PI_PI(angle);
angle = -angle;
@ -796,9 +796,9 @@ LRaceLine::GetRaceLineData(const tSituation * const s,
bool LRaceLine::isOnLine() const {
bool ret = false;
double lane2left = m_Seg[Next].tLane * m_dWidth;
if (fabs(m_pCar->_trkPos.toLeft - lane2left) <
MAX(0.1, 1.0 - (m_pCar->_speed_x * (m_pCar->_speed_x / 10)) / 600))
double lane2left = seg_[next_].tLane * width_;
if (fabs(car_->_trkPos.toLeft - lane2left) <
MAX(0.1, 1.0 - (car_->_speed_x * (car_->_speed_x / 10)) / 600))
ret = true;
return ret;
@ -807,23 +807,23 @@ bool LRaceLine::isOnLine() const {
void LRaceLine::GetPoint(const double offset, const double lookahead,
vec2f * const rt) const {
double dLane = (m_dWidth / 2.0 - offset) / m_dWidth;
double dLane = (width_ / 2.0 - offset) / width_;
vec2f last;
last.x = dLane * m_Seg[This].txRight + (1.0 - dLane) * m_Seg[This].txLeft;
last.y = dLane * m_Seg[This].tyRight + (1.0 - dLane) * m_Seg[This].tyLeft;
last.x = dLane * seg_[this_].txRight + (1.0 - dLane) * seg_[this_].txLeft;
last.y = dLane * seg_[this_].tyRight + (1.0 - dLane) * seg_[this_].tyLeft;
int ndiv = Next;
int ndiv = next_;
double dLength = 0.0;
double la = static_cast<double>(lookahead)
* MIN(1.0, MAX(0.8, m_pCar->_speed_x / m_dTargetSpeed));
int iLookaheadLimit = static_cast<int>(la / m_lDivLength);
* MIN(1.0, MAX(0.8, car_->_speed_x / target_speed_));
int iLookaheadLimit = static_cast<int>(la / div_length_);
for (int count = 0; count < iLookaheadLimit && dLength < la; count++) {
rt->x = dLane * m_Seg[ndiv].txRight + (1 - dLane) * m_Seg[ndiv].txLeft;
rt->y = dLane * m_Seg[ndiv].tyRight + (1 - dLane) * m_Seg[ndiv].tyLeft;
rt->x = dLane * seg_[ndiv].txRight + (1 - dLane) * seg_[ndiv].txLeft;
rt->y = dLane * seg_[ndiv].tyRight + (1 - dLane) * seg_[ndiv].tyLeft;
vec2f d = (*rt) - last;
dLength += Mag(d.x, d.y);
ndiv = (ndiv + 1) % m_cDivs;
ndiv = (ndiv + 1) % divs_;
last = (*rt);
} // for
} // GetPoint
@ -832,61 +832,37 @@ void LRaceLine::GetPoint(const double offset, const double lookahead,
// this returns true if we're approaching a corner & are significantly
// inside the ideal racing line. The idea is to prevent a sudden outwards
// movement at a time when we should be looking to turn in.
double LRaceLine::correctLimit(void) const {
double toLeft = m_pCar->_trkPos.toLeft;
double nlane2left = m_Seg[Next].tLane * m_dWidth;
double LRaceLine::CorrectLimit(void) const {
double toLeft = car_->_trkPos.toLeft;
double nlane2left = seg_[next_].tLane * width_;
if ((m_Seg[Next].tRInverse > 0.001 && toLeft < nlane2left - 2.0)
|| (m_Seg[Next].tRInverse < -0.001 && toLeft > nlane2left + 2.0))
return MAX(0.2, MIN(1.0, 1.0 - fabs(m_Seg[Next].tRInverse) * 100.0));
if ((seg_[next_].tRInverse > 0.001 && toLeft < nlane2left - 2.0)
|| (seg_[next_].tRInverse < -0.001 && toLeft > nlane2left + 2.0))
return MAX(0.2, MIN(1.0, 1.0 - fabs(seg_[next_].tRInverse) * 100.0));
int nnext = (Next + static_cast<int>(m_pCar->_speed_x / 3)) % m_cDivs;
double nnlane2left = m_Seg[nnext].tLane * m_dWidth;
if ((m_Seg[nnext].tRInverse > 0.001 && toLeft < nnlane2left - 2.0)
|| (m_Seg[nnext].tRInverse < -0.001 && toLeft > nnlane2left + 2.0))
return MAX(0.3, MIN(1.0, 1.0 - fabs(m_Seg[nnext].tRInverse) * 40.0));
int nnext = (next_ + static_cast<int>(car_->_speed_x / 3)) % divs_;
double nnlane2left = seg_[nnext].tLane * width_;
if ((seg_[nnext].tRInverse > 0.001 && toLeft < nnlane2left - 2.0)
|| (seg_[nnext].tRInverse < -0.001 && toLeft > nnlane2left + 2.0))
return MAX(0.3, MIN(1.0, 1.0 - fabs(seg_[nnext].tRInverse) * 40.0));
// ok, we're not inside the racing line. Check and see
// if we're outside it and turning into a corner,
// in which case we want to correct more to try
// and get closer to the apex.
if ((m_Seg[Next].tRInverse > 0.001
&& m_Seg[Next].tLane <= m_Seg[This].tLane
if ((seg_[next_].tRInverse > 0.001
&& seg_[next_].tLane <= seg_[this_].tLane
&& toLeft > nlane2left + 2.0)
|| (m_Seg[Next].tRInverse < -0.001
&& m_Seg[Next].tLane >= m_Seg[This].tLane
|| (seg_[next_].tRInverse < -0.001
&& seg_[next_].tLane >= seg_[this_].tLane
&& toLeft < nlane2left - 2.0))
return MAX(1.0, MIN(1.5, 1.0 + fabs(m_Seg[Next].tRInverse)));
return MAX(1.0, MIN(1.5, 1.0 + fabs(seg_[next_].tRInverse)));
return 1.0;
}
double LRaceLine::getAvoidSpeed(const double distance1,
const double distance2) const {
double speed1 = 1000.0;
double speed2 = 1000.0;
int i = Next;
int dist_limit = static_cast<int>(distance1 / m_lDivLength);
for (int count = 0; count < dist_limit; count++, i++) {
i = i % m_cDivs;
speed1 = MIN(speed1, m_Seg[i].tSpeed[LINE_MID]);
}
dist_limit = static_cast<int>(MIN(distance2, distance1 * 3) - distance1)
/ m_lDivLength;
for (int count = 0; count < dist_limit; count++, i++) {
i = i % m_cDivs;
speed2 = MIN(speed2, m_Seg[i].tSpeed[LINE_MID]
+ static_cast<double>(count) * 0.25);
}
return MIN(speed1, speed2);
}
void LRaceLine::SetSegCamber(const tTrackSeg *seg, const int div) {
void LRaceLine::SetSegmentCamber(const tTrackSeg *seg, const int div) {
double dDistRatio = 0.7;
double dCamberStart = seg->vertex[TR_SR].z - seg->vertex[TR_SL].z;
double dCamberEnd = seg->vertex[TR_ER].z - seg->vertex[TR_EL].z;
@ -896,7 +872,7 @@ void LRaceLine::SetSegCamber(const tTrackSeg *seg, const int div) {
dCamberEnd /= seg->width;
dCamber /= seg->width;
if (m_Seg[div].tRInverse < 0.0) {
if (seg_[div].tRInverse < 0.0) {
dCamber *= -1.0;
dCamberStart *= -1.0;
dCamberEnd *= -1.0;
@ -908,6 +884,6 @@ void LRaceLine::SetSegCamber(const tTrackSeg *seg, const int div) {
dCamber += (dCamberEnd - dCamberStart) * 0.4;
}
m_Seg[div].dCamber = dCamber;
} // SetSegCamber
seg_[div].dCamber = dCamber;
} // SetSegmentCamber

View file

@ -86,7 +86,11 @@ class LRaceLine {
LRaceLine() {}
virtual ~LRaceLine() {}
inline void setCar(tCarElt * const car) {m_pCar = car;}
inline double rinverse(void) const { return seg_[next_].tRInverse; }
inline double rinverse(const double distance) const {
int d = ((next_ + static_cast<int>(distance / div_length_)) % divs_);
return seg_[d].tRInverse; }
inline void set_car(tCarElt * const car) {car_ = car;}
void InitTrack(const tTrack * const track, void **carParmHandle,
const tSituation *s, const double filterSideSkill);
@ -97,53 +101,46 @@ class LRaceLine {
void GetPoint(const double offset, const double lookahead,
vec2f * const rt) const;
bool isOnLine(void) const;
double correctLimit(void) const;
inline double getRInverse(void) const {return m_Seg[Next].tRInverse;}
inline double getRInverse(const double distance) const {
int d = ((Next + static_cast<int>(distance / m_lDivLength)) % m_cDivs);
return m_Seg[d].tRInverse;
}
double CorrectLimit(void) const;
private:
double rinverse(const int prev, const double x, const double y,
const int next, const int rl) const;
void SetSegmentInfo(const tTrackSeg * pseg, const int i, const double l);
void SetSegmentCamber(const tTrackSeg *seg, const int div);
void SplitTrack(const tTrack * const ptrack, const int rl,
const tSituation *s);
double getRInverse(const int prev, const double x, const double y,
const int next, const int rl) const;
void AdjustRadius(int prev, int i, int next, double TargetRInverse, int rl,
double Security = 0);
double Security = 0);
void Smooth(const int Step, const int rl);
void StepInterpolate(int iMin, int iMax, int Step, int rl);
void Interpolate(int Step, int rl);
double getAvoidSpeed(const double distance1, const double distance2) const;
void SetSegCamber(const tTrackSeg *seg, const int div);
private:
double m_dMinCornerInverse;
double m_dCornerSpeed;
double m_dCornerAccel;
double m_dBrakeDelay;
double m_dIntMargin;
double m_dExtMargin;
double m_dAvoidSpeedAdjust;
double m_dSecurityRadius;
tCarElt * m_pCar;
tCarElt *car_;
double min_corner_inverse_;
double corner_speed_;
double corner_accel_;
double brake_delay_;
double int_margin_;
double ext_margin_;
double avoid_speed_adjust_;
double security_radius_;
double wheel_base_;
double wheel_track_;
double m_dWheelBase;
double m_dWheelTrack;
int m_cDivs;
int m_lDivLength;
double m_dTargetSpeed;
double m_dWidth;
int divs_;
int div_length_;
double target_speed_;
double width_;
// first: segment index, second: elem length
std::vector< std::pair<int, double> > m_SegInfo;
std::vector< std::pair<int, double> > seg_info_;
std::vector<rlSegment> m_Seg;
std::vector<rlSegment> seg_;
int Next;
int This;
int next_;
int this_;
};
#endif // SRC_DRIVERS_KILO2008_RACELINE_H_

View file

@ -43,13 +43,13 @@ const int KStrategy::LAST_LAPS = 10;
KStrategy::KStrategy() {
m_last_damages = new std::deque<int>;
last_damages_ = new std::deque<int>;
m_laps = 0;
m_fuel_checked = false;
m_fuel_per_lap = 0.0;
m_last_pit_fuel = 0.0;
m_fuel_sum = 0.0;
laps_ = 0;
fuel_checked_ = false;
fuel_per_lap_ = 0.0;
last_pit_fuel_ = 0.0;
fuel_sum_ = 0.0;
} // KStrategy
@ -69,13 +69,13 @@ void KStrategy::SetFuelAtRaceStart(const tTrack * const t,
const double fuel =
GfParmGetNum(*carParmHandle, KILO_SECT_PRIV, KILO_ATT_FUELPERLAP,
NULL, t->length * MAX_FUEL_PER_METER);
m_expected_fuel_per_lap = fuel;
expected_fuel_per_lap_ = fuel;
// Pittime is pittime without refuel.
m_pittime = GfParmGetNum(*carParmHandle, KILO_SECT_PRIV,
pittime_ = GfParmGetNum(*carParmHandle, KILO_SECT_PRIV,
KILO_ATT_PITTIME, NULL, 25.0);
m_best_lap = GfParmGetNum(*carParmHandle, KILO_SECT_PRIV,
best_lap_ = GfParmGetNum(*carParmHandle, KILO_SECT_PRIV,
KILO_ATT_BESTLAP, NULL, 87.0);
m_worst_lap = GfParmGetNum(*carParmHandle, KILO_SECT_PRIV,
worst_lap_ = GfParmGetNum(*carParmHandle, KILO_SECT_PRIV,
KILO_ATT_WORSTLAP, NULL, 87.0);
// Fuel tank capacity
const double maxfuel = GfParmGetNum(*carParmHandle, SECT_CAR,
@ -88,7 +88,7 @@ void KStrategy::SetFuelAtRaceStart(const tTrack * const t,
// Compute race times for min to min + 9 pit stops.
ComputeBestNumberOfPits(maxfuel, fuelForRace, s->_totLaps, true);
m_last_fuel = m_fuel_per_stint;
last_fuel_ = fuel_per_stint_;
// If the setup defines initial fuel amount, use that value in races.
// Otherwise use computed amount.
@ -100,7 +100,7 @@ void KStrategy::SetFuelAtRaceStart(const tTrack * const t,
} else {
// Add fuel dependent on index to avoid fuel stop in the same lap.
GfParmSetNum(*carParmHandle, SECT_CAR, PRM_FUEL, NULL,
m_last_fuel + index * m_expected_fuel_per_lap);
last_fuel_ + index * expected_fuel_per_lap_);
}
} else {
// Use fuel for whole 'race', ie qualy or practice N laps.
@ -121,14 +121,14 @@ void KStrategy::SetFuelAtRaceStart(const tTrack * const t,
void KStrategy::UpdateFuelStrategy() {
// Required additional fuel for the rest of the race.
// +1 because the computation happens right after crossing the start line.
double fuelperlap = MAX(m_fuel_per_lap, 2.5); // average
double required_fuel = ((LapsToGo() + 1) - ceil(m_car->_fuel / fuelperlap))
double fuelperlap = MAX(fuel_per_lap_, 2.5); // average
double required_fuel = ((LapsToGo() + 1) - ceil(car_->_fuel / fuelperlap))
* fuelperlap;
// We don't have enough fuel to end the race, need at least one stop.
if (required_fuel >= 0.0) {
// Compute race times for different pit strategies.
ComputeBestNumberOfPits(m_car->_tank, required_fuel, LapsToGo(), FALSE);
ComputeBestNumberOfPits(car_->_tank, required_fuel, LapsToGo(), FALSE);
}
} // UpdateFuelStrategy
@ -141,19 +141,19 @@ double KStrategy::PitRefuel() {
UpdateFuelStrategy();
double fuel;
if (m_remaining_stops > 1) {
fuel = MIN(MAX(m_fuel_per_stint, MAXFUEL_FOR_THIS_RACE),
m_car->_tank - m_car->_fuel); // !!!
--m_remaining_stops;
if (remaining_stops_ > 1) {
fuel = MIN(MAX(fuel_per_stint_, MAXFUEL_FOR_THIS_RACE),
car_->_tank - car_->_fuel); // !!!
--remaining_stops_;
} else {
double cmpfuel = (m_fuel_per_lap == 0.0)
? m_expected_fuel_per_lap
: m_fuel_per_lap;
fuel = MAX(MIN((LapsToGo() + 1.0) * cmpfuel - m_car->_fuel,
m_car->_tank - m_car->_fuel), 0.0);
double cmpfuel = (fuel_per_lap_ == 0.0)
? expected_fuel_per_lap_
: fuel_per_lap_;
fuel = MAX(MIN((LapsToGo() + 1.0) * cmpfuel - car_->_fuel,
car_->_tank - car_->_fuel), 0.0);
}
m_last_pit_fuel = fuel;
last_pit_fuel_ = fuel;
return fuel;
} // pitRefuel
@ -174,16 +174,16 @@ void KStrategy::ComputeBestNumberOfPits(const double tankCapacity,
for (int i = 0; i < (preRace ? 5 : 4); ++i) {
double stintFuel = requiredFuel / (pitstopMin + i); // + 1);
double fillratio = stintFuel / tankCapacity;
double avglapest = m_best_lap + (m_worst_lap - m_best_lap) * fillratio;
double racetime = (pitstopMin + i) * (m_pittime + stintFuel / 8.0) +
double avglapest = best_lap_ + (worst_lap_ - best_lap_) * fillratio;
double racetime = (pitstopMin + i) * (pittime_ + stintFuel / 8.0) +
remainingLaps * avglapest;
if (mintime > racetime) {
mintime = racetime;
beststops = pitstopMin + i - (preRace ? 1 : 0);
m_fuel_per_stint = stintFuel;
fuel_per_stint_ = stintFuel;
}
}
m_remaining_stops = beststops;
remaining_stops_ = beststops;
} // ComputeBestNumberOfPits
@ -198,45 +198,45 @@ void KStrategy::ComputeBestNumberOfPits(const double tankCapacity,
* @return: -
*/
void KStrategy::Update() {
if (m_car->_laps > m_laps) { // If a new lap has been finished
m_laps = m_car->_laps;
m_last_damages->push_front(m_car->_dammage); // store last lap's damage
if (static_cast<int>(m_last_damages->size()) > LAST_LAPS)
m_last_damages->pop_back(); // and keep deque size at limit
if (car_->_laps > laps_) { // If a new lap has been finished
laps_ = car_->_laps;
last_damages_->push_front(car_->_dammage); // store last lap's damage
if (static_cast<int>(last_damages_->size()) > LAST_LAPS)
last_damages_->pop_back(); // and keep deque size at limit
#ifdef STRAT_DEBUG
// print damage values in reverse order
cerr << car->_name << ": damages";
for (deque<int>::reverse_iterator rit = m_last_damages->rbegin();
rit < m_last_damages->rend();
rit++)
for (deque<int>::reverse_iterator rit = last_damages_->rbegin();
rit < last_damages_->rend();
++rit)
cerr << " " << *rit;
cerr << endl;
#endif
}
// Update best & worst lap times
m_best_lap = MIN((m_best_lap == 0.0 ? m_car->_lastLapTime : m_best_lap),
m_car->_lastLapTime);
m_worst_lap = MAX(m_worst_lap, m_car->_lastLapTime);
best_lap_ = MIN((best_lap_ == 0.0 ? car_->_lastLapTime : best_lap_),
car_->_lastLapTime);
worst_lap_ = MAX(worst_lap_, car_->_lastLapTime);
// Fuel statistics update.
int id = m_car->_trkPos.seg->id;
int id = car_->_trkPos.seg->id;
// Range must include enough segments to be executed once guaranteed.
if (id >= 0 && id < 5 && !m_fuel_checked) {
if (m_car->race.laps > 1) {
m_fuel_sum += (m_last_fuel + m_last_pit_fuel - m_car->priv.fuel);
m_fuel_per_lap = (m_fuel_sum / (m_car->race.laps - 1));
if (id >= 0 && id < 5 && !fuel_checked_) {
if (car_->race.laps > 1) {
fuel_sum_ += (last_fuel_ + last_pit_fuel_ - car_->priv.fuel);
fuel_per_lap_ = (fuel_sum_ / (car_->race.laps - 1));
// This is here for adding strategy decisions, otherwise
// it could be moved to pitRefuel for efficiency.
UpdateFuelStrategy();
}
m_last_fuel = m_car->priv.fuel;
m_last_pit_fuel = 0.0;
m_fuel_checked = true;
last_fuel_ = car_->priv.fuel;
last_pit_fuel_ = 0.0;
fuel_checked_ = true;
} else if (id > 5) {
m_fuel_checked = false;
fuel_checked_ = false;
}
} // update
@ -255,14 +255,14 @@ bool KStrategy::NeedPitstop() const {
bool ret = false;
// Question makes sense only if there is a pit.
if (m_car->_pit != NULL) {
if (car_->_pit != NULL) {
// Ideally we shouldn't pit on the last lap for any reason,
// just get to the finish line somehow.
if (LapsToGo() > 0) {
// Do we need to refuel?
double cmpfuel = (m_fuel_per_lap == 0.0)
? m_expected_fuel_per_lap
: m_fuel_per_lap;
double cmpfuel = (fuel_per_lap_ == 0.0)
? expected_fuel_per_lap_
: fuel_per_lap_;
#ifdef STRAT_DEBUG
if (strcmp(car->_name, "Kilo 1") == 0 && car->_fuel < 5.0)
@ -278,20 +278,20 @@ bool KStrategy::NeedPitstop() const {
<< endl;
#endif
cmpfuel *= MIN(SAFE_LAPS, LapsToGo());
if (m_car->_fuel < cmpfuel) {
if (car_->_fuel < cmpfuel) {
#ifdef STRAT_DEBUG
cerr << car->_name << " REFUEL" << endl;
#endif
ret = true;
} else {
// Do we need to repair and is the pit free?
if (m_car->_dammage > PIT_DAMAGE) {
if (car_->_dammage > PIT_DAMAGE) {
// Let's see if we can make it somehow onto the finish line
// BEWARE doesnt check for limits, works for races > 5 laps!!!
if (LapsToGo() <= LAST_LAPS) {
// If prediction shows we would top the damage limit,
// let's visit the pit
if (m_car->_dammage + GetAvgDamage() * LapsToGo() >= 10000) {
if (car_->_dammage + GetAvgDamage() * LapsToGo() >= 10000) {
ret = IsPitFree();
}
} else {
@ -314,8 +314,8 @@ bool KStrategy::NeedPitstop() const {
* @return average damage increment
*/
int KStrategy::GetAvgDamage(void) const {
return (m_last_damages->front() - m_last_damages->back())
/ MAX(m_last_damages->size(), 1);
return (last_damages_->front() - last_damages_->back())
/ MAX(last_damages_->size(), 1);
} // GetAvgDamage
@ -331,7 +331,7 @@ int KStrategy::GetAvgDamage(void) const {
int KStrategy::PitRepair() const {
int ret = (LapsToGo() <= LAST_LAPS) // In the last N laps
? GetAvgDamage() * LapsToGo() // repair only as much as really needed.
: m_car->_dammage; // Otherwise repair everything.
: car_->_dammage; // Otherwise repair everything.
#ifdef STRAT_DEBUG
cerr << car->_name
@ -340,14 +340,14 @@ int KStrategy::PitRepair() const {
#endif
// Clear buffer
m_last_damages->clear();
last_damages_->clear();
return ret;
} // pitRepair
bool KStrategy::IsPitFree() const {
if (m_car->_pit != NULL && m_car->_pit->pitCarIndex == TR_PIT_STATE_FREE)
if (car_->_pit != NULL && car_->_pit->pitCarIndex == TR_PIT_STATE_FREE)
return true;
else
return false;

View file

@ -39,7 +39,7 @@
class KStrategy {
public:
KStrategy();
~KStrategy() {delete m_last_damages;}
~KStrategy() {delete last_damages_;}
// Interface
void Update();
@ -50,33 +50,33 @@ class KStrategy {
void ** const carParmHandle,
const tSituation * const s,
const int index);
void set_car(const tCarElt * const car) {this->m_car = car;}
void set_car(const tCarElt * const car) {this->car_ = car;}
protected:
bool IsPitFree() const;
int GetAvgDamage() const;
inline int LapsToGo() const
{return m_car->_remainingLaps - m_car->_lapsBehindLeader;}
{return car_->_remainingLaps - car_->_lapsBehindLeader;}
void UpdateFuelStrategy();
void ComputeBestNumberOfPits(const double tankCapacity,
const double requiredFuel,
const int remainingLaps,
const bool preRace);
const tCarElt * m_car;
int m_laps;
std::deque<int> *m_last_damages;
int m_remaining_stops;
double m_fuel_per_stint;
double m_pittime; // Expected additional time for pit stop.
double m_best_lap; // Best possible lap, empty tank and alone.
double m_worst_lap; // Worst possible lap, full tank and alone.
bool m_fuel_checked; // Fuel statistics updated.
double m_fuel_per_lap; // Maximum amount of fuel we needed for a lap.
double m_last_pit_fuel; // Amount refueled, special case when we refuel.
double m_last_fuel; // Fuel available when we cross the start lane.
double m_expected_fuel_per_lap; // Expected fuel per lap (may be inaccurate).
double m_fuel_sum; // All the fuel used.
const tCarElt * car_;
int laps_;
std::deque<int> *last_damages_;
int remaining_stops_;
double fuel_per_stint_;
double pittime_; // Expected additional time for pit stop.
double best_lap_; // Best possible lap, empty tank and alone.
double worst_lap_; // Worst possible lap, full tank and alone.
bool fuel_checked_; // Fuel statistics updated.
double fuel_per_lap_; // Maximum amount of fuel we needed for a lap.
double last_pit_fuel_; // Amount refueled, special case when we refuel.
double last_fuel_; // Fuel available when we cross the start lane.
double expected_fuel_per_lap_; // Expected fuel per lap (may be inaccurate).
double fuel_sum_; // All the fuel used.
static const double MAX_FUEL_PER_METER; // [kg/m] fuel consumtion.
static const int PIT_DAMAGE; // If damage > we request a pit stop.