From 6ff78eb85d515a611345f0f9ac544b0b2ba4ffbd Mon Sep 17 00:00:00 2001 From: kmetykog Date: Tue, 22 Dec 2009 00:52:11 +0000 Subject: [PATCH] USR use global skill.xml. Untested. Re #50 git-svn-id: https://svn.code.sf.net/p/speed-dreams/code/trunk@2037 30fe4595-0a0c-4342-8851-515496e4dcbd Former-commit-id: a0040c09d7bf43074747903fb611325e05a414c0 Former-commit-id: 49bdf3df0bc9ced7016d1fd363ef18a2b9620eec --- src/drivers/usr_36GP/driver.cpp | 5516 +++++++++++++++---------------- src/drivers/usr_sc/driver.cpp | 5516 +++++++++++++++---------------- src/drivers/usr_trb1/driver.cpp | 5516 +++++++++++++++---------------- 3 files changed, 8268 insertions(+), 8280 deletions(-) diff --git a/src/drivers/usr_36GP/driver.cpp b/src/drivers/usr_36GP/driver.cpp index b601fd72c..9912cdd83 100644 --- a/src/drivers/usr_36GP/driver.cpp +++ b/src/drivers/usr_36GP/driver.cpp @@ -23,37 +23,37 @@ #define CONTROL_SKILL -//const float Driver::MAX_UNSTUCK_ANGLE = (float)(15.0f/180.0f*PI); // [radians] If the angle of the car on the track is smaller, we assume we are not stuck. +//const float Driver::MAX_UNSTUCK_ANGLE = (float)(15.0f/180.0f*PI); // [radians] If the angle of the car on the track is smaller, we assume we are not stuck. const float Driver::MAX_UNSTUCK_ANGLE = 1.3f; -const float Driver::UNSTUCK_TIME_LIMIT = 2.5f; // [s] We try to get unstuck after this time. -const float Driver::MAX_UNSTUCK_SPEED = 5.0f; // [m/s] Below this speed we consider being stuck. -const float Driver::MIN_UNSTUCK_DIST = -1.0f; // [m] If we are closer to the middle we assume to be not stuck. -const float Driver::G = 9.81f; // [m/(s*s)] Welcome on Earth. -const float Driver::FULL_ACCEL_MARGIN = 1.0f; // [m/s] Margin reduce oscillation of brake/acceleration. -const float Driver::SHIFT = 0.9f; // [-] (% of rpmredline) When do we like to shift gears. -const float Driver::SHIFT_MARGIN = 4.0f; // [m/s] Avoid oscillating gear changes. -const float Driver::ABS_MINSPEED = 3.0f; // [m/s] Below this speed the ABS is disabled (numeric, division by small numbers). -const float Driver::LOOKAHEAD_CONST = 18.0f; // [m] -const float Driver::LOOKAHEAD_FACTOR = 0.33f; // [-] -const float Driver::WIDTHDIV = 3.0f; // [-] Defines the percentage of the track to use (2/WIDTHDIV). -const float Driver::SIDECOLL_MARGIN = 3.0f; // [m] Distance between car centers to avoid side collisions. -const float Driver::BORDER_OVERTAKE_MARGIN = 1.0f; // [m] -const float Driver::OVERTAKE_OFFSET_SPEED = 5.0f; // [m/s] Offset change speed. -const float Driver::PIT_LOOKAHEAD = 6.0f; // [m] Lookahead to stop in the pit. -const float Driver::PIT_BRAKE_AHEAD = 200.0f; // [m] Workaround for "broken" pitentries. -const float Driver::PIT_MU = 0.4f; // [-] Friction of pit concrete. -const float Driver::MAX_SPEED = 84.0f; // [m/s] Speed to compute the percentage of brake to apply. -const float Driver::MAX_FUEL_PER_METER = 0.0008f; // [liter/m] fuel consumtion. -const float Driver::CLUTCH_SPEED = 5.0f; // [m/s] -const float Driver::CENTERDIV = 0.1f; // [-] (factor) [0.01..0.6]. -const float Driver::DISTCUTOFF = 200.0f; // [m] How far to look, terminate while loops. -const float Driver::MAX_INC_FACTOR = 8.0f; // [m] Increment faster if speed is slow [1.0..10.0]. -const float Driver::CATCH_FACTOR = 8.0f; // [-] select MIN(catchdist, dist*CATCH_FACTOR) to overtake. -const float Driver::CLUTCH_FULL_MAX_TIME = 2.0f; // [s] Time to apply full clutch. -const float Driver::USE_LEARNED_OFFSET_RANGE = 0.2f; // [m] if offset < this use the learned stuff +const float Driver::UNSTUCK_TIME_LIMIT = 2.5f; // [s] We try to get unstuck after this time. +const float Driver::MAX_UNSTUCK_SPEED = 5.0f; // [m/s] Below this speed we consider being stuck. +const float Driver::MIN_UNSTUCK_DIST = -1.0f; // [m] If we are closer to the middle we assume to be not stuck. +const float Driver::G = 9.81f; // [m/(s*s)] Welcome on Earth. +const float Driver::FULL_ACCEL_MARGIN = 1.0f; // [m/s] Margin reduce oscillation of brake/acceleration. +const float Driver::SHIFT = 0.9f; // [-] (% of rpmredline) When do we like to shift gears. +const float Driver::SHIFT_MARGIN = 4.0f; // [m/s] Avoid oscillating gear changes. +const float Driver::ABS_MINSPEED = 3.0f; // [m/s] Below this speed the ABS is disabled (numeric, division by small numbers). +const float Driver::LOOKAHEAD_CONST = 18.0f; // [m] +const float Driver::LOOKAHEAD_FACTOR = 0.33f; // [-] +const float Driver::WIDTHDIV = 3.0f; // [-] Defines the percentage of the track to use (2/WIDTHDIV). +const float Driver::SIDECOLL_MARGIN = 3.0f; // [m] Distance between car centers to avoid side collisions. +const float Driver::BORDER_OVERTAKE_MARGIN = 1.0f; // [m] +const float Driver::OVERTAKE_OFFSET_SPEED = 5.0f; // [m/s] Offset change speed. +const float Driver::PIT_LOOKAHEAD = 6.0f; // [m] Lookahead to stop in the pit. +const float Driver::PIT_BRAKE_AHEAD = 200.0f; // [m] Workaround for "broken" pitentries. +const float Driver::PIT_MU = 0.4f; // [-] Friction of pit concrete. +const float Driver::MAX_SPEED = 84.0f; // [m/s] Speed to compute the percentage of brake to apply. +const float Driver::MAX_FUEL_PER_METER = 0.0008f; // [liter/m] fuel consumtion. +const float Driver::CLUTCH_SPEED = 5.0f; // [m/s] +const float Driver::CENTERDIV = 0.1f; // [-] (factor) [0.01..0.6]. +const float Driver::DISTCUTOFF = 200.0f; // [m] How far to look, terminate while loops. +const float Driver::MAX_INC_FACTOR = 8.0f; // [m] Increment faster if speed is slow [1.0..10.0]. +const float Driver::CATCH_FACTOR = 8.0f; // [-] select MIN(catchdist, dist*CATCH_FACTOR) to overtake. +const float Driver::CLUTCH_FULL_MAX_TIME = 2.0f; // [s] Time to apply full clutch. +const float Driver::USE_LEARNED_OFFSET_RANGE = 0.2f; // [m] if offset < this use the learned stuff -const float Driver::TEAM_REAR_DIST = 50.0f; // -const int Driver::TEAM_DAMAGE_CHANGE_LEAD = 700; // When to change position in the team? +const float Driver::TEAM_REAR_DIST = 50.0f; // +const int Driver::TEAM_DAMAGE_CHANGE_LEAD = 700; // When to change position in the team? #define SKIPLIMIT 4 @@ -65,145 +65,145 @@ Cardata *Driver::cardata = NULL; Driver::Driver(int index) : - NoTeamWaiting(0), - TeamWaitTime(0.0f), - truespeed(0.0f), - deltaTime(0.0f), - FuelSpeedUp(0.0f), - TclSlip(2.0f), - TclRange(10.0f), - AbsSlip(2.5f), - AbsRange(5.0f), - OversteerASR(0.7f), - BrakeMu(1.0f), - YawRateAccel(0.0f), - random_seed(0), - DebugMsg(0), - racetype(0), - mode(0), - avoidmode(0), - lastmode(0), - allow_stuck(1), - stuck(0), - stuckcheck(0), - stuck_timer(0.0f), - last_stuck_time(-100.0f), - prefer_side(0), - allowcorrecting(0), - pitpos(0), - prevspeedangle(0.0f), - speedangle(0.0f), - angle(0.0f), - mass(0.0f), - maxfuel(0.0f), - myoffset(0.0f), - pitoffset(0.0f), - laststeer(0.0f), - lastbrake(0.0f), - lastaccel(0.0f), - lastNSasteer(0.0f), - lastNSksteer(0.0f), - avgaccel_x(0.0f), - car(NULL), - raceline(NULL), - opponents(NULL), - opponent(NULL), - pit(NULL), - strategy(NULL), - mycardata(NULL), - tLftMargin(NULL), - tRgtMargin(NULL), - simtime(0.0), - avoidtime(0.0), - frontavoidtime(0.0), - correcttimer(0.0), - correctlimit(1000.0), - aligned_timer(0.0), - stopped_timer(0.0), - brakedelay(0.0), - brakeratio(1.0), - deltamult(0.0), - nextCRinverse(0.0), - sideratio(100.0), - laststeer_direction(0.0), - steerLock(0.4), - currentspeedsqr(0.0f), - currentspeed(0.0f), - clutchtime(0.0f), - oldlookahead(0.0f), - oldtime_mod(0.0f), - racesteer(0.0f), - stucksteer(0.0f), - prevleft(0.0f), - rldata(NULL), - avoidlftoffset(0.0f), - avoidrgtoffset(0.0f), - accelcmd(0.0f), - brakecmd(0.0f), - faccelcmd(0.0f), - fbrakecmd(0.0f), - TurnDecel(0.0f), - PitOffset(0.0f), - PitExitSpeed(100.0f), - RevsChangeDown(0.0f), - RevsChangeUp(0.0f), - RevsChangeDownMax(0.0f), - MaxSteerTime(1.5f), - MinSteerTime(1.0f), - SteerCutoff(55.0f), - SmoothSteer(1.0f), - LookAhead(1.0f), - IncFactor(1.0f), - SideMargin(0.0f), - OutSteerFactor(0.0f), - StuckAccel(0.8f), - StuckAngle(1.6f), - FollowMargin(0.0f), - SteerLookahead(0.0f), - CorrectDelay(0.0f), - SteerMaxRI(0.008), - SkidSteer(0.7), - MinAccel(0.2), - lookahead(10.0f), - brakemargin(0.0f), - MaxGear(0), - NoPit(0), - radius(NULL), - alone(0), - carindex(0), - collision(0.0f), - global_skill(0.0f), - driver_aggression(0.0f), - skill(0.0f), - skill_adjust_limit(0.0), - skill_adjust_timer(-1.0), - decel_adjust_targ(1.0), - decel_adjust_perc(1.0), - brake_adjust_targ(1.0), - brake_adjust_perc(1.0), - fuelperlap(5.0f), + NoTeamWaiting(0), + TeamWaitTime(0.0f), + truespeed(0.0f), + deltaTime(0.0f), + FuelSpeedUp(0.0f), + TclSlip(2.0f), + TclRange(10.0f), + AbsSlip(2.5f), + AbsRange(5.0f), + OversteerASR(0.7f), + BrakeMu(1.0f), + YawRateAccel(0.0f), + random_seed(0), + DebugMsg(0), + racetype(0), + mode(0), + avoidmode(0), + lastmode(0), + allow_stuck(1), + stuck(0), + stuckcheck(0), + stuck_timer(0.0f), + last_stuck_time(-100.0f), + prefer_side(0), + allowcorrecting(0), + pitpos(0), + prevspeedangle(0.0f), + speedangle(0.0f), + angle(0.0f), + mass(0.0f), + maxfuel(0.0f), + myoffset(0.0f), + pitoffset(0.0f), + laststeer(0.0f), + lastbrake(0.0f), + lastaccel(0.0f), + lastNSasteer(0.0f), + lastNSksteer(0.0f), + avgaccel_x(0.0f), + car(NULL), + raceline(NULL), + opponents(NULL), + opponent(NULL), + pit(NULL), + strategy(NULL), + mycardata(NULL), + tLftMargin(NULL), + tRgtMargin(NULL), + simtime(0.0), + avoidtime(0.0), + frontavoidtime(0.0), + correcttimer(0.0), + correctlimit(1000.0), + aligned_timer(0.0), + stopped_timer(0.0), + brakedelay(0.0), + brakeratio(1.0), + deltamult(0.0), + nextCRinverse(0.0), + sideratio(100.0), + laststeer_direction(0.0), + steerLock(0.4), + currentspeedsqr(0.0f), + currentspeed(0.0f), + clutchtime(0.0f), + oldlookahead(0.0f), + oldtime_mod(0.0f), + racesteer(0.0f), + stucksteer(0.0f), + prevleft(0.0f), + rldata(NULL), + avoidlftoffset(0.0f), + avoidrgtoffset(0.0f), + accelcmd(0.0f), + brakecmd(0.0f), + faccelcmd(0.0f), + fbrakecmd(0.0f), + TurnDecel(0.0f), + PitOffset(0.0f), + PitExitSpeed(100.0f), + RevsChangeDown(0.0f), + RevsChangeUp(0.0f), + RevsChangeDownMax(0.0f), + MaxSteerTime(1.5f), + MinSteerTime(1.0f), + SteerCutoff(55.0f), + SmoothSteer(1.0f), + LookAhead(1.0f), + IncFactor(1.0f), + SideMargin(0.0f), + OutSteerFactor(0.0f), + StuckAccel(0.8f), + StuckAngle(1.6f), + FollowMargin(0.0f), + SteerLookahead(0.0f), + CorrectDelay(0.0f), + SteerMaxRI(0.008), + SkidSteer(0.7), + MinAccel(0.2), + lookahead(10.0f), + brakemargin(0.0f), + MaxGear(0), + NoPit(0), + radius(NULL), + alone(0), + carindex(0), + collision(0.0f), + global_skill(0.0f), + driver_aggression(0.0f), + skill(0.0f), + skill_adjust_limit(0.0), + skill_adjust_timer(-1.0), + decel_adjust_targ(1.0), + decel_adjust_perc(1.0), + brake_adjust_targ(1.0), + brake_adjust_perc(1.0), + fuelperlap(5.0f), #ifdef SPEED_DREAMS - teamIndex(0), - pitStopChecked(false), + teamIndex(0), + pitStopChecked(false), #endif - MAX_UNSTUCK_COUNT(0), - INDEX(0), - CARMASS(0.0f), - CA(0.0f), - CW(0.0f), - TIREMU(0.0f), - OVERTAKE_OFFSET_INC(0.0f), - MU_FACTOR(0.0f), - track(NULL), - skipcount(0), - cmd_accel(0.0f), - cmd_brake(0.0f), - cmd_steer(0.0f), - cmd_gear(0), - cmd_clutch(0.0f), - cmd_light(0.0f) + MAX_UNSTUCK_COUNT(0), + INDEX(0), + CARMASS(0.0f), + CA(0.0f), + CW(0.0f), + TIREMU(0.0f), + OVERTAKE_OFFSET_INC(0.0f), + MU_FACTOR(0.0f), + track(NULL), + skipcount(0), + cmd_accel(0.0f), + cmd_brake(0.0f), + cmd_steer(0.0f), + cmd_gear(0), + cmd_clutch(0.0f), + cmd_light(0.0f) { - INDEX = index; + INDEX = index; } @@ -214,19 +214,19 @@ Driver::~Driver() raceline->FreeTrack(true); delete raceline; } - delete opponents; - delete pit; - delete [] radius; - delete strategy; - delete rldata; - if (cardata != NULL) { - delete cardata; - cardata = NULL; - } + delete opponents; + delete pit; + delete [] radius; + delete strategy; + delete rldata; + if (cardata != NULL) { + delete cardata; + cardata = NULL; + } - free(tLftMargin); - free(tRgtMargin); - free(tYawRateAccel); + free(tLftMargin); + free(tRgtMargin); + free(tYawRateAccel); } #define RANDOM_SEED 0xfded @@ -249,194 +249,190 @@ unsigned int Driver::getRandom() // Called for every track change or new race. void Driver::initTrack(tTrack* t, void *carHandle, void **carParmHandle, tSituation *s) { - track = t; + track = t; - const int BUFSIZE = 255; - int i; - char buffer[BUFSIZE+1]; + const int BUFSIZE = 255; + int i; + char buffer[BUFSIZE+1]; - global_skill = skill = decel_adjust_perc = driver_aggression = 0.0; + global_skill = skill = decel_adjust_perc = driver_aggression = 0.0; #ifdef CONTROL_SKILL - // load the skill level - //if (s->_raceType == RM_TYPE_PRACTICE) - // global_skill = 0.0; - //else - { - snprintf(buffer, BUFSIZE, "config/raceman/extra/skill.xml"); - void *skillHandle = GfParmReadFile(buffer, GFPARM_RMODE_REREAD); - if (skillHandle) - { - global_skill = GfParmGetNum(skillHandle, (char *)SECT_SKILL, (char *)PRV_SKILL_LEVEL, (char *) NULL, 10.0f); - } - else - { - global_skill = 0.0f; - } - global_skill = MAX(0.0f, MIN(10.0f, global_skill)); + // load the global skill level, range 0 - 10 + snprintf(buffer, BUFSIZE, "%sconfig/raceman/extra/skill.xml", GetLocalDir()); + void *skillHandle = GfParmReadFile(buffer, GFPARM_RMODE_REREAD); + if(!skillHandle) { + snprintf(buffer, BUFSIZE, "%sconfig/raceman/extra/skill.xml", GetDataDir()); + skillHandle = GfParmReadFile(buffer, GFPARM_RMODE_REREAD); + }//if !skillHandle + + if (skillHandle) { + global_skill = GfParmGetNum(skillHandle, (char *)SECT_SKILL, (char *)PRV_SKILL_LEVEL, (char *) NULL, 10.0f); + } + global_skill = MAX(0.0f, MIN(10.0f, global_skill)); - float driver_skill = 0.0f; - snprintf(buffer, BUFSIZE, "drivers/%s/%d/skill.xml",robot_name,INDEX); - skillHandle = GfParmReadFile(buffer, GFPARM_RMODE_STD); - if (skillHandle) - { - driver_skill = GfParmGetNum(skillHandle, SECT_SKILL, PRV_SKILL_LEVEL, (char *) NULL, 0.0); - driver_aggression = GfParmGetNum(skillHandle, SECT_SKILL, PRV_SKILL_AGGRO, (char *)NULL, 0.0); - driver_skill = MIN(1.0, MAX(0.0, driver_skill)); - } + //load the driver skill level, range 0 - 1 + float driver_skill = 0.0f; + snprintf(buffer, BUFSIZE, "drivers/%s/%d/skill.xml",robot_name,INDEX); + skillHandle = GfParmReadFile(buffer, GFPARM_RMODE_STD); + if (skillHandle) + { + driver_skill = GfParmGetNum(skillHandle, SECT_SKILL, PRV_SKILL_LEVEL, (char *) NULL, 0.0); + driver_aggression = GfParmGetNum(skillHandle, SECT_SKILL, PRV_SKILL_AGGRO, (char *)NULL, 0.0); + driver_skill = MIN(1.0, MAX(0.0, driver_skill)); + } - skill = (global_skill + driver_skill * 2) * (1.0 + driver_skill); - } + skill = (global_skill + driver_skill * 2) * (1.0 + driver_skill); #endif - // Load a custom setup if one is available. - // Get a pointer to the first char of the track filename. - char *ptrackname = strrchr(track->filename, '/') + 1; - char *p = strrchr(ptrackname, '.'); - char trackname[256] = {0}; + // Load a custom setup if one is available. + // Get a pointer to the first char of the track filename. + char *ptrackname = strrchr(track->filename, '/') + 1; + char *p = strrchr(ptrackname, '.'); + char trackname[256] = {0}; - if (p) - strncpy(trackname, ptrackname, p - ptrackname); - else - strcpy(trackname, ptrackname); + if (p) + strncpy(trackname, ptrackname, p - ptrackname); + else + strcpy(trackname, ptrackname); - char carName[256]; - { - char const *path = SECT_GROBJECTS "/" LST_RANGES "/" "1"; - char const *key = PRM_CAR; - strncpy( carName, GfParmGetStr(carHandle, path, key, ""), sizeof(carName) ); - char *p = strrchr(carName, '.'); - if (p) *p = '\0'; - } + char carName[256]; + { + char const *path = SECT_GROBJECTS "/" LST_RANGES "/" "1"; + char const *key = PRM_CAR; + strncpy( carName, GfParmGetStr(carHandle, path, key, ""), sizeof(carName) ); + char *p = strrchr(carName, '.'); + if (p) *p = '\0'; + } - snprintf(buffer, BUFSIZE, "drivers/%s/cars/%s/default.xml", robot_name, carName); - *carParmHandle = GfParmReadFile(buffer, GFPARM_RMODE_STD); - void *newhandle; + snprintf(buffer, BUFSIZE, "drivers/%s/cars/%s/default.xml", robot_name, carName); + *carParmHandle = GfParmReadFile(buffer, GFPARM_RMODE_STD); + void *newhandle; - switch (s->_raceType) { - case RM_TYPE_PRACTICE: - snprintf(buffer, BUFSIZE, "drivers/%s/cars/%s/practice/%s.xml", robot_name, carName, trackname); - break; - case RM_TYPE_QUALIF: - snprintf(buffer, BUFSIZE, "drivers/%s/cars/%s/qualifying/%s.xml", robot_name, carName, trackname); - break; - case RM_TYPE_RACE: - snprintf(buffer, BUFSIZE, "drivers/%s/cars/%s/race/%s.xml", robot_name, carName, trackname); - break; - default: - break; - } + switch (s->_raceType) { + case RM_TYPE_PRACTICE: + snprintf(buffer, BUFSIZE, "drivers/%s/cars/%s/practice/%s.xml", robot_name, carName, trackname); + break; + case RM_TYPE_QUALIF: + snprintf(buffer, BUFSIZE, "drivers/%s/cars/%s/qualifying/%s.xml", robot_name, carName, trackname); + break; + case RM_TYPE_RACE: + snprintf(buffer, BUFSIZE, "drivers/%s/cars/%s/race/%s.xml", robot_name, carName, trackname); + break; + default: + break; + } - newhandle = GfParmReadFile(buffer, GFPARM_RMODE_STD); - if (newhandle) - { - if (*carParmHandle) - *carParmHandle = GfParmMergeHandles(*carParmHandle, newhandle, (GFPARM_MMODE_SRC|GFPARM_MMODE_DST|GFPARM_MMODE_RELSRC|GFPARM_MMODE_RELDST)); - else - *carParmHandle = newhandle; - } - else - { - snprintf(buffer, BUFSIZE, "drivers/%s/cars/%s/%s.xml", robot_name, carName, trackname); - newhandle = GfParmReadFile(buffer, GFPARM_RMODE_STD); - if (newhandle) - { - if (*carParmHandle) - *carParmHandle = GfParmMergeHandles(*carParmHandle, newhandle, (GFPARM_MMODE_SRC|GFPARM_MMODE_DST|GFPARM_MMODE_RELSRC|GFPARM_MMODE_RELDST)); - else - *carParmHandle = newhandle; - } - } + newhandle = GfParmReadFile(buffer, GFPARM_RMODE_STD); + if (newhandle) + { + if (*carParmHandle) + *carParmHandle = GfParmMergeHandles(*carParmHandle, newhandle, (GFPARM_MMODE_SRC|GFPARM_MMODE_DST|GFPARM_MMODE_RELSRC|GFPARM_MMODE_RELDST)); + else + *carParmHandle = newhandle; + } + else + { + snprintf(buffer, BUFSIZE, "drivers/%s/cars/%s/%s.xml", robot_name, carName, trackname); + newhandle = GfParmReadFile(buffer, GFPARM_RMODE_STD); + if (newhandle) + { + if (*carParmHandle) + *carParmHandle = GfParmMergeHandles(*carParmHandle, newhandle, (GFPARM_MMODE_SRC|GFPARM_MMODE_DST|GFPARM_MMODE_RELSRC|GFPARM_MMODE_RELDST)); + else + *carParmHandle = newhandle; + } + } - // Create a pit stop strategy object. - strategy = new SimpleStrategy2(); - strategy->setTrack(track); + // Create a pit stop strategy object. + strategy = new SimpleStrategy2(); + strategy->setTrack(track); - // Init fuel. - strategy->setFuelAtRaceStart(t, carParmHandle, s, INDEX); + // Init fuel. + strategy->setFuelAtRaceStart(t, carParmHandle, s, INDEX); - // Load and set parameters. - MU_FACTOR = GfParmGetNum(*carParmHandle, SECT_PRIVATE, BT_ATT_MUFACTOR, (char*)NULL, 0.69f); + // Load and set parameters. + MU_FACTOR = GfParmGetNum(*carParmHandle, SECT_PRIVATE, BT_ATT_MUFACTOR, (char*)NULL, 0.69f); - PitOffset = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_PIT_OFFSET, (char *)NULL, 10.0f ); - PitExitSpeed = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_PIT_EXIT_SPEED, (char *)NULL, 100.0f ); - TurnDecel = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_TURN_DECEL, (char *)NULL, 1.0f ); - RevsChangeUp = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_REVS_UP, (char *)NULL, 0.96f ); - RevsChangeDown = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_REVS_DOWN, (char *)NULL, 0.75f ); - RevsChangeDownMax = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_REVS_DOWN_MAX, (char *)NULL, 0.85f ); - MaxSteerTime = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_MAX_STEER_TIME, (char *)NULL, 1.5f ); - MinSteerTime = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_MIN_STEER_TIME, (char *)NULL, 1.0f ); - SteerCutoff = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_STEER_CUTOFF, (char *)NULL, 55.0f ); - SmoothSteer = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_SMOOTH_STEER, (char *)NULL, 1.0f ); - LookAhead = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_LOOKAHEAD, (char *)NULL, 1.0f ); - IncFactor = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_INC_FACTOR, (char *)NULL, 1.0f ); - SideMargin = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_SIDE_MARGIN, (char *)NULL, 0.0f ); - OutSteerFactor = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_OUT_STEER_X, (char *)NULL, 1.0f ); - StuckAccel = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_STUCK_ACCEL, (char *)NULL, 0.8f ); - StuckAngle = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_STUCK_ANGLE, (char *)NULL, 1.6f ); - FollowMargin = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_FOLLOW_MARGIN, (char *)NULL, 0.0f ); - SteerLookahead = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_STEER_LOOKAHEAD, (char *)NULL, 1.0f ); - CorrectDelay = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_CORRECT_DELAY, (char *)NULL, 0.0f ); - MinAccel = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_MIN_ACCEL, (char *)NULL, 0.2f ); - MaxGear = (int) GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_MAX_GEAR, (char *)NULL, 6.0f ); - NoPit = (int) GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_NO_PIT, (char *)NULL, 0.0f ); - NoTeamWaiting = (int) GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_NO_TEAM_WAITING, (char *)NULL, 1.0f ); - TeamWaitTime = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_TEAM_WAIT_TIME, (char *)NULL, 0.0f); - YawRateAccel = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_YAW_RATE_ACCEL, (char *)NULL, 0.0f); + PitOffset = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_PIT_OFFSET, (char *)NULL, 10.0f ); + PitExitSpeed = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_PIT_EXIT_SPEED, (char *)NULL, 100.0f ); + TurnDecel = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_TURN_DECEL, (char *)NULL, 1.0f ); + RevsChangeUp = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_REVS_UP, (char *)NULL, 0.96f ); + RevsChangeDown = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_REVS_DOWN, (char *)NULL, 0.75f ); + RevsChangeDownMax = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_REVS_DOWN_MAX, (char *)NULL, 0.85f ); + MaxSteerTime = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_MAX_STEER_TIME, (char *)NULL, 1.5f ); + MinSteerTime = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_MIN_STEER_TIME, (char *)NULL, 1.0f ); + SteerCutoff = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_STEER_CUTOFF, (char *)NULL, 55.0f ); + SmoothSteer = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_SMOOTH_STEER, (char *)NULL, 1.0f ); + LookAhead = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_LOOKAHEAD, (char *)NULL, 1.0f ); + IncFactor = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_INC_FACTOR, (char *)NULL, 1.0f ); + SideMargin = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_SIDE_MARGIN, (char *)NULL, 0.0f ); + OutSteerFactor = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_OUT_STEER_X, (char *)NULL, 1.0f ); + StuckAccel = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_STUCK_ACCEL, (char *)NULL, 0.8f ); + StuckAngle = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_STUCK_ANGLE, (char *)NULL, 1.6f ); + FollowMargin = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_FOLLOW_MARGIN, (char *)NULL, 0.0f ); + SteerLookahead = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_STEER_LOOKAHEAD, (char *)NULL, 1.0f ); + CorrectDelay = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_CORRECT_DELAY, (char *)NULL, 0.0f ); + MinAccel = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_MIN_ACCEL, (char *)NULL, 0.2f ); + MaxGear = (int) GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_MAX_GEAR, (char *)NULL, 6.0f ); + NoPit = (int) GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_NO_PIT, (char *)NULL, 0.0f ); + NoTeamWaiting = (int) GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_NO_TEAM_WAITING, (char *)NULL, 1.0f ); + TeamWaitTime = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_TEAM_WAIT_TIME, (char *)NULL, 0.0f); + YawRateAccel = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_YAW_RATE_ACCEL, (char *)NULL, 0.0f); - double brkpressure = GfParmGetNum( *carParmHandle, SECT_BRKSYST, PRM_BRKPRESS, (char *) NULL, 0.0f ) / 1000; + double brkpressure = GfParmGetNum( *carParmHandle, SECT_BRKSYST, PRM_BRKPRESS, (char *) NULL, 0.0f ) / 1000; brakeratio -= MIN(0.5, MAX(0.0, brkpressure - 20000.0) / 100000); - for (i=0; i<6; i++) - { - char szTmp[32]; + for (i=0; i<6; i++) + { + char szTmp[32]; - sprintf(szTmp, "%s %d", PRV_REVS_UP, i+1); - GearRevsChangeUp[i] = GfParmGetNum( *carParmHandle, SECT_PRIVATE, szTmp, (char *)NULL, RevsChangeUp ); + sprintf(szTmp, "%s %d", PRV_REVS_UP, i+1); + GearRevsChangeUp[i] = GfParmGetNum( *carParmHandle, SECT_PRIVATE, szTmp, (char *)NULL, RevsChangeUp ); - sprintf(szTmp, "%s %d", PRV_REVS_DOWN, i+1); - GearRevsChangeDown[i] = GfParmGetNum( *carParmHandle, SECT_PRIVATE, szTmp, (char *)NULL, RevsChangeDown ); + sprintf(szTmp, "%s %d", PRV_REVS_DOWN, i+1); + GearRevsChangeDown[i] = GfParmGetNum( *carParmHandle, SECT_PRIVATE, szTmp, (char *)NULL, RevsChangeDown ); - sprintf(szTmp, "%s %d", PRV_REVS_DOWN_MAX, i+1); - GearRevsChangeDownMax[i] = GfParmGetNum( *carParmHandle, SECT_PRIVATE, szTmp, (char *)NULL, RevsChangeDownMax ); - } + sprintf(szTmp, "%s %d", PRV_REVS_DOWN_MAX, i+1); + GearRevsChangeDownMax[i] = GfParmGetNum( *carParmHandle, SECT_PRIVATE, szTmp, (char *)NULL, RevsChangeDownMax ); + } - tLftMargin = (LRLMod *) malloc( sizeof(LRLMod) ); - tRgtMargin = (LRLMod *) malloc( sizeof(LRLMod) ); - tYawRateAccel = (LRLMod *) malloc( sizeof(LRLMod) ); - memset( tLftMargin, 0, sizeof(LRLMod) ); - memset( tRgtMargin, 0, sizeof(LRLMod) ); - memset( tYawRateAccel, 0, sizeof(LRLMod) ); + tLftMargin = (LRLMod *) malloc( sizeof(LRLMod) ); + tRgtMargin = (LRLMod *) malloc( sizeof(LRLMod) ); + tYawRateAccel = (LRLMod *) malloc( sizeof(LRLMod) ); + memset( tLftMargin, 0, sizeof(LRLMod) ); + memset( tRgtMargin, 0, sizeof(LRLMod) ); + memset( tYawRateAccel, 0, sizeof(LRLMod) ); - for (i=0; i_trkPos.toLeft; - this->car = car; - int stdebug = (int) GfParmGetNum(car->_carHandle, SECT_PRIVATE, PRV_STEER_DEBUG, NULL, 0); - int otdebug = (int) GfParmGetNum(car->_carHandle, SECT_PRIVATE, PRV_OVERTAKE_DEBUG, NULL, 0); - int brdebug = (int) GfParmGetNum(car->_carHandle, SECT_PRIVATE, PRV_BRAKE_DEBUG, NULL, 0); - if ((RM_TYPE_PRACTICE == s->_raceType && stdebug >= 0) || stdebug > 0) DebugMsg |= debug_steer; - if (otdebug) DebugMsg |= debug_overtake; - if (brdebug) DebugMsg |= debug_brake; - FuelSpeedUp = GfParmGetNum(car->_carHandle, SECT_PRIVATE, PRV_FUEL_SPEEDUP, NULL, 0.0f); - TclSlip = GfParmGetNum(car->_carHandle, SECT_PRIVATE, PRV_TCL_SLIP, NULL, 2.0f); - TclRange = GfParmGetNum(car->_carHandle, SECT_PRIVATE, PRV_TCL_RANGE, NULL, 10.0f); - AbsSlip = GfParmGetNum(car->_carHandle, SECT_PRIVATE, PRV_ABS_SLIP, NULL, 2.5f); - AbsRange = GfParmGetNum(car->_carHandle, SECT_PRIVATE, PRV_ABS_RANGE, NULL, 5.0f); - OversteerASR = GfParmGetNum(car->_carHandle, SECT_PRIVATE, PRV_OVERSTEER_ASR, NULL, 0.4f); - BrakeMu = GfParmGetNum(car->_carHandle, SECT_PRIVATE, PRV_BRAKE_MU, NULL, 1.0f); - YawRateAccel = GfParmGetNum(car->_carHandle, SECT_PRIVATE, PRV_YAW_RATE_ACCEL, NULL, 0.0f); - fuelperlap = GfParmGetNum(car->_carHandle, SECT_PRIVATE, PRV_FUEL_PER_LAP, NULL, 5.0f); - CARMASS = GfParmGetNum(car->_carHandle, SECT_CAR, PRM_MASS, NULL, 1000.0f); - maxfuel = GfParmGetNum(car->_carHandle, SECT_CAR, PRM_TANK, NULL, 100.0f); - steerLock = GfParmGetNum(car->_carHandle, SECT_STEER, PRM_STEERLOCK, (char *)NULL, 4.0f); - brakemargin = GfParmGetNum(car->_carHandle, SECT_PRIVATE, PRV_BRAKE_MARGIN, (char *)NULL, 0.0f); - myoffset = 0.0f; - cmd_accel = cmd_brake = cmd_clutch = cmd_steer = cmd_light = 0.0f; - cmd_gear = 1; - skipcount = 0; - simtime = correcttimer = skill_adjust_limit = aligned_timer = stopped_timer = 0.0; - avoidtime = frontavoidtime = 0.0; - correctlimit = 1000.0; - deltamult = 1.0 / s->deltaTime; - racetype = s->_raceType; - initWheelPos(); - initCa(); - initCw(); - initTireMu(); - initTCLfilter(); + deltaTime = (float) RCM_MAX_DT_ROBOTS; + MAX_UNSTUCK_COUNT = int(UNSTUCK_TIME_LIMIT/deltaTime); + OVERTAKE_OFFSET_INC = OVERTAKE_OFFSET_SPEED*deltaTime; + random_seed = 0; + alone = allow_stuck = 1; + stuckcheck = 0; + clutchtime = stuck_timer = 0.0f; + last_stuck_time = -100.0f; + oldtime_mod = oldlookahead = laststeer = lastbrake = lastaccel = avgaccel_x = lastNSasteer = lastNSksteer = 0.0f; + brake_adjust_targ = decel_adjust_targ = 1.0f; + brake_adjust_perc = decel_adjust_perc = 1.0f; + prevleft = car->_trkPos.toLeft; + this->car = car; + int stdebug = (int) GfParmGetNum(car->_carHandle, SECT_PRIVATE, PRV_STEER_DEBUG, NULL, 0); + int otdebug = (int) GfParmGetNum(car->_carHandle, SECT_PRIVATE, PRV_OVERTAKE_DEBUG, NULL, 0); + int brdebug = (int) GfParmGetNum(car->_carHandle, SECT_PRIVATE, PRV_BRAKE_DEBUG, NULL, 0); + if ((RM_TYPE_PRACTICE == s->_raceType && stdebug >= 0) || stdebug > 0) DebugMsg |= debug_steer; + if (otdebug) DebugMsg |= debug_overtake; + if (brdebug) DebugMsg |= debug_brake; + FuelSpeedUp = GfParmGetNum(car->_carHandle, SECT_PRIVATE, PRV_FUEL_SPEEDUP, NULL, 0.0f); + TclSlip = GfParmGetNum(car->_carHandle, SECT_PRIVATE, PRV_TCL_SLIP, NULL, 2.0f); + TclRange = GfParmGetNum(car->_carHandle, SECT_PRIVATE, PRV_TCL_RANGE, NULL, 10.0f); + AbsSlip = GfParmGetNum(car->_carHandle, SECT_PRIVATE, PRV_ABS_SLIP, NULL, 2.5f); + AbsRange = GfParmGetNum(car->_carHandle, SECT_PRIVATE, PRV_ABS_RANGE, NULL, 5.0f); + OversteerASR = GfParmGetNum(car->_carHandle, SECT_PRIVATE, PRV_OVERSTEER_ASR, NULL, 0.4f); + BrakeMu = GfParmGetNum(car->_carHandle, SECT_PRIVATE, PRV_BRAKE_MU, NULL, 1.0f); + YawRateAccel = GfParmGetNum(car->_carHandle, SECT_PRIVATE, PRV_YAW_RATE_ACCEL, NULL, 0.0f); + fuelperlap = GfParmGetNum(car->_carHandle, SECT_PRIVATE, PRV_FUEL_PER_LAP, NULL, 5.0f); + CARMASS = GfParmGetNum(car->_carHandle, SECT_CAR, PRM_MASS, NULL, 1000.0f); + maxfuel = GfParmGetNum(car->_carHandle, SECT_CAR, PRM_TANK, NULL, 100.0f); + steerLock = GfParmGetNum(car->_carHandle, SECT_STEER, PRM_STEERLOCK, (char *)NULL, 4.0f); + brakemargin = GfParmGetNum(car->_carHandle, SECT_PRIVATE, PRV_BRAKE_MARGIN, (char *)NULL, 0.0f); + myoffset = 0.0f; + cmd_accel = cmd_brake = cmd_clutch = cmd_steer = cmd_light = 0.0f; + cmd_gear = 1; + skipcount = 0; + simtime = correcttimer = skill_adjust_limit = aligned_timer = stopped_timer = 0.0; + avoidtime = frontavoidtime = 0.0; + correctlimit = 1000.0; + deltamult = 1.0 / s->deltaTime; + racetype = s->_raceType; + initWheelPos(); + initCa(); + initCw(); + initTireMu(); + initTCLfilter(); - raceline = new LRaceLine(); - raceline->NewRace( car, s ); - raceline->setSkill( skill ); - raceline->AllocTrack( track ); - { - char *ptrackname = strrchr(track->filename, '/') + 1; - char *p = strrchr(ptrackname, '.'); - char trackname[256] = {0}; - - if (p) - strncpy(trackname, ptrackname, p - ptrackname); - else - strcpy(trackname, ptrackname); + raceline = new LRaceLine(); + raceline->NewRace( car, s ); + raceline->setSkill( skill ); + raceline->AllocTrack( track ); + { + char *ptrackname = strrchr(track->filename, '/') + 1; + char *p = strrchr(ptrackname, '.'); + char trackname[256] = {0}; + + if (p) + strncpy(trackname, ptrackname, p - ptrackname); + else + strcpy(trackname, ptrackname); - char carName[256]; - { - char const *path = SECT_GROBJECTS "/" LST_RANGES "/" "1"; - char const *key = PRM_CAR; - strncpy( carName, GfParmGetStr(car->_carHandle, path, key, ""), sizeof(carName) ); - char *p = strrchr(carName, '.'); - if (p) *p = '\0'; - } + char carName[256]; + { + char const *path = SECT_GROBJECTS "/" LST_RANGES "/" "1"; + char const *key = PRM_CAR; + strncpy( carName, GfParmGetStr(car->_carHandle, path, key, ""), sizeof(carName) ); + char *p = strrchr(carName, '.'); + if (p) *p = '\0'; + } - LoadDAT( s, carName, trackname ); - } - raceline->InitTrack(track, s); - raceline->setCW( CW ); + LoadDAT( s, carName, trackname ); + } + raceline->InitTrack(track, s); + raceline->setCW( CW ); - rldata = new LRaceLineData(); - memset(rldata, 0, sizeof(LRaceLineData)); + rldata = new LRaceLineData(); + memset(rldata, 0, sizeof(LRaceLineData)); - // Create just one instance of cardata shared by all drivers. - if (cardata == NULL) { - cardata = new Cardata(s); - } - mycardata = cardata->findCar(car); - simtime = s->currentTime; - skill_adjust_timer = -1; + // Create just one instance of cardata shared by all drivers. + if (cardata == NULL) { + cardata = new Cardata(s); + } + mycardata = cardata->findCar(car); + simtime = s->currentTime; + skill_adjust_timer = -1; - // initialize the list of opponents. - opponents = new Opponents(s, this, cardata); - opponent = opponents->getOpponentPtr(); + // initialize the list of opponents. + opponents = new Opponents(s, this, cardata); + opponent = opponents->getOpponentPtr(); - // Set team mate. - char *teammate = (char *) GfParmGetStr(car->_carHandle, SECT_PRIVATE, BT_ATT_TEAMMATE, NULL); - if (teammate != NULL) { - opponents->setTeamMate(teammate); - } + // Set team mate. + char *teammate = (char *) GfParmGetStr(car->_carHandle, SECT_PRIVATE, BT_ATT_TEAMMATE, NULL); + if (teammate != NULL) { + opponents->setTeamMate(teammate); + } - // Initialize radius of segments. - radius = new float[track->nseg]; - computeRadius(radius); + // Initialize radius of segments. + radius = new float[track->nseg]; + computeRadius(radius); - // create the pit object. - pit = new Pit(s, this, PitOffset); - setMode( mode_correcting ); - lastmode = mode_correcting; + // create the pit object. + pit = new Pit(s, this, PitOffset); + setMode( mode_correcting ); + lastmode = mode_correcting; - carindex = 0; + carindex = 0; - for (int i = 0; i < s->_ncars; i++) - { - if (s->cars[i] == car) - { - carindex = i; - break; - } - } + for (int i = 0; i < s->_ncars; i++) + { + if (s->cars[i] == car) + { + carindex = i; + break; + } + } #ifdef SPEED_DREAMS - teamIndex = RtTeamManagerIndex( car, track, s ); - strategy->setTeamIndex( teamIndex ); + teamIndex = RtTeamManagerIndex( car, track, s ); + strategy->setTeamIndex( teamIndex ); #endif } void Driver::calcSpeed() { - accelcmd = brakecmd = 0.0f; - faccelcmd = fbrakecmd = 0.0f; - double speed = rldata->speed; - double avspeed = MAX((currentspeed+0.4)-(MAX(0.0, 1.6-fabs(MAX(0.0, angle-speedangle))*5)), rldata->avspeed); - double slowavspeed = rldata->slowavspeed; + accelcmd = brakecmd = 0.0f; + faccelcmd = fbrakecmd = 0.0f; + double speed = rldata->speed; + double avspeed = MAX((currentspeed+0.4)-(MAX(0.0, 1.6-fabs(MAX(0.0, angle-speedangle))*5)), rldata->avspeed); + double slowavspeed = rldata->slowavspeed; - double speed_redux = 1.0; + double speed_redux = 1.0; - if (mode != mode_normal) - { - if (fabs(speedangle) > 0.05 && - (fabs(speedangle) > fabs(rldata->rlangle) || fabs(speedangle - rldata->rlangle) > 0.05)) - speed_redux -= MIN(0.6, MIN(fabs(speedangle), fabs(speedangle-rldata->rlangle))/2); - avspeed *= speed_redux; - slowavspeed *= speed_redux; - } + if (mode != mode_normal) + { + if (fabs(speedangle) > 0.05 && + (fabs(speedangle) > fabs(rldata->rlangle) || fabs(speedangle - rldata->rlangle) > 0.05)) + speed_redux -= MIN(0.6, MIN(fabs(speedangle), fabs(speedangle-rldata->rlangle))/2); + avspeed *= speed_redux; + slowavspeed *= speed_redux; + } - if (mode == mode_avoiding && !allowcorrecting) - { - speed = avspeed; - if ((avoidmode & avoidside) && !rldata->insideline && sideratio < 1.0 && - ((rldata->rInverse > 0.0 && (avoidmode & avoidright) && speedangle < -(sideratio/10)) || - (rldata->rInverse < 0.0 && (avoidmode & avoidleft) && speedangle > (sideratio/10)))) - { - speed = slowavspeed; - } - } - else if ((mode == mode_correcting || (simtime - aligned_timer < 2.0)) && rldata->insideline && rldata->closing) - { - speed = slowavspeed; - } - else if ((mode == mode_correcting || (simtime - aligned_timer < 5.0))) - { - //avspeed = MIN(rldata->speed - MIN(3.0, fabs(rldata->rInverse)*400), avspeed); - avspeed = MIN(rldata->speed, (slowavspeed+avspeed)/2); - double rlspeed = rldata->speed;//MAX(avspeed, rldata->speed-1.0); - //speed = avspeed + (rlspeed-avspeed) * MAX(0.0, MIN(1.0, 1.0 - MAX(fabs(correctlimit*2), fabs(fabs(laststeer)-fabs(rldata->rInverse*80))/2))); - speed = avspeed + (rlspeed-avspeed) * MAX(0.0, MIN(1.0, 1.0 - (fabs(correctlimit*2) + fabs(angle - rldata->rlangle)*5))); - } + if (mode == mode_avoiding && !allowcorrecting) + { + speed = avspeed; + if ((avoidmode & avoidside) && !rldata->insideline && sideratio < 1.0 && + ((rldata->rInverse > 0.0 && (avoidmode & avoidright) && speedangle < -(sideratio/10)) || + (rldata->rInverse < 0.0 && (avoidmode & avoidleft) && speedangle > (sideratio/10)))) + { + speed = slowavspeed; + } + } + else if ((mode == mode_correcting || (simtime - aligned_timer < 2.0)) && rldata->insideline && rldata->closing) + { + speed = slowavspeed; + } + else if ((mode == mode_correcting || (simtime - aligned_timer < 5.0))) + { + //avspeed = MIN(rldata->speed - MIN(3.0, fabs(rldata->rInverse)*400), avspeed); + avspeed = MIN(rldata->speed, (slowavspeed+avspeed)/2); + double rlspeed = rldata->speed;//MAX(avspeed, rldata->speed-1.0); + //speed = avspeed + (rlspeed-avspeed) * MAX(0.0, MIN(1.0, 1.0 - MAX(fabs(correctlimit*2), fabs(fabs(laststeer)-fabs(rldata->rInverse*80))/2))); + speed = avspeed + (rlspeed-avspeed) * MAX(0.0, MIN(1.0, 1.0 - (fabs(correctlimit*2) + fabs(angle - rldata->rlangle)*5))); + } - if (pit->getInPit() && !pit->getPitstop()) - { - float s = pit->toSplineCoord( car->_distFromStartLine ); - if (s > pit->getNPitEnd()) - speed = MIN(speed, PitExitSpeed); - } + if (pit->getInPit() && !pit->getPitstop()) + { + float s = pit->toSplineCoord( car->_distFromStartLine ); + if (s > pit->getNPitEnd()) + speed = MIN(speed, PitExitSpeed); + } - //if (mode == mode_normal && fabs(rldata->rInverse) < 0.001 && fabs(car->_steerCmd) < 0.01 && fabs(angle) < 0.01 && fabs(car->_yaw_rate) < 0.01) - // aligned_timer = 0.0; + //if (mode == mode_normal && fabs(rldata->rInverse) < 0.001 && fabs(car->_steerCmd) < 0.01 && fabs(angle) < 0.01 && fabs(car->_yaw_rate) < 0.01) + // aligned_timer = 0.0; - double x = (10 + car->_speed_x) * (speed - car->_speed_x) / 200; - double lane2left = car->_trkPos.toLeft / track->width; - double lane2right = car->_trkPos.toRight / track->width; - int sidedanger = ((rldata->rInverse > 0.0 && speedangle < -(rldata->rInverse) * lane2left*2) || (rldata->rInverse < 0.0 && speedangle > rldata->rInverse*lane2right*2)); - double skid = MAX(0.0, (car->_skid[2] + car->_skid[3] + car->_skid[0] + car->_skid[1])) * 3; + double x = (10 + car->_speed_x) * (speed - car->_speed_x) / 200; + double lane2left = car->_trkPos.toLeft / track->width; + double lane2right = car->_trkPos.toRight / track->width; + int sidedanger = ((rldata->rInverse > 0.0 && speedangle < -(rldata->rInverse) * lane2left*2) || (rldata->rInverse < 0.0 && speedangle > rldata->rInverse*lane2right*2)); + double skid = MAX(0.0, (car->_skid[2] + car->_skid[3] + car->_skid[0] + car->_skid[1])) * 3; - brakecmd = 0.0f; - accelcmd = 100.0f; + brakecmd = 0.0f; + accelcmd = 100.0f; - { - double skidangle = angle; - if (mode != mode_normal) - { - if ((angle > 0.0 && speedangle < angle) || - (angle < 0.0 && speedangle > angle)) - skidangle += speedangle/2; - } + { + double skidangle = angle; + if (mode != mode_normal) + { + if ((angle > 0.0 && speedangle < angle) || + (angle < 0.0 && speedangle > angle)) + skidangle += speedangle/2; + } #if 0 - // if over/understeering, decrease speed - if (rldata->rInverse > 0.0) - { - double mod = ((laststeer-rldata->rInverse) * fabs(rldata->rInverse*15)); - if (mod < 0.0) // oversteer, will increase x but by less if skidding outwards - mod /= 4 - MIN(0.0, skidangle * 10); - x = MIN(x, 1.0) - mod; - } - else - { - double mod = ((laststeer-rldata->rInverse) * fabs(rldata->rInverse*15)); - if (mod > 0.0) // oversteer - mod /= 4 + MAX(0.0, skidangle * 10); - x = MIN(x, 1.0) + mod; - } + // if over/understeering, decrease speed + if (rldata->rInverse > 0.0) + { + double mod = ((laststeer-rldata->rInverse) * fabs(rldata->rInverse*15)); + if (mod < 0.0) // oversteer, will increase x but by less if skidding outwards + mod /= 4 - MIN(0.0, skidangle * 10); + x = MIN(x, 1.0) - mod; + } + else + { + double mod = ((laststeer-rldata->rInverse) * fabs(rldata->rInverse*15)); + if (mod > 0.0) // oversteer + mod /= 4 + MAX(0.0, skidangle * 10); + x = MIN(x, 1.0) + mod; + } #else - if (//(mode == mode_normal || !sidedanger) && - (skidangle < 0.0 && laststeer > 0.0 && rldata->rInverse < -0.001) || - (skidangle > 0.0 && laststeer < 0.0 && rldata->rInverse > 0.001)) - { - // increase acceleration if correcting a skid - double diff = MAX(0.0, MIN(fabs(laststeer), MAX(fabs(skidangle/7)/1000, fabs(rldata->rInverse * 50)))) * MAX(0.0, MIN(2.0, (7-skid))); - if (collision) - diff *= MIN(1.0, collision / 3.0f)*0.8; - x += diff * OversteerASR; - } - else if (mode != mode_normal && - (car->_accel_x < 1.0 || sidedanger) && - ((angle > 0.0 && laststeer > 0.0 && rldata->rInverse < -0.001) || - (angle < 0.0 && laststeer < 0.0 && rldata->rInverse > 0.001))) - { - // understeering, decrease speed - double diff = MIN(fabs(laststeer), MAX(fabs(angle)/50, fabs(rldata->rInverse * 50))) * 4; - x -= diff; - } + if (//(mode == mode_normal || !sidedanger) && + (skidangle < 0.0 && laststeer > 0.0 && rldata->rInverse < -0.001) || + (skidangle > 0.0 && laststeer < 0.0 && rldata->rInverse > 0.001)) + { + // increase acceleration if correcting a skid + double diff = MAX(0.0, MIN(fabs(laststeer), MAX(fabs(skidangle/7)/1000, fabs(rldata->rInverse * 50)))) * MAX(0.0, MIN(2.0, (7-skid))); + if (collision) + diff *= MIN(1.0, collision / 3.0f)*0.8; + x += diff * OversteerASR; + } + else if (mode != mode_normal && + (car->_accel_x < 1.0 || sidedanger) && + ((angle > 0.0 && laststeer > 0.0 && rldata->rInverse < -0.001) || + (angle < 0.0 && laststeer < 0.0 && rldata->rInverse > 0.001))) + { + // understeering, decrease speed + double diff = MIN(fabs(laststeer), MAX(fabs(angle)/50, fabs(rldata->rInverse * 50))) * 4; + x -= diff; + } #endif #if 0 - // check if we're really close behind someone on a bend - // if so (and we're not overtaking) make sure we don't under-brake or - // over-accelerate and thus lose control. - fbrakecmd = faccelcmd = 0.0f; + // check if we're really close behind someone on a bend + // if so (and we're not overtaking) make sure we don't under-brake or + // over-accelerate and thus lose control. + fbrakecmd = faccelcmd = 0.0f; - if (mode == mode_normal) - { - for (int i=0; igetNOpponents(); i++) - { - tCarElt *ocar = opponent[i].getCarPtr(); + if (mode == mode_normal) + { + for (int i=0; igetNOpponents(); i++) + { + tCarElt *ocar = opponent[i].getCarPtr(); - if (ocar == car) - continue; + if (ocar == car) + continue; - if (opponent[i].getTeam() != TEAM_FRIEND) - continue; + if (opponent[i].getTeam() != TEAM_FRIEND) + continue; - if (!(opponent[i].getState() & OPP_FRONT) || opponent[i].getDistance() > 3.0) - continue; + if (!(opponent[i].getState() & OPP_FRONT) || opponent[i].getDistance() > 3.0) + continue; - if (fabs(car->_trkPos.toLeft - ocar->_trkPos.toLeft) > car->_dimension_x*0.8) - continue; + if (fabs(car->_trkPos.toLeft - ocar->_trkPos.toLeft) > car->_dimension_x*0.8) + continue; - if (mode == mode_normal && opponent[i].isTeamMate() && opponent[i].getDistance() < 1.5) - { - accelcmd = ocar->_accelCmd; - if (accelcmd > 0.0f) - faccelcmd = accelcmd; - } + if (mode == mode_normal && opponent[i].isTeamMate() && opponent[i].getDistance() < 1.5) + { + accelcmd = ocar->_accelCmd; + if (accelcmd > 0.0f) + faccelcmd = accelcmd; + } - /* - if ((rldata->rInverse > 0.001 && car->_trkPos.toLeft > rldata->lane * car->_trkPos.seg->width) || - (rldata->rInverse < -0.001 && car->_trkPos.toLeft < rldata->lane * car->_trkPos.seg->width)) - { - double change = MAX(currentspeed-rldata->speed, fabs(car->_trkPos.toLeft - (rldata->lane * car->_trkPos.seg->width))); + /* + if ((rldata->rInverse > 0.001 && car->_trkPos.toLeft > rldata->lane * car->_trkPos.seg->width) || + (rldata->rInverse < -0.001 && car->_trkPos.toLeft < rldata->lane * car->_trkPos.seg->width)) + { + double change = MAX(currentspeed-rldata->speed, fabs(car->_trkPos.toLeft - (rldata->lane * car->_trkPos.seg->width))); - x -= MAX(0.0, MIN(1.0, change)); - break; - } - */ + x -= MAX(0.0, MIN(1.0, change)); + break; + } + */ - if (opponent[i].getDistance() < 1.5 && ocar->_brakeCmd > 0.0 && (opponent[i].getState() & OPP_COLL)) - { - brakecmd = ocar->_brakeCmd*MAX(1.0, currentspeed / opponent[i].getSpeed()); - if (brakecmd > 0.0) - { - x = MIN(x, -0.001); - fbrakecmd = brakecmd; - } - } + if (opponent[i].getDistance() < 1.5 && ocar->_brakeCmd > 0.0 && (opponent[i].getState() & OPP_COLL)) + { + brakecmd = ocar->_brakeCmd*MAX(1.0, currentspeed / opponent[i].getSpeed()); + if (brakecmd > 0.0) + { + x = MIN(x, -0.001); + fbrakecmd = brakecmd; + } + } - break; - } - } + break; + } + } #endif - } + } - if (x > 0) - { - if (accelcmd < 100.0f) - accelcmd = MIN(accelcmd, (float) x); - else - accelcmd = (float) x; - accelcmd = MAX(accelcmd, MinAccel); - } - else - brakecmd = MIN(1.0f, MAX(brakecmd, (float) (-(MAX(10.0, brakedelay*0.7))*x))); + if (x > 0) + { + if (accelcmd < 100.0f) + accelcmd = MIN(accelcmd, (float) x); + else + accelcmd = (float) x; + accelcmd = MAX(accelcmd, MinAccel); + } + else + brakecmd = MIN(1.0f, MAX(brakecmd, (float) (-(MAX(10.0, brakedelay*0.7))*x))); } int Driver::rearOffTrack() @@ -847,113 +843,113 @@ int Driver::rearOffTrack() // Drive during race. void Driver::drive(tSituation *s) { - laststeer = car->_steerCmd; - memset(&car->ctrl, 0, sizeof(tCarCtrl)); + laststeer = car->_steerCmd; + memset(&car->ctrl, 0, sizeof(tCarCtrl)); - skipcount++; + skipcount++; - if (skipcount > SKIPLIMIT) - skipcount = 0; + if (skipcount > SKIPLIMIT) + skipcount = 0; - if (skipcount > 1) - { - // potentially can skip (we never do if skipcount == 0) + if (skipcount > 1) + { + // potentially can skip (we never do if skipcount == 0) - if (mode == mode_normal) - { - // driving on the raceline - if (fabs(car->_yaw_rate) < 0.15 && - fabs(car->_accel_x) > -2 && - fabs(speedangle - angle) < 0.1) - { - // car not under stress, we can skip - car->_accelCmd = cmd_accel; - car->_brakeCmd = cmd_brake; - car->_steerCmd = cmd_steer; - car->_gearCmd = cmd_gear; - car->_clutchCmd = cmd_clutch; - car->_lightCmd = (int)cmd_light; - return; - } - } - else - { - // we're avoiding someone, don't skip (for the most part) - if (skipcount > 2) - skipcount = 0; - } - } + if (mode == mode_normal) + { + // driving on the raceline + if (fabs(car->_yaw_rate) < 0.15 && + fabs(car->_accel_x) > -2 && + fabs(speedangle - angle) < 0.1) + { + // car not under stress, we can skip + car->_accelCmd = cmd_accel; + car->_brakeCmd = cmd_brake; + car->_steerCmd = cmd_steer; + car->_gearCmd = cmd_gear; + car->_clutchCmd = cmd_clutch; + car->_lightCmd = (int)cmd_light; + return; + } + } + else + { + // we're avoiding someone, don't skip (for the most part) + if (skipcount > 2) + skipcount = 0; + } + } - update(s); + update(s); - //pit->setPitstop(true); + //pit->setPitstop(true); #ifdef CONTROL_SKILL - calcSkill(); + calcSkill(); #endif - car->_steerCmd = getSteer(s); + car->_steerCmd = getSteer(s); - if (!isStuck()) - { - car->_gearCmd = getGear(); - calcSpeed(); - car->_brakeCmd = filterABS(filterBrakeSpeed(filterBColl(filterBPit(getBrake())))); - if (car->_brakeCmd == 0.0f) { - car->_accelCmd = filterTCL(filterTrk(filterTeam(filterOverlap(getAccel())))); - } else { - car->_accelCmd = 0.0f; - } + if (!isStuck()) + { + car->_gearCmd = getGear(); + calcSpeed(); + car->_brakeCmd = filterABS(filterBrakeSpeed(filterBColl(filterBPit(getBrake())))); + if (car->_brakeCmd == 0.0f) { + car->_accelCmd = filterTCL(filterTrk(filterTeam(filterOverlap(getAccel())))); + } else { + car->_accelCmd = 0.0f; + } - if (!collision && fabs(car->_speed_x) < 1.0) - { - car->_accelCmd = MAX(car->_accelCmd, 0.4f); - car->_brakeCmd = 0.0f; - } + if (!collision && fabs(car->_speed_x) < 1.0) + { + car->_accelCmd = MAX(car->_accelCmd, 0.4f); + car->_brakeCmd = 0.0f; + } - if (car->_speed_x < -1.0f) - { - car->_accelCmd = 0.0f; - car->_brakeCmd = 0.7f; - } + if (car->_speed_x < -1.0f) + { + car->_accelCmd = 0.0f; + car->_brakeCmd = 0.7f; + } - car->_clutchCmd = getClutch(); - if (DebugMsg & debug_steer) - fprintf(stderr,"%s %d/%d: ",car->_name,rldata->thisdiv,rldata->nextdiv); + car->_clutchCmd = getClutch(); + if (DebugMsg & debug_steer) + fprintf(stderr,"%s %d/%d: ",car->_name,rldata->thisdiv,rldata->nextdiv); - } + } - if (DebugMsg & debug_steer) - { - double skid = (car->_skid[0]+car->_skid[1]+car->_skid[2]+car->_skid[3])/2; - fprintf(stderr,"%d%c%c%c s%.2f k%.2f ss%.2f cl%.3f g%d->%d brk%.3f acc%.2f dec%.2f coll%.1f",mode,((mode==mode_avoiding)?'A':' '),(avoidmode==avoidleft?'L':(avoidmode==avoidright?'R':' ')),(mode==mode_correcting?'c':' '),car->_steerCmd,rldata->ksteer,stucksteer,correctlimit,car->_gear,car->_gearCmd,car->_brakeCmd,car->_accelCmd,rldata->decel,collision); - fprintf(stderr," spd%.1f|k%.1f|a%.1f/%.1f|t%.1f angle=%.2f/%.2f/%.2f yr=%.2f skid=%.2f acxy=%.2f/%.2f slip=%.3f/%.3f %.3f/%.3f\n",(double)currentspeed,(double)rldata->speed,(double)rldata->avspeed,(double)rldata->slowavspeed,(double)getTrueSpeed(),angle,speedangle,rldata->rlangle,car->_yaw_rate,skid,car->_accel_x,car->_accel_y,nextCRinverse,rldata->mInverse,car->_wheelSpinVel(FRNT_RGT)*car->_wheelRadius(FRNT_RGT)-car->_speed_x,car->_wheelSpinVel(FRNT_LFT)*car->_wheelRadius(FRNT_LFT)-car->_speed_x,car->_wheelSpinVel(REAR_RGT)*car->_wheelRadius(REAR_RGT)-car->_speed_x,car->_wheelSpinVel(REAR_LFT)*car->_wheelRadius(REAR_LFT)-car->_speed_x);fflush(stderr); - } + if (DebugMsg & debug_steer) + { + double skid = (car->_skid[0]+car->_skid[1]+car->_skid[2]+car->_skid[3])/2; + fprintf(stderr,"%d%c%c%c s%.2f k%.2f ss%.2f cl%.3f g%d->%d brk%.3f acc%.2f dec%.2f coll%.1f",mode,((mode==mode_avoiding)?'A':' '),(avoidmode==avoidleft?'L':(avoidmode==avoidright?'R':' ')),(mode==mode_correcting?'c':' '),car->_steerCmd,rldata->ksteer,stucksteer,correctlimit,car->_gear,car->_gearCmd,car->_brakeCmd,car->_accelCmd,rldata->decel,collision); + fprintf(stderr," spd%.1f|k%.1f|a%.1f/%.1f|t%.1f angle=%.2f/%.2f/%.2f yr=%.2f skid=%.2f acxy=%.2f/%.2f slip=%.3f/%.3f %.3f/%.3f\n",(double)currentspeed,(double)rldata->speed,(double)rldata->avspeed,(double)rldata->slowavspeed,(double)getTrueSpeed(),angle,speedangle,rldata->rlangle,car->_yaw_rate,skid,car->_accel_x,car->_accel_y,nextCRinverse,rldata->mInverse,car->_wheelSpinVel(FRNT_RGT)*car->_wheelRadius(FRNT_RGT)-car->_speed_x,car->_wheelSpinVel(FRNT_LFT)*car->_wheelRadius(FRNT_LFT)-car->_speed_x,car->_wheelSpinVel(REAR_RGT)*car->_wheelRadius(REAR_RGT)-car->_speed_x,car->_wheelSpinVel(REAR_LFT)*car->_wheelRadius(REAR_LFT)-car->_speed_x);fflush(stderr); + } - laststeer = car->_steerCmd; - lastbrake = car->_brakeCmd; - lastaccel = car->_accelCmd; - lastmode = mode; - prevleft = car->_trkPos.toLeft; + laststeer = car->_steerCmd; + lastbrake = car->_brakeCmd; + lastaccel = car->_accelCmd; + lastmode = mode; + prevleft = car->_trkPos.toLeft; - cmd_accel = car->_accelCmd; - cmd_brake = car->_brakeCmd; - cmd_steer = car->_steerCmd; - cmd_clutch = car->_clutchCmd; - cmd_gear = car->_gearCmd; - cmd_light = (float)car->_lightCmd; + cmd_accel = car->_accelCmd; + cmd_brake = car->_brakeCmd; + cmd_steer = car->_steerCmd; + cmd_clutch = car->_clutchCmd; + cmd_gear = car->_gearCmd; + cmd_light = (float)car->_lightCmd; } // Set pitstop commands. int Driver::pitCommand(tSituation *s) { - car->_pitRepair = strategy->pitRepair(car, s); - car->_pitFuel = strategy->pitRefuel(car, s); - // This should be the only place where the pit stop is set to false! - pit->setPitstop(false); - return ROB_PIT_IM; // return immediately. + car->_pitRepair = strategy->pitRepair(car, s); + car->_pitFuel = strategy->pitRefuel(car, s); + // This should be the only place where the pit stop is set to false! + pit->setPitstop(false); + return ROB_PIT_IM; // return immediately. } @@ -962,16 +958,16 @@ int Driver::pitCommand(tSituation *s) void Driver::endRace(tSituation *s) { #ifdef SPEED_DREAMS - RtTeamReleasePit(teamIndex); + RtTeamReleasePit(teamIndex); #endif - car->ctrl.raceCmd = 0; + car->ctrl.raceCmd = 0; } // cleanup void Driver::shutdown() { #ifdef SPEED_DREAMS - RtTeamManagerRelease(); + RtTeamManagerRelease(); #endif } @@ -985,32 +981,32 @@ void Driver::shutdown() void Driver::computeRadius(float *radius) { - float lastturnarc = 0.0f; - int lastsegtype = TR_STR; + float lastturnarc = 0.0f; + int lastsegtype = TR_STR; - tTrackSeg *currentseg, *startseg = track->seg; - currentseg = startseg; + tTrackSeg *currentseg, *startseg = track->seg; + currentseg = startseg; - do { - if (currentseg->type == TR_STR) { - lastsegtype = TR_STR; - radius[currentseg->id] = FLT_MAX; - } else { - if (currentseg->type != lastsegtype) { - float arc = 0.0f; - tTrackSeg *s = currentseg; - lastsegtype = currentseg->type; + do { + if (currentseg->type == TR_STR) { + lastsegtype = TR_STR; + radius[currentseg->id] = FLT_MAX; + } else { + if (currentseg->type != lastsegtype) { + float arc = 0.0f; + tTrackSeg *s = currentseg; + lastsegtype = currentseg->type; - while (s->type == lastsegtype && arc < PI/2.0f) { - arc += s->arc; - s = s->next; - } - lastturnarc = (float) (arc/(PI/2.0f)); - } - radius[currentseg->id] = (float) (currentseg->radius + currentseg->width/2.0)/lastturnarc; - } - currentseg = currentseg->next; - } while (currentseg != startseg); + while (s->type == lastsegtype && arc < PI/2.0f) { + arc += s->arc; + s = s->next; + } + lastturnarc = (float) (arc/(PI/2.0f)); + } + radius[currentseg->id] = (float) (currentseg->radius + currentseg->width/2.0)/lastturnarc; + } + currentseg = currentseg->next; + } while (currentseg != startseg); } @@ -1018,63 +1014,63 @@ void Driver::computeRadius(float *radius) // Compute the length to the end of the segment. float Driver::getDistToSegEnd() { - if (car->_trkPos.seg->type == TR_STR) { - return car->_trkPos.seg->length - car->_trkPos.toStart; - } else { - return (car->_trkPos.seg->arc - car->_trkPos.toStart)*car->_trkPos.seg->radius; - } + if (car->_trkPos.seg->type == TR_STR) { + return car->_trkPos.seg->length - car->_trkPos.toStart; + } else { + return (car->_trkPos.seg->arc - car->_trkPos.toStart)*car->_trkPos.seg->radius; + } } // Compute fitting acceleration. float Driver::getAccel() { - if (car->_gear > 0) { - accelcmd = MIN(1.0f, accelcmd); + if (car->_gear > 0) { + accelcmd = MIN(1.0f, accelcmd); - if (pit->getInPit() && car->_brakeCmd == 0.0f) - { - //float s = pit->toSplineCoord( car->_distFromStartLine ); - + if (pit->getInPit() && car->_brakeCmd == 0.0f) + { + //float s = pit->toSplineCoord( car->_distFromStartLine ); + #if 0 - if (pit->needPitstop()) - { - if (currentspeedsqr > pit->getSpeedlimitSqr()*0.9) - { - accelcmd = MIN(accelcmd, 0.4f); - } - } + if (pit->needPitstop()) + { + if (currentspeedsqr > pit->getSpeedlimitSqr()*0.9) + { + accelcmd = MIN(accelcmd, 0.4f); + } + } #endif - - accelcmd = MIN(accelcmd, 0.6f); - } - else if (fabs(angle) > 0.8 && currentspeed > 10.0f) - accelcmd = MAX(0.0f, MIN(accelcmd, 1.0f - currentspeed/100.0f * fabs(angle))); + + accelcmd = MIN(accelcmd, 0.6f); + } + else if (fabs(angle) > 0.8 && currentspeed > 10.0f) + accelcmd = MAX(0.0f, MIN(accelcmd, 1.0f - currentspeed/100.0f * fabs(angle))); - return accelcmd; - } else { - return 1.0; - } + return accelcmd; + } else { + return 1.0; + } } // If we get lapped reduce accelerator. float Driver::filterOverlap(float accel) { - int i; + int i; - if (!(avoidmode & avoidback)) - { - return accel; - } + if (!(avoidmode & avoidback)) + { + return accel; + } - for (i = 0; i < opponents->getNOpponents(); i++) { - if (opponent[i].getState() & OPP_LETPASS) - { - return accel*0.4f; - } - } - return accel; + for (i = 0; i < opponents->getNOpponents(); i++) { + if (opponent[i].getState() & OPP_LETPASS) + { + return accel*0.4f; + } + } + return accel; } // slows us down to allow a team-member to catch up @@ -1166,81 +1162,81 @@ double Driver::filterTeam(double accel) // Compute initial brake value. float Driver::getBrake() { - // Car drives backward? - if (car->_speed_x < -MAX_UNSTUCK_SPEED) { - // Yes, brake. - return 1.0; - } else { - // We drive forward, normal braking. + // Car drives backward? + if (car->_speed_x < -MAX_UNSTUCK_SPEED) { + // Yes, brake. + return 1.0; + } else { + // We drive forward, normal braking. #ifdef CONTROL_SKILL - brakecmd *= brake_adjust_perc; + brakecmd *= brake_adjust_perc; #endif - return brakecmd; - } + return brakecmd; + } } // Compute gear. int Driver::getGear() { - car->_gearCmd = car->_gear; - if (car->_gear <= 0) { - return 1; - } + car->_gearCmd = car->_gear; + if (car->_gear <= 0) { + return 1; + } #if 1 - // Hymie gear changing - float speed = currentspeed; - float *tRatio = car->_gearRatio + car->_gearOffset; - float rpm = (float) ((speed + 0.5) * tRatio[car->_gear] / car->_wheelRadius(2)); - float down_rpm = (float) (car->_gear > 1 ? (speed + 0.5) * tRatio[car->_gear-1] / car->_wheelRadius(2) : rpm); + // Hymie gear changing + float speed = currentspeed; + float *tRatio = car->_gearRatio + car->_gearOffset; + float rpm = (float) ((speed + 0.5) * tRatio[car->_gear] / car->_wheelRadius(2)); + float down_rpm = (float) (car->_gear > 1 ? (speed + 0.5) * tRatio[car->_gear-1] / car->_wheelRadius(2) : rpm); - float rcu = (car->_gear < 6 && car->_gear >= 0 ? GearRevsChangeUp[car->_gear] : RevsChangeUp); - float rcd = (car->_gear < 6 && car->_gear >= 0 ? GearRevsChangeDown[car->_gear] : RevsChangeDown); - float rcm = (car->_gear < 6 && car->_gear >= 0 ? GearRevsChangeDownMax[car->_gear] : RevsChangeDownMax); + float rcu = (car->_gear < 6 && car->_gear >= 0 ? GearRevsChangeUp[car->_gear] : RevsChangeUp); + float rcd = (car->_gear < 6 && car->_gear >= 0 ? GearRevsChangeDown[car->_gear] : RevsChangeDown); + float rcm = (car->_gear < 6 && car->_gear >= 0 ? GearRevsChangeDownMax[car->_gear] : RevsChangeDownMax); - if (rpm + MAX(0.0, (double) (car->_gear-3) * (car->_gear-3)*5) > car->_enginerpmMax * rcu && car->_gear < MaxGear) - car->_gearCmd = car->_gear + 1; + if (rpm + MAX(0.0, (double) (car->_gear-3) * (car->_gear-3)*5) > car->_enginerpmMax * rcu && car->_gear < MaxGear) + car->_gearCmd = car->_gear + 1; - if (car->_gear > 1 && - rpm < car->_enginerpmMax * rcd && - down_rpm < car->_enginerpmMax * rcm) - car->_gearCmd = car->_gear - 1; + if (car->_gear > 1 && + rpm < car->_enginerpmMax * rcd && + down_rpm < car->_enginerpmMax * rcm) + car->_gearCmd = car->_gear - 1; #else - // BT gear changing - float gr_up = car->_gearRatio[car->_gear + car->_gearOffset]; - float omega = car->_enginerpmRedLine/gr_up; - float wr = car->_wheelRadius(2); + // BT gear changing + float gr_up = car->_gearRatio[car->_gear + car->_gearOffset]; + float omega = car->_enginerpmRedLine/gr_up; + float wr = car->_wheelRadius(2); - if (omega*wr*SHIFT < car->_speed_x) { - car->_gearCmd = car->_gear + 1; - } else { - float gr_down = car->_gearRatio[car->_gear + car->_gearOffset - 1]; - omega = car->_enginerpmRedLine/gr_down; - if (car->_gear > 1 && omega*wr*SHIFT > car->_speed_x + SHIFT_MARGIN) { - car->_gearCmd = car->_gear - 1; - } - } + if (omega*wr*SHIFT < car->_speed_x) { + car->_gearCmd = car->_gear + 1; + } else { + float gr_down = car->_gearRatio[car->_gear + car->_gearOffset - 1]; + omega = car->_enginerpmRedLine/gr_down; + if (car->_gear > 1 && omega*wr*SHIFT > car->_speed_x + SHIFT_MARGIN) { + car->_gearCmd = car->_gear - 1; + } + } #endif - - return car->_gearCmd; + + return car->_gearCmd; } void Driver::setMode( int newmode ) { - if (mode == newmode) - return; + if (mode == newmode) + return; - if (mode == mode_normal || mode == mode_pitting) - { - correcttimer = simtime + 7.0; - //correctlimit = 1000.0; - } + if (mode == mode_normal || mode == mode_pitting) + { + correcttimer = simtime + 7.0; + //correctlimit = 1000.0; + } - if (newmode == mode_avoiding && mode != mode_avoiding) - avoidtime = simtime; + if (newmode == mode_avoiding && mode != mode_avoiding) + avoidtime = simtime; - mode = newmode; + mode = newmode; } void Driver::calcSkill() @@ -1282,331 +1278,331 @@ void Driver::calcSkill() double Driver::getFollowDistance() { - double mindist = 1000.0; + double mindist = 1000.0; - if (mode != mode_normal) - return mindist; + if (mode != mode_normal) + return mindist; - for (int i = 0; i < opponents->getNOpponents(); i++) - { - if (opponent[i].getCarPtr() == car) continue; - //if (opponent[i].getTeam() != TEAM_FRIEND) continue; - if (!(opponent[i].getState() & OPP_FRONT)) - continue; + for (int i = 0; i < opponents->getNOpponents(); i++) + { + if (opponent[i].getCarPtr() == car) continue; + //if (opponent[i].getTeam() != TEAM_FRIEND) continue; + if (!(opponent[i].getState() & OPP_FRONT)) + continue; - if (opponent[i].getDistance() > 5.0) - continue; + if (opponent[i].getDistance() > 5.0) + continue; - mindist = MIN(mindist, opponent[i].getDistance()) - FollowMargin; - } - return mindist; + mindist = MIN(mindist, opponent[i].getDistance()) - FollowMargin; + } + return mindist; } // Compute steer value. float Driver::getSteer(tSituation *s) { - double targetAngle; - memset(rldata, 0, sizeof(LRaceLineData)); - rldata->angle = angle; - rldata->speedangle = speedangle; - rldata->mode = mode; - rldata->avoidmode = avoidmode; - rldata->collision = collision; - rldata->steer = rldata->laststeer = laststeer; - rldata->alone = alone; - rldata->followdist = getFollowDistance(); - rldata->s = s; - rldata->aligned_time = simtime - aligned_timer; - raceline->GetRaceLineData( s, rldata ); - if (FuelSpeedUp) - { - double fuel = (car->_fuel/maxfuel); - fuel = MIN(1.0, fuel * (fuel+0.15)); - rldata->speed += FuelSpeedUp * (1.0 - fuel); - } - double steer = 0.0, tmpsteer = 0.0; - double avoidsteer = 0.0; - double racesteer = (rldata->ksteer); - vec2f target; + double targetAngle; + memset(rldata, 0, sizeof(LRaceLineData)); + rldata->angle = angle; + rldata->speedangle = speedangle; + rldata->mode = mode; + rldata->avoidmode = avoidmode; + rldata->collision = collision; + rldata->steer = rldata->laststeer = laststeer; + rldata->alone = alone; + rldata->followdist = getFollowDistance(); + rldata->s = s; + rldata->aligned_time = simtime - aligned_timer; + raceline->GetRaceLineData( s, rldata ); + if (FuelSpeedUp) + { + double fuel = (car->_fuel/maxfuel); + fuel = MIN(1.0, fuel * (fuel+0.15)); + rldata->speed += FuelSpeedUp * (1.0 - fuel); + } + double steer = 0.0, tmpsteer = 0.0; + double avoidsteer = 0.0; + double racesteer = (rldata->ksteer); + vec2f target; #if 0 - if (SteerLookahead > 6.0f) - { - raceline->GetSteerPoint( (double) SteerLookahead, &target ); - targetAngle = atan2(target.y - car->_pos_Y, target.x - car->_pos_X); - racesteer = calcSteer( targetAngle, 0 ); - double rIf = MIN(1.0, fabs(rldata->rInverse) / SteerMaxRI); - racesteer = racesteer + (rldata->ksteer - racesteer) * rIf; - } + if (SteerLookahead > 6.0f) + { + raceline->GetSteerPoint( (double) SteerLookahead, &target ); + targetAngle = atan2(target.y - car->_pos_Y, target.x - car->_pos_X); + racesteer = calcSteer( targetAngle, 0 ); + double rIf = MIN(1.0, fabs(rldata->rInverse) / SteerMaxRI); + racesteer = racesteer + (rldata->ksteer - racesteer) * rIf; + } #endif - target = getTargetPoint(false); - steer = avoidsteer = racesteer; - lastNSksteer = rldata->NSsteer; + target = getTargetPoint(false); + steer = avoidsteer = racesteer; + lastNSksteer = rldata->NSsteer; - if (mode != mode_normal || SteerLookahead < 6.0f) - { - targetAngle = atan2(target.y - car->_pos_Y, target.x - car->_pos_X); - tmpsteer = calcSteer( targetAngle, 0 ); - } + if (mode != mode_normal || SteerLookahead < 6.0f) + { + targetAngle = atan2(target.y - car->_pos_Y, target.x - car->_pos_X); + tmpsteer = calcSteer( targetAngle, 0 ); + } - if (mode != mode_normal) - { - avoidsteer = tmpsteer; + if (mode != mode_normal) + { + avoidsteer = tmpsteer; - if (mode == mode_pitting) - { - correctlimit = (avoidsteer - racesteer); - return avoidsteer; - } + if (mode == mode_pitting) + { + correctlimit = (avoidsteer - racesteer); + return avoidsteer; + } - //targetAngle = atan2(rldata->target.y - car->_pos_Y, rldata->target.x - car->_pos_X); + //targetAngle = atan2(rldata->target.y - car->_pos_Y, rldata->target.x - car->_pos_X); - allowcorrecting = 0; - if (mode == mode_avoiding && - (!avoidmode || - (avoidmode == avoidright && racesteer > avoidsteer) || - (avoidmode == avoidleft && racesteer < avoidsteer))) - { - // we're avoiding, but trying to steer somewhere the raceline takes us. - // hence we'll just correct towards the raceline instead. - allowcorrecting = 1; - } + allowcorrecting = 0; + if (mode == mode_avoiding && + (!avoidmode || + (avoidmode == avoidright && racesteer > avoidsteer) || + (avoidmode == avoidleft && racesteer < avoidsteer))) + { + // we're avoiding, but trying to steer somewhere the raceline takes us. + // hence we'll just correct towards the raceline instead. + allowcorrecting = 1; + } - bool yr_ok = (fabs(car->_yaw_rate) < 0.1 || (car->_yaw_rate > rldata->rInverse*100-0.1 && car->_yaw_rate < rldata->rInverse*100+0.1)); - bool angle_ok = (angle > rldata->rlangle-0.06 && angle < rldata->rlangle+0.06); - //double rlsteer = (fabs(rldata->rInverse) >= 0.004 ? rldata->rInverse * 12 : 0.0); - bool steer_ok = (racesteerlaststeer-0.05); + bool yr_ok = (fabs(car->_yaw_rate) < 0.1 || (car->_yaw_rate > rldata->rInverse*100-0.1 && car->_yaw_rate < rldata->rInverse*100+0.1)); + bool angle_ok = (angle > rldata->rlangle-0.06 && angle < rldata->rlangle+0.06); + //double rlsteer = (fabs(rldata->rInverse) >= 0.004 ? rldata->rInverse * 12 : 0.0); + bool steer_ok = (racesteerlaststeer-0.05); - double skid = (car->_skid[0] + car->_skid[1] + car->_skid[2] + car->_skid[3]) / 2; - if (mode == mode_correcting) - { - if (lastmode == mode_normal || - (angle_ok && - (simtime > 15.0 || car->_speed_x > 20) && - yr_ok && - skid < 0.1 && - steer_ok && - ((fabs(car->_trkPos.toMiddle) < car->_trkPos.seg->width/2 - 1.0) || car->_speed_x < 10.0) && - (raceline->isOnLine()))) - { - // we're correcting & are now close enough to the raceline to - // switch back to 'normal' mode... - setMode( mode_normal ); - aligned_timer = simtime; - steer = racesteer; - if (DebugMsg & debug_steer) - fprintf(stderr,"ALIGNED steer_ok=%d avsteer=%.3f racest=%.3f\n",steer_ok,avoidsteer,racesteer); - } - else if (DebugMsg & debug_steer) - fprintf(stderr,"NOT ALIGNED %d %d %d %d %.2f %.2f %.2f\n",angle_ok,yr_ok,(skid<0.1),steer_ok,avoidsteer,racesteer,laststeer); - } + double skid = (car->_skid[0] + car->_skid[1] + car->_skid[2] + car->_skid[3]) / 2; + if (mode == mode_correcting) + { + if (lastmode == mode_normal || + (angle_ok && + (simtime > 15.0 || car->_speed_x > 20) && + yr_ok && + skid < 0.1 && + steer_ok && + ((fabs(car->_trkPos.toMiddle) < car->_trkPos.seg->width/2 - 1.0) || car->_speed_x < 10.0) && + (raceline->isOnLine()))) + { + // we're correcting & are now close enough to the raceline to + // switch back to 'normal' mode... + setMode( mode_normal ); + aligned_timer = simtime; + steer = racesteer; + if (DebugMsg & debug_steer) + fprintf(stderr,"ALIGNED steer_ok=%d avsteer=%.3f racest=%.3f\n",steer_ok,avoidsteer,racesteer); + } + else if (DebugMsg & debug_steer) + fprintf(stderr,"NOT ALIGNED %d %d %d %d %.2f %.2f %.2f\n",angle_ok,yr_ok,(skid<0.1),steer_ok,avoidsteer,racesteer,laststeer); + } - if (mode != mode_normal) - { - if (mode != mode_correcting && !allowcorrecting) - { - int flying = checkFlying(); - if (flying & FLYING_FRONT) - { - steer = 0.0; - } - else if (flying & FLYING_BACK) - { - steer /= 3.0; - } - else - { - //correctlimit = 1000.0; - correcttimer = simtime + 7.0; - steer = ( avoidsteer ); - } - double climit = (steer - racesteer); - if (fabs(climit) > fabs(correctlimit)) - correctlimit = climit; - } - else - { - steer = (correctSteering( avoidsteer, racesteer )); - correctlimit = (steer - racesteer); - } - - if (fabs(angle) >= 1.6) - { - if (steer > 0.0) - steer = 1.0; - else - steer = -1.0; - } - } - else - correctlimit = (steer - racesteer); - } - else - { - raceline->NoAvoidSteer(); - lastNSasteer = rldata->NSsteer; - correctlimit = (steer - racesteer); - } + if (mode != mode_normal) + { + if (mode != mode_correcting && !allowcorrecting) + { + int flying = checkFlying(); + if (flying & FLYING_FRONT) + { + steer = 0.0; + } + else if (flying & FLYING_BACK) + { + steer /= 3.0; + } + else + { + //correctlimit = 1000.0; + correcttimer = simtime + 7.0; + steer = ( avoidsteer ); + } + double climit = (steer - racesteer); + if (fabs(climit) > fabs(correctlimit)) + correctlimit = climit; + } + else + { + steer = (correctSteering( avoidsteer, racesteer )); + correctlimit = (steer - racesteer); + } + + if (fabs(angle) >= 1.6) + { + if (steer > 0.0) + steer = 1.0; + else + steer = -1.0; + } + } + else + correctlimit = (steer - racesteer); + } + else + { + raceline->NoAvoidSteer(); + lastNSasteer = rldata->NSsteer; + correctlimit = (steer - racesteer); + } - if (mode == mode_avoiding && - (lastmode == mode_normal || lastmode == mode_correcting) && - !((avoidmode & avoidright) && (avoidmode & avoidleft))) - { - // if we're only avoiding on one side, and racesteer avoids more than avoidsteer, and just prior we - // weren't avoiding, return to prior mode. - if ((racesteer >= steer && avoidmode == avoidright) || - (racesteer <= steer && avoidmode == avoidleft)) - { - if (lastmode == mode_normal) - steer = racesteer; - setMode(lastmode); - } - } + if (mode == mode_avoiding && + (lastmode == mode_normal || lastmode == mode_correcting) && + !((avoidmode & avoidright) && (avoidmode & avoidleft))) + { + // if we're only avoiding on one side, and racesteer avoids more than avoidsteer, and just prior we + // weren't avoiding, return to prior mode. + if ((racesteer >= steer && avoidmode == avoidright) || + (racesteer <= steer && avoidmode == avoidleft)) + { + if (lastmode == mode_normal) + steer = racesteer; + setMode(lastmode); + } + } - return steer; + return steer; } double Driver::calcSteer( double targetAngle, int rl ) { #if 1 - if (mode != mode_pitting) - { - float kksteer = raceline->getAvoidSteer(myoffset, rldata); - return kksteer; - } + if (mode != mode_pitting) + { + float kksteer = raceline->getAvoidSteer(myoffset, rldata); + return kksteer; + } #endif - double rearskid = MAX(0.0, MAX(car->_skid[2], car->_skid[3]) - MAX(car->_skid[0], car->_skid[1])) + MAX(car->_skid[2], car->_skid[3]) * fabs(angle)*0.9; - double steer = 0.0; + double rearskid = MAX(0.0, MAX(car->_skid[2], car->_skid[3]) - MAX(car->_skid[0], car->_skid[1])) + MAX(car->_skid[2], car->_skid[3]) * fabs(angle)*0.9; + double steer = 0.0; #if 0 // olethros steering - double steer_direction = targetAngle - car->_yaw - 0.1 * car->_yaw_rate; + double steer_direction = targetAngle - car->_yaw - 0.1 * car->_yaw_rate; - double avoidance = 0.0; - if (!(pit->getInPit())) - { - if (car->_trkPos.toRight < car->_dimension_y) - avoidance = tanh(0.2 * (car->_dimension_y - car->_trkPos.toRight)); - else if (car->_trkPos.toLeft < car->_dimension_y) - avoidance = tanh(0.2 * (car->_trkPos.toLeft - car->_dimension_y)); - } + double avoidance = 0.0; + if (!(pit->getInPit())) + { + if (car->_trkPos.toRight < car->_dimension_y) + avoidance = tanh(0.2 * (car->_dimension_y - car->_trkPos.toRight)); + else if (car->_trkPos.toLeft < car->_dimension_y) + avoidance = tanh(0.2 * (car->_trkPos.toLeft - car->_dimension_y)); + } - tTrackSeg *seg = car->_trkPos.seg; - double correct_drift = -0.01 * atan2(car->_speed_Y, car->_speed_X); - NORM_PI_PI(steer_direction); + tTrackSeg *seg = car->_trkPos.seg; + double correct_drift = -0.01 * atan2(car->_speed_Y, car->_speed_X); + NORM_PI_PI(steer_direction); - steer = avoidance + correct_drift + steer_direction/car->_steerLock; + steer = avoidance + correct_drift + steer_direction/car->_steerLock; #else // old ki steering - double steer_direction = targetAngle - car->_yaw - car->_speed_x/300 * car->_yaw_rate; + double steer_direction = targetAngle - car->_yaw - car->_speed_x/300 * car->_yaw_rate; - NORM_PI_PI(steer_direction); - if (DebugMsg & debug_steer) - fprintf(stderr,"STEER tm%.2f off%.2f sd%.3f",car->_trkPos.toMiddle,myoffset,steer_direction); + NORM_PI_PI(steer_direction); + if (DebugMsg & debug_steer) + fprintf(stderr,"STEER tm%.2f off%.2f sd%.3f",car->_trkPos.toMiddle,myoffset,steer_direction); - if (car->_speed_x > 10.0 && mode != mode_normal && mode != mode_pitting) - { - double limit = MAX(20.0, 90.0 - car->_speed_x) * (((avoidmode & avoidside) ? 0.0074 : 0.0045) * SmoothSteer); - double rgtlimit = limit, lftlimit = limit; - if (laststeer_direction > 0.0) rgtlimit = MIN(laststeer_direction, rgtlimit*2); - if (laststeer_direction < 0.0) lftlimit = MIN(-laststeer_direction, lftlimit*2); + if (car->_speed_x > 10.0 && mode != mode_normal && mode != mode_pitting) + { + double limit = MAX(20.0, 90.0 - car->_speed_x) * (((avoidmode & avoidside) ? 0.0074 : 0.0045) * SmoothSteer); + double rgtlimit = limit, lftlimit = limit; + if (laststeer_direction > 0.0) rgtlimit = MIN(laststeer_direction, rgtlimit*2); + if (laststeer_direction < 0.0) lftlimit = MIN(-laststeer_direction, lftlimit*2); - steer_direction = MAX(laststeer_direction - rgtlimit, MIN(laststeer_direction + lftlimit, steer_direction)); + steer_direction = MAX(laststeer_direction - rgtlimit, MIN(laststeer_direction + lftlimit, steer_direction)); #if 1 - double speedsteer = (80.0 - MIN(70.0, MAX(40.0, currentspeed))) / - ((185.0 * MIN(1.0, car->_steerLock / 0.785)) + - (185.0 * (MIN(1.3, MAX(1.0, 1.0 + rearskid))) - 185.0)); - if (fabs(steer_direction) > speedsteer) - { - steer_direction = MAX(-speedsteer, MIN(speedsteer, steer_direction)); - } + double speedsteer = (80.0 - MIN(70.0, MAX(40.0, currentspeed))) / + ((185.0 * MIN(1.0, car->_steerLock / 0.785)) + + (185.0 * (MIN(1.3, MAX(1.0, 1.0 + rearskid))) - 185.0)); + if (fabs(steer_direction) > speedsteer) + { + steer_direction = MAX(-speedsteer, MIN(speedsteer, steer_direction)); + } #endif - } - laststeer_direction = steer_direction; + } + laststeer_direction = steer_direction; - steer = (steer_direction/car->_steerLock); - if (DebugMsg & debug_steer) - fprintf(stderr,"/sd%.3f a%.3f",steer_direction,steer); + steer = (steer_direction/car->_steerLock); + if (DebugMsg & debug_steer) + fprintf(stderr,"/sd%.3f a%.3f",steer_direction,steer); - if (DebugMsg & debug_steer) - fprintf(stderr," b%.3f",steer); + if (DebugMsg & debug_steer) + fprintf(stderr," b%.3f",steer); - lastNSasteer = steer; + lastNSasteer = steer; - double nextangle = angle + car->_yaw_rate/3; - if (fabs(nextangle) > fabs(speedangle)) - { - // steer into the skid - //double sa = MAX(-0.3, MIN(0.3, speedangle/3)); - //double anglediff = (sa - angle) * (0.3 + fabs(angle)/6); - double anglediff = (speedangle - nextangle) * (0.1 + fabs(nextangle)/6); - steer += (float) (anglediff*SkidSteer); - } + double nextangle = angle + car->_yaw_rate/3; + if (fabs(nextangle) > fabs(speedangle)) + { + // steer into the skid + //double sa = MAX(-0.3, MIN(0.3, speedangle/3)); + //double anglediff = (sa - angle) * (0.3 + fabs(angle)/6); + double anglediff = (speedangle - nextangle) * (0.1 + fabs(nextangle)/6); + steer += (float) (anglediff*SkidSteer); + } - if (fabs(angle) > 1.2) - { - if (steer > 0.0f) - steer = 1.0f; - else - steer = -1.0f; - } - else if (fabs(car->_trkPos.toMiddle) - car->_trkPos.seg->width/2 > 2.0) - { - steer = (float) MIN(1.0f, MAX(-1.0f, steer * (1.0f + (fabs(car->_trkPos.toMiddle) - car->_trkPos.seg->width/2)/14 + fabs(angle)/2))); - } + if (fabs(angle) > 1.2) + { + if (steer > 0.0f) + steer = 1.0f; + else + steer = -1.0f; + } + else if (fabs(car->_trkPos.toMiddle) - car->_trkPos.seg->width/2 > 2.0) + { + steer = (float) MIN(1.0f, MAX(-1.0f, steer * (1.0f + (fabs(car->_trkPos.toMiddle) - car->_trkPos.seg->width/2)/14 + fabs(angle)/2))); + } #endif // old ki steering - if (DebugMsg & debug_steer) - fprintf(stderr," d%.3f",steer); + if (DebugMsg & debug_steer) + fprintf(stderr," d%.3f",steer); - if (mode != mode_pitting) - { - // limit how far we can steer against last steer... - double limit = 0.0; - limit = ((90.0 - MAX(40.0, MIN(60.0, car->_speed_x))) / (120)) * SmoothSteer; // (130); - if (fabs(laststeer) > fabs(steer)) - limit = MAX(limit, fabs(laststeer)/2); - steer = MAX(laststeer-limit, MIN(laststeer+limit, steer)); - //steer = MAX(rldata->steer-limit, MIN(rldata->steer+limit, steer)); + if (mode != mode_pitting) + { + // limit how far we can steer against last steer... + double limit = 0.0; + limit = ((90.0 - MAX(40.0, MIN(60.0, car->_speed_x))) / (120)) * SmoothSteer; // (130); + if (fabs(laststeer) > fabs(steer)) + limit = MAX(limit, fabs(laststeer)/2); + steer = MAX(laststeer-limit, MIN(laststeer+limit, steer)); + //steer = MAX(rldata->steer-limit, MIN(rldata->steer+limit, steer)); #if 1 - if (simtime > 3.0) - { - // and against raceline... - double climit = fabs(correctlimit); + if (simtime > 3.0) + { + // and against raceline... + double climit = fabs(correctlimit); #if 0 - if (climit > 0.0 && angle - rldata->rlangle > 0.0) - climit += (angle - rldata->rlangle)/2; - else if (climit < 0.0 && angle - rldata->rlangle < 0.0) - climit -= fabs(angle - rldata->rlangle)/2; + if (climit > 0.0 && angle - rldata->rlangle > 0.0) + climit += (angle - rldata->rlangle)/2; + else if (climit < 0.0 && angle - rldata->rlangle < 0.0) + climit -= fabs(angle - rldata->rlangle)/2; #endif - double limitchange = ((90.0 - MAX(40.0, MIN(60.0, car->_speed_x))) / ((avoidmode & avoidside) ? 130 : 200)) * 3; - climit += limitchange; - steer = MAX(rldata->ksteer-climit, MIN(rldata->ksteer+climit, steer)); - } + double limitchange = ((90.0 - MAX(40.0, MIN(60.0, car->_speed_x))) / ((avoidmode & avoidside) ? 130 : 200)) * 3; + climit += limitchange; + steer = MAX(rldata->ksteer-climit, MIN(rldata->ksteer+climit, steer)); + } #endif - steer = smoothSteering(steer); - } + steer = smoothSteering(steer); + } #if 0 - else if (currentspeed > MAX(25.0, pit->getSpeedlimit())) - { - // stop sudden steer changes while pitting - double limit = MAX(0.1, (40 - fabs(currentspeed - pit->getSpeedlimit())) * 0.025); - steer = MIN(limit, MAX(-limit, steer)); - } + else if (currentspeed > MAX(25.0, pit->getSpeedlimit())) + { + // stop sudden steer changes while pitting + double limit = MAX(0.1, (40 - fabs(currentspeed - pit->getSpeedlimit())) * 0.025); + steer = MIN(limit, MAX(-limit, steer)); + } #endif - if (DebugMsg & debug_steer) - fprintf(stderr," e%.3f\n",steer); + if (DebugMsg & debug_steer) + fprintf(stderr," e%.3f\n",steer); - return steer; + return steer; } int Driver::checkFlying() @@ -1641,1806 +1637,1806 @@ int Driver::checkFlying() float Driver::correctSteering( float avoidsteer, float racesteer ) { - if (simtime < 15.0 && car->_speed_x < 20.0) - return avoidsteer; - if (simtime < CorrectDelay) - return avoidsteer; + if (simtime < 15.0 && car->_speed_x < 20.0) + return avoidsteer; + if (simtime < CorrectDelay) + return avoidsteer; - float steer = avoidsteer; - //float accel = MIN(0.0f, car->_accel_x); - double speed = 50.0; //MAX(50.0, currentspeed); - double changelimit = MIN(raceline->correctLimit(avoidsteer, racesteer), (((120.0-currentspeed)/6000) * (0.1 + fabs(rldata->mInverse/4)))) * SmoothSteer; + float steer = avoidsteer; + //float accel = MIN(0.0f, car->_accel_x); + double speed = 50.0; //MAX(50.0, currentspeed); + double changelimit = MIN(raceline->correctLimit(avoidsteer, racesteer), (((120.0-currentspeed)/6000) * (0.1 + fabs(rldata->mInverse/4)))) * SmoothSteer; if (DebugMsg & debug_steer) fprintf(stderr,"CORRECT: cl=%.3f as=%.3f rs=%.3f NS=%.3f",correctlimit,avoidsteer,racesteer,lastNSasteer); - if (/*mode == mode_correcting &&*/ simtime > 2.0f) - { - // move steering towards racesteer... - if (correctlimit < 900.0) - { - if (steer < racesteer) - { - if (correctlimit >= 0.0) - { - //steer = (float) MIN(racesteer, steer + correctlimit); + if (/*mode == mode_correcting &&*/ simtime > 2.0f) + { + // move steering towards racesteer... + if (correctlimit < 900.0) + { + if (steer < racesteer) + { + if (correctlimit >= 0.0) + { + //steer = (float) MIN(racesteer, steer + correctlimit); if (DebugMsg & debug_steer) fprintf(stderr," RA%.3f",racesteer); - steer = racesteer; - lastNSasteer = rldata->NSsteer; - } - else - { - steer = (float) MIN(racesteer, MAX(steer, racesteer + correctlimit)); - lastNSasteer = (float) MIN(rldata->NSsteer, MAX(lastNSasteer, rldata->NSsteer + correctlimit)); + steer = racesteer; + lastNSasteer = rldata->NSsteer; + } + else + { + steer = (float) MIN(racesteer, MAX(steer, racesteer + correctlimit)); + lastNSasteer = (float) MIN(rldata->NSsteer, MAX(lastNSasteer, rldata->NSsteer + correctlimit)); if (DebugMsg & debug_steer) fprintf(stderr," MA%.3f",steer); - } - } - else - { - if (correctlimit <= 0.0) - { - //steer = (float) MAX(racesteer, steer-correctlimit); - steer = racesteer; - lastNSasteer = rldata->NSsteer; + } + } + else + { + if (correctlimit <= 0.0) + { + //steer = (float) MAX(racesteer, steer-correctlimit); + steer = racesteer; + lastNSasteer = rldata->NSsteer; if (DebugMsg & debug_steer) fprintf(stderr," RB%.3f",racesteer); - } - else - { - steer = (float) MAX(racesteer, MIN(steer, racesteer + correctlimit)); - lastNSasteer = (float) MAX(rldata->NSsteer, MIN(lastNSasteer, rldata->NSsteer + correctlimit)); + } + else + { + steer = (float) MAX(racesteer, MIN(steer, racesteer + correctlimit)); + lastNSasteer = (float) MAX(rldata->NSsteer, MIN(lastNSasteer, rldata->NSsteer + correctlimit)); if (DebugMsg & debug_steer) fprintf(stderr," MB%.3f",steer); - } - } - } - //else - { - speed -= avgaccel_x/10; - speed = MAX(55.0, MIN(150.0, speed + (speed*speed/55))); - double rInverse = rldata->mInverse * (avgaccel_x<0.0 ? 1.0 + fabs(avgaccel_x)/10.0 : 1.0); - double correctspeed = 0.5; - if ((rInverse > 0.0 && racesteer > steer) || (rInverse < 0.0 && racesteer < steer)) - correctspeed += rInverse*110; + } + } + } + //else + { + speed -= avgaccel_x/10; + speed = MAX(55.0, MIN(150.0, speed + (speed*speed/55))); + double rInverse = rldata->mInverse * (avgaccel_x<0.0 ? 1.0 + fabs(avgaccel_x)/10.0 : 1.0); + double correctspeed = 0.5; + if ((rInverse > 0.0 && racesteer > steer) || (rInverse < 0.0 && racesteer < steer)) + correctspeed += rInverse*110; - if (racesteer > steer) - //steer = (float) MIN(racesteer, steer + (((155.0-speed)/10000) * correctspeed)); - steer = (float) MIN(racesteer, steer + changelimit); - else - //steer = (float) MAX(racesteer, steer - (((155.0-speed)/10000) * correctspeed)); - steer = (float) MAX(racesteer, steer - changelimit); - if (fabs(racesteer) < fabs(steer)) - { - if (racesteer > steer) - steer += (fabs(steer) - fabs(racesteer)) / 2; - else - steer -= (fabs(steer) - fabs(racesteer)) / 2; - } + if (racesteer > steer) + //steer = (float) MIN(racesteer, steer + (((155.0-speed)/10000) * correctspeed)); + steer = (float) MIN(racesteer, steer + changelimit); + else + //steer = (float) MAX(racesteer, steer - (((155.0-speed)/10000) * correctspeed)); + steer = (float) MAX(racesteer, steer - changelimit); + if (fabs(racesteer) < fabs(steer)) + { + if (racesteer > steer) + steer += (fabs(steer) - fabs(racesteer)) / 2; + else + steer -= (fabs(steer) - fabs(racesteer)) / 2; + } - if (lastNSksteer > lastNSasteer) - //lastNSasteer = (float) MIN(rldata->NSsteer, lastNSasteer + (((155.0-speed)/10000) * correctspeed)); - lastNSasteer = (float) MIN(rldata->NSsteer, lastNSasteer + changelimit); - else - //lastNSasteer = (float) MAX(rldata->NSsteer, lastNSasteer - (((155.0-speed)/10000) * correctspeed)); - lastNSasteer = (float) MAX(rldata->NSsteer, lastNSasteer - changelimit); + if (lastNSksteer > lastNSasteer) + //lastNSasteer = (float) MIN(rldata->NSsteer, lastNSasteer + (((155.0-speed)/10000) * correctspeed)); + lastNSasteer = (float) MIN(rldata->NSsteer, lastNSasteer + changelimit); + else + //lastNSasteer = (float) MAX(rldata->NSsteer, lastNSasteer - (((155.0-speed)/10000) * correctspeed)); + lastNSasteer = (float) MAX(rldata->NSsteer, lastNSasteer - changelimit); if (DebugMsg & debug_steer) fprintf(stderr," I%.3f",steer); - } - - } + } + + } if (DebugMsg & debug_steer) fprintf(stderr," %.3f NS=%.3f\n",steer,lastNSasteer); - return steer; + return steer; } float Driver::smoothSteering( float steercmd ) { - if (pitoffset != -100.0f) - return steercmd; + if (pitoffset != -100.0f) + return steercmd; #if 1 - // experimental smoothing code, beware!!! - double steer = steercmd; - double stdelta = steer - laststeer;//car->_steerCmd; - double maxSpeed = MAX(200.0, 300.0 - car->_speed_x*2) * (PI/180.0); + // experimental smoothing code, beware!!! + double steer = steercmd; + double stdelta = steer - laststeer;//car->_steerCmd; + double maxSpeed = MAX(200.0, 300.0 - car->_speed_x*2) * (PI/180.0); - //if (mode == mode_normal) - // maxSpeed = 200.0 * (PI / 180.0); + //if (mode == mode_normal) + // maxSpeed = 200.0 * (PI / 180.0); - if ((fabs(stdelta) / deltaTime) > maxSpeed) - steer = SIGN(stdelta) * maxSpeed * deltaTime + laststeer;//car->_steerCmd; + if ((fabs(stdelta) / deltaTime) > maxSpeed) + steer = SIGN(stdelta) * maxSpeed * deltaTime + laststeer;//car->_steerCmd; - steercmd = steer; + steercmd = steer; - // limit amount of steer according to speed & raceline - double a_error_factor = ((rldata->exiting && rldata->outsideline) ? 0.9 : 0.8); - double smangle = angle * (0.5 + fabs(angle*2)); - double angle_error = (smangle - rldata->rlangle/2) * a_error_factor; - double lstlimit = MAX(40.0, 80.0 - car->_speed_x) * 0.004 - MIN(0.0, MAX(-0.5, angle_error)); - double rstlimit = -(MAX(40.0, 80.0 - car->_speed_x) * 0.004 + MAX(0.0, MIN(0.5, angle_error))); - double strate = 61.0 + lastaccel*10; + // limit amount of steer according to speed & raceline + double a_error_factor = ((rldata->exiting && rldata->outsideline) ? 0.9 : 0.8); + double smangle = angle * (0.5 + fabs(angle*2)); + double angle_error = (smangle - rldata->rlangle/2) * a_error_factor; + double lstlimit = MAX(40.0, 80.0 - car->_speed_x) * 0.004 - MIN(0.0, MAX(-0.5, angle_error)); + double rstlimit = -(MAX(40.0, 80.0 - car->_speed_x) * 0.004 + MAX(0.0, MIN(0.5, angle_error))); + double strate = 61.0 + lastaccel*10; - if (rldata->rInverse*strate > lstlimit) - lstlimit = rldata->rInverse*strate; - if (rldata->rInverse*strate < rstlimit) - rstlimit = rldata->rInverse*strate; - steercmd = MAX(rstlimit, MIN(lstlimit, steercmd)); + if (rldata->rInverse*strate > lstlimit) + lstlimit = rldata->rInverse*strate; + if (rldata->rInverse*strate < rstlimit) + rstlimit = rldata->rInverse*strate; + steercmd = MAX(rstlimit, MIN(lstlimit, steercmd)); #endif - return steercmd; + return steercmd; #if 0 - // try to limit sudden changes in steering to avoid loss of control through oversteer. - double lftspeedfactor = ((((60.0 - (MAX(40.0, MIN(70.0, currentspeed + MAX(0.0, car->_accel_x*5))) - 25)) / 300) * 2.5) / 0.585) * SmoothSteer; - double rgtspeedfactor = lftspeedfactor; + // try to limit sudden changes in steering to avoid loss of control through oversteer. + double lftspeedfactor = ((((60.0 - (MAX(40.0, MIN(70.0, currentspeed + MAX(0.0, car->_accel_x*5))) - 25)) / 300) * 2.5) / 0.585) * SmoothSteer; + double rgtspeedfactor = lftspeedfactor; - if (fabs(steercmd) < fabs(laststeer) && fabs(steercmd) <= fabs(laststeer - steercmd)) - { - lftspeedfactor *= 2; - rgtspeedfactor *= 2; - } + if (fabs(steercmd) < fabs(laststeer) && fabs(steercmd) <= fabs(laststeer - steercmd)) + { + lftspeedfactor *= 2; + rgtspeedfactor *= 2; + } - lftspeedfactor -= MIN(0.0f, car->_yaw_rate/10); - rgtspeedfactor += MAX(0.0f, car->_yaw_rate/10); + lftspeedfactor -= MIN(0.0f, car->_yaw_rate/10); + rgtspeedfactor += MAX(0.0f, car->_yaw_rate/10); - steercmd = (float) MAX(laststeer - rgtspeedfactor, MIN(laststeer + lftspeedfactor, steercmd)); - return steercmd; + steercmd = (float) MAX(laststeer - rgtspeedfactor, MIN(laststeer + lftspeedfactor, steercmd)); + return steercmd; #endif } // Compute the clutch value. float Driver::getClutch() { - if (1 || car->_gearCmd > 1) - { - float maxtime = MAX(0.06f, 0.32f - ((float) car->_gearCmd / 65.0f)); - if (car->_gear != car->_gearCmd && car->_gearCmd < MaxGear) - clutchtime = maxtime; - if (clutchtime > 0.0f) - clutchtime -= (float) (RCM_MAX_DT_ROBOTS * (0.02f + ((float) car->_gearCmd / 8.0f))); - return 2.0f * clutchtime; - } else { - float drpm = car->_enginerpm - car->_enginerpmRedLine/2.0f; - float ctlimit = 0.9f; - if (car->_gearCmd > 1) - ctlimit -= 0.15f + (float) car->_gearCmd/13.0f; - clutchtime = MIN(ctlimit, clutchtime); - if (car->_gear != car->_gearCmd) - clutchtime = 0.0f; - float clutcht = (ctlimit - clutchtime) / ctlimit; - if (car->_gear == 1 && car->_accelCmd > 0.0f) { - clutchtime += (float) RCM_MAX_DT_ROBOTS; - } + if (1 || car->_gearCmd > 1) + { + float maxtime = MAX(0.06f, 0.32f - ((float) car->_gearCmd / 65.0f)); + if (car->_gear != car->_gearCmd && car->_gearCmd < MaxGear) + clutchtime = maxtime; + if (clutchtime > 0.0f) + clutchtime -= (float) (RCM_MAX_DT_ROBOTS * (0.02f + ((float) car->_gearCmd / 8.0f))); + return 2.0f * clutchtime; + } else { + float drpm = car->_enginerpm - car->_enginerpmRedLine/2.0f; + float ctlimit = 0.9f; + if (car->_gearCmd > 1) + ctlimit -= 0.15f + (float) car->_gearCmd/13.0f; + clutchtime = MIN(ctlimit, clutchtime); + if (car->_gear != car->_gearCmd) + clutchtime = 0.0f; + float clutcht = (ctlimit - clutchtime) / ctlimit; + if (car->_gear == 1 && car->_accelCmd > 0.0f) { + clutchtime += (float) RCM_MAX_DT_ROBOTS; + } - if (car->_gearCmd == 1 || drpm > 0) { - float speedr; - if (car->_gearCmd == 1) { - // Compute corresponding speed to engine rpm. - float omega = car->_enginerpmRedLine/car->_gearRatio[car->_gear + car->_gearOffset]; - float wr = car->_wheelRadius(2); - speedr = (CLUTCH_SPEED + MAX(0.0f, car->_speed_x))/fabs(wr*omega); - float clutchr = MAX(0.0f, (1.0f - speedr*2.0f*drpm/car->_enginerpmRedLine)) * (car->_gearCmd == 1 ? 0.95f : (0.7f - (float)(car->_gearCmd)/30.0f)); - return MIN(clutcht, clutchr); - } else { - // For the reverse gear. - clutchtime = 0.0f; - return 0.0f; - } - } else { - return clutcht; - } - } + if (car->_gearCmd == 1 || drpm > 0) { + float speedr; + if (car->_gearCmd == 1) { + // Compute corresponding speed to engine rpm. + float omega = car->_enginerpmRedLine/car->_gearRatio[car->_gear + car->_gearOffset]; + float wr = car->_wheelRadius(2); + speedr = (CLUTCH_SPEED + MAX(0.0f, car->_speed_x))/fabs(wr*omega); + float clutchr = MAX(0.0f, (1.0f - speedr*2.0f*drpm/car->_enginerpmRedLine)) * (car->_gearCmd == 1 ? 0.95f : (0.7f - (float)(car->_gearCmd)/30.0f)); + return MIN(clutcht, clutchr); + } else { + // For the reverse gear. + clutchtime = 0.0f; + return 0.0f; + } + } else { + return clutcht; + } + } } // move offset to allow for bends (if any) float Driver::adjustOffset(float offset) { return offset; - float adjustment = (float) (rldata->rInverse * 10); - float width = (float) (car->_trkPos.seg->width * 0.75); + float adjustment = (float) (rldata->rInverse * 10); + float width = (float) (car->_trkPos.seg->width * 0.75); #if 0 #endif - //if (mode==mode_avoiding) - { - // we want to adjust outwards a bit if in close to the corner (more if avoiding - // a car on the inside, way less otherwise). If the car is on the outside third - // of the track we don't want to adjust at all. Inbetween the inside third and - // the outside third we want a gradual decline in the adjust amount... - if (adjustment < 0.0) - { - if (car->_trkPos.toRight > width*0.7) - adjustment = 0.0; - else if (car->_trkPos.toRight > width*0.3) - adjustment *= MAX(0.0, 1.0 - ((car->_trkPos.toRight-width*0.3)/width*0.4)); - } - else if (adjustment > 0.0) - { - if (car->_trkPos.toLeft > width*0.7) - adjustment = 0.0; - else if (car->_trkPos.toLeft > width*0.3) - adjustment *= MAX(0.0, 1.0 - ((car->_trkPos.toLeft-width*0.3)/width*0.4)); - } + //if (mode==mode_avoiding) + { + // we want to adjust outwards a bit if in close to the corner (more if avoiding + // a car on the inside, way less otherwise). If the car is on the outside third + // of the track we don't want to adjust at all. Inbetween the inside third and + // the outside third we want a gradual decline in the adjust amount... + if (adjustment < 0.0) + { + if (car->_trkPos.toRight > width*0.7) + adjustment = 0.0; + else if (car->_trkPos.toRight > width*0.3) + adjustment *= MAX(0.0, 1.0 - ((car->_trkPos.toRight-width*0.3)/width*0.4)); + } + else if (adjustment > 0.0) + { + if (car->_trkPos.toLeft > width*0.7) + adjustment = 0.0; + else if (car->_trkPos.toLeft > width*0.3) + adjustment *= MAX(0.0, 1.0 - ((car->_trkPos.toLeft-width*0.3)/width*0.4)); + } #if 0 - if (adjustment < 0.0 && car->_trkPos.toLeft < width) - adjustment *= MAX(0.1, MIN(1.0, car->_trkPos.toLeft*1.6 / width)); - else if (adjustment > 0.0 && car->_trkPos.toRight < width) - adjustment *= MAX(0.1, MIN(1.0, car->_trkPos.toRight*1.6 / width)); + if (adjustment < 0.0 && car->_trkPos.toLeft < width) + adjustment *= MAX(0.1, MIN(1.0, car->_trkPos.toLeft*1.6 / width)); + else if (adjustment > 0.0 && car->_trkPos.toRight < width) + adjustment *= MAX(0.1, MIN(1.0, car->_trkPos.toRight*1.6 / width)); #endif - //adjustment *= 1.0 + MAX(0.0, currentspeed / rldata->avspeed)*2; - if ((avoidmode == avoidright && adjustment < 0.0) || - (avoidmode == avoidleft && adjustment > 0.0)) - adjustment *= 1; - else - adjustment /= 2; - } + //adjustment *= 1.0 + MAX(0.0, currentspeed / rldata->avspeed)*2; + if ((avoidmode == avoidright && adjustment < 0.0) || + (avoidmode == avoidleft && adjustment > 0.0)) + adjustment *= 1; + else + adjustment /= 2; + } - double speed = currentspeed; - double xspeed = MIN(rldata->speed, rldata->avspeed); - if (speed < xspeed) - adjustment *= MIN(2.0, xspeed / speed); + double speed = currentspeed; + double xspeed = MIN(rldata->speed, rldata->avspeed); + if (speed < xspeed) + adjustment *= MIN(2.0, xspeed / speed); - offset -= adjustment; + offset -= adjustment; - return offset; + return offset; } // Compute target point for steering. vec2f Driver::getTargetPoint(bool use_lookahead, double targetoffset) { - tTrackSeg *seg = car->_trkPos.seg; - float length = getDistToSegEnd(); - float offset = (targetoffset > -99 ? targetoffset - : (skipcount < 2 ? getOffset() : myoffset)); - double time_mod = 1.0; - pitoffset = -100.0f; + tTrackSeg *seg = car->_trkPos.seg; + float length = getDistToSegEnd(); + float offset = (targetoffset > -99 ? targetoffset + : (skipcount < 2 ? getOffset() : myoffset)); + double time_mod = 1.0; + pitoffset = -100.0f; - if (pit->getInPit()) { - // To stop in the pit we need special lookahead values. - if (currentspeedsqr > pit->getSpeedlimitSqr()) { - lookahead = PIT_LOOKAHEAD + car->_speed_x*LOOKAHEAD_FACTOR; - } else { - lookahead = PIT_LOOKAHEAD; - } - } else { - // Usual lookahead. - lookahead = (float) rldata->lookahead; + if (pit->getInPit()) { + // To stop in the pit we need special lookahead values. + if (currentspeedsqr > pit->getSpeedlimitSqr()) { + lookahead = PIT_LOOKAHEAD + car->_speed_x*LOOKAHEAD_FACTOR; + } else { + lookahead = PIT_LOOKAHEAD; + } + } else { + // Usual lookahead. + lookahead = (float) rldata->lookahead; - double speed = MAX(20.0, currentspeed);// + MAX(0.0, car->_accel_x)); - lookahead = (float) (LOOKAHEAD_CONST * 1.2 + speed * 0.75); - lookahead = MIN(lookahead, (float) (LOOKAHEAD_CONST + ((speed*(speed/7)) * 0.15))); - lookahead *= SteerLookahead; - double ri = (fabs(rldata->mInverse) < fabs(rldata->rInverse) ? rldata->mInverse : rldata->rInverse); - //double amI = MIN(0.05, MAX(-0.05, (rldata->amInverse))); - double amI = MIN(0.05, MAX(-0.05, (ri))); - double famI = fabs(amI); + double speed = MAX(20.0, currentspeed);// + MAX(0.0, car->_accel_x)); + lookahead = (float) (LOOKAHEAD_CONST * 1.2 + speed * 0.75); + lookahead = MIN(lookahead, (float) (LOOKAHEAD_CONST + ((speed*(speed/7)) * 0.15))); + lookahead *= SteerLookahead; + double ri = (fabs(rldata->mInverse) < fabs(rldata->rInverse) ? rldata->mInverse : rldata->rInverse); + //double amI = MIN(0.05, MAX(-0.05, (rldata->amInverse))); + double amI = MIN(0.05, MAX(-0.05, (ri))); + double famI = fabs(amI); - if (famI > 0.0) - { - double cornerfx = 1.0; - double toMid = car->_trkPos.toMiddle + speedangle * 20; - double modfactor = (currentspeed / rldata->avspeed); - modfactor *= modfactor; - if (amI > 0.0) - { - if (toMid < 0.0) - { - cornerfx += famI * (MIN(track->width/2, fabs(toMid)) / track->width) * 50; - time_mod += famI * (MIN(track->width/2, fabs(toMid)) / track->width) * 50; - } - else - { - cornerfx -= MIN(0.7, famI * (MIN(track->width/2, fabs(toMid)) / track->width) * 30); - time_mod -= MIN(0.7, famI * (MIN(track->width/2, fabs(toMid)) / track->width) * 30 * modfactor); - } - } - else - { - if (toMid > 0.0) - { - cornerfx += famI * (MIN(track->width/2, fabs(toMid)) / track->width) * 50; - time_mod += famI * (MIN(track->width/2, fabs(toMid)) / track->width) * 50; - } - else - { - cornerfx -= MIN(0.7, famI * (MIN(track->width/2, fabs(toMid)) / track->width) * 30); - time_mod -= MIN(0.7, famI * (MIN(track->width/2, fabs(toMid)) / track->width) * 30 * modfactor); - } - } - lookahead *= cornerfx; - } + if (famI > 0.0) + { + double cornerfx = 1.0; + double toMid = car->_trkPos.toMiddle + speedangle * 20; + double modfactor = (currentspeed / rldata->avspeed); + modfactor *= modfactor; + if (amI > 0.0) + { + if (toMid < 0.0) + { + cornerfx += famI * (MIN(track->width/2, fabs(toMid)) / track->width) * 50; + time_mod += famI * (MIN(track->width/2, fabs(toMid)) / track->width) * 50; + } + else + { + cornerfx -= MIN(0.7, famI * (MIN(track->width/2, fabs(toMid)) / track->width) * 30); + time_mod -= MIN(0.7, famI * (MIN(track->width/2, fabs(toMid)) / track->width) * 30 * modfactor); + } + } + else + { + if (toMid > 0.0) + { + cornerfx += famI * (MIN(track->width/2, fabs(toMid)) / track->width) * 50; + time_mod += famI * (MIN(track->width/2, fabs(toMid)) / track->width) * 50; + } + else + { + cornerfx -= MIN(0.7, famI * (MIN(track->width/2, fabs(toMid)) / track->width) * 30); + time_mod -= MIN(0.7, famI * (MIN(track->width/2, fabs(toMid)) / track->width) * 30 * modfactor); + } + } + lookahead *= cornerfx; + } - if (time_mod < oldtime_mod) - time_mod = MAX(time_mod, oldtime_mod - deltaTime*2); - oldtime_mod = time_mod; + if (time_mod < oldtime_mod) + time_mod = MAX(time_mod, oldtime_mod - deltaTime*2); + oldtime_mod = time_mod; #if 0 - if (fabs(rldata->rInverse) > 0.001) - { - // increase lookahead if on the outside of a corner - double cornerfx = 1.0; - double cornerlmt = MIN(track->width/2, 1.0 + fabs(rldata->rInverse)*500); - if (rldata->rInverse > 0.0 && car->_trkPos.toRight < cornerlmt) - cornerfx = 1.0 + MAX(0.0, (cornerlmt-car->_trkPos.toRight)/cornerlmt)*1.5; - else if (rldata->rInverse < 0.0 && car->_trkPos.toLeft < cornerlmt) - cornerfx = (1.0 - MAX(0.0, (cornerlmt-car->_trkPos.toLeft)/cornerlmt))*1.5; - lookahead *= cornerfx; - } + if (fabs(rldata->rInverse) > 0.001) + { + // increase lookahead if on the outside of a corner + double cornerfx = 1.0; + double cornerlmt = MIN(track->width/2, 1.0 + fabs(rldata->rInverse)*500); + if (rldata->rInverse > 0.0 && car->_trkPos.toRight < cornerlmt) + cornerfx = 1.0 + MAX(0.0, (cornerlmt-car->_trkPos.toRight)/cornerlmt)*1.5; + else if (rldata->rInverse < 0.0 && car->_trkPos.toLeft < cornerlmt) + cornerfx = (1.0 - MAX(0.0, (cornerlmt-car->_trkPos.toLeft)/cornerlmt))*1.5; + lookahead *= cornerfx; + } #endif #if 0 - lookahead = LOOKAHEAD_CONST + car->_speed_x*LOOKAHEAD_FACTOR; - lookahead = MAX(lookahead, LOOKAHEAD_CONST + ((car->_speed_x*(car->_speed_x/2)) / 60.0)); + lookahead = LOOKAHEAD_CONST + car->_speed_x*LOOKAHEAD_FACTOR; + lookahead = MAX(lookahead, LOOKAHEAD_CONST + ((car->_speed_x*(car->_speed_x/2)) / 60.0)); #endif #if 1 - lookahead *= LookAhead; + lookahead *= LookAhead; - // Prevent "snap back" of lookahead on harsh braking. - float cmplookahead = oldlookahead - (car->_speed_x*RCM_MAX_DT_ROBOTS)*0.65f;//0.55f; - if (lookahead < cmplookahead) { - lookahead = cmplookahead; - } + // Prevent "snap back" of lookahead on harsh braking. + float cmplookahead = oldlookahead - (car->_speed_x*RCM_MAX_DT_ROBOTS)*0.65f;//0.55f; + if (lookahead < cmplookahead) { + lookahead = cmplookahead; + } #endif - } + } - oldlookahead = lookahead; + oldlookahead = lookahead; - // Search for the segment containing the target point. - while (length < lookahead) { - seg = seg->next; - length += seg->length; - } + // Search for the segment containing the target point. + while (length < lookahead) { + seg = seg->next; + length += seg->length; + } - length = lookahead - length + seg->length; - float fromstart = seg->lgfromstart; - fromstart += length; + length = lookahead - length + seg->length; + float fromstart = seg->lgfromstart; + fromstart += length; - // Compute the target point. - pitoffset = pit->getPitOffset(pitoffset, fromstart, pitpos); - if ((pit->getPitstop() || pit->getInPit()) && pitoffset != -100.0f) - { - setMode(mode_pitting); - offset = myoffset = pitoffset; - } - else if (mode == mode_pitting) - { - setMode(mode_correcting); - } + // Compute the target point. + pitoffset = pit->getPitOffset(pitoffset, fromstart, pitpos); + if ((pit->getPitstop() || pit->getInPit()) && pitoffset != -100.0f) + { + setMode(mode_pitting); + offset = myoffset = pitoffset; + } + else if (mode == mode_pitting) + { + setMode(mode_correcting); + } - //if (mode == mode_correcting || mode == mode_avoiding) - // offset = adjustOffset( offset ); + //if (mode == mode_correcting || mode == mode_avoiding) + // offset = adjustOffset( offset ); - vec2f s; - //if (mode != mode_pitting) - { - //double steertime = SteerTime * time_mod * MAX(1.0, (1.0 - (car->_accel_x/70 * MAX(0.1, MIN(1.0, collision))))); - double steertime = MIN(MaxSteerTime, MinSteerTime + MAX(0.0, currentspeed-20.0)/30.0); - if (car->_speed_x > SteerCutoff) - time_mod *= SteerCutoff / currentspeed; - raceline->GetSteerPoint( lookahead, &s, offset, (use_lookahead ? -100.0 : steertime * time_mod) ); - return s; - } + vec2f s; + //if (mode != mode_pitting) + { + //double steertime = SteerTime * time_mod * MAX(1.0, (1.0 - (car->_accel_x/70 * MAX(0.1, MIN(1.0, collision))))); + double steertime = MIN(MaxSteerTime, MinSteerTime + MAX(0.0, currentspeed-20.0)/30.0); + if (car->_speed_x > SteerCutoff) + time_mod *= SteerCutoff / currentspeed; + raceline->GetSteerPoint( lookahead, &s, offset, (use_lookahead ? -100.0 : steertime * time_mod) ); + return s; + } - // all the BT code below is for steering into pits only. - s.x = (seg->vertex[TR_SL].x + seg->vertex[TR_SR].x)/2; - s.y = (seg->vertex[TR_SL].y + seg->vertex[TR_SR].y)/2; - //double dx, dy; - vec2f t, rt; + // all the BT code below is for steering into pits only. + s.x = (seg->vertex[TR_SL].x + seg->vertex[TR_SR].x)/2; + s.y = (seg->vertex[TR_SL].y + seg->vertex[TR_SR].y)/2; + //double dx, dy; + vec2f t, rt; - if ( seg->type == TR_STR) { - vec2f d, n; - n.x = (seg->vertex[TR_EL].x - seg->vertex[TR_ER].x)/seg->length; - n.y = (seg->vertex[TR_EL].y - seg->vertex[TR_ER].y)/seg->length; - n.normalize(); - d.x = (seg->vertex[TR_EL].x - seg->vertex[TR_SL].x)/seg->length; - d.y = (seg->vertex[TR_EL].y - seg->vertex[TR_SL].y)/seg->length; - t = s + d*length + offset*n; + if ( seg->type == TR_STR) { + vec2f d, n; + n.x = (seg->vertex[TR_EL].x - seg->vertex[TR_ER].x)/seg->length; + n.y = (seg->vertex[TR_EL].y - seg->vertex[TR_ER].y)/seg->length; + n.normalize(); + d.x = (seg->vertex[TR_EL].x - seg->vertex[TR_SL].x)/seg->length; + d.y = (seg->vertex[TR_EL].y - seg->vertex[TR_SL].y)/seg->length; + t = s + d*length + offset*n; - return t; - } else { - vec2f c, n; - c.x = seg->center.x; - c.y = seg->center.y; - float arc = length/seg->radius; - float arcsign = (seg->type == TR_RGT) ? -1.0f : 1.0f; - arc = arc*arcsign; - s = s.rotate(c, arc); - - n = c - s; - n.normalize(); - t = s + arcsign*offset*n; + return t; + } else { + vec2f c, n; + c.x = seg->center.x; + c.y = seg->center.y; + float arc = length/seg->radius; + float arcsign = (seg->type == TR_RGT) ? -1.0f : 1.0f; + arc = arc*arcsign; + s = s.rotate(c, arc); + + n = c - s; + n.normalize(); + t = s + arcsign*offset*n; - return t; - } + return t; + } } bool Driver::canOvertake( Opponent *o, double *mincatchdist, bool outside, bool lenient ) { - if (!o) return false; + if (!o) return false; #if 1 - //int segid = car->_trkPos.seg->id; - tCarElt *ocar = o->getCarPtr(); - //int osegid = ocar->_trkPos.seg->id; - double otry_factor = (lenient ? (0.2 + MAX(0.0, 1.0 - ((simtime-frontavoidtime)/7.0)) * 0.8) : 1.0); - double overtakecaution = MAX(0.0, rldata->overtakecaution + (outside ? MIN(0.0, car->_accel_x/8) : 0.0)) - driver_aggression/2; - double orInv=0.0, oAspeed=0.0; - raceline->getOpponentInfo(o->getDistance(), &oAspeed, &orInv); - double rInv = MAX(fabs(rldata->rInverse), fabs(orInv)); - double distance = o->getDistance() * otry_factor * MAX(0.5, 1.0 - (ocar->_pos > car->_pos ? MIN(o->getDistance()/2, 3.0) : 0.0)); - //double speed = MIN(rldata->avspeed, MIN(oAspeed, currentspeed + MAX(0.0, (30.0 - distance) * MAX(0.1, 1.0 - MAX(0.0, rInv-0.001)*80)))); - double speed = currentspeed; - double avspeed = MIN(rldata->avspeed, speed + 2.0); - speed = MIN(avspeed, (speed + MAX(0.0, (30.0 - distance) * MAX(0.1, 1.0 - MAX(0.0, rInv-0.001)*80)))); - double ospeed = o->getSpeed(); - double timeLimit = 3.0 - MIN(2.4, rInv * 1000); + //int segid = car->_trkPos.seg->id; + tCarElt *ocar = o->getCarPtr(); + //int osegid = ocar->_trkPos.seg->id; + double otry_factor = (lenient ? (0.2 + MAX(0.0, 1.0 - ((simtime-frontavoidtime)/7.0)) * 0.8) : 1.0); + double overtakecaution = MAX(0.0, rldata->overtakecaution + (outside ? MIN(0.0, car->_accel_x/8) : 0.0)) - driver_aggression/2; + double orInv=0.0, oAspeed=0.0; + raceline->getOpponentInfo(o->getDistance(), &oAspeed, &orInv); + double rInv = MAX(fabs(rldata->rInverse), fabs(orInv)); + double distance = o->getDistance() * otry_factor * MAX(0.5, 1.0 - (ocar->_pos > car->_pos ? MIN(o->getDistance()/2, 3.0) : 0.0)); + //double speed = MIN(rldata->avspeed, MIN(oAspeed, currentspeed + MAX(0.0, (30.0 - distance) * MAX(0.1, 1.0 - MAX(0.0, rInv-0.001)*80)))); + double speed = currentspeed; + double avspeed = MIN(rldata->avspeed, speed + 2.0); + speed = MIN(avspeed, (speed + MAX(0.0, (30.0 - distance) * MAX(0.1, 1.0 - MAX(0.0, rInv-0.001)*80)))); + double ospeed = o->getSpeed(); + double timeLimit = 3.0 - MIN(2.4, rInv * 1000); - //double speeddiff = MAX((15.0-(rInv*1000*1.0+overtakecaution/2)) - distance, fabs(speed - ospeed) * (8 - MIN(5.5, rInv*300))); - double speeddiff = (MIN(speed, avspeed) - ospeed) * 2; - if (outside) - ospeed *= 1.0 + rInv*3; - //double catchdist = (double) MIN((speed*distance)/(speed-ospeed), distance*CATCH_FACTOR) * otry_factor; - double catchdist = (double) ((speed*distance)/(speed-ospeed)) * otry_factor * 0.8 + distance/10; - double mcd = car->_speed_x * (2.0 - MIN(1.5, rInv * 500)); + //double speeddiff = MAX((15.0-(rInv*1000*1.0+overtakecaution/2)) - distance, fabs(speed - ospeed) * (8 - MIN(5.5, rInv*300))); + double speeddiff = (MIN(speed, avspeed) - ospeed) * 2; + if (outside) + ospeed *= 1.0 + rInv*3; + //double catchdist = (double) MIN((speed*distance)/(speed-ospeed), distance*CATCH_FACTOR) * otry_factor; + double catchdist = (double) ((speed*distance)/(speed-ospeed)) * otry_factor * 0.8 + distance/10; + double mcd = car->_speed_x * (2.0 - MIN(1.5, rInv * 500)); #if 0 - // TRB ENDURANCE RACES ONLY!!! - if (car->race.laps < 2 && - ocar->_pos < car->_pos && - fabs(o->getAngle()) < 0.6 && - ocar->_speed_x > MAX(10.0, car->_speed_x/2)) - { - overtakecaution += (2 - car->race.laps) * 4; - } + // TRB ENDURANCE RACES ONLY!!! + if (car->race.laps < 2 && + ocar->_pos < car->_pos && + fabs(o->getAngle()) < 0.6 && + ocar->_speed_x > MAX(10.0, car->_speed_x/2)) + { + overtakecaution += (2 - car->race.laps) * 4; + } #endif - if (catchdist < mcd && MIN(speed, avspeed) > ospeed && //catchdist < *mincatchdist+0.1 && - (distance * (1.0+overtakecaution) < MIN(speeddiff, catchdist/4 + 2.0) * (1.0-rInv*30) || - o->getTimeImpact() * (1.0+overtakecaution) < timeLimit)) - { - if (DebugMsg & debug_overtake) - fprintf(stderr,"%.1f %s: OVERTAKE! (cd %.1f<%.1f) (dist %.1f (%.1f) < (%.1f-%.1f)*X = %.1f TI %.3f < tl %.3f || caut=%.1f avspd=%.1f oAspd=%.1f\n",otry_factor,ocar->_name,catchdist,mcd,distance,o->getDistance(),speed,ospeed,speeddiff,o->getTimeImpact(),timeLimit,overtakecaution,avspeed,oAspeed); - *mincatchdist = catchdist + 0.1; - return true; - } - else if (DebugMsg & debug_overtake) - fprintf(stderr,"%.1f %s: FAIL!!!!! (cd %.1f<%.1f) (dist %.1f (%.1f) < (%.1f-%.1f)*X = %.1f TI %.3f < tl %.3f || caut=%.1f avspd=%.1f oAspd=%.1f\n",otry_factor,ocar->_name,catchdist,mcd,distance,o->getDistance(),speed,ospeed,speeddiff,o->getTimeImpact(),timeLimit,overtakecaution,avspeed,oAspeed); + if (catchdist < mcd && MIN(speed, avspeed) > ospeed && //catchdist < *mincatchdist+0.1 && + (distance * (1.0+overtakecaution) < MIN(speeddiff, catchdist/4 + 2.0) * (1.0-rInv*30) || + o->getTimeImpact() * (1.0+overtakecaution) < timeLimit)) + { + if (DebugMsg & debug_overtake) + fprintf(stderr,"%.1f %s: OVERTAKE! (cd %.1f<%.1f) (dist %.1f (%.1f) < (%.1f-%.1f)*X = %.1f TI %.3f < tl %.3f || caut=%.1f avspd=%.1f oAspd=%.1f\n",otry_factor,ocar->_name,catchdist,mcd,distance,o->getDistance(),speed,ospeed,speeddiff,o->getTimeImpact(),timeLimit,overtakecaution,avspeed,oAspeed); + *mincatchdist = catchdist + 0.1; + return true; + } + else if (DebugMsg & debug_overtake) + fprintf(stderr,"%.1f %s: FAIL!!!!! (cd %.1f<%.1f) (dist %.1f (%.1f) < (%.1f-%.1f)*X = %.1f TI %.3f < tl %.3f || caut=%.1f avspd=%.1f oAspd=%.1f\n",otry_factor,ocar->_name,catchdist,mcd,distance,o->getDistance(),speed,ospeed,speeddiff,o->getTimeImpact(),timeLimit,overtakecaution,avspeed,oAspeed); #else - double distance = o->getDistance(); - double speed = MIN(rldata->avspeed, currentspeed + MAX(0.0, (currentspeed/3 - distance)/2)); - double ospeed = o->getSpeed(); - double caution = overtakecaution + (outside == true ? 0.5 : 0.0); - //double rInverse = (fabs(nextCRinverse)>fabs(rldata->rInverse) ? nextCRinverse : rldata->rInverse); - double rInverse = rldata->aInverse; //rldata->rInverse; + double distance = o->getDistance(); + double speed = MIN(rldata->avspeed, currentspeed + MAX(0.0, (currentspeed/3 - distance)/2)); + double ospeed = o->getSpeed(); + double caution = overtakecaution + (outside == true ? 0.5 : 0.0); + //double rInverse = (fabs(nextCRinverse)>fabs(rldata->rInverse) ? nextCRinverse : rldata->rInverse); + double rInverse = rldata->aInverse; //rldata->rInverse; - { - tTrackSeg *wseg = (rInverse > 0.0 ? car->_wheelSeg(FRNT_LFT) : car->_wheelSeg(FRNT_RGT)); - if (wseg->surface->kFriction > car->_trkPos.seg->surface->kFriction) - caution += (wseg->surface->kFriction - car->_trkPos.seg->surface->kFriction) * 4; - } + { + tTrackSeg *wseg = (rInverse > 0.0 ? car->_wheelSeg(FRNT_LFT) : car->_wheelSeg(FRNT_RGT)); + if (wseg->surface->kFriction > car->_trkPos.seg->surface->kFriction) + caution += (wseg->surface->kFriction - car->_trkPos.seg->surface->kFriction) * 4; + } - distance += fabs(rInverse) * 200; - if (outside) - { - distance += fabs(rInverse) * 800; - if ((rInverse > 0.0 && angle > 0.0) || (rInverse < 0.0 && angle < 0.0)) - caution += fabs(speedangle-angle) * 20; - } + distance += fabs(rInverse) * 200; + if (outside) + { + distance += fabs(rInverse) * 800; + if ((rInverse > 0.0 && angle > 0.0) || (rInverse < 0.0 && angle < 0.0)) + caution += fabs(speedangle-angle) * 20; + } - double catchdist = MIN(speed*distance/(speed-ospeed), distance*CATCH_FACTOR) * (lenient ? (0.7 + MIN(0.3, (simtime-frontavoidtime)/10.0)) : 1.0) * (1.0 + caution/2); - - if (catchdist > *mincatchdist && - *mincatchdist >= MAX(100.0, car->_speed_x*5) && - rldata->avspeed > 1000.0 && currentspeed > ospeed - (lenient ? 3.0 : 1.5)) - { - // on a fast section - don't let catchdist be a barrier to overtaking - catchdist = *mincatchdist * 0.9; - } + double catchdist = MIN(speed*distance/(speed-ospeed), distance*CATCH_FACTOR) * (lenient ? (0.7 + MIN(0.3, (simtime-frontavoidtime)/10.0)) : 1.0) * (1.0 + caution/2); + + if (catchdist > *mincatchdist && + *mincatchdist >= MAX(100.0, car->_speed_x*5) && + rldata->avspeed > 1000.0 && currentspeed > ospeed - (lenient ? 3.0 : 1.5)) + { + // on a fast section - don't let catchdist be a barrier to overtaking + catchdist = *mincatchdist * 0.9; + } - if ((catchdist <= *mincatchdist) && distance < (speed-ospeed)*2) - { - double mradius = MAX(0.0, MIN(1.0, fabs(rInverse) * 70)); - double oradius = MAX(0.0, MIN(1.0, fabs(raceline->getRInverse(distance)) * 80)); - double radius = MAX(1.0, MIN(10.0, MAX(1.0 / mradius, 1.0 / oradius))); - catchdist *= radius; - double distance2 = distance * radius; - - if (catchdist <= *mincatchdist && distance < fabs(speed-ospeed)*2) - { - if (DebugMsg & debug_overtake) - fprintf(stderr,"%s - %s OVERTAKE: cd=%.1f > %.1f, dist=%.1f > (%.1f-%.1f)*2=%.1f\n",car->_name,o->getCarPtr()->_name,catchdist,*mincatchdist,distance,speed,ospeed,(speed-ospeed)*2); - *mincatchdist = catchdist+0.1; - return true; - } - else if (DebugMsg & debug_overtake) - fprintf(stderr,"%s - %s FAIL 2: cd=%.1f > %.1f, dist=%.1f (%.1f/%.1f) > (%.1f-%.1f)*2=%.1f\n",car->_name,o->getCarPtr()->_name,catchdist,*mincatchdist,distance2,distance,o->getDistance(),speed,ospeed,(speed-ospeed)*2); - } - else if (DebugMsg & debug_overtake) - fprintf(stderr,"%s - %s FAIL 1: cd=%.1f > %.1f, dist=%.1f (%.1f) > (%.1f-%.1f)*2=%.1f\n",car->_name,o->getCarPtr()->_name,catchdist,*mincatchdist,distance,o->getDistance(),speed,ospeed,(speed-ospeed)*2); + if ((catchdist <= *mincatchdist) && distance < (speed-ospeed)*2) + { + double mradius = MAX(0.0, MIN(1.0, fabs(rInverse) * 70)); + double oradius = MAX(0.0, MIN(1.0, fabs(raceline->getRInverse(distance)) * 80)); + double radius = MAX(1.0, MIN(10.0, MAX(1.0 / mradius, 1.0 / oradius))); + catchdist *= radius; + double distance2 = distance * radius; + + if (catchdist <= *mincatchdist && distance < fabs(speed-ospeed)*2) + { + if (DebugMsg & debug_overtake) + fprintf(stderr,"%s - %s OVERTAKE: cd=%.1f > %.1f, dist=%.1f > (%.1f-%.1f)*2=%.1f\n",car->_name,o->getCarPtr()->_name,catchdist,*mincatchdist,distance,speed,ospeed,(speed-ospeed)*2); + *mincatchdist = catchdist+0.1; + return true; + } + else if (DebugMsg & debug_overtake) + fprintf(stderr,"%s - %s FAIL 2: cd=%.1f > %.1f, dist=%.1f (%.1f/%.1f) > (%.1f-%.1f)*2=%.1f\n",car->_name,o->getCarPtr()->_name,catchdist,*mincatchdist,distance2,distance,o->getDistance(),speed,ospeed,(speed-ospeed)*2); + } + else if (DebugMsg & debug_overtake) + fprintf(stderr,"%s - %s FAIL 1: cd=%.1f > %.1f, dist=%.1f (%.1f) > (%.1f-%.1f)*2=%.1f\n",car->_name,o->getCarPtr()->_name,catchdist,*mincatchdist,distance,o->getDistance(),speed,ospeed,(speed-ospeed)*2); #endif - return false; + return false; } // Compute offset to normal target point for overtaking or let pass an opponent. float Driver::getOffset() { - int i, avoidmovt = 0; - double /*catchdist,*/ mincatchdist = MAX(100.0, car->_speed_x * 5), mindist = -1000.0; - Opponent *o = NULL; - double lane2left = rldata->lane * car->_trkPos.seg->width; - double lane2right = car->_trkPos.seg->width-lane2left; - avoidmode = 0; - sideratio = 100.0; + int i, avoidmovt = 0; + double /*catchdist,*/ mincatchdist = MAX(100.0, car->_speed_x * 5), mindist = -1000.0; + Opponent *o = NULL; + double lane2left = rldata->lane * car->_trkPos.seg->width; + double lane2right = car->_trkPos.seg->width-lane2left; + avoidmode = 0; + sideratio = 100.0; - avoidlftoffset = car->_trkPos.seg->width / 2; - avoidrgtoffset = -car->_trkPos.seg->width / 2; + avoidlftoffset = car->_trkPos.seg->width / 2; + avoidrgtoffset = -car->_trkPos.seg->width / 2; - // Increment speed dependent. - //double incspeed = MIN(40.0, MAX(30.0, currentspeed)); - //double incfactor = (MAX_INC_FACTOR*0.5 - MIN(incspeed/10, MAX_INC_FACTOR*0.5-0.5)) * 60 * IncFactor; - //double incspeed = MIN(60.0, MAX(40.0, currentspeed)) - 10.0; - //double incfactor = (MAX_INC_FACTOR - MIN(fabs(incspeed)/MAX_INC_FACTOR, (MAX_INC_FACTOR - 1.0f))) * (10.0f + MAX(0.0, (CA-1.9)*10)) * IncFactor; - double incfactor = (MAX_INC_FACTOR - MIN(40.0/MAX_INC_FACTOR, (MAX_INC_FACTOR - 1.0f))) * (10.0f + MAX(0.0, (CA-1.9)*10)) * IncFactor; + // Increment speed dependent. + //double incspeed = MIN(40.0, MAX(30.0, currentspeed)); + //double incfactor = (MAX_INC_FACTOR*0.5 - MIN(incspeed/10, MAX_INC_FACTOR*0.5-0.5)) * 60 * IncFactor; + //double incspeed = MIN(60.0, MAX(40.0, currentspeed)) - 10.0; + //double incfactor = (MAX_INC_FACTOR - MIN(fabs(incspeed)/MAX_INC_FACTOR, (MAX_INC_FACTOR - 1.0f))) * (10.0f + MAX(0.0, (CA-1.9)*10)) * IncFactor; + double incfactor = (MAX_INC_FACTOR - MIN(40.0/MAX_INC_FACTOR, (MAX_INC_FACTOR - 1.0f))) * (10.0f + MAX(0.0, (CA-1.9)*10)) * IncFactor; - //double rgtinc = incfactor * MIN(3.0, MAX(0.6, 1.0 + rldata->mInverse * (rldata->mInverse<0.0?-5:100))); - //double lftinc = incfactor * MIN(3.0, MAX(0.6, 1.0 - rldata->mInverse * (rldata->mInverse>0.0?-5:100))); - double ri = rldata->aInverse; - double rgtinc = incfactor * MIN(3.0, MAX(0.6, 1.0 + (ri < 0.0 ? ri*4 : ri*MAX(10.0, car->_speed_x-25)*2*OutSteerFactor))); - double lftinc = incfactor * MIN(3.0, MAX(0.6, 1.0 - (ri > 0.0 ? ri*4 : ri*MAX(10.0,car->_speed_x-25)*2*OutSteerFactor))); - - //double reduce_movt = MAX(0.01, 1.0 - (MIN(1.0, fabs(laststeer))*2 * fabs(angle-speedangle)*3)); + //double rgtinc = incfactor * MIN(3.0, MAX(0.6, 1.0 + rldata->mInverse * (rldata->mInverse<0.0?-5:100))); + //double lftinc = incfactor * MIN(3.0, MAX(0.6, 1.0 - rldata->mInverse * (rldata->mInverse>0.0?-5:100))); + double ri = rldata->aInverse; + double rgtinc = incfactor * MIN(3.0, MAX(0.6, 1.0 + (ri < 0.0 ? ri*4 : ri*MAX(10.0, car->_speed_x-25)*2*OutSteerFactor))); + double lftinc = incfactor * MIN(3.0, MAX(0.6, 1.0 - (ri > 0.0 ? ri*4 : ri*MAX(10.0,car->_speed_x-25)*2*OutSteerFactor))); + + //double reduce_movt = MAX(0.01, 1.0 - (MIN(1.0, fabs(laststeer))*2 * fabs(angle-speedangle)*3)); #if 1 - double reduce_movt = MAX(0.1, MIN(1.0, 1.0 - fabs(angle*2 - laststeer)) * MAX(fabs(angle-speedangle), fabs(speedangle-angle))*1); - reduce_movt = MIN(reduce_movt, MAX(0.1, 1.0 + fabs(car->_accel_x)/30)); - lftinc *= reduce_movt; - rgtinc *= reduce_movt; + double reduce_movt = MAX(0.1, MIN(1.0, 1.0 - fabs(angle*2 - laststeer)) * MAX(fabs(angle-speedangle), fabs(speedangle-angle))*1); + reduce_movt = MIN(reduce_movt, MAX(0.1, 1.0 + fabs(car->_accel_x)/30)); + lftinc *= reduce_movt; + rgtinc *= reduce_movt; #else - if (ri > 0.0) - rgtinc *= MAX(0.0, MIN(1.0, 1.0 - (angle*2-car->_yaw_rate/2) * MIN(1.0, rldata->rInverse*40))); - else if (ri < 0.0) - lftinc *= MAX(0.0, MIN(1.0, 1.0 + (angle*2-car->_yaw_rate/2) * MIN(1.0, (-rldata->rInverse)*40))); + if (ri > 0.0) + rgtinc *= MAX(0.0, MIN(1.0, 1.0 - (angle*2-car->_yaw_rate/2) * MIN(1.0, rldata->rInverse*40))); + else if (ri < 0.0) + lftinc *= MAX(0.0, MIN(1.0, 1.0 + (angle*2-car->_yaw_rate/2) * MIN(1.0, (-rldata->rInverse)*40))); #endif - double moffset = car->_trkPos.toMiddle; + double moffset = car->_trkPos.toMiddle; - //double origoffset = moffset; + //double origoffset = moffset; - double Width = car->_trkPos.seg->width; + double Width = car->_trkPos.seg->width; #if 1 - double lftmargin = GetModD( tLftMargin, rldata->nextdiv ); - double rgtmargin = GetModD( tRgtMargin, rldata->nextdiv ); - double maxoffset = MIN(moffset+OVERTAKE_OFFSET_INC*lftinc*4, Width/2 - (car->_dimension_y+SideMargin+rgtmargin)); - double minoffset = MAX(moffset-OVERTAKE_OFFSET_INC*rgtinc*4, -(Width/2 - (car->_dimension_y+SideMargin+lftmargin))); + double lftmargin = GetModD( tLftMargin, rldata->nextdiv ); + double rgtmargin = GetModD( tRgtMargin, rldata->nextdiv ); + double maxoffset = MIN(moffset+OVERTAKE_OFFSET_INC*lftinc*4, Width/2 - (car->_dimension_y+SideMargin+rgtmargin)); + double minoffset = MAX(moffset-OVERTAKE_OFFSET_INC*rgtinc*4, -(Width/2 - (car->_dimension_y+SideMargin+lftmargin))); - double oldmax = maxoffset, oldmin = minoffset; + double oldmax = maxoffset, oldmin = minoffset; - { - ri = (fabs(rldata->aInverse) < fabs(rldata->mInverse) ? rldata->aInverse : rldata->mInverse); - if (rldata->mInverse > 0.0) - maxoffset = MIN(maxoffset, MAX(Width/8, Width/2 - (1.5 + ri*1000))); - else - minoffset = MAX(minoffset, MIN(-Width/8, -Width/2 + (1.5 - ri*1000))); - } + { + ri = (fabs(rldata->aInverse) < fabs(rldata->mInverse) ? rldata->aInverse : rldata->mInverse); + if (rldata->mInverse > 0.0) + maxoffset = MIN(maxoffset, MAX(Width/8, Width/2 - (1.5 + ri*1000))); + else + minoffset = MAX(minoffset, MIN(-Width/8, -Width/2 + (1.5 - ri*1000))); + } #endif - - //myoffset = car->_trkPos.toMiddle; - if (mode == mode_normal) - { - moffset = rldata->offset; - myoffset = (float) moffset; - } - else - { - // reduce amount we deviate from the raceline according to how long we've been avoiding, and also - // how fast we're going. - //double dspeed = MAX(0.0, rldata->speed - currentspeed) * 4; - //double pspeed = MAX(1.0, 60.0 - (currentspeed - (30.0 + MAX(0.0, car->_accel_x) + dspeed))) / 10; + + //myoffset = car->_trkPos.toMiddle; + if (mode == mode_normal) + { + moffset = rldata->offset; + myoffset = (float) moffset; + } + else + { + // reduce amount we deviate from the raceline according to how long we've been avoiding, and also + // how fast we're going. + //double dspeed = MAX(0.0, rldata->speed - currentspeed) * 4; + //double pspeed = MAX(1.0, 60.0 - (currentspeed - (30.0 + MAX(0.0, car->_accel_x) + dspeed))) / 10; - // instead of toMiddle just aiming at where the car currently is, we move it in the direction - // the car's travelling ... but less so if the speedangle is different from the car's angle. - double sa = speedangle; - //double anglechange = ((sa*0.8) * MAX(0.0, 1.0 - fabs(sa-angle)*(0.6+fabs(sa-angle)))) * 0.7; - double anglechange = ((sa*1.0) * MAX(0.0, 1.0 - fabs(sa-angle))) * (fabs(currentspeed)/50); - double toMiddle = car->_trkPos.toMiddle + anglechange*0; - moffset = toMiddle; - myoffset = (float) moffset; + // instead of toMiddle just aiming at where the car currently is, we move it in the direction + // the car's travelling ... but less so if the speedangle is different from the car's angle. + double sa = speedangle; + //double anglechange = ((sa*0.8) * MAX(0.0, 1.0 - fabs(sa-angle)*(0.6+fabs(sa-angle)))) * 0.7; + double anglechange = ((sa*1.0) * MAX(0.0, 1.0 - fabs(sa-angle))) * (fabs(currentspeed)/50); + double toMiddle = car->_trkPos.toMiddle + anglechange*0; + moffset = toMiddle; + myoffset = (float) moffset; - if (mode == mode_correcting && avoidtime < simtime) - avoidtime += deltaTime*0.8; - if (simtime - avoidtime > 3.0) - avoidtime = simtime - 3.0; + if (mode == mode_correcting && avoidtime < simtime) + avoidtime += deltaTime*0.8; + if (simtime - avoidtime > 3.0) + avoidtime = simtime - 3.0; - if (0) - { - if (toMiddle > rldata->offset) - moffset = MIN(toMiddle, rldata->offset + (simtime-avoidtime) * 45.0 * incfactor/8); - else - moffset = MAX(toMiddle, rldata->offset - (simtime-avoidtime) * 45.0 * incfactor/8); - } + if (0) + { + if (toMiddle > rldata->offset) + moffset = MIN(toMiddle, rldata->offset + (simtime-avoidtime) * 45.0 * incfactor/8); + else + moffset = MAX(toMiddle, rldata->offset - (simtime-avoidtime) * 45.0 * incfactor/8); + } #if 0 - if (fabs(car->_trkPos.toMiddle) < MAX(fabs(minoffset), fabs(maxoffset))) - { - if (anglechange > 0.0) - minoffset = MIN(maxoffset, MAX(minoffset, car->_trkPos.toMiddle - MAX(0.1, 1.0 - anglechange*2)*2)); - else - maxoffset = MAX(minoffset, MIN(maxoffset, car->_trkPos.toMiddle + MAX(0.1, 1.0 - fabs(anglechange*2))*2)); - } + if (fabs(car->_trkPos.toMiddle) < MAX(fabs(minoffset), fabs(maxoffset))) + { + if (anglechange > 0.0) + minoffset = MIN(maxoffset, MAX(minoffset, car->_trkPos.toMiddle - MAX(0.1, 1.0 - anglechange*2)*2)); + else + maxoffset = MAX(minoffset, MIN(maxoffset, car->_trkPos.toMiddle + MAX(0.1, 1.0 - fabs(anglechange*2))*2)); + } #endif - } + } - { - minoffset = MAX(minoffset, car->_trkPos.toMiddle - OVERTAKE_OFFSET_INC*rgtinc*100); - maxoffset = MIN(maxoffset, car->_trkPos.toMiddle + OVERTAKE_OFFSET_INC*lftinc*100); - } - //myoffset = car->_trkPos.toMiddle; + { + minoffset = MAX(minoffset, car->_trkPos.toMiddle - OVERTAKE_OFFSET_INC*rgtinc*100); + maxoffset = MIN(maxoffset, car->_trkPos.toMiddle + OVERTAKE_OFFSET_INC*lftinc*100); + } + //myoffset = car->_trkPos.toMiddle; - // Side Collision. - for (i = 0; i < opponents->getNOpponents(); i++) - { - tCarElt *ocar = opponent[i].getCarPtr(); + // Side Collision. + for (i = 0; i < opponents->getNOpponents(); i++) + { + tCarElt *ocar = opponent[i].getCarPtr(); - if (ocar->_state & (RM_CAR_STATE_NO_SIMU & ~RM_CAR_STATE_PIT)) - continue; + if (ocar->_state & (RM_CAR_STATE_NO_SIMU & ~RM_CAR_STATE_PIT)) + continue; - if (fabs(ocar->_trkPos.toMiddle) > Width/2 + 3.0 && - fabs(car->_trkPos.toMiddle-ocar->_trkPos.toMiddle) >= 5.0) - continue; + if (fabs(ocar->_trkPos.toMiddle) > Width/2 + 3.0 && + fabs(car->_trkPos.toMiddle-ocar->_trkPos.toMiddle) >= 5.0) + continue; - if ((opponent[i].getState() & OPP_SIDE)) - { - o = &opponent[i]; + if ((opponent[i].getState() & OPP_SIDE)) + { + o = &opponent[i]; if (DebugMsg & debug_overtake) fprintf(stderr,"%s SIDE %s\n",car->_name,ocar->_name);fflush(stderr); - - double sidedist = fabs(ocar->_trkPos.toLeft - car->_trkPos.toLeft); - double sidemargin = opponent[i].getWidth()/2 + getWidth()/2 + 5.0f + MAX(fabs(rldata->rInverse), fabs(rldata->mInverse))*100; - double side = (car->_trkPos.toMiddle-angle) - (ocar->_trkPos.toMiddle-opponent[i].getAngle()); - double sidedist2 = sidedist; - if (side > 0.0) - { - // I'm on his left - sidedist2 -= (o->getSpeedAngle() - speedangle) * 40; - sidemargin -= MIN(0.0, rldata->rInverse*100); - } - else - { - // I'm on his right - sidedist2 -= (speedangle - o->getSpeedAngle()) * 40; - sidemargin += MAX(0.0, rldata->rInverse*100); - } - int closing = (sidedist2 < sidedist); + + double sidedist = fabs(ocar->_trkPos.toLeft - car->_trkPos.toLeft); + double sidemargin = opponent[i].getWidth()/2 + getWidth()/2 + 5.0f + MAX(fabs(rldata->rInverse), fabs(rldata->mInverse))*100; + double side = (car->_trkPos.toMiddle-angle) - (ocar->_trkPos.toMiddle-opponent[i].getAngle()); + double sidedist2 = sidedist; + if (side > 0.0) + { + // I'm on his left + sidedist2 -= (o->getSpeedAngle() - speedangle) * 40; + sidemargin -= MIN(0.0, rldata->rInverse*100); + } + else + { + // I'm on his right + sidedist2 -= (speedangle - o->getSpeedAngle()) * 40; + sidemargin += MAX(0.0, rldata->rInverse*100); + } + int closing = (sidedist2 < sidedist); - if (sidedist < sidemargin || sidedist2 < sidemargin) - { - //double w = Width/WIDTHDIV-BORDER_OVERTAKE_MARGIN; - //double sdiff = 2.0 - MAX(sidemargin-sidedist, sidemargin-sidedist2)/sidemargin; - double sdiff = MAX(sidemargin-sidedist, sidemargin-sidedist2) + MAX(0.0, sidedist - sidedist2); + if (sidedist < sidemargin || sidedist2 < sidemargin) + { + //double w = Width/WIDTHDIV-BORDER_OVERTAKE_MARGIN; + //double sdiff = 2.0 - MAX(sidemargin-sidedist, sidemargin-sidedist2)/sidemargin; + double sdiff = MAX(sidemargin-sidedist, sidemargin-sidedist2) + MAX(0.0, sidedist - sidedist2); - if (side > 0.0) { - double linc = OVERTAKE_OFFSET_INC * (lftinc * MAX(0.2, MIN(1.1, sdiff/4)) * 1.5); - if (rldata->rInverse < 0.0) - linc -= rldata->rInverse * 200 * IncFactor; - myoffset += (float) linc; - //if (rldata->rInverse < 0.0) - // myoffset -= rldata->rInverse * 500 * IncFactor; - avoidmovt = 1; + if (side > 0.0) { + double linc = OVERTAKE_OFFSET_INC * (lftinc * MAX(0.2, MIN(1.1, sdiff/4)) * 1.5); + if (rldata->rInverse < 0.0) + linc -= rldata->rInverse * 200 * IncFactor; + myoffset += (float) linc; + //if (rldata->rInverse < 0.0) + // myoffset -= rldata->rInverse * 500 * IncFactor; + avoidmovt = 1; if (DebugMsg & debug_overtake) fprintf(stderr,"%s SIDE to Rgt %s, MOVING LEFT by %.3f, sm=%.3f sd=%.3f/%.3f sm-sd=%.3f mInv=%.3f\n",car->_name,ocar->_name,(float) (OVERTAKE_OFFSET_INC*lftinc*MAX(0.2f, MIN(1.5f, sdiff))),sidemargin,sidedist,sidedist2,sdiff,rldata->mInverse);fflush(stderr); - } else if (side <= 0.0) { - double rinc = OVERTAKE_OFFSET_INC * (rgtinc * MAX(0.2, MIN(1.1, sdiff/4)) * 1.5); - if (rldata->rInverse > 0.0) - rinc += rldata->rInverse * 200 * IncFactor; - myoffset -= (float) rinc; - //if (rldata->rInverse > 0.0) - // myoffset -= rldata->rInverse * 500 * IncFactor; - avoidmovt = 1; + } else if (side <= 0.0) { + double rinc = OVERTAKE_OFFSET_INC * (rgtinc * MAX(0.2, MIN(1.1, sdiff/4)) * 1.5); + if (rldata->rInverse > 0.0) + rinc += rldata->rInverse * 200 * IncFactor; + myoffset -= (float) rinc; + //if (rldata->rInverse > 0.0) + // myoffset -= rldata->rInverse * 500 * IncFactor; + avoidmovt = 1; if (DebugMsg & debug_overtake) fprintf(stderr,"%s SIDE to Lft %s, MOVING RIGHT by %.3f sm-sd=%.2f mo=%.3f\n",car->_name,ocar->_name,(OVERTAKE_OFFSET_INC*lftinc*MAX(1.0f, MIN(2.0f, sdiff))),sdiff,myoffset);fflush(stderr); - } + } - if (avoidmovt) - sideratio = MIN(sidedist,sidedist2)/sidemargin; + if (avoidmovt) + sideratio = MIN(sidedist,sidedist2)/sidemargin; else if (DebugMsg & debug_overtake) fprintf(stderr,"%s SIDE %s, NO MOVE %.1f\n",car->_name,ocar->_name,myoffset);fflush(stderr); - } - else if (sidedist > sidemargin+3.0) - { - if ((car->_trkPos.toLeft > ocar->_trkPos.toLeft && rldata->rInverse > 0.0) || - (car->_trkPos.toLeft < ocar->_trkPos.toLeft && rldata->rInverse < 0.0)) - avoidtime = MIN(simtime, avoidtime + MIN(deltaTime*0.9, fabs(rldata->rInverse*1.2))); + } + else if (sidedist > sidemargin+3.0) + { + if ((car->_trkPos.toLeft > ocar->_trkPos.toLeft && rldata->rInverse > 0.0) || + (car->_trkPos.toLeft < ocar->_trkPos.toLeft && rldata->rInverse < 0.0)) + avoidtime = MIN(simtime, avoidtime + MIN(deltaTime*0.9, fabs(rldata->rInverse*1.2))); - if (ocar->_trkPos.toLeft > car->_trkPos.toLeft && - car->_trkPos.toLeft < MIN(lane2left, 4.0 + fabs(nextCRinverse)*1000)) - { - myoffset -= (float) (OVERTAKE_OFFSET_INC*lftinc/4); + if (ocar->_trkPos.toLeft > car->_trkPos.toLeft && + car->_trkPos.toLeft < MIN(lane2left, 4.0 + fabs(nextCRinverse)*1000)) + { + myoffset -= (float) (OVERTAKE_OFFSET_INC*lftinc/4); if (DebugMsg & debug_overtake) fprintf(stderr,"%s SIDE to Rgt %s, MOVING BACK TO RIGHT\n",car->_name,ocar->_name);fflush(stderr); - if (!avoidmode) - avoidtime = MIN(simtime, avoidtime+deltaTime*0.5); - } - else if (ocar->_trkPos.toLeft < car->_trkPos.toLeft && - car->_trkPos.toRight < MIN(lane2right, 4.0 + fabs(nextCRinverse)*1000)) - { - myoffset += (float) (OVERTAKE_OFFSET_INC*rgtinc/4); + if (!avoidmode) + avoidtime = MIN(simtime, avoidtime+deltaTime*0.5); + } + else if (ocar->_trkPos.toLeft < car->_trkPos.toLeft && + car->_trkPos.toRight < MIN(lane2right, 4.0 + fabs(nextCRinverse)*1000)) + { + myoffset += (float) (OVERTAKE_OFFSET_INC*rgtinc/4); if (DebugMsg & debug_overtake) fprintf(stderr,"%s SIDE to Lft %s, MOVING BACK TO LEFT\n",car->_name,ocar->_name);fflush(stderr); - if (!avoidmode) - avoidtime = MIN(simtime, avoidtime+deltaTime*0.5); - } + if (!avoidmode) + avoidtime = MIN(simtime, avoidtime+deltaTime*0.5); + } else if (DebugMsg & debug_overtake) fprintf(stderr,"%s SIDE %s, NO MOVE %.1f\n",car->_name,ocar->_name,myoffset);fflush(stderr); - } + } else if (DebugMsg & debug_overtake) fprintf(stderr,"%s SIDE %s, NO MOVE AT ALL! %.1f\n",car->_name,ocar->_name,myoffset);fflush(stderr); - if (ocar->_trkPos.toLeft > car->_trkPos.toLeft) - { - avoidrgtoffset = (float) MAX(avoidrgtoffset, ocar->_trkPos.toMiddle + (o->getWidth()+1.0f)); - avoidmode |= avoidright; - //if (avoidmovt) - avoidmode |= avoidside; - if (closing) - avoidmode |= avoidsideclosing; - } - else - { - avoidlftoffset = (float) MIN(avoidlftoffset, ocar->_trkPos.toMiddle - (o->getWidth()+1.0f)); - avoidmode |= avoidleft; - //if (avoidmovt) - avoidmode |= avoidside; - if (closing) - avoidmode |= avoidsideclosing; - } + if (ocar->_trkPos.toLeft > car->_trkPos.toLeft) + { + avoidrgtoffset = (float) MAX(avoidrgtoffset, ocar->_trkPos.toMiddle + (o->getWidth()+1.0f)); + avoidmode |= avoidright; + //if (avoidmovt) + avoidmode |= avoidside; + if (closing) + avoidmode |= avoidsideclosing; + } + else + { + avoidlftoffset = (float) MIN(avoidlftoffset, ocar->_trkPos.toMiddle - (o->getWidth()+1.0f)); + avoidmode |= avoidleft; + //if (avoidmovt) + avoidmode |= avoidside; + if (closing) + avoidmode |= avoidsideclosing; + } - } - } + } + } - if (avoidmode) - { - if (!avoidmovt) - avoidtime = MIN(simtime, avoidtime+deltaTime*1.0); - goto end_getoffset; - } + if (avoidmode) + { + if (!avoidmovt) + avoidtime = MIN(simtime, avoidtime+deltaTime*1.0); + goto end_getoffset; + } #if 0 - // don't try and front-avoid if we're struggling for control! - if (avgaccel_x - fabs(laststeer) * fabs(angle-speedangle) < -10.0) - goto end_getoffset; + // don't try and front-avoid if we're struggling for control! + if (avgaccel_x - fabs(laststeer) * fabs(angle-speedangle) < -10.0) + goto end_getoffset; - if (rldata->lftmargin > 0.0 && minoffset < rldata->offset - rldata->lftmargin) - minoffset = rldata->offset - rldata->lftmargin; - if (rldata->rgtmargin > 0.0 && maxoffset > rldata->offset + rldata->rgtmargin) - maxoffset = rldata->offset + rldata->rgtmargin; + if (rldata->lftmargin > 0.0 && minoffset < rldata->offset - rldata->lftmargin) + minoffset = rldata->offset - rldata->lftmargin; + if (rldata->rgtmargin > 0.0 && maxoffset > rldata->offset + rldata->rgtmargin) + maxoffset = rldata->offset + rldata->rgtmargin; #endif - if (car->_speed_x > 20.0 || simtime > 10.0) - { - double caution = rldata->overtakecaution; + if (car->_speed_x > 20.0 || simtime > 10.0) + { + double caution = rldata->overtakecaution; - { - tTrackSeg *wseg = (rldata->rInverse > 0.0 ? car->_wheelSeg(FRNT_LFT) : car->_wheelSeg(FRNT_RGT)); - if (wseg->surface->kFriction > car->_trkPos.seg->surface->kFriction) - caution += (wseg->surface->kFriction - car->_trkPos.seg->surface->kFriction) * 4; - } + { + tTrackSeg *wseg = (rldata->rInverse > 0.0 ? car->_wheelSeg(FRNT_LFT) : car->_wheelSeg(FRNT_RGT)); + if (wseg->surface->kFriction > car->_trkPos.seg->surface->kFriction) + caution += (wseg->surface->kFriction - car->_trkPos.seg->surface->kFriction) * 4; + } - //caution += fabs(speedangle - angle)*10; - int otry_success = 0; - double rInverse = rldata->rInverse; - if (fabs(nextCRinverse) > fabs(rInverse)) - rInverse = nextCRinverse; + //caution += fabs(speedangle - angle)*10; + int otry_success = 0; + double rInverse = rldata->rInverse; + if (fabs(nextCRinverse) > fabs(rInverse)) + rInverse = nextCRinverse; - for (int otry=0; otry<=1; otry++) - { - // Overtake. - for (i = 0; i < opponents->getNOpponents(); i++) - { - tCarElt *ocar = opponent[i].getCarPtr(); - - // strategy telling us to follow this car? - if ((opponent[i].getState() & OPP_FRONT_FOLLOW)) - continue; + for (int otry=0; otry<=1; otry++) + { + // Overtake. + for (i = 0; i < opponents->getNOpponents(); i++) + { + tCarElt *ocar = opponent[i].getCarPtr(); + + // strategy telling us to follow this car? + if ((opponent[i].getState() & OPP_FRONT_FOLLOW)) + continue; - // off track or a long way wide of us? - if (!(opponent[i].getState() & OPP_COLL) && - fabs(ocar->_trkPos.toMiddle) > Width/2 + 3.0 && - fabs(car->_trkPos.toMiddle-ocar->_trkPos.toMiddle) >= 8.0) - continue; + // off track or a long way wide of us? + if (!(opponent[i].getState() & OPP_COLL) && + fabs(ocar->_trkPos.toMiddle) > Width/2 + 3.0 && + fabs(car->_trkPos.toMiddle-ocar->_trkPos.toMiddle) >= 8.0) + continue; - if (ocar->_state & (RM_CAR_STATE_NO_SIMU & ~RM_CAR_STATE_PIT)) - continue; + if (ocar->_state & (RM_CAR_STATE_NO_SIMU & ~RM_CAR_STATE_PIT)) + continue; - if ((opponent[i].getState() & OPP_FRONT) && - !(0 && opponent[i].isTeamMate() && car->race.laps <= opponent[i].getCarPtr()->race.laps)) - { + if ((opponent[i].getState() & OPP_FRONT) && + !(0 && opponent[i].isTeamMate() && car->race.laps <= opponent[i].getCarPtr()->race.laps)) + { #if 1 - if (canOvertake(&opponent[i], &mincatchdist, false, (otry == 1))) - o = &opponent[i]; + if (canOvertake(&opponent[i], &mincatchdist, false, (otry == 1))) + o = &opponent[i]; #else - int segid = car->_trkPos.seg->id; - int osegid = opponent[i].getCarPtr()->_trkPos.seg->id; - double distance = opponent[i].getDistance(); - double truespeed = getTrueSpeed(); - double truespeed2 = truespeed + MAX(0.0, 6.0 - fabs(rInverse)*400); - double speed = MIN(truespeed2, MIN(rldata->avspeed, truespeed+MAX(1.0, (((car->_speed_x*car->_speed_x)/100)-distance)/3))); - double ospeed = opponent[i].getTrueSpeed(); - double try_timer = (0.3 + (1.0 - ((simtime-frontavoidtime)/5.0)/2)) * otry; - double sidedist = fabs(car->_trkPos.toMiddle - opponent[i].getCarPtr()->_trkPos.toMiddle); - double spddiff = (speed - ospeed)*1.5; - catchdist = ((double) MIN(speed*distance/(spddiff), distance*CATCH_FACTOR) + (speed * caution)) * (1.0 + try_timer); - double sdiff = ((distance - MAX(0.0, 5.0-sidedist)) - (spddiff)*2); + int segid = car->_trkPos.seg->id; + int osegid = opponent[i].getCarPtr()->_trkPos.seg->id; + double distance = opponent[i].getDistance(); + double truespeed = getTrueSpeed(); + double truespeed2 = truespeed + MAX(0.0, 6.0 - fabs(rInverse)*400); + double speed = MIN(truespeed2, MIN(rldata->avspeed, truespeed+MAX(1.0, (((car->_speed_x*car->_speed_x)/100)-distance)/3))); + double ospeed = opponent[i].getTrueSpeed(); + double try_timer = (0.3 + (1.0 - ((simtime-frontavoidtime)/5.0)/2)) * otry; + double sidedist = fabs(car->_trkPos.toMiddle - opponent[i].getCarPtr()->_trkPos.toMiddle); + double spddiff = (speed - ospeed)*1.5; + catchdist = ((double) MIN(speed*distance/(spddiff), distance*CATCH_FACTOR) + (speed * caution)) * (1.0 + try_timer); + double sdiff = ((distance - MAX(0.0, 5.0-sidedist)) - (spddiff)*2); - if (catchdist < mincatchdist && speed >= ospeed && sdiff < speed/(3+caution)) - { - double aspeed = speed+1.0; - double aspeed2 = aspeed-3.0; - if (truespeed < currentspeed) - speed -= currentspeed - truespeed; - if (rldata->avspeed < currentspeed && car->_accel_x < -2.0 && - ((rInverse > 0.001 && speedangle < 0.0) || - (rInverse < -0.001 && speedangle > 0.0))) - speed -= fabs(speedangle*4); - - if (speed > ospeed) - catchdist = ((double) MIN(speed*distance/(spddiff), distance*CATCH_FACTOR) + (speed * caution)) * (0.6 + try_timer); - else - catchdist = 10000.0; + if (catchdist < mincatchdist && speed >= ospeed && sdiff < speed/(3+caution)) + { + double aspeed = speed+1.0; + double aspeed2 = aspeed-3.0; + if (truespeed < currentspeed) + speed -= currentspeed - truespeed; + if (rldata->avspeed < currentspeed && car->_accel_x < -2.0 && + ((rInverse > 0.001 && speedangle < 0.0) || + (rInverse < -0.001 && speedangle > 0.0))) + speed -= fabs(speedangle*4); + + if (speed > ospeed) + catchdist = ((double) MIN(speed*distance/(spddiff), distance*CATCH_FACTOR) + (speed * caution)) * (0.6 + try_timer); + else + catchdist = 10000.0; - if (catchdist < mincatchdist) // && ((catchdist < MAX(20.0, (distance * 3 + (speed-ospeed)))) || distance + caution < 3.0 + MIN(50.0, car->_speed_x)/15)) - { - - double mradius = MAX(5.0, 100.0 - fabs(rInverse) * 5000); - int odiv = (rldata->thisdiv + int(distance/3)); - double oradius = MAX(5.0, 100.0 - fabs(raceline->getRInverse(odiv)) * 5000); + if (catchdist < mincatchdist) // && ((catchdist < MAX(20.0, (distance * 3 + (speed-ospeed)))) || distance + caution < 3.0 + MIN(50.0, car->_speed_x)/15)) + { + + double mradius = MAX(5.0, 100.0 - fabs(rInverse) * 5000); + int odiv = (rldata->thisdiv + int(distance/3)); + double oradius = MAX(5.0, 100.0 - fabs(raceline->getRInverse(odiv)) * 5000); - if (simtime > 1.0 && - (catchdist < MIN(MIN(500.0, aspeed*7.0), MIN(mradius, oradius)*1.5) && - distance < MAX(3.0, MIN(speed, aspeed2)/4 + (aspeed2-ospeed)) && - ospeed < MAX(10.0, aspeed))) - { + if (simtime > 1.0 && + (catchdist < MIN(MIN(500.0, aspeed*7.0), MIN(mradius, oradius)*1.5) && + distance < MAX(3.0, MIN(speed, aspeed2)/4 + (aspeed2-ospeed)) && + ospeed < MAX(10.0, aspeed))) + { if (DebugMsg & debug_overtake) fprintf(stderr,"%s -> %s (%.1f < %.1f (ot=%.2f))\n",car->_name,ocar->_name,catchdist,mincatchdist,caution);fflush(stderr); - mincatchdist = catchdist; - o = &opponent[i]; - otry_success = otry; - } - } + mincatchdist = catchdist; + o = &opponent[i]; + otry_success = otry; + } + } else if (DebugMsg & debug_overtake) fprintf(stderr,"%s -> %s CANCEL 2 (%.1f > %.1f || %.1f < %.1f || %.3f > %.3f)\n",car->_name,ocar->_name,catchdist,mincatchdist,speed,ospeed,sdiff,speed/(3+caution)); - } + } else if (DebugMsg & debug_overtake) fprintf(stderr,"%s -> %s CANCEL 1 (%.1f > %.1f || %.1f < %.1f || %.3f > %.3f)\n",car->_name,ocar->_name,catchdist,mincatchdist,speed,ospeed,sdiff,speed/(3+caution)); #endif - } - } + } + } - if (o || mode != mode_avoiding) break; - } + if (o || mode != mode_avoiding) break; + } - if (o != NULL) - { - tCarElt *ocar = o->getCarPtr(); + if (o != NULL) + { + tCarElt *ocar = o->getCarPtr(); - // Compute the width around the middle which we can use for overtaking. - //float w = ocar->_trkPos.seg->width/WIDTHDIV-BORDER_OVERTAKE_MARGIN; - // Compute the opponents distance to the middle. - //float otm = ocar->_trkPos.toMiddle; - // Define the with of the middle range. - //float wm = ocar->_trkPos.seg->width*CENTERDIV; - float sidedist = fabs(car->_trkPos.toMiddle-ocar->_trkPos.toMiddle); - //double sdist = (rInverse > 0.0 ? (-sidedist - 3.0) : (sidedist - 3.0)); + // Compute the width around the middle which we can use for overtaking. + //float w = ocar->_trkPos.seg->width/WIDTHDIV-BORDER_OVERTAKE_MARGIN; + // Compute the opponents distance to the middle. + //float otm = ocar->_trkPos.toMiddle; + // Define the with of the middle range. + //float wm = ocar->_trkPos.seg->width*CENTERDIV; + float sidedist = fabs(car->_trkPos.toMiddle-ocar->_trkPos.toMiddle); + //double sdist = (rInverse > 0.0 ? (-sidedist - 3.0) : (sidedist - 3.0)); - //int avoidingside = (otm > wm && myoffset > -w) ? TR_RGT : ((otm < -wm && myoffset < w) ? TR_LFT : TR_STR); - int avoidingside = (car->_trkPos.toLeft > ocar->_trkPos.toLeft ? TR_LFT : TR_RGT); - int mustmove = 0; - int cancelovertake = 0; - double distance = o->getDistance(); + //int avoidingside = (otm > wm && myoffset > -w) ? TR_RGT : ((otm < -wm && myoffset < w) ? TR_LFT : TR_STR); + int avoidingside = (car->_trkPos.toLeft > ocar->_trkPos.toLeft ? TR_LFT : TR_RGT); + int mustmove = 0; + int cancelovertake = 0; + double distance = o->getDistance(); - if (avoidingside != TR_STR) - { - int newside = checkSwitch(avoidingside, o, ocar); + if (avoidingside != TR_STR) + { + int newside = checkSwitch(avoidingside, o, ocar); if (DebugMsg & debug_overtake) fprintf(stderr," AVOIDING A %c\n",(avoidingside==TR_LFT?'L':'R')); - if (newside != avoidingside) - { + if (newside != avoidingside) + { if (DebugMsg & debug_overtake) fprintf(stderr," SWITCH 1 from %c to %c\n",(avoidingside==TR_LFT?'L':'R'),(newside==TR_LFT?'L':'R')); - avoidingside = newside; - mustmove = 1; - } + avoidingside = newside; + mustmove = 1; + } - if ((((avoidingside == prefer_side && prefer_side != TR_STR) || (avoidingside == car->_trkPos.seg->type)) && distance > 1.0) || - rldata->braking <= 0.0) - { + if ((((avoidingside == prefer_side && prefer_side != TR_STR) || (avoidingside == car->_trkPos.seg->type)) && distance > 1.0) || + rldata->braking <= 0.0) + { #if 1 - if (!(canOvertake(o, &mincatchdist, true, false))) - { + if (!(canOvertake(o, &mincatchdist, true, false))) + { if (DebugMsg & debug_overtake) fprintf(stderr," CANCEL :(\n"); - cancelovertake = 1; - } + cancelovertake = 1; + } #else - if ((rInverse > 0.0 && angle > 0.0) || (rInverse < 0.0 && angle < 0.0)) - caution += fabs(speedangle-angle) * 20; + if ((rInverse > 0.0 && angle > 0.0) || (rInverse < 0.0 && angle < 0.0)) + caution += fabs(speedangle-angle) * 20; - double cdistance = o->getDistance() + (fabs(rInverse)*700); - double truespeed = getTrueSpeed(); - double truespeed2 = truespeed + MAX(0.0, 6.0 - fabs(rInverse)*700); - //double speed = MIN(truespeed2, MIN(rldata->avspeed, truespeed+MAX(1.0, cdistance+1.0))); - double speed = MIN(truespeed2, MIN(rldata->avspeed, truespeed+MAX(1.0, (((car->_speed_x*car->_speed_x)/100)-cdistance)/4))); - double ospeed = o->getTrueSpeed() * (1.0 + fabs(rInverse)*50); - catchdist = ((double) MIN(speed*cdistance/(speed-ospeed), cdistance*CATCH_FACTOR) + (speed * caution)) * (1.0 + fabs(rInverse)*120); - //double sdiff = ((distance + MAX(0.0, 10.0-sdist*2)) - (speed - ospeed)*2); - double sdiff = (sdist*3+(speed-ospeed)) - distance * (1.0 + fabs(rInverse*80)); + double cdistance = o->getDistance() + (fabs(rInverse)*700); + double truespeed = getTrueSpeed(); + double truespeed2 = truespeed + MAX(0.0, 6.0 - fabs(rInverse)*700); + //double speed = MIN(truespeed2, MIN(rldata->avspeed, truespeed+MAX(1.0, cdistance+1.0))); + double speed = MIN(truespeed2, MIN(rldata->avspeed, truespeed+MAX(1.0, (((car->_speed_x*car->_speed_x)/100)-cdistance)/4))); + double ospeed = o->getTrueSpeed() * (1.0 + fabs(rInverse)*50); + catchdist = ((double) MIN(speed*cdistance/(speed-ospeed), cdistance*CATCH_FACTOR) + (speed * caution)) * (1.0 + fabs(rInverse)*120); + //double sdiff = ((distance + MAX(0.0, 10.0-sdist*2)) - (speed - ospeed)*2); + double sdiff = (sdist*3+(speed-ospeed)) - distance * (1.0 + fabs(rInverse*80)); - if ((catchdist > MAX(20.0 + sdist*2, (cdistance * 3 + (speed-ospeed)))) || sdiff < 0.0) - { - cancelovertake = 1; - avoidmode = 0; + if ((catchdist > MAX(20.0 + sdist*2, (cdistance * 3 + (speed-ospeed)))) || sdiff < 0.0) + { + cancelovertake = 1; + avoidmode = 0; if (DebugMsg & debug_overtake) fprintf(stderr,"%s -> %s CANCEL 3 (%.1f < %.1f)\n",car->_name,ocar->_name,catchdist,mincatchdist);fflush(stderr); - } + } #endif - } - } + } + } - if (!cancelovertake) - { - if (avoidingside == TR_LFT) - { - sidedist -= (speedangle - o->getSpeedAngle()) * 20; - if (mustmove || - sidedist < car->_dimension_y + ocar->_dimension_y + 2.0 || - (o->getState() & OPP_COLL) || - (prefer_side == TR_RGT && car->_trkPos.toRight > MIN(lane2right, 3.0 - nextCRinverse*1000))) - { - double rinc = OVERTAKE_OFFSET_INC * rgtinc; - if (rInverse > 0.0) - rinc += rInverse * 200 * IncFactor; - myoffset -= (float) rinc; + if (!cancelovertake) + { + if (avoidingside == TR_LFT) + { + sidedist -= (speedangle - o->getSpeedAngle()) * 20; + if (mustmove || + sidedist < car->_dimension_y + ocar->_dimension_y + 2.0 || + (o->getState() & OPP_COLL) || + (prefer_side == TR_RGT && car->_trkPos.toRight > MIN(lane2right, 3.0 - nextCRinverse*1000))) + { + double rinc = OVERTAKE_OFFSET_INC * rgtinc; + if (rInverse > 0.0) + rinc += rInverse * 200 * IncFactor; + myoffset -= (float) rinc; if (DebugMsg & debug_overtake) fprintf(stderr,"%s LFT %s, MOVING RIGHT %.3f/%.3f -> %.3f (rgtinc=%.2f (%.2f) rinc=%.2f)\n",car->_name,ocar->_name,(float) (OVERTAKE_OFFSET_INC*rgtinc),rinc,myoffset,rgtinc,lftinc,rinc); - avoidmovt = 1; - } - else if (sidedist > car->_dimension_y + ocar->_dimension_y + 4.0 && - car->_trkPos.toRight < MIN(lane2right-1.0, 4.0 + fabs(nextCRinverse)*1000)) - { + avoidmovt = 1; + } + else if (sidedist > car->_dimension_y + ocar->_dimension_y + 4.0 && + car->_trkPos.toRight < MIN(lane2right-1.0, 4.0 + fabs(nextCRinverse)*1000)) + { if (DebugMsg & debug_overtake) fprintf(stderr,"%s LFT %s, MOVING BACK TO LEFT %.3f\n",car->_name,ocar->_name,(float) (OVERTAKE_OFFSET_INC*lftinc/2)); - myoffset += (float) (OVERTAKE_OFFSET_INC*lftinc)/2; - if (!avoidmode) - avoidtime = MIN(simtime, avoidtime+deltaTime); - } + myoffset += (float) (OVERTAKE_OFFSET_INC*lftinc)/2; + if (!avoidmode) + avoidtime = MIN(simtime, avoidtime+deltaTime); + } else if (DebugMsg & debug_overtake) fprintf(stderr,"%s LFT %s, HOLDING LINE\n",car->_name,ocar->_name); - } - else if (avoidingside == TR_RGT) - { - sidedist -= (o->getSpeedAngle() - speedangle) * 20; - if (mustmove || - sidedist < car->_dimension_y + ocar->_dimension_y + 2.0 || - (o->getState() & OPP_COLL) || - (prefer_side == TR_LFT && car->_trkPos.toLeft > MIN(lane2left, 3.0 + nextCRinverse*1000))) - { + } + else if (avoidingside == TR_RGT) + { + sidedist -= (o->getSpeedAngle() - speedangle) * 20; + if (mustmove || + sidedist < car->_dimension_y + ocar->_dimension_y + 2.0 || + (o->getState() & OPP_COLL) || + (prefer_side == TR_LFT && car->_trkPos.toLeft > MIN(lane2left, 3.0 + nextCRinverse*1000))) + { if (DebugMsg & debug_overtake) fprintf(stderr,"%s RGT %s, MOVING LEFT %.3f\n",car->_name,ocar->_name,(float) (OVERTAKE_OFFSET_INC*lftinc)); - double linc = OVERTAKE_OFFSET_INC * lftinc; - if (rInverse < 0.0) - linc -= rInverse * 200 * IncFactor; - myoffset += (float) linc; - avoidmovt = 1; - } - else if (sidedist > car->_dimension_y + ocar->_dimension_y + 4.0 && - car->_trkPos.toLeft < MIN(lane2left-1.0, 4.0 + fabs(nextCRinverse)*1000)) - { + double linc = OVERTAKE_OFFSET_INC * lftinc; + if (rInverse < 0.0) + linc -= rInverse * 200 * IncFactor; + myoffset += (float) linc; + avoidmovt = 1; + } + else if (sidedist > car->_dimension_y + ocar->_dimension_y + 4.0 && + car->_trkPos.toLeft < MIN(lane2left-1.0, 4.0 + fabs(nextCRinverse)*1000)) + { if (DebugMsg & debug_overtake) fprintf(stderr,"%s RGT %s, MOVING BACK TO RIGHT %.3f\n",car->_name,ocar->_name,(float) (OVERTAKE_OFFSET_INC*rgtinc/2)); - myoffset -= (float) (OVERTAKE_OFFSET_INC*rgtinc)/2; - if (!avoidmode) - avoidtime = MIN(simtime, avoidtime+deltaTime); - } + myoffset -= (float) (OVERTAKE_OFFSET_INC*rgtinc)/2; + if (!avoidmode) + avoidtime = MIN(simtime, avoidtime+deltaTime); + } else if (DebugMsg & debug_overtake) fprintf(stderr,"%s RGT %s, HOLDING LINE\n",car->_name,ocar->_name); - } - else - { - // If the opponent is near the middle we try to move the offset toward - // the inside of the expected turn. - // Try to find out the characteristic of the track up to catchdist. - tTrackSeg *seg = car->_trkPos.seg; - float length = getDistToSegEnd(); - float oldlen, seglen = length; - float lenright = 0.0f, lenleft = 0.0f; - mincatchdist = MIN(mincatchdist, DISTCUTOFF); + } + else + { + // If the opponent is near the middle we try to move the offset toward + // the inside of the expected turn. + // Try to find out the characteristic of the track up to catchdist. + tTrackSeg *seg = car->_trkPos.seg; + float length = getDistToSegEnd(); + float oldlen, seglen = length; + float lenright = 0.0f, lenleft = 0.0f; + mincatchdist = MIN(mincatchdist, DISTCUTOFF); - do { - switch (seg->type) { - case TR_LFT: - lenleft += seglen; - break; - case TR_RGT: - lenright += seglen; - break; - default: - // Do nothing. - break; - } - seg = seg->next; - seglen = seg->length; - oldlen = length; - length += seglen; - } while (oldlen < mincatchdist); + do { + switch (seg->type) { + case TR_LFT: + lenleft += seglen; + break; + case TR_RGT: + lenright += seglen; + break; + default: + // Do nothing. + break; + } + seg = seg->next; + seglen = seg->length; + oldlen = length; + length += seglen; + } while (oldlen < mincatchdist); - if (lenleft > lenright) - avoidingside = TR_RGT; - else if (lenright > lenleft) - avoidingside = TR_LFT; + if (lenleft > lenright) + avoidingside = TR_RGT; + else if (lenright > lenleft) + avoidingside = TR_LFT; - // If we are on a straight look for the next turn. - if (avoidingside == TR_STR) - { - while (seg->type == TR_STR) { - seg = seg->next; - } - // Assume: left or right if not straight. - if (seg->type == TR_LFT) { - avoidingside = TR_RGT; - } else { - avoidingside = TR_LFT; - } - } + // If we are on a straight look for the next turn. + if (avoidingside == TR_STR) + { + while (seg->type == TR_STR) { + seg = seg->next; + } + // Assume: left or right if not straight. + if (seg->type == TR_LFT) { + avoidingside = TR_RGT; + } else { + avoidingside = TR_LFT; + } + } - // Because we are inside we can go to the border. - //float maxoff = (float) ((ocar->_trkPos.seg->width - car->_dimension_y)/2.0f-BORDER_OVERTAKE_MARGIN*15); - int newside = checkSwitch( avoidingside, o, ocar ); + // Because we are inside we can go to the border. + //float maxoff = (float) ((ocar->_trkPos.seg->width - car->_dimension_y)/2.0f-BORDER_OVERTAKE_MARGIN*15); + int newside = checkSwitch( avoidingside, o, ocar ); if (DebugMsg & debug_overtake) fprintf(stderr," AVOIDING %c\n",(avoidingside==TR_LFT?'l':'r')); - if (newside != avoidingside) - { + if (newside != avoidingside) + { if (DebugMsg & debug_overtake) fprintf(stderr," SWITCH 2 from %c to %c\n",(avoidingside==TR_LFT?'l':'r'),(newside==TR_LFT?'l':'r')); - avoidingside = newside; - mustmove = 1; - } + avoidingside = newside; + mustmove = 1; + } - if (prefer_side != TR_STR && avoidingside == prefer_side) - { + if (prefer_side != TR_STR && avoidingside == prefer_side) + { #if 1 - if (!(canOvertake(o, &mincatchdist, true, false))) - cancelovertake = 1; + if (!(canOvertake(o, &mincatchdist, true, false))) + cancelovertake = 1; #else - double cdistance = o->getDistance() + (fabs(rInverse)*700); - double truespeed = getTrueSpeed(); - double truespeed2 = truespeed + MAX(0.0, 6.0 - fabs(rInverse)*700); - //double speed = MIN(truespeed2, MIN(rldata->avspeed, truespeed+MAX(1.0, cdistance+1.0))); - double speed = MIN(truespeed2, MIN(rldata->avspeed, truespeed+MAX(1.0, (((car->_speed_x*car->_speed_x)/100)-cdistance)/4))); - double ospeed = o->getTrueSpeed() * (1.0 + fabs(rInverse)*50); - catchdist = ((double) MIN(speed*cdistance/(speed-ospeed), cdistance*CATCH_FACTOR) + (speed * caution)) * (1.0 + fabs(rInverse)*120); - double sdiff = (sdist*3+(speed-ospeed)) - distance * (1.0 + fabs(rInverse*80)); - - if ((catchdist > MAX(20.0 + sdist*2, (cdistance * 3 + (speed-ospeed)))) || sdiff < 0.0) - { + double cdistance = o->getDistance() + (fabs(rInverse)*700); + double truespeed = getTrueSpeed(); + double truespeed2 = truespeed + MAX(0.0, 6.0 - fabs(rInverse)*700); + //double speed = MIN(truespeed2, MIN(rldata->avspeed, truespeed+MAX(1.0, cdistance+1.0))); + double speed = MIN(truespeed2, MIN(rldata->avspeed, truespeed+MAX(1.0, (((car->_speed_x*car->_speed_x)/100)-cdistance)/4))); + double ospeed = o->getTrueSpeed() * (1.0 + fabs(rInverse)*50); + catchdist = ((double) MIN(speed*cdistance/(speed-ospeed), cdistance*CATCH_FACTOR) + (speed * caution)) * (1.0 + fabs(rInverse)*120); + double sdiff = (sdist*3+(speed-ospeed)) - distance * (1.0 + fabs(rInverse*80)); + + if ((catchdist > MAX(20.0 + sdist*2, (cdistance * 3 + (speed-ospeed)))) || sdiff < 0.0) + { if (DebugMsg & debug_overtake) fprintf(stderr,"%s -> %s CANCEL 4 (%.1f < %.1f)\n",car->_name,ocar->_name,catchdist,mincatchdist);fflush(stderr); - cancelovertake = 1; - } + cancelovertake = 1; + } #endif - } + } - if (!cancelovertake) - { - if (mustmove || (o->getState() & OPP_COLL) || sidedist < car->_dimension_y + ocar->_dimension_y + 1.0) - { - if (avoidingside == TR_RGT) - { - sidedist -= (o->getSpeedAngle() - speedangle) * 20; - if (myoffset < maxoffset || - (prefer_side == TR_LFT && car->_trkPos.toLeft > 3.0 + nextCRinverse*1000)) - { + if (!cancelovertake) + { + if (mustmove || (o->getState() & OPP_COLL) || sidedist < car->_dimension_y + ocar->_dimension_y + 1.0) + { + if (avoidingside == TR_RGT) + { + sidedist -= (o->getSpeedAngle() - speedangle) * 20; + if (myoffset < maxoffset || + (prefer_side == TR_LFT && car->_trkPos.toLeft > 3.0 + nextCRinverse*1000)) + { if (DebugMsg & debug_overtake) fprintf(stderr,"%s RGT %s, MOVING LEFT %.3f\n",car->_name,ocar->_name,(float) (OVERTAKE_OFFSET_INC*lftinc)); - myoffset += (float) (OVERTAKE_OFFSET_INC*lftinc); - avoidmovt = 1; - } - else if (sidedist > car->_dimension_y + ocar->_dimension_y + 4.0 && - car->_trkPos.toLeft < 4.0 + fabs(nextCRinverse)*1000) - { + myoffset += (float) (OVERTAKE_OFFSET_INC*lftinc); + avoidmovt = 1; + } + else if (sidedist > car->_dimension_y + ocar->_dimension_y + 4.0 && + car->_trkPos.toLeft < 4.0 + fabs(nextCRinverse)*1000) + { if (DebugMsg & debug_overtake) fprintf(stderr,"%s RGT %s, MOVING BACK TO RIGHT %.3f\n",car->_name,ocar->_name,(float) (OVERTAKE_OFFSET_INC*rgtinc)/2); - myoffset -= (float) (OVERTAKE_OFFSET_INC*rgtinc)/2; - if (!avoidmode) - avoidtime = MIN(simtime, avoidtime+deltaTime); - } + myoffset -= (float) (OVERTAKE_OFFSET_INC*rgtinc)/2; + if (!avoidmode) + avoidtime = MIN(simtime, avoidtime+deltaTime); + } else if (DebugMsg & debug_overtake) fprintf(stderr,"%s RGT %s, NO MOVEMENT\n",car->_name,ocar->_name); - } - else - { - sidedist -= (speedangle - o->getSpeedAngle()) * 20; - if (myoffset > minoffset || - (prefer_side == TR_RGT && car->_trkPos.toRight > 3.0 - nextCRinverse*1000)) - { + } + else + { + sidedist -= (speedangle - o->getSpeedAngle()) * 20; + if (myoffset > minoffset || + (prefer_side == TR_RGT && car->_trkPos.toRight > 3.0 - nextCRinverse*1000)) + { if (DebugMsg & debug_overtake) fprintf(stderr,"%s LFT %s, MOVING RIGHT %.3f -> %.3f\n",car->_name,ocar->_name,(float) (OVERTAKE_OFFSET_INC*rgtinc),myoffset); - myoffset -= (float) (OVERTAKE_OFFSET_INC*rgtinc); - avoidmovt = 1; - } - else if (sidedist > car->_dimension_y + ocar->_dimension_y + 4.0 && - car->_trkPos.toRight < 4.0 + fabs(nextCRinverse)*1000) - { + myoffset -= (float) (OVERTAKE_OFFSET_INC*rgtinc); + avoidmovt = 1; + } + else if (sidedist > car->_dimension_y + ocar->_dimension_y + 4.0 && + car->_trkPos.toRight < 4.0 + fabs(nextCRinverse)*1000) + { if (DebugMsg & debug_overtake) fprintf(stderr,"%s LFT %s, MOVING BACK TO LEFT %.3f\n",car->_name,ocar->_name,(float) (OVERTAKE_OFFSET_INC*lftinc)/2); - myoffset += (float) (OVERTAKE_OFFSET_INC*lftinc)/2; - if (!avoidmode) - avoidtime = MIN(simtime, avoidtime+deltaTime); - } + myoffset += (float) (OVERTAKE_OFFSET_INC*lftinc)/2; + if (!avoidmode) + avoidtime = MIN(simtime, avoidtime+deltaTime); + } else if (DebugMsg & debug_overtake) fprintf(stderr,"%s LFT %s, NO MOVEMENT\n",car->_name,ocar->_name); - } - } - } - } + } + } + } + } - if (!cancelovertake) - { - //if (ocar->_trkPos.toLeft > car->_trkPos.toLeft) - if (avoidingside == TR_RGT) - { - avoidrgtoffset = (float) MAX(avoidrgtoffset, ocar->_trkPos.toMiddle + (o->getWidth()+1.0f)); - avoidmode |= avoidright; - } - else - { - avoidlftoffset = (float) MIN(avoidlftoffset, ocar->_trkPos.toMiddle - (o->getWidth()+1.0f)); - avoidmode |= avoidleft; - } - - if ((avoidingside == TR_LFT && rInverse > 0.0) || - (avoidingside == TR_RGT && rInverse < 0.0)) - avoidtime = MIN(simtime, avoidtime + MIN(deltaTime*0.9, fabs(rInverse*1.2))); + if (!cancelovertake) + { + //if (ocar->_trkPos.toLeft > car->_trkPos.toLeft) + if (avoidingside == TR_RGT) + { + avoidrgtoffset = (float) MAX(avoidrgtoffset, ocar->_trkPos.toMiddle + (o->getWidth()+1.0f)); + avoidmode |= avoidright; + } + else + { + avoidlftoffset = (float) MIN(avoidlftoffset, ocar->_trkPos.toMiddle - (o->getWidth()+1.0f)); + avoidmode |= avoidleft; + } + + if ((avoidingside == TR_LFT && rInverse > 0.0) || + (avoidingside == TR_RGT && rInverse < 0.0)) + avoidtime = MIN(simtime, avoidtime + MIN(deltaTime*0.9, fabs(rInverse*1.2))); - myoffset = (float) (MAX(minoffset, MIN(maxoffset, myoffset))); + myoffset = (float) (MAX(minoffset, MIN(maxoffset, myoffset))); - if (!otry_success) - frontavoidtime = simtime; - } - } - } + if (!otry_success) + frontavoidtime = simtime; + } + } + } - if (!avoidmode) - { - o = NULL; + if (!avoidmode) + { + o = NULL; - // Let overlap or let less damaged team mate pass. - for (i = 0; i < opponents->getNOpponents(); i++) - { - // Let the teammate with less damage overtake to use slipstreaming. - // The position change happens when the damage difference is greater than - // TEAM_DAMAGE_CHANGE_LEAD. - if ((opponent[i].getState() & OPP_LETPASS)) - { - // Behind, larger distances are smaller ("more negative"). - if (opponent[i].getDistance() > mindist) { - mindist = opponent[i].getDistance(); - o = &opponent[i]; - } - } - } + // Let overlap or let less damaged team mate pass. + for (i = 0; i < opponents->getNOpponents(); i++) + { + // Let the teammate with less damage overtake to use slipstreaming. + // The position change happens when the damage difference is greater than + // TEAM_DAMAGE_CHANGE_LEAD. + if ((opponent[i].getState() & OPP_LETPASS)) + { + // Behind, larger distances are smaller ("more negative"). + if (opponent[i].getDistance() > mindist) { + mindist = opponent[i].getDistance(); + o = &opponent[i]; + } + } + } - if (o != NULL) - { - tCarElt *ocar = o->getCarPtr(); - float side = car->_trkPos.toMiddle - ocar->_trkPos.toMiddle; - float w = car->_trkPos.seg->width/WIDTHDIV-BORDER_OVERTAKE_MARGIN; + if (o != NULL) + { + tCarElt *ocar = o->getCarPtr(); + float side = car->_trkPos.toMiddle - ocar->_trkPos.toMiddle; + float w = car->_trkPos.seg->width/WIDTHDIV-BORDER_OVERTAKE_MARGIN; if (DebugMsg & debug_overtake) fprintf(stderr,"%s BEHIND %s (%d %d %d %d)\n",car->_name,ocar->_name,((o->getState() & OPP_LETPASS) && !o->isTeamMate()),(o->isTeamMate() && (car->_dammage - o->getDamage() > TEAM_DAMAGE_CHANGE_LEAD)),((o->getDistance() > -TEAM_REAR_DIST) && (o->getDistance() < -car->_dimension_x)),(car->race.laps == o->getCarPtr()->race.laps)); - if (side > 0.0f) { - if (myoffset < w) { - myoffset += (float) (OVERTAKE_OFFSET_INC*lftinc); - avoidmovt = 1; - } - } else { - if (myoffset > -w) { - myoffset -= (float) (OVERTAKE_OFFSET_INC*rgtinc); - avoidmovt = 1; - } - } + if (side > 0.0f) { + if (myoffset < w) { + myoffset += (float) (OVERTAKE_OFFSET_INC*lftinc); + avoidmovt = 1; + } + } else { + if (myoffset > -w) { + myoffset -= (float) (OVERTAKE_OFFSET_INC*rgtinc); + avoidmovt = 1; + } + } - avoidmode |= avoidback; + avoidmode |= avoidback; - if (ocar->_trkPos.toLeft > car->_trkPos.toLeft) - { - avoidrgtoffset = (float) MAX(avoidrgtoffset, ocar->_trkPos.toMiddle + (o->getWidth()+1.0f)); - avoidmode |= avoidright; - } - else - { - avoidlftoffset = (float) MIN(avoidlftoffset, ocar->_trkPos.toMiddle - (o->getWidth()+1.0f)); - avoidmode |= avoidleft; - } - - myoffset = (float) (MAX(minoffset, MIN(maxoffset, myoffset))); - } - } - } + if (ocar->_trkPos.toLeft > car->_trkPos.toLeft) + { + avoidrgtoffset = (float) MAX(avoidrgtoffset, ocar->_trkPos.toMiddle + (o->getWidth()+1.0f)); + avoidmode |= avoidright; + } + else + { + avoidlftoffset = (float) MIN(avoidlftoffset, ocar->_trkPos.toMiddle - (o->getWidth()+1.0f)); + avoidmode |= avoidleft; + } + + myoffset = (float) (MAX(minoffset, MIN(maxoffset, myoffset))); + } + } + } - if (mode == mode_avoiding && avoidmode == 0) - setMode(mode_correcting); - if (mode == mode_normal) - myoffset = (float) moffset; + if (mode == mode_avoiding && avoidmode == 0) + setMode(mode_correcting); + if (mode == mode_normal) + myoffset = (float) moffset; #if 1 - // no-one to avoid, work back towards raceline - if (mode == mode_correcting && (simtime > 15.0 || car->_speed_x > 20) && simtime > CorrectDelay) - { - double factor = 0.25;//(fabs(car->_trkPos.toMiddle) < car->_trkPos.seg->width/2 + 2.0 ? 0.25 : 1.0); - if (fabs(myoffset) > fabs(rldata->offset)) - { - //double inc = OVERTAKE_OFFSET_INC * MIN(lftinc, rgtinc) * factor; - if (myoffset < rldata->offset && myoffset < 2.0) - myoffset += (float) (MIN(rldata->offset-myoffset, OVERTAKE_OFFSET_INC * rgtinc/3 * factor)); - else if (myoffset > rldata->offset && myoffset > 2.0) - myoffset -= (float) (MIN(myoffset-rldata->offset, OVERTAKE_OFFSET_INC * lftinc/3 * factor)); - } + // no-one to avoid, work back towards raceline + if (mode == mode_correcting && (simtime > 15.0 || car->_speed_x > 20) && simtime > CorrectDelay) + { + double factor = 0.25;//(fabs(car->_trkPos.toMiddle) < car->_trkPos.seg->width/2 + 2.0 ? 0.25 : 1.0); + if (fabs(myoffset) > fabs(rldata->offset)) + { + //double inc = OVERTAKE_OFFSET_INC * MIN(lftinc, rgtinc) * factor; + if (myoffset < rldata->offset && myoffset < 2.0) + myoffset += (float) (MIN(rldata->offset-myoffset, OVERTAKE_OFFSET_INC * rgtinc/3 * factor)); + else if (myoffset > rldata->offset && myoffset > 2.0) + myoffset -= (float) (MIN(myoffset-rldata->offset, OVERTAKE_OFFSET_INC * lftinc/3 * factor)); + } - maxoffset = MIN(moffset+OVERTAKE_OFFSET_INC*lftinc/2, Width/2 - (car->_dimension_y+SideMargin)); - minoffset = MAX(moffset-OVERTAKE_OFFSET_INC*rgtinc/2, -(Width/2 - (car->_dimension_y+SideMargin))); - } + maxoffset = MIN(moffset+OVERTAKE_OFFSET_INC*lftinc/2, Width/2 - (car->_dimension_y+SideMargin)); + minoffset = MAX(moffset-OVERTAKE_OFFSET_INC*rgtinc/2, -(Width/2 - (car->_dimension_y+SideMargin))); + } #endif end_getoffset: - if (avoidmode) - setMode(mode_avoiding); + if (avoidmode) + setMode(mode_avoiding); - if (mode == mode_avoiding && !avoidmovt) - avoidtime = MIN(simtime, avoidtime+deltaTime*1.5); + if (mode == mode_avoiding && !avoidmovt) + avoidtime = MIN(simtime, avoidtime+deltaTime*1.5); -// minoffset = MAX(minoffset, MIN(1.5, rldata->offset)); -// maxoffset = MIN(maxoffset, MAX(track->width - 1.5, rldata->offset)); - { - double mo = myoffset; - myoffset = (float) (MAX(minoffset, MIN(maxoffset, myoffset))); - if (DebugMsg & debug_overtake) - if (mode != mode_normal) - { - fprintf(stderr,"mode=%d max=%.1f(%.1f) min=%.1f(%.1f) myoff=%.1f->%.1f->%.1f\n",mode,maxoffset,oldmax,minoffset,oldmin,car->_trkPos.toMiddle,mo,myoffset); - fflush(stderr); - } - } - return myoffset; +// minoffset = MAX(minoffset, MIN(1.5, rldata->offset)); +// maxoffset = MIN(maxoffset, MAX(track->width - 1.5, rldata->offset)); + { + double mo = myoffset; + myoffset = (float) (MAX(minoffset, MIN(maxoffset, myoffset))); + if (DebugMsg & debug_overtake) + if (mode != mode_normal) + { + fprintf(stderr,"mode=%d max=%.1f(%.1f) min=%.1f(%.1f) myoff=%.1f->%.1f->%.1f\n",mode,maxoffset,oldmax,minoffset,oldmin,car->_trkPos.toMiddle,mo,myoffset); + fflush(stderr); + } + } + return myoffset; } int Driver::checkSwitch( int side, Opponent *o, tCarElt *ocar ) { - double xdist = o->getDistance(); - double t_impact = MAX(0.0, MIN(10.0, o->getTimeImpact())); - if (car->_speed_x - ocar->_speed_x < MIN(5.0, xdist*3)) - t_impact *= (1.0 + (5.0 - (car->_speed_x - ocar->_speed_x))); - t_impact = MIN(3.0, MIN(t_impact, (5.0-(xdist-fabs(rldata->mInverse*1000)))/10)); + double xdist = o->getDistance(); + double t_impact = MAX(0.0, MIN(10.0, o->getTimeImpact())); + if (car->_speed_x - ocar->_speed_x < MIN(5.0, xdist*3)) + t_impact *= (1.0 + (5.0 - (car->_speed_x - ocar->_speed_x))); + t_impact = MIN(3.0, MIN(t_impact, (5.0-(xdist-fabs(rldata->mInverse*1000)))/10)); - double mcatchleft = MAX(1.0, MIN(track->width-1.0, car->_trkPos.toLeft - speedangle * (t_impact * 10))); - double ocatchleft = MAX(1.0, MIN(track->width-1.0, ocar->_trkPos.toLeft - o->getSpeedAngle() * (t_impact * 10))); - double ydist = mcatchleft-ocatchleft; - double sdiff = MAX(0.0, currentspeed - o->getSpeed()); - double radius = MIN(car->_dimension_y*3, fabs(nextCRinverse) * 200); - double speedchange = 0.0; + double mcatchleft = MAX(1.0, MIN(track->width-1.0, car->_trkPos.toLeft - speedangle * (t_impact * 10))); + double ocatchleft = MAX(1.0, MIN(track->width-1.0, ocar->_trkPos.toLeft - o->getSpeedAngle() * (t_impact * 10))); + double ydist = mcatchleft-ocatchleft; + double sdiff = MAX(0.0, currentspeed - o->getSpeed()); + double radius = MIN(car->_dimension_y*3, fabs(nextCRinverse) * 200); + double speedchange = 0.0; - if (prefer_side == side && rldata->speedchange < 0.0 && ocar->_pos > car->_pos) - speedchange = fabs(rldata->speedchange)*3; + if (prefer_side == side && rldata->speedchange < 0.0 && ocar->_pos > car->_pos) + speedchange = fabs(rldata->speedchange)*3; #if 0 - if (fabs(mcatchleft - ocatchleft) < car->_dimension_y + 1.5 + radius && - (fabs(mcatchleft - ocatchleft) < fabs(car->_trkPos.toLeft - ocar->_trkPos.toLeft) || - (side == TR_LFT && ocatchleft > car->_trkPos.seg->width - car->_dimension_y + 1.5 + radius) || - (side == TR_RGT && ocatchleft < car->_dimension_y + 1.5 + radius))) + if (fabs(mcatchleft - ocatchleft) < car->_dimension_y + 1.5 + radius && + (fabs(mcatchleft - ocatchleft) < fabs(car->_trkPos.toLeft - ocar->_trkPos.toLeft) || + (side == TR_LFT && ocatchleft > car->_trkPos.seg->width - car->_dimension_y + 1.5 + radius) || + (side == TR_RGT && ocatchleft < car->_dimension_y + 1.5 + radius))) #endif - { - double switchrad = 1.0 + (side == prefer_side ? radius * 4 : 0); + { + double switchrad = 1.0 + (side == prefer_side ? radius * 4 : 0); - switch (side) - { - case TR_RGT: + switch (side) + { + case TR_RGT: if (DebugMsg & debug_overtake) fprintf(stderr,"CHECKSWITCH: Rgt - ti=%.2f dm=%.1f o=%.2f->%.2f m=%.2f->%.2f\n",t_impact,deltamult,ocar->_trkPos.toLeft,ocatchleft,car->_trkPos.toLeft,mcatchleft); - if (nextCRinverse > 0.0) - radius = 0.0; - if ((side == prefer_side || - ocatchleft < (car->_dimension_y + 3.0 + radius + speedchange) * switchrad || - ocatchleft < (mcatchleft - 1.5) * switchrad) && - xdist > sdiff + ydist + MAX(0.0, angle*10) && - track->width - ocatchleft > (car->_dimension_y + 3.0 + radius + speedchange)) - { + if (nextCRinverse > 0.0) + radius = 0.0; + if ((side == prefer_side || + ocatchleft < (car->_dimension_y + 3.0 + radius + speedchange) * switchrad || + ocatchleft < (mcatchleft - 1.5) * switchrad) && + xdist > sdiff + ydist + MAX(0.0, angle*10) && + track->width - ocatchleft > (car->_dimension_y + 3.0 + radius + speedchange)) + { if (DebugMsg & debug_overtake) fprintf(stderr," Switch to his right (side=lft) - %d %d %d %d\n",(side==prefer_side),(ocatchleftsdiff+ydist+MAX(0.0, angle*10)),(track->width-ocatchleft>(car->_dimension_y+3+radius+speedchange))); - side = TR_LFT; - } - break; + side = TR_LFT; + } + break; - case TR_LFT: - default: + case TR_LFT: + default: if (DebugMsg & debug_overtake) fprintf(stderr,"CHECKSWITCH: Lft - ti=%.2f dm=%.1f o=%.2f->%.2f m=%.2f->%.2f\n",t_impact,deltamult,ocar->_trkPos.toLeft,ocatchleft,car->_trkPos.toLeft,mcatchleft); - if (nextCRinverse < 0.0) - radius = 0.0; - if ((side == prefer_side || - track->width-ocatchleft < (car->_dimension_y + 3.0 + radius + speedchange) * switchrad || - ocatchleft > (mcatchleft + 1.5) * switchrad) && - xdist > sdiff + (-ydist) + MAX(0.0, -angle*10) && - ocatchleft > (car->_dimension_y + 3.0 + radius + speedchange)) - { - side = TR_RGT; - } - break; - } - } + if (nextCRinverse < 0.0) + radius = 0.0; + if ((side == prefer_side || + track->width-ocatchleft < (car->_dimension_y + 3.0 + radius + speedchange) * switchrad || + ocatchleft > (mcatchleft + 1.5) * switchrad) && + xdist > sdiff + (-ydist) + MAX(0.0, -angle*10) && + ocatchleft > (car->_dimension_y + 3.0 + radius + speedchange)) + { + side = TR_RGT; + } + break; + } + } - return side; + return side; } // Update my private data every timestep. void Driver::update(tSituation *s) { - // Update global car data (shared by all instances) just once per timestep. - if (simtime != s->currentTime) { - simtime = s->currentTime; - cardata->update(); - mycardata->updateWalls(); - } - else - { - // always update my car - mycardata->update(); - mycardata->updateWalls(); + // Update global car data (shared by all instances) just once per timestep. + if (simtime != s->currentTime) { + simtime = s->currentTime; + cardata->update(); + mycardata->updateWalls(); + } + else + { + // always update my car + mycardata->update(); + mycardata->updateWalls(); - int nCars = cardata->getNCars(); + int nCars = cardata->getNCars(); - for (int i = 0; i < nCars; i++) - { - // update cars that are close to ours - SingleCardata *cdata = cardata->getCarData(i); - double mdist = car->_distFromStartLine; - double odist = (double) cdata->getDistFromStart(); + for (int i = 0; i < nCars; i++) + { + // update cars that are close to ours + SingleCardata *cdata = cardata->getCarData(i); + double mdist = car->_distFromStartLine; + double odist = (double) cdata->getDistFromStart(); - if (odist > track->length - 30 && mdist < 30) - mdist += track->length; - else if (mdist > track->length - 30 && odist < 30) - odist += track->length; + if (odist > track->length - 30 && mdist < 30) + mdist += track->length; + else if (mdist > track->length - 30 && odist < 30) + odist += track->length; - double dist = fabs(mdist - odist); - if (dist < 60.0) - cdata->update(); - } - } + double dist = fabs(mdist - odist); + if (dist < 60.0) + cdata->update(); + } + } - evalTrueSpeed(); + evalTrueSpeed(); - prefer_side = raceline->findNextCorner( &nextCRinverse ); + prefer_side = raceline->findNextCorner( &nextCRinverse ); - // Update the local data rest. - avgaccel_x += (car->_accel_x - avgaccel_x)/2; - prevspeedangle = speedangle; - speedangle = (float) -(mycardata->getTrackangle() - atan2(car->_speed_Y, car->_speed_X)); - NORM_PI_PI(speedangle); - mass = CARMASS + car->_fuel; - currentspeedsqr = car->_speed_x*car->_speed_x; - currentspeed = getSpeed(); - opponents->update(s, this, DebugMsg); - strategy->update(car, s); + // Update the local data rest. + avgaccel_x += (car->_accel_x - avgaccel_x)/2; + prevspeedangle = speedangle; + speedangle = (float) -(mycardata->getTrackangle() - atan2(car->_speed_Y, car->_speed_X)); + NORM_PI_PI(speedangle); + mass = CARMASS + car->_fuel; + currentspeedsqr = car->_speed_x*car->_speed_x; + currentspeed = getSpeed(); + opponents->update(s, this, DebugMsg); + strategy->update(car, s); - if (car->_state <= RM_CAR_STATE_PIT && !NoPit) - { + if (car->_state <= RM_CAR_STATE_PIT && !NoPit) + { #ifdef SPEED_DREAMS - float DLong, DLat; // Dist to Pit - RtDistToPit(car,track,&DLong,&DLat); + float DLong, DLat; // Dist to Pit + RtDistToPit(car,track,&DLong,&DLat); - if (DLong > 500) - pitStopChecked = false; + if (DLong > 500) + pitStopChecked = false; - if (!pit->getPitstop() - && (!pitStopChecked) - && (DLong < 500) - && (car->_distFromStartLine < pit->getNPitEntry() || car->_distFromStartLine > pit->getNPitEnd())) + if (!pit->getPitstop() + && (!pitStopChecked) + && (DLong < 500) + && (car->_distFromStartLine < pit->getNPitEntry() || car->_distFromStartLine > pit->getNPitEnd())) #else - if (!pit->getPitstop() && (car->_distFromStartLine < pit->getNPitEntry() || car->_distFromStartLine > pit->getNPitEnd())) + if (!pit->getPitstop() && (car->_distFromStartLine < pit->getNPitEntry() || car->_distFromStartLine > pit->getNPitEnd())) #endif - { - bool pitstop = strategy->needPitstop(car, s, opponents); - if (pitstop) - { - pit->setPitstop(pitstop); - pit->needPitstop(pitstop); - } - } + { + bool pitstop = strategy->needPitstop(car, s, opponents); + if (pitstop) + { + pit->setPitstop(pitstop); + pit->needPitstop(pitstop); + } + } - if (pit->getPitstop() && car->_pit) - { - pitpos = PIT_MID; + if (pit->getPitstop() && car->_pit) + { + pitpos = PIT_MID; - for (int i=0; igetNOpponents(); i++) - { - //int idx = opponent[i].getIndex(); - if (opponent[i].getTeam() != TEAM_FRIEND) continue; - if (opponent[i].getCarPtr() == car) continue; - if (opponent[i].getCarPtr()->_state > RM_CAR_STATE_PIT) - continue; + for (int i=0; igetNOpponents(); i++) + { + //int idx = opponent[i].getIndex(); + if (opponent[i].getTeam() != TEAM_FRIEND) continue; + if (opponent[i].getCarPtr() == car) continue; + if (opponent[i].getCarPtr()->_state > RM_CAR_STATE_PIT) + continue; - int opitpos = (int) opponent[i].getCarPtr()->_lightCmd; + int opitpos = (int) opponent[i].getCarPtr()->_lightCmd; - if (opitpos != PIT_NONE && car->_fuel > fuelperlap*1.5 && car->_trkPos.toLeft >= 0.0 && car->_trkPos.toLeft <= track->width) - { - // pit occupied & we've got enough fuel to go around again - pit->setPitstop( 0 ); - pitpos = PIT_NONE; - break; - } + if (opitpos != PIT_NONE && car->_fuel > fuelperlap*1.5 && car->_trkPos.toLeft >= 0.0 && car->_trkPos.toLeft <= track->width) + { + // pit occupied & we've got enough fuel to go around again + pit->setPitstop( 0 ); + pitpos = PIT_NONE; + break; + } - if (opponent[i].getCarPtr()->_pit->pos.seg == car->_pit->pos.seg) - { - // sharing a pit - if (opitpos == PIT_FRONT) - { - double pitloc = pit->getNPitLoc( PIT_MID ); - double myfrompit = pitloc - car->_distFromStartLine; - double opfrompit = pitloc - opponent[i].getCarPtr()->_distFromStartLine; - if (myfrompit < 0.0) myfrompit += track->length; - if (opfrompit < 0.0) opfrompit += track->length; + if (opponent[i].getCarPtr()->_pit->pos.seg == car->_pit->pos.seg) + { + // sharing a pit + if (opitpos == PIT_FRONT) + { + double pitloc = pit->getNPitLoc( PIT_MID ); + double myfrompit = pitloc - car->_distFromStartLine; + double opfrompit = pitloc - opponent[i].getCarPtr()->_distFromStartLine; + if (myfrompit < 0.0) myfrompit += track->length; + if (opfrompit < 0.0) opfrompit += track->length; - // work out who's closest to the pit & therefore should go in front - if (opfrompit > myfrompit) - { - pitpos = PIT_FRONT; - } - else - { - pitpos = PIT_BACK; // go in behind other car - } - } - else - { - pitpos = PIT_FRONT; // stop at end of pit space to leave room - } - } + // work out who's closest to the pit & therefore should go in front + if (opfrompit > myfrompit) + { + pitpos = PIT_FRONT; + } + else + { + pitpos = PIT_BACK; // go in behind other car + } + } + else + { + pitpos = PIT_FRONT; // stop at end of pit space to leave room + } + } - break; - } - } - else if (!pit->getInPit()) - pitpos = PIT_NONE; - } - else - { - pitpos = PIT_NONE; - } + break; + } + } + else if (!pit->getInPit()) + pitpos = PIT_NONE; + } + else + { + pitpos = PIT_NONE; + } #ifdef SPEED_DREAMS - if (pitpos == PIT_NONE) - RtTeamReleasePit(teamIndex); + if (pitpos == PIT_NONE) + RtTeamReleasePit(teamIndex); #else - car->_lightCmd = (char) pitpos; + car->_lightCmd = (char) pitpos; #endif - pit->update(); - alone = isAlone(); - simtime = s->currentTime; + pit->update(); + alone = isAlone(); + simtime = s->currentTime; - float trackangle = RtTrackSideTgAngleL(&(car->_trkPos)); - angle = trackangle - car->_yaw; - NORM_PI_PI(angle); - angle = -angle; + float trackangle = RtTrackSideTgAngleL(&(car->_trkPos)); + angle = trackangle - car->_yaw; + NORM_PI_PI(angle); + angle = -angle; } int Driver::isAlone() { - int i; + int i; - for (i = 0; i < opponents->getNOpponents(); i++) { + for (i = 0; i < opponents->getNOpponents(); i++) { #if 0 - if (opponent[i].getTeam() == TEAM_FRIEND) - continue; + if (opponent[i].getTeam() == TEAM_FRIEND) + continue; #endif - // not a friend - if we're avoiding then we're obviously not alone - if (mode == mode_avoiding) - return 0; + // not a friend - if we're avoiding then we're obviously not alone + if (mode == mode_avoiding) + return 0; - if ((opponent[i].getState() & (OPP_COLL | OPP_LETPASS)) || - ((opponent[i].getState() & (OPP_FRONT)) && opponent[i].getDistance() < MAX(50.0, car->_speed_x*1.5)) || - (fabs(opponent[i].getDistance()) < 50.0)) - { - return 0; // Not alone. - } - } - return 1; // Alone. + if ((opponent[i].getState() & (OPP_COLL | OPP_LETPASS)) || + ((opponent[i].getState() & (OPP_FRONT)) && opponent[i].getDistance() < MAX(50.0, car->_speed_x*1.5)) || + (fabs(opponent[i].getDistance()) < 50.0)) + { + return 0; // Not alone. + } + } + return 1; // Alone. } float Driver::stuckSteering( float steercmd ) { - if (stucksteer > 0.0f) - steercmd = (fabs(steercmd) + stucksteer) / 2; - else - steercmd = -(fabs(steercmd) + fabs(stucksteer)) / 2; - return steercmd; + if (stucksteer > 0.0f) + steercmd = (fabs(steercmd) + stucksteer) / 2; + else + steercmd = -(fabs(steercmd) + fabs(stucksteer)) / 2; + return steercmd; } float Driver::GetSafeStuckAccel() { - // see if wheels are on a bumpy surface - tTrackSeg *rgt_seg = car->_trkPos.seg; - tTrackSeg *lft_seg = car->_trkPos.seg; - double max_rough = 0.0f; - float accel = MAX(0.5f, 1.0f - fabs(angle)/3); - int rgt_off = 0, lft_off = 0; + // see if wheels are on a bumpy surface + tTrackSeg *rgt_seg = car->_trkPos.seg; + tTrackSeg *lft_seg = car->_trkPos.seg; + double max_rough = 0.0f; + float accel = MAX(0.5f, 1.0f - fabs(angle)/3); + int rgt_off = 0, lft_off = 0; - if ((car->priv.wheel[FRNT_RGT].seg != car->_trkPos.seg && car->priv.wheel[FRNT_RGT].seg->style == TR_PLAN && - car->priv.wheel[REAR_RGT].seg != car->_trkPos.seg && car->priv.wheel[FRNT_RGT].seg->style == TR_PLAN)) - { - rgt_seg = car->priv.wheel[REAR_RGT].seg; - if (rgt_seg->style == TR_PLAN && - (rgt_seg->surface->kFriction < car->_trkPos.seg->surface->kFriction*0.7 || - rgt_seg->surface->kRoughness > MAX(0.03, car->_trkPos.seg->surface->kRoughness*1.3) || - rgt_seg->surface->kRollRes > MAX(0.005, car->_trkPos.seg->surface->kRollRes*1.5))) - { - rgt_off = 1; - if (car->_trkPos.toRight < car->_dimension_y - 1.5) - rgt_off = 2; - max_rough = MAX(max_rough, rgt_seg->surface->kRoughness); - } - } + if ((car->priv.wheel[FRNT_RGT].seg != car->_trkPos.seg && car->priv.wheel[FRNT_RGT].seg->style == TR_PLAN && + car->priv.wheel[REAR_RGT].seg != car->_trkPos.seg && car->priv.wheel[FRNT_RGT].seg->style == TR_PLAN)) + { + rgt_seg = car->priv.wheel[REAR_RGT].seg; + if (rgt_seg->style == TR_PLAN && + (rgt_seg->surface->kFriction < car->_trkPos.seg->surface->kFriction*0.7 || + rgt_seg->surface->kRoughness > MAX(0.03, car->_trkPos.seg->surface->kRoughness*1.3) || + rgt_seg->surface->kRollRes > MAX(0.005, car->_trkPos.seg->surface->kRollRes*1.5))) + { + rgt_off = 1; + if (car->_trkPos.toRight < car->_dimension_y - 1.5) + rgt_off = 2; + max_rough = MAX(max_rough, rgt_seg->surface->kRoughness); + } + } - if ((car->priv.wheel[FRNT_LFT].seg != car->_trkPos.seg && car->priv.wheel[FRNT_LFT].seg->style == TR_PLAN && - car->priv.wheel[REAR_LFT].seg != car->_trkPos.seg && car->priv.wheel[REAR_LFT].seg->style == TR_PLAN)) - { - lft_seg = car->priv.wheel[REAR_LFT].seg; - if (lft_seg->style == TR_PLAN && - (lft_seg->surface->kFriction < car->_trkPos.seg->surface->kFriction*0.7 || - lft_seg->surface->kRoughness > MAX(0.03, car->_trkPos.seg->surface->kRoughness*1.3) || - lft_seg->surface->kRollRes > MAX(0.005, car->_trkPos.seg->surface->kRollRes*1.5))) - { - lft_off = 1; - if (car->_trkPos.toRight < car->_dimension_y - 1.5) - lft_off = 2; - max_rough = MAX(max_rough, lft_seg->surface->kRoughness); - } - } + if ((car->priv.wheel[FRNT_LFT].seg != car->_trkPos.seg && car->priv.wheel[FRNT_LFT].seg->style == TR_PLAN && + car->priv.wheel[REAR_LFT].seg != car->_trkPos.seg && car->priv.wheel[REAR_LFT].seg->style == TR_PLAN)) + { + lft_seg = car->priv.wheel[REAR_LFT].seg; + if (lft_seg->style == TR_PLAN && + (lft_seg->surface->kFriction < car->_trkPos.seg->surface->kFriction*0.7 || + lft_seg->surface->kRoughness > MAX(0.03, car->_trkPos.seg->surface->kRoughness*1.3) || + lft_seg->surface->kRollRes > MAX(0.005, car->_trkPos.seg->surface->kRollRes*1.5))) + { + lft_off = 1; + if (car->_trkPos.toRight < car->_dimension_y - 1.5) + lft_off = 2; + max_rough = MAX(max_rough, lft_seg->surface->kRoughness); + } + } - if (lft_off + rgt_off > 0 && (car->_speed_x + fabs(car->_yaw_rate*5) > 3.0)) - { - // at least one wheel on the bumpy stuff and we're moving - accel = MAX(0.2f, MIN(accel, (0.8f - (1.0+fabs(car->_yaw_rate)) * (max_rough*20)))); - } - else if (car->_speed_x > 5.0 && fabs(car->_steerCmd) > fabs(car->_yaw_rate)) - { - // understeering, reduce accel - accel = MAX(0.3f, accel - (fabs(car->_steerCmd) - fabs(car->_yaw_rate))); - } + if (lft_off + rgt_off > 0 && (car->_speed_x + fabs(car->_yaw_rate*5) > 3.0)) + { + // at least one wheel on the bumpy stuff and we're moving + accel = MAX(0.2f, MIN(accel, (0.8f - (1.0+fabs(car->_yaw_rate)) * (max_rough*20)))); + } + else if (car->_speed_x > 5.0 && fabs(car->_steerCmd) > fabs(car->_yaw_rate)) + { + // understeering, reduce accel + accel = MAX(0.3f, accel - (fabs(car->_steerCmd) - fabs(car->_yaw_rate))); + } - return accel; + return accel; } // Check if I'm stuck. bool Driver::isStuck() { - double toSide = MIN(car->_trkPos.toLeft, car->_trkPos.toRight); - double stangle = angle; - double fangle = fabs(angle); + double toSide = MIN(car->_trkPos.toLeft, car->_trkPos.toRight); + double stangle = angle; + double fangle = fabs(angle); - vec2f target = getTargetPoint(false, 0.0); - double targetAngle = atan2(target.y - car->_pos_Y, target.x - car->_pos_X); - double stuck_steer = calcSteer( targetAngle, 0 ); + vec2f target = getTargetPoint(false, 0.0); + double targetAngle = atan2(target.y - car->_pos_Y, target.x - car->_pos_X); + double stuck_steer = calcSteer( targetAngle, 0 ); - if (stangle < 1.0 && stangle > -0.3 && car->_trkPos.toLeft < 1.0) - stangle += MIN(0.5, car->_trkPos.toLeft / 5); - else if (stangle > -1.0 && stangle < 0.3 && car->_trkPos.toRight < 1.0) - stangle -= MIN(0.5, car->_trkPos.toRight / 5); + if (stangle < 1.0 && stangle > -0.3 && car->_trkPos.toLeft < 1.0) + stangle += MIN(0.5, car->_trkPos.toLeft / 5); + else if (stangle > -1.0 && stangle < 0.3 && car->_trkPos.toRight < 1.0) + stangle -= MIN(0.5, car->_trkPos.toRight / 5); - bool returning = ((car->_trkPos.toMiddle > 0.0 && speedangle < -0.2) || - (car->_trkPos.toMiddle < 0.0 && speedangle > 0.2)); - bool departing = ((car->_trkPos.toMiddle > 0.0 && speedangle > 0.2) || - (car->_trkPos.toMiddle < 0.0 && speedangle < -0.2)); - double toWall = toSide; + bool returning = ((car->_trkPos.toMiddle > 0.0 && speedangle < -0.2) || + (car->_trkPos.toMiddle < 0.0 && speedangle > 0.2)); + bool departing = ((car->_trkPos.toMiddle > 0.0 && speedangle > 0.2) || + (car->_trkPos.toMiddle < 0.0 && speedangle < -0.2)); + double toWall = toSide; - // how far to the nearest wall? - if (car->_trkPos.toMiddle < 0.0 && car->_trkPos.seg->side[TR_SIDE_RGT] != NULL) - { - tTrackSeg *seg = car->_trkPos.seg->side[TR_SIDE_RGT]; - if (seg->style == TR_PLAN) - { - toWall += seg->width; - if (seg->side[TR_SIDE_RGT]) - { - seg = seg->side[TR_SIDE_RGT]; - if (seg->style == TR_PLAN) - toWall += seg->width; - } - } - } - else if (car->_trkPos.toMiddle > 0.0 && car->_trkPos.seg->side[TR_SIDE_LFT] != NULL) - { - tTrackSeg *seg = car->_trkPos.seg->side[TR_SIDE_LFT]; - if (seg->style == TR_PLAN) - { - toWall += seg->width; - if (seg->side[TR_SIDE_LFT]) - { - seg = seg->side[TR_SIDE_LFT]; - if (seg->style == TR_PLAN) - toWall += seg->width; - } - } - } + // how far to the nearest wall? + if (car->_trkPos.toMiddle < 0.0 && car->_trkPos.seg->side[TR_SIDE_RGT] != NULL) + { + tTrackSeg *seg = car->_trkPos.seg->side[TR_SIDE_RGT]; + if (seg->style == TR_PLAN) + { + toWall += seg->width; + if (seg->side[TR_SIDE_RGT]) + { + seg = seg->side[TR_SIDE_RGT]; + if (seg->style == TR_PLAN) + toWall += seg->width; + } + } + } + else if (car->_trkPos.toMiddle > 0.0 && car->_trkPos.seg->side[TR_SIDE_LFT] != NULL) + { + tTrackSeg *seg = car->_trkPos.seg->side[TR_SIDE_LFT]; + if (seg->style == TR_PLAN) + { + toWall += seg->width; + if (seg->side[TR_SIDE_LFT]) + { + seg = seg->side[TR_SIDE_LFT]; + if (seg->style == TR_PLAN) + toWall += seg->width; + } + } + } - // update stopped timer - if (fabs(car->_speed_x) > 5.0) - stopped_timer = simtime; + // update stopped timer + if (fabs(car->_speed_x) > 5.0) + stopped_timer = simtime; - if (pit->getInPit()) - { - stuck = 0; - stuck_timer = simtime; - stucksteer = -100.0f; - } + if (pit->getInPit()) + { + stuck = 0; + stuck_timer = simtime; + stucksteer = -100.0f; + } - if (stuck) - { - // stuck - ok to be "unstuck"? - if (fangle < 0.7 && - toSide > 2.0 && - simtime - stuck_timer > 2.0) - { - stuck = 0; - stuck_timer = simtime; - stucksteer = -100.0f; - return false; - } + if (stuck) + { + // stuck - ok to be "unstuck"? + if (fangle < 0.7 && + toSide > 2.0 && + simtime - stuck_timer > 2.0) + { + stuck = 0; + stuck_timer = simtime; + stucksteer = -100.0f; + return false; + } - setMode( mode_correcting ); + setMode( mode_correcting ); - // still stuck - see if we should change gear. - if (stuck == STUCK_REVERSE) - { - // should we give up and go forwards? - if ((simtime - stuck_timer > (1.0 + fangle) && (fabs(car->_speed_x) < 2.0 || !returning)) || - (car->_trkPos.toMiddle > 0.0 && angle < 0.4 && angle > -2.4) || - (car->_trkPos.toMiddle < 0.0 && angle > -0.4 && angle < 2.4)) - { - stuck = STUCK_FORWARD; - stuck_timer = simtime; - } - } - else if (stuck == STUCK_FORWARD) - { - // should we try reverse? - if ((simtime - stuck_timer > MAX(4.0, car->_speed_x/2) && - (fabs(car->_speed_x) < 4.0 || (!returning && fabs(car->_yaw_rate) < 0.4))) || - (car->_trkPos.toRight < 0.0 + fangle && angle < -0.6 && angle > -2.4) || - (car->_trkPos.toLeft < 0.0 + fangle && angle > 0.6 && angle < 2.4)) - { - stuck = STUCK_REVERSE; - stuck_timer = simtime; - } - } - - last_stuck_time = simtime; - } - else if (getSpeed() < 10.0 || toSide < 2.0) - { - // not stuck - but are we? - if (simtime - last_stuck_time > 3.0 && // only get stuck if 3 seconds since we were last stuck - (fangle > MAX(1.0, 1.0 + toSide/5) || - simtime - stopped_timer > 4.0 || - (car->_trkPos.toLeft < 1.0 && car->_trkPos.toMiddle > rldata->offset + 2 && angle > 0.7) || - (car->_trkPos.toRight < 1.0 && car->_trkPos.toMiddle < rldata->offset - 2 && angle < -0.7))) - { - // yes, we're stuck - stuck_timer = last_stuck_time = simtime; - setMode( mode_correcting ); + // still stuck - see if we should change gear. + if (stuck == STUCK_REVERSE) + { + // should we give up and go forwards? + if ((simtime - stuck_timer > (1.0 + fangle) && (fabs(car->_speed_x) < 2.0 || !returning)) || + (car->_trkPos.toMiddle > 0.0 && angle < 0.4 && angle > -2.4) || + (car->_trkPos.toMiddle < 0.0 && angle > -0.4 && angle < 2.4)) + { + stuck = STUCK_FORWARD; + stuck_timer = simtime; + } + } + else if (stuck == STUCK_FORWARD) + { + // should we try reverse? + if ((simtime - stuck_timer > MAX(4.0, car->_speed_x/2) && + (fabs(car->_speed_x) < 4.0 || (!returning && fabs(car->_yaw_rate) < 0.4))) || + (car->_trkPos.toRight < 0.0 + fangle && angle < -0.6 && angle > -2.4) || + (car->_trkPos.toLeft < 0.0 + fangle && angle > 0.6 && angle < 2.4)) + { + stuck = STUCK_REVERSE; + stuck_timer = simtime; + } + } + + last_stuck_time = simtime; + } + else if (getSpeed() < 10.0 || toSide < 2.0) + { + // not stuck - but are we? + if (simtime - last_stuck_time > 3.0 && // only get stuck if 3 seconds since we were last stuck + (fangle > MAX(1.0, 1.0 + toSide/5) || + simtime - stopped_timer > 4.0 || + (car->_trkPos.toLeft < 1.0 && car->_trkPos.toMiddle > rldata->offset + 2 && angle > 0.7) || + (car->_trkPos.toRight < 1.0 && car->_trkPos.toMiddle < rldata->offset - 2 && angle < -0.7))) + { + // yes, we're stuck + stuck_timer = last_stuck_time = simtime; + setMode( mode_correcting ); - stuck = STUCK_REVERSE; + stuck = STUCK_REVERSE; - if ((fangle < 2.0 && currentspeed > 10.0) || - (angle < 0.0 && car->_trkPos.toMiddle > 0.0) || - (angle > 0.0 && car->_trkPos.toMiddle < 0.0) || - (fangle < 1.8 && toWall > 4.0 + fangle*3) || - (fabs(angle - speedangle) * 1.2 && car->_speed_x > 2.0)) - { - stuck = STUCK_FORWARD; - } - } - else - { - // free to keep driving - stucksteer = -100.0f; - stuck = 0; - return false; - } - } - else - { - // free to keep driving - stucksteer = -100.0f; - stuck = 0; - return false; - } + if ((fangle < 2.0 && currentspeed > 10.0) || + (angle < 0.0 && car->_trkPos.toMiddle > 0.0) || + (angle > 0.0 && car->_trkPos.toMiddle < 0.0) || + (fangle < 1.8 && toWall > 4.0 + fangle*3) || + (fabs(angle - speedangle) * 1.2 && car->_speed_x > 2.0)) + { + stuck = STUCK_FORWARD; + } + } + else + { + // free to keep driving + stucksteer = -100.0f; + stuck = 0; + return false; + } + } + else + { + // free to keep driving + stucksteer = -100.0f; + stuck = 0; + return false; + } - // seeing we're stuck, determine steering, braking, accel - if (fangle > 1.7) - { - stuck_steer = -stuck_steer; - if (stuck_steer > 0.0) - stuck_steer = 1.0; - else - stuck_steer = -1.0; - } - else if (car->_speed_x > 5.0 && fangle < 0.6 && stuck == STUCK_FORWARD && - ((car->_trkPos.toLeft < 2.0 && racesteer < stuck_steer) || - (car->_trkPos.toRight < 2.0 && racesteer > stuck_steer))) - { - stuck_steer += MAX(-0.15, MIN(0.15, racesteer - stuck_steer)); - } + // seeing we're stuck, determine steering, braking, accel + if (fangle > 1.7) + { + stuck_steer = -stuck_steer; + if (stuck_steer > 0.0) + stuck_steer = 1.0; + else + stuck_steer = -1.0; + } + else if (car->_speed_x > 5.0 && fangle < 0.6 && stuck == STUCK_FORWARD && + ((car->_trkPos.toLeft < 2.0 && racesteer < stuck_steer) || + (car->_trkPos.toRight < 2.0 && racesteer > stuck_steer))) + { + stuck_steer += MAX(-0.15, MIN(0.15, racesteer - stuck_steer)); + } - if (stucksteer < -99.0f) - { - stucksteer = stuck_steer; - } - else - { - if (stuck == STUCK_FORWARD && - ((stucksteer > 0.0 && stuck_steer < 0.0) || (stucksteer < 0.0 && stuck_steer > 0.0)) && - fabs(angle) < 1.6) - stucksteer = stuck_steer; - else if (stucksteer > 0.0) - stucksteer = fabs(stuck_steer); - else - stucksteer = -fabs(stuck_steer); - } + if (stucksteer < -99.0f) + { + stucksteer = stuck_steer; + } + else + { + if (stuck == STUCK_FORWARD && + ((stucksteer > 0.0 && stuck_steer < 0.0) || (stucksteer < 0.0 && stuck_steer > 0.0)) && + fabs(angle) < 1.6) + stucksteer = stuck_steer; + else if (stucksteer > 0.0) + stucksteer = fabs(stuck_steer); + else + stucksteer = -fabs(stuck_steer); + } - if (stuck == STUCK_REVERSE) - { - car->_steerCmd = -stucksteer*1.4; + if (stuck == STUCK_REVERSE) + { + car->_steerCmd = -stucksteer*1.4; - if (car->_speed_x > 3.0 || (toSide < 0.0 && departing)) - { - car->_accelCmd = 0.0f; - car->_brakeCmd = 0.4f; - car->_clutchCmd = 1.0f; - } - else - { - car->_accelCmd = MAX(0.3f, 0.7f + MIN(0.0f, car->_speed_x/40)); - car->_brakeCmd = 0.0f; - car->_clutchCmd = 0.0f; - } + if (car->_speed_x > 3.0 || (toSide < 0.0 && departing)) + { + car->_accelCmd = 0.0f; + car->_brakeCmd = 0.4f; + car->_clutchCmd = 1.0f; + } + else + { + car->_accelCmd = MAX(0.3f, 0.7f + MIN(0.0f, car->_speed_x/40)); + car->_brakeCmd = 0.0f; + car->_clutchCmd = 0.0f; + } - car->_gearCmd = -1; - } - else - { - car->_steerCmd = stucksteer; + car->_gearCmd = -1; + } + else + { + car->_steerCmd = stucksteer; - if (car->_speed_x < -3.0) - { - car->_accelCmd = 0.0f; - car->_brakeCmd = 0.4f; - car->_clutchCmd = 1.0f; - } - else - { - car->_brakeCmd = 0.0f; - car->_accelCmd = GetSafeStuckAccel(); - car->_accelCmd = MAX(car->_accelCmd/3, car->_accelCmd - fabs(stucksteer/2)); - if (car->_speed_x < 2.0 || fabs(car->_yaw_rate) < 0.5) - car->_accelCmd = MAX(0.3, car->_accelCmd); - car->_clutchCmd = 0.0f; - } + if (car->_speed_x < -3.0) + { + car->_accelCmd = 0.0f; + car->_brakeCmd = 0.4f; + car->_clutchCmd = 1.0f; + } + else + { + car->_brakeCmd = 0.0f; + car->_accelCmd = GetSafeStuckAccel(); + car->_accelCmd = MAX(car->_accelCmd/3, car->_accelCmd - fabs(stucksteer/2)); + if (car->_speed_x < 2.0 || fabs(car->_yaw_rate) < 0.5) + car->_accelCmd = MAX(0.3, car->_accelCmd); + car->_clutchCmd = 0.0f; + } - car->_gearCmd = 1; - } + car->_gearCmd = 1; + } - return true; + return true; } @@ -3458,390 +3454,390 @@ void Driver::initWheelPos() void Driver::initCa() { - char const *WheelSect[4] = {SECT_FRNTRGTWHEEL, SECT_FRNTLFTWHEEL, SECT_REARRGTWHEEL, SECT_REARLFTWHEEL}; - float rearwingarea = GfParmGetNum(car->_carHandle, SECT_REARWING, PRM_WINGAREA, (char*) NULL, 0.0f); - float rearwingangle = GfParmGetNum(car->_carHandle, SECT_REARWING, PRM_WINGANGLE, (char*) NULL, 0.0f); - float wingca = 1.23f*rearwingarea*sin(rearwingangle); + char const *WheelSect[4] = {SECT_FRNTRGTWHEEL, SECT_FRNTLFTWHEEL, SECT_REARRGTWHEEL, SECT_REARLFTWHEEL}; + float rearwingarea = GfParmGetNum(car->_carHandle, SECT_REARWING, PRM_WINGAREA, (char*) NULL, 0.0f); + float rearwingangle = GfParmGetNum(car->_carHandle, SECT_REARWING, PRM_WINGANGLE, (char*) NULL, 0.0f); + float wingca = 1.23f*rearwingarea*sin(rearwingangle); - float cl = GfParmGetNum(car->_carHandle, SECT_AERODYNAMICS, PRM_FCL, (char*) NULL, 0.0f) + - GfParmGetNum(car->_carHandle, SECT_AERODYNAMICS, PRM_RCL, (char*) NULL, 0.0f); - float h = 0.0f; - int i; - for (i = 0; i < 4; i++) - h += GfParmGetNum(car->_carHandle, WheelSect[i], PRM_RIDEHEIGHT, (char*) NULL, 0.20f); - h*= 1.5f; h = h*h; h = h*h; h = 2.0f * exp(-3.0f*h); - CA = h*cl + 4.0f*wingca; + float cl = GfParmGetNum(car->_carHandle, SECT_AERODYNAMICS, PRM_FCL, (char*) NULL, 0.0f) + + GfParmGetNum(car->_carHandle, SECT_AERODYNAMICS, PRM_RCL, (char*) NULL, 0.0f); + float h = 0.0f; + int i; + for (i = 0; i < 4; i++) + h += GfParmGetNum(car->_carHandle, WheelSect[i], PRM_RIDEHEIGHT, (char*) NULL, 0.20f); + h*= 1.5f; h = h*h; h = h*h; h = 2.0f * exp(-3.0f*h); + CA = h*cl + 4.0f*wingca; } // Compute aerodynamic drag coefficient CW. void Driver::initCw() { - float cx = GfParmGetNum(car->_carHandle, SECT_AERODYNAMICS, PRM_CX, (char*) NULL, 0.0f); - float frontarea = GfParmGetNum(car->_carHandle, SECT_AERODYNAMICS, PRM_FRNTAREA, (char*) NULL, 0.0f); - CW = 0.645f*cx*frontarea; + float cx = GfParmGetNum(car->_carHandle, SECT_AERODYNAMICS, PRM_CX, (char*) NULL, 0.0f); + float frontarea = GfParmGetNum(car->_carHandle, SECT_AERODYNAMICS, PRM_FRNTAREA, (char*) NULL, 0.0f); + CW = 0.645f*cx*frontarea; } // Init the friction coefficient of the the tires. void Driver::initTireMu() { - char const *WheelSect[4] = {SECT_FRNTRGTWHEEL, SECT_FRNTLFTWHEEL, SECT_REARRGTWHEEL, SECT_REARLFTWHEEL}; - float tm = FLT_MAX; - int i; + char const *WheelSect[4] = {SECT_FRNTRGTWHEEL, SECT_FRNTLFTWHEEL, SECT_REARRGTWHEEL, SECT_REARLFTWHEEL}; + float tm = FLT_MAX; + int i; - for (i = 0; i < 4; i++) { - tm = MIN(tm, GfParmGetNum(car->_carHandle, WheelSect[i], PRM_MU, (char*) NULL, 1.0f)); - } - TIREMU = tm; + for (i = 0; i < 4; i++) { + tm = MIN(tm, GfParmGetNum(car->_carHandle, WheelSect[i], PRM_MU, (char*) NULL, 1.0f)); + } + TIREMU = tm; } void Driver::GetSteerPoint( double lookahead, vec2f *rt, double offset, double time ) { - if (offset < -90.0 && mode != mode_normal) - offset = myoffset; + if (offset < -90.0 && mode != mode_normal) + offset = myoffset; - raceline->GetSteerPoint( lookahead, rt, offset, time ); + raceline->GetSteerPoint( lookahead, rt, offset, time ); } // Reduces the brake value such that it fits the speed (more downforce -> more braking). float Driver::filterBrakeSpeed(float brake) { - float weight = (CARMASS + car->_fuel)*G; - float maxForce = weight + CA*MAX_SPEED*MAX_SPEED; - float force = weight + CA*currentspeedsqr; - return brake*force/maxForce; + float weight = (CARMASS + car->_fuel)*G; + float maxForce = weight + CA*MAX_SPEED*MAX_SPEED; + float force = weight + CA*currentspeedsqr; + return brake*force/maxForce; } // Brake filter for pit stop. float Driver::filterBPit(float brake) { - if (pit->getPitstop() && !pit->getInPit()) { - float dl, dw; - RtDistToPit(car, track, &dl, &dw); - if (dl < PIT_BRAKE_AHEAD) { - float mu = car->_trkPos.seg->surface->kFriction*TIREMU*PIT_MU; - if (brakedist(0.0f, mu) > dl) { - return 1.0f; - } - } - } + if (pit->getPitstop() && !pit->getInPit()) { + float dl, dw; + RtDistToPit(car, track, &dl, &dw); + if (dl < PIT_BRAKE_AHEAD) { + float mu = car->_trkPos.seg->surface->kFriction*TIREMU*PIT_MU; + if (brakedist(0.0f, mu) > dl) { + return 1.0f; + } + } + } - if (pit->getInPit()) { - float s = pit->toSplineCoord(car->_distFromStartLine); - // Pit entry. - if (pit->getPitstop()) { - float mu = car->_trkPos.seg->surface->kFriction*TIREMU*PIT_MU; - if (s < pit->getNPitStart()) { - // Brake to pit speed limit. - float dist = pit->getNPitStart() - s; - if (brakedist(pit->getSpeedlimit(), mu) > dist) { - return 1.0f; - } - } else { - // Hold speed limit. - if (currentspeedsqr > pit->getSpeedlimitSqr()) { - return pit->getSpeedLimitBrake(currentspeedsqr); - } - } - // Brake into pit (speed limit 0.0 to stop) - float dist = pit->getNPitLoc(pitpos) - s; - if (pitpos != PIT_BACK && pit->isTimeout(dist)) { - pit->setPitstop(false); - return 0.0f; - } else { - if (brakedist(0.0f, mu) > dist) { - return 2.0f; - } else if (s > pit->getNPitLoc(pitpos)) { - // Stop in the pit. - return 2.0f; - } - } - } else { - // Pit exit. - if (s < pit->getNPitEnd()) { - // Pit speed limit. - if (currentspeedsqr > pit->getSpeedlimitSqr()) { - return pit->getSpeedLimitBrake(currentspeedsqr); - } - } - } - } + if (pit->getInPit()) { + float s = pit->toSplineCoord(car->_distFromStartLine); + // Pit entry. + if (pit->getPitstop()) { + float mu = car->_trkPos.seg->surface->kFriction*TIREMU*PIT_MU; + if (s < pit->getNPitStart()) { + // Brake to pit speed limit. + float dist = pit->getNPitStart() - s; + if (brakedist(pit->getSpeedlimit(), mu) > dist) { + return 1.0f; + } + } else { + // Hold speed limit. + if (currentspeedsqr > pit->getSpeedlimitSqr()) { + return pit->getSpeedLimitBrake(currentspeedsqr); + } + } + // Brake into pit (speed limit 0.0 to stop) + float dist = pit->getNPitLoc(pitpos) - s; + if (pitpos != PIT_BACK && pit->isTimeout(dist)) { + pit->setPitstop(false); + return 0.0f; + } else { + if (brakedist(0.0f, mu) > dist) { + return 2.0f; + } else if (s > pit->getNPitLoc(pitpos)) { + // Stop in the pit. + return 2.0f; + } + } + } else { + // Pit exit. + if (s < pit->getNPitEnd()) { + // Pit speed limit. + if (currentspeedsqr > pit->getSpeedlimitSqr()) { + return pit->getSpeedLimitBrake(currentspeedsqr); + } + } + } + } - return brake; + return brake; } // Brake filter for collision avoidance. float Driver::filterBColl(float brake) { - collision = 0.0f; + collision = 0.0f; - if (simtime < 1.5) - return brake; + if (simtime < 1.5) + return brake; - float mu = car->_trkPos.seg->surface->kFriction * BrakeMu; - int i; - float thisbrake = 0.0f; - for (i = 0; i < opponents->getNOpponents(); i++) - { - if ((opponent[i].getState() & OPP_COLL)) - { - float accel = 0.0f;//opponent[i].getCarPtr()->_accel_x / MAX(1.0, opponent[i].getTimeImpact()*2); - float ospeed = opponent[i].getSpeed() + accel; - float margin = MIN(0.3f, MAX(0.0f, 0.3f - opponent[i].getDistance())); - if ((opponent[i].getState() & OPP_SIDE_COLL) || - brakedist(ospeed, mu) + MIN(1.0, margin + MAX(0.0, (getSpeed()-ospeed)/9)) > opponent[i].getDistance() + accel) - { - accelcmd = 0.0f; - float thiscollision = MAX(0.01f, MIN(5.0f, opponent[i].getTimeImpact())); - //thiscollision = MAX(0.01f, MIN(thiscollision, opponent[i].getDistance()/2)); - if (collision) - collision = MIN(collision, thiscollision); - else - collision = thiscollision; - thisbrake = MAX(thisbrake, (0.3f + (5.0 - collision)/4) * brakeratio); + float mu = car->_trkPos.seg->surface->kFriction * BrakeMu; + int i; + float thisbrake = 0.0f; + for (i = 0; i < opponents->getNOpponents(); i++) + { + if ((opponent[i].getState() & OPP_COLL)) + { + float accel = 0.0f;//opponent[i].getCarPtr()->_accel_x / MAX(1.0, opponent[i].getTimeImpact()*2); + float ospeed = opponent[i].getSpeed() + accel; + float margin = MIN(0.3f, MAX(0.0f, 0.3f - opponent[i].getDistance())); + if ((opponent[i].getState() & OPP_SIDE_COLL) || + brakedist(ospeed, mu) + MIN(1.0, margin + MAX(0.0, (getSpeed()-ospeed)/9)) > opponent[i].getDistance() + accel) + { + accelcmd = 0.0f; + float thiscollision = MAX(0.01f, MIN(5.0f, opponent[i].getTimeImpact())); + //thiscollision = MAX(0.01f, MIN(thiscollision, opponent[i].getDistance()/2)); + if (collision) + collision = MIN(collision, thiscollision); + else + collision = thiscollision; + thisbrake = MAX(thisbrake, (0.3f + (5.0 - collision)/4) * brakeratio); if (DebugMsg & debug_brake) fprintf(stderr,"%s - %s BRAKE: ti=%.3f\n",car->_name,opponent[i].getCarPtr()->_name,opponent[i].getTimeImpact()); - } - } - } - return MAX(thisbrake, brake); + } + } + } + return MAX(thisbrake, brake); } // Antilocking filter for brakes. float Driver::filterABS(float brake) { - if (car->_speed_x < ABS_MINSPEED) return brake; - float origbrake = brake; - //float rearskid = MAX(0.0f, MAX(car->_skid[2], car->_skid[3]) - MAX(car->_skid[0], car->_skid[1])); - int i; - float slip = 0.0f; - for (i = 0; i < 4; i++) { - slip += car->_wheelSpinVel(i) * car->_wheelRadius(i); - } - //slip *= 1.0f + MAX(rearskid, MAX(fabs(car->_yaw_rate)/10, fabs(angle)/8)); - slip = car->_speed_x - slip/4.0f; - //if (collision) - // slip *= 0.25f; - if (origbrake == 2.0f) - slip *= 0.1f; + if (car->_speed_x < ABS_MINSPEED) return brake; + float origbrake = brake; + //float rearskid = MAX(0.0f, MAX(car->_skid[2], car->_skid[3]) - MAX(car->_skid[0], car->_skid[1])); + int i; + float slip = 0.0f; + for (i = 0; i < 4; i++) { + slip += car->_wheelSpinVel(i) * car->_wheelRadius(i); + } + //slip *= 1.0f + MAX(rearskid, MAX(fabs(car->_yaw_rate)/10, fabs(angle)/8)); + slip = car->_speed_x - slip/4.0f; + //if (collision) + // slip *= 0.25f; + if (origbrake == 2.0f) + slip *= 0.1f; - float absslip = (car->_speed_x < 20.0f ? MIN(AbsSlip, AbsRange/2) : AbsSlip); - if (slip > absslip) { - brake = brake - MIN(brake, (slip - absslip)/AbsRange); - } - brake = MAX(brake, MIN(origbrake, 0.1f)); + float absslip = (car->_speed_x < 20.0f ? MIN(AbsSlip, AbsRange/2) : AbsSlip); + if (slip > absslip) { + brake = brake - MIN(brake, (slip - absslip)/AbsRange); + } + brake = MAX(brake, MIN(origbrake, 0.1f)); - //brake = MAX(MIN(origbrake, collision ? 0.15f :0.05f), brake - MAX(fabs(angle), fabs(car->_yaw_rate) / 2)); - brake = (float) (MAX(MIN(origbrake, (collision ? MAX(0.05f, (5.0-collision)/30) : 0.05f)), brake - fabs(angle-speedangle)*0.3)); + //brake = MAX(MIN(origbrake, collision ? 0.15f :0.05f), brake - MAX(fabs(angle), fabs(car->_yaw_rate) / 2)); + brake = (float) (MAX(MIN(origbrake, (collision ? MAX(0.05f, (5.0-collision)/30) : 0.05f)), brake - fabs(angle-speedangle)*0.3)); - if (fbrakecmd) - brake = MAX(brake, fbrakecmd); + if (fbrakecmd) + brake = MAX(brake, fbrakecmd); - return brake; + return brake; } // TCL filter for accelerator pedal. float Driver::filterTCL(float accel) { - if (simtime < 3.0) - return accel; + if (simtime < 3.0) + return accel; - accel = MIN(1.0f, accel); - float accel1 = accel, accel2 = accel, accel3 = accel, accel4 = accel, accel5 = accel; + accel = MIN(1.0f, accel); + float accel1 = accel, accel2 = accel, accel3 = accel, accel4 = accel, accel5 = accel; - if (car->_speed_x > 10.0f && !pit->getInPit()) - { - tTrackSeg *seg = car->_trkPos.seg; - tTrackSeg *wseg0 = car->_wheelSeg(REAR_RGT); - tTrackSeg *wseg1 = car->_wheelSeg(REAR_LFT); - int count = 0; + if (car->_speed_x > 10.0f && !pit->getInPit()) + { + tTrackSeg *seg = car->_trkPos.seg; + tTrackSeg *wseg0 = car->_wheelSeg(REAR_RGT); + tTrackSeg *wseg1 = car->_wheelSeg(REAR_LFT); + int count = 0; - if (wseg0->surface->kRoughness > MAX(0.02, seg->surface->kRoughness*1.2)) - { - accel1 = (float) MAX(0.1f, accel1 - (wseg0->surface->kRoughness-(seg->surface->kRoughness*2.2)) * (wseg0->style == TR_CURB ? 2 : 10)); - if (fabs(car->_steerCmd) > 0.3f) - { - if (car->_steerCmd < 0.0) - car->_steerCmd = MIN(car->_steerCmd*0.3, car->_steerCmd + (wseg0->surface->kRoughness-(seg->surface->kRoughness*2.2)) * (wseg0->style == TR_CURB ? 2 : 10)); - else - car->_steerCmd = MAX(car->_steerCmd*0.3, car->_steerCmd + (wseg0->surface->kRoughness-(seg->surface->kRoughness*2.2)) * (wseg0->style == TR_CURB ? 2 : 10)); - } - } - if (wseg1->surface->kRoughness > MAX(0.02, seg->surface->kRoughness*1.2)) - { - accel1 = (float) MAX(0.1f, accel1 - (wseg1->surface->kRoughness-(seg->surface->kRoughness*2.2)) * (wseg1->style == TR_CURB ? 2 : 10)); - if (fabs(car->_steerCmd) > 0.3f) - { - if (car->_steerCmd < 0.0) - car->_steerCmd = MIN(car->_steerCmd*0.3, car->_steerCmd - (wseg0->surface->kRoughness-(seg->surface->kRoughness*2.2)) * (wseg0->style == TR_CURB ? 2 : 10)); - else - car->_steerCmd = MAX(car->_steerCmd*0.3, car->_steerCmd - (wseg0->surface->kRoughness-(seg->surface->kRoughness*2.2)) * (wseg0->style == TR_CURB ? 2 : 10)); - } - } + if (wseg0->surface->kRoughness > MAX(0.02, seg->surface->kRoughness*1.2)) + { + accel1 = (float) MAX(0.1f, accel1 - (wseg0->surface->kRoughness-(seg->surface->kRoughness*2.2)) * (wseg0->style == TR_CURB ? 2 : 10)); + if (fabs(car->_steerCmd) > 0.3f) + { + if (car->_steerCmd < 0.0) + car->_steerCmd = MIN(car->_steerCmd*0.3, car->_steerCmd + (wseg0->surface->kRoughness-(seg->surface->kRoughness*2.2)) * (wseg0->style == TR_CURB ? 2 : 10)); + else + car->_steerCmd = MAX(car->_steerCmd*0.3, car->_steerCmd + (wseg0->surface->kRoughness-(seg->surface->kRoughness*2.2)) * (wseg0->style == TR_CURB ? 2 : 10)); + } + } + if (wseg1->surface->kRoughness > MAX(0.02, seg->surface->kRoughness*1.2)) + { + accel1 = (float) MAX(0.1f, accel1 - (wseg1->surface->kRoughness-(seg->surface->kRoughness*2.2)) * (wseg1->style == TR_CURB ? 2 : 10)); + if (fabs(car->_steerCmd) > 0.3f) + { + if (car->_steerCmd < 0.0) + car->_steerCmd = MIN(car->_steerCmd*0.3, car->_steerCmd - (wseg0->surface->kRoughness-(seg->surface->kRoughness*2.2)) * (wseg0->style == TR_CURB ? 2 : 10)); + else + car->_steerCmd = MAX(car->_steerCmd*0.3, car->_steerCmd - (wseg0->surface->kRoughness-(seg->surface->kRoughness*2.2)) * (wseg0->style == TR_CURB ? 2 : 10)); + } + } #if 0 - if (wseg0->surface->kFriction < seg->surface->kFriction) - accel1 = (float) MAX(0.0f, accel1 - (seg->surface->kFriction - wseg0->surface->kFriction)); - if (wseg1->surface->kFriction < seg->surface->kFriction) - accel1 = (float) MAX(0.0f, accel1 - (seg->surface->kFriction - wseg1->surface->kFriction)); + if (wseg0->surface->kFriction < seg->surface->kFriction) + accel1 = (float) MAX(0.0f, accel1 - (seg->surface->kFriction - wseg0->surface->kFriction)); + if (wseg1->surface->kFriction < seg->surface->kFriction) + accel1 = (float) MAX(0.0f, accel1 - (seg->surface->kFriction - wseg1->surface->kFriction)); #endif - - if (wseg0->surface->kRollRes > MAX(0.01, seg->surface->kRollRes*1.2)) - accel1 = (float) MAX(0.0f, accel1 - (wseg0->surface->kRollRes - seg->surface->kRollRes*1.2)*4); - if (wseg1->surface->kRollRes > MAX(0.01, seg->surface->kRollRes*1.2)) - accel1 = (float) MAX(0.0f, accel1 - (wseg1->surface->kRollRes - seg->surface->kRollRes*1.2)*4); + + if (wseg0->surface->kRollRes > MAX(0.01, seg->surface->kRollRes*1.2)) + accel1 = (float) MAX(0.0f, accel1 - (wseg0->surface->kRollRes - seg->surface->kRollRes*1.2)*4); + if (wseg1->surface->kRollRes > MAX(0.01, seg->surface->kRollRes*1.2)) + accel1 = (float) MAX(0.0f, accel1 - (wseg1->surface->kRollRes - seg->surface->kRollRes*1.2)*4); - if (count) - { - if (mode != mode_normal && - ((seg->type == TR_RGT && seg->radius <= 200.0f && car->_trkPos.toLeft < 3.0f) || - (seg->type == TR_LFT && seg->radius <= 200.0f && car->_trkPos.toRight < 3.0f))) - count++; - accel1 = (float) MAX(0.0f, MIN(accel1, (1.0f-(0.25f*count)) - MAX(0.0f, (getSpeed()-car->_speed_x)/10.0f))); - } + if (count) + { + if (mode != mode_normal && + ((seg->type == TR_RGT && seg->radius <= 200.0f && car->_trkPos.toLeft < 3.0f) || + (seg->type == TR_LFT && seg->radius <= 200.0f && car->_trkPos.toRight < 3.0f))) + count++; + accel1 = (float) MAX(0.0f, MIN(accel1, (1.0f-(0.25f*count)) - MAX(0.0f, (getSpeed()-car->_speed_x)/10.0f))); + } - if (fabs(angle) > 1.0) - accel1 = (float) MIN(accel1, 1.0f - (fabs(angle)-1.0)*1.3); - } + if (fabs(angle) > 1.0) + accel1 = (float) MIN(accel1, 1.0f - (fabs(angle)-1.0)*1.3); + } - double turndecel = TurnDecel + rldata->decel; + double turndecel = TurnDecel + rldata->decel; #ifdef CONTROL_SKILL - turndecel += decel_adjust_perc; + turndecel += decel_adjust_perc; #endif - turndecel *= (mode == mode_normal ? 1 : 2); - if (fabs(car->_steerCmd) > 0.02 && turndecel > 0.0) - { - float decel = (float) ((fabs(car->_steerCmd)-0.02f) * (1.0f+fabs(car->_steerCmd)) * 0.7f); - decel *= (float) (turndecel); - if (mode != mode_normal) - { - decel *= 1.0 + rldata->adecel; - } - accel2 = (float) MIN(accel2, MAX(accel2*0.3, 1.0f-decel)); - } + turndecel *= (mode == mode_normal ? 1 : 2); + if (fabs(car->_steerCmd) > 0.02 && turndecel > 0.0) + { + float decel = (float) ((fabs(car->_steerCmd)-0.02f) * (1.0f+fabs(car->_steerCmd)) * 0.7f); + decel *= (float) (turndecel); + if (mode != mode_normal) + { + decel *= 1.0 + rldata->adecel; + } + accel2 = (float) MIN(accel2, MAX(accel2*0.3, 1.0f-decel)); + } - float slip = (this->*GET_DRIVEN_WHEEL_SPEED)() - fabs(car->_speed_x); - if (slip > TclSlip) { - accel3 = accel3 - MIN(accel3, (slip - TclSlip)/TclRange); - } + float slip = (this->*GET_DRIVEN_WHEEL_SPEED)() - fabs(car->_speed_x); + if (slip > TclSlip) { + accel3 = accel3 - MIN(accel3, (slip - TclSlip)/TclRange); + } - double yra = GetModD( tYawRateAccel, rldata->nextdiv ); - if (yra <= 0.0) - yra = YawRateAccel; + double yra = GetModD( tYawRateAccel, rldata->nextdiv ); + if (yra <= 0.0) + yra = YawRateAccel; - accel4 = MAX(0.0, accel4 - fabs(car->_yaw_rate - car->_steerCmd) * yra); + accel4 = MAX(0.0, accel4 - fabs(car->_yaw_rate - car->_steerCmd) * yra); - accel = MAX(accel/4, MIN(accel1, MIN(accel2, MIN(accel4, accel3)))); + accel = MAX(accel/4, MIN(accel1, MIN(accel2, MIN(accel4, accel3)))); - if (mode == mode_normal) - { - accel5 = MAX(0.0, accel5 - rldata->accel_redux); - accel = MIN(accel, accel5); - } + if (mode == mode_normal) + { + accel5 = MAX(0.0, accel5 - rldata->accel_redux); + accel = MIN(accel, accel5); + } - if (accel > 0.9f) - accel = 1.0f; + if (accel > 0.9f) + accel = 1.0f; - if (faccelcmd > 0.0f) - accel = MIN(accel, faccelcmd * 1.2f); + if (faccelcmd > 0.0f) + accel = MIN(accel, faccelcmd * 1.2f); - return accel; + return accel; } // Traction Control (TCL) setup. void Driver::initTCLfilter() { - char *traintype = (char *) GfParmGetStr(car->_carHandle, SECT_DRIVETRAIN, PRM_TYPE, VAL_TRANS_RWD); - if (strcmp(traintype, VAL_TRANS_RWD) == 0) { - GET_DRIVEN_WHEEL_SPEED = &Driver::filterTCL_RWD; - } else if (strcmp(traintype, VAL_TRANS_FWD) == 0) { - GET_DRIVEN_WHEEL_SPEED = &Driver::filterTCL_FWD; - } else if (strcmp(traintype, VAL_TRANS_4WD) == 0) { - GET_DRIVEN_WHEEL_SPEED = &Driver::filterTCL_4WD; - } + char *traintype = (char *) GfParmGetStr(car->_carHandle, SECT_DRIVETRAIN, PRM_TYPE, VAL_TRANS_RWD); + if (strcmp(traintype, VAL_TRANS_RWD) == 0) { + GET_DRIVEN_WHEEL_SPEED = &Driver::filterTCL_RWD; + } else if (strcmp(traintype, VAL_TRANS_FWD) == 0) { + GET_DRIVEN_WHEEL_SPEED = &Driver::filterTCL_FWD; + } else if (strcmp(traintype, VAL_TRANS_4WD) == 0) { + GET_DRIVEN_WHEEL_SPEED = &Driver::filterTCL_4WD; + } } // TCL filter plugin for rear wheel driven cars. float Driver::filterTCL_RWD() { - return (car->_wheelSpinVel(REAR_RGT) + car->_wheelSpinVel(REAR_LFT)) * - car->_wheelRadius(REAR_LFT) / 2.0f; + return (car->_wheelSpinVel(REAR_RGT) + car->_wheelSpinVel(REAR_LFT)) * + car->_wheelRadius(REAR_LFT) / 2.0f; } // TCL filter plugin for front wheel driven cars. float Driver::filterTCL_FWD() { - return (car->_wheelSpinVel(FRNT_RGT) + car->_wheelSpinVel(FRNT_LFT)) * - car->_wheelRadius(FRNT_LFT) / 2.0f; + return (car->_wheelSpinVel(FRNT_RGT) + car->_wheelSpinVel(FRNT_LFT)) * + car->_wheelRadius(FRNT_LFT) / 2.0f; } // TCL filter plugin for all wheel driven cars. float Driver::filterTCL_4WD() { - return ((car->_wheelSpinVel(FRNT_RGT) + car->_wheelSpinVel(FRNT_LFT)) * - car->_wheelRadius(FRNT_LFT) + - (car->_wheelSpinVel(REAR_RGT) + car->_wheelSpinVel(REAR_LFT)) * - car->_wheelRadius(REAR_LFT)) / 4.0f; + return ((car->_wheelSpinVel(FRNT_RGT) + car->_wheelSpinVel(FRNT_LFT)) * + car->_wheelRadius(FRNT_LFT) + + (car->_wheelSpinVel(REAR_RGT) + car->_wheelSpinVel(REAR_LFT)) * + car->_wheelRadius(REAR_LFT)) / 4.0f; } // Hold car on the track. float Driver::filterTrk(float accel) { - return accel; + return accel; - tTrackSeg* seg = car->_trkPos.seg; + tTrackSeg* seg = car->_trkPos.seg; - if (car->_speed_x < MAX_UNSTUCK_SPEED || // Too slow. - pit->getInPit() || // Pit stop. - car->_trkPos.toMiddle*speedangle > 0.0f) // Speedvector points to the inside of the turn. - { - return accel; - } + if (car->_speed_x < MAX_UNSTUCK_SPEED || // Too slow. + pit->getInPit() || // Pit stop. + car->_trkPos.toMiddle*speedangle > 0.0f) // Speedvector points to the inside of the turn. + { + return accel; + } - if (seg->type == TR_STR) { - float tm = fabs(car->_trkPos.toMiddle); - float w = (seg->width - car->_dimension_y)/2.0f ; - if (tm > w) { - return 0.0f; - } else { - return accel; - } - } else { - float sign = (seg->type == TR_RGT) ? -1.0f : 1.0f; - if (car->_trkPos.toMiddle*sign > 0.0f) { - return accel; - } else { - float tm = fabs(car->_trkPos.toMiddle); - float w = seg->width/WIDTHDIV; - if (tm > w) { - return 0.0f; - } else { - return accel; - } - } - } + if (seg->type == TR_STR) { + float tm = fabs(car->_trkPos.toMiddle); + float w = (seg->width - car->_dimension_y)/2.0f ; + if (tm > w) { + return 0.0f; + } else { + return accel; + } + } else { + float sign = (seg->type == TR_RGT) ? -1.0f : 1.0f; + if (car->_trkPos.toMiddle*sign > 0.0f) { + return accel; + } else { + float tm = fabs(car->_trkPos.toMiddle); + float w = seg->width/WIDTHDIV; + if (tm > w) { + return 0.0f; + } else { + return accel; + } + } + } } // Compute the needed distance to brake. float Driver::brakedist(float allowedspeed, float mu) { - float c = mu*G; - float d = (CA*mu + CW)/mass; - float v1sqr = currentspeedsqr; - float v2sqr = allowedspeed*allowedspeed; - return (-log((c + v2sqr*d)/(c + v1sqr*d))/(2.0f*d)) + 1.0; + float c = mu*G; + float d = (CA*mu + CW)/mass; + float v1sqr = currentspeedsqr; + float v2sqr = allowedspeed*allowedspeed; + return (-log((c + v2sqr*d)/(c + v1sqr*d))/(2.0f*d)) + 1.0; } diff --git a/src/drivers/usr_sc/driver.cpp b/src/drivers/usr_sc/driver.cpp index 06b6fca7a..3f2e18509 100644 --- a/src/drivers/usr_sc/driver.cpp +++ b/src/drivers/usr_sc/driver.cpp @@ -23,37 +23,37 @@ #define CONTROL_SKILL -//const float Driver::MAX_UNSTUCK_ANGLE = (float)(15.0f/180.0f*PI); // [radians] If the angle of the car on the track is smaller, we assume we are not stuck. +//const float Driver::MAX_UNSTUCK_ANGLE = (float)(15.0f/180.0f*PI); // [radians] If the angle of the car on the track is smaller, we assume we are not stuck. const float Driver::MAX_UNSTUCK_ANGLE = 1.3f; -const float Driver::UNSTUCK_TIME_LIMIT = 2.5f; // [s] We try to get unstuck after this time. -const float Driver::MAX_UNSTUCK_SPEED = 5.0f; // [m/s] Below this speed we consider being stuck. -const float Driver::MIN_UNSTUCK_DIST = -1.0f; // [m] If we are closer to the middle we assume to be not stuck. -const float Driver::G = 9.81f; // [m/(s*s)] Welcome on Earth. -const float Driver::FULL_ACCEL_MARGIN = 1.0f; // [m/s] Margin reduce oscillation of brake/acceleration. -const float Driver::SHIFT = 0.9f; // [-] (% of rpmredline) When do we like to shift gears. -const float Driver::SHIFT_MARGIN = 4.0f; // [m/s] Avoid oscillating gear changes. -const float Driver::ABS_MINSPEED = 3.0f; // [m/s] Below this speed the ABS is disabled (numeric, division by small numbers). -const float Driver::LOOKAHEAD_CONST = 18.0f; // [m] -const float Driver::LOOKAHEAD_FACTOR = 0.33f; // [-] -const float Driver::WIDTHDIV = 3.0f; // [-] Defines the percentage of the track to use (2/WIDTHDIV). -const float Driver::SIDECOLL_MARGIN = 3.0f; // [m] Distance between car centers to avoid side collisions. -const float Driver::BORDER_OVERTAKE_MARGIN = 1.0f; // [m] -const float Driver::OVERTAKE_OFFSET_SPEED = 5.0f; // [m/s] Offset change speed. -const float Driver::PIT_LOOKAHEAD = 6.0f; // [m] Lookahead to stop in the pit. -const float Driver::PIT_BRAKE_AHEAD = 200.0f; // [m] Workaround for "broken" pitentries. -const float Driver::PIT_MU = 0.4f; // [-] Friction of pit concrete. -const float Driver::MAX_SPEED = 84.0f; // [m/s] Speed to compute the percentage of brake to apply. -const float Driver::MAX_FUEL_PER_METER = 0.0008f; // [liter/m] fuel consumtion. -const float Driver::CLUTCH_SPEED = 5.0f; // [m/s] -const float Driver::CENTERDIV = 0.1f; // [-] (factor) [0.01..0.6]. -const float Driver::DISTCUTOFF = 200.0f; // [m] How far to look, terminate while loops. -const float Driver::MAX_INC_FACTOR = 8.0f; // [m] Increment faster if speed is slow [1.0..10.0]. -const float Driver::CATCH_FACTOR = 8.0f; // [-] select MIN(catchdist, dist*CATCH_FACTOR) to overtake. -const float Driver::CLUTCH_FULL_MAX_TIME = 2.0f; // [s] Time to apply full clutch. -const float Driver::USE_LEARNED_OFFSET_RANGE = 0.2f; // [m] if offset < this use the learned stuff +const float Driver::UNSTUCK_TIME_LIMIT = 2.5f; // [s] We try to get unstuck after this time. +const float Driver::MAX_UNSTUCK_SPEED = 5.0f; // [m/s] Below this speed we consider being stuck. +const float Driver::MIN_UNSTUCK_DIST = -1.0f; // [m] If we are closer to the middle we assume to be not stuck. +const float Driver::G = 9.81f; // [m/(s*s)] Welcome on Earth. +const float Driver::FULL_ACCEL_MARGIN = 1.0f; // [m/s] Margin reduce oscillation of brake/acceleration. +const float Driver::SHIFT = 0.9f; // [-] (% of rpmredline) When do we like to shift gears. +const float Driver::SHIFT_MARGIN = 4.0f; // [m/s] Avoid oscillating gear changes. +const float Driver::ABS_MINSPEED = 3.0f; // [m/s] Below this speed the ABS is disabled (numeric, division by small numbers). +const float Driver::LOOKAHEAD_CONST = 18.0f; // [m] +const float Driver::LOOKAHEAD_FACTOR = 0.33f; // [-] +const float Driver::WIDTHDIV = 3.0f; // [-] Defines the percentage of the track to use (2/WIDTHDIV). +const float Driver::SIDECOLL_MARGIN = 3.0f; // [m] Distance between car centers to avoid side collisions. +const float Driver::BORDER_OVERTAKE_MARGIN = 1.0f; // [m] +const float Driver::OVERTAKE_OFFSET_SPEED = 5.0f; // [m/s] Offset change speed. +const float Driver::PIT_LOOKAHEAD = 6.0f; // [m] Lookahead to stop in the pit. +const float Driver::PIT_BRAKE_AHEAD = 200.0f; // [m] Workaround for "broken" pitentries. +const float Driver::PIT_MU = 0.4f; // [-] Friction of pit concrete. +const float Driver::MAX_SPEED = 84.0f; // [m/s] Speed to compute the percentage of brake to apply. +const float Driver::MAX_FUEL_PER_METER = 0.0008f; // [liter/m] fuel consumtion. +const float Driver::CLUTCH_SPEED = 5.0f; // [m/s] +const float Driver::CENTERDIV = 0.1f; // [-] (factor) [0.01..0.6]. +const float Driver::DISTCUTOFF = 200.0f; // [m] How far to look, terminate while loops. +const float Driver::MAX_INC_FACTOR = 8.0f; // [m] Increment faster if speed is slow [1.0..10.0]. +const float Driver::CATCH_FACTOR = 8.0f; // [-] select MIN(catchdist, dist*CATCH_FACTOR) to overtake. +const float Driver::CLUTCH_FULL_MAX_TIME = 2.0f; // [s] Time to apply full clutch. +const float Driver::USE_LEARNED_OFFSET_RANGE = 0.2f; // [m] if offset < this use the learned stuff -const float Driver::TEAM_REAR_DIST = 50.0f; // -const int Driver::TEAM_DAMAGE_CHANGE_LEAD = 700; // When to change position in the team? +const float Driver::TEAM_REAR_DIST = 50.0f; // +const int Driver::TEAM_DAMAGE_CHANGE_LEAD = 700; // When to change position in the team? #define SKIPLIMIT 4 @@ -65,145 +65,145 @@ Cardata *Driver::cardata = NULL; Driver::Driver(int index) : - NoTeamWaiting(0), - TeamWaitTime(0.0f), - truespeed(0.0f), - deltaTime(0.0f), - FuelSpeedUp(0.0f), - TclSlip(2.0f), - TclRange(10.0f), - AbsSlip(2.5f), - AbsRange(5.0f), - OversteerASR(0.7f), - BrakeMu(1.0f), - YawRateAccel(0.0f), - random_seed(0), - DebugMsg(0), - racetype(0), - mode(0), - avoidmode(0), - lastmode(0), - allow_stuck(1), - stuck(0), - stuckcheck(0), - stuck_timer(0.0f), - last_stuck_time(-100.0f), - prefer_side(0), - allowcorrecting(0), - pitpos(0), - prevspeedangle(0.0f), - speedangle(0.0f), - angle(0.0f), - mass(0.0f), - maxfuel(0.0f), - myoffset(0.0f), - pitoffset(0.0f), - laststeer(0.0f), - lastbrake(0.0f), - lastaccel(0.0f), - lastNSasteer(0.0f), - lastNSksteer(0.0f), - avgaccel_x(0.0f), - car(NULL), - raceline(NULL), - opponents(NULL), - opponent(NULL), - pit(NULL), - strategy(NULL), - mycardata(NULL), - tLftMargin(NULL), - tRgtMargin(NULL), - simtime(0.0), - avoidtime(0.0), - frontavoidtime(0.0), - correcttimer(0.0), - correctlimit(1000.0), - aligned_timer(0.0), - stopped_timer(0.0), - brakedelay(0.0), - brakeratio(1.0), - deltamult(0.0), - nextCRinverse(0.0), - sideratio(100.0), - laststeer_direction(0.0), - steerLock(0.4), - currentspeedsqr(0.0f), - currentspeed(0.0f), - clutchtime(0.0f), - oldlookahead(0.0f), - oldtime_mod(0.0f), - racesteer(0.0f), - stucksteer(0.0f), - prevleft(0.0f), - rldata(NULL), - avoidlftoffset(0.0f), - avoidrgtoffset(0.0f), - accelcmd(0.0f), - brakecmd(0.0f), - faccelcmd(0.0f), - fbrakecmd(0.0f), - TurnDecel(0.0f), - PitOffset(0.0f), - PitExitSpeed(100.0f), - RevsChangeDown(0.0f), - RevsChangeUp(0.0f), - RevsChangeDownMax(0.0f), - MaxSteerTime(1.5f), - MinSteerTime(1.0f), - SteerCutoff(55.0f), - SmoothSteer(1.0f), - LookAhead(1.0f), - IncFactor(1.0f), - SideMargin(0.0f), - OutSteerFactor(0.0f), - StuckAccel(0.8f), - StuckAngle(1.6f), - FollowMargin(0.0f), - SteerLookahead(0.0f), - CorrectDelay(0.0f), - SteerMaxRI(0.008), - SkidSteer(0.7), - MinAccel(0.2), - lookahead(10.0f), - brakemargin(0.0f), - MaxGear(0), - NoPit(0), - radius(NULL), - alone(0), - carindex(0), - collision(0.0f), - global_skill(0.0f), - driver_aggression(0.0f), - skill(0.0f), - skill_adjust_limit(0.0), - skill_adjust_timer(-1.0), - decel_adjust_targ(1.0), - decel_adjust_perc(1.0), - brake_adjust_targ(1.0), - brake_adjust_perc(1.0), - fuelperlap(5.0f), + NoTeamWaiting(0), + TeamWaitTime(0.0f), + truespeed(0.0f), + deltaTime(0.0f), + FuelSpeedUp(0.0f), + TclSlip(2.0f), + TclRange(10.0f), + AbsSlip(2.5f), + AbsRange(5.0f), + OversteerASR(0.7f), + BrakeMu(1.0f), + YawRateAccel(0.0f), + random_seed(0), + DebugMsg(0), + racetype(0), + mode(0), + avoidmode(0), + lastmode(0), + allow_stuck(1), + stuck(0), + stuckcheck(0), + stuck_timer(0.0f), + last_stuck_time(-100.0f), + prefer_side(0), + allowcorrecting(0), + pitpos(0), + prevspeedangle(0.0f), + speedangle(0.0f), + angle(0.0f), + mass(0.0f), + maxfuel(0.0f), + myoffset(0.0f), + pitoffset(0.0f), + laststeer(0.0f), + lastbrake(0.0f), + lastaccel(0.0f), + lastNSasteer(0.0f), + lastNSksteer(0.0f), + avgaccel_x(0.0f), + car(NULL), + raceline(NULL), + opponents(NULL), + opponent(NULL), + pit(NULL), + strategy(NULL), + mycardata(NULL), + tLftMargin(NULL), + tRgtMargin(NULL), + simtime(0.0), + avoidtime(0.0), + frontavoidtime(0.0), + correcttimer(0.0), + correctlimit(1000.0), + aligned_timer(0.0), + stopped_timer(0.0), + brakedelay(0.0), + brakeratio(1.0), + deltamult(0.0), + nextCRinverse(0.0), + sideratio(100.0), + laststeer_direction(0.0), + steerLock(0.4), + currentspeedsqr(0.0f), + currentspeed(0.0f), + clutchtime(0.0f), + oldlookahead(0.0f), + oldtime_mod(0.0f), + racesteer(0.0f), + stucksteer(0.0f), + prevleft(0.0f), + rldata(NULL), + avoidlftoffset(0.0f), + avoidrgtoffset(0.0f), + accelcmd(0.0f), + brakecmd(0.0f), + faccelcmd(0.0f), + fbrakecmd(0.0f), + TurnDecel(0.0f), + PitOffset(0.0f), + PitExitSpeed(100.0f), + RevsChangeDown(0.0f), + RevsChangeUp(0.0f), + RevsChangeDownMax(0.0f), + MaxSteerTime(1.5f), + MinSteerTime(1.0f), + SteerCutoff(55.0f), + SmoothSteer(1.0f), + LookAhead(1.0f), + IncFactor(1.0f), + SideMargin(0.0f), + OutSteerFactor(0.0f), + StuckAccel(0.8f), + StuckAngle(1.6f), + FollowMargin(0.0f), + SteerLookahead(0.0f), + CorrectDelay(0.0f), + SteerMaxRI(0.008), + SkidSteer(0.7), + MinAccel(0.2), + lookahead(10.0f), + brakemargin(0.0f), + MaxGear(0), + NoPit(0), + radius(NULL), + alone(0), + carindex(0), + collision(0.0f), + global_skill(0.0f), + driver_aggression(0.0f), + skill(0.0f), + skill_adjust_limit(0.0), + skill_adjust_timer(-1.0), + decel_adjust_targ(1.0), + decel_adjust_perc(1.0), + brake_adjust_targ(1.0), + brake_adjust_perc(1.0), + fuelperlap(5.0f), #ifdef SPEED_DREAMS - teamIndex(0), - pitStopChecked(false), + teamIndex(0), + pitStopChecked(false), #endif - MAX_UNSTUCK_COUNT(0), - INDEX(0), - CARMASS(0.0f), - CA(0.0f), - CW(0.0f), - TIREMU(0.0f), - OVERTAKE_OFFSET_INC(0.0f), - MU_FACTOR(0.0f), - track(NULL), - skipcount(0), - cmd_accel(0.0f), - cmd_brake(0.0f), - cmd_steer(0.0f), - cmd_gear(0), - cmd_clutch(0.0f), - cmd_light(0.0f) + MAX_UNSTUCK_COUNT(0), + INDEX(0), + CARMASS(0.0f), + CA(0.0f), + CW(0.0f), + TIREMU(0.0f), + OVERTAKE_OFFSET_INC(0.0f), + MU_FACTOR(0.0f), + track(NULL), + skipcount(0), + cmd_accel(0.0f), + cmd_brake(0.0f), + cmd_steer(0.0f), + cmd_gear(0), + cmd_clutch(0.0f), + cmd_light(0.0f) { - INDEX = index; + INDEX = index; } @@ -214,19 +214,19 @@ Driver::~Driver() raceline->FreeTrack(true); delete raceline; } - delete opponents; - delete pit; - delete [] radius; - delete strategy; - delete rldata; - if (cardata != NULL) { - delete cardata; - cardata = NULL; - } + delete opponents; + delete pit; + delete [] radius; + delete strategy; + delete rldata; + if (cardata != NULL) { + delete cardata; + cardata = NULL; + } - free(tLftMargin); - free(tRgtMargin); - free(tYawRateAccel); + free(tLftMargin); + free(tRgtMargin); + free(tYawRateAccel); } #define RANDOM_SEED 0xfded @@ -249,194 +249,190 @@ unsigned int Driver::getRandom() // Called for every track change or new race. void Driver::initTrack(tTrack* t, void *carHandle, void **carParmHandle, tSituation *s) { - track = t; + track = t; - const int BUFSIZE = 255; - int i; - char buffer[BUFSIZE+1]; + const int BUFSIZE = 255; + int i; + char buffer[BUFSIZE+1]; - global_skill = skill = decel_adjust_perc = driver_aggression = 0.0; + global_skill = skill = decel_adjust_perc = driver_aggression = 0.0; #ifdef CONTROL_SKILL - // load the skill level - //if (s->_raceType == RM_TYPE_PRACTICE) - // global_skill = 0.0; - //else - { - snprintf(buffer, BUFSIZE, "config/raceman/extra/skill.xml"); - void *skillHandle = GfParmReadFile(buffer, GFPARM_RMODE_REREAD); - if (skillHandle) - { - global_skill = GfParmGetNum(skillHandle, (char *)SECT_SKILL, (char *)PRV_SKILL_LEVEL, (char *) NULL, 10.0f); - } - else - { - global_skill = 0.0f; - } - global_skill = MAX(0.0f, MIN(10.0f, global_skill)); + // load the global skill level, range 0 - 10 + snprintf(buffer, BUFSIZE, "%sconfig/raceman/extra/skill.xml", GetLocalDir()); + void *skillHandle = GfParmReadFile(buffer, GFPARM_RMODE_REREAD); + if(!skillHandle) { + snprintf(buffer, BUFSIZE, "%sconfig/raceman/extra/skill.xml", GetDataDir()); + skillHandle = GfParmReadFile(buffer, GFPARM_RMODE_REREAD); + }//if !skillHandle + + if (skillHandle) { + global_skill = GfParmGetNum(skillHandle, (char *)SECT_SKILL, (char *)PRV_SKILL_LEVEL, (char *) NULL, 10.0f); + } + global_skill = MAX(0.0f, MIN(10.0f, global_skill)); - float driver_skill = 0.0f; - snprintf(buffer, BUFSIZE, "drivers/%s/%d/skill.xml",robot_name,INDEX); - skillHandle = GfParmReadFile(buffer, GFPARM_RMODE_STD); - if (skillHandle) - { - driver_skill = GfParmGetNum(skillHandle, SECT_SKILL, PRV_SKILL_LEVEL, (char *) NULL, 0.0); - driver_aggression = GfParmGetNum(skillHandle, SECT_SKILL, PRV_SKILL_AGGRO, (char *)NULL, 0.0); - driver_skill = MIN(1.0, MAX(0.0, driver_skill)); - } + //load the driver skill level, range 0 - 1 + float driver_skill = 0.0f; + snprintf(buffer, BUFSIZE, "drivers/%s/%d/skill.xml",robot_name,INDEX); + skillHandle = GfParmReadFile(buffer, GFPARM_RMODE_STD); + if (skillHandle) + { + driver_skill = GfParmGetNum(skillHandle, SECT_SKILL, PRV_SKILL_LEVEL, (char *) NULL, 0.0); + driver_aggression = GfParmGetNum(skillHandle, SECT_SKILL, PRV_SKILL_AGGRO, (char *)NULL, 0.0); + driver_skill = MIN(1.0, MAX(0.0, driver_skill)); + } - skill = (global_skill + driver_skill * 2) * (1.0 + driver_skill); - } + skill = (global_skill + driver_skill * 2) * (1.0 + driver_skill); #endif - // Load a custom setup if one is available. - // Get a pointer to the first char of the track filename. - char *ptrackname = strrchr(track->filename, '/') + 1; - char *p = strrchr(ptrackname, '.'); - char trackname[256] = {0}; + // Load a custom setup if one is available. + // Get a pointer to the first char of the track filename. + char *ptrackname = strrchr(track->filename, '/') + 1; + char *p = strrchr(ptrackname, '.'); + char trackname[256] = {0}; - if (p) - strncpy(trackname, ptrackname, p - ptrackname); - else - strcpy(trackname, ptrackname); + if (p) + strncpy(trackname, ptrackname, p - ptrackname); + else + strcpy(trackname, ptrackname); - char carName[256]; - { - char const *path = SECT_GROBJECTS "/" LST_RANGES "/" "1"; - char const *key = PRM_CAR; - strncpy( carName, GfParmGetStr(carHandle, path, key, ""), sizeof(carName) ); - char *p = strrchr(carName, '.'); - if (p) *p = '\0'; - } + char carName[256]; + { + char const *path = SECT_GROBJECTS "/" LST_RANGES "/" "1"; + char const *key = PRM_CAR; + strncpy( carName, GfParmGetStr(carHandle, path, key, ""), sizeof(carName) ); + char *p = strrchr(carName, '.'); + if (p) *p = '\0'; + } - snprintf(buffer, BUFSIZE, "drivers/%s/cars/%s/default.xml", robot_name, carName); - *carParmHandle = GfParmReadFile(buffer, GFPARM_RMODE_STD); - void *newhandle; + snprintf(buffer, BUFSIZE, "drivers/%s/cars/%s/default.xml", robot_name, carName); + *carParmHandle = GfParmReadFile(buffer, GFPARM_RMODE_STD); + void *newhandle; - switch (s->_raceType) { - case RM_TYPE_PRACTICE: - snprintf(buffer, BUFSIZE, "drivers/%s/cars/%s/practice/%s.xml", robot_name, carName, trackname); - break; - case RM_TYPE_QUALIF: - snprintf(buffer, BUFSIZE, "drivers/%s/cars/%s/qualifying/%s.xml", robot_name, carName, trackname); - break; - case RM_TYPE_RACE: - snprintf(buffer, BUFSIZE, "drivers/%s/cars/%s/race/%s.xml", robot_name, carName, trackname); - break; - default: - break; - } + switch (s->_raceType) { + case RM_TYPE_PRACTICE: + snprintf(buffer, BUFSIZE, "drivers/%s/cars/%s/practice/%s.xml", robot_name, carName, trackname); + break; + case RM_TYPE_QUALIF: + snprintf(buffer, BUFSIZE, "drivers/%s/cars/%s/qualifying/%s.xml", robot_name, carName, trackname); + break; + case RM_TYPE_RACE: + snprintf(buffer, BUFSIZE, "drivers/%s/cars/%s/race/%s.xml", robot_name, carName, trackname); + break; + default: + break; + } - newhandle = GfParmReadFile(buffer, GFPARM_RMODE_STD); - if (newhandle) - { - if (*carParmHandle) - *carParmHandle = GfParmMergeHandles(*carParmHandle, newhandle, (GFPARM_MMODE_SRC|GFPARM_MMODE_DST|GFPARM_MMODE_RELSRC|GFPARM_MMODE_RELDST)); - else - *carParmHandle = newhandle; - } - else - { - snprintf(buffer, BUFSIZE, "drivers/%s/cars/%s/%s.xml", robot_name, carName, trackname); - newhandle = GfParmReadFile(buffer, GFPARM_RMODE_STD); - if (newhandle) - { - if (*carParmHandle) - *carParmHandle = GfParmMergeHandles(*carParmHandle, newhandle, (GFPARM_MMODE_SRC|GFPARM_MMODE_DST|GFPARM_MMODE_RELSRC|GFPARM_MMODE_RELDST)); - else - *carParmHandle = newhandle; - } - } + newhandle = GfParmReadFile(buffer, GFPARM_RMODE_STD); + if (newhandle) + { + if (*carParmHandle) + *carParmHandle = GfParmMergeHandles(*carParmHandle, newhandle, (GFPARM_MMODE_SRC|GFPARM_MMODE_DST|GFPARM_MMODE_RELSRC|GFPARM_MMODE_RELDST)); + else + *carParmHandle = newhandle; + } + else + { + snprintf(buffer, BUFSIZE, "drivers/%s/cars/%s/%s.xml", robot_name, carName, trackname); + newhandle = GfParmReadFile(buffer, GFPARM_RMODE_STD); + if (newhandle) + { + if (*carParmHandle) + *carParmHandle = GfParmMergeHandles(*carParmHandle, newhandle, (GFPARM_MMODE_SRC|GFPARM_MMODE_DST|GFPARM_MMODE_RELSRC|GFPARM_MMODE_RELDST)); + else + *carParmHandle = newhandle; + } + } - // Create a pit stop strategy object. - strategy = new SimpleStrategy2(); - strategy->setTrack(track); + // Create a pit stop strategy object. + strategy = new SimpleStrategy2(); + strategy->setTrack(track); - // Init fuel. - strategy->setFuelAtRaceStart(t, carParmHandle, s, INDEX); + // Init fuel. + strategy->setFuelAtRaceStart(t, carParmHandle, s, INDEX); - // Load and set parameters. - MU_FACTOR = GfParmGetNum(*carParmHandle, SECT_PRIVATE, BT_ATT_MUFACTOR, (char*)NULL, 0.69f); + // Load and set parameters. + MU_FACTOR = GfParmGetNum(*carParmHandle, SECT_PRIVATE, BT_ATT_MUFACTOR, (char*)NULL, 0.69f); - PitOffset = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_PIT_OFFSET, (char *)NULL, 10.0f ); - PitExitSpeed = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_PIT_EXIT_SPEED, (char *)NULL, 100.0f ); - TurnDecel = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_TURN_DECEL, (char *)NULL, 1.0f ); - RevsChangeUp = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_REVS_UP, (char *)NULL, 0.96f ); - RevsChangeDown = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_REVS_DOWN, (char *)NULL, 0.75f ); - RevsChangeDownMax = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_REVS_DOWN_MAX, (char *)NULL, 0.85f ); - MaxSteerTime = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_MAX_STEER_TIME, (char *)NULL, 1.5f ); - MinSteerTime = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_MIN_STEER_TIME, (char *)NULL, 1.0f ); - SteerCutoff = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_STEER_CUTOFF, (char *)NULL, 55.0f ); - SmoothSteer = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_SMOOTH_STEER, (char *)NULL, 1.0f ); - LookAhead = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_LOOKAHEAD, (char *)NULL, 1.0f ); - IncFactor = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_INC_FACTOR, (char *)NULL, 1.0f ); - SideMargin = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_SIDE_MARGIN, (char *)NULL, 0.0f ); - OutSteerFactor = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_OUT_STEER_X, (char *)NULL, 1.0f ); - StuckAccel = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_STUCK_ACCEL, (char *)NULL, 0.8f ); - StuckAngle = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_STUCK_ANGLE, (char *)NULL, 1.6f ); - FollowMargin = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_FOLLOW_MARGIN, (char *)NULL, 0.0f ); - SteerLookahead = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_STEER_LOOKAHEAD, (char *)NULL, 1.0f ); - CorrectDelay = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_CORRECT_DELAY, (char *)NULL, 0.0f ); - MinAccel = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_MIN_ACCEL, (char *)NULL, 0.2f ); - MaxGear = (int) GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_MAX_GEAR, (char *)NULL, 6.0f ); - NoPit = (int) GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_NO_PIT, (char *)NULL, 0.0f ); - NoTeamWaiting = (int) GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_NO_TEAM_WAITING, (char *)NULL, 1.0f ); - TeamWaitTime = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_TEAM_WAIT_TIME, (char *)NULL, 0.0f); - YawRateAccel = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_YAW_RATE_ACCEL, (char *)NULL, 0.0f); + PitOffset = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_PIT_OFFSET, (char *)NULL, 10.0f ); + PitExitSpeed = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_PIT_EXIT_SPEED, (char *)NULL, 100.0f ); + TurnDecel = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_TURN_DECEL, (char *)NULL, 1.0f ); + RevsChangeUp = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_REVS_UP, (char *)NULL, 0.96f ); + RevsChangeDown = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_REVS_DOWN, (char *)NULL, 0.75f ); + RevsChangeDownMax = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_REVS_DOWN_MAX, (char *)NULL, 0.85f ); + MaxSteerTime = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_MAX_STEER_TIME, (char *)NULL, 1.5f ); + MinSteerTime = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_MIN_STEER_TIME, (char *)NULL, 1.0f ); + SteerCutoff = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_STEER_CUTOFF, (char *)NULL, 55.0f ); + SmoothSteer = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_SMOOTH_STEER, (char *)NULL, 1.0f ); + LookAhead = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_LOOKAHEAD, (char *)NULL, 1.0f ); + IncFactor = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_INC_FACTOR, (char *)NULL, 1.0f ); + SideMargin = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_SIDE_MARGIN, (char *)NULL, 0.0f ); + OutSteerFactor = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_OUT_STEER_X, (char *)NULL, 1.0f ); + StuckAccel = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_STUCK_ACCEL, (char *)NULL, 0.8f ); + StuckAngle = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_STUCK_ANGLE, (char *)NULL, 1.6f ); + FollowMargin = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_FOLLOW_MARGIN, (char *)NULL, 0.0f ); + SteerLookahead = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_STEER_LOOKAHEAD, (char *)NULL, 1.0f ); + CorrectDelay = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_CORRECT_DELAY, (char *)NULL, 0.0f ); + MinAccel = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_MIN_ACCEL, (char *)NULL, 0.2f ); + MaxGear = (int) GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_MAX_GEAR, (char *)NULL, 6.0f ); + NoPit = (int) GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_NO_PIT, (char *)NULL, 0.0f ); + NoTeamWaiting = (int) GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_NO_TEAM_WAITING, (char *)NULL, 1.0f ); + TeamWaitTime = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_TEAM_WAIT_TIME, (char *)NULL, 0.0f); + YawRateAccel = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_YAW_RATE_ACCEL, (char *)NULL, 0.0f); - double brkpressure = GfParmGetNum( *carParmHandle, SECT_BRKSYST, PRM_BRKPRESS, (char *) NULL, 0.0f ) / 1000; + double brkpressure = GfParmGetNum( *carParmHandle, SECT_BRKSYST, PRM_BRKPRESS, (char *) NULL, 0.0f ) / 1000; brakeratio -= MIN(0.5, MAX(0.0, brkpressure - 20000.0) / 100000); - for (i=0; i<6; i++) - { - char szTmp[32]; + for (i=0; i<6; i++) + { + char szTmp[32]; - sprintf(szTmp, "%s %d", PRV_REVS_UP, i+1); - GearRevsChangeUp[i] = GfParmGetNum( *carParmHandle, SECT_PRIVATE, szTmp, (char *)NULL, RevsChangeUp ); + sprintf(szTmp, "%s %d", PRV_REVS_UP, i+1); + GearRevsChangeUp[i] = GfParmGetNum( *carParmHandle, SECT_PRIVATE, szTmp, (char *)NULL, RevsChangeUp ); - sprintf(szTmp, "%s %d", PRV_REVS_DOWN, i+1); - GearRevsChangeDown[i] = GfParmGetNum( *carParmHandle, SECT_PRIVATE, szTmp, (char *)NULL, RevsChangeDown ); + sprintf(szTmp, "%s %d", PRV_REVS_DOWN, i+1); + GearRevsChangeDown[i] = GfParmGetNum( *carParmHandle, SECT_PRIVATE, szTmp, (char *)NULL, RevsChangeDown ); - sprintf(szTmp, "%s %d", PRV_REVS_DOWN_MAX, i+1); - GearRevsChangeDownMax[i] = GfParmGetNum( *carParmHandle, SECT_PRIVATE, szTmp, (char *)NULL, RevsChangeDownMax ); - } + sprintf(szTmp, "%s %d", PRV_REVS_DOWN_MAX, i+1); + GearRevsChangeDownMax[i] = GfParmGetNum( *carParmHandle, SECT_PRIVATE, szTmp, (char *)NULL, RevsChangeDownMax ); + } - tLftMargin = (LRLMod *) malloc( sizeof(LRLMod) ); - tRgtMargin = (LRLMod *) malloc( sizeof(LRLMod) ); - tYawRateAccel = (LRLMod *) malloc( sizeof(LRLMod) ); - memset( tLftMargin, 0, sizeof(LRLMod) ); - memset( tRgtMargin, 0, sizeof(LRLMod) ); - memset( tYawRateAccel, 0, sizeof(LRLMod) ); + tLftMargin = (LRLMod *) malloc( sizeof(LRLMod) ); + tRgtMargin = (LRLMod *) malloc( sizeof(LRLMod) ); + tYawRateAccel = (LRLMod *) malloc( sizeof(LRLMod) ); + memset( tLftMargin, 0, sizeof(LRLMod) ); + memset( tRgtMargin, 0, sizeof(LRLMod) ); + memset( tYawRateAccel, 0, sizeof(LRLMod) ); - for (i=0; i_trkPos.toLeft; - this->car = car; - int stdebug = (int) GfParmGetNum(car->_carHandle, SECT_PRIVATE, PRV_STEER_DEBUG, NULL, 0); - int otdebug = (int) GfParmGetNum(car->_carHandle, SECT_PRIVATE, PRV_OVERTAKE_DEBUG, NULL, 0); - int brdebug = (int) GfParmGetNum(car->_carHandle, SECT_PRIVATE, PRV_BRAKE_DEBUG, NULL, 0); - if ((RM_TYPE_PRACTICE == s->_raceType && stdebug >= 0) || stdebug > 0) DebugMsg |= debug_steer; - if (otdebug) DebugMsg |= debug_overtake; - if (brdebug) DebugMsg |= debug_brake; - FuelSpeedUp = GfParmGetNum(car->_carHandle, SECT_PRIVATE, PRV_FUEL_SPEEDUP, NULL, 0.0f); - TclSlip = GfParmGetNum(car->_carHandle, SECT_PRIVATE, PRV_TCL_SLIP, NULL, 2.0f); - TclRange = GfParmGetNum(car->_carHandle, SECT_PRIVATE, PRV_TCL_RANGE, NULL, 10.0f); - AbsSlip = GfParmGetNum(car->_carHandle, SECT_PRIVATE, PRV_ABS_SLIP, NULL, 2.5f); - AbsRange = GfParmGetNum(car->_carHandle, SECT_PRIVATE, PRV_ABS_RANGE, NULL, 5.0f); - OversteerASR = GfParmGetNum(car->_carHandle, SECT_PRIVATE, PRV_OVERSTEER_ASR, NULL, 0.4f); - BrakeMu = GfParmGetNum(car->_carHandle, SECT_PRIVATE, PRV_BRAKE_MU, NULL, 1.0f); - YawRateAccel = GfParmGetNum(car->_carHandle, SECT_PRIVATE, PRV_YAW_RATE_ACCEL, NULL, 0.0f); - fuelperlap = GfParmGetNum(car->_carHandle, SECT_PRIVATE, PRV_FUEL_PER_LAP, NULL, 5.0f); - CARMASS = GfParmGetNum(car->_carHandle, SECT_CAR, PRM_MASS, NULL, 1000.0f); - maxfuel = GfParmGetNum(car->_carHandle, SECT_CAR, PRM_TANK, NULL, 100.0f); - steerLock = GfParmGetNum(car->_carHandle, SECT_STEER, PRM_STEERLOCK, (char *)NULL, 4.0f); - brakemargin = GfParmGetNum(car->_carHandle, SECT_PRIVATE, PRV_BRAKE_MARGIN, (char *)NULL, 0.0f); - myoffset = 0.0f; - cmd_accel = cmd_brake = cmd_clutch = cmd_steer = cmd_light = 0.0f; - cmd_gear = 1; - skipcount = 0; - simtime = correcttimer = skill_adjust_limit = aligned_timer = stopped_timer = 0.0; - avoidtime = frontavoidtime = 0.0; - correctlimit = 1000.0; - deltamult = 1.0 / s->deltaTime; - racetype = s->_raceType; - initWheelPos(); - initCa(); - initCw(); - initTireMu(); - initTCLfilter(); + deltaTime = (float) RCM_MAX_DT_ROBOTS; + MAX_UNSTUCK_COUNT = int(UNSTUCK_TIME_LIMIT/deltaTime); + OVERTAKE_OFFSET_INC = OVERTAKE_OFFSET_SPEED*deltaTime; + random_seed = 0; + alone = allow_stuck = 1; + stuckcheck = 0; + clutchtime = stuck_timer = 0.0f; + last_stuck_time = -100.0f; + oldtime_mod = oldlookahead = laststeer = lastbrake = lastaccel = avgaccel_x = lastNSasteer = lastNSksteer = 0.0f; + brake_adjust_targ = decel_adjust_targ = 1.0f; + brake_adjust_perc = decel_adjust_perc = 1.0f; + prevleft = car->_trkPos.toLeft; + this->car = car; + int stdebug = (int) GfParmGetNum(car->_carHandle, SECT_PRIVATE, PRV_STEER_DEBUG, NULL, 0); + int otdebug = (int) GfParmGetNum(car->_carHandle, SECT_PRIVATE, PRV_OVERTAKE_DEBUG, NULL, 0); + int brdebug = (int) GfParmGetNum(car->_carHandle, SECT_PRIVATE, PRV_BRAKE_DEBUG, NULL, 0); + if ((RM_TYPE_PRACTICE == s->_raceType && stdebug >= 0) || stdebug > 0) DebugMsg |= debug_steer; + if (otdebug) DebugMsg |= debug_overtake; + if (brdebug) DebugMsg |= debug_brake; + FuelSpeedUp = GfParmGetNum(car->_carHandle, SECT_PRIVATE, PRV_FUEL_SPEEDUP, NULL, 0.0f); + TclSlip = GfParmGetNum(car->_carHandle, SECT_PRIVATE, PRV_TCL_SLIP, NULL, 2.0f); + TclRange = GfParmGetNum(car->_carHandle, SECT_PRIVATE, PRV_TCL_RANGE, NULL, 10.0f); + AbsSlip = GfParmGetNum(car->_carHandle, SECT_PRIVATE, PRV_ABS_SLIP, NULL, 2.5f); + AbsRange = GfParmGetNum(car->_carHandle, SECT_PRIVATE, PRV_ABS_RANGE, NULL, 5.0f); + OversteerASR = GfParmGetNum(car->_carHandle, SECT_PRIVATE, PRV_OVERSTEER_ASR, NULL, 0.4f); + BrakeMu = GfParmGetNum(car->_carHandle, SECT_PRIVATE, PRV_BRAKE_MU, NULL, 1.0f); + YawRateAccel = GfParmGetNum(car->_carHandle, SECT_PRIVATE, PRV_YAW_RATE_ACCEL, NULL, 0.0f); + fuelperlap = GfParmGetNum(car->_carHandle, SECT_PRIVATE, PRV_FUEL_PER_LAP, NULL, 5.0f); + CARMASS = GfParmGetNum(car->_carHandle, SECT_CAR, PRM_MASS, NULL, 1000.0f); + maxfuel = GfParmGetNum(car->_carHandle, SECT_CAR, PRM_TANK, NULL, 100.0f); + steerLock = GfParmGetNum(car->_carHandle, SECT_STEER, PRM_STEERLOCK, (char *)NULL, 4.0f); + brakemargin = GfParmGetNum(car->_carHandle, SECT_PRIVATE, PRV_BRAKE_MARGIN, (char *)NULL, 0.0f); + myoffset = 0.0f; + cmd_accel = cmd_brake = cmd_clutch = cmd_steer = cmd_light = 0.0f; + cmd_gear = 1; + skipcount = 0; + simtime = correcttimer = skill_adjust_limit = aligned_timer = stopped_timer = 0.0; + avoidtime = frontavoidtime = 0.0; + correctlimit = 1000.0; + deltamult = 1.0 / s->deltaTime; + racetype = s->_raceType; + initWheelPos(); + initCa(); + initCw(); + initTireMu(); + initTCLfilter(); - raceline = new LRaceLine(); - raceline->NewRace( car, s ); - raceline->setSkill( skill ); - raceline->AllocTrack( track ); - { - char *ptrackname = strrchr(track->filename, '/') + 1; - char *p = strrchr(ptrackname, '.'); - char trackname[256] = {0}; - - if (p) - strncpy(trackname, ptrackname, p - ptrackname); - else - strcpy(trackname, ptrackname); + raceline = new LRaceLine(); + raceline->NewRace( car, s ); + raceline->setSkill( skill ); + raceline->AllocTrack( track ); + { + char *ptrackname = strrchr(track->filename, '/') + 1; + char *p = strrchr(ptrackname, '.'); + char trackname[256] = {0}; + + if (p) + strncpy(trackname, ptrackname, p - ptrackname); + else + strcpy(trackname, ptrackname); - char carName[256]; - { - char const *path = SECT_GROBJECTS "/" LST_RANGES "/" "1"; - char const *key = PRM_CAR; - strncpy( carName, GfParmGetStr(car->_carHandle, path, key, ""), sizeof(carName) ); - char *p = strrchr(carName, '.'); - if (p) *p = '\0'; - } + char carName[256]; + { + char const *path = SECT_GROBJECTS "/" LST_RANGES "/" "1"; + char const *key = PRM_CAR; + strncpy( carName, GfParmGetStr(car->_carHandle, path, key, ""), sizeof(carName) ); + char *p = strrchr(carName, '.'); + if (p) *p = '\0'; + } - LoadDAT( s, carName, trackname ); - } - raceline->InitTrack(track, s); - raceline->setCW( CW ); + LoadDAT( s, carName, trackname ); + } + raceline->InitTrack(track, s); + raceline->setCW( CW ); - rldata = new LRaceLineData(); - memset(rldata, 0, sizeof(LRaceLineData)); + rldata = new LRaceLineData(); + memset(rldata, 0, sizeof(LRaceLineData)); - // Create just one instance of cardata shared by all drivers. - if (cardata == NULL) { - cardata = new Cardata(s); - } - mycardata = cardata->findCar(car); - simtime = s->currentTime; - skill_adjust_timer = -1; + // Create just one instance of cardata shared by all drivers. + if (cardata == NULL) { + cardata = new Cardata(s); + } + mycardata = cardata->findCar(car); + simtime = s->currentTime; + skill_adjust_timer = -1; - // initialize the list of opponents. - opponents = new Opponents(s, this, cardata); - opponent = opponents->getOpponentPtr(); + // initialize the list of opponents. + opponents = new Opponents(s, this, cardata); + opponent = opponents->getOpponentPtr(); - // Set team mate. - char *teammate = (char *) GfParmGetStr(car->_carHandle, SECT_PRIVATE, BT_ATT_TEAMMATE, NULL); - if (teammate != NULL) { - opponents->setTeamMate(teammate); - } + // Set team mate. + char *teammate = (char *) GfParmGetStr(car->_carHandle, SECT_PRIVATE, BT_ATT_TEAMMATE, NULL); + if (teammate != NULL) { + opponents->setTeamMate(teammate); + } - // Initialize radius of segments. - radius = new float[track->nseg]; - computeRadius(radius); + // Initialize radius of segments. + radius = new float[track->nseg]; + computeRadius(radius); - // create the pit object. - pit = new Pit(s, this, PitOffset); - setMode( mode_correcting ); - lastmode = mode_correcting; + // create the pit object. + pit = new Pit(s, this, PitOffset); + setMode( mode_correcting ); + lastmode = mode_correcting; - carindex = 0; + carindex = 0; - for (int i = 0; i < s->_ncars; i++) - { - if (s->cars[i] == car) - { - carindex = i; - break; - } - } + for (int i = 0; i < s->_ncars; i++) + { + if (s->cars[i] == car) + { + carindex = i; + break; + } + } #ifdef SPEED_DREAMS - teamIndex = RtTeamManagerIndex( car, track, s ); - strategy->setTeamIndex( teamIndex ); + teamIndex = RtTeamManagerIndex( car, track, s ); + strategy->setTeamIndex( teamIndex ); #endif } void Driver::calcSpeed() { - accelcmd = brakecmd = 0.0f; - faccelcmd = fbrakecmd = 0.0f; - double speed = rldata->speed; - double avspeed = MAX((currentspeed+0.4)-(MAX(0.0, 1.6-fabs(MAX(0.0, angle-speedangle))*5)), rldata->avspeed); - double slowavspeed = rldata->slowavspeed; + accelcmd = brakecmd = 0.0f; + faccelcmd = fbrakecmd = 0.0f; + double speed = rldata->speed; + double avspeed = MAX((currentspeed+0.4)-(MAX(0.0, 1.6-fabs(MAX(0.0, angle-speedangle))*5)), rldata->avspeed); + double slowavspeed = rldata->slowavspeed; - double speed_redux = 1.0; + double speed_redux = 1.0; - if (mode != mode_normal) - { - if (fabs(speedangle) > 0.05 && - (fabs(speedangle) > fabs(rldata->rlangle) || fabs(speedangle - rldata->rlangle) > 0.05)) - speed_redux -= MIN(0.6, MIN(fabs(speedangle), fabs(speedangle-rldata->rlangle))/2); - avspeed *= speed_redux; - slowavspeed *= speed_redux; - } + if (mode != mode_normal) + { + if (fabs(speedangle) > 0.05 && + (fabs(speedangle) > fabs(rldata->rlangle) || fabs(speedangle - rldata->rlangle) > 0.05)) + speed_redux -= MIN(0.6, MIN(fabs(speedangle), fabs(speedangle-rldata->rlangle))/2); + avspeed *= speed_redux; + slowavspeed *= speed_redux; + } - if (mode == mode_avoiding && !allowcorrecting) - { - speed = avspeed; - if ((avoidmode & avoidside) && !rldata->insideline && sideratio < 1.0 && - ((rldata->rInverse > 0.0 && (avoidmode & avoidright) && speedangle < -(sideratio/10)) || - (rldata->rInverse < 0.0 && (avoidmode & avoidleft) && speedangle > (sideratio/10)))) - { - speed = slowavspeed; - } - } - else if ((mode == mode_correcting || (simtime - aligned_timer < 2.0)) && rldata->insideline && rldata->closing) - { - speed = slowavspeed; - } - else if ((mode == mode_correcting || (simtime - aligned_timer < 5.0))) - { - //avspeed = MIN(rldata->speed - MIN(3.0, fabs(rldata->rInverse)*400), avspeed); - avspeed = MIN(rldata->speed, (slowavspeed+avspeed)/2); - double rlspeed = rldata->speed;//MAX(avspeed, rldata->speed-1.0); - //speed = avspeed + (rlspeed-avspeed) * MAX(0.0, MIN(1.0, 1.0 - MAX(fabs(correctlimit*2), fabs(fabs(laststeer)-fabs(rldata->rInverse*80))/2))); - speed = avspeed + (rlspeed-avspeed) * MAX(0.0, MIN(1.0, 1.0 - (fabs(correctlimit*2) + fabs(angle - rldata->rlangle)*5))); - } + if (mode == mode_avoiding && !allowcorrecting) + { + speed = avspeed; + if ((avoidmode & avoidside) && !rldata->insideline && sideratio < 1.0 && + ((rldata->rInverse > 0.0 && (avoidmode & avoidright) && speedangle < -(sideratio/10)) || + (rldata->rInverse < 0.0 && (avoidmode & avoidleft) && speedangle > (sideratio/10)))) + { + speed = slowavspeed; + } + } + else if ((mode == mode_correcting || (simtime - aligned_timer < 2.0)) && rldata->insideline && rldata->closing) + { + speed = slowavspeed; + } + else if ((mode == mode_correcting || (simtime - aligned_timer < 5.0))) + { + //avspeed = MIN(rldata->speed - MIN(3.0, fabs(rldata->rInverse)*400), avspeed); + avspeed = MIN(rldata->speed, (slowavspeed+avspeed)/2); + double rlspeed = rldata->speed;//MAX(avspeed, rldata->speed-1.0); + //speed = avspeed + (rlspeed-avspeed) * MAX(0.0, MIN(1.0, 1.0 - MAX(fabs(correctlimit*2), fabs(fabs(laststeer)-fabs(rldata->rInverse*80))/2))); + speed = avspeed + (rlspeed-avspeed) * MAX(0.0, MIN(1.0, 1.0 - (fabs(correctlimit*2) + fabs(angle - rldata->rlangle)*5))); + } - if (pit->getInPit() && !pit->getPitstop()) - { - float s = pit->toSplineCoord( car->_distFromStartLine ); - if (s > pit->getNPitEnd()) - speed = MIN(speed, PitExitSpeed); - } + if (pit->getInPit() && !pit->getPitstop()) + { + float s = pit->toSplineCoord( car->_distFromStartLine ); + if (s > pit->getNPitEnd()) + speed = MIN(speed, PitExitSpeed); + } - //if (mode == mode_normal && fabs(rldata->rInverse) < 0.001 && fabs(car->_steerCmd) < 0.01 && fabs(angle) < 0.01 && fabs(car->_yaw_rate) < 0.01) - // aligned_timer = 0.0; + //if (mode == mode_normal && fabs(rldata->rInverse) < 0.001 && fabs(car->_steerCmd) < 0.01 && fabs(angle) < 0.01 && fabs(car->_yaw_rate) < 0.01) + // aligned_timer = 0.0; - double x = (10 + car->_speed_x) * (speed - car->_speed_x) / 200; - double lane2left = car->_trkPos.toLeft / track->width; - double lane2right = car->_trkPos.toRight / track->width; - int sidedanger = ((rldata->rInverse > 0.0 && speedangle < -(rldata->rInverse) * lane2left*2) || (rldata->rInverse < 0.0 && speedangle > rldata->rInverse*lane2right*2)); - double skid = MAX(0.0, (car->_skid[2] + car->_skid[3] + car->_skid[0] + car->_skid[1])) * 3; + double x = (10 + car->_speed_x) * (speed - car->_speed_x) / 200; + double lane2left = car->_trkPos.toLeft / track->width; + double lane2right = car->_trkPos.toRight / track->width; + int sidedanger = ((rldata->rInverse > 0.0 && speedangle < -(rldata->rInverse) * lane2left*2) || (rldata->rInverse < 0.0 && speedangle > rldata->rInverse*lane2right*2)); + double skid = MAX(0.0, (car->_skid[2] + car->_skid[3] + car->_skid[0] + car->_skid[1])) * 3; - brakecmd = 0.0f; - accelcmd = 100.0f; + brakecmd = 0.0f; + accelcmd = 100.0f; - { - double skidangle = angle; - if (mode != mode_normal) - { - if ((angle > 0.0 && speedangle < angle) || - (angle < 0.0 && speedangle > angle)) - skidangle += speedangle/2; - } + { + double skidangle = angle; + if (mode != mode_normal) + { + if ((angle > 0.0 && speedangle < angle) || + (angle < 0.0 && speedangle > angle)) + skidangle += speedangle/2; + } #if 0 - // if over/understeering, decrease speed - if (rldata->rInverse > 0.0) - { - double mod = ((laststeer-rldata->rInverse) * fabs(rldata->rInverse*15)); - if (mod < 0.0) // oversteer, will increase x but by less if skidding outwards - mod /= 4 - MIN(0.0, skidangle * 10); - x = MIN(x, 1.0) - mod; - } - else - { - double mod = ((laststeer-rldata->rInverse) * fabs(rldata->rInverse*15)); - if (mod > 0.0) // oversteer - mod /= 4 + MAX(0.0, skidangle * 10); - x = MIN(x, 1.0) + mod; - } + // if over/understeering, decrease speed + if (rldata->rInverse > 0.0) + { + double mod = ((laststeer-rldata->rInverse) * fabs(rldata->rInverse*15)); + if (mod < 0.0) // oversteer, will increase x but by less if skidding outwards + mod /= 4 - MIN(0.0, skidangle * 10); + x = MIN(x, 1.0) - mod; + } + else + { + double mod = ((laststeer-rldata->rInverse) * fabs(rldata->rInverse*15)); + if (mod > 0.0) // oversteer + mod /= 4 + MAX(0.0, skidangle * 10); + x = MIN(x, 1.0) + mod; + } #else - if (//(mode == mode_normal || !sidedanger) && - (skidangle < 0.0 && laststeer > 0.0 && rldata->rInverse < -0.001) || - (skidangle > 0.0 && laststeer < 0.0 && rldata->rInverse > 0.001)) - { - // increase acceleration if correcting a skid - double diff = MAX(0.0, MIN(fabs(laststeer), MAX(fabs(skidangle/7)/1000, fabs(rldata->rInverse * 50)))) * MAX(0.0, MIN(2.0, (7-skid))); - if (collision) - diff *= MIN(1.0, collision / 3.0f)*0.8; - x += diff * OversteerASR; - } - else if (mode != mode_normal && - (car->_accel_x < 1.0 || sidedanger) && - ((angle > 0.0 && laststeer > 0.0 && rldata->rInverse < -0.001) || - (angle < 0.0 && laststeer < 0.0 && rldata->rInverse > 0.001))) - { - // understeering, decrease speed - double diff = MIN(fabs(laststeer), MAX(fabs(angle)/50, fabs(rldata->rInverse * 50))) * 4; - x -= diff; - } + if (//(mode == mode_normal || !sidedanger) && + (skidangle < 0.0 && laststeer > 0.0 && rldata->rInverse < -0.001) || + (skidangle > 0.0 && laststeer < 0.0 && rldata->rInverse > 0.001)) + { + // increase acceleration if correcting a skid + double diff = MAX(0.0, MIN(fabs(laststeer), MAX(fabs(skidangle/7)/1000, fabs(rldata->rInverse * 50)))) * MAX(0.0, MIN(2.0, (7-skid))); + if (collision) + diff *= MIN(1.0, collision / 3.0f)*0.8; + x += diff * OversteerASR; + } + else if (mode != mode_normal && + (car->_accel_x < 1.0 || sidedanger) && + ((angle > 0.0 && laststeer > 0.0 && rldata->rInverse < -0.001) || + (angle < 0.0 && laststeer < 0.0 && rldata->rInverse > 0.001))) + { + // understeering, decrease speed + double diff = MIN(fabs(laststeer), MAX(fabs(angle)/50, fabs(rldata->rInverse * 50))) * 4; + x -= diff; + } #endif #if 0 - // check if we're really close behind someone on a bend - // if so (and we're not overtaking) make sure we don't under-brake or - // over-accelerate and thus lose control. - fbrakecmd = faccelcmd = 0.0f; + // check if we're really close behind someone on a bend + // if so (and we're not overtaking) make sure we don't under-brake or + // over-accelerate and thus lose control. + fbrakecmd = faccelcmd = 0.0f; - if (mode == mode_normal) - { - for (int i=0; igetNOpponents(); i++) - { - tCarElt *ocar = opponent[i].getCarPtr(); + if (mode == mode_normal) + { + for (int i=0; igetNOpponents(); i++) + { + tCarElt *ocar = opponent[i].getCarPtr(); - if (ocar == car) - continue; + if (ocar == car) + continue; - if (opponent[i].getTeam() != TEAM_FRIEND) - continue; + if (opponent[i].getTeam() != TEAM_FRIEND) + continue; - if (!(opponent[i].getState() & OPP_FRONT) || opponent[i].getDistance() > 3.0) - continue; + if (!(opponent[i].getState() & OPP_FRONT) || opponent[i].getDistance() > 3.0) + continue; - if (fabs(car->_trkPos.toLeft - ocar->_trkPos.toLeft) > car->_dimension_x*0.8) - continue; + if (fabs(car->_trkPos.toLeft - ocar->_trkPos.toLeft) > car->_dimension_x*0.8) + continue; - if (mode == mode_normal && opponent[i].isTeamMate() && opponent[i].getDistance() < 1.5) - { - accelcmd = ocar->_accelCmd; - if (accelcmd > 0.0f) - faccelcmd = accelcmd; - } + if (mode == mode_normal && opponent[i].isTeamMate() && opponent[i].getDistance() < 1.5) + { + accelcmd = ocar->_accelCmd; + if (accelcmd > 0.0f) + faccelcmd = accelcmd; + } - /* - if ((rldata->rInverse > 0.001 && car->_trkPos.toLeft > rldata->lane * car->_trkPos.seg->width) || - (rldata->rInverse < -0.001 && car->_trkPos.toLeft < rldata->lane * car->_trkPos.seg->width)) - { - double change = MAX(currentspeed-rldata->speed, fabs(car->_trkPos.toLeft - (rldata->lane * car->_trkPos.seg->width))); + /* + if ((rldata->rInverse > 0.001 && car->_trkPos.toLeft > rldata->lane * car->_trkPos.seg->width) || + (rldata->rInverse < -0.001 && car->_trkPos.toLeft < rldata->lane * car->_trkPos.seg->width)) + { + double change = MAX(currentspeed-rldata->speed, fabs(car->_trkPos.toLeft - (rldata->lane * car->_trkPos.seg->width))); - x -= MAX(0.0, MIN(1.0, change)); - break; - } - */ + x -= MAX(0.0, MIN(1.0, change)); + break; + } + */ - if (opponent[i].getDistance() < 1.5 && ocar->_brakeCmd > 0.0 && (opponent[i].getState() & OPP_COLL)) - { - brakecmd = ocar->_brakeCmd*MAX(1.0, currentspeed / opponent[i].getSpeed()); - if (brakecmd > 0.0) - { - x = MIN(x, -0.001); - fbrakecmd = brakecmd; - } - } + if (opponent[i].getDistance() < 1.5 && ocar->_brakeCmd > 0.0 && (opponent[i].getState() & OPP_COLL)) + { + brakecmd = ocar->_brakeCmd*MAX(1.0, currentspeed / opponent[i].getSpeed()); + if (brakecmd > 0.0) + { + x = MIN(x, -0.001); + fbrakecmd = brakecmd; + } + } - break; - } - } + break; + } + } #endif - } + } - if (x > 0) - { - if (accelcmd < 100.0f) - accelcmd = MIN(accelcmd, (float) x); - else - accelcmd = (float) x; - accelcmd = MAX(accelcmd, MinAccel); - } - else - brakecmd = MIN(1.0f, MAX(brakecmd, (float) (-(MAX(10.0, brakedelay*0.7))*x))); + if (x > 0) + { + if (accelcmd < 100.0f) + accelcmd = MIN(accelcmd, (float) x); + else + accelcmd = (float) x; + accelcmd = MAX(accelcmd, MinAccel); + } + else + brakecmd = MIN(1.0f, MAX(brakecmd, (float) (-(MAX(10.0, brakedelay*0.7))*x))); } int Driver::rearOffTrack() @@ -847,113 +843,113 @@ int Driver::rearOffTrack() // Drive during race. void Driver::drive(tSituation *s) { - laststeer = car->_steerCmd; - memset(&car->ctrl, 0, sizeof(tCarCtrl)); + laststeer = car->_steerCmd; + memset(&car->ctrl, 0, sizeof(tCarCtrl)); - skipcount++; + skipcount++; - if (skipcount > SKIPLIMIT) - skipcount = 0; + if (skipcount > SKIPLIMIT) + skipcount = 0; - if (skipcount > 1) - { - // potentially can skip (we never do if skipcount == 0) + if (skipcount > 1) + { + // potentially can skip (we never do if skipcount == 0) - if (mode == mode_normal) - { - // driving on the raceline - if (fabs(car->_yaw_rate) < 0.15 && - fabs(car->_accel_x) > -2 && - fabs(speedangle - angle) < 0.1) - { - // car not under stress, we can skip - car->_accelCmd = cmd_accel; - car->_brakeCmd = cmd_brake; - car->_steerCmd = cmd_steer; - car->_gearCmd = cmd_gear; - car->_clutchCmd = cmd_clutch; - car->_lightCmd = (int)cmd_light; - return; - } - } - else - { - // we're avoiding someone, don't skip (for the most part) - if (skipcount > 2) - skipcount = 0; - } - } + if (mode == mode_normal) + { + // driving on the raceline + if (fabs(car->_yaw_rate) < 0.15 && + fabs(car->_accel_x) > -2 && + fabs(speedangle - angle) < 0.1) + { + // car not under stress, we can skip + car->_accelCmd = cmd_accel; + car->_brakeCmd = cmd_brake; + car->_steerCmd = cmd_steer; + car->_gearCmd = cmd_gear; + car->_clutchCmd = cmd_clutch; + car->_lightCmd = (int)cmd_light; + return; + } + } + else + { + // we're avoiding someone, don't skip (for the most part) + if (skipcount > 2) + skipcount = 0; + } + } - update(s); + update(s); - //pit->setPitstop(true); + //pit->setPitstop(true); #ifdef CONTROL_SKILL - calcSkill(); + calcSkill(); #endif - car->_steerCmd = getSteer(s); + car->_steerCmd = getSteer(s); - if (!isStuck()) - { - car->_gearCmd = getGear(); - calcSpeed(); - car->_brakeCmd = filterABS(filterBrakeSpeed(filterBColl(filterBPit(getBrake())))); - if (car->_brakeCmd == 0.0f) { - car->_accelCmd = filterTCL(filterTrk(filterTeam(filterOverlap(getAccel())))); - } else { - car->_accelCmd = 0.0f; - } + if (!isStuck()) + { + car->_gearCmd = getGear(); + calcSpeed(); + car->_brakeCmd = filterABS(filterBrakeSpeed(filterBColl(filterBPit(getBrake())))); + if (car->_brakeCmd == 0.0f) { + car->_accelCmd = filterTCL(filterTrk(filterTeam(filterOverlap(getAccel())))); + } else { + car->_accelCmd = 0.0f; + } - if (!collision && fabs(car->_speed_x) < 1.0) - { - car->_accelCmd = MAX(car->_accelCmd, 0.4f); - car->_brakeCmd = 0.0f; - } + if (!collision && fabs(car->_speed_x) < 1.0) + { + car->_accelCmd = MAX(car->_accelCmd, 0.4f); + car->_brakeCmd = 0.0f; + } - if (car->_speed_x < -1.0f) - { - car->_accelCmd = 0.0f; - car->_brakeCmd = 0.7f; - } + if (car->_speed_x < -1.0f) + { + car->_accelCmd = 0.0f; + car->_brakeCmd = 0.7f; + } - car->_clutchCmd = getClutch(); - if (DebugMsg & debug_steer) - fprintf(stderr,"%s %d/%d: ",car->_name,rldata->thisdiv,rldata->nextdiv); + car->_clutchCmd = getClutch(); + if (DebugMsg & debug_steer) + fprintf(stderr,"%s %d/%d: ",car->_name,rldata->thisdiv,rldata->nextdiv); - } + } - if (DebugMsg & debug_steer) - { - double skid = (car->_skid[0]+car->_skid[1]+car->_skid[2]+car->_skid[3])/2; - fprintf(stderr,"%d%c%c%c s%.2f k%.2f ss%.2f cl%.3f g%d->%d brk%.3f acc%.2f dec%.2f coll%.1f",mode,((mode==mode_avoiding)?'A':' '),(avoidmode==avoidleft?'L':(avoidmode==avoidright?'R':' ')),(mode==mode_correcting?'c':' '),car->_steerCmd,rldata->ksteer,stucksteer,correctlimit,car->_gear,car->_gearCmd,car->_brakeCmd,car->_accelCmd,rldata->decel,collision); - fprintf(stderr," spd%.1f|k%.1f|a%.1f/%.1f|t%.1f angle=%.2f/%.2f/%.2f yr=%.2f skid=%.2f acxy=%.2f/%.2f slip=%.3f/%.3f %.3f/%.3f\n",(double)currentspeed,(double)rldata->speed,(double)rldata->avspeed,(double)rldata->slowavspeed,(double)getTrueSpeed(),angle,speedangle,rldata->rlangle,car->_yaw_rate,skid,car->_accel_x,car->_accel_y,nextCRinverse,rldata->mInverse,car->_wheelSpinVel(FRNT_RGT)*car->_wheelRadius(FRNT_RGT)-car->_speed_x,car->_wheelSpinVel(FRNT_LFT)*car->_wheelRadius(FRNT_LFT)-car->_speed_x,car->_wheelSpinVel(REAR_RGT)*car->_wheelRadius(REAR_RGT)-car->_speed_x,car->_wheelSpinVel(REAR_LFT)*car->_wheelRadius(REAR_LFT)-car->_speed_x);fflush(stderr); - } + if (DebugMsg & debug_steer) + { + double skid = (car->_skid[0]+car->_skid[1]+car->_skid[2]+car->_skid[3])/2; + fprintf(stderr,"%d%c%c%c s%.2f k%.2f ss%.2f cl%.3f g%d->%d brk%.3f acc%.2f dec%.2f coll%.1f",mode,((mode==mode_avoiding)?'A':' '),(avoidmode==avoidleft?'L':(avoidmode==avoidright?'R':' ')),(mode==mode_correcting?'c':' '),car->_steerCmd,rldata->ksteer,stucksteer,correctlimit,car->_gear,car->_gearCmd,car->_brakeCmd,car->_accelCmd,rldata->decel,collision); + fprintf(stderr," spd%.1f|k%.1f|a%.1f/%.1f|t%.1f angle=%.2f/%.2f/%.2f yr=%.2f skid=%.2f acxy=%.2f/%.2f slip=%.3f/%.3f %.3f/%.3f\n",(double)currentspeed,(double)rldata->speed,(double)rldata->avspeed,(double)rldata->slowavspeed,(double)getTrueSpeed(),angle,speedangle,rldata->rlangle,car->_yaw_rate,skid,car->_accel_x,car->_accel_y,nextCRinverse,rldata->mInverse,car->_wheelSpinVel(FRNT_RGT)*car->_wheelRadius(FRNT_RGT)-car->_speed_x,car->_wheelSpinVel(FRNT_LFT)*car->_wheelRadius(FRNT_LFT)-car->_speed_x,car->_wheelSpinVel(REAR_RGT)*car->_wheelRadius(REAR_RGT)-car->_speed_x,car->_wheelSpinVel(REAR_LFT)*car->_wheelRadius(REAR_LFT)-car->_speed_x);fflush(stderr); + } - laststeer = car->_steerCmd; - lastbrake = car->_brakeCmd; - lastaccel = car->_accelCmd; - lastmode = mode; - prevleft = car->_trkPos.toLeft; + laststeer = car->_steerCmd; + lastbrake = car->_brakeCmd; + lastaccel = car->_accelCmd; + lastmode = mode; + prevleft = car->_trkPos.toLeft; - cmd_accel = car->_accelCmd; - cmd_brake = car->_brakeCmd; - cmd_steer = car->_steerCmd; - cmd_clutch = car->_clutchCmd; - cmd_gear = car->_gearCmd; - cmd_light = (float)car->_lightCmd; + cmd_accel = car->_accelCmd; + cmd_brake = car->_brakeCmd; + cmd_steer = car->_steerCmd; + cmd_clutch = car->_clutchCmd; + cmd_gear = car->_gearCmd; + cmd_light = (float)car->_lightCmd; } // Set pitstop commands. int Driver::pitCommand(tSituation *s) { - car->_pitRepair = strategy->pitRepair(car, s); - car->_pitFuel = strategy->pitRefuel(car, s); - // This should be the only place where the pit stop is set to false! - pit->setPitstop(false); - return ROB_PIT_IM; // return immediately. + car->_pitRepair = strategy->pitRepair(car, s); + car->_pitFuel = strategy->pitRefuel(car, s); + // This should be the only place where the pit stop is set to false! + pit->setPitstop(false); + return ROB_PIT_IM; // return immediately. } @@ -962,16 +958,16 @@ int Driver::pitCommand(tSituation *s) void Driver::endRace(tSituation *s) { #ifdef SPEED_DREAMS - RtTeamReleasePit(teamIndex); + RtTeamReleasePit(teamIndex); #endif - car->ctrl.raceCmd = 0; + car->ctrl.raceCmd = 0; } // cleanup void Driver::shutdown() { #ifdef SPEED_DREAMS - RtTeamManagerRelease(); + RtTeamManagerRelease(); #endif } @@ -985,32 +981,32 @@ void Driver::shutdown() void Driver::computeRadius(float *radius) { - float lastturnarc = 0.0f; - int lastsegtype = TR_STR; + float lastturnarc = 0.0f; + int lastsegtype = TR_STR; - tTrackSeg *currentseg, *startseg = track->seg; - currentseg = startseg; + tTrackSeg *currentseg, *startseg = track->seg; + currentseg = startseg; - do { - if (currentseg->type == TR_STR) { - lastsegtype = TR_STR; - radius[currentseg->id] = FLT_MAX; - } else { - if (currentseg->type != lastsegtype) { - float arc = 0.0f; - tTrackSeg *s = currentseg; - lastsegtype = currentseg->type; + do { + if (currentseg->type == TR_STR) { + lastsegtype = TR_STR; + radius[currentseg->id] = FLT_MAX; + } else { + if (currentseg->type != lastsegtype) { + float arc = 0.0f; + tTrackSeg *s = currentseg; + lastsegtype = currentseg->type; - while (s->type == lastsegtype && arc < PI/2.0f) { - arc += s->arc; - s = s->next; - } - lastturnarc = (float) (arc/(PI/2.0f)); - } - radius[currentseg->id] = (float) (currentseg->radius + currentseg->width/2.0)/lastturnarc; - } - currentseg = currentseg->next; - } while (currentseg != startseg); + while (s->type == lastsegtype && arc < PI/2.0f) { + arc += s->arc; + s = s->next; + } + lastturnarc = (float) (arc/(PI/2.0f)); + } + radius[currentseg->id] = (float) (currentseg->radius + currentseg->width/2.0)/lastturnarc; + } + currentseg = currentseg->next; + } while (currentseg != startseg); } @@ -1018,63 +1014,63 @@ void Driver::computeRadius(float *radius) // Compute the length to the end of the segment. float Driver::getDistToSegEnd() { - if (car->_trkPos.seg->type == TR_STR) { - return car->_trkPos.seg->length - car->_trkPos.toStart; - } else { - return (car->_trkPos.seg->arc - car->_trkPos.toStart)*car->_trkPos.seg->radius; - } + if (car->_trkPos.seg->type == TR_STR) { + return car->_trkPos.seg->length - car->_trkPos.toStart; + } else { + return (car->_trkPos.seg->arc - car->_trkPos.toStart)*car->_trkPos.seg->radius; + } } // Compute fitting acceleration. float Driver::getAccel() { - if (car->_gear > 0) { - accelcmd = MIN(1.0f, accelcmd); + if (car->_gear > 0) { + accelcmd = MIN(1.0f, accelcmd); - if (pit->getInPit() && car->_brakeCmd == 0.0f) - { - //float s = pit->toSplineCoord( car->_distFromStartLine ); - + if (pit->getInPit() && car->_brakeCmd == 0.0f) + { + //float s = pit->toSplineCoord( car->_distFromStartLine ); + #if 0 - if (pit->needPitstop()) - { - if (currentspeedsqr > pit->getSpeedlimitSqr()*0.9) - { - accelcmd = MIN(accelcmd, 0.4f); - } - } + if (pit->needPitstop()) + { + if (currentspeedsqr > pit->getSpeedlimitSqr()*0.9) + { + accelcmd = MIN(accelcmd, 0.4f); + } + } #endif - - accelcmd = MIN(accelcmd, 0.6f); - } - else if (fabs(angle) > 0.8 && currentspeed > 10.0f) - accelcmd = MAX(0.0f, MIN(accelcmd, 1.0f - currentspeed/100.0f * fabs(angle))); + + accelcmd = MIN(accelcmd, 0.6f); + } + else if (fabs(angle) > 0.8 && currentspeed > 10.0f) + accelcmd = MAX(0.0f, MIN(accelcmd, 1.0f - currentspeed/100.0f * fabs(angle))); - return accelcmd; - } else { - return 1.0; - } + return accelcmd; + } else { + return 1.0; + } } // If we get lapped reduce accelerator. float Driver::filterOverlap(float accel) { - int i; + int i; - if (!(avoidmode & avoidback)) - { - return accel; - } + if (!(avoidmode & avoidback)) + { + return accel; + } - for (i = 0; i < opponents->getNOpponents(); i++) { - if (opponent[i].getState() & OPP_LETPASS) - { - return accel*0.4f; - } - } - return accel; + for (i = 0; i < opponents->getNOpponents(); i++) { + if (opponent[i].getState() & OPP_LETPASS) + { + return accel*0.4f; + } + } + return accel; } // slows us down to allow a team-member to catch up @@ -1166,81 +1162,81 @@ double Driver::filterTeam(double accel) // Compute initial brake value. float Driver::getBrake() { - // Car drives backward? - if (car->_speed_x < -MAX_UNSTUCK_SPEED) { - // Yes, brake. - return 1.0; - } else { - // We drive forward, normal braking. + // Car drives backward? + if (car->_speed_x < -MAX_UNSTUCK_SPEED) { + // Yes, brake. + return 1.0; + } else { + // We drive forward, normal braking. #ifdef CONTROL_SKILL - brakecmd *= brake_adjust_perc; + brakecmd *= brake_adjust_perc; #endif - return brakecmd; - } + return brakecmd; + } } // Compute gear. int Driver::getGear() { - car->_gearCmd = car->_gear; - if (car->_gear <= 0) { - return 1; - } + car->_gearCmd = car->_gear; + if (car->_gear <= 0) { + return 1; + } #if 1 - // Hymie gear changing - float speed = currentspeed; - float *tRatio = car->_gearRatio + car->_gearOffset; - float rpm = (float) ((speed + 0.5) * tRatio[car->_gear] / car->_wheelRadius(2)); - float down_rpm = (float) (car->_gear > 1 ? (speed + 0.5) * tRatio[car->_gear-1] / car->_wheelRadius(2) : rpm); + // Hymie gear changing + float speed = currentspeed; + float *tRatio = car->_gearRatio + car->_gearOffset; + float rpm = (float) ((speed + 0.5) * tRatio[car->_gear] / car->_wheelRadius(2)); + float down_rpm = (float) (car->_gear > 1 ? (speed + 0.5) * tRatio[car->_gear-1] / car->_wheelRadius(2) : rpm); - float rcu = (car->_gear < 6 && car->_gear >= 0 ? GearRevsChangeUp[car->_gear] : RevsChangeUp); - float rcd = (car->_gear < 6 && car->_gear >= 0 ? GearRevsChangeDown[car->_gear] : RevsChangeDown); - float rcm = (car->_gear < 6 && car->_gear >= 0 ? GearRevsChangeDownMax[car->_gear] : RevsChangeDownMax); + float rcu = (car->_gear < 6 && car->_gear >= 0 ? GearRevsChangeUp[car->_gear] : RevsChangeUp); + float rcd = (car->_gear < 6 && car->_gear >= 0 ? GearRevsChangeDown[car->_gear] : RevsChangeDown); + float rcm = (car->_gear < 6 && car->_gear >= 0 ? GearRevsChangeDownMax[car->_gear] : RevsChangeDownMax); - if (rpm + MAX(0.0, (double) (car->_gear-3) * (car->_gear-3)*5) > car->_enginerpmMax * rcu && car->_gear < MaxGear) - car->_gearCmd = car->_gear + 1; + if (rpm + MAX(0.0, (double) (car->_gear-3) * (car->_gear-3)*5) > car->_enginerpmMax * rcu && car->_gear < MaxGear) + car->_gearCmd = car->_gear + 1; - if (car->_gear > 1 && - rpm < car->_enginerpmMax * rcd && - down_rpm < car->_enginerpmMax * rcm) - car->_gearCmd = car->_gear - 1; + if (car->_gear > 1 && + rpm < car->_enginerpmMax * rcd && + down_rpm < car->_enginerpmMax * rcm) + car->_gearCmd = car->_gear - 1; #else - // BT gear changing - float gr_up = car->_gearRatio[car->_gear + car->_gearOffset]; - float omega = car->_enginerpmRedLine/gr_up; - float wr = car->_wheelRadius(2); + // BT gear changing + float gr_up = car->_gearRatio[car->_gear + car->_gearOffset]; + float omega = car->_enginerpmRedLine/gr_up; + float wr = car->_wheelRadius(2); - if (omega*wr*SHIFT < car->_speed_x) { - car->_gearCmd = car->_gear + 1; - } else { - float gr_down = car->_gearRatio[car->_gear + car->_gearOffset - 1]; - omega = car->_enginerpmRedLine/gr_down; - if (car->_gear > 1 && omega*wr*SHIFT > car->_speed_x + SHIFT_MARGIN) { - car->_gearCmd = car->_gear - 1; - } - } + if (omega*wr*SHIFT < car->_speed_x) { + car->_gearCmd = car->_gear + 1; + } else { + float gr_down = car->_gearRatio[car->_gear + car->_gearOffset - 1]; + omega = car->_enginerpmRedLine/gr_down; + if (car->_gear > 1 && omega*wr*SHIFT > car->_speed_x + SHIFT_MARGIN) { + car->_gearCmd = car->_gear - 1; + } + } #endif - - return car->_gearCmd; + + return car->_gearCmd; } void Driver::setMode( int newmode ) { - if (mode == newmode) - return; + if (mode == newmode) + return; - if (mode == mode_normal || mode == mode_pitting) - { - correcttimer = simtime + 7.0; - //correctlimit = 1000.0; - } + if (mode == mode_normal || mode == mode_pitting) + { + correcttimer = simtime + 7.0; + //correctlimit = 1000.0; + } - if (newmode == mode_avoiding && mode != mode_avoiding) - avoidtime = simtime; + if (newmode == mode_avoiding && mode != mode_avoiding) + avoidtime = simtime; - mode = newmode; + mode = newmode; } void Driver::calcSkill() @@ -1282,331 +1278,331 @@ void Driver::calcSkill() double Driver::getFollowDistance() { - double mindist = 1000.0; + double mindist = 1000.0; - if (mode != mode_normal) - return mindist; + if (mode != mode_normal) + return mindist; - for (int i = 0; i < opponents->getNOpponents(); i++) - { - if (opponent[i].getCarPtr() == car) continue; - //if (opponent[i].getTeam() != TEAM_FRIEND) continue; - if (!(opponent[i].getState() & OPP_FRONT)) - continue; + for (int i = 0; i < opponents->getNOpponents(); i++) + { + if (opponent[i].getCarPtr() == car) continue; + //if (opponent[i].getTeam() != TEAM_FRIEND) continue; + if (!(opponent[i].getState() & OPP_FRONT)) + continue; - if (opponent[i].getDistance() > 5.0) - continue; + if (opponent[i].getDistance() > 5.0) + continue; - mindist = MIN(mindist, opponent[i].getDistance()) - FollowMargin; - } - return mindist; + mindist = MIN(mindist, opponent[i].getDistance()) - FollowMargin; + } + return mindist; } // Compute steer value. float Driver::getSteer(tSituation *s) { - double targetAngle; - memset(rldata, 0, sizeof(LRaceLineData)); - rldata->angle = angle; - rldata->speedangle = speedangle; - rldata->mode = mode; - rldata->avoidmode = avoidmode; - rldata->collision = collision; - rldata->steer = rldata->laststeer = laststeer; - rldata->alone = alone; - rldata->followdist = getFollowDistance(); - rldata->s = s; - rldata->aligned_time = simtime - aligned_timer; - raceline->GetRaceLineData( s, rldata ); - if (FuelSpeedUp) - { - double fuel = (car->_fuel/maxfuel); - fuel = MIN(1.0, fuel * (fuel+0.15)); - rldata->speed += FuelSpeedUp * (1.0 - fuel); - } - double steer = 0.0, tmpsteer = 0.0; - double avoidsteer = 0.0; - double racesteer = (rldata->ksteer); - vec2f target; + double targetAngle; + memset(rldata, 0, sizeof(LRaceLineData)); + rldata->angle = angle; + rldata->speedangle = speedangle; + rldata->mode = mode; + rldata->avoidmode = avoidmode; + rldata->collision = collision; + rldata->steer = rldata->laststeer = laststeer; + rldata->alone = alone; + rldata->followdist = getFollowDistance(); + rldata->s = s; + rldata->aligned_time = simtime - aligned_timer; + raceline->GetRaceLineData( s, rldata ); + if (FuelSpeedUp) + { + double fuel = (car->_fuel/maxfuel); + fuel = MIN(1.0, fuel * (fuel+0.15)); + rldata->speed += FuelSpeedUp * (1.0 - fuel); + } + double steer = 0.0, tmpsteer = 0.0; + double avoidsteer = 0.0; + double racesteer = (rldata->ksteer); + vec2f target; #if 0 - if (SteerLookahead > 6.0f) - { - raceline->GetSteerPoint( (double) SteerLookahead, &target ); - targetAngle = atan2(target.y - car->_pos_Y, target.x - car->_pos_X); - racesteer = calcSteer( targetAngle, 0 ); - double rIf = MIN(1.0, fabs(rldata->rInverse) / SteerMaxRI); - racesteer = racesteer + (rldata->ksteer - racesteer) * rIf; - } + if (SteerLookahead > 6.0f) + { + raceline->GetSteerPoint( (double) SteerLookahead, &target ); + targetAngle = atan2(target.y - car->_pos_Y, target.x - car->_pos_X); + racesteer = calcSteer( targetAngle, 0 ); + double rIf = MIN(1.0, fabs(rldata->rInverse) / SteerMaxRI); + racesteer = racesteer + (rldata->ksteer - racesteer) * rIf; + } #endif - target = getTargetPoint(false); - steer = avoidsteer = racesteer; - lastNSksteer = rldata->NSsteer; + target = getTargetPoint(false); + steer = avoidsteer = racesteer; + lastNSksteer = rldata->NSsteer; - if (mode != mode_normal || SteerLookahead < 6.0f) - { - targetAngle = atan2(target.y - car->_pos_Y, target.x - car->_pos_X); - tmpsteer = calcSteer( targetAngle, 0 ); - } + if (mode != mode_normal || SteerLookahead < 6.0f) + { + targetAngle = atan2(target.y - car->_pos_Y, target.x - car->_pos_X); + tmpsteer = calcSteer( targetAngle, 0 ); + } - if (mode != mode_normal) - { - avoidsteer = tmpsteer; + if (mode != mode_normal) + { + avoidsteer = tmpsteer; - if (mode == mode_pitting) - { - correctlimit = (avoidsteer - racesteer); - return avoidsteer; - } + if (mode == mode_pitting) + { + correctlimit = (avoidsteer - racesteer); + return avoidsteer; + } - //targetAngle = atan2(rldata->target.y - car->_pos_Y, rldata->target.x - car->_pos_X); + //targetAngle = atan2(rldata->target.y - car->_pos_Y, rldata->target.x - car->_pos_X); - allowcorrecting = 0; - if (mode == mode_avoiding && - (!avoidmode || - (avoidmode == avoidright && racesteer > avoidsteer) || - (avoidmode == avoidleft && racesteer < avoidsteer))) - { - // we're avoiding, but trying to steer somewhere the raceline takes us. - // hence we'll just correct towards the raceline instead. - allowcorrecting = 1; - } + allowcorrecting = 0; + if (mode == mode_avoiding && + (!avoidmode || + (avoidmode == avoidright && racesteer > avoidsteer) || + (avoidmode == avoidleft && racesteer < avoidsteer))) + { + // we're avoiding, but trying to steer somewhere the raceline takes us. + // hence we'll just correct towards the raceline instead. + allowcorrecting = 1; + } - bool yr_ok = (fabs(car->_yaw_rate) < 0.1 || (car->_yaw_rate > rldata->rInverse*100-0.1 && car->_yaw_rate < rldata->rInverse*100+0.1)); - bool angle_ok = (angle > rldata->rlangle-0.06 && angle < rldata->rlangle+0.06); - //double rlsteer = (fabs(rldata->rInverse) >= 0.004 ? rldata->rInverse * 12 : 0.0); - bool steer_ok = (racesteerlaststeer-0.05); + bool yr_ok = (fabs(car->_yaw_rate) < 0.1 || (car->_yaw_rate > rldata->rInverse*100-0.1 && car->_yaw_rate < rldata->rInverse*100+0.1)); + bool angle_ok = (angle > rldata->rlangle-0.06 && angle < rldata->rlangle+0.06); + //double rlsteer = (fabs(rldata->rInverse) >= 0.004 ? rldata->rInverse * 12 : 0.0); + bool steer_ok = (racesteerlaststeer-0.05); - double skid = (car->_skid[0] + car->_skid[1] + car->_skid[2] + car->_skid[3]) / 2; - if (mode == mode_correcting) - { - if (lastmode == mode_normal || - (angle_ok && - (simtime > 15.0 || car->_speed_x > 20) && - yr_ok && - skid < 0.1 && - steer_ok && - ((fabs(car->_trkPos.toMiddle) < car->_trkPos.seg->width/2 - 1.0) || car->_speed_x < 10.0) && - (raceline->isOnLine()))) - { - // we're correcting & are now close enough to the raceline to - // switch back to 'normal' mode... - setMode( mode_normal ); - aligned_timer = simtime; - steer = racesteer; - if (DebugMsg & debug_steer) - fprintf(stderr,"ALIGNED steer_ok=%d avsteer=%.3f racest=%.3f\n",steer_ok,avoidsteer,racesteer); - } - else if (DebugMsg & debug_steer) - fprintf(stderr,"NOT ALIGNED %d %d %d %d %.2f %.2f %.2f\n",angle_ok,yr_ok,(skid<0.1),steer_ok,avoidsteer,racesteer,laststeer); - } + double skid = (car->_skid[0] + car->_skid[1] + car->_skid[2] + car->_skid[3]) / 2; + if (mode == mode_correcting) + { + if (lastmode == mode_normal || + (angle_ok && + (simtime > 15.0 || car->_speed_x > 20) && + yr_ok && + skid < 0.1 && + steer_ok && + ((fabs(car->_trkPos.toMiddle) < car->_trkPos.seg->width/2 - 1.0) || car->_speed_x < 10.0) && + (raceline->isOnLine()))) + { + // we're correcting & are now close enough to the raceline to + // switch back to 'normal' mode... + setMode( mode_normal ); + aligned_timer = simtime; + steer = racesteer; + if (DebugMsg & debug_steer) + fprintf(stderr,"ALIGNED steer_ok=%d avsteer=%.3f racest=%.3f\n",steer_ok,avoidsteer,racesteer); + } + else if (DebugMsg & debug_steer) + fprintf(stderr,"NOT ALIGNED %d %d %d %d %.2f %.2f %.2f\n",angle_ok,yr_ok,(skid<0.1),steer_ok,avoidsteer,racesteer,laststeer); + } - if (mode != mode_normal) - { - if (mode != mode_correcting && !allowcorrecting) - { - int flying = checkFlying(); - if (flying & FLYING_FRONT) - { - steer = 0.0; - } - else if (flying & FLYING_BACK) - { - steer /= 3.0; - } - else - { - //correctlimit = 1000.0; - correcttimer = simtime + 7.0; - steer = ( avoidsteer ); - } - double climit = (steer - racesteer); - if (fabs(climit) > fabs(correctlimit)) - correctlimit = climit; - } - else - { - steer = (correctSteering( avoidsteer, racesteer )); - correctlimit = (steer - racesteer); - } - - if (fabs(angle) >= 1.6) - { - if (steer > 0.0) - steer = 1.0; - else - steer = -1.0; - } - } - else - correctlimit = (steer - racesteer); - } - else - { - raceline->NoAvoidSteer(); - lastNSasteer = rldata->NSsteer; - correctlimit = (steer - racesteer); - } + if (mode != mode_normal) + { + if (mode != mode_correcting && !allowcorrecting) + { + int flying = checkFlying(); + if (flying & FLYING_FRONT) + { + steer = 0.0; + } + else if (flying & FLYING_BACK) + { + steer /= 3.0; + } + else + { + //correctlimit = 1000.0; + correcttimer = simtime + 7.0; + steer = ( avoidsteer ); + } + double climit = (steer - racesteer); + if (fabs(climit) > fabs(correctlimit)) + correctlimit = climit; + } + else + { + steer = (correctSteering( avoidsteer, racesteer )); + correctlimit = (steer - racesteer); + } + + if (fabs(angle) >= 1.6) + { + if (steer > 0.0) + steer = 1.0; + else + steer = -1.0; + } + } + else + correctlimit = (steer - racesteer); + } + else + { + raceline->NoAvoidSteer(); + lastNSasteer = rldata->NSsteer; + correctlimit = (steer - racesteer); + } - if (mode == mode_avoiding && - (lastmode == mode_normal || lastmode == mode_correcting) && - !((avoidmode & avoidright) && (avoidmode & avoidleft))) - { - // if we're only avoiding on one side, and racesteer avoids more than avoidsteer, and just prior we - // weren't avoiding, return to prior mode. - if ((racesteer >= steer && avoidmode == avoidright) || - (racesteer <= steer && avoidmode == avoidleft)) - { - if (lastmode == mode_normal) - steer = racesteer; - setMode(lastmode); - } - } + if (mode == mode_avoiding && + (lastmode == mode_normal || lastmode == mode_correcting) && + !((avoidmode & avoidright) && (avoidmode & avoidleft))) + { + // if we're only avoiding on one side, and racesteer avoids more than avoidsteer, and just prior we + // weren't avoiding, return to prior mode. + if ((racesteer >= steer && avoidmode == avoidright) || + (racesteer <= steer && avoidmode == avoidleft)) + { + if (lastmode == mode_normal) + steer = racesteer; + setMode(lastmode); + } + } - return steer; + return steer; } double Driver::calcSteer( double targetAngle, int rl ) { #if 1 - if (mode != mode_pitting) - { - float kksteer = raceline->getAvoidSteer(myoffset, rldata); - return kksteer; - } + if (mode != mode_pitting) + { + float kksteer = raceline->getAvoidSteer(myoffset, rldata); + return kksteer; + } #endif - double rearskid = MAX(0.0, MAX(car->_skid[2], car->_skid[3]) - MAX(car->_skid[0], car->_skid[1])) + MAX(car->_skid[2], car->_skid[3]) * fabs(angle)*0.9; - double steer = 0.0; + double rearskid = MAX(0.0, MAX(car->_skid[2], car->_skid[3]) - MAX(car->_skid[0], car->_skid[1])) + MAX(car->_skid[2], car->_skid[3]) * fabs(angle)*0.9; + double steer = 0.0; #if 0 // olethros steering - double steer_direction = targetAngle - car->_yaw - 0.1 * car->_yaw_rate; + double steer_direction = targetAngle - car->_yaw - 0.1 * car->_yaw_rate; - double avoidance = 0.0; - if (!(pit->getInPit())) - { - if (car->_trkPos.toRight < car->_dimension_y) - avoidance = tanh(0.2 * (car->_dimension_y - car->_trkPos.toRight)); - else if (car->_trkPos.toLeft < car->_dimension_y) - avoidance = tanh(0.2 * (car->_trkPos.toLeft - car->_dimension_y)); - } + double avoidance = 0.0; + if (!(pit->getInPit())) + { + if (car->_trkPos.toRight < car->_dimension_y) + avoidance = tanh(0.2 * (car->_dimension_y - car->_trkPos.toRight)); + else if (car->_trkPos.toLeft < car->_dimension_y) + avoidance = tanh(0.2 * (car->_trkPos.toLeft - car->_dimension_y)); + } - tTrackSeg *seg = car->_trkPos.seg; - double correct_drift = -0.01 * atan2(car->_speed_Y, car->_speed_X); - NORM_PI_PI(steer_direction); + tTrackSeg *seg = car->_trkPos.seg; + double correct_drift = -0.01 * atan2(car->_speed_Y, car->_speed_X); + NORM_PI_PI(steer_direction); - steer = avoidance + correct_drift + steer_direction/car->_steerLock; + steer = avoidance + correct_drift + steer_direction/car->_steerLock; #else // old ki steering - double steer_direction = targetAngle - car->_yaw - car->_speed_x/300 * car->_yaw_rate; + double steer_direction = targetAngle - car->_yaw - car->_speed_x/300 * car->_yaw_rate; - NORM_PI_PI(steer_direction); - if (DebugMsg & debug_steer) - fprintf(stderr,"STEER tm%.2f off%.2f sd%.3f",car->_trkPos.toMiddle,myoffset,steer_direction); + NORM_PI_PI(steer_direction); + if (DebugMsg & debug_steer) + fprintf(stderr,"STEER tm%.2f off%.2f sd%.3f",car->_trkPos.toMiddle,myoffset,steer_direction); - if (car->_speed_x > 10.0 && mode != mode_normal && mode != mode_pitting) - { - double limit = MAX(20.0, 90.0 - car->_speed_x) * (((avoidmode & avoidside) ? 0.0074 : 0.0045) * SmoothSteer); - double rgtlimit = limit, lftlimit = limit; - if (laststeer_direction > 0.0) rgtlimit = MIN(laststeer_direction, rgtlimit*2); - if (laststeer_direction < 0.0) lftlimit = MIN(-laststeer_direction, lftlimit*2); + if (car->_speed_x > 10.0 && mode != mode_normal && mode != mode_pitting) + { + double limit = MAX(20.0, 90.0 - car->_speed_x) * (((avoidmode & avoidside) ? 0.0074 : 0.0045) * SmoothSteer); + double rgtlimit = limit, lftlimit = limit; + if (laststeer_direction > 0.0) rgtlimit = MIN(laststeer_direction, rgtlimit*2); + if (laststeer_direction < 0.0) lftlimit = MIN(-laststeer_direction, lftlimit*2); - steer_direction = MAX(laststeer_direction - rgtlimit, MIN(laststeer_direction + lftlimit, steer_direction)); + steer_direction = MAX(laststeer_direction - rgtlimit, MIN(laststeer_direction + lftlimit, steer_direction)); #if 1 - double speedsteer = (80.0 - MIN(70.0, MAX(40.0, currentspeed))) / - ((185.0 * MIN(1.0, car->_steerLock / 0.785)) + - (185.0 * (MIN(1.3, MAX(1.0, 1.0 + rearskid))) - 185.0)); - if (fabs(steer_direction) > speedsteer) - { - steer_direction = MAX(-speedsteer, MIN(speedsteer, steer_direction)); - } + double speedsteer = (80.0 - MIN(70.0, MAX(40.0, currentspeed))) / + ((185.0 * MIN(1.0, car->_steerLock / 0.785)) + + (185.0 * (MIN(1.3, MAX(1.0, 1.0 + rearskid))) - 185.0)); + if (fabs(steer_direction) > speedsteer) + { + steer_direction = MAX(-speedsteer, MIN(speedsteer, steer_direction)); + } #endif - } - laststeer_direction = steer_direction; + } + laststeer_direction = steer_direction; - steer = (steer_direction/car->_steerLock); - if (DebugMsg & debug_steer) - fprintf(stderr,"/sd%.3f a%.3f",steer_direction,steer); + steer = (steer_direction/car->_steerLock); + if (DebugMsg & debug_steer) + fprintf(stderr,"/sd%.3f a%.3f",steer_direction,steer); - if (DebugMsg & debug_steer) - fprintf(stderr," b%.3f",steer); + if (DebugMsg & debug_steer) + fprintf(stderr," b%.3f",steer); - lastNSasteer = steer; + lastNSasteer = steer; - double nextangle = angle + car->_yaw_rate/3; - if (fabs(nextangle) > fabs(speedangle)) - { - // steer into the skid - //double sa = MAX(-0.3, MIN(0.3, speedangle/3)); - //double anglediff = (sa - angle) * (0.3 + fabs(angle)/6); - double anglediff = (speedangle - nextangle) * (0.1 + fabs(nextangle)/6); - steer += (float) (anglediff*SkidSteer); - } + double nextangle = angle + car->_yaw_rate/3; + if (fabs(nextangle) > fabs(speedangle)) + { + // steer into the skid + //double sa = MAX(-0.3, MIN(0.3, speedangle/3)); + //double anglediff = (sa - angle) * (0.3 + fabs(angle)/6); + double anglediff = (speedangle - nextangle) * (0.1 + fabs(nextangle)/6); + steer += (float) (anglediff*SkidSteer); + } - if (fabs(angle) > 1.2) - { - if (steer > 0.0f) - steer = 1.0f; - else - steer = -1.0f; - } - else if (fabs(car->_trkPos.toMiddle) - car->_trkPos.seg->width/2 > 2.0) - { - steer = (float) MIN(1.0f, MAX(-1.0f, steer * (1.0f + (fabs(car->_trkPos.toMiddle) - car->_trkPos.seg->width/2)/14 + fabs(angle)/2))); - } + if (fabs(angle) > 1.2) + { + if (steer > 0.0f) + steer = 1.0f; + else + steer = -1.0f; + } + else if (fabs(car->_trkPos.toMiddle) - car->_trkPos.seg->width/2 > 2.0) + { + steer = (float) MIN(1.0f, MAX(-1.0f, steer * (1.0f + (fabs(car->_trkPos.toMiddle) - car->_trkPos.seg->width/2)/14 + fabs(angle)/2))); + } #endif // old ki steering - if (DebugMsg & debug_steer) - fprintf(stderr," d%.3f",steer); + if (DebugMsg & debug_steer) + fprintf(stderr," d%.3f",steer); - if (mode != mode_pitting) - { - // limit how far we can steer against last steer... - double limit = 0.0; - limit = ((90.0 - MAX(40.0, MIN(60.0, car->_speed_x))) / (120)) * SmoothSteer; // (130); - if (fabs(laststeer) > fabs(steer)) - limit = MAX(limit, fabs(laststeer)/2); - steer = MAX(laststeer-limit, MIN(laststeer+limit, steer)); - //steer = MAX(rldata->steer-limit, MIN(rldata->steer+limit, steer)); + if (mode != mode_pitting) + { + // limit how far we can steer against last steer... + double limit = 0.0; + limit = ((90.0 - MAX(40.0, MIN(60.0, car->_speed_x))) / (120)) * SmoothSteer; // (130); + if (fabs(laststeer) > fabs(steer)) + limit = MAX(limit, fabs(laststeer)/2); + steer = MAX(laststeer-limit, MIN(laststeer+limit, steer)); + //steer = MAX(rldata->steer-limit, MIN(rldata->steer+limit, steer)); #if 1 - if (simtime > 3.0) - { - // and against raceline... - double climit = fabs(correctlimit); + if (simtime > 3.0) + { + // and against raceline... + double climit = fabs(correctlimit); #if 0 - if (climit > 0.0 && angle - rldata->rlangle > 0.0) - climit += (angle - rldata->rlangle)/2; - else if (climit < 0.0 && angle - rldata->rlangle < 0.0) - climit -= fabs(angle - rldata->rlangle)/2; + if (climit > 0.0 && angle - rldata->rlangle > 0.0) + climit += (angle - rldata->rlangle)/2; + else if (climit < 0.0 && angle - rldata->rlangle < 0.0) + climit -= fabs(angle - rldata->rlangle)/2; #endif - double limitchange = ((90.0 - MAX(40.0, MIN(60.0, car->_speed_x))) / ((avoidmode & avoidside) ? 130 : 200)) * 3; - climit += limitchange; - steer = MAX(rldata->ksteer-climit, MIN(rldata->ksteer+climit, steer)); - } + double limitchange = ((90.0 - MAX(40.0, MIN(60.0, car->_speed_x))) / ((avoidmode & avoidside) ? 130 : 200)) * 3; + climit += limitchange; + steer = MAX(rldata->ksteer-climit, MIN(rldata->ksteer+climit, steer)); + } #endif - steer = smoothSteering(steer); - } + steer = smoothSteering(steer); + } #if 0 - else if (currentspeed > MAX(25.0, pit->getSpeedlimit())) - { - // stop sudden steer changes while pitting - double limit = MAX(0.1, (40 - fabs(currentspeed - pit->getSpeedlimit())) * 0.025); - steer = MIN(limit, MAX(-limit, steer)); - } + else if (currentspeed > MAX(25.0, pit->getSpeedlimit())) + { + // stop sudden steer changes while pitting + double limit = MAX(0.1, (40 - fabs(currentspeed - pit->getSpeedlimit())) * 0.025); + steer = MIN(limit, MAX(-limit, steer)); + } #endif - if (DebugMsg & debug_steer) - fprintf(stderr," e%.3f\n",steer); + if (DebugMsg & debug_steer) + fprintf(stderr," e%.3f\n",steer); - return steer; + return steer; } int Driver::checkFlying() @@ -1641,1806 +1637,1806 @@ int Driver::checkFlying() float Driver::correctSteering( float avoidsteer, float racesteer ) { - if (simtime < 15.0 && car->_speed_x < 20.0) - return avoidsteer; - if (simtime < CorrectDelay) - return avoidsteer; + if (simtime < 15.0 && car->_speed_x < 20.0) + return avoidsteer; + if (simtime < CorrectDelay) + return avoidsteer; - float steer = avoidsteer; - //float accel = MIN(0.0f, car->_accel_x); - double speed = 50.0; //MAX(50.0, currentspeed); - double changelimit = MIN(raceline->correctLimit(avoidsteer, racesteer), (((120.0-currentspeed)/6000) * (0.1 + fabs(rldata->mInverse/4)))) * SmoothSteer; + float steer = avoidsteer; + //float accel = MIN(0.0f, car->_accel_x); + double speed = 50.0; //MAX(50.0, currentspeed); + double changelimit = MIN(raceline->correctLimit(avoidsteer, racesteer), (((120.0-currentspeed)/6000) * (0.1 + fabs(rldata->mInverse/4)))) * SmoothSteer; if (DebugMsg & debug_steer) fprintf(stderr,"CORRECT: cl=%.3f as=%.3f rs=%.3f NS=%.3f",correctlimit,avoidsteer,racesteer,lastNSasteer); - if (/*mode == mode_correcting &&*/ simtime > 2.0f) - { - // move steering towards racesteer... - if (correctlimit < 900.0) - { - if (steer < racesteer) - { - if (correctlimit >= 0.0) - { - //steer = (float) MIN(racesteer, steer + correctlimit); + if (/*mode == mode_correcting &&*/ simtime > 2.0f) + { + // move steering towards racesteer... + if (correctlimit < 900.0) + { + if (steer < racesteer) + { + if (correctlimit >= 0.0) + { + //steer = (float) MIN(racesteer, steer + correctlimit); if (DebugMsg & debug_steer) fprintf(stderr," RA%.3f",racesteer); - steer = racesteer; - lastNSasteer = rldata->NSsteer; - } - else - { - steer = (float) MIN(racesteer, MAX(steer, racesteer + correctlimit)); - lastNSasteer = (float) MIN(rldata->NSsteer, MAX(lastNSasteer, rldata->NSsteer + correctlimit)); + steer = racesteer; + lastNSasteer = rldata->NSsteer; + } + else + { + steer = (float) MIN(racesteer, MAX(steer, racesteer + correctlimit)); + lastNSasteer = (float) MIN(rldata->NSsteer, MAX(lastNSasteer, rldata->NSsteer + correctlimit)); if (DebugMsg & debug_steer) fprintf(stderr," MA%.3f",steer); - } - } - else - { - if (correctlimit <= 0.0) - { - //steer = (float) MAX(racesteer, steer-correctlimit); - steer = racesteer; - lastNSasteer = rldata->NSsteer; + } + } + else + { + if (correctlimit <= 0.0) + { + //steer = (float) MAX(racesteer, steer-correctlimit); + steer = racesteer; + lastNSasteer = rldata->NSsteer; if (DebugMsg & debug_steer) fprintf(stderr," RB%.3f",racesteer); - } - else - { - steer = (float) MAX(racesteer, MIN(steer, racesteer + correctlimit)); - lastNSasteer = (float) MAX(rldata->NSsteer, MIN(lastNSasteer, rldata->NSsteer + correctlimit)); + } + else + { + steer = (float) MAX(racesteer, MIN(steer, racesteer + correctlimit)); + lastNSasteer = (float) MAX(rldata->NSsteer, MIN(lastNSasteer, rldata->NSsteer + correctlimit)); if (DebugMsg & debug_steer) fprintf(stderr," MB%.3f",steer); - } - } - } - //else - { - speed -= avgaccel_x/10; - speed = MAX(55.0, MIN(150.0, speed + (speed*speed/55))); - double rInverse = rldata->mInverse * (avgaccel_x<0.0 ? 1.0 + fabs(avgaccel_x)/10.0 : 1.0); - double correctspeed = 0.5; - if ((rInverse > 0.0 && racesteer > steer) || (rInverse < 0.0 && racesteer < steer)) - correctspeed += rInverse*110; + } + } + } + //else + { + speed -= avgaccel_x/10; + speed = MAX(55.0, MIN(150.0, speed + (speed*speed/55))); + double rInverse = rldata->mInverse * (avgaccel_x<0.0 ? 1.0 + fabs(avgaccel_x)/10.0 : 1.0); + double correctspeed = 0.5; + if ((rInverse > 0.0 && racesteer > steer) || (rInverse < 0.0 && racesteer < steer)) + correctspeed += rInverse*110; - if (racesteer > steer) - //steer = (float) MIN(racesteer, steer + (((155.0-speed)/10000) * correctspeed)); - steer = (float) MIN(racesteer, steer + changelimit); - else - //steer = (float) MAX(racesteer, steer - (((155.0-speed)/10000) * correctspeed)); - steer = (float) MAX(racesteer, steer - changelimit); - if (fabs(racesteer) < fabs(steer)) - { - if (racesteer > steer) - steer += (fabs(steer) - fabs(racesteer)) / 2; - else - steer -= (fabs(steer) - fabs(racesteer)) / 2; - } + if (racesteer > steer) + //steer = (float) MIN(racesteer, steer + (((155.0-speed)/10000) * correctspeed)); + steer = (float) MIN(racesteer, steer + changelimit); + else + //steer = (float) MAX(racesteer, steer - (((155.0-speed)/10000) * correctspeed)); + steer = (float) MAX(racesteer, steer - changelimit); + if (fabs(racesteer) < fabs(steer)) + { + if (racesteer > steer) + steer += (fabs(steer) - fabs(racesteer)) / 2; + else + steer -= (fabs(steer) - fabs(racesteer)) / 2; + } - if (lastNSksteer > lastNSasteer) - //lastNSasteer = (float) MIN(rldata->NSsteer, lastNSasteer + (((155.0-speed)/10000) * correctspeed)); - lastNSasteer = (float) MIN(rldata->NSsteer, lastNSasteer + changelimit); - else - //lastNSasteer = (float) MAX(rldata->NSsteer, lastNSasteer - (((155.0-speed)/10000) * correctspeed)); - lastNSasteer = (float) MAX(rldata->NSsteer, lastNSasteer - changelimit); + if (lastNSksteer > lastNSasteer) + //lastNSasteer = (float) MIN(rldata->NSsteer, lastNSasteer + (((155.0-speed)/10000) * correctspeed)); + lastNSasteer = (float) MIN(rldata->NSsteer, lastNSasteer + changelimit); + else + //lastNSasteer = (float) MAX(rldata->NSsteer, lastNSasteer - (((155.0-speed)/10000) * correctspeed)); + lastNSasteer = (float) MAX(rldata->NSsteer, lastNSasteer - changelimit); if (DebugMsg & debug_steer) fprintf(stderr," I%.3f",steer); - } - - } + } + + } if (DebugMsg & debug_steer) fprintf(stderr," %.3f NS=%.3f\n",steer,lastNSasteer); - return steer; + return steer; } float Driver::smoothSteering( float steercmd ) { - if (pitoffset != -100.0f) - return steercmd; + if (pitoffset != -100.0f) + return steercmd; #if 1 - // experimental smoothing code, beware!!! - double steer = steercmd; - double stdelta = steer - laststeer;//car->_steerCmd; - double maxSpeed = MAX(200.0, 300.0 - car->_speed_x*2) * (PI/180.0); + // experimental smoothing code, beware!!! + double steer = steercmd; + double stdelta = steer - laststeer;//car->_steerCmd; + double maxSpeed = MAX(200.0, 300.0 - car->_speed_x*2) * (PI/180.0); - //if (mode == mode_normal) - // maxSpeed = 200.0 * (PI / 180.0); + //if (mode == mode_normal) + // maxSpeed = 200.0 * (PI / 180.0); - if ((fabs(stdelta) / deltaTime) > maxSpeed) - steer = SIGN(stdelta) * maxSpeed * deltaTime + laststeer;//car->_steerCmd; + if ((fabs(stdelta) / deltaTime) > maxSpeed) + steer = SIGN(stdelta) * maxSpeed * deltaTime + laststeer;//car->_steerCmd; - steercmd = steer; + steercmd = steer; - // limit amount of steer according to speed & raceline - double a_error_factor = ((rldata->exiting && rldata->outsideline) ? 0.9 : 0.8); - double smangle = angle * (0.5 + fabs(angle*2)); - double angle_error = (smangle - rldata->rlangle/2) * a_error_factor; - double lstlimit = MAX(40.0, 80.0 - car->_speed_x) * 0.004 - MIN(0.0, MAX(-0.5, angle_error)); - double rstlimit = -(MAX(40.0, 80.0 - car->_speed_x) * 0.004 + MAX(0.0, MIN(0.5, angle_error))); - double strate = 61.0 + lastaccel*10; + // limit amount of steer according to speed & raceline + double a_error_factor = ((rldata->exiting && rldata->outsideline) ? 0.9 : 0.8); + double smangle = angle * (0.5 + fabs(angle*2)); + double angle_error = (smangle - rldata->rlangle/2) * a_error_factor; + double lstlimit = MAX(40.0, 80.0 - car->_speed_x) * 0.004 - MIN(0.0, MAX(-0.5, angle_error)); + double rstlimit = -(MAX(40.0, 80.0 - car->_speed_x) * 0.004 + MAX(0.0, MIN(0.5, angle_error))); + double strate = 61.0 + lastaccel*10; - if (rldata->rInverse*strate > lstlimit) - lstlimit = rldata->rInverse*strate; - if (rldata->rInverse*strate < rstlimit) - rstlimit = rldata->rInverse*strate; - steercmd = MAX(rstlimit, MIN(lstlimit, steercmd)); + if (rldata->rInverse*strate > lstlimit) + lstlimit = rldata->rInverse*strate; + if (rldata->rInverse*strate < rstlimit) + rstlimit = rldata->rInverse*strate; + steercmd = MAX(rstlimit, MIN(lstlimit, steercmd)); #endif - return steercmd; + return steercmd; #if 0 - // try to limit sudden changes in steering to avoid loss of control through oversteer. - double lftspeedfactor = ((((60.0 - (MAX(40.0, MIN(70.0, currentspeed + MAX(0.0, car->_accel_x*5))) - 25)) / 300) * 2.5) / 0.585) * SmoothSteer; - double rgtspeedfactor = lftspeedfactor; + // try to limit sudden changes in steering to avoid loss of control through oversteer. + double lftspeedfactor = ((((60.0 - (MAX(40.0, MIN(70.0, currentspeed + MAX(0.0, car->_accel_x*5))) - 25)) / 300) * 2.5) / 0.585) * SmoothSteer; + double rgtspeedfactor = lftspeedfactor; - if (fabs(steercmd) < fabs(laststeer) && fabs(steercmd) <= fabs(laststeer - steercmd)) - { - lftspeedfactor *= 2; - rgtspeedfactor *= 2; - } + if (fabs(steercmd) < fabs(laststeer) && fabs(steercmd) <= fabs(laststeer - steercmd)) + { + lftspeedfactor *= 2; + rgtspeedfactor *= 2; + } - lftspeedfactor -= MIN(0.0f, car->_yaw_rate/10); - rgtspeedfactor += MAX(0.0f, car->_yaw_rate/10); + lftspeedfactor -= MIN(0.0f, car->_yaw_rate/10); + rgtspeedfactor += MAX(0.0f, car->_yaw_rate/10); - steercmd = (float) MAX(laststeer - rgtspeedfactor, MIN(laststeer + lftspeedfactor, steercmd)); - return steercmd; + steercmd = (float) MAX(laststeer - rgtspeedfactor, MIN(laststeer + lftspeedfactor, steercmd)); + return steercmd; #endif } // Compute the clutch value. float Driver::getClutch() { - if (1 || car->_gearCmd > 1) - { - float maxtime = MAX(0.06f, 0.32f - ((float) car->_gearCmd / 65.0f)); - if (car->_gear != car->_gearCmd && car->_gearCmd < MaxGear) - clutchtime = maxtime; - if (clutchtime > 0.0f) - clutchtime -= (float) (RCM_MAX_DT_ROBOTS * (0.02f + ((float) car->_gearCmd / 8.0f))); - return 2.0f * clutchtime; - } else { - float drpm = car->_enginerpm - car->_enginerpmRedLine/2.0f; - float ctlimit = 0.9f; - if (car->_gearCmd > 1) - ctlimit -= 0.15f + (float) car->_gearCmd/13.0f; - clutchtime = MIN(ctlimit, clutchtime); - if (car->_gear != car->_gearCmd) - clutchtime = 0.0f; - float clutcht = (ctlimit - clutchtime) / ctlimit; - if (car->_gear == 1 && car->_accelCmd > 0.0f) { - clutchtime += (float) RCM_MAX_DT_ROBOTS; - } + if (1 || car->_gearCmd > 1) + { + float maxtime = MAX(0.06f, 0.32f - ((float) car->_gearCmd / 65.0f)); + if (car->_gear != car->_gearCmd && car->_gearCmd < MaxGear) + clutchtime = maxtime; + if (clutchtime > 0.0f) + clutchtime -= (float) (RCM_MAX_DT_ROBOTS * (0.02f + ((float) car->_gearCmd / 8.0f))); + return 2.0f * clutchtime; + } else { + float drpm = car->_enginerpm - car->_enginerpmRedLine/2.0f; + float ctlimit = 0.9f; + if (car->_gearCmd > 1) + ctlimit -= 0.15f + (float) car->_gearCmd/13.0f; + clutchtime = MIN(ctlimit, clutchtime); + if (car->_gear != car->_gearCmd) + clutchtime = 0.0f; + float clutcht = (ctlimit - clutchtime) / ctlimit; + if (car->_gear == 1 && car->_accelCmd > 0.0f) { + clutchtime += (float) RCM_MAX_DT_ROBOTS; + } - if (car->_gearCmd == 1 || drpm > 0) { - float speedr; - if (car->_gearCmd == 1) { - // Compute corresponding speed to engine rpm. - float omega = car->_enginerpmRedLine/car->_gearRatio[car->_gear + car->_gearOffset]; - float wr = car->_wheelRadius(2); - speedr = (CLUTCH_SPEED + MAX(0.0f, car->_speed_x))/fabs(wr*omega); - float clutchr = MAX(0.0f, (1.0f - speedr*2.0f*drpm/car->_enginerpmRedLine)) * (car->_gearCmd == 1 ? 0.95f : (0.7f - (float)(car->_gearCmd)/30.0f)); - return MIN(clutcht, clutchr); - } else { - // For the reverse gear. - clutchtime = 0.0f; - return 0.0f; - } - } else { - return clutcht; - } - } + if (car->_gearCmd == 1 || drpm > 0) { + float speedr; + if (car->_gearCmd == 1) { + // Compute corresponding speed to engine rpm. + float omega = car->_enginerpmRedLine/car->_gearRatio[car->_gear + car->_gearOffset]; + float wr = car->_wheelRadius(2); + speedr = (CLUTCH_SPEED + MAX(0.0f, car->_speed_x))/fabs(wr*omega); + float clutchr = MAX(0.0f, (1.0f - speedr*2.0f*drpm/car->_enginerpmRedLine)) * (car->_gearCmd == 1 ? 0.95f : (0.7f - (float)(car->_gearCmd)/30.0f)); + return MIN(clutcht, clutchr); + } else { + // For the reverse gear. + clutchtime = 0.0f; + return 0.0f; + } + } else { + return clutcht; + } + } } // move offset to allow for bends (if any) float Driver::adjustOffset(float offset) { return offset; - float adjustment = (float) (rldata->rInverse * 10); - float width = (float) (car->_trkPos.seg->width * 0.75); + float adjustment = (float) (rldata->rInverse * 10); + float width = (float) (car->_trkPos.seg->width * 0.75); #if 0 #endif - //if (mode==mode_avoiding) - { - // we want to adjust outwards a bit if in close to the corner (more if avoiding - // a car on the inside, way less otherwise). If the car is on the outside third - // of the track we don't want to adjust at all. Inbetween the inside third and - // the outside third we want a gradual decline in the adjust amount... - if (adjustment < 0.0) - { - if (car->_trkPos.toRight > width*0.7) - adjustment = 0.0; - else if (car->_trkPos.toRight > width*0.3) - adjustment *= MAX(0.0, 1.0 - ((car->_trkPos.toRight-width*0.3)/width*0.4)); - } - else if (adjustment > 0.0) - { - if (car->_trkPos.toLeft > width*0.7) - adjustment = 0.0; - else if (car->_trkPos.toLeft > width*0.3) - adjustment *= MAX(0.0, 1.0 - ((car->_trkPos.toLeft-width*0.3)/width*0.4)); - } + //if (mode==mode_avoiding) + { + // we want to adjust outwards a bit if in close to the corner (more if avoiding + // a car on the inside, way less otherwise). If the car is on the outside third + // of the track we don't want to adjust at all. Inbetween the inside third and + // the outside third we want a gradual decline in the adjust amount... + if (adjustment < 0.0) + { + if (car->_trkPos.toRight > width*0.7) + adjustment = 0.0; + else if (car->_trkPos.toRight > width*0.3) + adjustment *= MAX(0.0, 1.0 - ((car->_trkPos.toRight-width*0.3)/width*0.4)); + } + else if (adjustment > 0.0) + { + if (car->_trkPos.toLeft > width*0.7) + adjustment = 0.0; + else if (car->_trkPos.toLeft > width*0.3) + adjustment *= MAX(0.0, 1.0 - ((car->_trkPos.toLeft-width*0.3)/width*0.4)); + } #if 0 - if (adjustment < 0.0 && car->_trkPos.toLeft < width) - adjustment *= MAX(0.1, MIN(1.0, car->_trkPos.toLeft*1.6 / width)); - else if (adjustment > 0.0 && car->_trkPos.toRight < width) - adjustment *= MAX(0.1, MIN(1.0, car->_trkPos.toRight*1.6 / width)); + if (adjustment < 0.0 && car->_trkPos.toLeft < width) + adjustment *= MAX(0.1, MIN(1.0, car->_trkPos.toLeft*1.6 / width)); + else if (adjustment > 0.0 && car->_trkPos.toRight < width) + adjustment *= MAX(0.1, MIN(1.0, car->_trkPos.toRight*1.6 / width)); #endif - //adjustment *= 1.0 + MAX(0.0, currentspeed / rldata->avspeed)*2; - if ((avoidmode == avoidright && adjustment < 0.0) || - (avoidmode == avoidleft && adjustment > 0.0)) - adjustment *= 1; - else - adjustment /= 2; - } + //adjustment *= 1.0 + MAX(0.0, currentspeed / rldata->avspeed)*2; + if ((avoidmode == avoidright && adjustment < 0.0) || + (avoidmode == avoidleft && adjustment > 0.0)) + adjustment *= 1; + else + adjustment /= 2; + } - double speed = currentspeed; - double xspeed = MIN(rldata->speed, rldata->avspeed); - if (speed < xspeed) - adjustment *= MIN(2.0, xspeed / speed); + double speed = currentspeed; + double xspeed = MIN(rldata->speed, rldata->avspeed); + if (speed < xspeed) + adjustment *= MIN(2.0, xspeed / speed); - offset -= adjustment; + offset -= adjustment; - return offset; + return offset; } // Compute target point for steering. vec2f Driver::getTargetPoint(bool use_lookahead, double targetoffset) { - tTrackSeg *seg = car->_trkPos.seg; - float length = getDistToSegEnd(); - float offset = (targetoffset > -99 ? targetoffset - : (skipcount < 2 ? getOffset() : myoffset)); - double time_mod = 1.0; - pitoffset = -100.0f; + tTrackSeg *seg = car->_trkPos.seg; + float length = getDistToSegEnd(); + float offset = (targetoffset > -99 ? targetoffset + : (skipcount < 2 ? getOffset() : myoffset)); + double time_mod = 1.0; + pitoffset = -100.0f; - if (pit->getInPit()) { - // To stop in the pit we need special lookahead values. - if (currentspeedsqr > pit->getSpeedlimitSqr()) { - lookahead = PIT_LOOKAHEAD + car->_speed_x*LOOKAHEAD_FACTOR; - } else { - lookahead = PIT_LOOKAHEAD; - } - } else { - // Usual lookahead. - lookahead = (float) rldata->lookahead; + if (pit->getInPit()) { + // To stop in the pit we need special lookahead values. + if (currentspeedsqr > pit->getSpeedlimitSqr()) { + lookahead = PIT_LOOKAHEAD + car->_speed_x*LOOKAHEAD_FACTOR; + } else { + lookahead = PIT_LOOKAHEAD; + } + } else { + // Usual lookahead. + lookahead = (float) rldata->lookahead; - double speed = MAX(20.0, currentspeed);// + MAX(0.0, car->_accel_x)); - lookahead = (float) (LOOKAHEAD_CONST * 1.2 + speed * 0.75); - lookahead = MIN(lookahead, (float) (LOOKAHEAD_CONST + ((speed*(speed/7)) * 0.15))); - lookahead *= SteerLookahead; - double ri = (fabs(rldata->mInverse) < fabs(rldata->rInverse) ? rldata->mInverse : rldata->rInverse); - //double amI = MIN(0.05, MAX(-0.05, (rldata->amInverse))); - double amI = MIN(0.05, MAX(-0.05, (ri))); - double famI = fabs(amI); + double speed = MAX(20.0, currentspeed);// + MAX(0.0, car->_accel_x)); + lookahead = (float) (LOOKAHEAD_CONST * 1.2 + speed * 0.75); + lookahead = MIN(lookahead, (float) (LOOKAHEAD_CONST + ((speed*(speed/7)) * 0.15))); + lookahead *= SteerLookahead; + double ri = (fabs(rldata->mInverse) < fabs(rldata->rInverse) ? rldata->mInverse : rldata->rInverse); + //double amI = MIN(0.05, MAX(-0.05, (rldata->amInverse))); + double amI = MIN(0.05, MAX(-0.05, (ri))); + double famI = fabs(amI); - if (famI > 0.0) - { - double cornerfx = 1.0; - double toMid = car->_trkPos.toMiddle + speedangle * 20; - double modfactor = (currentspeed / rldata->avspeed); - modfactor *= modfactor; - if (amI > 0.0) - { - if (toMid < 0.0) - { - cornerfx += famI * (MIN(track->width/2, fabs(toMid)) / track->width) * 50; - time_mod += famI * (MIN(track->width/2, fabs(toMid)) / track->width) * 50; - } - else - { - cornerfx -= MIN(0.7, famI * (MIN(track->width/2, fabs(toMid)) / track->width) * 30); - time_mod -= MIN(0.7, famI * (MIN(track->width/2, fabs(toMid)) / track->width) * 30 * modfactor); - } - } - else - { - if (toMid > 0.0) - { - cornerfx += famI * (MIN(track->width/2, fabs(toMid)) / track->width) * 50; - time_mod += famI * (MIN(track->width/2, fabs(toMid)) / track->width) * 50; - } - else - { - cornerfx -= MIN(0.7, famI * (MIN(track->width/2, fabs(toMid)) / track->width) * 30); - time_mod -= MIN(0.7, famI * (MIN(track->width/2, fabs(toMid)) / track->width) * 30 * modfactor); - } - } - lookahead *= cornerfx; - } + if (famI > 0.0) + { + double cornerfx = 1.0; + double toMid = car->_trkPos.toMiddle + speedangle * 20; + double modfactor = (currentspeed / rldata->avspeed); + modfactor *= modfactor; + if (amI > 0.0) + { + if (toMid < 0.0) + { + cornerfx += famI * (MIN(track->width/2, fabs(toMid)) / track->width) * 50; + time_mod += famI * (MIN(track->width/2, fabs(toMid)) / track->width) * 50; + } + else + { + cornerfx -= MIN(0.7, famI * (MIN(track->width/2, fabs(toMid)) / track->width) * 30); + time_mod -= MIN(0.7, famI * (MIN(track->width/2, fabs(toMid)) / track->width) * 30 * modfactor); + } + } + else + { + if (toMid > 0.0) + { + cornerfx += famI * (MIN(track->width/2, fabs(toMid)) / track->width) * 50; + time_mod += famI * (MIN(track->width/2, fabs(toMid)) / track->width) * 50; + } + else + { + cornerfx -= MIN(0.7, famI * (MIN(track->width/2, fabs(toMid)) / track->width) * 30); + time_mod -= MIN(0.7, famI * (MIN(track->width/2, fabs(toMid)) / track->width) * 30 * modfactor); + } + } + lookahead *= cornerfx; + } - if (time_mod < oldtime_mod) - time_mod = MAX(time_mod, oldtime_mod - deltaTime*2); - oldtime_mod = time_mod; + if (time_mod < oldtime_mod) + time_mod = MAX(time_mod, oldtime_mod - deltaTime*2); + oldtime_mod = time_mod; #if 0 - if (fabs(rldata->rInverse) > 0.001) - { - // increase lookahead if on the outside of a corner - double cornerfx = 1.0; - double cornerlmt = MIN(track->width/2, 1.0 + fabs(rldata->rInverse)*500); - if (rldata->rInverse > 0.0 && car->_trkPos.toRight < cornerlmt) - cornerfx = 1.0 + MAX(0.0, (cornerlmt-car->_trkPos.toRight)/cornerlmt)*1.5; - else if (rldata->rInverse < 0.0 && car->_trkPos.toLeft < cornerlmt) - cornerfx = (1.0 - MAX(0.0, (cornerlmt-car->_trkPos.toLeft)/cornerlmt))*1.5; - lookahead *= cornerfx; - } + if (fabs(rldata->rInverse) > 0.001) + { + // increase lookahead if on the outside of a corner + double cornerfx = 1.0; + double cornerlmt = MIN(track->width/2, 1.0 + fabs(rldata->rInverse)*500); + if (rldata->rInverse > 0.0 && car->_trkPos.toRight < cornerlmt) + cornerfx = 1.0 + MAX(0.0, (cornerlmt-car->_trkPos.toRight)/cornerlmt)*1.5; + else if (rldata->rInverse < 0.0 && car->_trkPos.toLeft < cornerlmt) + cornerfx = (1.0 - MAX(0.0, (cornerlmt-car->_trkPos.toLeft)/cornerlmt))*1.5; + lookahead *= cornerfx; + } #endif #if 0 - lookahead = LOOKAHEAD_CONST + car->_speed_x*LOOKAHEAD_FACTOR; - lookahead = MAX(lookahead, LOOKAHEAD_CONST + ((car->_speed_x*(car->_speed_x/2)) / 60.0)); + lookahead = LOOKAHEAD_CONST + car->_speed_x*LOOKAHEAD_FACTOR; + lookahead = MAX(lookahead, LOOKAHEAD_CONST + ((car->_speed_x*(car->_speed_x/2)) / 60.0)); #endif #if 1 - lookahead *= LookAhead; + lookahead *= LookAhead; - // Prevent "snap back" of lookahead on harsh braking. - float cmplookahead = oldlookahead - (car->_speed_x*RCM_MAX_DT_ROBOTS)*0.65f;//0.55f; - if (lookahead < cmplookahead) { - lookahead = cmplookahead; - } + // Prevent "snap back" of lookahead on harsh braking. + float cmplookahead = oldlookahead - (car->_speed_x*RCM_MAX_DT_ROBOTS)*0.65f;//0.55f; + if (lookahead < cmplookahead) { + lookahead = cmplookahead; + } #endif - } + } - oldlookahead = lookahead; + oldlookahead = lookahead; - // Search for the segment containing the target point. - while (length < lookahead) { - seg = seg->next; - length += seg->length; - } + // Search for the segment containing the target point. + while (length < lookahead) { + seg = seg->next; + length += seg->length; + } - length = lookahead - length + seg->length; - float fromstart = seg->lgfromstart; - fromstart += length; + length = lookahead - length + seg->length; + float fromstart = seg->lgfromstart; + fromstart += length; - // Compute the target point. - pitoffset = pit->getPitOffset(pitoffset, fromstart, pitpos); - if ((pit->getPitstop() || pit->getInPit()) && pitoffset != -100.0f) - { - setMode(mode_pitting); - offset = myoffset = pitoffset; - } - else if (mode == mode_pitting) - { - setMode(mode_correcting); - } + // Compute the target point. + pitoffset = pit->getPitOffset(pitoffset, fromstart, pitpos); + if ((pit->getPitstop() || pit->getInPit()) && pitoffset != -100.0f) + { + setMode(mode_pitting); + offset = myoffset = pitoffset; + } + else if (mode == mode_pitting) + { + setMode(mode_correcting); + } - //if (mode == mode_correcting || mode == mode_avoiding) - // offset = adjustOffset( offset ); + //if (mode == mode_correcting || mode == mode_avoiding) + // offset = adjustOffset( offset ); - vec2f s; - //if (mode != mode_pitting) - { - //double steertime = SteerTime * time_mod * MAX(1.0, (1.0 - (car->_accel_x/70 * MAX(0.1, MIN(1.0, collision))))); - double steertime = MIN(MaxSteerTime, MinSteerTime + MAX(0.0, currentspeed-20.0)/30.0); - if (car->_speed_x > SteerCutoff) - time_mod *= SteerCutoff / currentspeed; - raceline->GetSteerPoint( lookahead, &s, offset, (use_lookahead ? -100.0 : steertime * time_mod) ); - return s; - } + vec2f s; + //if (mode != mode_pitting) + { + //double steertime = SteerTime * time_mod * MAX(1.0, (1.0 - (car->_accel_x/70 * MAX(0.1, MIN(1.0, collision))))); + double steertime = MIN(MaxSteerTime, MinSteerTime + MAX(0.0, currentspeed-20.0)/30.0); + if (car->_speed_x > SteerCutoff) + time_mod *= SteerCutoff / currentspeed; + raceline->GetSteerPoint( lookahead, &s, offset, (use_lookahead ? -100.0 : steertime * time_mod) ); + return s; + } - // all the BT code below is for steering into pits only. - s.x = (seg->vertex[TR_SL].x + seg->vertex[TR_SR].x)/2; - s.y = (seg->vertex[TR_SL].y + seg->vertex[TR_SR].y)/2; - //double dx, dy; - vec2f t, rt; + // all the BT code below is for steering into pits only. + s.x = (seg->vertex[TR_SL].x + seg->vertex[TR_SR].x)/2; + s.y = (seg->vertex[TR_SL].y + seg->vertex[TR_SR].y)/2; + //double dx, dy; + vec2f t, rt; - if ( seg->type == TR_STR) { - vec2f d, n; - n.x = (seg->vertex[TR_EL].x - seg->vertex[TR_ER].x)/seg->length; - n.y = (seg->vertex[TR_EL].y - seg->vertex[TR_ER].y)/seg->length; - n.normalize(); - d.x = (seg->vertex[TR_EL].x - seg->vertex[TR_SL].x)/seg->length; - d.y = (seg->vertex[TR_EL].y - seg->vertex[TR_SL].y)/seg->length; - t = s + d*length + offset*n; + if ( seg->type == TR_STR) { + vec2f d, n; + n.x = (seg->vertex[TR_EL].x - seg->vertex[TR_ER].x)/seg->length; + n.y = (seg->vertex[TR_EL].y - seg->vertex[TR_ER].y)/seg->length; + n.normalize(); + d.x = (seg->vertex[TR_EL].x - seg->vertex[TR_SL].x)/seg->length; + d.y = (seg->vertex[TR_EL].y - seg->vertex[TR_SL].y)/seg->length; + t = s + d*length + offset*n; - return t; - } else { - vec2f c, n; - c.x = seg->center.x; - c.y = seg->center.y; - float arc = length/seg->radius; - float arcsign = (seg->type == TR_RGT) ? -1.0f : 1.0f; - arc = arc*arcsign; - s = s.rotate(c, arc); - - n = c - s; - n.normalize(); - t = s + arcsign*offset*n; + return t; + } else { + vec2f c, n; + c.x = seg->center.x; + c.y = seg->center.y; + float arc = length/seg->radius; + float arcsign = (seg->type == TR_RGT) ? -1.0f : 1.0f; + arc = arc*arcsign; + s = s.rotate(c, arc); + + n = c - s; + n.normalize(); + t = s + arcsign*offset*n; - return t; - } + return t; + } } bool Driver::canOvertake( Opponent *o, double *mincatchdist, bool outside, bool lenient ) { - if (!o) return false; + if (!o) return false; #if 1 - //int segid = car->_trkPos.seg->id; - tCarElt *ocar = o->getCarPtr(); - //int osegid = ocar->_trkPos.seg->id; - double otry_factor = (lenient ? (0.2 + MAX(0.0, 1.0 - ((simtime-frontavoidtime)/7.0)) * 0.8) : 1.0); - double overtakecaution = MAX(0.0, rldata->overtakecaution + (outside ? MIN(0.0, car->_accel_x/8) : 0.0)) - driver_aggression/2; - double orInv=0.0, oAspeed=0.0; - raceline->getOpponentInfo(o->getDistance(), &oAspeed, &orInv); - double rInv = MAX(fabs(rldata->rInverse), fabs(orInv)); - double distance = o->getDistance() * otry_factor * MAX(0.5, 1.0 - (ocar->_pos > car->_pos ? MIN(o->getDistance()/2, 3.0) : 0.0)); - //double speed = MIN(rldata->avspeed, MIN(oAspeed, currentspeed + MAX(0.0, (30.0 - distance) * MAX(0.1, 1.0 - MAX(0.0, rInv-0.001)*80)))); - double speed = currentspeed; - double avspeed = MIN(rldata->avspeed, speed + 2.0); - speed = MIN(avspeed, (speed + MAX(0.0, (30.0 - distance) * MAX(0.1, 1.0 - MAX(0.0, rInv-0.001)*80)))); - double ospeed = o->getSpeed(); - double timeLimit = 3.0 - MIN(2.4, rInv * 1000); + //int segid = car->_trkPos.seg->id; + tCarElt *ocar = o->getCarPtr(); + //int osegid = ocar->_trkPos.seg->id; + double otry_factor = (lenient ? (0.2 + MAX(0.0, 1.0 - ((simtime-frontavoidtime)/7.0)) * 0.8) : 1.0); + double overtakecaution = MAX(0.0, rldata->overtakecaution + (outside ? MIN(0.0, car->_accel_x/8) : 0.0)) - driver_aggression/2; + double orInv=0.0, oAspeed=0.0; + raceline->getOpponentInfo(o->getDistance(), &oAspeed, &orInv); + double rInv = MAX(fabs(rldata->rInverse), fabs(orInv)); + double distance = o->getDistance() * otry_factor * MAX(0.5, 1.0 - (ocar->_pos > car->_pos ? MIN(o->getDistance()/2, 3.0) : 0.0)); + //double speed = MIN(rldata->avspeed, MIN(oAspeed, currentspeed + MAX(0.0, (30.0 - distance) * MAX(0.1, 1.0 - MAX(0.0, rInv-0.001)*80)))); + double speed = currentspeed; + double avspeed = MIN(rldata->avspeed, speed + 2.0); + speed = MIN(avspeed, (speed + MAX(0.0, (30.0 - distance) * MAX(0.1, 1.0 - MAX(0.0, rInv-0.001)*80)))); + double ospeed = o->getSpeed(); + double timeLimit = 3.0 - MIN(2.4, rInv * 1000); - //double speeddiff = MAX((15.0-(rInv*1000*1.0+overtakecaution/2)) - distance, fabs(speed - ospeed) * (8 - MIN(5.5, rInv*300))); - double speeddiff = (MIN(speed, avspeed) - ospeed) * 2; - if (outside) - ospeed *= 1.0 + rInv*3; - //double catchdist = (double) MIN((speed*distance)/(speed-ospeed), distance*CATCH_FACTOR) * otry_factor; - double catchdist = (double) ((speed*distance)/(speed-ospeed)) * otry_factor * 0.8 + distance/10; - double mcd = car->_speed_x * (2.0 - MIN(1.5, rInv * 500)); + //double speeddiff = MAX((15.0-(rInv*1000*1.0+overtakecaution/2)) - distance, fabs(speed - ospeed) * (8 - MIN(5.5, rInv*300))); + double speeddiff = (MIN(speed, avspeed) - ospeed) * 2; + if (outside) + ospeed *= 1.0 + rInv*3; + //double catchdist = (double) MIN((speed*distance)/(speed-ospeed), distance*CATCH_FACTOR) * otry_factor; + double catchdist = (double) ((speed*distance)/(speed-ospeed)) * otry_factor * 0.8 + distance/10; + double mcd = car->_speed_x * (2.0 - MIN(1.5, rInv * 500)); #if 0 - // TRB ENDURANCE RACES ONLY!!! - if (car->race.laps < 2 && - ocar->_pos < car->_pos && - fabs(o->getAngle()) < 0.6 && - ocar->_speed_x > MAX(10.0, car->_speed_x/2)) - { - overtakecaution += (2 - car->race.laps) * 4; - } + // TRB ENDURANCE RACES ONLY!!! + if (car->race.laps < 2 && + ocar->_pos < car->_pos && + fabs(o->getAngle()) < 0.6 && + ocar->_speed_x > MAX(10.0, car->_speed_x/2)) + { + overtakecaution += (2 - car->race.laps) * 4; + } #endif - if (catchdist < mcd && MIN(speed, avspeed) > ospeed && //catchdist < *mincatchdist+0.1 && - (distance * (1.0+overtakecaution) < MIN(speeddiff, catchdist/4 + 2.0) * (1.0-rInv*30) || - o->getTimeImpact() * (1.0+overtakecaution) < timeLimit)) - { - if (DebugMsg & debug_overtake) - fprintf(stderr,"%.1f %s: OVERTAKE! (cd %.1f<%.1f) (dist %.1f (%.1f) < (%.1f-%.1f)*X = %.1f TI %.3f < tl %.3f || caut=%.1f avspd=%.1f oAspd=%.1f\n",otry_factor,ocar->_name,catchdist,mcd,distance,o->getDistance(),speed,ospeed,speeddiff,o->getTimeImpact(),timeLimit,overtakecaution,avspeed,oAspeed); - *mincatchdist = catchdist + 0.1; - return true; - } - else if (DebugMsg & debug_overtake) - fprintf(stderr,"%.1f %s: FAIL!!!!! (cd %.1f<%.1f) (dist %.1f (%.1f) < (%.1f-%.1f)*X = %.1f TI %.3f < tl %.3f || caut=%.1f avspd=%.1f oAspd=%.1f\n",otry_factor,ocar->_name,catchdist,mcd,distance,o->getDistance(),speed,ospeed,speeddiff,o->getTimeImpact(),timeLimit,overtakecaution,avspeed,oAspeed); + if (catchdist < mcd && MIN(speed, avspeed) > ospeed && //catchdist < *mincatchdist+0.1 && + (distance * (1.0+overtakecaution) < MIN(speeddiff, catchdist/4 + 2.0) * (1.0-rInv*30) || + o->getTimeImpact() * (1.0+overtakecaution) < timeLimit)) + { + if (DebugMsg & debug_overtake) + fprintf(stderr,"%.1f %s: OVERTAKE! (cd %.1f<%.1f) (dist %.1f (%.1f) < (%.1f-%.1f)*X = %.1f TI %.3f < tl %.3f || caut=%.1f avspd=%.1f oAspd=%.1f\n",otry_factor,ocar->_name,catchdist,mcd,distance,o->getDistance(),speed,ospeed,speeddiff,o->getTimeImpact(),timeLimit,overtakecaution,avspeed,oAspeed); + *mincatchdist = catchdist + 0.1; + return true; + } + else if (DebugMsg & debug_overtake) + fprintf(stderr,"%.1f %s: FAIL!!!!! (cd %.1f<%.1f) (dist %.1f (%.1f) < (%.1f-%.1f)*X = %.1f TI %.3f < tl %.3f || caut=%.1f avspd=%.1f oAspd=%.1f\n",otry_factor,ocar->_name,catchdist,mcd,distance,o->getDistance(),speed,ospeed,speeddiff,o->getTimeImpact(),timeLimit,overtakecaution,avspeed,oAspeed); #else - double distance = o->getDistance(); - double speed = MIN(rldata->avspeed, currentspeed + MAX(0.0, (currentspeed/3 - distance)/2)); - double ospeed = o->getSpeed(); - double caution = overtakecaution + (outside == true ? 0.5 : 0.0); - //double rInverse = (fabs(nextCRinverse)>fabs(rldata->rInverse) ? nextCRinverse : rldata->rInverse); - double rInverse = rldata->aInverse; //rldata->rInverse; + double distance = o->getDistance(); + double speed = MIN(rldata->avspeed, currentspeed + MAX(0.0, (currentspeed/3 - distance)/2)); + double ospeed = o->getSpeed(); + double caution = overtakecaution + (outside == true ? 0.5 : 0.0); + //double rInverse = (fabs(nextCRinverse)>fabs(rldata->rInverse) ? nextCRinverse : rldata->rInverse); + double rInverse = rldata->aInverse; //rldata->rInverse; - { - tTrackSeg *wseg = (rInverse > 0.0 ? car->_wheelSeg(FRNT_LFT) : car->_wheelSeg(FRNT_RGT)); - if (wseg->surface->kFriction > car->_trkPos.seg->surface->kFriction) - caution += (wseg->surface->kFriction - car->_trkPos.seg->surface->kFriction) * 4; - } + { + tTrackSeg *wseg = (rInverse > 0.0 ? car->_wheelSeg(FRNT_LFT) : car->_wheelSeg(FRNT_RGT)); + if (wseg->surface->kFriction > car->_trkPos.seg->surface->kFriction) + caution += (wseg->surface->kFriction - car->_trkPos.seg->surface->kFriction) * 4; + } - distance += fabs(rInverse) * 200; - if (outside) - { - distance += fabs(rInverse) * 800; - if ((rInverse > 0.0 && angle > 0.0) || (rInverse < 0.0 && angle < 0.0)) - caution += fabs(speedangle-angle) * 20; - } + distance += fabs(rInverse) * 200; + if (outside) + { + distance += fabs(rInverse) * 800; + if ((rInverse > 0.0 && angle > 0.0) || (rInverse < 0.0 && angle < 0.0)) + caution += fabs(speedangle-angle) * 20; + } - double catchdist = MIN(speed*distance/(speed-ospeed), distance*CATCH_FACTOR) * (lenient ? (0.7 + MIN(0.3, (simtime-frontavoidtime)/10.0)) : 1.0) * (1.0 + caution/2); - - if (catchdist > *mincatchdist && - *mincatchdist >= MAX(100.0, car->_speed_x*5) && - rldata->avspeed > 1000.0 && currentspeed > ospeed - (lenient ? 3.0 : 1.5)) - { - // on a fast section - don't let catchdist be a barrier to overtaking - catchdist = *mincatchdist * 0.9; - } + double catchdist = MIN(speed*distance/(speed-ospeed), distance*CATCH_FACTOR) * (lenient ? (0.7 + MIN(0.3, (simtime-frontavoidtime)/10.0)) : 1.0) * (1.0 + caution/2); + + if (catchdist > *mincatchdist && + *mincatchdist >= MAX(100.0, car->_speed_x*5) && + rldata->avspeed > 1000.0 && currentspeed > ospeed - (lenient ? 3.0 : 1.5)) + { + // on a fast section - don't let catchdist be a barrier to overtaking + catchdist = *mincatchdist * 0.9; + } - if ((catchdist <= *mincatchdist) && distance < (speed-ospeed)*2) - { - double mradius = MAX(0.0, MIN(1.0, fabs(rInverse) * 70)); - double oradius = MAX(0.0, MIN(1.0, fabs(raceline->getRInverse(distance)) * 80)); - double radius = MAX(1.0, MIN(10.0, MAX(1.0 / mradius, 1.0 / oradius))); - catchdist *= radius; - double distance2 = distance * radius; - - if (catchdist <= *mincatchdist && distance < fabs(speed-ospeed)*2) - { - if (DebugMsg & debug_overtake) - fprintf(stderr,"%s - %s OVERTAKE: cd=%.1f > %.1f, dist=%.1f > (%.1f-%.1f)*2=%.1f\n",car->_name,o->getCarPtr()->_name,catchdist,*mincatchdist,distance,speed,ospeed,(speed-ospeed)*2); - *mincatchdist = catchdist+0.1; - return true; - } - else if (DebugMsg & debug_overtake) - fprintf(stderr,"%s - %s FAIL 2: cd=%.1f > %.1f, dist=%.1f (%.1f/%.1f) > (%.1f-%.1f)*2=%.1f\n",car->_name,o->getCarPtr()->_name,catchdist,*mincatchdist,distance2,distance,o->getDistance(),speed,ospeed,(speed-ospeed)*2); - } - else if (DebugMsg & debug_overtake) - fprintf(stderr,"%s - %s FAIL 1: cd=%.1f > %.1f, dist=%.1f (%.1f) > (%.1f-%.1f)*2=%.1f\n",car->_name,o->getCarPtr()->_name,catchdist,*mincatchdist,distance,o->getDistance(),speed,ospeed,(speed-ospeed)*2); + if ((catchdist <= *mincatchdist) && distance < (speed-ospeed)*2) + { + double mradius = MAX(0.0, MIN(1.0, fabs(rInverse) * 70)); + double oradius = MAX(0.0, MIN(1.0, fabs(raceline->getRInverse(distance)) * 80)); + double radius = MAX(1.0, MIN(10.0, MAX(1.0 / mradius, 1.0 / oradius))); + catchdist *= radius; + double distance2 = distance * radius; + + if (catchdist <= *mincatchdist && distance < fabs(speed-ospeed)*2) + { + if (DebugMsg & debug_overtake) + fprintf(stderr,"%s - %s OVERTAKE: cd=%.1f > %.1f, dist=%.1f > (%.1f-%.1f)*2=%.1f\n",car->_name,o->getCarPtr()->_name,catchdist,*mincatchdist,distance,speed,ospeed,(speed-ospeed)*2); + *mincatchdist = catchdist+0.1; + return true; + } + else if (DebugMsg & debug_overtake) + fprintf(stderr,"%s - %s FAIL 2: cd=%.1f > %.1f, dist=%.1f (%.1f/%.1f) > (%.1f-%.1f)*2=%.1f\n",car->_name,o->getCarPtr()->_name,catchdist,*mincatchdist,distance2,distance,o->getDistance(),speed,ospeed,(speed-ospeed)*2); + } + else if (DebugMsg & debug_overtake) + fprintf(stderr,"%s - %s FAIL 1: cd=%.1f > %.1f, dist=%.1f (%.1f) > (%.1f-%.1f)*2=%.1f\n",car->_name,o->getCarPtr()->_name,catchdist,*mincatchdist,distance,o->getDistance(),speed,ospeed,(speed-ospeed)*2); #endif - return false; + return false; } // Compute offset to normal target point for overtaking or let pass an opponent. float Driver::getOffset() { - int i, avoidmovt = 0; - double /*catchdist,*/ mincatchdist = MAX(100.0, car->_speed_x * 5), mindist = -1000.0; - Opponent *o = NULL; - double lane2left = rldata->lane * car->_trkPos.seg->width; - double lane2right = car->_trkPos.seg->width-lane2left; - avoidmode = 0; - sideratio = 100.0; + int i, avoidmovt = 0; + double /*catchdist,*/ mincatchdist = MAX(100.0, car->_speed_x * 5), mindist = -1000.0; + Opponent *o = NULL; + double lane2left = rldata->lane * car->_trkPos.seg->width; + double lane2right = car->_trkPos.seg->width-lane2left; + avoidmode = 0; + sideratio = 100.0; - avoidlftoffset = car->_trkPos.seg->width / 2; - avoidrgtoffset = -car->_trkPos.seg->width / 2; + avoidlftoffset = car->_trkPos.seg->width / 2; + avoidrgtoffset = -car->_trkPos.seg->width / 2; - // Increment speed dependent. - //double incspeed = MIN(40.0, MAX(30.0, currentspeed)); - //double incfactor = (MAX_INC_FACTOR*0.5 - MIN(incspeed/10, MAX_INC_FACTOR*0.5-0.5)) * 60 * IncFactor; - //double incspeed = MIN(60.0, MAX(40.0, currentspeed)) - 10.0; - //double incfactor = (MAX_INC_FACTOR - MIN(fabs(incspeed)/MAX_INC_FACTOR, (MAX_INC_FACTOR - 1.0f))) * (10.0f + MAX(0.0, (CA-1.9)*10)) * IncFactor; - double incfactor = (MAX_INC_FACTOR - MIN(40.0/MAX_INC_FACTOR, (MAX_INC_FACTOR - 1.0f))) * (10.0f + MAX(0.0, (CA-1.9)*10)) * IncFactor; + // Increment speed dependent. + //double incspeed = MIN(40.0, MAX(30.0, currentspeed)); + //double incfactor = (MAX_INC_FACTOR*0.5 - MIN(incspeed/10, MAX_INC_FACTOR*0.5-0.5)) * 60 * IncFactor; + //double incspeed = MIN(60.0, MAX(40.0, currentspeed)) - 10.0; + //double incfactor = (MAX_INC_FACTOR - MIN(fabs(incspeed)/MAX_INC_FACTOR, (MAX_INC_FACTOR - 1.0f))) * (10.0f + MAX(0.0, (CA-1.9)*10)) * IncFactor; + double incfactor = (MAX_INC_FACTOR - MIN(40.0/MAX_INC_FACTOR, (MAX_INC_FACTOR - 1.0f))) * (10.0f + MAX(0.0, (CA-1.9)*10)) * IncFactor; - //double rgtinc = incfactor * MIN(3.0, MAX(0.6, 1.0 + rldata->mInverse * (rldata->mInverse<0.0?-5:100))); - //double lftinc = incfactor * MIN(3.0, MAX(0.6, 1.0 - rldata->mInverse * (rldata->mInverse>0.0?-5:100))); - double ri = rldata->aInverse; - double rgtinc = incfactor * MIN(3.0, MAX(0.6, 1.0 + (ri < 0.0 ? ri*4 : ri*MAX(10.0, car->_speed_x-25)*2*OutSteerFactor))); - double lftinc = incfactor * MIN(3.0, MAX(0.6, 1.0 - (ri > 0.0 ? ri*4 : ri*MAX(10.0,car->_speed_x-25)*2*OutSteerFactor))); - - //double reduce_movt = MAX(0.01, 1.0 - (MIN(1.0, fabs(laststeer))*2 * fabs(angle-speedangle)*3)); + //double rgtinc = incfactor * MIN(3.0, MAX(0.6, 1.0 + rldata->mInverse * (rldata->mInverse<0.0?-5:100))); + //double lftinc = incfactor * MIN(3.0, MAX(0.6, 1.0 - rldata->mInverse * (rldata->mInverse>0.0?-5:100))); + double ri = rldata->aInverse; + double rgtinc = incfactor * MIN(3.0, MAX(0.6, 1.0 + (ri < 0.0 ? ri*4 : ri*MAX(10.0, car->_speed_x-25)*2*OutSteerFactor))); + double lftinc = incfactor * MIN(3.0, MAX(0.6, 1.0 - (ri > 0.0 ? ri*4 : ri*MAX(10.0,car->_speed_x-25)*2*OutSteerFactor))); + + //double reduce_movt = MAX(0.01, 1.0 - (MIN(1.0, fabs(laststeer))*2 * fabs(angle-speedangle)*3)); #if 1 - double reduce_movt = MAX(0.1, MIN(1.0, 1.0 - fabs(angle*2 - laststeer)) * MAX(fabs(angle-speedangle), fabs(speedangle-angle))*1); - reduce_movt = MIN(reduce_movt, MAX(0.1, 1.0 + fabs(car->_accel_x)/30)); - lftinc *= reduce_movt; - rgtinc *= reduce_movt; + double reduce_movt = MAX(0.1, MIN(1.0, 1.0 - fabs(angle*2 - laststeer)) * MAX(fabs(angle-speedangle), fabs(speedangle-angle))*1); + reduce_movt = MIN(reduce_movt, MAX(0.1, 1.0 + fabs(car->_accel_x)/30)); + lftinc *= reduce_movt; + rgtinc *= reduce_movt; #else - if (ri > 0.0) - rgtinc *= MAX(0.0, MIN(1.0, 1.0 - (angle*2-car->_yaw_rate/2) * MIN(1.0, rldata->rInverse*40))); - else if (ri < 0.0) - lftinc *= MAX(0.0, MIN(1.0, 1.0 + (angle*2-car->_yaw_rate/2) * MIN(1.0, (-rldata->rInverse)*40))); + if (ri > 0.0) + rgtinc *= MAX(0.0, MIN(1.0, 1.0 - (angle*2-car->_yaw_rate/2) * MIN(1.0, rldata->rInverse*40))); + else if (ri < 0.0) + lftinc *= MAX(0.0, MIN(1.0, 1.0 + (angle*2-car->_yaw_rate/2) * MIN(1.0, (-rldata->rInverse)*40))); #endif - double moffset = car->_trkPos.toMiddle; + double moffset = car->_trkPos.toMiddle; - //double origoffset = moffset; + //double origoffset = moffset; - double Width = car->_trkPos.seg->width; + double Width = car->_trkPos.seg->width; #if 1 - double lftmargin = GetModD( tLftMargin, rldata->nextdiv ); - double rgtmargin = GetModD( tRgtMargin, rldata->nextdiv ); - double maxoffset = MIN(moffset+OVERTAKE_OFFSET_INC*lftinc*4, Width/2 - (car->_dimension_y+SideMargin+rgtmargin)); - double minoffset = MAX(moffset-OVERTAKE_OFFSET_INC*rgtinc*4, -(Width/2 - (car->_dimension_y+SideMargin+lftmargin))); + double lftmargin = GetModD( tLftMargin, rldata->nextdiv ); + double rgtmargin = GetModD( tRgtMargin, rldata->nextdiv ); + double maxoffset = MIN(moffset+OVERTAKE_OFFSET_INC*lftinc*4, Width/2 - (car->_dimension_y+SideMargin+rgtmargin)); + double minoffset = MAX(moffset-OVERTAKE_OFFSET_INC*rgtinc*4, -(Width/2 - (car->_dimension_y+SideMargin+lftmargin))); - double oldmax = maxoffset, oldmin = minoffset; + double oldmax = maxoffset, oldmin = minoffset; - { - ri = (fabs(rldata->aInverse) < fabs(rldata->mInverse) ? rldata->aInverse : rldata->mInverse); - if (rldata->mInverse > 0.0) - maxoffset = MIN(maxoffset, MAX(Width/8, Width/2 - (1.5 + ri*1000))); - else - minoffset = MAX(minoffset, MIN(-Width/8, -Width/2 + (1.5 - ri*1000))); - } + { + ri = (fabs(rldata->aInverse) < fabs(rldata->mInverse) ? rldata->aInverse : rldata->mInverse); + if (rldata->mInverse > 0.0) + maxoffset = MIN(maxoffset, MAX(Width/8, Width/2 - (1.5 + ri*1000))); + else + minoffset = MAX(minoffset, MIN(-Width/8, -Width/2 + (1.5 - ri*1000))); + } #endif - - //myoffset = car->_trkPos.toMiddle; - if (mode == mode_normal) - { - moffset = rldata->offset; - myoffset = (float) moffset; - } - else - { - // reduce amount we deviate from the raceline according to how long we've been avoiding, and also - // how fast we're going. - //double dspeed = MAX(0.0, rldata->speed - currentspeed) * 4; - //double pspeed = MAX(1.0, 60.0 - (currentspeed - (30.0 + MAX(0.0, car->_accel_x) + dspeed))) / 10; + + //myoffset = car->_trkPos.toMiddle; + if (mode == mode_normal) + { + moffset = rldata->offset; + myoffset = (float) moffset; + } + else + { + // reduce amount we deviate from the raceline according to how long we've been avoiding, and also + // how fast we're going. + //double dspeed = MAX(0.0, rldata->speed - currentspeed) * 4; + //double pspeed = MAX(1.0, 60.0 - (currentspeed - (30.0 + MAX(0.0, car->_accel_x) + dspeed))) / 10; - // instead of toMiddle just aiming at where the car currently is, we move it in the direction - // the car's travelling ... but less so if the speedangle is different from the car's angle. - double sa = speedangle; - //double anglechange = ((sa*0.8) * MAX(0.0, 1.0 - fabs(sa-angle)*(0.6+fabs(sa-angle)))) * 0.7; - double anglechange = ((sa*1.0) * MAX(0.0, 1.0 - fabs(sa-angle))) * (fabs(currentspeed)/50); - double toMiddle = car->_trkPos.toMiddle + anglechange*0; - moffset = toMiddle; - myoffset = (float) moffset; + // instead of toMiddle just aiming at where the car currently is, we move it in the direction + // the car's travelling ... but less so if the speedangle is different from the car's angle. + double sa = speedangle; + //double anglechange = ((sa*0.8) * MAX(0.0, 1.0 - fabs(sa-angle)*(0.6+fabs(sa-angle)))) * 0.7; + double anglechange = ((sa*1.0) * MAX(0.0, 1.0 - fabs(sa-angle))) * (fabs(currentspeed)/50); + double toMiddle = car->_trkPos.toMiddle + anglechange*0; + moffset = toMiddle; + myoffset = (float) moffset; - if (mode == mode_correcting && avoidtime < simtime) - avoidtime += deltaTime*0.8; - if (simtime - avoidtime > 3.0) - avoidtime = simtime - 3.0; + if (mode == mode_correcting && avoidtime < simtime) + avoidtime += deltaTime*0.8; + if (simtime - avoidtime > 3.0) + avoidtime = simtime - 3.0; - if (0) - { - if (toMiddle > rldata->offset) - moffset = MIN(toMiddle, rldata->offset + (simtime-avoidtime) * 45.0 * incfactor/8); - else - moffset = MAX(toMiddle, rldata->offset - (simtime-avoidtime) * 45.0 * incfactor/8); - } + if (0) + { + if (toMiddle > rldata->offset) + moffset = MIN(toMiddle, rldata->offset + (simtime-avoidtime) * 45.0 * incfactor/8); + else + moffset = MAX(toMiddle, rldata->offset - (simtime-avoidtime) * 45.0 * incfactor/8); + } #if 0 - if (fabs(car->_trkPos.toMiddle) < MAX(fabs(minoffset), fabs(maxoffset))) - { - if (anglechange > 0.0) - minoffset = MIN(maxoffset, MAX(minoffset, car->_trkPos.toMiddle - MAX(0.1, 1.0 - anglechange*2)*2)); - else - maxoffset = MAX(minoffset, MIN(maxoffset, car->_trkPos.toMiddle + MAX(0.1, 1.0 - fabs(anglechange*2))*2)); - } + if (fabs(car->_trkPos.toMiddle) < MAX(fabs(minoffset), fabs(maxoffset))) + { + if (anglechange > 0.0) + minoffset = MIN(maxoffset, MAX(minoffset, car->_trkPos.toMiddle - MAX(0.1, 1.0 - anglechange*2)*2)); + else + maxoffset = MAX(minoffset, MIN(maxoffset, car->_trkPos.toMiddle + MAX(0.1, 1.0 - fabs(anglechange*2))*2)); + } #endif - } + } - { - minoffset = MAX(minoffset, car->_trkPos.toMiddle - OVERTAKE_OFFSET_INC*rgtinc*100); - maxoffset = MIN(maxoffset, car->_trkPos.toMiddle + OVERTAKE_OFFSET_INC*lftinc*100); - } - //myoffset = car->_trkPos.toMiddle; + { + minoffset = MAX(minoffset, car->_trkPos.toMiddle - OVERTAKE_OFFSET_INC*rgtinc*100); + maxoffset = MIN(maxoffset, car->_trkPos.toMiddle + OVERTAKE_OFFSET_INC*lftinc*100); + } + //myoffset = car->_trkPos.toMiddle; - // Side Collision. - for (i = 0; i < opponents->getNOpponents(); i++) - { - tCarElt *ocar = opponent[i].getCarPtr(); + // Side Collision. + for (i = 0; i < opponents->getNOpponents(); i++) + { + tCarElt *ocar = opponent[i].getCarPtr(); - if (ocar->_state & (RM_CAR_STATE_NO_SIMU & ~RM_CAR_STATE_PIT)) - continue; + if (ocar->_state & (RM_CAR_STATE_NO_SIMU & ~RM_CAR_STATE_PIT)) + continue; - if (fabs(ocar->_trkPos.toMiddle) > Width/2 + 3.0 && - fabs(car->_trkPos.toMiddle-ocar->_trkPos.toMiddle) >= 5.0) - continue; + if (fabs(ocar->_trkPos.toMiddle) > Width/2 + 3.0 && + fabs(car->_trkPos.toMiddle-ocar->_trkPos.toMiddle) >= 5.0) + continue; - if ((opponent[i].getState() & OPP_SIDE)) - { - o = &opponent[i]; + if ((opponent[i].getState() & OPP_SIDE)) + { + o = &opponent[i]; if (DebugMsg & debug_overtake) fprintf(stderr,"%s SIDE %s\n",car->_name,ocar->_name);fflush(stderr); - - double sidedist = fabs(ocar->_trkPos.toLeft - car->_trkPos.toLeft); - double sidemargin = opponent[i].getWidth()/2 + getWidth()/2 + 5.0f + MAX(fabs(rldata->rInverse), fabs(rldata->mInverse))*100; - double side = (car->_trkPos.toMiddle-angle) - (ocar->_trkPos.toMiddle-opponent[i].getAngle()); - double sidedist2 = sidedist; - if (side > 0.0) - { - // I'm on his left - sidedist2 -= (o->getSpeedAngle() - speedangle) * 40; - sidemargin -= MIN(0.0, rldata->rInverse*100); - } - else - { - // I'm on his right - sidedist2 -= (speedangle - o->getSpeedAngle()) * 40; - sidemargin += MAX(0.0, rldata->rInverse*100); - } - int closing = (sidedist2 < sidedist); + + double sidedist = fabs(ocar->_trkPos.toLeft - car->_trkPos.toLeft); + double sidemargin = opponent[i].getWidth()/2 + getWidth()/2 + 5.0f + MAX(fabs(rldata->rInverse), fabs(rldata->mInverse))*100; + double side = (car->_trkPos.toMiddle-angle) - (ocar->_trkPos.toMiddle-opponent[i].getAngle()); + double sidedist2 = sidedist; + if (side > 0.0) + { + // I'm on his left + sidedist2 -= (o->getSpeedAngle() - speedangle) * 40; + sidemargin -= MIN(0.0, rldata->rInverse*100); + } + else + { + // I'm on his right + sidedist2 -= (speedangle - o->getSpeedAngle()) * 40; + sidemargin += MAX(0.0, rldata->rInverse*100); + } + int closing = (sidedist2 < sidedist); - if (sidedist < sidemargin || sidedist2 < sidemargin) - { - //double w = Width/WIDTHDIV-BORDER_OVERTAKE_MARGIN; - //double sdiff = 2.0 - MAX(sidemargin-sidedist, sidemargin-sidedist2)/sidemargin; - double sdiff = MAX(sidemargin-sidedist, sidemargin-sidedist2) + MAX(0.0, sidedist - sidedist2); + if (sidedist < sidemargin || sidedist2 < sidemargin) + { + //double w = Width/WIDTHDIV-BORDER_OVERTAKE_MARGIN; + //double sdiff = 2.0 - MAX(sidemargin-sidedist, sidemargin-sidedist2)/sidemargin; + double sdiff = MAX(sidemargin-sidedist, sidemargin-sidedist2) + MAX(0.0, sidedist - sidedist2); - if (side > 0.0) { - double linc = OVERTAKE_OFFSET_INC * (lftinc * MAX(0.2, MIN(1.1, sdiff/4)) * 1.5); - if (rldata->rInverse < 0.0) - linc -= rldata->rInverse * 200 * IncFactor; - myoffset += (float) linc; - //if (rldata->rInverse < 0.0) - // myoffset -= rldata->rInverse * 500 * IncFactor; - avoidmovt = 1; + if (side > 0.0) { + double linc = OVERTAKE_OFFSET_INC * (lftinc * MAX(0.2, MIN(1.1, sdiff/4)) * 1.5); + if (rldata->rInverse < 0.0) + linc -= rldata->rInverse * 200 * IncFactor; + myoffset += (float) linc; + //if (rldata->rInverse < 0.0) + // myoffset -= rldata->rInverse * 500 * IncFactor; + avoidmovt = 1; if (DebugMsg & debug_overtake) fprintf(stderr,"%s SIDE to Rgt %s, MOVING LEFT by %.3f, sm=%.3f sd=%.3f/%.3f sm-sd=%.3f mInv=%.3f\n",car->_name,ocar->_name,(float) (OVERTAKE_OFFSET_INC*lftinc*MAX(0.2f, MIN(1.5f, sdiff))),sidemargin,sidedist,sidedist2,sdiff,rldata->mInverse);fflush(stderr); - } else if (side <= 0.0) { - double rinc = OVERTAKE_OFFSET_INC * (rgtinc * MAX(0.2, MIN(1.1, sdiff/4)) * 1.5); - if (rldata->rInverse > 0.0) - rinc += rldata->rInverse * 200 * IncFactor; - myoffset -= (float) rinc; - //if (rldata->rInverse > 0.0) - // myoffset -= rldata->rInverse * 500 * IncFactor; - avoidmovt = 1; + } else if (side <= 0.0) { + double rinc = OVERTAKE_OFFSET_INC * (rgtinc * MAX(0.2, MIN(1.1, sdiff/4)) * 1.5); + if (rldata->rInverse > 0.0) + rinc += rldata->rInverse * 200 * IncFactor; + myoffset -= (float) rinc; + //if (rldata->rInverse > 0.0) + // myoffset -= rldata->rInverse * 500 * IncFactor; + avoidmovt = 1; if (DebugMsg & debug_overtake) fprintf(stderr,"%s SIDE to Lft %s, MOVING RIGHT by %.3f sm-sd=%.2f mo=%.3f\n",car->_name,ocar->_name,(OVERTAKE_OFFSET_INC*lftinc*MAX(1.0f, MIN(2.0f, sdiff))),sdiff,myoffset);fflush(stderr); - } + } - if (avoidmovt) - sideratio = MIN(sidedist,sidedist2)/sidemargin; + if (avoidmovt) + sideratio = MIN(sidedist,sidedist2)/sidemargin; else if (DebugMsg & debug_overtake) fprintf(stderr,"%s SIDE %s, NO MOVE %.1f\n",car->_name,ocar->_name,myoffset);fflush(stderr); - } - else if (sidedist > sidemargin+3.0) - { - if ((car->_trkPos.toLeft > ocar->_trkPos.toLeft && rldata->rInverse > 0.0) || - (car->_trkPos.toLeft < ocar->_trkPos.toLeft && rldata->rInverse < 0.0)) - avoidtime = MIN(simtime, avoidtime + MIN(deltaTime*0.9, fabs(rldata->rInverse*1.2))); + } + else if (sidedist > sidemargin+3.0) + { + if ((car->_trkPos.toLeft > ocar->_trkPos.toLeft && rldata->rInverse > 0.0) || + (car->_trkPos.toLeft < ocar->_trkPos.toLeft && rldata->rInverse < 0.0)) + avoidtime = MIN(simtime, avoidtime + MIN(deltaTime*0.9, fabs(rldata->rInverse*1.2))); - if (ocar->_trkPos.toLeft > car->_trkPos.toLeft && - car->_trkPos.toLeft < MIN(lane2left, 4.0 + fabs(nextCRinverse)*1000)) - { - myoffset -= (float) (OVERTAKE_OFFSET_INC*lftinc/4); + if (ocar->_trkPos.toLeft > car->_trkPos.toLeft && + car->_trkPos.toLeft < MIN(lane2left, 4.0 + fabs(nextCRinverse)*1000)) + { + myoffset -= (float) (OVERTAKE_OFFSET_INC*lftinc/4); if (DebugMsg & debug_overtake) fprintf(stderr,"%s SIDE to Rgt %s, MOVING BACK TO RIGHT\n",car->_name,ocar->_name);fflush(stderr); - if (!avoidmode) - avoidtime = MIN(simtime, avoidtime+deltaTime*0.5); - } - else if (ocar->_trkPos.toLeft < car->_trkPos.toLeft && - car->_trkPos.toRight < MIN(lane2right, 4.0 + fabs(nextCRinverse)*1000)) - { - myoffset += (float) (OVERTAKE_OFFSET_INC*rgtinc/4); + if (!avoidmode) + avoidtime = MIN(simtime, avoidtime+deltaTime*0.5); + } + else if (ocar->_trkPos.toLeft < car->_trkPos.toLeft && + car->_trkPos.toRight < MIN(lane2right, 4.0 + fabs(nextCRinverse)*1000)) + { + myoffset += (float) (OVERTAKE_OFFSET_INC*rgtinc/4); if (DebugMsg & debug_overtake) fprintf(stderr,"%s SIDE to Lft %s, MOVING BACK TO LEFT\n",car->_name,ocar->_name);fflush(stderr); - if (!avoidmode) - avoidtime = MIN(simtime, avoidtime+deltaTime*0.5); - } + if (!avoidmode) + avoidtime = MIN(simtime, avoidtime+deltaTime*0.5); + } else if (DebugMsg & debug_overtake) fprintf(stderr,"%s SIDE %s, NO MOVE %.1f\n",car->_name,ocar->_name,myoffset);fflush(stderr); - } + } else if (DebugMsg & debug_overtake) fprintf(stderr,"%s SIDE %s, NO MOVE AT ALL! %.1f\n",car->_name,ocar->_name,myoffset);fflush(stderr); - if (ocar->_trkPos.toLeft > car->_trkPos.toLeft) - { - avoidrgtoffset = (float) MAX(avoidrgtoffset, ocar->_trkPos.toMiddle + (o->getWidth()+1.0f)); - avoidmode |= avoidright; - //if (avoidmovt) - avoidmode |= avoidside; - if (closing) - avoidmode |= avoidsideclosing; - } - else - { - avoidlftoffset = (float) MIN(avoidlftoffset, ocar->_trkPos.toMiddle - (o->getWidth()+1.0f)); - avoidmode |= avoidleft; - //if (avoidmovt) - avoidmode |= avoidside; - if (closing) - avoidmode |= avoidsideclosing; - } + if (ocar->_trkPos.toLeft > car->_trkPos.toLeft) + { + avoidrgtoffset = (float) MAX(avoidrgtoffset, ocar->_trkPos.toMiddle + (o->getWidth()+1.0f)); + avoidmode |= avoidright; + //if (avoidmovt) + avoidmode |= avoidside; + if (closing) + avoidmode |= avoidsideclosing; + } + else + { + avoidlftoffset = (float) MIN(avoidlftoffset, ocar->_trkPos.toMiddle - (o->getWidth()+1.0f)); + avoidmode |= avoidleft; + //if (avoidmovt) + avoidmode |= avoidside; + if (closing) + avoidmode |= avoidsideclosing; + } - } - } + } + } - if (avoidmode) - { - if (!avoidmovt) - avoidtime = MIN(simtime, avoidtime+deltaTime*1.0); - goto end_getoffset; - } + if (avoidmode) + { + if (!avoidmovt) + avoidtime = MIN(simtime, avoidtime+deltaTime*1.0); + goto end_getoffset; + } #if 0 - // don't try and front-avoid if we're struggling for control! - if (avgaccel_x - fabs(laststeer) * fabs(angle-speedangle) < -10.0) - goto end_getoffset; + // don't try and front-avoid if we're struggling for control! + if (avgaccel_x - fabs(laststeer) * fabs(angle-speedangle) < -10.0) + goto end_getoffset; - if (rldata->lftmargin > 0.0 && minoffset < rldata->offset - rldata->lftmargin) - minoffset = rldata->offset - rldata->lftmargin; - if (rldata->rgtmargin > 0.0 && maxoffset > rldata->offset + rldata->rgtmargin) - maxoffset = rldata->offset + rldata->rgtmargin; + if (rldata->lftmargin > 0.0 && minoffset < rldata->offset - rldata->lftmargin) + minoffset = rldata->offset - rldata->lftmargin; + if (rldata->rgtmargin > 0.0 && maxoffset > rldata->offset + rldata->rgtmargin) + maxoffset = rldata->offset + rldata->rgtmargin; #endif - if (car->_speed_x > 20.0 || simtime > 10.0) - { - double caution = rldata->overtakecaution; + if (car->_speed_x > 20.0 || simtime > 10.0) + { + double caution = rldata->overtakecaution; - { - tTrackSeg *wseg = (rldata->rInverse > 0.0 ? car->_wheelSeg(FRNT_LFT) : car->_wheelSeg(FRNT_RGT)); - if (wseg->surface->kFriction > car->_trkPos.seg->surface->kFriction) - caution += (wseg->surface->kFriction - car->_trkPos.seg->surface->kFriction) * 4; - } + { + tTrackSeg *wseg = (rldata->rInverse > 0.0 ? car->_wheelSeg(FRNT_LFT) : car->_wheelSeg(FRNT_RGT)); + if (wseg->surface->kFriction > car->_trkPos.seg->surface->kFriction) + caution += (wseg->surface->kFriction - car->_trkPos.seg->surface->kFriction) * 4; + } - //caution += fabs(speedangle - angle)*10; - int otry_success = 0; - double rInverse = rldata->rInverse; - if (fabs(nextCRinverse) > fabs(rInverse)) - rInverse = nextCRinverse; + //caution += fabs(speedangle - angle)*10; + int otry_success = 0; + double rInverse = rldata->rInverse; + if (fabs(nextCRinverse) > fabs(rInverse)) + rInverse = nextCRinverse; - for (int otry=0; otry<=1; otry++) - { - // Overtake. - for (i = 0; i < opponents->getNOpponents(); i++) - { - tCarElt *ocar = opponent[i].getCarPtr(); - - // strategy telling us to follow this car? - if ((opponent[i].getState() & OPP_FRONT_FOLLOW)) - continue; + for (int otry=0; otry<=1; otry++) + { + // Overtake. + for (i = 0; i < opponents->getNOpponents(); i++) + { + tCarElt *ocar = opponent[i].getCarPtr(); + + // strategy telling us to follow this car? + if ((opponent[i].getState() & OPP_FRONT_FOLLOW)) + continue; - // off track or a long way wide of us? - if (!(opponent[i].getState() & OPP_COLL) && - fabs(ocar->_trkPos.toMiddle) > Width/2 + 3.0 && - fabs(car->_trkPos.toMiddle-ocar->_trkPos.toMiddle) >= 8.0) - continue; + // off track or a long way wide of us? + if (!(opponent[i].getState() & OPP_COLL) && + fabs(ocar->_trkPos.toMiddle) > Width/2 + 3.0 && + fabs(car->_trkPos.toMiddle-ocar->_trkPos.toMiddle) >= 8.0) + continue; - if (ocar->_state & (RM_CAR_STATE_NO_SIMU & ~RM_CAR_STATE_PIT)) - continue; + if (ocar->_state & (RM_CAR_STATE_NO_SIMU & ~RM_CAR_STATE_PIT)) + continue; - if ((opponent[i].getState() & OPP_FRONT) && - !(0 && opponent[i].isTeamMate() && car->race.laps <= opponent[i].getCarPtr()->race.laps)) - { + if ((opponent[i].getState() & OPP_FRONT) && + !(0 && opponent[i].isTeamMate() && car->race.laps <= opponent[i].getCarPtr()->race.laps)) + { #if 1 - if (canOvertake(&opponent[i], &mincatchdist, false, (otry == 1))) - o = &opponent[i]; + if (canOvertake(&opponent[i], &mincatchdist, false, (otry == 1))) + o = &opponent[i]; #else - int segid = car->_trkPos.seg->id; - int osegid = opponent[i].getCarPtr()->_trkPos.seg->id; - double distance = opponent[i].getDistance(); - double truespeed = getTrueSpeed(); - double truespeed2 = truespeed + MAX(0.0, 6.0 - fabs(rInverse)*400); - double speed = MIN(truespeed2, MIN(rldata->avspeed, truespeed+MAX(1.0, (((car->_speed_x*car->_speed_x)/100)-distance)/3))); - double ospeed = opponent[i].getTrueSpeed(); - double try_timer = (0.3 + (1.0 - ((simtime-frontavoidtime)/5.0)/2)) * otry; - double sidedist = fabs(car->_trkPos.toMiddle - opponent[i].getCarPtr()->_trkPos.toMiddle); - double spddiff = (speed - ospeed)*1.5; - catchdist = ((double) MIN(speed*distance/(spddiff), distance*CATCH_FACTOR) + (speed * caution)) * (1.0 + try_timer); - double sdiff = ((distance - MAX(0.0, 5.0-sidedist)) - (spddiff)*2); + int segid = car->_trkPos.seg->id; + int osegid = opponent[i].getCarPtr()->_trkPos.seg->id; + double distance = opponent[i].getDistance(); + double truespeed = getTrueSpeed(); + double truespeed2 = truespeed + MAX(0.0, 6.0 - fabs(rInverse)*400); + double speed = MIN(truespeed2, MIN(rldata->avspeed, truespeed+MAX(1.0, (((car->_speed_x*car->_speed_x)/100)-distance)/3))); + double ospeed = opponent[i].getTrueSpeed(); + double try_timer = (0.3 + (1.0 - ((simtime-frontavoidtime)/5.0)/2)) * otry; + double sidedist = fabs(car->_trkPos.toMiddle - opponent[i].getCarPtr()->_trkPos.toMiddle); + double spddiff = (speed - ospeed)*1.5; + catchdist = ((double) MIN(speed*distance/(spddiff), distance*CATCH_FACTOR) + (speed * caution)) * (1.0 + try_timer); + double sdiff = ((distance - MAX(0.0, 5.0-sidedist)) - (spddiff)*2); - if (catchdist < mincatchdist && speed >= ospeed && sdiff < speed/(3+caution)) - { - double aspeed = speed+1.0; - double aspeed2 = aspeed-3.0; - if (truespeed < currentspeed) - speed -= currentspeed - truespeed; - if (rldata->avspeed < currentspeed && car->_accel_x < -2.0 && - ((rInverse > 0.001 && speedangle < 0.0) || - (rInverse < -0.001 && speedangle > 0.0))) - speed -= fabs(speedangle*4); - - if (speed > ospeed) - catchdist = ((double) MIN(speed*distance/(spddiff), distance*CATCH_FACTOR) + (speed * caution)) * (0.6 + try_timer); - else - catchdist = 10000.0; + if (catchdist < mincatchdist && speed >= ospeed && sdiff < speed/(3+caution)) + { + double aspeed = speed+1.0; + double aspeed2 = aspeed-3.0; + if (truespeed < currentspeed) + speed -= currentspeed - truespeed; + if (rldata->avspeed < currentspeed && car->_accel_x < -2.0 && + ((rInverse > 0.001 && speedangle < 0.0) || + (rInverse < -0.001 && speedangle > 0.0))) + speed -= fabs(speedangle*4); + + if (speed > ospeed) + catchdist = ((double) MIN(speed*distance/(spddiff), distance*CATCH_FACTOR) + (speed * caution)) * (0.6 + try_timer); + else + catchdist = 10000.0; - if (catchdist < mincatchdist) // && ((catchdist < MAX(20.0, (distance * 3 + (speed-ospeed)))) || distance + caution < 3.0 + MIN(50.0, car->_speed_x)/15)) - { - - double mradius = MAX(5.0, 100.0 - fabs(rInverse) * 5000); - int odiv = (rldata->thisdiv + int(distance/3)); - double oradius = MAX(5.0, 100.0 - fabs(raceline->getRInverse(odiv)) * 5000); + if (catchdist < mincatchdist) // && ((catchdist < MAX(20.0, (distance * 3 + (speed-ospeed)))) || distance + caution < 3.0 + MIN(50.0, car->_speed_x)/15)) + { + + double mradius = MAX(5.0, 100.0 - fabs(rInverse) * 5000); + int odiv = (rldata->thisdiv + int(distance/3)); + double oradius = MAX(5.0, 100.0 - fabs(raceline->getRInverse(odiv)) * 5000); - if (simtime > 1.0 && - (catchdist < MIN(MIN(500.0, aspeed*7.0), MIN(mradius, oradius)*1.5) && - distance < MAX(3.0, MIN(speed, aspeed2)/4 + (aspeed2-ospeed)) && - ospeed < MAX(10.0, aspeed))) - { + if (simtime > 1.0 && + (catchdist < MIN(MIN(500.0, aspeed*7.0), MIN(mradius, oradius)*1.5) && + distance < MAX(3.0, MIN(speed, aspeed2)/4 + (aspeed2-ospeed)) && + ospeed < MAX(10.0, aspeed))) + { if (DebugMsg & debug_overtake) fprintf(stderr,"%s -> %s (%.1f < %.1f (ot=%.2f))\n",car->_name,ocar->_name,catchdist,mincatchdist,caution);fflush(stderr); - mincatchdist = catchdist; - o = &opponent[i]; - otry_success = otry; - } - } + mincatchdist = catchdist; + o = &opponent[i]; + otry_success = otry; + } + } else if (DebugMsg & debug_overtake) fprintf(stderr,"%s -> %s CANCEL 2 (%.1f > %.1f || %.1f < %.1f || %.3f > %.3f)\n",car->_name,ocar->_name,catchdist,mincatchdist,speed,ospeed,sdiff,speed/(3+caution)); - } + } else if (DebugMsg & debug_overtake) fprintf(stderr,"%s -> %s CANCEL 1 (%.1f > %.1f || %.1f < %.1f || %.3f > %.3f)\n",car->_name,ocar->_name,catchdist,mincatchdist,speed,ospeed,sdiff,speed/(3+caution)); #endif - } - } + } + } - if (o || mode != mode_avoiding) break; - } + if (o || mode != mode_avoiding) break; + } - if (o != NULL) - { - tCarElt *ocar = o->getCarPtr(); + if (o != NULL) + { + tCarElt *ocar = o->getCarPtr(); - // Compute the width around the middle which we can use for overtaking. - //float w = ocar->_trkPos.seg->width/WIDTHDIV-BORDER_OVERTAKE_MARGIN; - // Compute the opponents distance to the middle. - //float otm = ocar->_trkPos.toMiddle; - // Define the with of the middle range. - //float wm = ocar->_trkPos.seg->width*CENTERDIV; - float sidedist = fabs(car->_trkPos.toMiddle-ocar->_trkPos.toMiddle); - //double sdist = (rInverse > 0.0 ? (-sidedist - 3.0) : (sidedist - 3.0)); + // Compute the width around the middle which we can use for overtaking. + //float w = ocar->_trkPos.seg->width/WIDTHDIV-BORDER_OVERTAKE_MARGIN; + // Compute the opponents distance to the middle. + //float otm = ocar->_trkPos.toMiddle; + // Define the with of the middle range. + //float wm = ocar->_trkPos.seg->width*CENTERDIV; + float sidedist = fabs(car->_trkPos.toMiddle-ocar->_trkPos.toMiddle); + //double sdist = (rInverse > 0.0 ? (-sidedist - 3.0) : (sidedist - 3.0)); - //int avoidingside = (otm > wm && myoffset > -w) ? TR_RGT : ((otm < -wm && myoffset < w) ? TR_LFT : TR_STR); - int avoidingside = (car->_trkPos.toLeft > ocar->_trkPos.toLeft ? TR_LFT : TR_RGT); - int mustmove = 0; - int cancelovertake = 0; - double distance = o->getDistance(); + //int avoidingside = (otm > wm && myoffset > -w) ? TR_RGT : ((otm < -wm && myoffset < w) ? TR_LFT : TR_STR); + int avoidingside = (car->_trkPos.toLeft > ocar->_trkPos.toLeft ? TR_LFT : TR_RGT); + int mustmove = 0; + int cancelovertake = 0; + double distance = o->getDistance(); - if (avoidingside != TR_STR) - { - int newside = checkSwitch(avoidingside, o, ocar); + if (avoidingside != TR_STR) + { + int newside = checkSwitch(avoidingside, o, ocar); if (DebugMsg & debug_overtake) fprintf(stderr," AVOIDING A %c\n",(avoidingside==TR_LFT?'L':'R')); - if (newside != avoidingside) - { + if (newside != avoidingside) + { if (DebugMsg & debug_overtake) fprintf(stderr," SWITCH 1 from %c to %c\n",(avoidingside==TR_LFT?'L':'R'),(newside==TR_LFT?'L':'R')); - avoidingside = newside; - mustmove = 1; - } + avoidingside = newside; + mustmove = 1; + } - if ((((avoidingside == prefer_side && prefer_side != TR_STR) || (avoidingside == car->_trkPos.seg->type)) && distance > 1.0) || - rldata->braking <= 0.0) - { + if ((((avoidingside == prefer_side && prefer_side != TR_STR) || (avoidingside == car->_trkPos.seg->type)) && distance > 1.0) || + rldata->braking <= 0.0) + { #if 1 - if (!(canOvertake(o, &mincatchdist, true, false))) - { + if (!(canOvertake(o, &mincatchdist, true, false))) + { if (DebugMsg & debug_overtake) fprintf(stderr," CANCEL :(\n"); - cancelovertake = 1; - } + cancelovertake = 1; + } #else - if ((rInverse > 0.0 && angle > 0.0) || (rInverse < 0.0 && angle < 0.0)) - caution += fabs(speedangle-angle) * 20; + if ((rInverse > 0.0 && angle > 0.0) || (rInverse < 0.0 && angle < 0.0)) + caution += fabs(speedangle-angle) * 20; - double cdistance = o->getDistance() + (fabs(rInverse)*700); - double truespeed = getTrueSpeed(); - double truespeed2 = truespeed + MAX(0.0, 6.0 - fabs(rInverse)*700); - //double speed = MIN(truespeed2, MIN(rldata->avspeed, truespeed+MAX(1.0, cdistance+1.0))); - double speed = MIN(truespeed2, MIN(rldata->avspeed, truespeed+MAX(1.0, (((car->_speed_x*car->_speed_x)/100)-cdistance)/4))); - double ospeed = o->getTrueSpeed() * (1.0 + fabs(rInverse)*50); - catchdist = ((double) MIN(speed*cdistance/(speed-ospeed), cdistance*CATCH_FACTOR) + (speed * caution)) * (1.0 + fabs(rInverse)*120); - //double sdiff = ((distance + MAX(0.0, 10.0-sdist*2)) - (speed - ospeed)*2); - double sdiff = (sdist*3+(speed-ospeed)) - distance * (1.0 + fabs(rInverse*80)); + double cdistance = o->getDistance() + (fabs(rInverse)*700); + double truespeed = getTrueSpeed(); + double truespeed2 = truespeed + MAX(0.0, 6.0 - fabs(rInverse)*700); + //double speed = MIN(truespeed2, MIN(rldata->avspeed, truespeed+MAX(1.0, cdistance+1.0))); + double speed = MIN(truespeed2, MIN(rldata->avspeed, truespeed+MAX(1.0, (((car->_speed_x*car->_speed_x)/100)-cdistance)/4))); + double ospeed = o->getTrueSpeed() * (1.0 + fabs(rInverse)*50); + catchdist = ((double) MIN(speed*cdistance/(speed-ospeed), cdistance*CATCH_FACTOR) + (speed * caution)) * (1.0 + fabs(rInverse)*120); + //double sdiff = ((distance + MAX(0.0, 10.0-sdist*2)) - (speed - ospeed)*2); + double sdiff = (sdist*3+(speed-ospeed)) - distance * (1.0 + fabs(rInverse*80)); - if ((catchdist > MAX(20.0 + sdist*2, (cdistance * 3 + (speed-ospeed)))) || sdiff < 0.0) - { - cancelovertake = 1; - avoidmode = 0; + if ((catchdist > MAX(20.0 + sdist*2, (cdistance * 3 + (speed-ospeed)))) || sdiff < 0.0) + { + cancelovertake = 1; + avoidmode = 0; if (DebugMsg & debug_overtake) fprintf(stderr,"%s -> %s CANCEL 3 (%.1f < %.1f)\n",car->_name,ocar->_name,catchdist,mincatchdist);fflush(stderr); - } + } #endif - } - } + } + } - if (!cancelovertake) - { - if (avoidingside == TR_LFT) - { - sidedist -= (speedangle - o->getSpeedAngle()) * 20; - if (mustmove || - sidedist < car->_dimension_y + ocar->_dimension_y + 2.0 || - (o->getState() & OPP_COLL) || - (prefer_side == TR_RGT && car->_trkPos.toRight > MIN(lane2right, 3.0 - nextCRinverse*1000))) - { - double rinc = OVERTAKE_OFFSET_INC * rgtinc; - if (rInverse > 0.0) - rinc += rInverse * 200 * IncFactor; - myoffset -= (float) rinc; + if (!cancelovertake) + { + if (avoidingside == TR_LFT) + { + sidedist -= (speedangle - o->getSpeedAngle()) * 20; + if (mustmove || + sidedist < car->_dimension_y + ocar->_dimension_y + 2.0 || + (o->getState() & OPP_COLL) || + (prefer_side == TR_RGT && car->_trkPos.toRight > MIN(lane2right, 3.0 - nextCRinverse*1000))) + { + double rinc = OVERTAKE_OFFSET_INC * rgtinc; + if (rInverse > 0.0) + rinc += rInverse * 200 * IncFactor; + myoffset -= (float) rinc; if (DebugMsg & debug_overtake) fprintf(stderr,"%s LFT %s, MOVING RIGHT %.3f/%.3f -> %.3f (rgtinc=%.2f (%.2f) rinc=%.2f)\n",car->_name,ocar->_name,(float) (OVERTAKE_OFFSET_INC*rgtinc),rinc,myoffset,rgtinc,lftinc,rinc); - avoidmovt = 1; - } - else if (sidedist > car->_dimension_y + ocar->_dimension_y + 4.0 && - car->_trkPos.toRight < MIN(lane2right-1.0, 4.0 + fabs(nextCRinverse)*1000)) - { + avoidmovt = 1; + } + else if (sidedist > car->_dimension_y + ocar->_dimension_y + 4.0 && + car->_trkPos.toRight < MIN(lane2right-1.0, 4.0 + fabs(nextCRinverse)*1000)) + { if (DebugMsg & debug_overtake) fprintf(stderr,"%s LFT %s, MOVING BACK TO LEFT %.3f\n",car->_name,ocar->_name,(float) (OVERTAKE_OFFSET_INC*lftinc/2)); - myoffset += (float) (OVERTAKE_OFFSET_INC*lftinc)/2; - if (!avoidmode) - avoidtime = MIN(simtime, avoidtime+deltaTime); - } + myoffset += (float) (OVERTAKE_OFFSET_INC*lftinc)/2; + if (!avoidmode) + avoidtime = MIN(simtime, avoidtime+deltaTime); + } else if (DebugMsg & debug_overtake) fprintf(stderr,"%s LFT %s, HOLDING LINE\n",car->_name,ocar->_name); - } - else if (avoidingside == TR_RGT) - { - sidedist -= (o->getSpeedAngle() - speedangle) * 20; - if (mustmove || - sidedist < car->_dimension_y + ocar->_dimension_y + 2.0 || - (o->getState() & OPP_COLL) || - (prefer_side == TR_LFT && car->_trkPos.toLeft > MIN(lane2left, 3.0 + nextCRinverse*1000))) - { + } + else if (avoidingside == TR_RGT) + { + sidedist -= (o->getSpeedAngle() - speedangle) * 20; + if (mustmove || + sidedist < car->_dimension_y + ocar->_dimension_y + 2.0 || + (o->getState() & OPP_COLL) || + (prefer_side == TR_LFT && car->_trkPos.toLeft > MIN(lane2left, 3.0 + nextCRinverse*1000))) + { if (DebugMsg & debug_overtake) fprintf(stderr,"%s RGT %s, MOVING LEFT %.3f\n",car->_name,ocar->_name,(float) (OVERTAKE_OFFSET_INC*lftinc)); - double linc = OVERTAKE_OFFSET_INC * lftinc; - if (rInverse < 0.0) - linc -= rInverse * 200 * IncFactor; - myoffset += (float) linc; - avoidmovt = 1; - } - else if (sidedist > car->_dimension_y + ocar->_dimension_y + 4.0 && - car->_trkPos.toLeft < MIN(lane2left-1.0, 4.0 + fabs(nextCRinverse)*1000)) - { + double linc = OVERTAKE_OFFSET_INC * lftinc; + if (rInverse < 0.0) + linc -= rInverse * 200 * IncFactor; + myoffset += (float) linc; + avoidmovt = 1; + } + else if (sidedist > car->_dimension_y + ocar->_dimension_y + 4.0 && + car->_trkPos.toLeft < MIN(lane2left-1.0, 4.0 + fabs(nextCRinverse)*1000)) + { if (DebugMsg & debug_overtake) fprintf(stderr,"%s RGT %s, MOVING BACK TO RIGHT %.3f\n",car->_name,ocar->_name,(float) (OVERTAKE_OFFSET_INC*rgtinc/2)); - myoffset -= (float) (OVERTAKE_OFFSET_INC*rgtinc)/2; - if (!avoidmode) - avoidtime = MIN(simtime, avoidtime+deltaTime); - } + myoffset -= (float) (OVERTAKE_OFFSET_INC*rgtinc)/2; + if (!avoidmode) + avoidtime = MIN(simtime, avoidtime+deltaTime); + } else if (DebugMsg & debug_overtake) fprintf(stderr,"%s RGT %s, HOLDING LINE\n",car->_name,ocar->_name); - } - else - { - // If the opponent is near the middle we try to move the offset toward - // the inside of the expected turn. - // Try to find out the characteristic of the track up to catchdist. - tTrackSeg *seg = car->_trkPos.seg; - float length = getDistToSegEnd(); - float oldlen, seglen = length; - float lenright = 0.0f, lenleft = 0.0f; - mincatchdist = MIN(mincatchdist, DISTCUTOFF); + } + else + { + // If the opponent is near the middle we try to move the offset toward + // the inside of the expected turn. + // Try to find out the characteristic of the track up to catchdist. + tTrackSeg *seg = car->_trkPos.seg; + float length = getDistToSegEnd(); + float oldlen, seglen = length; + float lenright = 0.0f, lenleft = 0.0f; + mincatchdist = MIN(mincatchdist, DISTCUTOFF); - do { - switch (seg->type) { - case TR_LFT: - lenleft += seglen; - break; - case TR_RGT: - lenright += seglen; - break; - default: - // Do nothing. - break; - } - seg = seg->next; - seglen = seg->length; - oldlen = length; - length += seglen; - } while (oldlen < mincatchdist); + do { + switch (seg->type) { + case TR_LFT: + lenleft += seglen; + break; + case TR_RGT: + lenright += seglen; + break; + default: + // Do nothing. + break; + } + seg = seg->next; + seglen = seg->length; + oldlen = length; + length += seglen; + } while (oldlen < mincatchdist); - if (lenleft > lenright) - avoidingside = TR_RGT; - else if (lenright > lenleft) - avoidingside = TR_LFT; + if (lenleft > lenright) + avoidingside = TR_RGT; + else if (lenright > lenleft) + avoidingside = TR_LFT; - // If we are on a straight look for the next turn. - if (avoidingside == TR_STR) - { - while (seg->type == TR_STR) { - seg = seg->next; - } - // Assume: left or right if not straight. - if (seg->type == TR_LFT) { - avoidingside = TR_RGT; - } else { - avoidingside = TR_LFT; - } - } + // If we are on a straight look for the next turn. + if (avoidingside == TR_STR) + { + while (seg->type == TR_STR) { + seg = seg->next; + } + // Assume: left or right if not straight. + if (seg->type == TR_LFT) { + avoidingside = TR_RGT; + } else { + avoidingside = TR_LFT; + } + } - // Because we are inside we can go to the border. - //float maxoff = (float) ((ocar->_trkPos.seg->width - car->_dimension_y)/2.0f-BORDER_OVERTAKE_MARGIN*15); - int newside = checkSwitch( avoidingside, o, ocar ); + // Because we are inside we can go to the border. + //float maxoff = (float) ((ocar->_trkPos.seg->width - car->_dimension_y)/2.0f-BORDER_OVERTAKE_MARGIN*15); + int newside = checkSwitch( avoidingside, o, ocar ); if (DebugMsg & debug_overtake) fprintf(stderr," AVOIDING %c\n",(avoidingside==TR_LFT?'l':'r')); - if (newside != avoidingside) - { + if (newside != avoidingside) + { if (DebugMsg & debug_overtake) fprintf(stderr," SWITCH 2 from %c to %c\n",(avoidingside==TR_LFT?'l':'r'),(newside==TR_LFT?'l':'r')); - avoidingside = newside; - mustmove = 1; - } + avoidingside = newside; + mustmove = 1; + } - if (prefer_side != TR_STR && avoidingside == prefer_side) - { + if (prefer_side != TR_STR && avoidingside == prefer_side) + { #if 1 - if (!(canOvertake(o, &mincatchdist, true, false))) - cancelovertake = 1; + if (!(canOvertake(o, &mincatchdist, true, false))) + cancelovertake = 1; #else - double cdistance = o->getDistance() + (fabs(rInverse)*700); - double truespeed = getTrueSpeed(); - double truespeed2 = truespeed + MAX(0.0, 6.0 - fabs(rInverse)*700); - //double speed = MIN(truespeed2, MIN(rldata->avspeed, truespeed+MAX(1.0, cdistance+1.0))); - double speed = MIN(truespeed2, MIN(rldata->avspeed, truespeed+MAX(1.0, (((car->_speed_x*car->_speed_x)/100)-cdistance)/4))); - double ospeed = o->getTrueSpeed() * (1.0 + fabs(rInverse)*50); - catchdist = ((double) MIN(speed*cdistance/(speed-ospeed), cdistance*CATCH_FACTOR) + (speed * caution)) * (1.0 + fabs(rInverse)*120); - double sdiff = (sdist*3+(speed-ospeed)) - distance * (1.0 + fabs(rInverse*80)); - - if ((catchdist > MAX(20.0 + sdist*2, (cdistance * 3 + (speed-ospeed)))) || sdiff < 0.0) - { + double cdistance = o->getDistance() + (fabs(rInverse)*700); + double truespeed = getTrueSpeed(); + double truespeed2 = truespeed + MAX(0.0, 6.0 - fabs(rInverse)*700); + //double speed = MIN(truespeed2, MIN(rldata->avspeed, truespeed+MAX(1.0, cdistance+1.0))); + double speed = MIN(truespeed2, MIN(rldata->avspeed, truespeed+MAX(1.0, (((car->_speed_x*car->_speed_x)/100)-cdistance)/4))); + double ospeed = o->getTrueSpeed() * (1.0 + fabs(rInverse)*50); + catchdist = ((double) MIN(speed*cdistance/(speed-ospeed), cdistance*CATCH_FACTOR) + (speed * caution)) * (1.0 + fabs(rInverse)*120); + double sdiff = (sdist*3+(speed-ospeed)) - distance * (1.0 + fabs(rInverse*80)); + + if ((catchdist > MAX(20.0 + sdist*2, (cdistance * 3 + (speed-ospeed)))) || sdiff < 0.0) + { if (DebugMsg & debug_overtake) fprintf(stderr,"%s -> %s CANCEL 4 (%.1f < %.1f)\n",car->_name,ocar->_name,catchdist,mincatchdist);fflush(stderr); - cancelovertake = 1; - } + cancelovertake = 1; + } #endif - } + } - if (!cancelovertake) - { - if (mustmove || (o->getState() & OPP_COLL) || sidedist < car->_dimension_y + ocar->_dimension_y + 1.0) - { - if (avoidingside == TR_RGT) - { - sidedist -= (o->getSpeedAngle() - speedangle) * 20; - if (myoffset < maxoffset || - (prefer_side == TR_LFT && car->_trkPos.toLeft > 3.0 + nextCRinverse*1000)) - { + if (!cancelovertake) + { + if (mustmove || (o->getState() & OPP_COLL) || sidedist < car->_dimension_y + ocar->_dimension_y + 1.0) + { + if (avoidingside == TR_RGT) + { + sidedist -= (o->getSpeedAngle() - speedangle) * 20; + if (myoffset < maxoffset || + (prefer_side == TR_LFT && car->_trkPos.toLeft > 3.0 + nextCRinverse*1000)) + { if (DebugMsg & debug_overtake) fprintf(stderr,"%s RGT %s, MOVING LEFT %.3f\n",car->_name,ocar->_name,(float) (OVERTAKE_OFFSET_INC*lftinc)); - myoffset += (float) (OVERTAKE_OFFSET_INC*lftinc); - avoidmovt = 1; - } - else if (sidedist > car->_dimension_y + ocar->_dimension_y + 4.0 && - car->_trkPos.toLeft < 4.0 + fabs(nextCRinverse)*1000) - { + myoffset += (float) (OVERTAKE_OFFSET_INC*lftinc); + avoidmovt = 1; + } + else if (sidedist > car->_dimension_y + ocar->_dimension_y + 4.0 && + car->_trkPos.toLeft < 4.0 + fabs(nextCRinverse)*1000) + { if (DebugMsg & debug_overtake) fprintf(stderr,"%s RGT %s, MOVING BACK TO RIGHT %.3f\n",car->_name,ocar->_name,(float) (OVERTAKE_OFFSET_INC*rgtinc)/2); - myoffset -= (float) (OVERTAKE_OFFSET_INC*rgtinc)/2; - if (!avoidmode) - avoidtime = MIN(simtime, avoidtime+deltaTime); - } + myoffset -= (float) (OVERTAKE_OFFSET_INC*rgtinc)/2; + if (!avoidmode) + avoidtime = MIN(simtime, avoidtime+deltaTime); + } else if (DebugMsg & debug_overtake) fprintf(stderr,"%s RGT %s, NO MOVEMENT\n",car->_name,ocar->_name); - } - else - { - sidedist -= (speedangle - o->getSpeedAngle()) * 20; - if (myoffset > minoffset || - (prefer_side == TR_RGT && car->_trkPos.toRight > 3.0 - nextCRinverse*1000)) - { + } + else + { + sidedist -= (speedangle - o->getSpeedAngle()) * 20; + if (myoffset > minoffset || + (prefer_side == TR_RGT && car->_trkPos.toRight > 3.0 - nextCRinverse*1000)) + { if (DebugMsg & debug_overtake) fprintf(stderr,"%s LFT %s, MOVING RIGHT %.3f -> %.3f\n",car->_name,ocar->_name,(float) (OVERTAKE_OFFSET_INC*rgtinc),myoffset); - myoffset -= (float) (OVERTAKE_OFFSET_INC*rgtinc); - avoidmovt = 1; - } - else if (sidedist > car->_dimension_y + ocar->_dimension_y + 4.0 && - car->_trkPos.toRight < 4.0 + fabs(nextCRinverse)*1000) - { + myoffset -= (float) (OVERTAKE_OFFSET_INC*rgtinc); + avoidmovt = 1; + } + else if (sidedist > car->_dimension_y + ocar->_dimension_y + 4.0 && + car->_trkPos.toRight < 4.0 + fabs(nextCRinverse)*1000) + { if (DebugMsg & debug_overtake) fprintf(stderr,"%s LFT %s, MOVING BACK TO LEFT %.3f\n",car->_name,ocar->_name,(float) (OVERTAKE_OFFSET_INC*lftinc)/2); - myoffset += (float) (OVERTAKE_OFFSET_INC*lftinc)/2; - if (!avoidmode) - avoidtime = MIN(simtime, avoidtime+deltaTime); - } + myoffset += (float) (OVERTAKE_OFFSET_INC*lftinc)/2; + if (!avoidmode) + avoidtime = MIN(simtime, avoidtime+deltaTime); + } else if (DebugMsg & debug_overtake) fprintf(stderr,"%s LFT %s, NO MOVEMENT\n",car->_name,ocar->_name); - } - } - } - } + } + } + } + } - if (!cancelovertake) - { - //if (ocar->_trkPos.toLeft > car->_trkPos.toLeft) - if (avoidingside == TR_RGT) - { - avoidrgtoffset = (float) MAX(avoidrgtoffset, ocar->_trkPos.toMiddle + (o->getWidth()+1.0f)); - avoidmode |= avoidright; - } - else - { - avoidlftoffset = (float) MIN(avoidlftoffset, ocar->_trkPos.toMiddle - (o->getWidth()+1.0f)); - avoidmode |= avoidleft; - } - - if ((avoidingside == TR_LFT && rInverse > 0.0) || - (avoidingside == TR_RGT && rInverse < 0.0)) - avoidtime = MIN(simtime, avoidtime + MIN(deltaTime*0.9, fabs(rInverse*1.2))); + if (!cancelovertake) + { + //if (ocar->_trkPos.toLeft > car->_trkPos.toLeft) + if (avoidingside == TR_RGT) + { + avoidrgtoffset = (float) MAX(avoidrgtoffset, ocar->_trkPos.toMiddle + (o->getWidth()+1.0f)); + avoidmode |= avoidright; + } + else + { + avoidlftoffset = (float) MIN(avoidlftoffset, ocar->_trkPos.toMiddle - (o->getWidth()+1.0f)); + avoidmode |= avoidleft; + } + + if ((avoidingside == TR_LFT && rInverse > 0.0) || + (avoidingside == TR_RGT && rInverse < 0.0)) + avoidtime = MIN(simtime, avoidtime + MIN(deltaTime*0.9, fabs(rInverse*1.2))); - myoffset = (float) (MAX(minoffset, MIN(maxoffset, myoffset))); + myoffset = (float) (MAX(minoffset, MIN(maxoffset, myoffset))); - if (!otry_success) - frontavoidtime = simtime; - } - } - } + if (!otry_success) + frontavoidtime = simtime; + } + } + } - if (!avoidmode) - { - o = NULL; + if (!avoidmode) + { + o = NULL; - // Let overlap or let less damaged team mate pass. - for (i = 0; i < opponents->getNOpponents(); i++) - { - // Let the teammate with less damage overtake to use slipstreaming. - // The position change happens when the damage difference is greater than - // TEAM_DAMAGE_CHANGE_LEAD. - if ((opponent[i].getState() & OPP_LETPASS)) - { - // Behind, larger distances are smaller ("more negative"). - if (opponent[i].getDistance() > mindist) { - mindist = opponent[i].getDistance(); - o = &opponent[i]; - } - } - } + // Let overlap or let less damaged team mate pass. + for (i = 0; i < opponents->getNOpponents(); i++) + { + // Let the teammate with less damage overtake to use slipstreaming. + // The position change happens when the damage difference is greater than + // TEAM_DAMAGE_CHANGE_LEAD. + if ((opponent[i].getState() & OPP_LETPASS)) + { + // Behind, larger distances are smaller ("more negative"). + if (opponent[i].getDistance() > mindist) { + mindist = opponent[i].getDistance(); + o = &opponent[i]; + } + } + } - if (o != NULL) - { - tCarElt *ocar = o->getCarPtr(); - float side = car->_trkPos.toMiddle - ocar->_trkPos.toMiddle; - float w = car->_trkPos.seg->width/WIDTHDIV-BORDER_OVERTAKE_MARGIN; + if (o != NULL) + { + tCarElt *ocar = o->getCarPtr(); + float side = car->_trkPos.toMiddle - ocar->_trkPos.toMiddle; + float w = car->_trkPos.seg->width/WIDTHDIV-BORDER_OVERTAKE_MARGIN; if (DebugMsg & debug_overtake) fprintf(stderr,"%s BEHIND %s (%d %d %d %d)\n",car->_name,ocar->_name,((o->getState() & OPP_LETPASS) && !o->isTeamMate()),(o->isTeamMate() && (car->_dammage - o->getDamage() > TEAM_DAMAGE_CHANGE_LEAD)),((o->getDistance() > -TEAM_REAR_DIST) && (o->getDistance() < -car->_dimension_x)),(car->race.laps == o->getCarPtr()->race.laps)); - if (side > 0.0f) { - if (myoffset < w) { - myoffset += (float) (OVERTAKE_OFFSET_INC*lftinc); - avoidmovt = 1; - } - } else { - if (myoffset > -w) { - myoffset -= (float) (OVERTAKE_OFFSET_INC*rgtinc); - avoidmovt = 1; - } - } + if (side > 0.0f) { + if (myoffset < w) { + myoffset += (float) (OVERTAKE_OFFSET_INC*lftinc); + avoidmovt = 1; + } + } else { + if (myoffset > -w) { + myoffset -= (float) (OVERTAKE_OFFSET_INC*rgtinc); + avoidmovt = 1; + } + } - avoidmode |= avoidback; + avoidmode |= avoidback; - if (ocar->_trkPos.toLeft > car->_trkPos.toLeft) - { - avoidrgtoffset = (float) MAX(avoidrgtoffset, ocar->_trkPos.toMiddle + (o->getWidth()+1.0f)); - avoidmode |= avoidright; - } - else - { - avoidlftoffset = (float) MIN(avoidlftoffset, ocar->_trkPos.toMiddle - (o->getWidth()+1.0f)); - avoidmode |= avoidleft; - } - - myoffset = (float) (MAX(minoffset, MIN(maxoffset, myoffset))); - } - } - } + if (ocar->_trkPos.toLeft > car->_trkPos.toLeft) + { + avoidrgtoffset = (float) MAX(avoidrgtoffset, ocar->_trkPos.toMiddle + (o->getWidth()+1.0f)); + avoidmode |= avoidright; + } + else + { + avoidlftoffset = (float) MIN(avoidlftoffset, ocar->_trkPos.toMiddle - (o->getWidth()+1.0f)); + avoidmode |= avoidleft; + } + + myoffset = (float) (MAX(minoffset, MIN(maxoffset, myoffset))); + } + } + } - if (mode == mode_avoiding && avoidmode == 0) - setMode(mode_correcting); - if (mode == mode_normal) - myoffset = (float) moffset; + if (mode == mode_avoiding && avoidmode == 0) + setMode(mode_correcting); + if (mode == mode_normal) + myoffset = (float) moffset; #if 1 - // no-one to avoid, work back towards raceline - if (mode == mode_correcting && (simtime > 15.0 || car->_speed_x > 20) && simtime > CorrectDelay) - { - double factor = 0.25;//(fabs(car->_trkPos.toMiddle) < car->_trkPos.seg->width/2 + 2.0 ? 0.25 : 1.0); - if (fabs(myoffset) > fabs(rldata->offset)) - { - //double inc = OVERTAKE_OFFSET_INC * MIN(lftinc, rgtinc) * factor; - if (myoffset < rldata->offset && myoffset < 2.0) - myoffset += (float) (MIN(rldata->offset-myoffset, OVERTAKE_OFFSET_INC * rgtinc/3 * factor)); - else if (myoffset > rldata->offset && myoffset > 2.0) - myoffset -= (float) (MIN(myoffset-rldata->offset, OVERTAKE_OFFSET_INC * lftinc/3 * factor)); - } + // no-one to avoid, work back towards raceline + if (mode == mode_correcting && (simtime > 15.0 || car->_speed_x > 20) && simtime > CorrectDelay) + { + double factor = 0.25;//(fabs(car->_trkPos.toMiddle) < car->_trkPos.seg->width/2 + 2.0 ? 0.25 : 1.0); + if (fabs(myoffset) > fabs(rldata->offset)) + { + //double inc = OVERTAKE_OFFSET_INC * MIN(lftinc, rgtinc) * factor; + if (myoffset < rldata->offset && myoffset < 2.0) + myoffset += (float) (MIN(rldata->offset-myoffset, OVERTAKE_OFFSET_INC * rgtinc/3 * factor)); + else if (myoffset > rldata->offset && myoffset > 2.0) + myoffset -= (float) (MIN(myoffset-rldata->offset, OVERTAKE_OFFSET_INC * lftinc/3 * factor)); + } - maxoffset = MIN(moffset+OVERTAKE_OFFSET_INC*lftinc/2, Width/2 - (car->_dimension_y+SideMargin)); - minoffset = MAX(moffset-OVERTAKE_OFFSET_INC*rgtinc/2, -(Width/2 - (car->_dimension_y+SideMargin))); - } + maxoffset = MIN(moffset+OVERTAKE_OFFSET_INC*lftinc/2, Width/2 - (car->_dimension_y+SideMargin)); + minoffset = MAX(moffset-OVERTAKE_OFFSET_INC*rgtinc/2, -(Width/2 - (car->_dimension_y+SideMargin))); + } #endif end_getoffset: - if (avoidmode) - setMode(mode_avoiding); + if (avoidmode) + setMode(mode_avoiding); - if (mode == mode_avoiding && !avoidmovt) - avoidtime = MIN(simtime, avoidtime+deltaTime*1.5); + if (mode == mode_avoiding && !avoidmovt) + avoidtime = MIN(simtime, avoidtime+deltaTime*1.5); -// minoffset = MAX(minoffset, MIN(1.5, rldata->offset)); -// maxoffset = MIN(maxoffset, MAX(track->width - 1.5, rldata->offset)); - { - double mo = myoffset; - myoffset = (float) (MAX(minoffset, MIN(maxoffset, myoffset))); - if (DebugMsg & debug_overtake) - if (mode != mode_normal) - { - fprintf(stderr,"mode=%d max=%.1f(%.1f) min=%.1f(%.1f) myoff=%.1f->%.1f->%.1f\n",mode,maxoffset,oldmax,minoffset,oldmin,car->_trkPos.toMiddle,mo,myoffset); - fflush(stderr); - } - } - return myoffset; +// minoffset = MAX(minoffset, MIN(1.5, rldata->offset)); +// maxoffset = MIN(maxoffset, MAX(track->width - 1.5, rldata->offset)); + { + double mo = myoffset; + myoffset = (float) (MAX(minoffset, MIN(maxoffset, myoffset))); + if (DebugMsg & debug_overtake) + if (mode != mode_normal) + { + fprintf(stderr,"mode=%d max=%.1f(%.1f) min=%.1f(%.1f) myoff=%.1f->%.1f->%.1f\n",mode,maxoffset,oldmax,minoffset,oldmin,car->_trkPos.toMiddle,mo,myoffset); + fflush(stderr); + } + } + return myoffset; } int Driver::checkSwitch( int side, Opponent *o, tCarElt *ocar ) { - double xdist = o->getDistance(); - double t_impact = MAX(0.0, MIN(10.0, o->getTimeImpact())); - if (car->_speed_x - ocar->_speed_x < MIN(5.0, xdist*3)) - t_impact *= (1.0 + (5.0 - (car->_speed_x - ocar->_speed_x))); - t_impact = MIN(3.0, MIN(t_impact, (5.0-(xdist-fabs(rldata->mInverse*1000)))/10)); + double xdist = o->getDistance(); + double t_impact = MAX(0.0, MIN(10.0, o->getTimeImpact())); + if (car->_speed_x - ocar->_speed_x < MIN(5.0, xdist*3)) + t_impact *= (1.0 + (5.0 - (car->_speed_x - ocar->_speed_x))); + t_impact = MIN(3.0, MIN(t_impact, (5.0-(xdist-fabs(rldata->mInverse*1000)))/10)); - double mcatchleft = MAX(1.0, MIN(track->width-1.0, car->_trkPos.toLeft - speedangle * (t_impact * 10))); - double ocatchleft = MAX(1.0, MIN(track->width-1.0, ocar->_trkPos.toLeft - o->getSpeedAngle() * (t_impact * 10))); - double ydist = mcatchleft-ocatchleft; - double sdiff = MAX(0.0, currentspeed - o->getSpeed()); - double radius = MIN(car->_dimension_y*3, fabs(nextCRinverse) * 200); - double speedchange = 0.0; + double mcatchleft = MAX(1.0, MIN(track->width-1.0, car->_trkPos.toLeft - speedangle * (t_impact * 10))); + double ocatchleft = MAX(1.0, MIN(track->width-1.0, ocar->_trkPos.toLeft - o->getSpeedAngle() * (t_impact * 10))); + double ydist = mcatchleft-ocatchleft; + double sdiff = MAX(0.0, currentspeed - o->getSpeed()); + double radius = MIN(car->_dimension_y*3, fabs(nextCRinverse) * 200); + double speedchange = 0.0; - if (prefer_side == side && rldata->speedchange < 0.0 && ocar->_pos > car->_pos) - speedchange = fabs(rldata->speedchange)*3; + if (prefer_side == side && rldata->speedchange < 0.0 && ocar->_pos > car->_pos) + speedchange = fabs(rldata->speedchange)*3; #if 0 - if (fabs(mcatchleft - ocatchleft) < car->_dimension_y + 1.5 + radius && - (fabs(mcatchleft - ocatchleft) < fabs(car->_trkPos.toLeft - ocar->_trkPos.toLeft) || - (side == TR_LFT && ocatchleft > car->_trkPos.seg->width - car->_dimension_y + 1.5 + radius) || - (side == TR_RGT && ocatchleft < car->_dimension_y + 1.5 + radius))) + if (fabs(mcatchleft - ocatchleft) < car->_dimension_y + 1.5 + radius && + (fabs(mcatchleft - ocatchleft) < fabs(car->_trkPos.toLeft - ocar->_trkPos.toLeft) || + (side == TR_LFT && ocatchleft > car->_trkPos.seg->width - car->_dimension_y + 1.5 + radius) || + (side == TR_RGT && ocatchleft < car->_dimension_y + 1.5 + radius))) #endif - { - double switchrad = 1.0 + (side == prefer_side ? radius * 4 : 0); + { + double switchrad = 1.0 + (side == prefer_side ? radius * 4 : 0); - switch (side) - { - case TR_RGT: + switch (side) + { + case TR_RGT: if (DebugMsg & debug_overtake) fprintf(stderr,"CHECKSWITCH: Rgt - ti=%.2f dm=%.1f o=%.2f->%.2f m=%.2f->%.2f\n",t_impact,deltamult,ocar->_trkPos.toLeft,ocatchleft,car->_trkPos.toLeft,mcatchleft); - if (nextCRinverse > 0.0) - radius = 0.0; - if ((side == prefer_side || - ocatchleft < (car->_dimension_y + 3.0 + radius + speedchange) * switchrad || - ocatchleft < (mcatchleft - 1.5) * switchrad) && - xdist > sdiff + ydist + MAX(0.0, angle*10) && - track->width - ocatchleft > (car->_dimension_y + 3.0 + radius + speedchange)) - { + if (nextCRinverse > 0.0) + radius = 0.0; + if ((side == prefer_side || + ocatchleft < (car->_dimension_y + 3.0 + radius + speedchange) * switchrad || + ocatchleft < (mcatchleft - 1.5) * switchrad) && + xdist > sdiff + ydist + MAX(0.0, angle*10) && + track->width - ocatchleft > (car->_dimension_y + 3.0 + radius + speedchange)) + { if (DebugMsg & debug_overtake) fprintf(stderr," Switch to his right (side=lft) - %d %d %d %d\n",(side==prefer_side),(ocatchleftsdiff+ydist+MAX(0.0, angle*10)),(track->width-ocatchleft>(car->_dimension_y+3+radius+speedchange))); - side = TR_LFT; - } - break; + side = TR_LFT; + } + break; - case TR_LFT: - default: + case TR_LFT: + default: if (DebugMsg & debug_overtake) fprintf(stderr,"CHECKSWITCH: Lft - ti=%.2f dm=%.1f o=%.2f->%.2f m=%.2f->%.2f\n",t_impact,deltamult,ocar->_trkPos.toLeft,ocatchleft,car->_trkPos.toLeft,mcatchleft); - if (nextCRinverse < 0.0) - radius = 0.0; - if ((side == prefer_side || - track->width-ocatchleft < (car->_dimension_y + 3.0 + radius + speedchange) * switchrad || - ocatchleft > (mcatchleft + 1.5) * switchrad) && - xdist > sdiff + (-ydist) + MAX(0.0, -angle*10) && - ocatchleft > (car->_dimension_y + 3.0 + radius + speedchange)) - { - side = TR_RGT; - } - break; - } - } + if (nextCRinverse < 0.0) + radius = 0.0; + if ((side == prefer_side || + track->width-ocatchleft < (car->_dimension_y + 3.0 + radius + speedchange) * switchrad || + ocatchleft > (mcatchleft + 1.5) * switchrad) && + xdist > sdiff + (-ydist) + MAX(0.0, -angle*10) && + ocatchleft > (car->_dimension_y + 3.0 + radius + speedchange)) + { + side = TR_RGT; + } + break; + } + } - return side; + return side; } // Update my private data every timestep. void Driver::update(tSituation *s) { - // Update global car data (shared by all instances) just once per timestep. - if (simtime != s->currentTime) { - simtime = s->currentTime; - cardata->update(); - mycardata->updateWalls(); - } - else - { - // always update my car - mycardata->update(); - mycardata->updateWalls(); + // Update global car data (shared by all instances) just once per timestep. + if (simtime != s->currentTime) { + simtime = s->currentTime; + cardata->update(); + mycardata->updateWalls(); + } + else + { + // always update my car + mycardata->update(); + mycardata->updateWalls(); - int nCars = cardata->getNCars(); + int nCars = cardata->getNCars(); - for (int i = 0; i < nCars; i++) - { - // update cars that are close to ours - SingleCardata *cdata = cardata->getCarData(i); - double mdist = car->_distFromStartLine; - double odist = (double) cdata->getDistFromStart(); + for (int i = 0; i < nCars; i++) + { + // update cars that are close to ours + SingleCardata *cdata = cardata->getCarData(i); + double mdist = car->_distFromStartLine; + double odist = (double) cdata->getDistFromStart(); - if (odist > track->length - 30 && mdist < 30) - mdist += track->length; - else if (mdist > track->length - 30 && odist < 30) - odist += track->length; + if (odist > track->length - 30 && mdist < 30) + mdist += track->length; + else if (mdist > track->length - 30 && odist < 30) + odist += track->length; - double dist = fabs(mdist - odist); - if (dist < 60.0) - cdata->update(); - } - } + double dist = fabs(mdist - odist); + if (dist < 60.0) + cdata->update(); + } + } - evalTrueSpeed(); + evalTrueSpeed(); - prefer_side = raceline->findNextCorner( &nextCRinverse ); + prefer_side = raceline->findNextCorner( &nextCRinverse ); - // Update the local data rest. - avgaccel_x += (car->_accel_x - avgaccel_x)/2; - prevspeedangle = speedangle; - speedangle = (float) -(mycardata->getTrackangle() - atan2(car->_speed_Y, car->_speed_X)); - NORM_PI_PI(speedangle); - mass = CARMASS + car->_fuel; - currentspeedsqr = car->_speed_x*car->_speed_x; - currentspeed = getSpeed(); - opponents->update(s, this, DebugMsg); - strategy->update(car, s); + // Update the local data rest. + avgaccel_x += (car->_accel_x - avgaccel_x)/2; + prevspeedangle = speedangle; + speedangle = (float) -(mycardata->getTrackangle() - atan2(car->_speed_Y, car->_speed_X)); + NORM_PI_PI(speedangle); + mass = CARMASS + car->_fuel; + currentspeedsqr = car->_speed_x*car->_speed_x; + currentspeed = getSpeed(); + opponents->update(s, this, DebugMsg); + strategy->update(car, s); - if (car->_state <= RM_CAR_STATE_PIT && !NoPit) - { + if (car->_state <= RM_CAR_STATE_PIT && !NoPit) + { #ifdef SPEED_DREAMS - float DLong, DLat; // Dist to Pit - RtDistToPit(car,track,&DLong,&DLat); + float DLong, DLat; // Dist to Pit + RtDistToPit(car,track,&DLong,&DLat); - if (DLong > 500) - pitStopChecked = false; + if (DLong > 500) + pitStopChecked = false; - if (!pit->getPitstop() - && (!pitStopChecked) - && (DLong < 500) - && (car->_distFromStartLine < pit->getNPitEntry() || car->_distFromStartLine > pit->getNPitEnd())) + if (!pit->getPitstop() + && (!pitStopChecked) + && (DLong < 500) + && (car->_distFromStartLine < pit->getNPitEntry() || car->_distFromStartLine > pit->getNPitEnd())) #else - if (!pit->getPitstop() && (car->_distFromStartLine < pit->getNPitEntry() || car->_distFromStartLine > pit->getNPitEnd())) + if (!pit->getPitstop() && (car->_distFromStartLine < pit->getNPitEntry() || car->_distFromStartLine > pit->getNPitEnd())) #endif - { - bool pitstop = strategy->needPitstop(car, s, opponents); - if (pitstop) - { - pit->setPitstop(pitstop); - pit->needPitstop(pitstop); - } - } + { + bool pitstop = strategy->needPitstop(car, s, opponents); + if (pitstop) + { + pit->setPitstop(pitstop); + pit->needPitstop(pitstop); + } + } - if (pit->getPitstop() && car->_pit) - { - pitpos = PIT_MID; + if (pit->getPitstop() && car->_pit) + { + pitpos = PIT_MID; - for (int i=0; igetNOpponents(); i++) - { - //int idx = opponent[i].getIndex(); - if (opponent[i].getTeam() != TEAM_FRIEND) continue; - if (opponent[i].getCarPtr() == car) continue; - if (opponent[i].getCarPtr()->_state > RM_CAR_STATE_PIT) - continue; + for (int i=0; igetNOpponents(); i++) + { + //int idx = opponent[i].getIndex(); + if (opponent[i].getTeam() != TEAM_FRIEND) continue; + if (opponent[i].getCarPtr() == car) continue; + if (opponent[i].getCarPtr()->_state > RM_CAR_STATE_PIT) + continue; - int opitpos = (int) opponent[i].getCarPtr()->_lightCmd; + int opitpos = (int) opponent[i].getCarPtr()->_lightCmd; - if (opitpos != PIT_NONE && car->_fuel > fuelperlap*1.5 && car->_trkPos.toLeft >= 0.0 && car->_trkPos.toLeft <= track->width) - { - // pit occupied & we've got enough fuel to go around again - pit->setPitstop( 0 ); - pitpos = PIT_NONE; - break; - } + if (opitpos != PIT_NONE && car->_fuel > fuelperlap*1.5 && car->_trkPos.toLeft >= 0.0 && car->_trkPos.toLeft <= track->width) + { + // pit occupied & we've got enough fuel to go around again + pit->setPitstop( 0 ); + pitpos = PIT_NONE; + break; + } - if (opponent[i].getCarPtr()->_pit->pos.seg == car->_pit->pos.seg) - { - // sharing a pit - if (opitpos == PIT_FRONT) - { - double pitloc = pit->getNPitLoc( PIT_MID ); - double myfrompit = pitloc - car->_distFromStartLine; - double opfrompit = pitloc - opponent[i].getCarPtr()->_distFromStartLine; - if (myfrompit < 0.0) myfrompit += track->length; - if (opfrompit < 0.0) opfrompit += track->length; + if (opponent[i].getCarPtr()->_pit->pos.seg == car->_pit->pos.seg) + { + // sharing a pit + if (opitpos == PIT_FRONT) + { + double pitloc = pit->getNPitLoc( PIT_MID ); + double myfrompit = pitloc - car->_distFromStartLine; + double opfrompit = pitloc - opponent[i].getCarPtr()->_distFromStartLine; + if (myfrompit < 0.0) myfrompit += track->length; + if (opfrompit < 0.0) opfrompit += track->length; - // work out who's closest to the pit & therefore should go in front - if (opfrompit > myfrompit) - { - pitpos = PIT_FRONT; - } - else - { - pitpos = PIT_BACK; // go in behind other car - } - } - else - { - pitpos = PIT_FRONT; // stop at end of pit space to leave room - } - } + // work out who's closest to the pit & therefore should go in front + if (opfrompit > myfrompit) + { + pitpos = PIT_FRONT; + } + else + { + pitpos = PIT_BACK; // go in behind other car + } + } + else + { + pitpos = PIT_FRONT; // stop at end of pit space to leave room + } + } - break; - } - } - else if (!pit->getInPit()) - pitpos = PIT_NONE; - } - else - { - pitpos = PIT_NONE; - } + break; + } + } + else if (!pit->getInPit()) + pitpos = PIT_NONE; + } + else + { + pitpos = PIT_NONE; + } #ifdef SPEED_DREAMS - if (pitpos == PIT_NONE) - RtTeamReleasePit(teamIndex); + if (pitpos == PIT_NONE) + RtTeamReleasePit(teamIndex); #else - car->_lightCmd = (char) pitpos; + car->_lightCmd = (char) pitpos; #endif - pit->update(); - alone = isAlone(); - simtime = s->currentTime; + pit->update(); + alone = isAlone(); + simtime = s->currentTime; - float trackangle = RtTrackSideTgAngleL(&(car->_trkPos)); - angle = trackangle - car->_yaw; - NORM_PI_PI(angle); - angle = -angle; + float trackangle = RtTrackSideTgAngleL(&(car->_trkPos)); + angle = trackangle - car->_yaw; + NORM_PI_PI(angle); + angle = -angle; } int Driver::isAlone() { - int i; + int i; - for (i = 0; i < opponents->getNOpponents(); i++) { + for (i = 0; i < opponents->getNOpponents(); i++) { #if 0 - if (opponent[i].getTeam() == TEAM_FRIEND) - continue; + if (opponent[i].getTeam() == TEAM_FRIEND) + continue; #endif - // not a friend - if we're avoiding then we're obviously not alone - if (mode == mode_avoiding) - return 0; + // not a friend - if we're avoiding then we're obviously not alone + if (mode == mode_avoiding) + return 0; - if ((opponent[i].getState() & (OPP_COLL | OPP_LETPASS)) || - ((opponent[i].getState() & (OPP_FRONT)) && opponent[i].getDistance() < MAX(50.0, car->_speed_x*1.5)) || - (fabs(opponent[i].getDistance()) < 50.0)) - { - return 0; // Not alone. - } - } - return 1; // Alone. + if ((opponent[i].getState() & (OPP_COLL | OPP_LETPASS)) || + ((opponent[i].getState() & (OPP_FRONT)) && opponent[i].getDistance() < MAX(50.0, car->_speed_x*1.5)) || + (fabs(opponent[i].getDistance()) < 50.0)) + { + return 0; // Not alone. + } + } + return 1; // Alone. } float Driver::stuckSteering( float steercmd ) { - if (stucksteer > 0.0f) - steercmd = (fabs(steercmd) + stucksteer) / 2; - else - steercmd = -(fabs(steercmd) + fabs(stucksteer)) / 2; - return steercmd; + if (stucksteer > 0.0f) + steercmd = (fabs(steercmd) + stucksteer) / 2; + else + steercmd = -(fabs(steercmd) + fabs(stucksteer)) / 2; + return steercmd; } float Driver::GetSafeStuckAccel() { - // see if wheels are on a bumpy surface - tTrackSeg *rgt_seg = car->_trkPos.seg; - tTrackSeg *lft_seg = car->_trkPos.seg; - double max_rough = 0.0f; - float accel = MAX(0.5f, 1.0f - fabs(angle)/3); - int rgt_off = 0, lft_off = 0; + // see if wheels are on a bumpy surface + tTrackSeg *rgt_seg = car->_trkPos.seg; + tTrackSeg *lft_seg = car->_trkPos.seg; + double max_rough = 0.0f; + float accel = MAX(0.5f, 1.0f - fabs(angle)/3); + int rgt_off = 0, lft_off = 0; - if ((car->priv.wheel[FRNT_RGT].seg != car->_trkPos.seg && car->priv.wheel[FRNT_RGT].seg->style == TR_PLAN && - car->priv.wheel[REAR_RGT].seg != car->_trkPos.seg && car->priv.wheel[FRNT_RGT].seg->style == TR_PLAN)) - { - rgt_seg = car->priv.wheel[REAR_RGT].seg; - if (rgt_seg->style == TR_PLAN && - (rgt_seg->surface->kFriction < car->_trkPos.seg->surface->kFriction*0.7 || - rgt_seg->surface->kRoughness > MAX(0.03, car->_trkPos.seg->surface->kRoughness*1.3) || - rgt_seg->surface->kRollRes > MAX(0.005, car->_trkPos.seg->surface->kRollRes*1.5))) - { - rgt_off = 1; - if (car->_trkPos.toRight < car->_dimension_y - 1.5) - rgt_off = 2; - max_rough = MAX(max_rough, rgt_seg->surface->kRoughness); - } - } + if ((car->priv.wheel[FRNT_RGT].seg != car->_trkPos.seg && car->priv.wheel[FRNT_RGT].seg->style == TR_PLAN && + car->priv.wheel[REAR_RGT].seg != car->_trkPos.seg && car->priv.wheel[FRNT_RGT].seg->style == TR_PLAN)) + { + rgt_seg = car->priv.wheel[REAR_RGT].seg; + if (rgt_seg->style == TR_PLAN && + (rgt_seg->surface->kFriction < car->_trkPos.seg->surface->kFriction*0.7 || + rgt_seg->surface->kRoughness > MAX(0.03, car->_trkPos.seg->surface->kRoughness*1.3) || + rgt_seg->surface->kRollRes > MAX(0.005, car->_trkPos.seg->surface->kRollRes*1.5))) + { + rgt_off = 1; + if (car->_trkPos.toRight < car->_dimension_y - 1.5) + rgt_off = 2; + max_rough = MAX(max_rough, rgt_seg->surface->kRoughness); + } + } - if ((car->priv.wheel[FRNT_LFT].seg != car->_trkPos.seg && car->priv.wheel[FRNT_LFT].seg->style == TR_PLAN && - car->priv.wheel[REAR_LFT].seg != car->_trkPos.seg && car->priv.wheel[REAR_LFT].seg->style == TR_PLAN)) - { - lft_seg = car->priv.wheel[REAR_LFT].seg; - if (lft_seg->style == TR_PLAN && - (lft_seg->surface->kFriction < car->_trkPos.seg->surface->kFriction*0.7 || - lft_seg->surface->kRoughness > MAX(0.03, car->_trkPos.seg->surface->kRoughness*1.3) || - lft_seg->surface->kRollRes > MAX(0.005, car->_trkPos.seg->surface->kRollRes*1.5))) - { - lft_off = 1; - if (car->_trkPos.toRight < car->_dimension_y - 1.5) - lft_off = 2; - max_rough = MAX(max_rough, lft_seg->surface->kRoughness); - } - } + if ((car->priv.wheel[FRNT_LFT].seg != car->_trkPos.seg && car->priv.wheel[FRNT_LFT].seg->style == TR_PLAN && + car->priv.wheel[REAR_LFT].seg != car->_trkPos.seg && car->priv.wheel[REAR_LFT].seg->style == TR_PLAN)) + { + lft_seg = car->priv.wheel[REAR_LFT].seg; + if (lft_seg->style == TR_PLAN && + (lft_seg->surface->kFriction < car->_trkPos.seg->surface->kFriction*0.7 || + lft_seg->surface->kRoughness > MAX(0.03, car->_trkPos.seg->surface->kRoughness*1.3) || + lft_seg->surface->kRollRes > MAX(0.005, car->_trkPos.seg->surface->kRollRes*1.5))) + { + lft_off = 1; + if (car->_trkPos.toRight < car->_dimension_y - 1.5) + lft_off = 2; + max_rough = MAX(max_rough, lft_seg->surface->kRoughness); + } + } - if (lft_off + rgt_off > 0 && (car->_speed_x + fabs(car->_yaw_rate*5) > 3.0)) - { - // at least one wheel on the bumpy stuff and we're moving - accel = MAX(0.2f, MIN(accel, (0.8f - (1.0+fabs(car->_yaw_rate)) * (max_rough*20)))); - } - else if (car->_speed_x > 5.0 && fabs(car->_steerCmd) > fabs(car->_yaw_rate)) - { - // understeering, reduce accel - accel = MAX(0.3f, accel - (fabs(car->_steerCmd) - fabs(car->_yaw_rate))); - } + if (lft_off + rgt_off > 0 && (car->_speed_x + fabs(car->_yaw_rate*5) > 3.0)) + { + // at least one wheel on the bumpy stuff and we're moving + accel = MAX(0.2f, MIN(accel, (0.8f - (1.0+fabs(car->_yaw_rate)) * (max_rough*20)))); + } + else if (car->_speed_x > 5.0 && fabs(car->_steerCmd) > fabs(car->_yaw_rate)) + { + // understeering, reduce accel + accel = MAX(0.3f, accel - (fabs(car->_steerCmd) - fabs(car->_yaw_rate))); + } - return accel; + return accel; } // Check if I'm stuck. bool Driver::isStuck() { - double toSide = MIN(car->_trkPos.toLeft, car->_trkPos.toRight); - double stangle = angle; - double fangle = fabs(angle); + double toSide = MIN(car->_trkPos.toLeft, car->_trkPos.toRight); + double stangle = angle; + double fangle = fabs(angle); - vec2f target = getTargetPoint(false, 0.0); - double targetAngle = atan2(target.y - car->_pos_Y, target.x - car->_pos_X); - double stuck_steer = calcSteer( targetAngle, 0 ); + vec2f target = getTargetPoint(false, 0.0); + double targetAngle = atan2(target.y - car->_pos_Y, target.x - car->_pos_X); + double stuck_steer = calcSteer( targetAngle, 0 ); - if (stangle < 1.0 && stangle > -0.3 && car->_trkPos.toLeft < 1.0) - stangle += MIN(0.5, car->_trkPos.toLeft / 5); - else if (stangle > -1.0 && stangle < 0.3 && car->_trkPos.toRight < 1.0) - stangle -= MIN(0.5, car->_trkPos.toRight / 5); + if (stangle < 1.0 && stangle > -0.3 && car->_trkPos.toLeft < 1.0) + stangle += MIN(0.5, car->_trkPos.toLeft / 5); + else if (stangle > -1.0 && stangle < 0.3 && car->_trkPos.toRight < 1.0) + stangle -= MIN(0.5, car->_trkPos.toRight / 5); - bool returning = ((car->_trkPos.toMiddle > 0.0 && speedangle < -0.2) || - (car->_trkPos.toMiddle < 0.0 && speedangle > 0.2)); - bool departing = ((car->_trkPos.toMiddle > 0.0 && speedangle > 0.2) || - (car->_trkPos.toMiddle < 0.0 && speedangle < -0.2)); - double toWall = toSide; + bool returning = ((car->_trkPos.toMiddle > 0.0 && speedangle < -0.2) || + (car->_trkPos.toMiddle < 0.0 && speedangle > 0.2)); + bool departing = ((car->_trkPos.toMiddle > 0.0 && speedangle > 0.2) || + (car->_trkPos.toMiddle < 0.0 && speedangle < -0.2)); + double toWall = toSide; - // how far to the nearest wall? - if (car->_trkPos.toMiddle < 0.0 && car->_trkPos.seg->side[TR_SIDE_RGT] != NULL) - { - tTrackSeg *seg = car->_trkPos.seg->side[TR_SIDE_RGT]; - if (seg->style == TR_PLAN) - { - toWall += seg->width; - if (seg->side[TR_SIDE_RGT]) - { - seg = seg->side[TR_SIDE_RGT]; - if (seg->style == TR_PLAN) - toWall += seg->width; - } - } - } - else if (car->_trkPos.toMiddle > 0.0 && car->_trkPos.seg->side[TR_SIDE_LFT] != NULL) - { - tTrackSeg *seg = car->_trkPos.seg->side[TR_SIDE_LFT]; - if (seg->style == TR_PLAN) - { - toWall += seg->width; - if (seg->side[TR_SIDE_LFT]) - { - seg = seg->side[TR_SIDE_LFT]; - if (seg->style == TR_PLAN) - toWall += seg->width; - } - } - } + // how far to the nearest wall? + if (car->_trkPos.toMiddle < 0.0 && car->_trkPos.seg->side[TR_SIDE_RGT] != NULL) + { + tTrackSeg *seg = car->_trkPos.seg->side[TR_SIDE_RGT]; + if (seg->style == TR_PLAN) + { + toWall += seg->width; + if (seg->side[TR_SIDE_RGT]) + { + seg = seg->side[TR_SIDE_RGT]; + if (seg->style == TR_PLAN) + toWall += seg->width; + } + } + } + else if (car->_trkPos.toMiddle > 0.0 && car->_trkPos.seg->side[TR_SIDE_LFT] != NULL) + { + tTrackSeg *seg = car->_trkPos.seg->side[TR_SIDE_LFT]; + if (seg->style == TR_PLAN) + { + toWall += seg->width; + if (seg->side[TR_SIDE_LFT]) + { + seg = seg->side[TR_SIDE_LFT]; + if (seg->style == TR_PLAN) + toWall += seg->width; + } + } + } - // update stopped timer - if (fabs(car->_speed_x) > 5.0) - stopped_timer = simtime; + // update stopped timer + if (fabs(car->_speed_x) > 5.0) + stopped_timer = simtime; - if (pit->getInPit()) - { - stuck = 0; - stuck_timer = simtime; - stucksteer = -100.0f; - } + if (pit->getInPit()) + { + stuck = 0; + stuck_timer = simtime; + stucksteer = -100.0f; + } - if (stuck) - { - // stuck - ok to be "unstuck"? - if (fangle < 0.7 && - toSide > 2.0 && - simtime - stuck_timer > 2.0) - { - stuck = 0; - stuck_timer = simtime; - stucksteer = -100.0f; - return false; - } + if (stuck) + { + // stuck - ok to be "unstuck"? + if (fangle < 0.7 && + toSide > 2.0 && + simtime - stuck_timer > 2.0) + { + stuck = 0; + stuck_timer = simtime; + stucksteer = -100.0f; + return false; + } - setMode( mode_correcting ); + setMode( mode_correcting ); - // still stuck - see if we should change gear. - if (stuck == STUCK_REVERSE) - { - // should we give up and go forwards? - if ((simtime - stuck_timer > (1.0 + fangle) && (fabs(car->_speed_x) < 2.0 || !returning)) || - (car->_trkPos.toMiddle > 0.0 && angle < 0.4 && angle > -2.4) || - (car->_trkPos.toMiddle < 0.0 && angle > -0.4 && angle < 2.4)) - { - stuck = STUCK_FORWARD; - stuck_timer = simtime; - } - } - else if (stuck == STUCK_FORWARD) - { - // should we try reverse? - if ((simtime - stuck_timer > MAX(4.0, car->_speed_x/2) && - (fabs(car->_speed_x) < 4.0 || (!returning && fabs(car->_yaw_rate) < 0.4))) || - (car->_trkPos.toRight < 0.0 + fangle && angle < -0.6 && angle > -2.4) || - (car->_trkPos.toLeft < 0.0 + fangle && angle > 0.6 && angle < 2.4)) - { - stuck = STUCK_REVERSE; - stuck_timer = simtime; - } - } - - last_stuck_time = simtime; - } - else if (getSpeed() < 10.0 || toSide < 2.0) - { - // not stuck - but are we? - if (simtime - last_stuck_time > 3.0 && // only get stuck if 3 seconds since we were last stuck - (fangle > MAX(1.0, 1.0 + toSide/5) || - simtime - stopped_timer > 4.0 || - (car->_trkPos.toLeft < 1.0 && car->_trkPos.toMiddle > rldata->offset + 2 && angle > 0.7) || - (car->_trkPos.toRight < 1.0 && car->_trkPos.toMiddle < rldata->offset - 2 && angle < -0.7))) - { - // yes, we're stuck - stuck_timer = last_stuck_time = simtime; - setMode( mode_correcting ); + // still stuck - see if we should change gear. + if (stuck == STUCK_REVERSE) + { + // should we give up and go forwards? + if ((simtime - stuck_timer > (1.0 + fangle) && (fabs(car->_speed_x) < 2.0 || !returning)) || + (car->_trkPos.toMiddle > 0.0 && angle < 0.4 && angle > -2.4) || + (car->_trkPos.toMiddle < 0.0 && angle > -0.4 && angle < 2.4)) + { + stuck = STUCK_FORWARD; + stuck_timer = simtime; + } + } + else if (stuck == STUCK_FORWARD) + { + // should we try reverse? + if ((simtime - stuck_timer > MAX(4.0, car->_speed_x/2) && + (fabs(car->_speed_x) < 4.0 || (!returning && fabs(car->_yaw_rate) < 0.4))) || + (car->_trkPos.toRight < 0.0 + fangle && angle < -0.6 && angle > -2.4) || + (car->_trkPos.toLeft < 0.0 + fangle && angle > 0.6 && angle < 2.4)) + { + stuck = STUCK_REVERSE; + stuck_timer = simtime; + } + } + + last_stuck_time = simtime; + } + else if (getSpeed() < 10.0 || toSide < 2.0) + { + // not stuck - but are we? + if (simtime - last_stuck_time > 3.0 && // only get stuck if 3 seconds since we were last stuck + (fangle > MAX(1.0, 1.0 + toSide/5) || + simtime - stopped_timer > 4.0 || + (car->_trkPos.toLeft < 1.0 && car->_trkPos.toMiddle > rldata->offset + 2 && angle > 0.7) || + (car->_trkPos.toRight < 1.0 && car->_trkPos.toMiddle < rldata->offset - 2 && angle < -0.7))) + { + // yes, we're stuck + stuck_timer = last_stuck_time = simtime; + setMode( mode_correcting ); - stuck = STUCK_REVERSE; + stuck = STUCK_REVERSE; - if ((fangle < 2.0 && currentspeed > 10.0) || - (angle < 0.0 && car->_trkPos.toMiddle > 0.0) || - (angle > 0.0 && car->_trkPos.toMiddle < 0.0) || - (fangle < 1.8 && toWall > 4.0 + fangle*3) || - (fabs(angle - speedangle) * 1.2 && car->_speed_x > 2.0)) - { - stuck = STUCK_FORWARD; - } - } - else - { - // free to keep driving - stucksteer = -100.0f; - stuck = 0; - return false; - } - } - else - { - // free to keep driving - stucksteer = -100.0f; - stuck = 0; - return false; - } + if ((fangle < 2.0 && currentspeed > 10.0) || + (angle < 0.0 && car->_trkPos.toMiddle > 0.0) || + (angle > 0.0 && car->_trkPos.toMiddle < 0.0) || + (fangle < 1.8 && toWall > 4.0 + fangle*3) || + (fabs(angle - speedangle) * 1.2 && car->_speed_x > 2.0)) + { + stuck = STUCK_FORWARD; + } + } + else + { + // free to keep driving + stucksteer = -100.0f; + stuck = 0; + return false; + } + } + else + { + // free to keep driving + stucksteer = -100.0f; + stuck = 0; + return false; + } - // seeing we're stuck, determine steering, braking, accel - if (fangle > 1.7) - { - stuck_steer = -stuck_steer; - if (stuck_steer > 0.0) - stuck_steer = 1.0; - else - stuck_steer = -1.0; - } - else if (car->_speed_x > 5.0 && fangle < 0.6 && stuck == STUCK_FORWARD && - ((car->_trkPos.toLeft < 2.0 && racesteer < stuck_steer) || - (car->_trkPos.toRight < 2.0 && racesteer > stuck_steer))) - { - stuck_steer += MAX(-0.15, MIN(0.15, racesteer - stuck_steer)); - } + // seeing we're stuck, determine steering, braking, accel + if (fangle > 1.7) + { + stuck_steer = -stuck_steer; + if (stuck_steer > 0.0) + stuck_steer = 1.0; + else + stuck_steer = -1.0; + } + else if (car->_speed_x > 5.0 && fangle < 0.6 && stuck == STUCK_FORWARD && + ((car->_trkPos.toLeft < 2.0 && racesteer < stuck_steer) || + (car->_trkPos.toRight < 2.0 && racesteer > stuck_steer))) + { + stuck_steer += MAX(-0.15, MIN(0.15, racesteer - stuck_steer)); + } - if (stucksteer < -99.0f) - { - stucksteer = stuck_steer; - } - else - { - if (stuck == STUCK_FORWARD && - ((stucksteer > 0.0 && stuck_steer < 0.0) || (stucksteer < 0.0 && stuck_steer > 0.0)) && - fabs(angle) < 1.6) - stucksteer = stuck_steer; - else if (stucksteer > 0.0) - stucksteer = fabs(stuck_steer); - else - stucksteer = -fabs(stuck_steer); - } + if (stucksteer < -99.0f) + { + stucksteer = stuck_steer; + } + else + { + if (stuck == STUCK_FORWARD && + ((stucksteer > 0.0 && stuck_steer < 0.0) || (stucksteer < 0.0 && stuck_steer > 0.0)) && + fabs(angle) < 1.6) + stucksteer = stuck_steer; + else if (stucksteer > 0.0) + stucksteer = fabs(stuck_steer); + else + stucksteer = -fabs(stuck_steer); + } - if (stuck == STUCK_REVERSE) - { - car->_steerCmd = -stucksteer*1.4; + if (stuck == STUCK_REVERSE) + { + car->_steerCmd = -stucksteer*1.4; - if (car->_speed_x > 3.0 || (toSide < 0.0 && departing)) - { - car->_accelCmd = 0.0f; - car->_brakeCmd = 0.4f; - car->_clutchCmd = 1.0f; - } - else - { - car->_accelCmd = MAX(0.3f, 0.7f + MIN(0.0f, car->_speed_x/40)); - car->_brakeCmd = 0.0f; - car->_clutchCmd = 0.0f; - } + if (car->_speed_x > 3.0 || (toSide < 0.0 && departing)) + { + car->_accelCmd = 0.0f; + car->_brakeCmd = 0.4f; + car->_clutchCmd = 1.0f; + } + else + { + car->_accelCmd = MAX(0.3f, 0.7f + MIN(0.0f, car->_speed_x/40)); + car->_brakeCmd = 0.0f; + car->_clutchCmd = 0.0f; + } - car->_gearCmd = -1; - } - else - { - car->_steerCmd = stucksteer; + car->_gearCmd = -1; + } + else + { + car->_steerCmd = stucksteer; - if (car->_speed_x < -3.0) - { - car->_accelCmd = 0.0f; - car->_brakeCmd = 0.4f; - car->_clutchCmd = 1.0f; - } - else - { - car->_brakeCmd = 0.0f; - car->_accelCmd = GetSafeStuckAccel(); - car->_accelCmd = MAX(car->_accelCmd/3, car->_accelCmd - fabs(stucksteer/2)); - if (car->_speed_x < 2.0 || fabs(car->_yaw_rate) < 0.5) - car->_accelCmd = MAX(0.3, car->_accelCmd); - car->_clutchCmd = 0.0f; - } + if (car->_speed_x < -3.0) + { + car->_accelCmd = 0.0f; + car->_brakeCmd = 0.4f; + car->_clutchCmd = 1.0f; + } + else + { + car->_brakeCmd = 0.0f; + car->_accelCmd = GetSafeStuckAccel(); + car->_accelCmd = MAX(car->_accelCmd/3, car->_accelCmd - fabs(stucksteer/2)); + if (car->_speed_x < 2.0 || fabs(car->_yaw_rate) < 0.5) + car->_accelCmd = MAX(0.3, car->_accelCmd); + car->_clutchCmd = 0.0f; + } - car->_gearCmd = 1; - } + car->_gearCmd = 1; + } - return true; + return true; } @@ -3458,390 +3454,390 @@ void Driver::initWheelPos() void Driver::initCa() { - char const *WheelSect[4] = {SECT_FRNTRGTWHEEL, SECT_FRNTLFTWHEEL, SECT_REARRGTWHEEL, SECT_REARLFTWHEEL}; - float rearwingarea = GfParmGetNum(car->_carHandle, SECT_REARWING, PRM_WINGAREA, (char*) NULL, 0.0f); - float rearwingangle = GfParmGetNum(car->_carHandle, SECT_REARWING, PRM_WINGANGLE, (char*) NULL, 0.0f); - float wingca = 1.23f*rearwingarea*sin(rearwingangle); + char const *WheelSect[4] = {SECT_FRNTRGTWHEEL, SECT_FRNTLFTWHEEL, SECT_REARRGTWHEEL, SECT_REARLFTWHEEL}; + float rearwingarea = GfParmGetNum(car->_carHandle, SECT_REARWING, PRM_WINGAREA, (char*) NULL, 0.0f); + float rearwingangle = GfParmGetNum(car->_carHandle, SECT_REARWING, PRM_WINGANGLE, (char*) NULL, 0.0f); + float wingca = 1.23f*rearwingarea*sin(rearwingangle); - float cl = GfParmGetNum(car->_carHandle, SECT_AERODYNAMICS, PRM_FCL, (char*) NULL, 0.0f) + - GfParmGetNum(car->_carHandle, SECT_AERODYNAMICS, PRM_RCL, (char*) NULL, 0.0f); - float h = 0.0f; - int i; - for (i = 0; i < 4; i++) - h += GfParmGetNum(car->_carHandle, WheelSect[i], PRM_RIDEHEIGHT, (char*) NULL, 0.20f); - h*= 1.5f; h = h*h; h = h*h; h = 2.0f * exp(-3.0f*h); - CA = h*cl + 4.0f*wingca; + float cl = GfParmGetNum(car->_carHandle, SECT_AERODYNAMICS, PRM_FCL, (char*) NULL, 0.0f) + + GfParmGetNum(car->_carHandle, SECT_AERODYNAMICS, PRM_RCL, (char*) NULL, 0.0f); + float h = 0.0f; + int i; + for (i = 0; i < 4; i++) + h += GfParmGetNum(car->_carHandle, WheelSect[i], PRM_RIDEHEIGHT, (char*) NULL, 0.20f); + h*= 1.5f; h = h*h; h = h*h; h = 2.0f * exp(-3.0f*h); + CA = h*cl + 4.0f*wingca; } // Compute aerodynamic drag coefficient CW. void Driver::initCw() { - float cx = GfParmGetNum(car->_carHandle, SECT_AERODYNAMICS, PRM_CX, (char*) NULL, 0.0f); - float frontarea = GfParmGetNum(car->_carHandle, SECT_AERODYNAMICS, PRM_FRNTAREA, (char*) NULL, 0.0f); - CW = 0.645f*cx*frontarea; + float cx = GfParmGetNum(car->_carHandle, SECT_AERODYNAMICS, PRM_CX, (char*) NULL, 0.0f); + float frontarea = GfParmGetNum(car->_carHandle, SECT_AERODYNAMICS, PRM_FRNTAREA, (char*) NULL, 0.0f); + CW = 0.645f*cx*frontarea; } // Init the friction coefficient of the the tires. void Driver::initTireMu() { - char const *WheelSect[4] = {SECT_FRNTRGTWHEEL, SECT_FRNTLFTWHEEL, SECT_REARRGTWHEEL, SECT_REARLFTWHEEL}; - float tm = FLT_MAX; - int i; + char const *WheelSect[4] = {SECT_FRNTRGTWHEEL, SECT_FRNTLFTWHEEL, SECT_REARRGTWHEEL, SECT_REARLFTWHEEL}; + float tm = FLT_MAX; + int i; - for (i = 0; i < 4; i++) { - tm = MIN(tm, GfParmGetNum(car->_carHandle, WheelSect[i], PRM_MU, (char*) NULL, 1.0f)); - } - TIREMU = tm; + for (i = 0; i < 4; i++) { + tm = MIN(tm, GfParmGetNum(car->_carHandle, WheelSect[i], PRM_MU, (char*) NULL, 1.0f)); + } + TIREMU = tm; } void Driver::GetSteerPoint( double lookahead, vec2f *rt, double offset, double time ) { - if (offset < -90.0 && mode != mode_normal) - offset = myoffset; + if (offset < -90.0 && mode != mode_normal) + offset = myoffset; - raceline->GetSteerPoint( lookahead, rt, offset, time ); + raceline->GetSteerPoint( lookahead, rt, offset, time ); } // Reduces the brake value such that it fits the speed (more downforce -> more braking). float Driver::filterBrakeSpeed(float brake) { - float weight = (CARMASS + car->_fuel)*G; - float maxForce = weight + CA*MAX_SPEED*MAX_SPEED; - float force = weight + CA*currentspeedsqr; - return brake*force/maxForce; + float weight = (CARMASS + car->_fuel)*G; + float maxForce = weight + CA*MAX_SPEED*MAX_SPEED; + float force = weight + CA*currentspeedsqr; + return brake*force/maxForce; } // Brake filter for pit stop. float Driver::filterBPit(float brake) { - if (pit->getPitstop() && !pit->getInPit()) { - float dl, dw; - RtDistToPit(car, track, &dl, &dw); - if (dl < PIT_BRAKE_AHEAD) { - float mu = car->_trkPos.seg->surface->kFriction*TIREMU*PIT_MU; - if (brakedist(0.0f, mu) > dl) { - return 1.0f; - } - } - } + if (pit->getPitstop() && !pit->getInPit()) { + float dl, dw; + RtDistToPit(car, track, &dl, &dw); + if (dl < PIT_BRAKE_AHEAD) { + float mu = car->_trkPos.seg->surface->kFriction*TIREMU*PIT_MU; + if (brakedist(0.0f, mu) > dl) { + return 1.0f; + } + } + } - if (pit->getInPit()) { - float s = pit->toSplineCoord(car->_distFromStartLine); - // Pit entry. - if (pit->getPitstop()) { - float mu = car->_trkPos.seg->surface->kFriction*TIREMU*PIT_MU; - if (s < pit->getNPitStart()) { - // Brake to pit speed limit. - float dist = pit->getNPitStart() - s; - if (brakedist(pit->getSpeedlimit(), mu) > dist) { - return 1.0f; - } - } else { - // Hold speed limit. - if (currentspeedsqr > pit->getSpeedlimitSqr()) { - return pit->getSpeedLimitBrake(currentspeedsqr); - } - } - // Brake into pit (speed limit 0.0 to stop) - float dist = pit->getNPitLoc(pitpos) - s; - if (pitpos != PIT_BACK && pit->isTimeout(dist)) { - pit->setPitstop(false); - return 0.0f; - } else { - if (brakedist(0.0f, mu) > dist) { - return 2.0f; - } else if (s > pit->getNPitLoc(pitpos)) { - // Stop in the pit. - return 2.0f; - } - } - } else { - // Pit exit. - if (s < pit->getNPitEnd()) { - // Pit speed limit. - if (currentspeedsqr > pit->getSpeedlimitSqr()) { - return pit->getSpeedLimitBrake(currentspeedsqr); - } - } - } - } + if (pit->getInPit()) { + float s = pit->toSplineCoord(car->_distFromStartLine); + // Pit entry. + if (pit->getPitstop()) { + float mu = car->_trkPos.seg->surface->kFriction*TIREMU*PIT_MU; + if (s < pit->getNPitStart()) { + // Brake to pit speed limit. + float dist = pit->getNPitStart() - s; + if (brakedist(pit->getSpeedlimit(), mu) > dist) { + return 1.0f; + } + } else { + // Hold speed limit. + if (currentspeedsqr > pit->getSpeedlimitSqr()) { + return pit->getSpeedLimitBrake(currentspeedsqr); + } + } + // Brake into pit (speed limit 0.0 to stop) + float dist = pit->getNPitLoc(pitpos) - s; + if (pitpos != PIT_BACK && pit->isTimeout(dist)) { + pit->setPitstop(false); + return 0.0f; + } else { + if (brakedist(0.0f, mu) > dist) { + return 2.0f; + } else if (s > pit->getNPitLoc(pitpos)) { + // Stop in the pit. + return 2.0f; + } + } + } else { + // Pit exit. + if (s < pit->getNPitEnd()) { + // Pit speed limit. + if (currentspeedsqr > pit->getSpeedlimitSqr()) { + return pit->getSpeedLimitBrake(currentspeedsqr); + } + } + } + } - return brake; + return brake; } // Brake filter for collision avoidance. float Driver::filterBColl(float brake) { - collision = 0.0f; + collision = 0.0f; - if (simtime < 1.5) - return brake; + if (simtime < 1.5) + return brake; - float mu = car->_trkPos.seg->surface->kFriction * BrakeMu; - int i; - float thisbrake = 0.0f; - for (i = 0; i < opponents->getNOpponents(); i++) - { - if ((opponent[i].getState() & OPP_COLL)) - { - float accel = 0.0f;//opponent[i].getCarPtr()->_accel_x / MAX(1.0, opponent[i].getTimeImpact()*2); - float ospeed = opponent[i].getSpeed() + accel; - float margin = MIN(0.3f, MAX(0.0f, 0.3f - opponent[i].getDistance())); - if ((opponent[i].getState() & OPP_SIDE_COLL) || - brakedist(ospeed, mu) + MIN(1.0, margin + MAX(0.0, (getSpeed()-ospeed)/9)) > opponent[i].getDistance() + accel) - { - accelcmd = 0.0f; - float thiscollision = MAX(0.01f, MIN(5.0f, opponent[i].getTimeImpact())); - //thiscollision = MAX(0.01f, MIN(thiscollision, opponent[i].getDistance()/2)); - if (collision) - collision = MIN(collision, thiscollision); - else - collision = thiscollision; - thisbrake = MAX(thisbrake, (0.3f + (5.0 - collision)/4) * brakeratio); + float mu = car->_trkPos.seg->surface->kFriction * BrakeMu; + int i; + float thisbrake = 0.0f; + for (i = 0; i < opponents->getNOpponents(); i++) + { + if ((opponent[i].getState() & OPP_COLL)) + { + float accel = 0.0f;//opponent[i].getCarPtr()->_accel_x / MAX(1.0, opponent[i].getTimeImpact()*2); + float ospeed = opponent[i].getSpeed() + accel; + float margin = MIN(0.3f, MAX(0.0f, 0.3f - opponent[i].getDistance())); + if ((opponent[i].getState() & OPP_SIDE_COLL) || + brakedist(ospeed, mu) + MIN(1.0, margin + MAX(0.0, (getSpeed()-ospeed)/9)) > opponent[i].getDistance() + accel) + { + accelcmd = 0.0f; + float thiscollision = MAX(0.01f, MIN(5.0f, opponent[i].getTimeImpact())); + //thiscollision = MAX(0.01f, MIN(thiscollision, opponent[i].getDistance()/2)); + if (collision) + collision = MIN(collision, thiscollision); + else + collision = thiscollision; + thisbrake = MAX(thisbrake, (0.3f + (5.0 - collision)/4) * brakeratio); if (DebugMsg & debug_brake) fprintf(stderr,"%s - %s BRAKE: ti=%.3f\n",car->_name,opponent[i].getCarPtr()->_name,opponent[i].getTimeImpact()); - } - } - } - return MAX(thisbrake, brake); + } + } + } + return MAX(thisbrake, brake); } // Antilocking filter for brakes. float Driver::filterABS(float brake) { - if (car->_speed_x < ABS_MINSPEED) return brake; - float origbrake = brake; - //float rearskid = MAX(0.0f, MAX(car->_skid[2], car->_skid[3]) - MAX(car->_skid[0], car->_skid[1])); - int i; - float slip = 0.0f; - for (i = 0; i < 4; i++) { - slip += car->_wheelSpinVel(i) * car->_wheelRadius(i); - } - //slip *= 1.0f + MAX(rearskid, MAX(fabs(car->_yaw_rate)/10, fabs(angle)/8)); - slip = car->_speed_x - slip/4.0f; - //if (collision) - // slip *= 0.25f; - if (origbrake == 2.0f) - slip *= 0.1f; + if (car->_speed_x < ABS_MINSPEED) return brake; + float origbrake = brake; + //float rearskid = MAX(0.0f, MAX(car->_skid[2], car->_skid[3]) - MAX(car->_skid[0], car->_skid[1])); + int i; + float slip = 0.0f; + for (i = 0; i < 4; i++) { + slip += car->_wheelSpinVel(i) * car->_wheelRadius(i); + } + //slip *= 1.0f + MAX(rearskid, MAX(fabs(car->_yaw_rate)/10, fabs(angle)/8)); + slip = car->_speed_x - slip/4.0f; + //if (collision) + // slip *= 0.25f; + if (origbrake == 2.0f) + slip *= 0.1f; - float absslip = (car->_speed_x < 20.0f ? MIN(AbsSlip, AbsRange/2) : AbsSlip); - if (slip > absslip) { - brake = brake - MIN(brake, (slip - absslip)/AbsRange); - } - brake = MAX(brake, MIN(origbrake, 0.1f)); + float absslip = (car->_speed_x < 20.0f ? MIN(AbsSlip, AbsRange/2) : AbsSlip); + if (slip > absslip) { + brake = brake - MIN(brake, (slip - absslip)/AbsRange); + } + brake = MAX(brake, MIN(origbrake, 0.1f)); - //brake = MAX(MIN(origbrake, collision ? 0.15f :0.05f), brake - MAX(fabs(angle), fabs(car->_yaw_rate) / 2)); - brake = (float) (MAX(MIN(origbrake, (collision ? MAX(0.05f, (5.0-collision)/30) : 0.05f)), brake - fabs(angle-speedangle)*0.3)); + //brake = MAX(MIN(origbrake, collision ? 0.15f :0.05f), brake - MAX(fabs(angle), fabs(car->_yaw_rate) / 2)); + brake = (float) (MAX(MIN(origbrake, (collision ? MAX(0.05f, (5.0-collision)/30) : 0.05f)), brake - fabs(angle-speedangle)*0.3)); - if (fbrakecmd) - brake = MAX(brake, fbrakecmd); + if (fbrakecmd) + brake = MAX(brake, fbrakecmd); - return brake; + return brake; } // TCL filter for accelerator pedal. float Driver::filterTCL(float accel) { - if (simtime < 3.0) - return accel; + if (simtime < 3.0) + return accel; - accel = MIN(1.0f, accel); - float accel1 = accel, accel2 = accel, accel3 = accel, accel4 = accel, accel5 = accel; + accel = MIN(1.0f, accel); + float accel1 = accel, accel2 = accel, accel3 = accel, accel4 = accel, accel5 = accel; - if (car->_speed_x > 10.0f && !pit->getInPit()) - { - tTrackSeg *seg = car->_trkPos.seg; - tTrackSeg *wseg0 = car->_wheelSeg(REAR_RGT); - tTrackSeg *wseg1 = car->_wheelSeg(REAR_LFT); - int count = 0; + if (car->_speed_x > 10.0f && !pit->getInPit()) + { + tTrackSeg *seg = car->_trkPos.seg; + tTrackSeg *wseg0 = car->_wheelSeg(REAR_RGT); + tTrackSeg *wseg1 = car->_wheelSeg(REAR_LFT); + int count = 0; - if (wseg0->surface->kRoughness > MAX(0.02, seg->surface->kRoughness*1.2)) - { - accel1 = (float) MAX(0.1f, accel1 - (wseg0->surface->kRoughness-(seg->surface->kRoughness*2.2)) * (wseg0->style == TR_CURB ? 2 : 10)); - if (fabs(car->_steerCmd) > 0.3f) - { - if (car->_steerCmd < 0.0) - car->_steerCmd = MIN(car->_steerCmd*0.3, car->_steerCmd + (wseg0->surface->kRoughness-(seg->surface->kRoughness*2.2)) * (wseg0->style == TR_CURB ? 2 : 10)); - else - car->_steerCmd = MAX(car->_steerCmd*0.3, car->_steerCmd + (wseg0->surface->kRoughness-(seg->surface->kRoughness*2.2)) * (wseg0->style == TR_CURB ? 2 : 10)); - } - } - if (wseg1->surface->kRoughness > MAX(0.02, seg->surface->kRoughness*1.2)) - { - accel1 = (float) MAX(0.1f, accel1 - (wseg1->surface->kRoughness-(seg->surface->kRoughness*2.2)) * (wseg1->style == TR_CURB ? 2 : 10)); - if (fabs(car->_steerCmd) > 0.3f) - { - if (car->_steerCmd < 0.0) - car->_steerCmd = MIN(car->_steerCmd*0.3, car->_steerCmd - (wseg0->surface->kRoughness-(seg->surface->kRoughness*2.2)) * (wseg0->style == TR_CURB ? 2 : 10)); - else - car->_steerCmd = MAX(car->_steerCmd*0.3, car->_steerCmd - (wseg0->surface->kRoughness-(seg->surface->kRoughness*2.2)) * (wseg0->style == TR_CURB ? 2 : 10)); - } - } + if (wseg0->surface->kRoughness > MAX(0.02, seg->surface->kRoughness*1.2)) + { + accel1 = (float) MAX(0.1f, accel1 - (wseg0->surface->kRoughness-(seg->surface->kRoughness*2.2)) * (wseg0->style == TR_CURB ? 2 : 10)); + if (fabs(car->_steerCmd) > 0.3f) + { + if (car->_steerCmd < 0.0) + car->_steerCmd = MIN(car->_steerCmd*0.3, car->_steerCmd + (wseg0->surface->kRoughness-(seg->surface->kRoughness*2.2)) * (wseg0->style == TR_CURB ? 2 : 10)); + else + car->_steerCmd = MAX(car->_steerCmd*0.3, car->_steerCmd + (wseg0->surface->kRoughness-(seg->surface->kRoughness*2.2)) * (wseg0->style == TR_CURB ? 2 : 10)); + } + } + if (wseg1->surface->kRoughness > MAX(0.02, seg->surface->kRoughness*1.2)) + { + accel1 = (float) MAX(0.1f, accel1 - (wseg1->surface->kRoughness-(seg->surface->kRoughness*2.2)) * (wseg1->style == TR_CURB ? 2 : 10)); + if (fabs(car->_steerCmd) > 0.3f) + { + if (car->_steerCmd < 0.0) + car->_steerCmd = MIN(car->_steerCmd*0.3, car->_steerCmd - (wseg0->surface->kRoughness-(seg->surface->kRoughness*2.2)) * (wseg0->style == TR_CURB ? 2 : 10)); + else + car->_steerCmd = MAX(car->_steerCmd*0.3, car->_steerCmd - (wseg0->surface->kRoughness-(seg->surface->kRoughness*2.2)) * (wseg0->style == TR_CURB ? 2 : 10)); + } + } #if 0 - if (wseg0->surface->kFriction < seg->surface->kFriction) - accel1 = (float) MAX(0.0f, accel1 - (seg->surface->kFriction - wseg0->surface->kFriction)); - if (wseg1->surface->kFriction < seg->surface->kFriction) - accel1 = (float) MAX(0.0f, accel1 - (seg->surface->kFriction - wseg1->surface->kFriction)); + if (wseg0->surface->kFriction < seg->surface->kFriction) + accel1 = (float) MAX(0.0f, accel1 - (seg->surface->kFriction - wseg0->surface->kFriction)); + if (wseg1->surface->kFriction < seg->surface->kFriction) + accel1 = (float) MAX(0.0f, accel1 - (seg->surface->kFriction - wseg1->surface->kFriction)); #endif - - if (wseg0->surface->kRollRes > MAX(0.01, seg->surface->kRollRes*1.2)) - accel1 = (float) MAX(0.0f, accel1 - (wseg0->surface->kRollRes - seg->surface->kRollRes*1.2)*4); - if (wseg1->surface->kRollRes > MAX(0.01, seg->surface->kRollRes*1.2)) - accel1 = (float) MAX(0.0f, accel1 - (wseg1->surface->kRollRes - seg->surface->kRollRes*1.2)*4); + + if (wseg0->surface->kRollRes > MAX(0.01, seg->surface->kRollRes*1.2)) + accel1 = (float) MAX(0.0f, accel1 - (wseg0->surface->kRollRes - seg->surface->kRollRes*1.2)*4); + if (wseg1->surface->kRollRes > MAX(0.01, seg->surface->kRollRes*1.2)) + accel1 = (float) MAX(0.0f, accel1 - (wseg1->surface->kRollRes - seg->surface->kRollRes*1.2)*4); - if (count) - { - if (mode != mode_normal && - ((seg->type == TR_RGT && seg->radius <= 200.0f && car->_trkPos.toLeft < 3.0f) || - (seg->type == TR_LFT && seg->radius <= 200.0f && car->_trkPos.toRight < 3.0f))) - count++; - accel1 = (float) MAX(0.0f, MIN(accel1, (1.0f-(0.25f*count)) - MAX(0.0f, (getSpeed()-car->_speed_x)/10.0f))); - } + if (count) + { + if (mode != mode_normal && + ((seg->type == TR_RGT && seg->radius <= 200.0f && car->_trkPos.toLeft < 3.0f) || + (seg->type == TR_LFT && seg->radius <= 200.0f && car->_trkPos.toRight < 3.0f))) + count++; + accel1 = (float) MAX(0.0f, MIN(accel1, (1.0f-(0.25f*count)) - MAX(0.0f, (getSpeed()-car->_speed_x)/10.0f))); + } - if (fabs(angle) > 1.0) - accel1 = (float) MIN(accel1, 1.0f - (fabs(angle)-1.0)*1.3); - } + if (fabs(angle) > 1.0) + accel1 = (float) MIN(accel1, 1.0f - (fabs(angle)-1.0)*1.3); + } - double turndecel = TurnDecel + rldata->decel; + double turndecel = TurnDecel + rldata->decel; #ifdef CONTROL_SKILL - turndecel += decel_adjust_perc; + turndecel += decel_adjust_perc; #endif - turndecel *= (mode == mode_normal ? 1 : 2); - if (fabs(car->_steerCmd) > 0.02 && turndecel > 0.0) - { - float decel = (float) ((fabs(car->_steerCmd)-0.02f) * (1.0f+fabs(car->_steerCmd)) * 0.7f); - decel *= (float) (turndecel); - if (mode != mode_normal) - { - decel *= 1.0 + rldata->adecel; - } - accel2 = (float) MIN(accel2, MAX(accel2*0.3, 1.0f-decel)); - } + turndecel *= (mode == mode_normal ? 1 : 2); + if (fabs(car->_steerCmd) > 0.02 && turndecel > 0.0) + { + float decel = (float) ((fabs(car->_steerCmd)-0.02f) * (1.0f+fabs(car->_steerCmd)) * 0.7f); + decel *= (float) (turndecel); + if (mode != mode_normal) + { + decel *= 1.0 + rldata->adecel; + } + accel2 = (float) MIN(accel2, MAX(accel2*0.3, 1.0f-decel)); + } - float slip = (this->*GET_DRIVEN_WHEEL_SPEED)() - fabs(car->_speed_x); - if (slip > TclSlip) { - accel3 = accel3 - MIN(accel3, (slip - TclSlip)/TclRange); - } + float slip = (this->*GET_DRIVEN_WHEEL_SPEED)() - fabs(car->_speed_x); + if (slip > TclSlip) { + accel3 = accel3 - MIN(accel3, (slip - TclSlip)/TclRange); + } - double yra = GetModD( tYawRateAccel, rldata->nextdiv ); - if (yra <= 0.0) - yra = YawRateAccel; + double yra = GetModD( tYawRateAccel, rldata->nextdiv ); + if (yra <= 0.0) + yra = YawRateAccel; - accel4 = MAX(0.0, accel4 - fabs(car->_yaw_rate - car->_steerCmd) * yra); + accel4 = MAX(0.0, accel4 - fabs(car->_yaw_rate - car->_steerCmd) * yra); - accel = MAX(accel/4, MIN(accel1, MIN(accel2, MIN(accel4, accel3)))); + accel = MAX(accel/4, MIN(accel1, MIN(accel2, MIN(accel4, accel3)))); - if (mode == mode_normal) - { - accel5 = MAX(0.0, accel5 - rldata->accel_redux); - accel = MIN(accel, accel5); - } + if (mode == mode_normal) + { + accel5 = MAX(0.0, accel5 - rldata->accel_redux); + accel = MIN(accel, accel5); + } - if (accel > 0.9f) - accel = 1.0f; + if (accel > 0.9f) + accel = 1.0f; - if (faccelcmd > 0.0f) - accel = MIN(accel, faccelcmd * 1.2f); + if (faccelcmd > 0.0f) + accel = MIN(accel, faccelcmd * 1.2f); - return accel; + return accel; } // Traction Control (TCL) setup. void Driver::initTCLfilter() { - char *traintype = (char *) GfParmGetStr(car->_carHandle, SECT_DRIVETRAIN, PRM_TYPE, VAL_TRANS_RWD); - if (strcmp(traintype, VAL_TRANS_RWD) == 0) { - GET_DRIVEN_WHEEL_SPEED = &Driver::filterTCL_RWD; - } else if (strcmp(traintype, VAL_TRANS_FWD) == 0) { - GET_DRIVEN_WHEEL_SPEED = &Driver::filterTCL_FWD; - } else if (strcmp(traintype, VAL_TRANS_4WD) == 0) { - GET_DRIVEN_WHEEL_SPEED = &Driver::filterTCL_4WD; - } + char *traintype = (char *) GfParmGetStr(car->_carHandle, SECT_DRIVETRAIN, PRM_TYPE, VAL_TRANS_RWD); + if (strcmp(traintype, VAL_TRANS_RWD) == 0) { + GET_DRIVEN_WHEEL_SPEED = &Driver::filterTCL_RWD; + } else if (strcmp(traintype, VAL_TRANS_FWD) == 0) { + GET_DRIVEN_WHEEL_SPEED = &Driver::filterTCL_FWD; + } else if (strcmp(traintype, VAL_TRANS_4WD) == 0) { + GET_DRIVEN_WHEEL_SPEED = &Driver::filterTCL_4WD; + } } // TCL filter plugin for rear wheel driven cars. float Driver::filterTCL_RWD() { - return (car->_wheelSpinVel(REAR_RGT) + car->_wheelSpinVel(REAR_LFT)) * - car->_wheelRadius(REAR_LFT) / 2.0f; + return (car->_wheelSpinVel(REAR_RGT) + car->_wheelSpinVel(REAR_LFT)) * + car->_wheelRadius(REAR_LFT) / 2.0f; } // TCL filter plugin for front wheel driven cars. float Driver::filterTCL_FWD() { - return (car->_wheelSpinVel(FRNT_RGT) + car->_wheelSpinVel(FRNT_LFT)) * - car->_wheelRadius(FRNT_LFT) / 2.0f; + return (car->_wheelSpinVel(FRNT_RGT) + car->_wheelSpinVel(FRNT_LFT)) * + car->_wheelRadius(FRNT_LFT) / 2.0f; } // TCL filter plugin for all wheel driven cars. float Driver::filterTCL_4WD() { - return ((car->_wheelSpinVel(FRNT_RGT) + car->_wheelSpinVel(FRNT_LFT)) * - car->_wheelRadius(FRNT_LFT) + - (car->_wheelSpinVel(REAR_RGT) + car->_wheelSpinVel(REAR_LFT)) * - car->_wheelRadius(REAR_LFT)) / 4.0f; + return ((car->_wheelSpinVel(FRNT_RGT) + car->_wheelSpinVel(FRNT_LFT)) * + car->_wheelRadius(FRNT_LFT) + + (car->_wheelSpinVel(REAR_RGT) + car->_wheelSpinVel(REAR_LFT)) * + car->_wheelRadius(REAR_LFT)) / 4.0f; } // Hold car on the track. float Driver::filterTrk(float accel) { - return accel; + return accel; - tTrackSeg* seg = car->_trkPos.seg; + tTrackSeg* seg = car->_trkPos.seg; - if (car->_speed_x < MAX_UNSTUCK_SPEED || // Too slow. - pit->getInPit() || // Pit stop. - car->_trkPos.toMiddle*speedangle > 0.0f) // Speedvector points to the inside of the turn. - { - return accel; - } + if (car->_speed_x < MAX_UNSTUCK_SPEED || // Too slow. + pit->getInPit() || // Pit stop. + car->_trkPos.toMiddle*speedangle > 0.0f) // Speedvector points to the inside of the turn. + { + return accel; + } - if (seg->type == TR_STR) { - float tm = fabs(car->_trkPos.toMiddle); - float w = (seg->width - car->_dimension_y)/2.0f ; - if (tm > w) { - return 0.0f; - } else { - return accel; - } - } else { - float sign = (seg->type == TR_RGT) ? -1.0f : 1.0f; - if (car->_trkPos.toMiddle*sign > 0.0f) { - return accel; - } else { - float tm = fabs(car->_trkPos.toMiddle); - float w = seg->width/WIDTHDIV; - if (tm > w) { - return 0.0f; - } else { - return accel; - } - } - } + if (seg->type == TR_STR) { + float tm = fabs(car->_trkPos.toMiddle); + float w = (seg->width - car->_dimension_y)/2.0f ; + if (tm > w) { + return 0.0f; + } else { + return accel; + } + } else { + float sign = (seg->type == TR_RGT) ? -1.0f : 1.0f; + if (car->_trkPos.toMiddle*sign > 0.0f) { + return accel; + } else { + float tm = fabs(car->_trkPos.toMiddle); + float w = seg->width/WIDTHDIV; + if (tm > w) { + return 0.0f; + } else { + return accel; + } + } + } } // Compute the needed distance to brake. float Driver::brakedist(float allowedspeed, float mu) { - float c = mu*G; - float d = (CA*mu + CW)/mass; - float v1sqr = currentspeedsqr; - float v2sqr = allowedspeed*allowedspeed; - return (-log((c + v2sqr*d)/(c + v1sqr*d))/(2.0f*d)) + 1.0; + float c = mu*G; + float d = (CA*mu + CW)/mass; + float v1sqr = currentspeedsqr; + float v2sqr = allowedspeed*allowedspeed; + return (-log((c + v2sqr*d)/(c + v1sqr*d))/(2.0f*d)) + 1.0; } diff --git a/src/drivers/usr_trb1/driver.cpp b/src/drivers/usr_trb1/driver.cpp index 6cb938479..e55b19667 100644 --- a/src/drivers/usr_trb1/driver.cpp +++ b/src/drivers/usr_trb1/driver.cpp @@ -23,37 +23,37 @@ #define CONTROL_SKILL -//const float Driver::MAX_UNSTUCK_ANGLE = (float)(15.0f/180.0f*PI); // [radians] If the angle of the car on the track is smaller, we assume we are not stuck. +//const float Driver::MAX_UNSTUCK_ANGLE = (float)(15.0f/180.0f*PI); // [radians] If the angle of the car on the track is smaller, we assume we are not stuck. const float Driver::MAX_UNSTUCK_ANGLE = 1.3f; -const float Driver::UNSTUCK_TIME_LIMIT = 2.5f; // [s] We try to get unstuck after this time. -const float Driver::MAX_UNSTUCK_SPEED = 5.0f; // [m/s] Below this speed we consider being stuck. -const float Driver::MIN_UNSTUCK_DIST = -1.0f; // [m] If we are closer to the middle we assume to be not stuck. -const float Driver::G = 9.81f; // [m/(s*s)] Welcome on Earth. -const float Driver::FULL_ACCEL_MARGIN = 1.0f; // [m/s] Margin reduce oscillation of brake/acceleration. -const float Driver::SHIFT = 0.9f; // [-] (% of rpmredline) When do we like to shift gears. -const float Driver::SHIFT_MARGIN = 4.0f; // [m/s] Avoid oscillating gear changes. -const float Driver::ABS_MINSPEED = 3.0f; // [m/s] Below this speed the ABS is disabled (numeric, division by small numbers). -const float Driver::LOOKAHEAD_CONST = 18.0f; // [m] -const float Driver::LOOKAHEAD_FACTOR = 0.33f; // [-] -const float Driver::WIDTHDIV = 3.0f; // [-] Defines the percentage of the track to use (2/WIDTHDIV). -const float Driver::SIDECOLL_MARGIN = 3.0f; // [m] Distance between car centers to avoid side collisions. -const float Driver::BORDER_OVERTAKE_MARGIN = 1.0f; // [m] -const float Driver::OVERTAKE_OFFSET_SPEED = 5.0f; // [m/s] Offset change speed. -const float Driver::PIT_LOOKAHEAD = 6.0f; // [m] Lookahead to stop in the pit. -const float Driver::PIT_BRAKE_AHEAD = 200.0f; // [m] Workaround for "broken" pitentries. -const float Driver::PIT_MU = 0.4f; // [-] Friction of pit concrete. -const float Driver::MAX_SPEED = 84.0f; // [m/s] Speed to compute the percentage of brake to apply. -const float Driver::MAX_FUEL_PER_METER = 0.0008f; // [liter/m] fuel consumtion. -const float Driver::CLUTCH_SPEED = 5.0f; // [m/s] -const float Driver::CENTERDIV = 0.1f; // [-] (factor) [0.01..0.6]. -const float Driver::DISTCUTOFF = 200.0f; // [m] How far to look, terminate while loops. -const float Driver::MAX_INC_FACTOR = 8.0f; // [m] Increment faster if speed is slow [1.0..10.0]. -const float Driver::CATCH_FACTOR = 8.0f; // [-] select MIN(catchdist, dist*CATCH_FACTOR) to overtake. -const float Driver::CLUTCH_FULL_MAX_TIME = 2.0f; // [s] Time to apply full clutch. -const float Driver::USE_LEARNED_OFFSET_RANGE = 0.2f; // [m] if offset < this use the learned stuff +const float Driver::UNSTUCK_TIME_LIMIT = 2.5f; // [s] We try to get unstuck after this time. +const float Driver::MAX_UNSTUCK_SPEED = 5.0f; // [m/s] Below this speed we consider being stuck. +const float Driver::MIN_UNSTUCK_DIST = -1.0f; // [m] If we are closer to the middle we assume to be not stuck. +const float Driver::G = 9.81f; // [m/(s*s)] Welcome on Earth. +const float Driver::FULL_ACCEL_MARGIN = 1.0f; // [m/s] Margin reduce oscillation of brake/acceleration. +const float Driver::SHIFT = 0.9f; // [-] (% of rpmredline) When do we like to shift gears. +const float Driver::SHIFT_MARGIN = 4.0f; // [m/s] Avoid oscillating gear changes. +const float Driver::ABS_MINSPEED = 3.0f; // [m/s] Below this speed the ABS is disabled (numeric, division by small numbers). +const float Driver::LOOKAHEAD_CONST = 18.0f; // [m] +const float Driver::LOOKAHEAD_FACTOR = 0.33f; // [-] +const float Driver::WIDTHDIV = 3.0f; // [-] Defines the percentage of the track to use (2/WIDTHDIV). +const float Driver::SIDECOLL_MARGIN = 3.0f; // [m] Distance between car centers to avoid side collisions. +const float Driver::BORDER_OVERTAKE_MARGIN = 1.0f; // [m] +const float Driver::OVERTAKE_OFFSET_SPEED = 5.0f; // [m/s] Offset change speed. +const float Driver::PIT_LOOKAHEAD = 6.0f; // [m] Lookahead to stop in the pit. +const float Driver::PIT_BRAKE_AHEAD = 200.0f; // [m] Workaround for "broken" pitentries. +const float Driver::PIT_MU = 0.4f; // [-] Friction of pit concrete. +const float Driver::MAX_SPEED = 84.0f; // [m/s] Speed to compute the percentage of brake to apply. +const float Driver::MAX_FUEL_PER_METER = 0.0008f; // [liter/m] fuel consumtion. +const float Driver::CLUTCH_SPEED = 5.0f; // [m/s] +const float Driver::CENTERDIV = 0.1f; // [-] (factor) [0.01..0.6]. +const float Driver::DISTCUTOFF = 200.0f; // [m] How far to look, terminate while loops. +const float Driver::MAX_INC_FACTOR = 8.0f; // [m] Increment faster if speed is slow [1.0..10.0]. +const float Driver::CATCH_FACTOR = 8.0f; // [-] select MIN(catchdist, dist*CATCH_FACTOR) to overtake. +const float Driver::CLUTCH_FULL_MAX_TIME = 2.0f; // [s] Time to apply full clutch. +const float Driver::USE_LEARNED_OFFSET_RANGE = 0.2f; // [m] if offset < this use the learned stuff -const float Driver::TEAM_REAR_DIST = 50.0f; // -const int Driver::TEAM_DAMAGE_CHANGE_LEAD = 700; // When to change position in the team? +const float Driver::TEAM_REAR_DIST = 50.0f; // +const int Driver::TEAM_DAMAGE_CHANGE_LEAD = 700; // When to change position in the team? #define SKIPLIMIT 4 @@ -65,145 +65,145 @@ Cardata *Driver::cardata = NULL; Driver::Driver(int index) : - NoTeamWaiting(0), - TeamWaitTime(0.0f), - truespeed(0.0f), - deltaTime(0.0f), - FuelSpeedUp(0.0f), - TclSlip(2.0f), - TclRange(10.0f), - AbsSlip(2.5f), - AbsRange(5.0f), - OversteerASR(0.7f), - BrakeMu(1.0f), - YawRateAccel(0.0f), - random_seed(0), - DebugMsg(0), - racetype(0), - mode(0), - avoidmode(0), - lastmode(0), - allow_stuck(1), - stuck(0), - stuckcheck(0), - stuck_timer(0.0f), - last_stuck_time(-100.0f), - prefer_side(0), - allowcorrecting(0), - pitpos(0), - prevspeedangle(0.0f), - speedangle(0.0f), - angle(0.0f), - mass(0.0f), - maxfuel(0.0f), - myoffset(0.0f), - pitoffset(0.0f), - laststeer(0.0f), - lastbrake(0.0f), - lastaccel(0.0f), - lastNSasteer(0.0f), - lastNSksteer(0.0f), - avgaccel_x(0.0f), - car(NULL), - raceline(NULL), - opponents(NULL), - opponent(NULL), - pit(NULL), - strategy(NULL), - mycardata(NULL), - tLftMargin(NULL), - tRgtMargin(NULL), - simtime(0.0), - avoidtime(0.0), - frontavoidtime(0.0), - correcttimer(0.0), - correctlimit(1000.0), - aligned_timer(0.0), - stopped_timer(0.0), - brakedelay(0.0), - brakeratio(1.0), - deltamult(0.0), - nextCRinverse(0.0), - sideratio(100.0), - laststeer_direction(0.0), - steerLock(0.4), - currentspeedsqr(0.0f), - currentspeed(0.0f), - clutchtime(0.0f), - oldlookahead(0.0f), - oldtime_mod(0.0f), - racesteer(0.0f), - stucksteer(0.0f), - prevleft(0.0f), - rldata(NULL), - avoidlftoffset(0.0f), - avoidrgtoffset(0.0f), - accelcmd(0.0f), - brakecmd(0.0f), - faccelcmd(0.0f), - fbrakecmd(0.0f), - TurnDecel(0.0f), - PitOffset(0.0f), - PitExitSpeed(100.0f), - RevsChangeDown(0.0f), - RevsChangeUp(0.0f), - RevsChangeDownMax(0.0f), - MaxSteerTime(1.5f), - MinSteerTime(1.0f), - SteerCutoff(55.0f), - SmoothSteer(1.0f), - LookAhead(1.0f), - IncFactor(1.0f), - SideMargin(0.0f), - OutSteerFactor(0.0f), - StuckAccel(0.8f), - StuckAngle(1.6f), - FollowMargin(0.0f), - SteerLookahead(0.0f), - CorrectDelay(0.0f), - SteerMaxRI(0.008), - SkidSteer(0.7), - MinAccel(0.2), - lookahead(10.0f), - brakemargin(0.0f), - MaxGear(0), - NoPit(0), - radius(NULL), - alone(0), - carindex(0), - collision(0.0f), - global_skill(0.0f), - driver_aggression(0.0f), - skill(0.0f), - skill_adjust_limit(0.0), - skill_adjust_timer(-1.0), - decel_adjust_targ(1.0), - decel_adjust_perc(1.0), - brake_adjust_targ(1.0), - brake_adjust_perc(1.0), - fuelperlap(5.0f), + NoTeamWaiting(0), + TeamWaitTime(0.0f), + truespeed(0.0f), + deltaTime(0.0f), + FuelSpeedUp(0.0f), + TclSlip(2.0f), + TclRange(10.0f), + AbsSlip(2.5f), + AbsRange(5.0f), + OversteerASR(0.7f), + BrakeMu(1.0f), + YawRateAccel(0.0f), + random_seed(0), + DebugMsg(0), + racetype(0), + mode(0), + avoidmode(0), + lastmode(0), + allow_stuck(1), + stuck(0), + stuckcheck(0), + stuck_timer(0.0f), + last_stuck_time(-100.0f), + prefer_side(0), + allowcorrecting(0), + pitpos(0), + prevspeedangle(0.0f), + speedangle(0.0f), + angle(0.0f), + mass(0.0f), + maxfuel(0.0f), + myoffset(0.0f), + pitoffset(0.0f), + laststeer(0.0f), + lastbrake(0.0f), + lastaccel(0.0f), + lastNSasteer(0.0f), + lastNSksteer(0.0f), + avgaccel_x(0.0f), + car(NULL), + raceline(NULL), + opponents(NULL), + opponent(NULL), + pit(NULL), + strategy(NULL), + mycardata(NULL), + tLftMargin(NULL), + tRgtMargin(NULL), + simtime(0.0), + avoidtime(0.0), + frontavoidtime(0.0), + correcttimer(0.0), + correctlimit(1000.0), + aligned_timer(0.0), + stopped_timer(0.0), + brakedelay(0.0), + brakeratio(1.0), + deltamult(0.0), + nextCRinverse(0.0), + sideratio(100.0), + laststeer_direction(0.0), + steerLock(0.4), + currentspeedsqr(0.0f), + currentspeed(0.0f), + clutchtime(0.0f), + oldlookahead(0.0f), + oldtime_mod(0.0f), + racesteer(0.0f), + stucksteer(0.0f), + prevleft(0.0f), + rldata(NULL), + avoidlftoffset(0.0f), + avoidrgtoffset(0.0f), + accelcmd(0.0f), + brakecmd(0.0f), + faccelcmd(0.0f), + fbrakecmd(0.0f), + TurnDecel(0.0f), + PitOffset(0.0f), + PitExitSpeed(100.0f), + RevsChangeDown(0.0f), + RevsChangeUp(0.0f), + RevsChangeDownMax(0.0f), + MaxSteerTime(1.5f), + MinSteerTime(1.0f), + SteerCutoff(55.0f), + SmoothSteer(1.0f), + LookAhead(1.0f), + IncFactor(1.0f), + SideMargin(0.0f), + OutSteerFactor(0.0f), + StuckAccel(0.8f), + StuckAngle(1.6f), + FollowMargin(0.0f), + SteerLookahead(0.0f), + CorrectDelay(0.0f), + SteerMaxRI(0.008), + SkidSteer(0.7), + MinAccel(0.2), + lookahead(10.0f), + brakemargin(0.0f), + MaxGear(0), + NoPit(0), + radius(NULL), + alone(0), + carindex(0), + collision(0.0f), + global_skill(0.0f), + driver_aggression(0.0f), + skill(0.0f), + skill_adjust_limit(0.0), + skill_adjust_timer(-1.0), + decel_adjust_targ(1.0), + decel_adjust_perc(1.0), + brake_adjust_targ(1.0), + brake_adjust_perc(1.0), + fuelperlap(5.0f), #ifdef SPEED_DREAMS - teamIndex(0), - pitStopChecked(false), + teamIndex(0), + pitStopChecked(false), #endif - MAX_UNSTUCK_COUNT(0), - INDEX(0), - CARMASS(0.0f), - CA(0.0f), - CW(0.0f), - TIREMU(0.0f), - OVERTAKE_OFFSET_INC(0.0f), - MU_FACTOR(0.0f), - track(NULL), - skipcount(0), - cmd_accel(0.0f), - cmd_brake(0.0f), - cmd_steer(0.0f), - cmd_gear(0), - cmd_clutch(0.0f), - cmd_light(0.0f) + MAX_UNSTUCK_COUNT(0), + INDEX(0), + CARMASS(0.0f), + CA(0.0f), + CW(0.0f), + TIREMU(0.0f), + OVERTAKE_OFFSET_INC(0.0f), + MU_FACTOR(0.0f), + track(NULL), + skipcount(0), + cmd_accel(0.0f), + cmd_brake(0.0f), + cmd_steer(0.0f), + cmd_gear(0), + cmd_clutch(0.0f), + cmd_light(0.0f) { - INDEX = index; + INDEX = index; } @@ -214,19 +214,19 @@ Driver::~Driver() raceline->FreeTrack(true); delete raceline; } - delete opponents; - delete pit; - delete [] radius; - delete strategy; - delete rldata; - if (cardata != NULL) { - delete cardata; - cardata = NULL; - } + delete opponents; + delete pit; + delete [] radius; + delete strategy; + delete rldata; + if (cardata != NULL) { + delete cardata; + cardata = NULL; + } - free(tLftMargin); - free(tRgtMargin); - free(tYawRateAccel); + free(tLftMargin); + free(tRgtMargin); + free(tYawRateAccel); } #define RANDOM_SEED 0xfded @@ -249,194 +249,190 @@ unsigned int Driver::getRandom() // Called for every track change or new race. void Driver::initTrack(tTrack* t, void *carHandle, void **carParmHandle, tSituation *s) { - track = t; + track = t; - const int BUFSIZE = 255; - int i; - char buffer[BUFSIZE+1]; + const int BUFSIZE = 255; + int i; + char buffer[BUFSIZE+1]; - global_skill = skill = decel_adjust_perc = driver_aggression = 0.0; + global_skill = skill = decel_adjust_perc = driver_aggression = 0.0; #ifdef CONTROL_SKILL - // load the skill level - //if (s->_raceType == RM_TYPE_PRACTICE) - // global_skill = 0.0; - //else - { - snprintf(buffer, BUFSIZE, "config/raceman/extra/skill.xml"); - void *skillHandle = GfParmReadFile(buffer, GFPARM_RMODE_REREAD); - if (skillHandle) - { - global_skill = GfParmGetNum(skillHandle, (char *)SECT_SKILL, (char *)PRV_SKILL_LEVEL, (char *) NULL, 10.0f); - } - else - { - global_skill = 0.0f; - } - global_skill = MAX(0.0f, MIN(10.0f, global_skill)); + // load the global skill level, range 0 - 10 + snprintf(buffer, BUFSIZE, "%sconfig/raceman/extra/skill.xml", GetLocalDir()); + void *skillHandle = GfParmReadFile(buffer, GFPARM_RMODE_REREAD); + if(!skillHandle) { + snprintf(buffer, BUFSIZE, "%sconfig/raceman/extra/skill.xml", GetDataDir()); + skillHandle = GfParmReadFile(buffer, GFPARM_RMODE_REREAD); + }//if !skillHandle + + if (skillHandle) { + global_skill = GfParmGetNum(skillHandle, (char *)SECT_SKILL, (char *)PRV_SKILL_LEVEL, (char *) NULL, 10.0f); + } + global_skill = MAX(0.0f, MIN(10.0f, global_skill)); - float driver_skill = 0.0f; - snprintf(buffer, BUFSIZE, "drivers/%s/%d/skill.xml",robot_name,INDEX); - skillHandle = GfParmReadFile(buffer, GFPARM_RMODE_STD); - if (skillHandle) - { - driver_skill = GfParmGetNum(skillHandle, SECT_SKILL, PRV_SKILL_LEVEL, (char *) NULL, 0.0); - driver_aggression = GfParmGetNum(skillHandle, SECT_SKILL, PRV_SKILL_AGGRO, (char *)NULL, 0.0); - driver_skill = MIN(1.0, MAX(0.0, driver_skill)); - } + //load the driver skill level, range 0 - 1 + float driver_skill = 0.0f; + snprintf(buffer, BUFSIZE, "drivers/%s/%d/skill.xml",robot_name,INDEX); + skillHandle = GfParmReadFile(buffer, GFPARM_RMODE_STD); + if (skillHandle) + { + driver_skill = GfParmGetNum(skillHandle, SECT_SKILL, PRV_SKILL_LEVEL, (char *) NULL, 0.0); + driver_aggression = GfParmGetNum(skillHandle, SECT_SKILL, PRV_SKILL_AGGRO, (char *)NULL, 0.0); + driver_skill = MIN(1.0, MAX(0.0, driver_skill)); + } - skill = (global_skill + driver_skill * 2) * (1.0 + driver_skill); - } + skill = (global_skill + driver_skill * 2) * (1.0 + driver_skill); #endif - // Load a custom setup if one is available. - // Get a pointer to the first char of the track filename. - char *ptrackname = strrchr(track->filename, '/') + 1; - char *p = strrchr(ptrackname, '.'); - char trackname[256] = {0}; + // Load a custom setup if one is available. + // Get a pointer to the first char of the track filename. + char *ptrackname = strrchr(track->filename, '/') + 1; + char *p = strrchr(ptrackname, '.'); + char trackname[256] = {0}; - if (p) - strncpy(trackname, ptrackname, p - ptrackname); - else - strcpy(trackname, ptrackname); + if (p) + strncpy(trackname, ptrackname, p - ptrackname); + else + strcpy(trackname, ptrackname); - char carName[256]; - { - char const *path = SECT_GROBJECTS "/" LST_RANGES "/" "1"; - char const *key = PRM_CAR; - strncpy( carName, GfParmGetStr(carHandle, path, key, ""), sizeof(carName) ); - char *p = strrchr(carName, '.'); - if (p) *p = '\0'; - } + char carName[256]; + { + char const *path = SECT_GROBJECTS "/" LST_RANGES "/" "1"; + char const *key = PRM_CAR; + strncpy( carName, GfParmGetStr(carHandle, path, key, ""), sizeof(carName) ); + char *p = strrchr(carName, '.'); + if (p) *p = '\0'; + } - snprintf(buffer, BUFSIZE, "drivers/%s/cars/%s/default.xml", robot_name, carName); - *carParmHandle = GfParmReadFile(buffer, GFPARM_RMODE_STD); - void *newhandle; + snprintf(buffer, BUFSIZE, "drivers/%s/cars/%s/default.xml", robot_name, carName); + *carParmHandle = GfParmReadFile(buffer, GFPARM_RMODE_STD); + void *newhandle; - switch (s->_raceType) { - case RM_TYPE_PRACTICE: - snprintf(buffer, BUFSIZE, "drivers/%s/cars/%s/practice/%s.xml", robot_name, carName, trackname); - break; - case RM_TYPE_QUALIF: - snprintf(buffer, BUFSIZE, "drivers/%s/cars/%s/qualifying/%s.xml", robot_name, carName, trackname); - break; - case RM_TYPE_RACE: - snprintf(buffer, BUFSIZE, "drivers/%s/cars/%s/race/%s.xml", robot_name, carName, trackname); - break; - default: - break; - } + switch (s->_raceType) { + case RM_TYPE_PRACTICE: + snprintf(buffer, BUFSIZE, "drivers/%s/cars/%s/practice/%s.xml", robot_name, carName, trackname); + break; + case RM_TYPE_QUALIF: + snprintf(buffer, BUFSIZE, "drivers/%s/cars/%s/qualifying/%s.xml", robot_name, carName, trackname); + break; + case RM_TYPE_RACE: + snprintf(buffer, BUFSIZE, "drivers/%s/cars/%s/race/%s.xml", robot_name, carName, trackname); + break; + default: + break; + } - newhandle = GfParmReadFile(buffer, GFPARM_RMODE_STD); - if (newhandle) - { - if (*carParmHandle) - *carParmHandle = GfParmMergeHandles(*carParmHandle, newhandle, (GFPARM_MMODE_SRC|GFPARM_MMODE_DST|GFPARM_MMODE_RELSRC|GFPARM_MMODE_RELDST)); - else - *carParmHandle = newhandle; - } - else - { - snprintf(buffer, BUFSIZE, "drivers/%s/cars/%s/%s.xml", robot_name, carName, trackname); - newhandle = GfParmReadFile(buffer, GFPARM_RMODE_STD); - if (newhandle) - { - if (*carParmHandle) - *carParmHandle = GfParmMergeHandles(*carParmHandle, newhandle, (GFPARM_MMODE_SRC|GFPARM_MMODE_DST|GFPARM_MMODE_RELSRC|GFPARM_MMODE_RELDST)); - else - *carParmHandle = newhandle; - } - } + newhandle = GfParmReadFile(buffer, GFPARM_RMODE_STD); + if (newhandle) + { + if (*carParmHandle) + *carParmHandle = GfParmMergeHandles(*carParmHandle, newhandle, (GFPARM_MMODE_SRC|GFPARM_MMODE_DST|GFPARM_MMODE_RELSRC|GFPARM_MMODE_RELDST)); + else + *carParmHandle = newhandle; + } + else + { + snprintf(buffer, BUFSIZE, "drivers/%s/cars/%s/%s.xml", robot_name, carName, trackname); + newhandle = GfParmReadFile(buffer, GFPARM_RMODE_STD); + if (newhandle) + { + if (*carParmHandle) + *carParmHandle = GfParmMergeHandles(*carParmHandle, newhandle, (GFPARM_MMODE_SRC|GFPARM_MMODE_DST|GFPARM_MMODE_RELSRC|GFPARM_MMODE_RELDST)); + else + *carParmHandle = newhandle; + } + } - // Create a pit stop strategy object. - strategy = new SimpleStrategy2(); - strategy->setTrack(track); + // Create a pit stop strategy object. + strategy = new SimpleStrategy2(); + strategy->setTrack(track); - // Init fuel. - strategy->setFuelAtRaceStart(t, carParmHandle, s, INDEX); + // Init fuel. + strategy->setFuelAtRaceStart(t, carParmHandle, s, INDEX); - // Load and set parameters. - MU_FACTOR = GfParmGetNum(*carParmHandle, SECT_PRIVATE, BT_ATT_MUFACTOR, (char*)NULL, 0.69f); + // Load and set parameters. + MU_FACTOR = GfParmGetNum(*carParmHandle, SECT_PRIVATE, BT_ATT_MUFACTOR, (char*)NULL, 0.69f); - PitOffset = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_PIT_OFFSET, (char *)NULL, 10.0f ); - PitExitSpeed = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_PIT_EXIT_SPEED, (char *)NULL, 100.0f ); - TurnDecel = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_TURN_DECEL, (char *)NULL, 1.0f ); - RevsChangeUp = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_REVS_UP, (char *)NULL, 0.96f ); - RevsChangeDown = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_REVS_DOWN, (char *)NULL, 0.75f ); - RevsChangeDownMax = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_REVS_DOWN_MAX, (char *)NULL, 0.85f ); - MaxSteerTime = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_MAX_STEER_TIME, (char *)NULL, 1.5f ); - MinSteerTime = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_MIN_STEER_TIME, (char *)NULL, 1.0f ); - SteerCutoff = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_STEER_CUTOFF, (char *)NULL, 55.0f ); - SmoothSteer = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_SMOOTH_STEER, (char *)NULL, 1.0f ); - LookAhead = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_LOOKAHEAD, (char *)NULL, 1.0f ); - IncFactor = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_INC_FACTOR, (char *)NULL, 1.0f ); - SideMargin = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_SIDE_MARGIN, (char *)NULL, 0.0f ); - OutSteerFactor = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_OUT_STEER_X, (char *)NULL, 1.0f ); - StuckAccel = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_STUCK_ACCEL, (char *)NULL, 0.8f ); - StuckAngle = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_STUCK_ANGLE, (char *)NULL, 1.6f ); - FollowMargin = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_FOLLOW_MARGIN, (char *)NULL, 0.0f ); - SteerLookahead = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_STEER_LOOKAHEAD, (char *)NULL, 1.0f ); - CorrectDelay = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_CORRECT_DELAY, (char *)NULL, 0.0f ); - MinAccel = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_MIN_ACCEL, (char *)NULL, 0.2f ); - MaxGear = (int) GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_MAX_GEAR, (char *)NULL, 6.0f ); - NoPit = (int) GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_NO_PIT, (char *)NULL, 0.0f ); - NoTeamWaiting = (int) GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_NO_TEAM_WAITING, (char *)NULL, 1.0f ); - TeamWaitTime = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_TEAM_WAIT_TIME, (char *)NULL, 0.0f); - YawRateAccel = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_YAW_RATE_ACCEL, (char *)NULL, 0.0f); + PitOffset = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_PIT_OFFSET, (char *)NULL, 10.0f ); + PitExitSpeed = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_PIT_EXIT_SPEED, (char *)NULL, 100.0f ); + TurnDecel = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_TURN_DECEL, (char *)NULL, 1.0f ); + RevsChangeUp = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_REVS_UP, (char *)NULL, 0.96f ); + RevsChangeDown = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_REVS_DOWN, (char *)NULL, 0.75f ); + RevsChangeDownMax = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_REVS_DOWN_MAX, (char *)NULL, 0.85f ); + MaxSteerTime = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_MAX_STEER_TIME, (char *)NULL, 1.5f ); + MinSteerTime = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_MIN_STEER_TIME, (char *)NULL, 1.0f ); + SteerCutoff = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_STEER_CUTOFF, (char *)NULL, 55.0f ); + SmoothSteer = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_SMOOTH_STEER, (char *)NULL, 1.0f ); + LookAhead = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_LOOKAHEAD, (char *)NULL, 1.0f ); + IncFactor = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_INC_FACTOR, (char *)NULL, 1.0f ); + SideMargin = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_SIDE_MARGIN, (char *)NULL, 0.0f ); + OutSteerFactor = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_OUT_STEER_X, (char *)NULL, 1.0f ); + StuckAccel = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_STUCK_ACCEL, (char *)NULL, 0.8f ); + StuckAngle = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_STUCK_ANGLE, (char *)NULL, 1.6f ); + FollowMargin = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_FOLLOW_MARGIN, (char *)NULL, 0.0f ); + SteerLookahead = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_STEER_LOOKAHEAD, (char *)NULL, 1.0f ); + CorrectDelay = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_CORRECT_DELAY, (char *)NULL, 0.0f ); + MinAccel = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_MIN_ACCEL, (char *)NULL, 0.2f ); + MaxGear = (int) GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_MAX_GEAR, (char *)NULL, 6.0f ); + NoPit = (int) GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_NO_PIT, (char *)NULL, 0.0f ); + NoTeamWaiting = (int) GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_NO_TEAM_WAITING, (char *)NULL, 1.0f ); + TeamWaitTime = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_TEAM_WAIT_TIME, (char *)NULL, 0.0f); + YawRateAccel = GfParmGetNum( *carParmHandle, SECT_PRIVATE, PRV_YAW_RATE_ACCEL, (char *)NULL, 0.0f); - double brkpressure = GfParmGetNum( *carParmHandle, SECT_BRKSYST, PRM_BRKPRESS, (char *) NULL, 0.0f ) / 1000; + double brkpressure = GfParmGetNum( *carParmHandle, SECT_BRKSYST, PRM_BRKPRESS, (char *) NULL, 0.0f ) / 1000; brakeratio -= MIN(0.5, MAX(0.0, brkpressure - 20000.0) / 100000); - for (i=0; i<6; i++) - { - char szTmp[32]; + for (i=0; i<6; i++) + { + char szTmp[32]; - sprintf(szTmp, "%s %d", PRV_REVS_UP, i+1); - GearRevsChangeUp[i] = GfParmGetNum( *carParmHandle, SECT_PRIVATE, szTmp, (char *)NULL, RevsChangeUp ); + sprintf(szTmp, "%s %d", PRV_REVS_UP, i+1); + GearRevsChangeUp[i] = GfParmGetNum( *carParmHandle, SECT_PRIVATE, szTmp, (char *)NULL, RevsChangeUp ); - sprintf(szTmp, "%s %d", PRV_REVS_DOWN, i+1); - GearRevsChangeDown[i] = GfParmGetNum( *carParmHandle, SECT_PRIVATE, szTmp, (char *)NULL, RevsChangeDown ); + sprintf(szTmp, "%s %d", PRV_REVS_DOWN, i+1); + GearRevsChangeDown[i] = GfParmGetNum( *carParmHandle, SECT_PRIVATE, szTmp, (char *)NULL, RevsChangeDown ); - sprintf(szTmp, "%s %d", PRV_REVS_DOWN_MAX, i+1); - GearRevsChangeDownMax[i] = GfParmGetNum( *carParmHandle, SECT_PRIVATE, szTmp, (char *)NULL, RevsChangeDownMax ); - } + sprintf(szTmp, "%s %d", PRV_REVS_DOWN_MAX, i+1); + GearRevsChangeDownMax[i] = GfParmGetNum( *carParmHandle, SECT_PRIVATE, szTmp, (char *)NULL, RevsChangeDownMax ); + } - tLftMargin = (LRLMod *) malloc( sizeof(LRLMod) ); - tRgtMargin = (LRLMod *) malloc( sizeof(LRLMod) ); - tYawRateAccel = (LRLMod *) malloc( sizeof(LRLMod) ); - memset( tLftMargin, 0, sizeof(LRLMod) ); - memset( tRgtMargin, 0, sizeof(LRLMod) ); - memset( tYawRateAccel, 0, sizeof(LRLMod) ); + tLftMargin = (LRLMod *) malloc( sizeof(LRLMod) ); + tRgtMargin = (LRLMod *) malloc( sizeof(LRLMod) ); + tYawRateAccel = (LRLMod *) malloc( sizeof(LRLMod) ); + memset( tLftMargin, 0, sizeof(LRLMod) ); + memset( tRgtMargin, 0, sizeof(LRLMod) ); + memset( tYawRateAccel, 0, sizeof(LRLMod) ); - for (i=0; i_trkPos.toLeft; - this->car = car; - int stdebug = (int) GfParmGetNum(car->_carHandle, SECT_PRIVATE, PRV_STEER_DEBUG, NULL, 0); - int otdebug = (int) GfParmGetNum(car->_carHandle, SECT_PRIVATE, PRV_OVERTAKE_DEBUG, NULL, 0); - int brdebug = (int) GfParmGetNum(car->_carHandle, SECT_PRIVATE, PRV_BRAKE_DEBUG, NULL, 0); - if ((RM_TYPE_PRACTICE == s->_raceType && stdebug >= 0) || stdebug > 0) DebugMsg |= debug_steer; - if (otdebug) DebugMsg |= debug_overtake; - if (brdebug) DebugMsg |= debug_brake; - FuelSpeedUp = GfParmGetNum(car->_carHandle, SECT_PRIVATE, PRV_FUEL_SPEEDUP, NULL, 0.0f); - TclSlip = GfParmGetNum(car->_carHandle, SECT_PRIVATE, PRV_TCL_SLIP, NULL, 2.0f); - TclRange = GfParmGetNum(car->_carHandle, SECT_PRIVATE, PRV_TCL_RANGE, NULL, 10.0f); - AbsSlip = GfParmGetNum(car->_carHandle, SECT_PRIVATE, PRV_ABS_SLIP, NULL, 2.5f); - AbsRange = GfParmGetNum(car->_carHandle, SECT_PRIVATE, PRV_ABS_RANGE, NULL, 5.0f); - OversteerASR = GfParmGetNum(car->_carHandle, SECT_PRIVATE, PRV_OVERSTEER_ASR, NULL, 0.4f); - BrakeMu = GfParmGetNum(car->_carHandle, SECT_PRIVATE, PRV_BRAKE_MU, NULL, 1.0f); - YawRateAccel = GfParmGetNum(car->_carHandle, SECT_PRIVATE, PRV_YAW_RATE_ACCEL, NULL, 0.0f); - fuelperlap = GfParmGetNum(car->_carHandle, SECT_PRIVATE, PRV_FUEL_PER_LAP, NULL, 5.0f); - CARMASS = GfParmGetNum(car->_carHandle, SECT_CAR, PRM_MASS, NULL, 1000.0f); - maxfuel = GfParmGetNum(car->_carHandle, SECT_CAR, PRM_TANK, NULL, 100.0f); - steerLock = GfParmGetNum(car->_carHandle, SECT_STEER, PRM_STEERLOCK, (char *)NULL, 4.0f); - brakemargin = GfParmGetNum(car->_carHandle, SECT_PRIVATE, PRV_BRAKE_MARGIN, (char *)NULL, 0.0f); - myoffset = 0.0f; - cmd_accel = cmd_brake = cmd_clutch = cmd_steer = cmd_light = 0.0f; - cmd_gear = 1; - skipcount = 0; - simtime = correcttimer = skill_adjust_limit = aligned_timer = stopped_timer = 0.0; - avoidtime = frontavoidtime = 0.0; - correctlimit = 1000.0; - deltamult = 1.0 / s->deltaTime; - racetype = s->_raceType; - initWheelPos(); - initCa(); - initCw(); - initTireMu(); - initTCLfilter(); + deltaTime = (float) RCM_MAX_DT_ROBOTS; + MAX_UNSTUCK_COUNT = int(UNSTUCK_TIME_LIMIT/deltaTime); + OVERTAKE_OFFSET_INC = OVERTAKE_OFFSET_SPEED*deltaTime; + random_seed = 0; + alone = allow_stuck = 1; + stuckcheck = 0; + clutchtime = stuck_timer = 0.0f; + last_stuck_time = -100.0f; + oldtime_mod = oldlookahead = laststeer = lastbrake = lastaccel = avgaccel_x = lastNSasteer = lastNSksteer = 0.0f; + brake_adjust_targ = decel_adjust_targ = 1.0f; + brake_adjust_perc = decel_adjust_perc = 1.0f; + prevleft = car->_trkPos.toLeft; + this->car = car; + int stdebug = (int) GfParmGetNum(car->_carHandle, SECT_PRIVATE, PRV_STEER_DEBUG, NULL, 0); + int otdebug = (int) GfParmGetNum(car->_carHandle, SECT_PRIVATE, PRV_OVERTAKE_DEBUG, NULL, 0); + int brdebug = (int) GfParmGetNum(car->_carHandle, SECT_PRIVATE, PRV_BRAKE_DEBUG, NULL, 0); + if ((RM_TYPE_PRACTICE == s->_raceType && stdebug >= 0) || stdebug > 0) DebugMsg |= debug_steer; + if (otdebug) DebugMsg |= debug_overtake; + if (brdebug) DebugMsg |= debug_brake; + FuelSpeedUp = GfParmGetNum(car->_carHandle, SECT_PRIVATE, PRV_FUEL_SPEEDUP, NULL, 0.0f); + TclSlip = GfParmGetNum(car->_carHandle, SECT_PRIVATE, PRV_TCL_SLIP, NULL, 2.0f); + TclRange = GfParmGetNum(car->_carHandle, SECT_PRIVATE, PRV_TCL_RANGE, NULL, 10.0f); + AbsSlip = GfParmGetNum(car->_carHandle, SECT_PRIVATE, PRV_ABS_SLIP, NULL, 2.5f); + AbsRange = GfParmGetNum(car->_carHandle, SECT_PRIVATE, PRV_ABS_RANGE, NULL, 5.0f); + OversteerASR = GfParmGetNum(car->_carHandle, SECT_PRIVATE, PRV_OVERSTEER_ASR, NULL, 0.4f); + BrakeMu = GfParmGetNum(car->_carHandle, SECT_PRIVATE, PRV_BRAKE_MU, NULL, 1.0f); + YawRateAccel = GfParmGetNum(car->_carHandle, SECT_PRIVATE, PRV_YAW_RATE_ACCEL, NULL, 0.0f); + fuelperlap = GfParmGetNum(car->_carHandle, SECT_PRIVATE, PRV_FUEL_PER_LAP, NULL, 5.0f); + CARMASS = GfParmGetNum(car->_carHandle, SECT_CAR, PRM_MASS, NULL, 1000.0f); + maxfuel = GfParmGetNum(car->_carHandle, SECT_CAR, PRM_TANK, NULL, 100.0f); + steerLock = GfParmGetNum(car->_carHandle, SECT_STEER, PRM_STEERLOCK, (char *)NULL, 4.0f); + brakemargin = GfParmGetNum(car->_carHandle, SECT_PRIVATE, PRV_BRAKE_MARGIN, (char *)NULL, 0.0f); + myoffset = 0.0f; + cmd_accel = cmd_brake = cmd_clutch = cmd_steer = cmd_light = 0.0f; + cmd_gear = 1; + skipcount = 0; + simtime = correcttimer = skill_adjust_limit = aligned_timer = stopped_timer = 0.0; + avoidtime = frontavoidtime = 0.0; + correctlimit = 1000.0; + deltamult = 1.0 / s->deltaTime; + racetype = s->_raceType; + initWheelPos(); + initCa(); + initCw(); + initTireMu(); + initTCLfilter(); - raceline = new LRaceLine(); - raceline->NewRace( car, s ); - raceline->setSkill( skill ); - raceline->AllocTrack( track ); - { - char *ptrackname = strrchr(track->filename, '/') + 1; - char *p = strrchr(ptrackname, '.'); - char trackname[256] = {0}; - - if (p) - strncpy(trackname, ptrackname, p - ptrackname); - else - strcpy(trackname, ptrackname); + raceline = new LRaceLine(); + raceline->NewRace( car, s ); + raceline->setSkill( skill ); + raceline->AllocTrack( track ); + { + char *ptrackname = strrchr(track->filename, '/') + 1; + char *p = strrchr(ptrackname, '.'); + char trackname[256] = {0}; + + if (p) + strncpy(trackname, ptrackname, p - ptrackname); + else + strcpy(trackname, ptrackname); - char carName[256]; - { - char const *path = SECT_GROBJECTS "/" LST_RANGES "/" "1"; - char const *key = PRM_CAR; - strncpy( carName, GfParmGetStr(car->_carHandle, path, key, ""), sizeof(carName) ); - char *p = strrchr(carName, '.'); - if (p) *p = '\0'; - } + char carName[256]; + { + char const *path = SECT_GROBJECTS "/" LST_RANGES "/" "1"; + char const *key = PRM_CAR; + strncpy( carName, GfParmGetStr(car->_carHandle, path, key, ""), sizeof(carName) ); + char *p = strrchr(carName, '.'); + if (p) *p = '\0'; + } - LoadDAT( s, carName, trackname ); - } - raceline->InitTrack(track, s); - raceline->setCW( CW ); + LoadDAT( s, carName, trackname ); + } + raceline->InitTrack(track, s); + raceline->setCW( CW ); - rldata = new LRaceLineData(); - memset(rldata, 0, sizeof(LRaceLineData)); + rldata = new LRaceLineData(); + memset(rldata, 0, sizeof(LRaceLineData)); - // Create just one instance of cardata shared by all drivers. - if (cardata == NULL) { - cardata = new Cardata(s); - } - mycardata = cardata->findCar(car); - simtime = s->currentTime; - skill_adjust_timer = -1; + // Create just one instance of cardata shared by all drivers. + if (cardata == NULL) { + cardata = new Cardata(s); + } + mycardata = cardata->findCar(car); + simtime = s->currentTime; + skill_adjust_timer = -1; - // initialize the list of opponents. - opponents = new Opponents(s, this, cardata); - opponent = opponents->getOpponentPtr(); + // initialize the list of opponents. + opponents = new Opponents(s, this, cardata); + opponent = opponents->getOpponentPtr(); - // Set team mate. - char *teammate = (char *) GfParmGetStr(car->_carHandle, SECT_PRIVATE, BT_ATT_TEAMMATE, NULL); - if (teammate != NULL) { - opponents->setTeamMate(teammate); - } + // Set team mate. + char *teammate = (char *) GfParmGetStr(car->_carHandle, SECT_PRIVATE, BT_ATT_TEAMMATE, NULL); + if (teammate != NULL) { + opponents->setTeamMate(teammate); + } - // Initialize radius of segments. - radius = new float[track->nseg]; - computeRadius(radius); + // Initialize radius of segments. + radius = new float[track->nseg]; + computeRadius(radius); - // create the pit object. - pit = new Pit(s, this, PitOffset); - setMode( mode_correcting ); - lastmode = mode_correcting; + // create the pit object. + pit = new Pit(s, this, PitOffset); + setMode( mode_correcting ); + lastmode = mode_correcting; - carindex = 0; + carindex = 0; - for (int i = 0; i < s->_ncars; i++) - { - if (s->cars[i] == car) - { - carindex = i; - break; - } - } + for (int i = 0; i < s->_ncars; i++) + { + if (s->cars[i] == car) + { + carindex = i; + break; + } + } #ifdef SPEED_DREAMS - teamIndex = RtTeamManagerIndex( car, track, s ); - strategy->setTeamIndex( teamIndex ); + teamIndex = RtTeamManagerIndex( car, track, s ); + strategy->setTeamIndex( teamIndex ); #endif } void Driver::calcSpeed() { - accelcmd = brakecmd = 0.0f; - faccelcmd = fbrakecmd = 0.0f; - double speed = rldata->speed; - double avspeed = MAX((currentspeed+0.4)-(MAX(0.0, 1.6-fabs(MAX(0.0, angle-speedangle))*5)), rldata->avspeed); - double slowavspeed = rldata->slowavspeed; + accelcmd = brakecmd = 0.0f; + faccelcmd = fbrakecmd = 0.0f; + double speed = rldata->speed; + double avspeed = MAX((currentspeed+0.4)-(MAX(0.0, 1.6-fabs(MAX(0.0, angle-speedangle))*5)), rldata->avspeed); + double slowavspeed = rldata->slowavspeed; - double speed_redux = 1.0; + double speed_redux = 1.0; - if (mode != mode_normal) - { - if (fabs(speedangle) > 0.05 && - (fabs(speedangle) > fabs(rldata->rlangle) || fabs(speedangle - rldata->rlangle) > 0.05)) - speed_redux -= MIN(0.6, MIN(fabs(speedangle), fabs(speedangle-rldata->rlangle))/2); - avspeed *= speed_redux; - slowavspeed *= speed_redux; - } + if (mode != mode_normal) + { + if (fabs(speedangle) > 0.05 && + (fabs(speedangle) > fabs(rldata->rlangle) || fabs(speedangle - rldata->rlangle) > 0.05)) + speed_redux -= MIN(0.6, MIN(fabs(speedangle), fabs(speedangle-rldata->rlangle))/2); + avspeed *= speed_redux; + slowavspeed *= speed_redux; + } - if (mode == mode_avoiding && !allowcorrecting) - { - speed = avspeed; - if ((avoidmode & avoidside) && !rldata->insideline && sideratio < 1.0 && - ((rldata->rInverse > 0.0 && (avoidmode & avoidright) && speedangle < -(sideratio/10)) || - (rldata->rInverse < 0.0 && (avoidmode & avoidleft) && speedangle > (sideratio/10)))) - { - speed = slowavspeed; - } - } - else if ((mode == mode_correcting || (simtime - aligned_timer < 2.0)) && rldata->insideline && rldata->closing) - { - speed = slowavspeed; - } - else if ((mode == mode_correcting || (simtime - aligned_timer < 5.0))) - { - //avspeed = MIN(rldata->speed - MIN(3.0, fabs(rldata->rInverse)*400), avspeed); - avspeed = MIN(rldata->speed, (slowavspeed+avspeed)/2); - double rlspeed = rldata->speed;//MAX(avspeed, rldata->speed-1.0); - //speed = avspeed + (rlspeed-avspeed) * MAX(0.0, MIN(1.0, 1.0 - MAX(fabs(correctlimit*2), fabs(fabs(laststeer)-fabs(rldata->rInverse*80))/2))); - speed = avspeed + (rlspeed-avspeed) * MAX(0.0, MIN(1.0, 1.0 - (fabs(correctlimit*2) + fabs(angle - rldata->rlangle)*5))); - } + if (mode == mode_avoiding && !allowcorrecting) + { + speed = avspeed; + if ((avoidmode & avoidside) && !rldata->insideline && sideratio < 1.0 && + ((rldata->rInverse > 0.0 && (avoidmode & avoidright) && speedangle < -(sideratio/10)) || + (rldata->rInverse < 0.0 && (avoidmode & avoidleft) && speedangle > (sideratio/10)))) + { + speed = slowavspeed; + } + } + else if ((mode == mode_correcting || (simtime - aligned_timer < 2.0)) && rldata->insideline && rldata->closing) + { + speed = slowavspeed; + } + else if ((mode == mode_correcting || (simtime - aligned_timer < 5.0))) + { + //avspeed = MIN(rldata->speed - MIN(3.0, fabs(rldata->rInverse)*400), avspeed); + avspeed = MIN(rldata->speed, (slowavspeed+avspeed)/2); + double rlspeed = rldata->speed;//MAX(avspeed, rldata->speed-1.0); + //speed = avspeed + (rlspeed-avspeed) * MAX(0.0, MIN(1.0, 1.0 - MAX(fabs(correctlimit*2), fabs(fabs(laststeer)-fabs(rldata->rInverse*80))/2))); + speed = avspeed + (rlspeed-avspeed) * MAX(0.0, MIN(1.0, 1.0 - (fabs(correctlimit*2) + fabs(angle - rldata->rlangle)*5))); + } - if (pit->getInPit() && !pit->getPitstop()) - { - float s = pit->toSplineCoord( car->_distFromStartLine ); - if (s > pit->getNPitEnd()) - speed = MIN(speed, PitExitSpeed); - } + if (pit->getInPit() && !pit->getPitstop()) + { + float s = pit->toSplineCoord( car->_distFromStartLine ); + if (s > pit->getNPitEnd()) + speed = MIN(speed, PitExitSpeed); + } - //if (mode == mode_normal && fabs(rldata->rInverse) < 0.001 && fabs(car->_steerCmd) < 0.01 && fabs(angle) < 0.01 && fabs(car->_yaw_rate) < 0.01) - // aligned_timer = 0.0; + //if (mode == mode_normal && fabs(rldata->rInverse) < 0.001 && fabs(car->_steerCmd) < 0.01 && fabs(angle) < 0.01 && fabs(car->_yaw_rate) < 0.01) + // aligned_timer = 0.0; - double x = (10 + car->_speed_x) * (speed - car->_speed_x) / 200; - double lane2left = car->_trkPos.toLeft / track->width; - double lane2right = car->_trkPos.toRight / track->width; - int sidedanger = ((rldata->rInverse > 0.0 && speedangle < -(rldata->rInverse) * lane2left*2) || (rldata->rInverse < 0.0 && speedangle > rldata->rInverse*lane2right*2)); - double skid = MAX(0.0, (car->_skid[2] + car->_skid[3] + car->_skid[0] + car->_skid[1])) * 3; + double x = (10 + car->_speed_x) * (speed - car->_speed_x) / 200; + double lane2left = car->_trkPos.toLeft / track->width; + double lane2right = car->_trkPos.toRight / track->width; + int sidedanger = ((rldata->rInverse > 0.0 && speedangle < -(rldata->rInverse) * lane2left*2) || (rldata->rInverse < 0.0 && speedangle > rldata->rInverse*lane2right*2)); + double skid = MAX(0.0, (car->_skid[2] + car->_skid[3] + car->_skid[0] + car->_skid[1])) * 3; - brakecmd = 0.0f; - accelcmd = 100.0f; + brakecmd = 0.0f; + accelcmd = 100.0f; - { - double skidangle = angle; - if (mode != mode_normal) - { - if ((angle > 0.0 && speedangle < angle) || - (angle < 0.0 && speedangle > angle)) - skidangle += speedangle/2; - } + { + double skidangle = angle; + if (mode != mode_normal) + { + if ((angle > 0.0 && speedangle < angle) || + (angle < 0.0 && speedangle > angle)) + skidangle += speedangle/2; + } #if 0 - // if over/understeering, decrease speed - if (rldata->rInverse > 0.0) - { - double mod = ((laststeer-rldata->rInverse) * fabs(rldata->rInverse*15)); - if (mod < 0.0) // oversteer, will increase x but by less if skidding outwards - mod /= 4 - MIN(0.0, skidangle * 10); - x = MIN(x, 1.0) - mod; - } - else - { - double mod = ((laststeer-rldata->rInverse) * fabs(rldata->rInverse*15)); - if (mod > 0.0) // oversteer - mod /= 4 + MAX(0.0, skidangle * 10); - x = MIN(x, 1.0) + mod; - } + // if over/understeering, decrease speed + if (rldata->rInverse > 0.0) + { + double mod = ((laststeer-rldata->rInverse) * fabs(rldata->rInverse*15)); + if (mod < 0.0) // oversteer, will increase x but by less if skidding outwards + mod /= 4 - MIN(0.0, skidangle * 10); + x = MIN(x, 1.0) - mod; + } + else + { + double mod = ((laststeer-rldata->rInverse) * fabs(rldata->rInverse*15)); + if (mod > 0.0) // oversteer + mod /= 4 + MAX(0.0, skidangle * 10); + x = MIN(x, 1.0) + mod; + } #else - if (//(mode == mode_normal || !sidedanger) && - (skidangle < 0.0 && laststeer > 0.0 && rldata->rInverse < -0.001) || - (skidangle > 0.0 && laststeer < 0.0 && rldata->rInverse > 0.001)) - { - // increase acceleration if correcting a skid - double diff = MAX(0.0, MIN(fabs(laststeer), MAX(fabs(skidangle/7)/1000, fabs(rldata->rInverse * 50)))) * MAX(0.0, MIN(2.0, (7-skid))); - if (collision) - diff *= MIN(1.0, collision / 3.0f)*0.8; - x += diff * OversteerASR; - } - else if (mode != mode_normal && - (car->_accel_x < 1.0 || sidedanger) && - ((angle > 0.0 && laststeer > 0.0 && rldata->rInverse < -0.001) || - (angle < 0.0 && laststeer < 0.0 && rldata->rInverse > 0.001))) - { - // understeering, decrease speed - double diff = MIN(fabs(laststeer), MAX(fabs(angle)/50, fabs(rldata->rInverse * 50))) * 4; - x -= diff; - } + if (//(mode == mode_normal || !sidedanger) && + (skidangle < 0.0 && laststeer > 0.0 && rldata->rInverse < -0.001) || + (skidangle > 0.0 && laststeer < 0.0 && rldata->rInverse > 0.001)) + { + // increase acceleration if correcting a skid + double diff = MAX(0.0, MIN(fabs(laststeer), MAX(fabs(skidangle/7)/1000, fabs(rldata->rInverse * 50)))) * MAX(0.0, MIN(2.0, (7-skid))); + if (collision) + diff *= MIN(1.0, collision / 3.0f)*0.8; + x += diff * OversteerASR; + } + else if (mode != mode_normal && + (car->_accel_x < 1.0 || sidedanger) && + ((angle > 0.0 && laststeer > 0.0 && rldata->rInverse < -0.001) || + (angle < 0.0 && laststeer < 0.0 && rldata->rInverse > 0.001))) + { + // understeering, decrease speed + double diff = MIN(fabs(laststeer), MAX(fabs(angle)/50, fabs(rldata->rInverse * 50))) * 4; + x -= diff; + } #endif #if 0 - // check if we're really close behind someone on a bend - // if so (and we're not overtaking) make sure we don't under-brake or - // over-accelerate and thus lose control. - fbrakecmd = faccelcmd = 0.0f; + // check if we're really close behind someone on a bend + // if so (and we're not overtaking) make sure we don't under-brake or + // over-accelerate and thus lose control. + fbrakecmd = faccelcmd = 0.0f; - if (mode == mode_normal) - { - for (int i=0; igetNOpponents(); i++) - { - tCarElt *ocar = opponent[i].getCarPtr(); + if (mode == mode_normal) + { + for (int i=0; igetNOpponents(); i++) + { + tCarElt *ocar = opponent[i].getCarPtr(); - if (ocar == car) - continue; + if (ocar == car) + continue; - if (opponent[i].getTeam() != TEAM_FRIEND) - continue; + if (opponent[i].getTeam() != TEAM_FRIEND) + continue; - if (!(opponent[i].getState() & OPP_FRONT) || opponent[i].getDistance() > 3.0) - continue; + if (!(opponent[i].getState() & OPP_FRONT) || opponent[i].getDistance() > 3.0) + continue; - if (fabs(car->_trkPos.toLeft - ocar->_trkPos.toLeft) > car->_dimension_x*0.8) - continue; + if (fabs(car->_trkPos.toLeft - ocar->_trkPos.toLeft) > car->_dimension_x*0.8) + continue; - if (mode == mode_normal && opponent[i].isTeamMate() && opponent[i].getDistance() < 1.5) - { - accelcmd = ocar->_accelCmd; - if (accelcmd > 0.0f) - faccelcmd = accelcmd; - } + if (mode == mode_normal && opponent[i].isTeamMate() && opponent[i].getDistance() < 1.5) + { + accelcmd = ocar->_accelCmd; + if (accelcmd > 0.0f) + faccelcmd = accelcmd; + } - /* - if ((rldata->rInverse > 0.001 && car->_trkPos.toLeft > rldata->lane * car->_trkPos.seg->width) || - (rldata->rInverse < -0.001 && car->_trkPos.toLeft < rldata->lane * car->_trkPos.seg->width)) - { - double change = MAX(currentspeed-rldata->speed, fabs(car->_trkPos.toLeft - (rldata->lane * car->_trkPos.seg->width))); + /* + if ((rldata->rInverse > 0.001 && car->_trkPos.toLeft > rldata->lane * car->_trkPos.seg->width) || + (rldata->rInverse < -0.001 && car->_trkPos.toLeft < rldata->lane * car->_trkPos.seg->width)) + { + double change = MAX(currentspeed-rldata->speed, fabs(car->_trkPos.toLeft - (rldata->lane * car->_trkPos.seg->width))); - x -= MAX(0.0, MIN(1.0, change)); - break; - } - */ + x -= MAX(0.0, MIN(1.0, change)); + break; + } + */ - if (opponent[i].getDistance() < 1.5 && ocar->_brakeCmd > 0.0 && (opponent[i].getState() & OPP_COLL)) - { - brakecmd = ocar->_brakeCmd*MAX(1.0, currentspeed / opponent[i].getSpeed()); - if (brakecmd > 0.0) - { - x = MIN(x, -0.001); - fbrakecmd = brakecmd; - } - } + if (opponent[i].getDistance() < 1.5 && ocar->_brakeCmd > 0.0 && (opponent[i].getState() & OPP_COLL)) + { + brakecmd = ocar->_brakeCmd*MAX(1.0, currentspeed / opponent[i].getSpeed()); + if (brakecmd > 0.0) + { + x = MIN(x, -0.001); + fbrakecmd = brakecmd; + } + } - break; - } - } + break; + } + } #endif - } + } - if (x > 0) - { - if (accelcmd < 100.0f) - accelcmd = MIN(accelcmd, (float) x); - else - accelcmd = (float) x; - accelcmd = MAX(accelcmd, MinAccel); - } - else - brakecmd = MIN(1.0f, MAX(brakecmd, (float) (-(MAX(10.0, brakedelay*0.7))*x))); + if (x > 0) + { + if (accelcmd < 100.0f) + accelcmd = MIN(accelcmd, (float) x); + else + accelcmd = (float) x; + accelcmd = MAX(accelcmd, MinAccel); + } + else + brakecmd = MIN(1.0f, MAX(brakecmd, (float) (-(MAX(10.0, brakedelay*0.7))*x))); } int Driver::rearOffTrack() @@ -847,113 +843,113 @@ int Driver::rearOffTrack() // Drive during race. void Driver::drive(tSituation *s) { - laststeer = car->_steerCmd; - memset(&car->ctrl, 0, sizeof(tCarCtrl)); + laststeer = car->_steerCmd; + memset(&car->ctrl, 0, sizeof(tCarCtrl)); - skipcount++; + skipcount++; - if (skipcount > SKIPLIMIT) - skipcount = 0; + if (skipcount > SKIPLIMIT) + skipcount = 0; - if (skipcount > 1) - { - // potentially can skip (we never do if skipcount == 0) + if (skipcount > 1) + { + // potentially can skip (we never do if skipcount == 0) - if (mode == mode_normal) - { - // driving on the raceline - if (fabs(car->_yaw_rate) < 0.15 && - fabs(car->_accel_x) > -2 && - fabs(speedangle - angle) < 0.1) - { - // car not under stress, we can skip - car->_accelCmd = cmd_accel; - car->_brakeCmd = cmd_brake; - car->_steerCmd = cmd_steer; - car->_gearCmd = cmd_gear; - car->_clutchCmd = cmd_clutch; - car->_lightCmd = (int)cmd_light; - return; - } - } - else - { - // we're avoiding someone, don't skip (for the most part) - if (skipcount > 2) - skipcount = 0; - } - } + if (mode == mode_normal) + { + // driving on the raceline + if (fabs(car->_yaw_rate) < 0.15 && + fabs(car->_accel_x) > -2 && + fabs(speedangle - angle) < 0.1) + { + // car not under stress, we can skip + car->_accelCmd = cmd_accel; + car->_brakeCmd = cmd_brake; + car->_steerCmd = cmd_steer; + car->_gearCmd = cmd_gear; + car->_clutchCmd = cmd_clutch; + car->_lightCmd = (int)cmd_light; + return; + } + } + else + { + // we're avoiding someone, don't skip (for the most part) + if (skipcount > 2) + skipcount = 0; + } + } - update(s); + update(s); - //pit->setPitstop(true); + //pit->setPitstop(true); #ifdef CONTROL_SKILL - calcSkill(); + calcSkill(); #endif - car->_steerCmd = getSteer(s); + car->_steerCmd = getSteer(s); - if (!isStuck()) - { - car->_gearCmd = getGear(); - calcSpeed(); - car->_brakeCmd = filterABS(filterBrakeSpeed(filterBColl(filterBPit(getBrake())))); - if (car->_brakeCmd == 0.0f) { - car->_accelCmd = filterTCL(filterTrk(filterTeam(filterOverlap(getAccel())))); - } else { - car->_accelCmd = 0.0f; - } + if (!isStuck()) + { + car->_gearCmd = getGear(); + calcSpeed(); + car->_brakeCmd = filterABS(filterBrakeSpeed(filterBColl(filterBPit(getBrake())))); + if (car->_brakeCmd == 0.0f) { + car->_accelCmd = filterTCL(filterTrk(filterTeam(filterOverlap(getAccel())))); + } else { + car->_accelCmd = 0.0f; + } - if (!collision && fabs(car->_speed_x) < 1.0) - { - car->_accelCmd = MAX(car->_accelCmd, 0.4f); - car->_brakeCmd = 0.0f; - } + if (!collision && fabs(car->_speed_x) < 1.0) + { + car->_accelCmd = MAX(car->_accelCmd, 0.4f); + car->_brakeCmd = 0.0f; + } - if (car->_speed_x < -1.0f) - { - car->_accelCmd = 0.0f; - car->_brakeCmd = 0.7f; - } + if (car->_speed_x < -1.0f) + { + car->_accelCmd = 0.0f; + car->_brakeCmd = 0.7f; + } - car->_clutchCmd = getClutch(); - if (DebugMsg & debug_steer) - fprintf(stderr,"%s %d/%d: ",car->_name,rldata->thisdiv,rldata->nextdiv); + car->_clutchCmd = getClutch(); + if (DebugMsg & debug_steer) + fprintf(stderr,"%s %d/%d: ",car->_name,rldata->thisdiv,rldata->nextdiv); - } + } - if (DebugMsg & debug_steer) - { - double skid = (car->_skid[0]+car->_skid[1]+car->_skid[2]+car->_skid[3])/2; - fprintf(stderr,"%d%c%c%c s%.2f k%.2f ss%.2f cl%.3f g%d->%d brk%.3f acc%.2f dec%.2f coll%.1f",mode,((mode==mode_avoiding)?'A':' '),(avoidmode==avoidleft?'L':(avoidmode==avoidright?'R':' ')),(mode==mode_correcting?'c':' '),car->_steerCmd,rldata->ksteer,stucksteer,correctlimit,car->_gear,car->_gearCmd,car->_brakeCmd,car->_accelCmd,rldata->decel,collision); - fprintf(stderr," spd%.1f|k%.1f|a%.1f/%.1f|t%.1f angle=%.2f/%.2f/%.2f yr=%.2f skid=%.2f acxy=%.2f/%.2f slip=%.3f/%.3f %.3f/%.3f\n",(double)currentspeed,(double)rldata->speed,(double)rldata->avspeed,(double)rldata->slowavspeed,(double)getTrueSpeed(),angle,speedangle,rldata->rlangle,car->_yaw_rate,skid,car->_accel_x,car->_accel_y,nextCRinverse,rldata->mInverse,car->_wheelSpinVel(FRNT_RGT)*car->_wheelRadius(FRNT_RGT)-car->_speed_x,car->_wheelSpinVel(FRNT_LFT)*car->_wheelRadius(FRNT_LFT)-car->_speed_x,car->_wheelSpinVel(REAR_RGT)*car->_wheelRadius(REAR_RGT)-car->_speed_x,car->_wheelSpinVel(REAR_LFT)*car->_wheelRadius(REAR_LFT)-car->_speed_x);fflush(stderr); - } + if (DebugMsg & debug_steer) + { + double skid = (car->_skid[0]+car->_skid[1]+car->_skid[2]+car->_skid[3])/2; + fprintf(stderr,"%d%c%c%c s%.2f k%.2f ss%.2f cl%.3f g%d->%d brk%.3f acc%.2f dec%.2f coll%.1f",mode,((mode==mode_avoiding)?'A':' '),(avoidmode==avoidleft?'L':(avoidmode==avoidright?'R':' ')),(mode==mode_correcting?'c':' '),car->_steerCmd,rldata->ksteer,stucksteer,correctlimit,car->_gear,car->_gearCmd,car->_brakeCmd,car->_accelCmd,rldata->decel,collision); + fprintf(stderr," spd%.1f|k%.1f|a%.1f/%.1f|t%.1f angle=%.2f/%.2f/%.2f yr=%.2f skid=%.2f acxy=%.2f/%.2f slip=%.3f/%.3f %.3f/%.3f\n",(double)currentspeed,(double)rldata->speed,(double)rldata->avspeed,(double)rldata->slowavspeed,(double)getTrueSpeed(),angle,speedangle,rldata->rlangle,car->_yaw_rate,skid,car->_accel_x,car->_accel_y,nextCRinverse,rldata->mInverse,car->_wheelSpinVel(FRNT_RGT)*car->_wheelRadius(FRNT_RGT)-car->_speed_x,car->_wheelSpinVel(FRNT_LFT)*car->_wheelRadius(FRNT_LFT)-car->_speed_x,car->_wheelSpinVel(REAR_RGT)*car->_wheelRadius(REAR_RGT)-car->_speed_x,car->_wheelSpinVel(REAR_LFT)*car->_wheelRadius(REAR_LFT)-car->_speed_x);fflush(stderr); + } - laststeer = car->_steerCmd; - lastbrake = car->_brakeCmd; - lastaccel = car->_accelCmd; - lastmode = mode; - prevleft = car->_trkPos.toLeft; + laststeer = car->_steerCmd; + lastbrake = car->_brakeCmd; + lastaccel = car->_accelCmd; + lastmode = mode; + prevleft = car->_trkPos.toLeft; - cmd_accel = car->_accelCmd; - cmd_brake = car->_brakeCmd; - cmd_steer = car->_steerCmd; - cmd_clutch = car->_clutchCmd; - cmd_gear = car->_gearCmd; - cmd_light = (float)car->_lightCmd; + cmd_accel = car->_accelCmd; + cmd_brake = car->_brakeCmd; + cmd_steer = car->_steerCmd; + cmd_clutch = car->_clutchCmd; + cmd_gear = car->_gearCmd; + cmd_light = (float)car->_lightCmd; } // Set pitstop commands. int Driver::pitCommand(tSituation *s) { - car->_pitRepair = strategy->pitRepair(car, s); - car->_pitFuel = strategy->pitRefuel(car, s); - // This should be the only place where the pit stop is set to false! - pit->setPitstop(false); - return ROB_PIT_IM; // return immediately. + car->_pitRepair = strategy->pitRepair(car, s); + car->_pitFuel = strategy->pitRefuel(car, s); + // This should be the only place where the pit stop is set to false! + pit->setPitstop(false); + return ROB_PIT_IM; // return immediately. } @@ -962,16 +958,16 @@ int Driver::pitCommand(tSituation *s) void Driver::endRace(tSituation *s) { #ifdef SPEED_DREAMS - RtTeamReleasePit(teamIndex); + RtTeamReleasePit(teamIndex); #endif - car->ctrl.raceCmd = 0; + car->ctrl.raceCmd = 0; } // cleanup void Driver::shutdown() { #ifdef SPEED_DREAMS - RtTeamManagerRelease(); + RtTeamManagerRelease(); #endif } @@ -985,32 +981,32 @@ void Driver::shutdown() void Driver::computeRadius(float *radius) { - float lastturnarc = 0.0f; - int lastsegtype = TR_STR; + float lastturnarc = 0.0f; + int lastsegtype = TR_STR; - tTrackSeg *currentseg, *startseg = track->seg; - currentseg = startseg; + tTrackSeg *currentseg, *startseg = track->seg; + currentseg = startseg; - do { - if (currentseg->type == TR_STR) { - lastsegtype = TR_STR; - radius[currentseg->id] = FLT_MAX; - } else { - if (currentseg->type != lastsegtype) { - float arc = 0.0f; - tTrackSeg *s = currentseg; - lastsegtype = currentseg->type; + do { + if (currentseg->type == TR_STR) { + lastsegtype = TR_STR; + radius[currentseg->id] = FLT_MAX; + } else { + if (currentseg->type != lastsegtype) { + float arc = 0.0f; + tTrackSeg *s = currentseg; + lastsegtype = currentseg->type; - while (s->type == lastsegtype && arc < PI/2.0f) { - arc += s->arc; - s = s->next; - } - lastturnarc = (float) (arc/(PI/2.0f)); - } - radius[currentseg->id] = (float) (currentseg->radius + currentseg->width/2.0)/lastturnarc; - } - currentseg = currentseg->next; - } while (currentseg != startseg); + while (s->type == lastsegtype && arc < PI/2.0f) { + arc += s->arc; + s = s->next; + } + lastturnarc = (float) (arc/(PI/2.0f)); + } + radius[currentseg->id] = (float) (currentseg->radius + currentseg->width/2.0)/lastturnarc; + } + currentseg = currentseg->next; + } while (currentseg != startseg); } @@ -1018,63 +1014,63 @@ void Driver::computeRadius(float *radius) // Compute the length to the end of the segment. float Driver::getDistToSegEnd() { - if (car->_trkPos.seg->type == TR_STR) { - return car->_trkPos.seg->length - car->_trkPos.toStart; - } else { - return (car->_trkPos.seg->arc - car->_trkPos.toStart)*car->_trkPos.seg->radius; - } + if (car->_trkPos.seg->type == TR_STR) { + return car->_trkPos.seg->length - car->_trkPos.toStart; + } else { + return (car->_trkPos.seg->arc - car->_trkPos.toStart)*car->_trkPos.seg->radius; + } } // Compute fitting acceleration. float Driver::getAccel() { - if (car->_gear > 0) { - accelcmd = MIN(1.0f, accelcmd); + if (car->_gear > 0) { + accelcmd = MIN(1.0f, accelcmd); - if (pit->getInPit() && car->_brakeCmd == 0.0f) - { - //float s = pit->toSplineCoord( car->_distFromStartLine ); - + if (pit->getInPit() && car->_brakeCmd == 0.0f) + { + //float s = pit->toSplineCoord( car->_distFromStartLine ); + #if 0 - if (pit->needPitstop()) - { - if (currentspeedsqr > pit->getSpeedlimitSqr()*0.9) - { - accelcmd = MIN(accelcmd, 0.4f); - } - } + if (pit->needPitstop()) + { + if (currentspeedsqr > pit->getSpeedlimitSqr()*0.9) + { + accelcmd = MIN(accelcmd, 0.4f); + } + } #endif - - accelcmd = MIN(accelcmd, 0.6f); - } - else if (fabs(angle) > 0.8 && currentspeed > 10.0f) - accelcmd = MAX(0.0f, MIN(accelcmd, 1.0f - currentspeed/100.0f * fabs(angle))); + + accelcmd = MIN(accelcmd, 0.6f); + } + else if (fabs(angle) > 0.8 && currentspeed > 10.0f) + accelcmd = MAX(0.0f, MIN(accelcmd, 1.0f - currentspeed/100.0f * fabs(angle))); - return accelcmd; - } else { - return 1.0; - } + return accelcmd; + } else { + return 1.0; + } } // If we get lapped reduce accelerator. float Driver::filterOverlap(float accel) { - int i; + int i; - if (!(avoidmode & avoidback)) - { - return accel; - } + if (!(avoidmode & avoidback)) + { + return accel; + } - for (i = 0; i < opponents->getNOpponents(); i++) { - if (opponent[i].getState() & OPP_LETPASS) - { - return accel*0.4f; - } - } - return accel; + for (i = 0; i < opponents->getNOpponents(); i++) { + if (opponent[i].getState() & OPP_LETPASS) + { + return accel*0.4f; + } + } + return accel; } // slows us down to allow a team-member to catch up @@ -1166,81 +1162,81 @@ double Driver::filterTeam(double accel) // Compute initial brake value. float Driver::getBrake() { - // Car drives backward? - if (car->_speed_x < -MAX_UNSTUCK_SPEED) { - // Yes, brake. - return 1.0; - } else { - // We drive forward, normal braking. + // Car drives backward? + if (car->_speed_x < -MAX_UNSTUCK_SPEED) { + // Yes, brake. + return 1.0; + } else { + // We drive forward, normal braking. #ifdef CONTROL_SKILL - brakecmd *= brake_adjust_perc; + brakecmd *= brake_adjust_perc; #endif - return brakecmd; - } + return brakecmd; + } } // Compute gear. int Driver::getGear() { - car->_gearCmd = car->_gear; - if (car->_gear <= 0) { - return 1; - } + car->_gearCmd = car->_gear; + if (car->_gear <= 0) { + return 1; + } #if 1 - // Hymie gear changing - float speed = currentspeed; - float *tRatio = car->_gearRatio + car->_gearOffset; - float rpm = (float) ((speed + 0.5) * tRatio[car->_gear] / car->_wheelRadius(2)); - float down_rpm = (float) (car->_gear > 1 ? (speed + 0.5) * tRatio[car->_gear-1] / car->_wheelRadius(2) : rpm); + // Hymie gear changing + float speed = currentspeed; + float *tRatio = car->_gearRatio + car->_gearOffset; + float rpm = (float) ((speed + 0.5) * tRatio[car->_gear] / car->_wheelRadius(2)); + float down_rpm = (float) (car->_gear > 1 ? (speed + 0.5) * tRatio[car->_gear-1] / car->_wheelRadius(2) : rpm); - float rcu = (car->_gear < 6 && car->_gear >= 0 ? GearRevsChangeUp[car->_gear] : RevsChangeUp); - float rcd = (car->_gear < 6 && car->_gear >= 0 ? GearRevsChangeDown[car->_gear] : RevsChangeDown); - float rcm = (car->_gear < 6 && car->_gear >= 0 ? GearRevsChangeDownMax[car->_gear] : RevsChangeDownMax); + float rcu = (car->_gear < 6 && car->_gear >= 0 ? GearRevsChangeUp[car->_gear] : RevsChangeUp); + float rcd = (car->_gear < 6 && car->_gear >= 0 ? GearRevsChangeDown[car->_gear] : RevsChangeDown); + float rcm = (car->_gear < 6 && car->_gear >= 0 ? GearRevsChangeDownMax[car->_gear] : RevsChangeDownMax); - if (rpm + MAX(0.0, (double) (car->_gear-3) * (car->_gear-3)*5) > car->_enginerpmMax * rcu && car->_gear < MaxGear) - car->_gearCmd = car->_gear + 1; + if (rpm + MAX(0.0, (double) (car->_gear-3) * (car->_gear-3)*5) > car->_enginerpmMax * rcu && car->_gear < MaxGear) + car->_gearCmd = car->_gear + 1; - if (car->_gear > 1 && - rpm < car->_enginerpmMax * rcd && - down_rpm < car->_enginerpmMax * rcm) - car->_gearCmd = car->_gear - 1; + if (car->_gear > 1 && + rpm < car->_enginerpmMax * rcd && + down_rpm < car->_enginerpmMax * rcm) + car->_gearCmd = car->_gear - 1; #else - // BT gear changing - float gr_up = car->_gearRatio[car->_gear + car->_gearOffset]; - float omega = car->_enginerpmRedLine/gr_up; - float wr = car->_wheelRadius(2); + // BT gear changing + float gr_up = car->_gearRatio[car->_gear + car->_gearOffset]; + float omega = car->_enginerpmRedLine/gr_up; + float wr = car->_wheelRadius(2); - if (omega*wr*SHIFT < car->_speed_x) { - car->_gearCmd = car->_gear + 1; - } else { - float gr_down = car->_gearRatio[car->_gear + car->_gearOffset - 1]; - omega = car->_enginerpmRedLine/gr_down; - if (car->_gear > 1 && omega*wr*SHIFT > car->_speed_x + SHIFT_MARGIN) { - car->_gearCmd = car->_gear - 1; - } - } + if (omega*wr*SHIFT < car->_speed_x) { + car->_gearCmd = car->_gear + 1; + } else { + float gr_down = car->_gearRatio[car->_gear + car->_gearOffset - 1]; + omega = car->_enginerpmRedLine/gr_down; + if (car->_gear > 1 && omega*wr*SHIFT > car->_speed_x + SHIFT_MARGIN) { + car->_gearCmd = car->_gear - 1; + } + } #endif - - return car->_gearCmd; + + return car->_gearCmd; } void Driver::setMode( int newmode ) { - if (mode == newmode) - return; + if (mode == newmode) + return; - if (mode == mode_normal || mode == mode_pitting) - { - correcttimer = simtime + 7.0; - //correctlimit = 1000.0; - } + if (mode == mode_normal || mode == mode_pitting) + { + correcttimer = simtime + 7.0; + //correctlimit = 1000.0; + } - if (newmode == mode_avoiding && mode != mode_avoiding) - avoidtime = simtime; + if (newmode == mode_avoiding && mode != mode_avoiding) + avoidtime = simtime; - mode = newmode; + mode = newmode; } void Driver::calcSkill() @@ -1282,331 +1278,331 @@ void Driver::calcSkill() double Driver::getFollowDistance() { - double mindist = 1000.0; + double mindist = 1000.0; - if (mode != mode_normal) - return mindist; + if (mode != mode_normal) + return mindist; - for (int i = 0; i < opponents->getNOpponents(); i++) - { - if (opponent[i].getCarPtr() == car) continue; - //if (opponent[i].getTeam() != TEAM_FRIEND) continue; - if (!(opponent[i].getState() & OPP_FRONT)) - continue; + for (int i = 0; i < opponents->getNOpponents(); i++) + { + if (opponent[i].getCarPtr() == car) continue; + //if (opponent[i].getTeam() != TEAM_FRIEND) continue; + if (!(opponent[i].getState() & OPP_FRONT)) + continue; - if (opponent[i].getDistance() > 5.0) - continue; + if (opponent[i].getDistance() > 5.0) + continue; - mindist = MIN(mindist, opponent[i].getDistance()) - FollowMargin; - } - return mindist; + mindist = MIN(mindist, opponent[i].getDistance()) - FollowMargin; + } + return mindist; } // Compute steer value. float Driver::getSteer(tSituation *s) { - double targetAngle; - memset(rldata, 0, sizeof(LRaceLineData)); - rldata->angle = angle; - rldata->speedangle = speedangle; - rldata->mode = mode; - rldata->avoidmode = avoidmode; - rldata->collision = collision; - rldata->steer = rldata->laststeer = laststeer; - rldata->alone = alone; - rldata->followdist = getFollowDistance(); - rldata->s = s; - rldata->aligned_time = simtime - aligned_timer; - raceline->GetRaceLineData( s, rldata ); - if (FuelSpeedUp) - { - double fuel = (car->_fuel/maxfuel); - fuel = MIN(1.0, fuel * (fuel+0.15)); - rldata->speed += FuelSpeedUp * (1.0 - fuel); - } - double steer = 0.0, tmpsteer = 0.0; - double avoidsteer = 0.0; - double racesteer = (rldata->ksteer); - vec2f target; + double targetAngle; + memset(rldata, 0, sizeof(LRaceLineData)); + rldata->angle = angle; + rldata->speedangle = speedangle; + rldata->mode = mode; + rldata->avoidmode = avoidmode; + rldata->collision = collision; + rldata->steer = rldata->laststeer = laststeer; + rldata->alone = alone; + rldata->followdist = getFollowDistance(); + rldata->s = s; + rldata->aligned_time = simtime - aligned_timer; + raceline->GetRaceLineData( s, rldata ); + if (FuelSpeedUp) + { + double fuel = (car->_fuel/maxfuel); + fuel = MIN(1.0, fuel * (fuel+0.15)); + rldata->speed += FuelSpeedUp * (1.0 - fuel); + } + double steer = 0.0, tmpsteer = 0.0; + double avoidsteer = 0.0; + double racesteer = (rldata->ksteer); + vec2f target; #if 0 - if (SteerLookahead > 6.0f) - { - raceline->GetSteerPoint( (double) SteerLookahead, &target ); - targetAngle = atan2(target.y - car->_pos_Y, target.x - car->_pos_X); - racesteer = calcSteer( targetAngle, 0 ); - double rIf = MIN(1.0, fabs(rldata->rInverse) / SteerMaxRI); - racesteer = racesteer + (rldata->ksteer - racesteer) * rIf; - } + if (SteerLookahead > 6.0f) + { + raceline->GetSteerPoint( (double) SteerLookahead, &target ); + targetAngle = atan2(target.y - car->_pos_Y, target.x - car->_pos_X); + racesteer = calcSteer( targetAngle, 0 ); + double rIf = MIN(1.0, fabs(rldata->rInverse) / SteerMaxRI); + racesteer = racesteer + (rldata->ksteer - racesteer) * rIf; + } #endif - target = getTargetPoint(false); - steer = avoidsteer = racesteer; - lastNSksteer = rldata->NSsteer; + target = getTargetPoint(false); + steer = avoidsteer = racesteer; + lastNSksteer = rldata->NSsteer; - if (mode != mode_normal || SteerLookahead < 6.0f) - { - targetAngle = atan2(target.y - car->_pos_Y, target.x - car->_pos_X); - tmpsteer = calcSteer( targetAngle, 0 ); - } + if (mode != mode_normal || SteerLookahead < 6.0f) + { + targetAngle = atan2(target.y - car->_pos_Y, target.x - car->_pos_X); + tmpsteer = calcSteer( targetAngle, 0 ); + } - if (mode != mode_normal) - { - avoidsteer = tmpsteer; + if (mode != mode_normal) + { + avoidsteer = tmpsteer; - if (mode == mode_pitting) - { - correctlimit = (avoidsteer - racesteer); - return avoidsteer; - } + if (mode == mode_pitting) + { + correctlimit = (avoidsteer - racesteer); + return avoidsteer; + } - //targetAngle = atan2(rldata->target.y - car->_pos_Y, rldata->target.x - car->_pos_X); + //targetAngle = atan2(rldata->target.y - car->_pos_Y, rldata->target.x - car->_pos_X); - allowcorrecting = 0; - if (mode == mode_avoiding && - (!avoidmode || - (avoidmode == avoidright && racesteer > avoidsteer) || - (avoidmode == avoidleft && racesteer < avoidsteer))) - { - // we're avoiding, but trying to steer somewhere the raceline takes us. - // hence we'll just correct towards the raceline instead. - allowcorrecting = 1; - } + allowcorrecting = 0; + if (mode == mode_avoiding && + (!avoidmode || + (avoidmode == avoidright && racesteer > avoidsteer) || + (avoidmode == avoidleft && racesteer < avoidsteer))) + { + // we're avoiding, but trying to steer somewhere the raceline takes us. + // hence we'll just correct towards the raceline instead. + allowcorrecting = 1; + } - bool yr_ok = (fabs(car->_yaw_rate) < 0.1 || (car->_yaw_rate > rldata->rInverse*100-0.1 && car->_yaw_rate < rldata->rInverse*100+0.1)); - bool angle_ok = (angle > rldata->rlangle-0.06 && angle < rldata->rlangle+0.06); - //double rlsteer = (fabs(rldata->rInverse) >= 0.004 ? rldata->rInverse * 12 : 0.0); - bool steer_ok = (racesteerlaststeer-0.05); + bool yr_ok = (fabs(car->_yaw_rate) < 0.1 || (car->_yaw_rate > rldata->rInverse*100-0.1 && car->_yaw_rate < rldata->rInverse*100+0.1)); + bool angle_ok = (angle > rldata->rlangle-0.06 && angle < rldata->rlangle+0.06); + //double rlsteer = (fabs(rldata->rInverse) >= 0.004 ? rldata->rInverse * 12 : 0.0); + bool steer_ok = (racesteerlaststeer-0.05); - double skid = (car->_skid[0] + car->_skid[1] + car->_skid[2] + car->_skid[3]) / 2; - if (mode == mode_correcting) - { - if (lastmode == mode_normal || - (angle_ok && - (simtime > 15.0 || car->_speed_x > 20) && - yr_ok && - skid < 0.1 && - steer_ok && - ((fabs(car->_trkPos.toMiddle) < car->_trkPos.seg->width/2 - 1.0) || car->_speed_x < 10.0) && - (raceline->isOnLine()))) - { - // we're correcting & are now close enough to the raceline to - // switch back to 'normal' mode... - setMode( mode_normal ); - aligned_timer = simtime; - steer = racesteer; - if (DebugMsg & debug_steer) - fprintf(stderr,"ALIGNED steer_ok=%d avsteer=%.3f racest=%.3f\n",steer_ok,avoidsteer,racesteer); - } - else if (DebugMsg & debug_steer) - fprintf(stderr,"NOT ALIGNED %d %d %d %d %.2f %.2f %.2f\n",angle_ok,yr_ok,(skid<0.1),steer_ok,avoidsteer,racesteer,laststeer); - } + double skid = (car->_skid[0] + car->_skid[1] + car->_skid[2] + car->_skid[3]) / 2; + if (mode == mode_correcting) + { + if (lastmode == mode_normal || + (angle_ok && + (simtime > 15.0 || car->_speed_x > 20) && + yr_ok && + skid < 0.1 && + steer_ok && + ((fabs(car->_trkPos.toMiddle) < car->_trkPos.seg->width/2 - 1.0) || car->_speed_x < 10.0) && + (raceline->isOnLine()))) + { + // we're correcting & are now close enough to the raceline to + // switch back to 'normal' mode... + setMode( mode_normal ); + aligned_timer = simtime; + steer = racesteer; + if (DebugMsg & debug_steer) + fprintf(stderr,"ALIGNED steer_ok=%d avsteer=%.3f racest=%.3f\n",steer_ok,avoidsteer,racesteer); + } + else if (DebugMsg & debug_steer) + fprintf(stderr,"NOT ALIGNED %d %d %d %d %.2f %.2f %.2f\n",angle_ok,yr_ok,(skid<0.1),steer_ok,avoidsteer,racesteer,laststeer); + } - if (mode != mode_normal) - { - if (mode != mode_correcting && !allowcorrecting) - { - int flying = checkFlying(); - if (flying & FLYING_FRONT) - { - steer = 0.0; - } - else if (flying & FLYING_BACK) - { - steer /= 3.0; - } - else - { - //correctlimit = 1000.0; - correcttimer = simtime + 7.0; - steer = ( avoidsteer ); - } - double climit = (steer - racesteer); - if (fabs(climit) > fabs(correctlimit)) - correctlimit = climit; - } - else - { - steer = (correctSteering( avoidsteer, racesteer )); - correctlimit = (steer - racesteer); - } - - if (fabs(angle) >= 1.6) - { - if (steer > 0.0) - steer = 1.0; - else - steer = -1.0; - } - } - else - correctlimit = (steer - racesteer); - } - else - { - raceline->NoAvoidSteer(); - lastNSasteer = rldata->NSsteer; - correctlimit = (steer - racesteer); - } + if (mode != mode_normal) + { + if (mode != mode_correcting && !allowcorrecting) + { + int flying = checkFlying(); + if (flying & FLYING_FRONT) + { + steer = 0.0; + } + else if (flying & FLYING_BACK) + { + steer /= 3.0; + } + else + { + //correctlimit = 1000.0; + correcttimer = simtime + 7.0; + steer = ( avoidsteer ); + } + double climit = (steer - racesteer); + if (fabs(climit) > fabs(correctlimit)) + correctlimit = climit; + } + else + { + steer = (correctSteering( avoidsteer, racesteer )); + correctlimit = (steer - racesteer); + } + + if (fabs(angle) >= 1.6) + { + if (steer > 0.0) + steer = 1.0; + else + steer = -1.0; + } + } + else + correctlimit = (steer - racesteer); + } + else + { + raceline->NoAvoidSteer(); + lastNSasteer = rldata->NSsteer; + correctlimit = (steer - racesteer); + } - if (mode == mode_avoiding && - (lastmode == mode_normal || lastmode == mode_correcting) && - !((avoidmode & avoidright) && (avoidmode & avoidleft))) - { - // if we're only avoiding on one side, and racesteer avoids more than avoidsteer, and just prior we - // weren't avoiding, return to prior mode. - if ((racesteer >= steer && avoidmode == avoidright) || - (racesteer <= steer && avoidmode == avoidleft)) - { - if (lastmode == mode_normal) - steer = racesteer; - setMode(lastmode); - } - } + if (mode == mode_avoiding && + (lastmode == mode_normal || lastmode == mode_correcting) && + !((avoidmode & avoidright) && (avoidmode & avoidleft))) + { + // if we're only avoiding on one side, and racesteer avoids more than avoidsteer, and just prior we + // weren't avoiding, return to prior mode. + if ((racesteer >= steer && avoidmode == avoidright) || + (racesteer <= steer && avoidmode == avoidleft)) + { + if (lastmode == mode_normal) + steer = racesteer; + setMode(lastmode); + } + } - return steer; + return steer; } double Driver::calcSteer( double targetAngle, int rl ) { #if 1 - if (mode != mode_pitting) - { - float kksteer = raceline->getAvoidSteer(myoffset, rldata); - return kksteer; - } + if (mode != mode_pitting) + { + float kksteer = raceline->getAvoidSteer(myoffset, rldata); + return kksteer; + } #endif - double rearskid = MAX(0.0, MAX(car->_skid[2], car->_skid[3]) - MAX(car->_skid[0], car->_skid[1])) + MAX(car->_skid[2], car->_skid[3]) * fabs(angle)*0.9; - double steer = 0.0; + double rearskid = MAX(0.0, MAX(car->_skid[2], car->_skid[3]) - MAX(car->_skid[0], car->_skid[1])) + MAX(car->_skid[2], car->_skid[3]) * fabs(angle)*0.9; + double steer = 0.0; #if 0 // olethros steering - double steer_direction = targetAngle - car->_yaw - 0.1 * car->_yaw_rate; + double steer_direction = targetAngle - car->_yaw - 0.1 * car->_yaw_rate; - double avoidance = 0.0; - if (!(pit->getInPit())) - { - if (car->_trkPos.toRight < car->_dimension_y) - avoidance = tanh(0.2 * (car->_dimension_y - car->_trkPos.toRight)); - else if (car->_trkPos.toLeft < car->_dimension_y) - avoidance = tanh(0.2 * (car->_trkPos.toLeft - car->_dimension_y)); - } + double avoidance = 0.0; + if (!(pit->getInPit())) + { + if (car->_trkPos.toRight < car->_dimension_y) + avoidance = tanh(0.2 * (car->_dimension_y - car->_trkPos.toRight)); + else if (car->_trkPos.toLeft < car->_dimension_y) + avoidance = tanh(0.2 * (car->_trkPos.toLeft - car->_dimension_y)); + } - tTrackSeg *seg = car->_trkPos.seg; - double correct_drift = -0.01 * atan2(car->_speed_Y, car->_speed_X); - NORM_PI_PI(steer_direction); + tTrackSeg *seg = car->_trkPos.seg; + double correct_drift = -0.01 * atan2(car->_speed_Y, car->_speed_X); + NORM_PI_PI(steer_direction); - steer = avoidance + correct_drift + steer_direction/car->_steerLock; + steer = avoidance + correct_drift + steer_direction/car->_steerLock; #else // old ki steering - double steer_direction = targetAngle - car->_yaw - car->_speed_x/300 * car->_yaw_rate; + double steer_direction = targetAngle - car->_yaw - car->_speed_x/300 * car->_yaw_rate; - NORM_PI_PI(steer_direction); - if (DebugMsg & debug_steer) - fprintf(stderr,"STEER tm%.2f off%.2f sd%.3f",car->_trkPos.toMiddle,myoffset,steer_direction); + NORM_PI_PI(steer_direction); + if (DebugMsg & debug_steer) + fprintf(stderr,"STEER tm%.2f off%.2f sd%.3f",car->_trkPos.toMiddle,myoffset,steer_direction); - if (car->_speed_x > 10.0 && mode != mode_normal && mode != mode_pitting) - { - double limit = MAX(20.0, 90.0 - car->_speed_x) * (((avoidmode & avoidside) ? 0.0074 : 0.0045) * SmoothSteer); - double rgtlimit = limit, lftlimit = limit; - if (laststeer_direction > 0.0) rgtlimit = MIN(laststeer_direction, rgtlimit*2); - if (laststeer_direction < 0.0) lftlimit = MIN(-laststeer_direction, lftlimit*2); + if (car->_speed_x > 10.0 && mode != mode_normal && mode != mode_pitting) + { + double limit = MAX(20.0, 90.0 - car->_speed_x) * (((avoidmode & avoidside) ? 0.0074 : 0.0045) * SmoothSteer); + double rgtlimit = limit, lftlimit = limit; + if (laststeer_direction > 0.0) rgtlimit = MIN(laststeer_direction, rgtlimit*2); + if (laststeer_direction < 0.0) lftlimit = MIN(-laststeer_direction, lftlimit*2); - steer_direction = MAX(laststeer_direction - rgtlimit, MIN(laststeer_direction + lftlimit, steer_direction)); + steer_direction = MAX(laststeer_direction - rgtlimit, MIN(laststeer_direction + lftlimit, steer_direction)); #if 1 - double speedsteer = (80.0 - MIN(70.0, MAX(40.0, currentspeed))) / - ((185.0 * MIN(1.0, car->_steerLock / 0.785)) + - (185.0 * (MIN(1.3, MAX(1.0, 1.0 + rearskid))) - 185.0)); - if (fabs(steer_direction) > speedsteer) - { - steer_direction = MAX(-speedsteer, MIN(speedsteer, steer_direction)); - } + double speedsteer = (80.0 - MIN(70.0, MAX(40.0, currentspeed))) / + ((185.0 * MIN(1.0, car->_steerLock / 0.785)) + + (185.0 * (MIN(1.3, MAX(1.0, 1.0 + rearskid))) - 185.0)); + if (fabs(steer_direction) > speedsteer) + { + steer_direction = MAX(-speedsteer, MIN(speedsteer, steer_direction)); + } #endif - } - laststeer_direction = steer_direction; + } + laststeer_direction = steer_direction; - steer = (steer_direction/car->_steerLock); - if (DebugMsg & debug_steer) - fprintf(stderr,"/sd%.3f a%.3f",steer_direction,steer); + steer = (steer_direction/car->_steerLock); + if (DebugMsg & debug_steer) + fprintf(stderr,"/sd%.3f a%.3f",steer_direction,steer); - if (DebugMsg & debug_steer) - fprintf(stderr," b%.3f",steer); + if (DebugMsg & debug_steer) + fprintf(stderr," b%.3f",steer); - lastNSasteer = steer; + lastNSasteer = steer; - double nextangle = angle + car->_yaw_rate/3; - if (fabs(nextangle) > fabs(speedangle)) - { - // steer into the skid - //double sa = MAX(-0.3, MIN(0.3, speedangle/3)); - //double anglediff = (sa - angle) * (0.3 + fabs(angle)/6); - double anglediff = (speedangle - nextangle) * (0.1 + fabs(nextangle)/6); - steer += (float) (anglediff*SkidSteer); - } + double nextangle = angle + car->_yaw_rate/3; + if (fabs(nextangle) > fabs(speedangle)) + { + // steer into the skid + //double sa = MAX(-0.3, MIN(0.3, speedangle/3)); + //double anglediff = (sa - angle) * (0.3 + fabs(angle)/6); + double anglediff = (speedangle - nextangle) * (0.1 + fabs(nextangle)/6); + steer += (float) (anglediff*SkidSteer); + } - if (fabs(angle) > 1.2) - { - if (steer > 0.0f) - steer = 1.0f; - else - steer = -1.0f; - } - else if (fabs(car->_trkPos.toMiddle) - car->_trkPos.seg->width/2 > 2.0) - { - steer = (float) MIN(1.0f, MAX(-1.0f, steer * (1.0f + (fabs(car->_trkPos.toMiddle) - car->_trkPos.seg->width/2)/14 + fabs(angle)/2))); - } + if (fabs(angle) > 1.2) + { + if (steer > 0.0f) + steer = 1.0f; + else + steer = -1.0f; + } + else if (fabs(car->_trkPos.toMiddle) - car->_trkPos.seg->width/2 > 2.0) + { + steer = (float) MIN(1.0f, MAX(-1.0f, steer * (1.0f + (fabs(car->_trkPos.toMiddle) - car->_trkPos.seg->width/2)/14 + fabs(angle)/2))); + } #endif // old ki steering - if (DebugMsg & debug_steer) - fprintf(stderr," d%.3f",steer); + if (DebugMsg & debug_steer) + fprintf(stderr," d%.3f",steer); - if (mode != mode_pitting) - { - // limit how far we can steer against last steer... - double limit = 0.0; - limit = ((90.0 - MAX(40.0, MIN(60.0, car->_speed_x))) / (120)) * SmoothSteer; // (130); - if (fabs(laststeer) > fabs(steer)) - limit = MAX(limit, fabs(laststeer)/2); - steer = MAX(laststeer-limit, MIN(laststeer+limit, steer)); - //steer = MAX(rldata->steer-limit, MIN(rldata->steer+limit, steer)); + if (mode != mode_pitting) + { + // limit how far we can steer against last steer... + double limit = 0.0; + limit = ((90.0 - MAX(40.0, MIN(60.0, car->_speed_x))) / (120)) * SmoothSteer; // (130); + if (fabs(laststeer) > fabs(steer)) + limit = MAX(limit, fabs(laststeer)/2); + steer = MAX(laststeer-limit, MIN(laststeer+limit, steer)); + //steer = MAX(rldata->steer-limit, MIN(rldata->steer+limit, steer)); #if 1 - if (simtime > 3.0) - { - // and against raceline... - double climit = fabs(correctlimit); + if (simtime > 3.0) + { + // and against raceline... + double climit = fabs(correctlimit); #if 0 - if (climit > 0.0 && angle - rldata->rlangle > 0.0) - climit += (angle - rldata->rlangle)/2; - else if (climit < 0.0 && angle - rldata->rlangle < 0.0) - climit -= fabs(angle - rldata->rlangle)/2; + if (climit > 0.0 && angle - rldata->rlangle > 0.0) + climit += (angle - rldata->rlangle)/2; + else if (climit < 0.0 && angle - rldata->rlangle < 0.0) + climit -= fabs(angle - rldata->rlangle)/2; #endif - double limitchange = ((90.0 - MAX(40.0, MIN(60.0, car->_speed_x))) / ((avoidmode & avoidside) ? 130 : 200)) * 3; - climit += limitchange; - steer = MAX(rldata->ksteer-climit, MIN(rldata->ksteer+climit, steer)); - } + double limitchange = ((90.0 - MAX(40.0, MIN(60.0, car->_speed_x))) / ((avoidmode & avoidside) ? 130 : 200)) * 3; + climit += limitchange; + steer = MAX(rldata->ksteer-climit, MIN(rldata->ksteer+climit, steer)); + } #endif - steer = smoothSteering(steer); - } + steer = smoothSteering(steer); + } #if 0 - else if (currentspeed > MAX(25.0, pit->getSpeedlimit())) - { - // stop sudden steer changes while pitting - double limit = MAX(0.1, (40 - fabs(currentspeed - pit->getSpeedlimit())) * 0.025); - steer = MIN(limit, MAX(-limit, steer)); - } + else if (currentspeed > MAX(25.0, pit->getSpeedlimit())) + { + // stop sudden steer changes while pitting + double limit = MAX(0.1, (40 - fabs(currentspeed - pit->getSpeedlimit())) * 0.025); + steer = MIN(limit, MAX(-limit, steer)); + } #endif - if (DebugMsg & debug_steer) - fprintf(stderr," e%.3f\n",steer); + if (DebugMsg & debug_steer) + fprintf(stderr," e%.3f\n",steer); - return steer; + return steer; } int Driver::checkFlying() @@ -1641,1806 +1637,1806 @@ int Driver::checkFlying() float Driver::correctSteering( float avoidsteer, float racesteer ) { - if (simtime < 15.0 && car->_speed_x < 20.0) - return avoidsteer; - if (simtime < CorrectDelay) - return avoidsteer; + if (simtime < 15.0 && car->_speed_x < 20.0) + return avoidsteer; + if (simtime < CorrectDelay) + return avoidsteer; - float steer = avoidsteer; - //float accel = MIN(0.0f, car->_accel_x); - double speed = 50.0; //MAX(50.0, currentspeed); - double changelimit = MIN(raceline->correctLimit(avoidsteer, racesteer), (((120.0-currentspeed)/6000) * (0.1 + fabs(rldata->mInverse/4)))) * SmoothSteer; + float steer = avoidsteer; + //float accel = MIN(0.0f, car->_accel_x); + double speed = 50.0; //MAX(50.0, currentspeed); + double changelimit = MIN(raceline->correctLimit(avoidsteer, racesteer), (((120.0-currentspeed)/6000) * (0.1 + fabs(rldata->mInverse/4)))) * SmoothSteer; if (DebugMsg & debug_steer) fprintf(stderr,"CORRECT: cl=%.3f as=%.3f rs=%.3f NS=%.3f",correctlimit,avoidsteer,racesteer,lastNSasteer); - if (/*mode == mode_correcting &&*/ simtime > 2.0f) - { - // move steering towards racesteer... - if (correctlimit < 900.0) - { - if (steer < racesteer) - { - if (correctlimit >= 0.0) - { - //steer = (float) MIN(racesteer, steer + correctlimit); + if (/*mode == mode_correcting &&*/ simtime > 2.0f) + { + // move steering towards racesteer... + if (correctlimit < 900.0) + { + if (steer < racesteer) + { + if (correctlimit >= 0.0) + { + //steer = (float) MIN(racesteer, steer + correctlimit); if (DebugMsg & debug_steer) fprintf(stderr," RA%.3f",racesteer); - steer = racesteer; - lastNSasteer = rldata->NSsteer; - } - else - { - steer = (float) MIN(racesteer, MAX(steer, racesteer + correctlimit)); - lastNSasteer = (float) MIN(rldata->NSsteer, MAX(lastNSasteer, rldata->NSsteer + correctlimit)); + steer = racesteer; + lastNSasteer = rldata->NSsteer; + } + else + { + steer = (float) MIN(racesteer, MAX(steer, racesteer + correctlimit)); + lastNSasteer = (float) MIN(rldata->NSsteer, MAX(lastNSasteer, rldata->NSsteer + correctlimit)); if (DebugMsg & debug_steer) fprintf(stderr," MA%.3f",steer); - } - } - else - { - if (correctlimit <= 0.0) - { - //steer = (float) MAX(racesteer, steer-correctlimit); - steer = racesteer; - lastNSasteer = rldata->NSsteer; + } + } + else + { + if (correctlimit <= 0.0) + { + //steer = (float) MAX(racesteer, steer-correctlimit); + steer = racesteer; + lastNSasteer = rldata->NSsteer; if (DebugMsg & debug_steer) fprintf(stderr," RB%.3f",racesteer); - } - else - { - steer = (float) MAX(racesteer, MIN(steer, racesteer + correctlimit)); - lastNSasteer = (float) MAX(rldata->NSsteer, MIN(lastNSasteer, rldata->NSsteer + correctlimit)); + } + else + { + steer = (float) MAX(racesteer, MIN(steer, racesteer + correctlimit)); + lastNSasteer = (float) MAX(rldata->NSsteer, MIN(lastNSasteer, rldata->NSsteer + correctlimit)); if (DebugMsg & debug_steer) fprintf(stderr," MB%.3f",steer); - } - } - } - //else - { - speed -= avgaccel_x/10; - speed = MAX(55.0, MIN(150.0, speed + (speed*speed/55))); - double rInverse = rldata->mInverse * (avgaccel_x<0.0 ? 1.0 + fabs(avgaccel_x)/10.0 : 1.0); - double correctspeed = 0.5; - if ((rInverse > 0.0 && racesteer > steer) || (rInverse < 0.0 && racesteer < steer)) - correctspeed += rInverse*110; + } + } + } + //else + { + speed -= avgaccel_x/10; + speed = MAX(55.0, MIN(150.0, speed + (speed*speed/55))); + double rInverse = rldata->mInverse * (avgaccel_x<0.0 ? 1.0 + fabs(avgaccel_x)/10.0 : 1.0); + double correctspeed = 0.5; + if ((rInverse > 0.0 && racesteer > steer) || (rInverse < 0.0 && racesteer < steer)) + correctspeed += rInverse*110; - if (racesteer > steer) - //steer = (float) MIN(racesteer, steer + (((155.0-speed)/10000) * correctspeed)); - steer = (float) MIN(racesteer, steer + changelimit); - else - //steer = (float) MAX(racesteer, steer - (((155.0-speed)/10000) * correctspeed)); - steer = (float) MAX(racesteer, steer - changelimit); - if (fabs(racesteer) < fabs(steer)) - { - if (racesteer > steer) - steer += (fabs(steer) - fabs(racesteer)) / 2; - else - steer -= (fabs(steer) - fabs(racesteer)) / 2; - } + if (racesteer > steer) + //steer = (float) MIN(racesteer, steer + (((155.0-speed)/10000) * correctspeed)); + steer = (float) MIN(racesteer, steer + changelimit); + else + //steer = (float) MAX(racesteer, steer - (((155.0-speed)/10000) * correctspeed)); + steer = (float) MAX(racesteer, steer - changelimit); + if (fabs(racesteer) < fabs(steer)) + { + if (racesteer > steer) + steer += (fabs(steer) - fabs(racesteer)) / 2; + else + steer -= (fabs(steer) - fabs(racesteer)) / 2; + } - if (lastNSksteer > lastNSasteer) - //lastNSasteer = (float) MIN(rldata->NSsteer, lastNSasteer + (((155.0-speed)/10000) * correctspeed)); - lastNSasteer = (float) MIN(rldata->NSsteer, lastNSasteer + changelimit); - else - //lastNSasteer = (float) MAX(rldata->NSsteer, lastNSasteer - (((155.0-speed)/10000) * correctspeed)); - lastNSasteer = (float) MAX(rldata->NSsteer, lastNSasteer - changelimit); + if (lastNSksteer > lastNSasteer) + //lastNSasteer = (float) MIN(rldata->NSsteer, lastNSasteer + (((155.0-speed)/10000) * correctspeed)); + lastNSasteer = (float) MIN(rldata->NSsteer, lastNSasteer + changelimit); + else + //lastNSasteer = (float) MAX(rldata->NSsteer, lastNSasteer - (((155.0-speed)/10000) * correctspeed)); + lastNSasteer = (float) MAX(rldata->NSsteer, lastNSasteer - changelimit); if (DebugMsg & debug_steer) fprintf(stderr," I%.3f",steer); - } - - } + } + + } if (DebugMsg & debug_steer) fprintf(stderr," %.3f NS=%.3f\n",steer,lastNSasteer); - return steer; + return steer; } float Driver::smoothSteering( float steercmd ) { - if (pitoffset != -100.0f) - return steercmd; + if (pitoffset != -100.0f) + return steercmd; #if 1 - // experimental smoothing code, beware!!! - double steer = steercmd; - double stdelta = steer - laststeer;//car->_steerCmd; - double maxSpeed = MAX(200.0, 300.0 - car->_speed_x*2) * (PI/180.0); + // experimental smoothing code, beware!!! + double steer = steercmd; + double stdelta = steer - laststeer;//car->_steerCmd; + double maxSpeed = MAX(200.0, 300.0 - car->_speed_x*2) * (PI/180.0); - //if (mode == mode_normal) - // maxSpeed = 200.0 * (PI / 180.0); + //if (mode == mode_normal) + // maxSpeed = 200.0 * (PI / 180.0); - if ((fabs(stdelta) / deltaTime) > maxSpeed) - steer = SIGN(stdelta) * maxSpeed * deltaTime + laststeer;//car->_steerCmd; + if ((fabs(stdelta) / deltaTime) > maxSpeed) + steer = SIGN(stdelta) * maxSpeed * deltaTime + laststeer;//car->_steerCmd; - steercmd = steer; + steercmd = steer; - // limit amount of steer according to speed & raceline - double a_error_factor = ((rldata->exiting && rldata->outsideline) ? 0.9 : 0.8); - double smangle = angle * (0.5 + fabs(angle*2)); - double angle_error = (smangle - rldata->rlangle/2) * a_error_factor; - double lstlimit = MAX(40.0, 80.0 - car->_speed_x) * 0.004 - MIN(0.0, MAX(-0.5, angle_error)); - double rstlimit = -(MAX(40.0, 80.0 - car->_speed_x) * 0.004 + MAX(0.0, MIN(0.5, angle_error))); - double strate = 61.0 + lastaccel*10; + // limit amount of steer according to speed & raceline + double a_error_factor = ((rldata->exiting && rldata->outsideline) ? 0.9 : 0.8); + double smangle = angle * (0.5 + fabs(angle*2)); + double angle_error = (smangle - rldata->rlangle/2) * a_error_factor; + double lstlimit = MAX(40.0, 80.0 - car->_speed_x) * 0.004 - MIN(0.0, MAX(-0.5, angle_error)); + double rstlimit = -(MAX(40.0, 80.0 - car->_speed_x) * 0.004 + MAX(0.0, MIN(0.5, angle_error))); + double strate = 61.0 + lastaccel*10; - if (rldata->rInverse*strate > lstlimit) - lstlimit = rldata->rInverse*strate; - if (rldata->rInverse*strate < rstlimit) - rstlimit = rldata->rInverse*strate; - steercmd = MAX(rstlimit, MIN(lstlimit, steercmd)); + if (rldata->rInverse*strate > lstlimit) + lstlimit = rldata->rInverse*strate; + if (rldata->rInverse*strate < rstlimit) + rstlimit = rldata->rInverse*strate; + steercmd = MAX(rstlimit, MIN(lstlimit, steercmd)); #endif - return steercmd; + return steercmd; #if 0 - // try to limit sudden changes in steering to avoid loss of control through oversteer. - double lftspeedfactor = ((((60.0 - (MAX(40.0, MIN(70.0, currentspeed + MAX(0.0, car->_accel_x*5))) - 25)) / 300) * 2.5) / 0.585) * SmoothSteer; - double rgtspeedfactor = lftspeedfactor; + // try to limit sudden changes in steering to avoid loss of control through oversteer. + double lftspeedfactor = ((((60.0 - (MAX(40.0, MIN(70.0, currentspeed + MAX(0.0, car->_accel_x*5))) - 25)) / 300) * 2.5) / 0.585) * SmoothSteer; + double rgtspeedfactor = lftspeedfactor; - if (fabs(steercmd) < fabs(laststeer) && fabs(steercmd) <= fabs(laststeer - steercmd)) - { - lftspeedfactor *= 2; - rgtspeedfactor *= 2; - } + if (fabs(steercmd) < fabs(laststeer) && fabs(steercmd) <= fabs(laststeer - steercmd)) + { + lftspeedfactor *= 2; + rgtspeedfactor *= 2; + } - lftspeedfactor -= MIN(0.0f, car->_yaw_rate/10); - rgtspeedfactor += MAX(0.0f, car->_yaw_rate/10); + lftspeedfactor -= MIN(0.0f, car->_yaw_rate/10); + rgtspeedfactor += MAX(0.0f, car->_yaw_rate/10); - steercmd = (float) MAX(laststeer - rgtspeedfactor, MIN(laststeer + lftspeedfactor, steercmd)); - return steercmd; + steercmd = (float) MAX(laststeer - rgtspeedfactor, MIN(laststeer + lftspeedfactor, steercmd)); + return steercmd; #endif } // Compute the clutch value. float Driver::getClutch() { - if (1 || car->_gearCmd > 1) - { - float maxtime = MAX(0.06f, 0.32f - ((float) car->_gearCmd / 65.0f)); - if (car->_gear != car->_gearCmd && car->_gearCmd < MaxGear) - clutchtime = maxtime; - if (clutchtime > 0.0f) - clutchtime -= (float) (RCM_MAX_DT_ROBOTS * (0.02f + ((float) car->_gearCmd / 8.0f))); - return 2.0f * clutchtime; - } else { - float drpm = car->_enginerpm - car->_enginerpmRedLine/2.0f; - float ctlimit = 0.9f; - if (car->_gearCmd > 1) - ctlimit -= 0.15f + (float) car->_gearCmd/13.0f; - clutchtime = MIN(ctlimit, clutchtime); - if (car->_gear != car->_gearCmd) - clutchtime = 0.0f; - float clutcht = (ctlimit - clutchtime) / ctlimit; - if (car->_gear == 1 && car->_accelCmd > 0.0f) { - clutchtime += (float) RCM_MAX_DT_ROBOTS; - } + if (1 || car->_gearCmd > 1) + { + float maxtime = MAX(0.06f, 0.32f - ((float) car->_gearCmd / 65.0f)); + if (car->_gear != car->_gearCmd && car->_gearCmd < MaxGear) + clutchtime = maxtime; + if (clutchtime > 0.0f) + clutchtime -= (float) (RCM_MAX_DT_ROBOTS * (0.02f + ((float) car->_gearCmd / 8.0f))); + return 2.0f * clutchtime; + } else { + float drpm = car->_enginerpm - car->_enginerpmRedLine/2.0f; + float ctlimit = 0.9f; + if (car->_gearCmd > 1) + ctlimit -= 0.15f + (float) car->_gearCmd/13.0f; + clutchtime = MIN(ctlimit, clutchtime); + if (car->_gear != car->_gearCmd) + clutchtime = 0.0f; + float clutcht = (ctlimit - clutchtime) / ctlimit; + if (car->_gear == 1 && car->_accelCmd > 0.0f) { + clutchtime += (float) RCM_MAX_DT_ROBOTS; + } - if (car->_gearCmd == 1 || drpm > 0) { - float speedr; - if (car->_gearCmd == 1) { - // Compute corresponding speed to engine rpm. - float omega = car->_enginerpmRedLine/car->_gearRatio[car->_gear + car->_gearOffset]; - float wr = car->_wheelRadius(2); - speedr = (CLUTCH_SPEED + MAX(0.0f, car->_speed_x))/fabs(wr*omega); - float clutchr = MAX(0.0f, (1.0f - speedr*2.0f*drpm/car->_enginerpmRedLine)) * (car->_gearCmd == 1 ? 0.95f : (0.7f - (float)(car->_gearCmd)/30.0f)); - return MIN(clutcht, clutchr); - } else { - // For the reverse gear. - clutchtime = 0.0f; - return 0.0f; - } - } else { - return clutcht; - } - } + if (car->_gearCmd == 1 || drpm > 0) { + float speedr; + if (car->_gearCmd == 1) { + // Compute corresponding speed to engine rpm. + float omega = car->_enginerpmRedLine/car->_gearRatio[car->_gear + car->_gearOffset]; + float wr = car->_wheelRadius(2); + speedr = (CLUTCH_SPEED + MAX(0.0f, car->_speed_x))/fabs(wr*omega); + float clutchr = MAX(0.0f, (1.0f - speedr*2.0f*drpm/car->_enginerpmRedLine)) * (car->_gearCmd == 1 ? 0.95f : (0.7f - (float)(car->_gearCmd)/30.0f)); + return MIN(clutcht, clutchr); + } else { + // For the reverse gear. + clutchtime = 0.0f; + return 0.0f; + } + } else { + return clutcht; + } + } } // move offset to allow for bends (if any) float Driver::adjustOffset(float offset) { return offset; - float adjustment = (float) (rldata->rInverse * 10); - float width = (float) (car->_trkPos.seg->width * 0.75); + float adjustment = (float) (rldata->rInverse * 10); + float width = (float) (car->_trkPos.seg->width * 0.75); #if 0 #endif - //if (mode==mode_avoiding) - { - // we want to adjust outwards a bit if in close to the corner (more if avoiding - // a car on the inside, way less otherwise). If the car is on the outside third - // of the track we don't want to adjust at all. Inbetween the inside third and - // the outside third we want a gradual decline in the adjust amount... - if (adjustment < 0.0) - { - if (car->_trkPos.toRight > width*0.7) - adjustment = 0.0; - else if (car->_trkPos.toRight > width*0.3) - adjustment *= MAX(0.0, 1.0 - ((car->_trkPos.toRight-width*0.3)/width*0.4)); - } - else if (adjustment > 0.0) - { - if (car->_trkPos.toLeft > width*0.7) - adjustment = 0.0; - else if (car->_trkPos.toLeft > width*0.3) - adjustment *= MAX(0.0, 1.0 - ((car->_trkPos.toLeft-width*0.3)/width*0.4)); - } + //if (mode==mode_avoiding) + { + // we want to adjust outwards a bit if in close to the corner (more if avoiding + // a car on the inside, way less otherwise). If the car is on the outside third + // of the track we don't want to adjust at all. Inbetween the inside third and + // the outside third we want a gradual decline in the adjust amount... + if (adjustment < 0.0) + { + if (car->_trkPos.toRight > width*0.7) + adjustment = 0.0; + else if (car->_trkPos.toRight > width*0.3) + adjustment *= MAX(0.0, 1.0 - ((car->_trkPos.toRight-width*0.3)/width*0.4)); + } + else if (adjustment > 0.0) + { + if (car->_trkPos.toLeft > width*0.7) + adjustment = 0.0; + else if (car->_trkPos.toLeft > width*0.3) + adjustment *= MAX(0.0, 1.0 - ((car->_trkPos.toLeft-width*0.3)/width*0.4)); + } #if 0 - if (adjustment < 0.0 && car->_trkPos.toLeft < width) - adjustment *= MAX(0.1, MIN(1.0, car->_trkPos.toLeft*1.6 / width)); - else if (adjustment > 0.0 && car->_trkPos.toRight < width) - adjustment *= MAX(0.1, MIN(1.0, car->_trkPos.toRight*1.6 / width)); + if (adjustment < 0.0 && car->_trkPos.toLeft < width) + adjustment *= MAX(0.1, MIN(1.0, car->_trkPos.toLeft*1.6 / width)); + else if (adjustment > 0.0 && car->_trkPos.toRight < width) + adjustment *= MAX(0.1, MIN(1.0, car->_trkPos.toRight*1.6 / width)); #endif - //adjustment *= 1.0 + MAX(0.0, currentspeed / rldata->avspeed)*2; - if ((avoidmode == avoidright && adjustment < 0.0) || - (avoidmode == avoidleft && adjustment > 0.0)) - adjustment *= 1; - else - adjustment /= 2; - } + //adjustment *= 1.0 + MAX(0.0, currentspeed / rldata->avspeed)*2; + if ((avoidmode == avoidright && adjustment < 0.0) || + (avoidmode == avoidleft && adjustment > 0.0)) + adjustment *= 1; + else + adjustment /= 2; + } - double speed = currentspeed; - double xspeed = MIN(rldata->speed, rldata->avspeed); - if (speed < xspeed) - adjustment *= MIN(2.0, xspeed / speed); + double speed = currentspeed; + double xspeed = MIN(rldata->speed, rldata->avspeed); + if (speed < xspeed) + adjustment *= MIN(2.0, xspeed / speed); - offset -= adjustment; + offset -= adjustment; - return offset; + return offset; } // Compute target point for steering. vec2f Driver::getTargetPoint(bool use_lookahead, double targetoffset) { - tTrackSeg *seg = car->_trkPos.seg; - float length = getDistToSegEnd(); - float offset = (targetoffset > -99 ? targetoffset - : (skipcount < 2 ? getOffset() : myoffset)); - double time_mod = 1.0; - pitoffset = -100.0f; + tTrackSeg *seg = car->_trkPos.seg; + float length = getDistToSegEnd(); + float offset = (targetoffset > -99 ? targetoffset + : (skipcount < 2 ? getOffset() : myoffset)); + double time_mod = 1.0; + pitoffset = -100.0f; - if (pit->getInPit()) { - // To stop in the pit we need special lookahead values. - if (currentspeedsqr > pit->getSpeedlimitSqr()) { - lookahead = PIT_LOOKAHEAD + car->_speed_x*LOOKAHEAD_FACTOR; - } else { - lookahead = PIT_LOOKAHEAD; - } - } else { - // Usual lookahead. - lookahead = (float) rldata->lookahead; + if (pit->getInPit()) { + // To stop in the pit we need special lookahead values. + if (currentspeedsqr > pit->getSpeedlimitSqr()) { + lookahead = PIT_LOOKAHEAD + car->_speed_x*LOOKAHEAD_FACTOR; + } else { + lookahead = PIT_LOOKAHEAD; + } + } else { + // Usual lookahead. + lookahead = (float) rldata->lookahead; - double speed = MAX(20.0, currentspeed);// + MAX(0.0, car->_accel_x)); - lookahead = (float) (LOOKAHEAD_CONST * 1.2 + speed * 0.75); - lookahead = MIN(lookahead, (float) (LOOKAHEAD_CONST + ((speed*(speed/7)) * 0.15))); - lookahead *= SteerLookahead; - double ri = (fabs(rldata->mInverse) < fabs(rldata->rInverse) ? rldata->mInverse : rldata->rInverse); - //double amI = MIN(0.05, MAX(-0.05, (rldata->amInverse))); - double amI = MIN(0.05, MAX(-0.05, (ri))); - double famI = fabs(amI); + double speed = MAX(20.0, currentspeed);// + MAX(0.0, car->_accel_x)); + lookahead = (float) (LOOKAHEAD_CONST * 1.2 + speed * 0.75); + lookahead = MIN(lookahead, (float) (LOOKAHEAD_CONST + ((speed*(speed/7)) * 0.15))); + lookahead *= SteerLookahead; + double ri = (fabs(rldata->mInverse) < fabs(rldata->rInverse) ? rldata->mInverse : rldata->rInverse); + //double amI = MIN(0.05, MAX(-0.05, (rldata->amInverse))); + double amI = MIN(0.05, MAX(-0.05, (ri))); + double famI = fabs(amI); - if (famI > 0.0) - { - double cornerfx = 1.0; - double toMid = car->_trkPos.toMiddle + speedangle * 20; - double modfactor = (currentspeed / rldata->avspeed); - modfactor *= modfactor; - if (amI > 0.0) - { - if (toMid < 0.0) - { - cornerfx += famI * (MIN(track->width/2, fabs(toMid)) / track->width) * 50; - time_mod += famI * (MIN(track->width/2, fabs(toMid)) / track->width) * 50; - } - else - { - cornerfx -= MIN(0.7, famI * (MIN(track->width/2, fabs(toMid)) / track->width) * 30); - time_mod -= MIN(0.7, famI * (MIN(track->width/2, fabs(toMid)) / track->width) * 30 * modfactor); - } - } - else - { - if (toMid > 0.0) - { - cornerfx += famI * (MIN(track->width/2, fabs(toMid)) / track->width) * 50; - time_mod += famI * (MIN(track->width/2, fabs(toMid)) / track->width) * 50; - } - else - { - cornerfx -= MIN(0.7, famI * (MIN(track->width/2, fabs(toMid)) / track->width) * 30); - time_mod -= MIN(0.7, famI * (MIN(track->width/2, fabs(toMid)) / track->width) * 30 * modfactor); - } - } - lookahead *= cornerfx; - } + if (famI > 0.0) + { + double cornerfx = 1.0; + double toMid = car->_trkPos.toMiddle + speedangle * 20; + double modfactor = (currentspeed / rldata->avspeed); + modfactor *= modfactor; + if (amI > 0.0) + { + if (toMid < 0.0) + { + cornerfx += famI * (MIN(track->width/2, fabs(toMid)) / track->width) * 50; + time_mod += famI * (MIN(track->width/2, fabs(toMid)) / track->width) * 50; + } + else + { + cornerfx -= MIN(0.7, famI * (MIN(track->width/2, fabs(toMid)) / track->width) * 30); + time_mod -= MIN(0.7, famI * (MIN(track->width/2, fabs(toMid)) / track->width) * 30 * modfactor); + } + } + else + { + if (toMid > 0.0) + { + cornerfx += famI * (MIN(track->width/2, fabs(toMid)) / track->width) * 50; + time_mod += famI * (MIN(track->width/2, fabs(toMid)) / track->width) * 50; + } + else + { + cornerfx -= MIN(0.7, famI * (MIN(track->width/2, fabs(toMid)) / track->width) * 30); + time_mod -= MIN(0.7, famI * (MIN(track->width/2, fabs(toMid)) / track->width) * 30 * modfactor); + } + } + lookahead *= cornerfx; + } - if (time_mod < oldtime_mod) - time_mod = MAX(time_mod, oldtime_mod - deltaTime*2); - oldtime_mod = time_mod; + if (time_mod < oldtime_mod) + time_mod = MAX(time_mod, oldtime_mod - deltaTime*2); + oldtime_mod = time_mod; #if 0 - if (fabs(rldata->rInverse) > 0.001) - { - // increase lookahead if on the outside of a corner - double cornerfx = 1.0; - double cornerlmt = MIN(track->width/2, 1.0 + fabs(rldata->rInverse)*500); - if (rldata->rInverse > 0.0 && car->_trkPos.toRight < cornerlmt) - cornerfx = 1.0 + MAX(0.0, (cornerlmt-car->_trkPos.toRight)/cornerlmt)*1.5; - else if (rldata->rInverse < 0.0 && car->_trkPos.toLeft < cornerlmt) - cornerfx = (1.0 - MAX(0.0, (cornerlmt-car->_trkPos.toLeft)/cornerlmt))*1.5; - lookahead *= cornerfx; - } + if (fabs(rldata->rInverse) > 0.001) + { + // increase lookahead if on the outside of a corner + double cornerfx = 1.0; + double cornerlmt = MIN(track->width/2, 1.0 + fabs(rldata->rInverse)*500); + if (rldata->rInverse > 0.0 && car->_trkPos.toRight < cornerlmt) + cornerfx = 1.0 + MAX(0.0, (cornerlmt-car->_trkPos.toRight)/cornerlmt)*1.5; + else if (rldata->rInverse < 0.0 && car->_trkPos.toLeft < cornerlmt) + cornerfx = (1.0 - MAX(0.0, (cornerlmt-car->_trkPos.toLeft)/cornerlmt))*1.5; + lookahead *= cornerfx; + } #endif #if 0 - lookahead = LOOKAHEAD_CONST + car->_speed_x*LOOKAHEAD_FACTOR; - lookahead = MAX(lookahead, LOOKAHEAD_CONST + ((car->_speed_x*(car->_speed_x/2)) / 60.0)); + lookahead = LOOKAHEAD_CONST + car->_speed_x*LOOKAHEAD_FACTOR; + lookahead = MAX(lookahead, LOOKAHEAD_CONST + ((car->_speed_x*(car->_speed_x/2)) / 60.0)); #endif #if 1 - lookahead *= LookAhead; + lookahead *= LookAhead; - // Prevent "snap back" of lookahead on harsh braking. - float cmplookahead = oldlookahead - (car->_speed_x*RCM_MAX_DT_ROBOTS)*0.65f;//0.55f; - if (lookahead < cmplookahead) { - lookahead = cmplookahead; - } + // Prevent "snap back" of lookahead on harsh braking. + float cmplookahead = oldlookahead - (car->_speed_x*RCM_MAX_DT_ROBOTS)*0.65f;//0.55f; + if (lookahead < cmplookahead) { + lookahead = cmplookahead; + } #endif - } + } - oldlookahead = lookahead; + oldlookahead = lookahead; - // Search for the segment containing the target point. - while (length < lookahead) { - seg = seg->next; - length += seg->length; - } + // Search for the segment containing the target point. + while (length < lookahead) { + seg = seg->next; + length += seg->length; + } - length = lookahead - length + seg->length; - float fromstart = seg->lgfromstart; - fromstart += length; + length = lookahead - length + seg->length; + float fromstart = seg->lgfromstart; + fromstart += length; - // Compute the target point. - pitoffset = pit->getPitOffset(pitoffset, fromstart, pitpos); - if ((pit->getPitstop() || pit->getInPit()) && pitoffset != -100.0f) - { - setMode(mode_pitting); - offset = myoffset = pitoffset; - } - else if (mode == mode_pitting) - { - setMode(mode_correcting); - } + // Compute the target point. + pitoffset = pit->getPitOffset(pitoffset, fromstart, pitpos); + if ((pit->getPitstop() || pit->getInPit()) && pitoffset != -100.0f) + { + setMode(mode_pitting); + offset = myoffset = pitoffset; + } + else if (mode == mode_pitting) + { + setMode(mode_correcting); + } - //if (mode == mode_correcting || mode == mode_avoiding) - // offset = adjustOffset( offset ); + //if (mode == mode_correcting || mode == mode_avoiding) + // offset = adjustOffset( offset ); - vec2f s; - //if (mode != mode_pitting) - { - //double steertime = SteerTime * time_mod * MAX(1.0, (1.0 - (car->_accel_x/70 * MAX(0.1, MIN(1.0, collision))))); - double steertime = MIN(MaxSteerTime, MinSteerTime + MAX(0.0, currentspeed-20.0)/30.0); - if (car->_speed_x > SteerCutoff) - time_mod *= SteerCutoff / currentspeed; - raceline->GetSteerPoint( lookahead, &s, offset, (use_lookahead ? -100.0 : steertime * time_mod) ); - return s; - } + vec2f s; + //if (mode != mode_pitting) + { + //double steertime = SteerTime * time_mod * MAX(1.0, (1.0 - (car->_accel_x/70 * MAX(0.1, MIN(1.0, collision))))); + double steertime = MIN(MaxSteerTime, MinSteerTime + MAX(0.0, currentspeed-20.0)/30.0); + if (car->_speed_x > SteerCutoff) + time_mod *= SteerCutoff / currentspeed; + raceline->GetSteerPoint( lookahead, &s, offset, (use_lookahead ? -100.0 : steertime * time_mod) ); + return s; + } - // all the BT code below is for steering into pits only. - s.x = (seg->vertex[TR_SL].x + seg->vertex[TR_SR].x)/2; - s.y = (seg->vertex[TR_SL].y + seg->vertex[TR_SR].y)/2; - //double dx, dy; - vec2f t, rt; + // all the BT code below is for steering into pits only. + s.x = (seg->vertex[TR_SL].x + seg->vertex[TR_SR].x)/2; + s.y = (seg->vertex[TR_SL].y + seg->vertex[TR_SR].y)/2; + //double dx, dy; + vec2f t, rt; - if ( seg->type == TR_STR) { - vec2f d, n; - n.x = (seg->vertex[TR_EL].x - seg->vertex[TR_ER].x)/seg->length; - n.y = (seg->vertex[TR_EL].y - seg->vertex[TR_ER].y)/seg->length; - n.normalize(); - d.x = (seg->vertex[TR_EL].x - seg->vertex[TR_SL].x)/seg->length; - d.y = (seg->vertex[TR_EL].y - seg->vertex[TR_SL].y)/seg->length; - t = s + d*length + offset*n; + if ( seg->type == TR_STR) { + vec2f d, n; + n.x = (seg->vertex[TR_EL].x - seg->vertex[TR_ER].x)/seg->length; + n.y = (seg->vertex[TR_EL].y - seg->vertex[TR_ER].y)/seg->length; + n.normalize(); + d.x = (seg->vertex[TR_EL].x - seg->vertex[TR_SL].x)/seg->length; + d.y = (seg->vertex[TR_EL].y - seg->vertex[TR_SL].y)/seg->length; + t = s + d*length + offset*n; - return t; - } else { - vec2f c, n; - c.x = seg->center.x; - c.y = seg->center.y; - float arc = length/seg->radius; - float arcsign = (seg->type == TR_RGT) ? -1.0f : 1.0f; - arc = arc*arcsign; - s = s.rotate(c, arc); - - n = c - s; - n.normalize(); - t = s + arcsign*offset*n; + return t; + } else { + vec2f c, n; + c.x = seg->center.x; + c.y = seg->center.y; + float arc = length/seg->radius; + float arcsign = (seg->type == TR_RGT) ? -1.0f : 1.0f; + arc = arc*arcsign; + s = s.rotate(c, arc); + + n = c - s; + n.normalize(); + t = s + arcsign*offset*n; - return t; - } + return t; + } } bool Driver::canOvertake( Opponent *o, double *mincatchdist, bool outside, bool lenient ) { - if (!o) return false; + if (!o) return false; #if 1 - //int segid = car->_trkPos.seg->id; - tCarElt *ocar = o->getCarPtr(); - //int osegid = ocar->_trkPos.seg->id; - double otry_factor = (lenient ? (0.2 + MAX(0.0, 1.0 - ((simtime-frontavoidtime)/7.0)) * 0.8) : 1.0); - double overtakecaution = MAX(0.0, rldata->overtakecaution + (outside ? MIN(0.0, car->_accel_x/8) : 0.0)) - driver_aggression/2; - double orInv=0.0, oAspeed=0.0; - raceline->getOpponentInfo(o->getDistance(), &oAspeed, &orInv); - double rInv = MAX(fabs(rldata->rInverse), fabs(orInv)); - double distance = o->getDistance() * otry_factor * MAX(0.5, 1.0 - (ocar->_pos > car->_pos ? MIN(o->getDistance()/2, 3.0) : 0.0)); - //double speed = MIN(rldata->avspeed, MIN(oAspeed, currentspeed + MAX(0.0, (30.0 - distance) * MAX(0.1, 1.0 - MAX(0.0, rInv-0.001)*80)))); - double speed = currentspeed; - double avspeed = MIN(rldata->avspeed, speed + 2.0); - speed = MIN(avspeed, (speed + MAX(0.0, (30.0 - distance) * MAX(0.1, 1.0 - MAX(0.0, rInv-0.001)*80)))); - double ospeed = o->getSpeed(); - double timeLimit = 3.0 - MIN(2.4, rInv * 1000); + //int segid = car->_trkPos.seg->id; + tCarElt *ocar = o->getCarPtr(); + //int osegid = ocar->_trkPos.seg->id; + double otry_factor = (lenient ? (0.2 + MAX(0.0, 1.0 - ((simtime-frontavoidtime)/7.0)) * 0.8) : 1.0); + double overtakecaution = MAX(0.0, rldata->overtakecaution + (outside ? MIN(0.0, car->_accel_x/8) : 0.0)) - driver_aggression/2; + double orInv=0.0, oAspeed=0.0; + raceline->getOpponentInfo(o->getDistance(), &oAspeed, &orInv); + double rInv = MAX(fabs(rldata->rInverse), fabs(orInv)); + double distance = o->getDistance() * otry_factor * MAX(0.5, 1.0 - (ocar->_pos > car->_pos ? MIN(o->getDistance()/2, 3.0) : 0.0)); + //double speed = MIN(rldata->avspeed, MIN(oAspeed, currentspeed + MAX(0.0, (30.0 - distance) * MAX(0.1, 1.0 - MAX(0.0, rInv-0.001)*80)))); + double speed = currentspeed; + double avspeed = MIN(rldata->avspeed, speed + 2.0); + speed = MIN(avspeed, (speed + MAX(0.0, (30.0 - distance) * MAX(0.1, 1.0 - MAX(0.0, rInv-0.001)*80)))); + double ospeed = o->getSpeed(); + double timeLimit = 3.0 - MIN(2.4, rInv * 1000); - //double speeddiff = MAX((15.0-(rInv*1000*1.0+overtakecaution/2)) - distance, fabs(speed - ospeed) * (8 - MIN(5.5, rInv*300))); - double speeddiff = (MIN(speed, avspeed) - ospeed) * 2; - if (outside) - ospeed *= 1.0 + rInv*3; - //double catchdist = (double) MIN((speed*distance)/(speed-ospeed), distance*CATCH_FACTOR) * otry_factor; - double catchdist = (double) ((speed*distance)/(speed-ospeed)) * otry_factor * 0.8 + distance/10; - double mcd = car->_speed_x * (2.0 - MIN(1.5, rInv * 500)); + //double speeddiff = MAX((15.0-(rInv*1000*1.0+overtakecaution/2)) - distance, fabs(speed - ospeed) * (8 - MIN(5.5, rInv*300))); + double speeddiff = (MIN(speed, avspeed) - ospeed) * 2; + if (outside) + ospeed *= 1.0 + rInv*3; + //double catchdist = (double) MIN((speed*distance)/(speed-ospeed), distance*CATCH_FACTOR) * otry_factor; + double catchdist = (double) ((speed*distance)/(speed-ospeed)) * otry_factor * 0.8 + distance/10; + double mcd = car->_speed_x * (2.0 - MIN(1.5, rInv * 500)); #if 0 - // TRB ENDURANCE RACES ONLY!!! - if (car->race.laps < 2 && - ocar->_pos < car->_pos && - fabs(o->getAngle()) < 0.6 && - ocar->_speed_x > MAX(10.0, car->_speed_x/2)) - { - overtakecaution += (2 - car->race.laps) * 4; - } + // TRB ENDURANCE RACES ONLY!!! + if (car->race.laps < 2 && + ocar->_pos < car->_pos && + fabs(o->getAngle()) < 0.6 && + ocar->_speed_x > MAX(10.0, car->_speed_x/2)) + { + overtakecaution += (2 - car->race.laps) * 4; + } #endif - if (catchdist < mcd && MIN(speed, avspeed) > ospeed && //catchdist < *mincatchdist+0.1 && - (distance * (1.0+overtakecaution) < MIN(speeddiff, catchdist/4 + 2.0) * (1.0-rInv*30) || - o->getTimeImpact() * (1.0+overtakecaution) < timeLimit)) - { - if (DebugMsg & debug_overtake) - fprintf(stderr,"%.1f %s: OVERTAKE! (cd %.1f<%.1f) (dist %.1f (%.1f) < (%.1f-%.1f)*X = %.1f TI %.3f < tl %.3f || caut=%.1f avspd=%.1f oAspd=%.1f\n",otry_factor,ocar->_name,catchdist,mcd,distance,o->getDistance(),speed,ospeed,speeddiff,o->getTimeImpact(),timeLimit,overtakecaution,avspeed,oAspeed); - *mincatchdist = catchdist + 0.1; - return true; - } - else if (DebugMsg & debug_overtake) - fprintf(stderr,"%.1f %s: FAIL!!!!! (cd %.1f<%.1f) (dist %.1f (%.1f) < (%.1f-%.1f)*X = %.1f TI %.3f < tl %.3f || caut=%.1f avspd=%.1f oAspd=%.1f\n",otry_factor,ocar->_name,catchdist,mcd,distance,o->getDistance(),speed,ospeed,speeddiff,o->getTimeImpact(),timeLimit,overtakecaution,avspeed,oAspeed); + if (catchdist < mcd && MIN(speed, avspeed) > ospeed && //catchdist < *mincatchdist+0.1 && + (distance * (1.0+overtakecaution) < MIN(speeddiff, catchdist/4 + 2.0) * (1.0-rInv*30) || + o->getTimeImpact() * (1.0+overtakecaution) < timeLimit)) + { + if (DebugMsg & debug_overtake) + fprintf(stderr,"%.1f %s: OVERTAKE! (cd %.1f<%.1f) (dist %.1f (%.1f) < (%.1f-%.1f)*X = %.1f TI %.3f < tl %.3f || caut=%.1f avspd=%.1f oAspd=%.1f\n",otry_factor,ocar->_name,catchdist,mcd,distance,o->getDistance(),speed,ospeed,speeddiff,o->getTimeImpact(),timeLimit,overtakecaution,avspeed,oAspeed); + *mincatchdist = catchdist + 0.1; + return true; + } + else if (DebugMsg & debug_overtake) + fprintf(stderr,"%.1f %s: FAIL!!!!! (cd %.1f<%.1f) (dist %.1f (%.1f) < (%.1f-%.1f)*X = %.1f TI %.3f < tl %.3f || caut=%.1f avspd=%.1f oAspd=%.1f\n",otry_factor,ocar->_name,catchdist,mcd,distance,o->getDistance(),speed,ospeed,speeddiff,o->getTimeImpact(),timeLimit,overtakecaution,avspeed,oAspeed); #else - double distance = o->getDistance(); - double speed = MIN(rldata->avspeed, currentspeed + MAX(0.0, (currentspeed/3 - distance)/2)); - double ospeed = o->getSpeed(); - double caution = overtakecaution + (outside == true ? 0.5 : 0.0); - //double rInverse = (fabs(nextCRinverse)>fabs(rldata->rInverse) ? nextCRinverse : rldata->rInverse); - double rInverse = rldata->aInverse; //rldata->rInverse; + double distance = o->getDistance(); + double speed = MIN(rldata->avspeed, currentspeed + MAX(0.0, (currentspeed/3 - distance)/2)); + double ospeed = o->getSpeed(); + double caution = overtakecaution + (outside == true ? 0.5 : 0.0); + //double rInverse = (fabs(nextCRinverse)>fabs(rldata->rInverse) ? nextCRinverse : rldata->rInverse); + double rInverse = rldata->aInverse; //rldata->rInverse; - { - tTrackSeg *wseg = (rInverse > 0.0 ? car->_wheelSeg(FRNT_LFT) : car->_wheelSeg(FRNT_RGT)); - if (wseg->surface->kFriction > car->_trkPos.seg->surface->kFriction) - caution += (wseg->surface->kFriction - car->_trkPos.seg->surface->kFriction) * 4; - } + { + tTrackSeg *wseg = (rInverse > 0.0 ? car->_wheelSeg(FRNT_LFT) : car->_wheelSeg(FRNT_RGT)); + if (wseg->surface->kFriction > car->_trkPos.seg->surface->kFriction) + caution += (wseg->surface->kFriction - car->_trkPos.seg->surface->kFriction) * 4; + } - distance += fabs(rInverse) * 200; - if (outside) - { - distance += fabs(rInverse) * 800; - if ((rInverse > 0.0 && angle > 0.0) || (rInverse < 0.0 && angle < 0.0)) - caution += fabs(speedangle-angle) * 20; - } + distance += fabs(rInverse) * 200; + if (outside) + { + distance += fabs(rInverse) * 800; + if ((rInverse > 0.0 && angle > 0.0) || (rInverse < 0.0 && angle < 0.0)) + caution += fabs(speedangle-angle) * 20; + } - double catchdist = MIN(speed*distance/(speed-ospeed), distance*CATCH_FACTOR) * (lenient ? (0.7 + MIN(0.3, (simtime-frontavoidtime)/10.0)) : 1.0) * (1.0 + caution/2); - - if (catchdist > *mincatchdist && - *mincatchdist >= MAX(100.0, car->_speed_x*5) && - rldata->avspeed > 1000.0 && currentspeed > ospeed - (lenient ? 3.0 : 1.5)) - { - // on a fast section - don't let catchdist be a barrier to overtaking - catchdist = *mincatchdist * 0.9; - } + double catchdist = MIN(speed*distance/(speed-ospeed), distance*CATCH_FACTOR) * (lenient ? (0.7 + MIN(0.3, (simtime-frontavoidtime)/10.0)) : 1.0) * (1.0 + caution/2); + + if (catchdist > *mincatchdist && + *mincatchdist >= MAX(100.0, car->_speed_x*5) && + rldata->avspeed > 1000.0 && currentspeed > ospeed - (lenient ? 3.0 : 1.5)) + { + // on a fast section - don't let catchdist be a barrier to overtaking + catchdist = *mincatchdist * 0.9; + } - if ((catchdist <= *mincatchdist) && distance < (speed-ospeed)*2) - { - double mradius = MAX(0.0, MIN(1.0, fabs(rInverse) * 70)); - double oradius = MAX(0.0, MIN(1.0, fabs(raceline->getRInverse(distance)) * 80)); - double radius = MAX(1.0, MIN(10.0, MAX(1.0 / mradius, 1.0 / oradius))); - catchdist *= radius; - double distance2 = distance * radius; - - if (catchdist <= *mincatchdist && distance < fabs(speed-ospeed)*2) - { - if (DebugMsg & debug_overtake) - fprintf(stderr,"%s - %s OVERTAKE: cd=%.1f > %.1f, dist=%.1f > (%.1f-%.1f)*2=%.1f\n",car->_name,o->getCarPtr()->_name,catchdist,*mincatchdist,distance,speed,ospeed,(speed-ospeed)*2); - *mincatchdist = catchdist+0.1; - return true; - } - else if (DebugMsg & debug_overtake) - fprintf(stderr,"%s - %s FAIL 2: cd=%.1f > %.1f, dist=%.1f (%.1f/%.1f) > (%.1f-%.1f)*2=%.1f\n",car->_name,o->getCarPtr()->_name,catchdist,*mincatchdist,distance2,distance,o->getDistance(),speed,ospeed,(speed-ospeed)*2); - } - else if (DebugMsg & debug_overtake) - fprintf(stderr,"%s - %s FAIL 1: cd=%.1f > %.1f, dist=%.1f (%.1f) > (%.1f-%.1f)*2=%.1f\n",car->_name,o->getCarPtr()->_name,catchdist,*mincatchdist,distance,o->getDistance(),speed,ospeed,(speed-ospeed)*2); + if ((catchdist <= *mincatchdist) && distance < (speed-ospeed)*2) + { + double mradius = MAX(0.0, MIN(1.0, fabs(rInverse) * 70)); + double oradius = MAX(0.0, MIN(1.0, fabs(raceline->getRInverse(distance)) * 80)); + double radius = MAX(1.0, MIN(10.0, MAX(1.0 / mradius, 1.0 / oradius))); + catchdist *= radius; + double distance2 = distance * radius; + + if (catchdist <= *mincatchdist && distance < fabs(speed-ospeed)*2) + { + if (DebugMsg & debug_overtake) + fprintf(stderr,"%s - %s OVERTAKE: cd=%.1f > %.1f, dist=%.1f > (%.1f-%.1f)*2=%.1f\n",car->_name,o->getCarPtr()->_name,catchdist,*mincatchdist,distance,speed,ospeed,(speed-ospeed)*2); + *mincatchdist = catchdist+0.1; + return true; + } + else if (DebugMsg & debug_overtake) + fprintf(stderr,"%s - %s FAIL 2: cd=%.1f > %.1f, dist=%.1f (%.1f/%.1f) > (%.1f-%.1f)*2=%.1f\n",car->_name,o->getCarPtr()->_name,catchdist,*mincatchdist,distance2,distance,o->getDistance(),speed,ospeed,(speed-ospeed)*2); + } + else if (DebugMsg & debug_overtake) + fprintf(stderr,"%s - %s FAIL 1: cd=%.1f > %.1f, dist=%.1f (%.1f) > (%.1f-%.1f)*2=%.1f\n",car->_name,o->getCarPtr()->_name,catchdist,*mincatchdist,distance,o->getDistance(),speed,ospeed,(speed-ospeed)*2); #endif - return false; + return false; } // Compute offset to normal target point for overtaking or let pass an opponent. float Driver::getOffset() { - int i, avoidmovt = 0; - double /*catchdist,*/ mincatchdist = MAX(100.0, car->_speed_x * 5), mindist = -1000.0; - Opponent *o = NULL; - double lane2left = rldata->lane * car->_trkPos.seg->width; - double lane2right = car->_trkPos.seg->width-lane2left; - avoidmode = 0; - sideratio = 100.0; + int i, avoidmovt = 0; + double /*catchdist,*/ mincatchdist = MAX(100.0, car->_speed_x * 5), mindist = -1000.0; + Opponent *o = NULL; + double lane2left = rldata->lane * car->_trkPos.seg->width; + double lane2right = car->_trkPos.seg->width-lane2left; + avoidmode = 0; + sideratio = 100.0; - avoidlftoffset = car->_trkPos.seg->width / 2; - avoidrgtoffset = -car->_trkPos.seg->width / 2; + avoidlftoffset = car->_trkPos.seg->width / 2; + avoidrgtoffset = -car->_trkPos.seg->width / 2; - // Increment speed dependent. - //double incspeed = MIN(40.0, MAX(30.0, currentspeed)); - //double incfactor = (MAX_INC_FACTOR*0.5 - MIN(incspeed/10, MAX_INC_FACTOR*0.5-0.5)) * 60 * IncFactor; - //double incspeed = MIN(60.0, MAX(40.0, currentspeed)) - 10.0; - //double incfactor = (MAX_INC_FACTOR - MIN(fabs(incspeed)/MAX_INC_FACTOR, (MAX_INC_FACTOR - 1.0f))) * (10.0f + MAX(0.0, (CA-1.9)*10)) * IncFactor; - double incfactor = (MAX_INC_FACTOR - MIN(40.0/MAX_INC_FACTOR, (MAX_INC_FACTOR - 1.0f))) * (10.0f + MAX(0.0, (CA-1.9)*10)) * IncFactor; + // Increment speed dependent. + //double incspeed = MIN(40.0, MAX(30.0, currentspeed)); + //double incfactor = (MAX_INC_FACTOR*0.5 - MIN(incspeed/10, MAX_INC_FACTOR*0.5-0.5)) * 60 * IncFactor; + //double incspeed = MIN(60.0, MAX(40.0, currentspeed)) - 10.0; + //double incfactor = (MAX_INC_FACTOR - MIN(fabs(incspeed)/MAX_INC_FACTOR, (MAX_INC_FACTOR - 1.0f))) * (10.0f + MAX(0.0, (CA-1.9)*10)) * IncFactor; + double incfactor = (MAX_INC_FACTOR - MIN(40.0/MAX_INC_FACTOR, (MAX_INC_FACTOR - 1.0f))) * (10.0f + MAX(0.0, (CA-1.9)*10)) * IncFactor; - //double rgtinc = incfactor * MIN(3.0, MAX(0.6, 1.0 + rldata->mInverse * (rldata->mInverse<0.0?-5:100))); - //double lftinc = incfactor * MIN(3.0, MAX(0.6, 1.0 - rldata->mInverse * (rldata->mInverse>0.0?-5:100))); - double ri = rldata->aInverse; - double rgtinc = incfactor * MIN(3.0, MAX(0.6, 1.0 + (ri < 0.0 ? ri*4 : ri*MAX(10.0, car->_speed_x-25)*2*OutSteerFactor))); - double lftinc = incfactor * MIN(3.0, MAX(0.6, 1.0 - (ri > 0.0 ? ri*4 : ri*MAX(10.0,car->_speed_x-25)*2*OutSteerFactor))); - - //double reduce_movt = MAX(0.01, 1.0 - (MIN(1.0, fabs(laststeer))*2 * fabs(angle-speedangle)*3)); + //double rgtinc = incfactor * MIN(3.0, MAX(0.6, 1.0 + rldata->mInverse * (rldata->mInverse<0.0?-5:100))); + //double lftinc = incfactor * MIN(3.0, MAX(0.6, 1.0 - rldata->mInverse * (rldata->mInverse>0.0?-5:100))); + double ri = rldata->aInverse; + double rgtinc = incfactor * MIN(3.0, MAX(0.6, 1.0 + (ri < 0.0 ? ri*4 : ri*MAX(10.0, car->_speed_x-25)*2*OutSteerFactor))); + double lftinc = incfactor * MIN(3.0, MAX(0.6, 1.0 - (ri > 0.0 ? ri*4 : ri*MAX(10.0,car->_speed_x-25)*2*OutSteerFactor))); + + //double reduce_movt = MAX(0.01, 1.0 - (MIN(1.0, fabs(laststeer))*2 * fabs(angle-speedangle)*3)); #if 1 - double reduce_movt = MAX(0.1, MIN(1.0, 1.0 - fabs(angle*2 - laststeer)) * MAX(fabs(angle-speedangle), fabs(speedangle-angle))*1); - reduce_movt = MIN(reduce_movt, MAX(0.1, 1.0 + fabs(car->_accel_x)/30)); - lftinc *= reduce_movt; - rgtinc *= reduce_movt; + double reduce_movt = MAX(0.1, MIN(1.0, 1.0 - fabs(angle*2 - laststeer)) * MAX(fabs(angle-speedangle), fabs(speedangle-angle))*1); + reduce_movt = MIN(reduce_movt, MAX(0.1, 1.0 + fabs(car->_accel_x)/30)); + lftinc *= reduce_movt; + rgtinc *= reduce_movt; #else - if (ri > 0.0) - rgtinc *= MAX(0.0, MIN(1.0, 1.0 - (angle*2-car->_yaw_rate/2) * MIN(1.0, rldata->rInverse*40))); - else if (ri < 0.0) - lftinc *= MAX(0.0, MIN(1.0, 1.0 + (angle*2-car->_yaw_rate/2) * MIN(1.0, (-rldata->rInverse)*40))); + if (ri > 0.0) + rgtinc *= MAX(0.0, MIN(1.0, 1.0 - (angle*2-car->_yaw_rate/2) * MIN(1.0, rldata->rInverse*40))); + else if (ri < 0.0) + lftinc *= MAX(0.0, MIN(1.0, 1.0 + (angle*2-car->_yaw_rate/2) * MIN(1.0, (-rldata->rInverse)*40))); #endif - double moffset = car->_trkPos.toMiddle; + double moffset = car->_trkPos.toMiddle; - //double origoffset = moffset; + //double origoffset = moffset; - double Width = car->_trkPos.seg->width; + double Width = car->_trkPos.seg->width; #if 1 - double lftmargin = GetModD( tLftMargin, rldata->nextdiv ); - double rgtmargin = GetModD( tRgtMargin, rldata->nextdiv ); - double maxoffset = MIN(moffset+OVERTAKE_OFFSET_INC*lftinc*4, Width/2 - (car->_dimension_y+SideMargin+rgtmargin)); - double minoffset = MAX(moffset-OVERTAKE_OFFSET_INC*rgtinc*4, -(Width/2 - (car->_dimension_y+SideMargin+lftmargin))); + double lftmargin = GetModD( tLftMargin, rldata->nextdiv ); + double rgtmargin = GetModD( tRgtMargin, rldata->nextdiv ); + double maxoffset = MIN(moffset+OVERTAKE_OFFSET_INC*lftinc*4, Width/2 - (car->_dimension_y+SideMargin+rgtmargin)); + double minoffset = MAX(moffset-OVERTAKE_OFFSET_INC*rgtinc*4, -(Width/2 - (car->_dimension_y+SideMargin+lftmargin))); - double oldmax = maxoffset, oldmin = minoffset; + double oldmax = maxoffset, oldmin = minoffset; - { - ri = (fabs(rldata->aInverse) < fabs(rldata->mInverse) ? rldata->aInverse : rldata->mInverse); - if (rldata->mInverse > 0.0) - maxoffset = MIN(maxoffset, MAX(Width/8, Width/2 - (1.5 + ri*1000))); - else - minoffset = MAX(minoffset, MIN(-Width/8, -Width/2 + (1.5 - ri*1000))); - } + { + ri = (fabs(rldata->aInverse) < fabs(rldata->mInverse) ? rldata->aInverse : rldata->mInverse); + if (rldata->mInverse > 0.0) + maxoffset = MIN(maxoffset, MAX(Width/8, Width/2 - (1.5 + ri*1000))); + else + minoffset = MAX(minoffset, MIN(-Width/8, -Width/2 + (1.5 - ri*1000))); + } #endif - - //myoffset = car->_trkPos.toMiddle; - if (mode == mode_normal) - { - moffset = rldata->offset; - myoffset = (float) moffset; - } - else - { - // reduce amount we deviate from the raceline according to how long we've been avoiding, and also - // how fast we're going. - //double dspeed = MAX(0.0, rldata->speed - currentspeed) * 4; - //double pspeed = MAX(1.0, 60.0 - (currentspeed - (30.0 + MAX(0.0, car->_accel_x) + dspeed))) / 10; + + //myoffset = car->_trkPos.toMiddle; + if (mode == mode_normal) + { + moffset = rldata->offset; + myoffset = (float) moffset; + } + else + { + // reduce amount we deviate from the raceline according to how long we've been avoiding, and also + // how fast we're going. + //double dspeed = MAX(0.0, rldata->speed - currentspeed) * 4; + //double pspeed = MAX(1.0, 60.0 - (currentspeed - (30.0 + MAX(0.0, car->_accel_x) + dspeed))) / 10; - // instead of toMiddle just aiming at where the car currently is, we move it in the direction - // the car's travelling ... but less so if the speedangle is different from the car's angle. - double sa = speedangle; - //double anglechange = ((sa*0.8) * MAX(0.0, 1.0 - fabs(sa-angle)*(0.6+fabs(sa-angle)))) * 0.7; - double anglechange = ((sa*1.0) * MAX(0.0, 1.0 - fabs(sa-angle))) * (fabs(currentspeed)/50); - double toMiddle = car->_trkPos.toMiddle + anglechange*0; - moffset = toMiddle; - myoffset = (float) moffset; + // instead of toMiddle just aiming at where the car currently is, we move it in the direction + // the car's travelling ... but less so if the speedangle is different from the car's angle. + double sa = speedangle; + //double anglechange = ((sa*0.8) * MAX(0.0, 1.0 - fabs(sa-angle)*(0.6+fabs(sa-angle)))) * 0.7; + double anglechange = ((sa*1.0) * MAX(0.0, 1.0 - fabs(sa-angle))) * (fabs(currentspeed)/50); + double toMiddle = car->_trkPos.toMiddle + anglechange*0; + moffset = toMiddle; + myoffset = (float) moffset; - if (mode == mode_correcting && avoidtime < simtime) - avoidtime += deltaTime*0.8; - if (simtime - avoidtime > 3.0) - avoidtime = simtime - 3.0; + if (mode == mode_correcting && avoidtime < simtime) + avoidtime += deltaTime*0.8; + if (simtime - avoidtime > 3.0) + avoidtime = simtime - 3.0; - if (0) - { - if (toMiddle > rldata->offset) - moffset = MIN(toMiddle, rldata->offset + (simtime-avoidtime) * 45.0 * incfactor/8); - else - moffset = MAX(toMiddle, rldata->offset - (simtime-avoidtime) * 45.0 * incfactor/8); - } + if (0) + { + if (toMiddle > rldata->offset) + moffset = MIN(toMiddle, rldata->offset + (simtime-avoidtime) * 45.0 * incfactor/8); + else + moffset = MAX(toMiddle, rldata->offset - (simtime-avoidtime) * 45.0 * incfactor/8); + } #if 0 - if (fabs(car->_trkPos.toMiddle) < MAX(fabs(minoffset), fabs(maxoffset))) - { - if (anglechange > 0.0) - minoffset = MIN(maxoffset, MAX(minoffset, car->_trkPos.toMiddle - MAX(0.1, 1.0 - anglechange*2)*2)); - else - maxoffset = MAX(minoffset, MIN(maxoffset, car->_trkPos.toMiddle + MAX(0.1, 1.0 - fabs(anglechange*2))*2)); - } + if (fabs(car->_trkPos.toMiddle) < MAX(fabs(minoffset), fabs(maxoffset))) + { + if (anglechange > 0.0) + minoffset = MIN(maxoffset, MAX(minoffset, car->_trkPos.toMiddle - MAX(0.1, 1.0 - anglechange*2)*2)); + else + maxoffset = MAX(minoffset, MIN(maxoffset, car->_trkPos.toMiddle + MAX(0.1, 1.0 - fabs(anglechange*2))*2)); + } #endif - } + } - { - minoffset = MAX(minoffset, car->_trkPos.toMiddle - OVERTAKE_OFFSET_INC*rgtinc*100); - maxoffset = MIN(maxoffset, car->_trkPos.toMiddle + OVERTAKE_OFFSET_INC*lftinc*100); - } - //myoffset = car->_trkPos.toMiddle; + { + minoffset = MAX(minoffset, car->_trkPos.toMiddle - OVERTAKE_OFFSET_INC*rgtinc*100); + maxoffset = MIN(maxoffset, car->_trkPos.toMiddle + OVERTAKE_OFFSET_INC*lftinc*100); + } + //myoffset = car->_trkPos.toMiddle; - // Side Collision. - for (i = 0; i < opponents->getNOpponents(); i++) - { - tCarElt *ocar = opponent[i].getCarPtr(); + // Side Collision. + for (i = 0; i < opponents->getNOpponents(); i++) + { + tCarElt *ocar = opponent[i].getCarPtr(); - if (ocar->_state & (RM_CAR_STATE_NO_SIMU & ~RM_CAR_STATE_PIT)) - continue; + if (ocar->_state & (RM_CAR_STATE_NO_SIMU & ~RM_CAR_STATE_PIT)) + continue; - if (fabs(ocar->_trkPos.toMiddle) > Width/2 + 3.0 && - fabs(car->_trkPos.toMiddle-ocar->_trkPos.toMiddle) >= 5.0) - continue; + if (fabs(ocar->_trkPos.toMiddle) > Width/2 + 3.0 && + fabs(car->_trkPos.toMiddle-ocar->_trkPos.toMiddle) >= 5.0) + continue; - if ((opponent[i].getState() & OPP_SIDE)) - { - o = &opponent[i]; + if ((opponent[i].getState() & OPP_SIDE)) + { + o = &opponent[i]; if (DebugMsg & debug_overtake) fprintf(stderr,"%s SIDE %s\n",car->_name,ocar->_name);fflush(stderr); - - double sidedist = fabs(ocar->_trkPos.toLeft - car->_trkPos.toLeft); - double sidemargin = opponent[i].getWidth()/2 + getWidth()/2 + 5.0f + MAX(fabs(rldata->rInverse), fabs(rldata->mInverse))*100; - double side = (car->_trkPos.toMiddle-angle) - (ocar->_trkPos.toMiddle-opponent[i].getAngle()); - double sidedist2 = sidedist; - if (side > 0.0) - { - // I'm on his left - sidedist2 -= (o->getSpeedAngle() - speedangle) * 40; - sidemargin -= MIN(0.0, rldata->rInverse*100); - } - else - { - // I'm on his right - sidedist2 -= (speedangle - o->getSpeedAngle()) * 40; - sidemargin += MAX(0.0, rldata->rInverse*100); - } - int closing = (sidedist2 < sidedist); + + double sidedist = fabs(ocar->_trkPos.toLeft - car->_trkPos.toLeft); + double sidemargin = opponent[i].getWidth()/2 + getWidth()/2 + 5.0f + MAX(fabs(rldata->rInverse), fabs(rldata->mInverse))*100; + double side = (car->_trkPos.toMiddle-angle) - (ocar->_trkPos.toMiddle-opponent[i].getAngle()); + double sidedist2 = sidedist; + if (side > 0.0) + { + // I'm on his left + sidedist2 -= (o->getSpeedAngle() - speedangle) * 40; + sidemargin -= MIN(0.0, rldata->rInverse*100); + } + else + { + // I'm on his right + sidedist2 -= (speedangle - o->getSpeedAngle()) * 40; + sidemargin += MAX(0.0, rldata->rInverse*100); + } + int closing = (sidedist2 < sidedist); - if (sidedist < sidemargin || sidedist2 < sidemargin) - { - //double w = Width/WIDTHDIV-BORDER_OVERTAKE_MARGIN; - //double sdiff = 2.0 - MAX(sidemargin-sidedist, sidemargin-sidedist2)/sidemargin; - double sdiff = MAX(sidemargin-sidedist, sidemargin-sidedist2) + MAX(0.0, sidedist - sidedist2); + if (sidedist < sidemargin || sidedist2 < sidemargin) + { + //double w = Width/WIDTHDIV-BORDER_OVERTAKE_MARGIN; + //double sdiff = 2.0 - MAX(sidemargin-sidedist, sidemargin-sidedist2)/sidemargin; + double sdiff = MAX(sidemargin-sidedist, sidemargin-sidedist2) + MAX(0.0, sidedist - sidedist2); - if (side > 0.0) { - double linc = OVERTAKE_OFFSET_INC * (lftinc * MAX(0.2, MIN(1.1, sdiff/4)) * 1.5); - if (rldata->rInverse < 0.0) - linc -= rldata->rInverse * 200 * IncFactor; - myoffset += (float) linc; - //if (rldata->rInverse < 0.0) - // myoffset -= rldata->rInverse * 500 * IncFactor; - avoidmovt = 1; + if (side > 0.0) { + double linc = OVERTAKE_OFFSET_INC * (lftinc * MAX(0.2, MIN(1.1, sdiff/4)) * 1.5); + if (rldata->rInverse < 0.0) + linc -= rldata->rInverse * 200 * IncFactor; + myoffset += (float) linc; + //if (rldata->rInverse < 0.0) + // myoffset -= rldata->rInverse * 500 * IncFactor; + avoidmovt = 1; if (DebugMsg & debug_overtake) fprintf(stderr,"%s SIDE to Rgt %s, MOVING LEFT by %.3f, sm=%.3f sd=%.3f/%.3f sm-sd=%.3f mInv=%.3f\n",car->_name,ocar->_name,(float) (OVERTAKE_OFFSET_INC*lftinc*MAX(0.2f, MIN(1.5f, sdiff))),sidemargin,sidedist,sidedist2,sdiff,rldata->mInverse);fflush(stderr); - } else if (side <= 0.0) { - double rinc = OVERTAKE_OFFSET_INC * (rgtinc * MAX(0.2, MIN(1.1, sdiff/4)) * 1.5); - if (rldata->rInverse > 0.0) - rinc += rldata->rInverse * 200 * IncFactor; - myoffset -= (float) rinc; - //if (rldata->rInverse > 0.0) - // myoffset -= rldata->rInverse * 500 * IncFactor; - avoidmovt = 1; + } else if (side <= 0.0) { + double rinc = OVERTAKE_OFFSET_INC * (rgtinc * MAX(0.2, MIN(1.1, sdiff/4)) * 1.5); + if (rldata->rInverse > 0.0) + rinc += rldata->rInverse * 200 * IncFactor; + myoffset -= (float) rinc; + //if (rldata->rInverse > 0.0) + // myoffset -= rldata->rInverse * 500 * IncFactor; + avoidmovt = 1; if (DebugMsg & debug_overtake) fprintf(stderr,"%s SIDE to Lft %s, MOVING RIGHT by %.3f sm-sd=%.2f mo=%.3f\n",car->_name,ocar->_name,(OVERTAKE_OFFSET_INC*lftinc*MAX(1.0f, MIN(2.0f, sdiff))),sdiff,myoffset);fflush(stderr); - } + } - if (avoidmovt) - sideratio = MIN(sidedist,sidedist2)/sidemargin; + if (avoidmovt) + sideratio = MIN(sidedist,sidedist2)/sidemargin; else if (DebugMsg & debug_overtake) fprintf(stderr,"%s SIDE %s, NO MOVE %.1f\n",car->_name,ocar->_name,myoffset);fflush(stderr); - } - else if (sidedist > sidemargin+3.0) - { - if ((car->_trkPos.toLeft > ocar->_trkPos.toLeft && rldata->rInverse > 0.0) || - (car->_trkPos.toLeft < ocar->_trkPos.toLeft && rldata->rInverse < 0.0)) - avoidtime = MIN(simtime, avoidtime + MIN(deltaTime*0.9, fabs(rldata->rInverse*1.2))); + } + else if (sidedist > sidemargin+3.0) + { + if ((car->_trkPos.toLeft > ocar->_trkPos.toLeft && rldata->rInverse > 0.0) || + (car->_trkPos.toLeft < ocar->_trkPos.toLeft && rldata->rInverse < 0.0)) + avoidtime = MIN(simtime, avoidtime + MIN(deltaTime*0.9, fabs(rldata->rInverse*1.2))); - if (ocar->_trkPos.toLeft > car->_trkPos.toLeft && - car->_trkPos.toLeft < MIN(lane2left, 4.0 + fabs(nextCRinverse)*1000)) - { - myoffset -= (float) (OVERTAKE_OFFSET_INC*lftinc/4); + if (ocar->_trkPos.toLeft > car->_trkPos.toLeft && + car->_trkPos.toLeft < MIN(lane2left, 4.0 + fabs(nextCRinverse)*1000)) + { + myoffset -= (float) (OVERTAKE_OFFSET_INC*lftinc/4); if (DebugMsg & debug_overtake) fprintf(stderr,"%s SIDE to Rgt %s, MOVING BACK TO RIGHT\n",car->_name,ocar->_name);fflush(stderr); - if (!avoidmode) - avoidtime = MIN(simtime, avoidtime+deltaTime*0.5); - } - else if (ocar->_trkPos.toLeft < car->_trkPos.toLeft && - car->_trkPos.toRight < MIN(lane2right, 4.0 + fabs(nextCRinverse)*1000)) - { - myoffset += (float) (OVERTAKE_OFFSET_INC*rgtinc/4); + if (!avoidmode) + avoidtime = MIN(simtime, avoidtime+deltaTime*0.5); + } + else if (ocar->_trkPos.toLeft < car->_trkPos.toLeft && + car->_trkPos.toRight < MIN(lane2right, 4.0 + fabs(nextCRinverse)*1000)) + { + myoffset += (float) (OVERTAKE_OFFSET_INC*rgtinc/4); if (DebugMsg & debug_overtake) fprintf(stderr,"%s SIDE to Lft %s, MOVING BACK TO LEFT\n",car->_name,ocar->_name);fflush(stderr); - if (!avoidmode) - avoidtime = MIN(simtime, avoidtime+deltaTime*0.5); - } + if (!avoidmode) + avoidtime = MIN(simtime, avoidtime+deltaTime*0.5); + } else if (DebugMsg & debug_overtake) fprintf(stderr,"%s SIDE %s, NO MOVE %.1f\n",car->_name,ocar->_name,myoffset);fflush(stderr); - } + } else if (DebugMsg & debug_overtake) fprintf(stderr,"%s SIDE %s, NO MOVE AT ALL! %.1f\n",car->_name,ocar->_name,myoffset);fflush(stderr); - if (ocar->_trkPos.toLeft > car->_trkPos.toLeft) - { - avoidrgtoffset = (float) MAX(avoidrgtoffset, ocar->_trkPos.toMiddle + (o->getWidth()+1.0f)); - avoidmode |= avoidright; - //if (avoidmovt) - avoidmode |= avoidside; - if (closing) - avoidmode |= avoidsideclosing; - } - else - { - avoidlftoffset = (float) MIN(avoidlftoffset, ocar->_trkPos.toMiddle - (o->getWidth()+1.0f)); - avoidmode |= avoidleft; - //if (avoidmovt) - avoidmode |= avoidside; - if (closing) - avoidmode |= avoidsideclosing; - } + if (ocar->_trkPos.toLeft > car->_trkPos.toLeft) + { + avoidrgtoffset = (float) MAX(avoidrgtoffset, ocar->_trkPos.toMiddle + (o->getWidth()+1.0f)); + avoidmode |= avoidright; + //if (avoidmovt) + avoidmode |= avoidside; + if (closing) + avoidmode |= avoidsideclosing; + } + else + { + avoidlftoffset = (float) MIN(avoidlftoffset, ocar->_trkPos.toMiddle - (o->getWidth()+1.0f)); + avoidmode |= avoidleft; + //if (avoidmovt) + avoidmode |= avoidside; + if (closing) + avoidmode |= avoidsideclosing; + } - } - } + } + } - if (avoidmode) - { - if (!avoidmovt) - avoidtime = MIN(simtime, avoidtime+deltaTime*1.0); - goto end_getoffset; - } + if (avoidmode) + { + if (!avoidmovt) + avoidtime = MIN(simtime, avoidtime+deltaTime*1.0); + goto end_getoffset; + } #if 0 - // don't try and front-avoid if we're struggling for control! - if (avgaccel_x - fabs(laststeer) * fabs(angle-speedangle) < -10.0) - goto end_getoffset; + // don't try and front-avoid if we're struggling for control! + if (avgaccel_x - fabs(laststeer) * fabs(angle-speedangle) < -10.0) + goto end_getoffset; - if (rldata->lftmargin > 0.0 && minoffset < rldata->offset - rldata->lftmargin) - minoffset = rldata->offset - rldata->lftmargin; - if (rldata->rgtmargin > 0.0 && maxoffset > rldata->offset + rldata->rgtmargin) - maxoffset = rldata->offset + rldata->rgtmargin; + if (rldata->lftmargin > 0.0 && minoffset < rldata->offset - rldata->lftmargin) + minoffset = rldata->offset - rldata->lftmargin; + if (rldata->rgtmargin > 0.0 && maxoffset > rldata->offset + rldata->rgtmargin) + maxoffset = rldata->offset + rldata->rgtmargin; #endif - if (car->_speed_x > 20.0 || simtime > 10.0) - { - double caution = rldata->overtakecaution; + if (car->_speed_x > 20.0 || simtime > 10.0) + { + double caution = rldata->overtakecaution; - { - tTrackSeg *wseg = (rldata->rInverse > 0.0 ? car->_wheelSeg(FRNT_LFT) : car->_wheelSeg(FRNT_RGT)); - if (wseg->surface->kFriction > car->_trkPos.seg->surface->kFriction) - caution += (wseg->surface->kFriction - car->_trkPos.seg->surface->kFriction) * 4; - } + { + tTrackSeg *wseg = (rldata->rInverse > 0.0 ? car->_wheelSeg(FRNT_LFT) : car->_wheelSeg(FRNT_RGT)); + if (wseg->surface->kFriction > car->_trkPos.seg->surface->kFriction) + caution += (wseg->surface->kFriction - car->_trkPos.seg->surface->kFriction) * 4; + } - //caution += fabs(speedangle - angle)*10; - int otry_success = 0; - double rInverse = rldata->rInverse; - if (fabs(nextCRinverse) > fabs(rInverse)) - rInverse = nextCRinverse; + //caution += fabs(speedangle - angle)*10; + int otry_success = 0; + double rInverse = rldata->rInverse; + if (fabs(nextCRinverse) > fabs(rInverse)) + rInverse = nextCRinverse; - for (int otry=0; otry<=1; otry++) - { - // Overtake. - for (i = 0; i < opponents->getNOpponents(); i++) - { - tCarElt *ocar = opponent[i].getCarPtr(); - - // strategy telling us to follow this car? - if ((opponent[i].getState() & OPP_FRONT_FOLLOW)) - continue; + for (int otry=0; otry<=1; otry++) + { + // Overtake. + for (i = 0; i < opponents->getNOpponents(); i++) + { + tCarElt *ocar = opponent[i].getCarPtr(); + + // strategy telling us to follow this car? + if ((opponent[i].getState() & OPP_FRONT_FOLLOW)) + continue; - // off track or a long way wide of us? - if (!(opponent[i].getState() & OPP_COLL) && - fabs(ocar->_trkPos.toMiddle) > Width/2 + 3.0 && - fabs(car->_trkPos.toMiddle-ocar->_trkPos.toMiddle) >= 8.0) - continue; + // off track or a long way wide of us? + if (!(opponent[i].getState() & OPP_COLL) && + fabs(ocar->_trkPos.toMiddle) > Width/2 + 3.0 && + fabs(car->_trkPos.toMiddle-ocar->_trkPos.toMiddle) >= 8.0) + continue; - if (ocar->_state & (RM_CAR_STATE_NO_SIMU & ~RM_CAR_STATE_PIT)) - continue; + if (ocar->_state & (RM_CAR_STATE_NO_SIMU & ~RM_CAR_STATE_PIT)) + continue; - if ((opponent[i].getState() & OPP_FRONT) && - !(0 && opponent[i].isTeamMate() && car->race.laps <= opponent[i].getCarPtr()->race.laps)) - { + if ((opponent[i].getState() & OPP_FRONT) && + !(0 && opponent[i].isTeamMate() && car->race.laps <= opponent[i].getCarPtr()->race.laps)) + { #if 1 - if (canOvertake(&opponent[i], &mincatchdist, false, (otry == 1))) - o = &opponent[i]; + if (canOvertake(&opponent[i], &mincatchdist, false, (otry == 1))) + o = &opponent[i]; #else - int segid = car->_trkPos.seg->id; - int osegid = opponent[i].getCarPtr()->_trkPos.seg->id; - double distance = opponent[i].getDistance(); - double truespeed = getTrueSpeed(); - double truespeed2 = truespeed + MAX(0.0, 6.0 - fabs(rInverse)*400); - double speed = MIN(truespeed2, MIN(rldata->avspeed, truespeed+MAX(1.0, (((car->_speed_x*car->_speed_x)/100)-distance)/3))); - double ospeed = opponent[i].getTrueSpeed(); - double try_timer = (0.3 + (1.0 - ((simtime-frontavoidtime)/5.0)/2)) * otry; - double sidedist = fabs(car->_trkPos.toMiddle - opponent[i].getCarPtr()->_trkPos.toMiddle); - double spddiff = (speed - ospeed)*1.5; - catchdist = ((double) MIN(speed*distance/(spddiff), distance*CATCH_FACTOR) + (speed * caution)) * (1.0 + try_timer); - double sdiff = ((distance - MAX(0.0, 5.0-sidedist)) - (spddiff)*2); + int segid = car->_trkPos.seg->id; + int osegid = opponent[i].getCarPtr()->_trkPos.seg->id; + double distance = opponent[i].getDistance(); + double truespeed = getTrueSpeed(); + double truespeed2 = truespeed + MAX(0.0, 6.0 - fabs(rInverse)*400); + double speed = MIN(truespeed2, MIN(rldata->avspeed, truespeed+MAX(1.0, (((car->_speed_x*car->_speed_x)/100)-distance)/3))); + double ospeed = opponent[i].getTrueSpeed(); + double try_timer = (0.3 + (1.0 - ((simtime-frontavoidtime)/5.0)/2)) * otry; + double sidedist = fabs(car->_trkPos.toMiddle - opponent[i].getCarPtr()->_trkPos.toMiddle); + double spddiff = (speed - ospeed)*1.5; + catchdist = ((double) MIN(speed*distance/(spddiff), distance*CATCH_FACTOR) + (speed * caution)) * (1.0 + try_timer); + double sdiff = ((distance - MAX(0.0, 5.0-sidedist)) - (spddiff)*2); - if (catchdist < mincatchdist && speed >= ospeed && sdiff < speed/(3+caution)) - { - double aspeed = speed+1.0; - double aspeed2 = aspeed-3.0; - if (truespeed < currentspeed) - speed -= currentspeed - truespeed; - if (rldata->avspeed < currentspeed && car->_accel_x < -2.0 && - ((rInverse > 0.001 && speedangle < 0.0) || - (rInverse < -0.001 && speedangle > 0.0))) - speed -= fabs(speedangle*4); - - if (speed > ospeed) - catchdist = ((double) MIN(speed*distance/(spddiff), distance*CATCH_FACTOR) + (speed * caution)) * (0.6 + try_timer); - else - catchdist = 10000.0; + if (catchdist < mincatchdist && speed >= ospeed && sdiff < speed/(3+caution)) + { + double aspeed = speed+1.0; + double aspeed2 = aspeed-3.0; + if (truespeed < currentspeed) + speed -= currentspeed - truespeed; + if (rldata->avspeed < currentspeed && car->_accel_x < -2.0 && + ((rInverse > 0.001 && speedangle < 0.0) || + (rInverse < -0.001 && speedangle > 0.0))) + speed -= fabs(speedangle*4); + + if (speed > ospeed) + catchdist = ((double) MIN(speed*distance/(spddiff), distance*CATCH_FACTOR) + (speed * caution)) * (0.6 + try_timer); + else + catchdist = 10000.0; - if (catchdist < mincatchdist) // && ((catchdist < MAX(20.0, (distance * 3 + (speed-ospeed)))) || distance + caution < 3.0 + MIN(50.0, car->_speed_x)/15)) - { - - double mradius = MAX(5.0, 100.0 - fabs(rInverse) * 5000); - int odiv = (rldata->thisdiv + int(distance/3)); - double oradius = MAX(5.0, 100.0 - fabs(raceline->getRInverse(odiv)) * 5000); + if (catchdist < mincatchdist) // && ((catchdist < MAX(20.0, (distance * 3 + (speed-ospeed)))) || distance + caution < 3.0 + MIN(50.0, car->_speed_x)/15)) + { + + double mradius = MAX(5.0, 100.0 - fabs(rInverse) * 5000); + int odiv = (rldata->thisdiv + int(distance/3)); + double oradius = MAX(5.0, 100.0 - fabs(raceline->getRInverse(odiv)) * 5000); - if (simtime > 1.0 && - (catchdist < MIN(MIN(500.0, aspeed*7.0), MIN(mradius, oradius)*1.5) && - distance < MAX(3.0, MIN(speed, aspeed2)/4 + (aspeed2-ospeed)) && - ospeed < MAX(10.0, aspeed))) - { + if (simtime > 1.0 && + (catchdist < MIN(MIN(500.0, aspeed*7.0), MIN(mradius, oradius)*1.5) && + distance < MAX(3.0, MIN(speed, aspeed2)/4 + (aspeed2-ospeed)) && + ospeed < MAX(10.0, aspeed))) + { if (DebugMsg & debug_overtake) fprintf(stderr,"%s -> %s (%.1f < %.1f (ot=%.2f))\n",car->_name,ocar->_name,catchdist,mincatchdist,caution);fflush(stderr); - mincatchdist = catchdist; - o = &opponent[i]; - otry_success = otry; - } - } + mincatchdist = catchdist; + o = &opponent[i]; + otry_success = otry; + } + } else if (DebugMsg & debug_overtake) fprintf(stderr,"%s -> %s CANCEL 2 (%.1f > %.1f || %.1f < %.1f || %.3f > %.3f)\n",car->_name,ocar->_name,catchdist,mincatchdist,speed,ospeed,sdiff,speed/(3+caution)); - } + } else if (DebugMsg & debug_overtake) fprintf(stderr,"%s -> %s CANCEL 1 (%.1f > %.1f || %.1f < %.1f || %.3f > %.3f)\n",car->_name,ocar->_name,catchdist,mincatchdist,speed,ospeed,sdiff,speed/(3+caution)); #endif - } - } + } + } - if (o || mode != mode_avoiding) break; - } + if (o || mode != mode_avoiding) break; + } - if (o != NULL) - { - tCarElt *ocar = o->getCarPtr(); + if (o != NULL) + { + tCarElt *ocar = o->getCarPtr(); - // Compute the width around the middle which we can use for overtaking. - //float w = ocar->_trkPos.seg->width/WIDTHDIV-BORDER_OVERTAKE_MARGIN; - // Compute the opponents distance to the middle. - //float otm = ocar->_trkPos.toMiddle; - // Define the with of the middle range. - //float wm = ocar->_trkPos.seg->width*CENTERDIV; - float sidedist = fabs(car->_trkPos.toMiddle-ocar->_trkPos.toMiddle); - //double sdist = (rInverse > 0.0 ? (-sidedist - 3.0) : (sidedist - 3.0)); + // Compute the width around the middle which we can use for overtaking. + //float w = ocar->_trkPos.seg->width/WIDTHDIV-BORDER_OVERTAKE_MARGIN; + // Compute the opponents distance to the middle. + //float otm = ocar->_trkPos.toMiddle; + // Define the with of the middle range. + //float wm = ocar->_trkPos.seg->width*CENTERDIV; + float sidedist = fabs(car->_trkPos.toMiddle-ocar->_trkPos.toMiddle); + //double sdist = (rInverse > 0.0 ? (-sidedist - 3.0) : (sidedist - 3.0)); - //int avoidingside = (otm > wm && myoffset > -w) ? TR_RGT : ((otm < -wm && myoffset < w) ? TR_LFT : TR_STR); - int avoidingside = (car->_trkPos.toLeft > ocar->_trkPos.toLeft ? TR_LFT : TR_RGT); - int mustmove = 0; - int cancelovertake = 0; - double distance = o->getDistance(); + //int avoidingside = (otm > wm && myoffset > -w) ? TR_RGT : ((otm < -wm && myoffset < w) ? TR_LFT : TR_STR); + int avoidingside = (car->_trkPos.toLeft > ocar->_trkPos.toLeft ? TR_LFT : TR_RGT); + int mustmove = 0; + int cancelovertake = 0; + double distance = o->getDistance(); - if (avoidingside != TR_STR) - { - int newside = checkSwitch(avoidingside, o, ocar); + if (avoidingside != TR_STR) + { + int newside = checkSwitch(avoidingside, o, ocar); if (DebugMsg & debug_overtake) fprintf(stderr," AVOIDING A %c\n",(avoidingside==TR_LFT?'L':'R')); - if (newside != avoidingside) - { + if (newside != avoidingside) + { if (DebugMsg & debug_overtake) fprintf(stderr," SWITCH 1 from %c to %c\n",(avoidingside==TR_LFT?'L':'R'),(newside==TR_LFT?'L':'R')); - avoidingside = newside; - mustmove = 1; - } + avoidingside = newside; + mustmove = 1; + } - if ((((avoidingside == prefer_side && prefer_side != TR_STR) || (avoidingside == car->_trkPos.seg->type)) && distance > 1.0) || - rldata->braking <= 0.0) - { + if ((((avoidingside == prefer_side && prefer_side != TR_STR) || (avoidingside == car->_trkPos.seg->type)) && distance > 1.0) || + rldata->braking <= 0.0) + { #if 1 - if (!(canOvertake(o, &mincatchdist, true, false))) - { + if (!(canOvertake(o, &mincatchdist, true, false))) + { if (DebugMsg & debug_overtake) fprintf(stderr," CANCEL :(\n"); - cancelovertake = 1; - } + cancelovertake = 1; + } #else - if ((rInverse > 0.0 && angle > 0.0) || (rInverse < 0.0 && angle < 0.0)) - caution += fabs(speedangle-angle) * 20; + if ((rInverse > 0.0 && angle > 0.0) || (rInverse < 0.0 && angle < 0.0)) + caution += fabs(speedangle-angle) * 20; - double cdistance = o->getDistance() + (fabs(rInverse)*700); - double truespeed = getTrueSpeed(); - double truespeed2 = truespeed + MAX(0.0, 6.0 - fabs(rInverse)*700); - //double speed = MIN(truespeed2, MIN(rldata->avspeed, truespeed+MAX(1.0, cdistance+1.0))); - double speed = MIN(truespeed2, MIN(rldata->avspeed, truespeed+MAX(1.0, (((car->_speed_x*car->_speed_x)/100)-cdistance)/4))); - double ospeed = o->getTrueSpeed() * (1.0 + fabs(rInverse)*50); - catchdist = ((double) MIN(speed*cdistance/(speed-ospeed), cdistance*CATCH_FACTOR) + (speed * caution)) * (1.0 + fabs(rInverse)*120); - //double sdiff = ((distance + MAX(0.0, 10.0-sdist*2)) - (speed - ospeed)*2); - double sdiff = (sdist*3+(speed-ospeed)) - distance * (1.0 + fabs(rInverse*80)); + double cdistance = o->getDistance() + (fabs(rInverse)*700); + double truespeed = getTrueSpeed(); + double truespeed2 = truespeed + MAX(0.0, 6.0 - fabs(rInverse)*700); + //double speed = MIN(truespeed2, MIN(rldata->avspeed, truespeed+MAX(1.0, cdistance+1.0))); + double speed = MIN(truespeed2, MIN(rldata->avspeed, truespeed+MAX(1.0, (((car->_speed_x*car->_speed_x)/100)-cdistance)/4))); + double ospeed = o->getTrueSpeed() * (1.0 + fabs(rInverse)*50); + catchdist = ((double) MIN(speed*cdistance/(speed-ospeed), cdistance*CATCH_FACTOR) + (speed * caution)) * (1.0 + fabs(rInverse)*120); + //double sdiff = ((distance + MAX(0.0, 10.0-sdist*2)) - (speed - ospeed)*2); + double sdiff = (sdist*3+(speed-ospeed)) - distance * (1.0 + fabs(rInverse*80)); - if ((catchdist > MAX(20.0 + sdist*2, (cdistance * 3 + (speed-ospeed)))) || sdiff < 0.0) - { - cancelovertake = 1; - avoidmode = 0; + if ((catchdist > MAX(20.0 + sdist*2, (cdistance * 3 + (speed-ospeed)))) || sdiff < 0.0) + { + cancelovertake = 1; + avoidmode = 0; if (DebugMsg & debug_overtake) fprintf(stderr,"%s -> %s CANCEL 3 (%.1f < %.1f)\n",car->_name,ocar->_name,catchdist,mincatchdist);fflush(stderr); - } + } #endif - } - } + } + } - if (!cancelovertake) - { - if (avoidingside == TR_LFT) - { - sidedist -= (speedangle - o->getSpeedAngle()) * 20; - if (mustmove || - sidedist < car->_dimension_y + ocar->_dimension_y + 2.0 || - (o->getState() & OPP_COLL) || - (prefer_side == TR_RGT && car->_trkPos.toRight > MIN(lane2right, 3.0 - nextCRinverse*1000))) - { - double rinc = OVERTAKE_OFFSET_INC * rgtinc; - if (rInverse > 0.0) - rinc += rInverse * 200 * IncFactor; - myoffset -= (float) rinc; + if (!cancelovertake) + { + if (avoidingside == TR_LFT) + { + sidedist -= (speedangle - o->getSpeedAngle()) * 20; + if (mustmove || + sidedist < car->_dimension_y + ocar->_dimension_y + 2.0 || + (o->getState() & OPP_COLL) || + (prefer_side == TR_RGT && car->_trkPos.toRight > MIN(lane2right, 3.0 - nextCRinverse*1000))) + { + double rinc = OVERTAKE_OFFSET_INC * rgtinc; + if (rInverse > 0.0) + rinc += rInverse * 200 * IncFactor; + myoffset -= (float) rinc; if (DebugMsg & debug_overtake) fprintf(stderr,"%s LFT %s, MOVING RIGHT %.3f/%.3f -> %.3f (rgtinc=%.2f (%.2f) rinc=%.2f)\n",car->_name,ocar->_name,(float) (OVERTAKE_OFFSET_INC*rgtinc),rinc,myoffset,rgtinc,lftinc,rinc); - avoidmovt = 1; - } - else if (sidedist > car->_dimension_y + ocar->_dimension_y + 4.0 && - car->_trkPos.toRight < MIN(lane2right-1.0, 4.0 + fabs(nextCRinverse)*1000)) - { + avoidmovt = 1; + } + else if (sidedist > car->_dimension_y + ocar->_dimension_y + 4.0 && + car->_trkPos.toRight < MIN(lane2right-1.0, 4.0 + fabs(nextCRinverse)*1000)) + { if (DebugMsg & debug_overtake) fprintf(stderr,"%s LFT %s, MOVING BACK TO LEFT %.3f\n",car->_name,ocar->_name,(float) (OVERTAKE_OFFSET_INC*lftinc/2)); - myoffset += (float) (OVERTAKE_OFFSET_INC*lftinc)/2; - if (!avoidmode) - avoidtime = MIN(simtime, avoidtime+deltaTime); - } + myoffset += (float) (OVERTAKE_OFFSET_INC*lftinc)/2; + if (!avoidmode) + avoidtime = MIN(simtime, avoidtime+deltaTime); + } else if (DebugMsg & debug_overtake) fprintf(stderr,"%s LFT %s, HOLDING LINE\n",car->_name,ocar->_name); - } - else if (avoidingside == TR_RGT) - { - sidedist -= (o->getSpeedAngle() - speedangle) * 20; - if (mustmove || - sidedist < car->_dimension_y + ocar->_dimension_y + 2.0 || - (o->getState() & OPP_COLL) || - (prefer_side == TR_LFT && car->_trkPos.toLeft > MIN(lane2left, 3.0 + nextCRinverse*1000))) - { + } + else if (avoidingside == TR_RGT) + { + sidedist -= (o->getSpeedAngle() - speedangle) * 20; + if (mustmove || + sidedist < car->_dimension_y + ocar->_dimension_y + 2.0 || + (o->getState() & OPP_COLL) || + (prefer_side == TR_LFT && car->_trkPos.toLeft > MIN(lane2left, 3.0 + nextCRinverse*1000))) + { if (DebugMsg & debug_overtake) fprintf(stderr,"%s RGT %s, MOVING LEFT %.3f\n",car->_name,ocar->_name,(float) (OVERTAKE_OFFSET_INC*lftinc)); - double linc = OVERTAKE_OFFSET_INC * lftinc; - if (rInverse < 0.0) - linc -= rInverse * 200 * IncFactor; - myoffset += (float) linc; - avoidmovt = 1; - } - else if (sidedist > car->_dimension_y + ocar->_dimension_y + 4.0 && - car->_trkPos.toLeft < MIN(lane2left-1.0, 4.0 + fabs(nextCRinverse)*1000)) - { + double linc = OVERTAKE_OFFSET_INC * lftinc; + if (rInverse < 0.0) + linc -= rInverse * 200 * IncFactor; + myoffset += (float) linc; + avoidmovt = 1; + } + else if (sidedist > car->_dimension_y + ocar->_dimension_y + 4.0 && + car->_trkPos.toLeft < MIN(lane2left-1.0, 4.0 + fabs(nextCRinverse)*1000)) + { if (DebugMsg & debug_overtake) fprintf(stderr,"%s RGT %s, MOVING BACK TO RIGHT %.3f\n",car->_name,ocar->_name,(float) (OVERTAKE_OFFSET_INC*rgtinc/2)); - myoffset -= (float) (OVERTAKE_OFFSET_INC*rgtinc)/2; - if (!avoidmode) - avoidtime = MIN(simtime, avoidtime+deltaTime); - } + myoffset -= (float) (OVERTAKE_OFFSET_INC*rgtinc)/2; + if (!avoidmode) + avoidtime = MIN(simtime, avoidtime+deltaTime); + } else if (DebugMsg & debug_overtake) fprintf(stderr,"%s RGT %s, HOLDING LINE\n",car->_name,ocar->_name); - } - else - { - // If the opponent is near the middle we try to move the offset toward - // the inside of the expected turn. - // Try to find out the characteristic of the track up to catchdist. - tTrackSeg *seg = car->_trkPos.seg; - float length = getDistToSegEnd(); - float oldlen, seglen = length; - float lenright = 0.0f, lenleft = 0.0f; - mincatchdist = MIN(mincatchdist, DISTCUTOFF); + } + else + { + // If the opponent is near the middle we try to move the offset toward + // the inside of the expected turn. + // Try to find out the characteristic of the track up to catchdist. + tTrackSeg *seg = car->_trkPos.seg; + float length = getDistToSegEnd(); + float oldlen, seglen = length; + float lenright = 0.0f, lenleft = 0.0f; + mincatchdist = MIN(mincatchdist, DISTCUTOFF); - do { - switch (seg->type) { - case TR_LFT: - lenleft += seglen; - break; - case TR_RGT: - lenright += seglen; - break; - default: - // Do nothing. - break; - } - seg = seg->next; - seglen = seg->length; - oldlen = length; - length += seglen; - } while (oldlen < mincatchdist); + do { + switch (seg->type) { + case TR_LFT: + lenleft += seglen; + break; + case TR_RGT: + lenright += seglen; + break; + default: + // Do nothing. + break; + } + seg = seg->next; + seglen = seg->length; + oldlen = length; + length += seglen; + } while (oldlen < mincatchdist); - if (lenleft > lenright) - avoidingside = TR_RGT; - else if (lenright > lenleft) - avoidingside = TR_LFT; + if (lenleft > lenright) + avoidingside = TR_RGT; + else if (lenright > lenleft) + avoidingside = TR_LFT; - // If we are on a straight look for the next turn. - if (avoidingside == TR_STR) - { - while (seg->type == TR_STR) { - seg = seg->next; - } - // Assume: left or right if not straight. - if (seg->type == TR_LFT) { - avoidingside = TR_RGT; - } else { - avoidingside = TR_LFT; - } - } + // If we are on a straight look for the next turn. + if (avoidingside == TR_STR) + { + while (seg->type == TR_STR) { + seg = seg->next; + } + // Assume: left or right if not straight. + if (seg->type == TR_LFT) { + avoidingside = TR_RGT; + } else { + avoidingside = TR_LFT; + } + } - // Because we are inside we can go to the border. - //float maxoff = (float) ((ocar->_trkPos.seg->width - car->_dimension_y)/2.0f-BORDER_OVERTAKE_MARGIN*15); - int newside = checkSwitch( avoidingside, o, ocar ); + // Because we are inside we can go to the border. + //float maxoff = (float) ((ocar->_trkPos.seg->width - car->_dimension_y)/2.0f-BORDER_OVERTAKE_MARGIN*15); + int newside = checkSwitch( avoidingside, o, ocar ); if (DebugMsg & debug_overtake) fprintf(stderr," AVOIDING %c\n",(avoidingside==TR_LFT?'l':'r')); - if (newside != avoidingside) - { + if (newside != avoidingside) + { if (DebugMsg & debug_overtake) fprintf(stderr," SWITCH 2 from %c to %c\n",(avoidingside==TR_LFT?'l':'r'),(newside==TR_LFT?'l':'r')); - avoidingside = newside; - mustmove = 1; - } + avoidingside = newside; + mustmove = 1; + } - if (prefer_side != TR_STR && avoidingside == prefer_side) - { + if (prefer_side != TR_STR && avoidingside == prefer_side) + { #if 1 - if (!(canOvertake(o, &mincatchdist, true, false))) - cancelovertake = 1; + if (!(canOvertake(o, &mincatchdist, true, false))) + cancelovertake = 1; #else - double cdistance = o->getDistance() + (fabs(rInverse)*700); - double truespeed = getTrueSpeed(); - double truespeed2 = truespeed + MAX(0.0, 6.0 - fabs(rInverse)*700); - //double speed = MIN(truespeed2, MIN(rldata->avspeed, truespeed+MAX(1.0, cdistance+1.0))); - double speed = MIN(truespeed2, MIN(rldata->avspeed, truespeed+MAX(1.0, (((car->_speed_x*car->_speed_x)/100)-cdistance)/4))); - double ospeed = o->getTrueSpeed() * (1.0 + fabs(rInverse)*50); - catchdist = ((double) MIN(speed*cdistance/(speed-ospeed), cdistance*CATCH_FACTOR) + (speed * caution)) * (1.0 + fabs(rInverse)*120); - double sdiff = (sdist*3+(speed-ospeed)) - distance * (1.0 + fabs(rInverse*80)); - - if ((catchdist > MAX(20.0 + sdist*2, (cdistance * 3 + (speed-ospeed)))) || sdiff < 0.0) - { + double cdistance = o->getDistance() + (fabs(rInverse)*700); + double truespeed = getTrueSpeed(); + double truespeed2 = truespeed + MAX(0.0, 6.0 - fabs(rInverse)*700); + //double speed = MIN(truespeed2, MIN(rldata->avspeed, truespeed+MAX(1.0, cdistance+1.0))); + double speed = MIN(truespeed2, MIN(rldata->avspeed, truespeed+MAX(1.0, (((car->_speed_x*car->_speed_x)/100)-cdistance)/4))); + double ospeed = o->getTrueSpeed() * (1.0 + fabs(rInverse)*50); + catchdist = ((double) MIN(speed*cdistance/(speed-ospeed), cdistance*CATCH_FACTOR) + (speed * caution)) * (1.0 + fabs(rInverse)*120); + double sdiff = (sdist*3+(speed-ospeed)) - distance * (1.0 + fabs(rInverse*80)); + + if ((catchdist > MAX(20.0 + sdist*2, (cdistance * 3 + (speed-ospeed)))) || sdiff < 0.0) + { if (DebugMsg & debug_overtake) fprintf(stderr,"%s -> %s CANCEL 4 (%.1f < %.1f)\n",car->_name,ocar->_name,catchdist,mincatchdist);fflush(stderr); - cancelovertake = 1; - } + cancelovertake = 1; + } #endif - } + } - if (!cancelovertake) - { - if (mustmove || (o->getState() & OPP_COLL) || sidedist < car->_dimension_y + ocar->_dimension_y + 1.0) - { - if (avoidingside == TR_RGT) - { - sidedist -= (o->getSpeedAngle() - speedangle) * 20; - if (myoffset < maxoffset || - (prefer_side == TR_LFT && car->_trkPos.toLeft > 3.0 + nextCRinverse*1000)) - { + if (!cancelovertake) + { + if (mustmove || (o->getState() & OPP_COLL) || sidedist < car->_dimension_y + ocar->_dimension_y + 1.0) + { + if (avoidingside == TR_RGT) + { + sidedist -= (o->getSpeedAngle() - speedangle) * 20; + if (myoffset < maxoffset || + (prefer_side == TR_LFT && car->_trkPos.toLeft > 3.0 + nextCRinverse*1000)) + { if (DebugMsg & debug_overtake) fprintf(stderr,"%s RGT %s, MOVING LEFT %.3f\n",car->_name,ocar->_name,(float) (OVERTAKE_OFFSET_INC*lftinc)); - myoffset += (float) (OVERTAKE_OFFSET_INC*lftinc); - avoidmovt = 1; - } - else if (sidedist > car->_dimension_y + ocar->_dimension_y + 4.0 && - car->_trkPos.toLeft < 4.0 + fabs(nextCRinverse)*1000) - { + myoffset += (float) (OVERTAKE_OFFSET_INC*lftinc); + avoidmovt = 1; + } + else if (sidedist > car->_dimension_y + ocar->_dimension_y + 4.0 && + car->_trkPos.toLeft < 4.0 + fabs(nextCRinverse)*1000) + { if (DebugMsg & debug_overtake) fprintf(stderr,"%s RGT %s, MOVING BACK TO RIGHT %.3f\n",car->_name,ocar->_name,(float) (OVERTAKE_OFFSET_INC*rgtinc)/2); - myoffset -= (float) (OVERTAKE_OFFSET_INC*rgtinc)/2; - if (!avoidmode) - avoidtime = MIN(simtime, avoidtime+deltaTime); - } + myoffset -= (float) (OVERTAKE_OFFSET_INC*rgtinc)/2; + if (!avoidmode) + avoidtime = MIN(simtime, avoidtime+deltaTime); + } else if (DebugMsg & debug_overtake) fprintf(stderr,"%s RGT %s, NO MOVEMENT\n",car->_name,ocar->_name); - } - else - { - sidedist -= (speedangle - o->getSpeedAngle()) * 20; - if (myoffset > minoffset || - (prefer_side == TR_RGT && car->_trkPos.toRight > 3.0 - nextCRinverse*1000)) - { + } + else + { + sidedist -= (speedangle - o->getSpeedAngle()) * 20; + if (myoffset > minoffset || + (prefer_side == TR_RGT && car->_trkPos.toRight > 3.0 - nextCRinverse*1000)) + { if (DebugMsg & debug_overtake) fprintf(stderr,"%s LFT %s, MOVING RIGHT %.3f -> %.3f\n",car->_name,ocar->_name,(float) (OVERTAKE_OFFSET_INC*rgtinc),myoffset); - myoffset -= (float) (OVERTAKE_OFFSET_INC*rgtinc); - avoidmovt = 1; - } - else if (sidedist > car->_dimension_y + ocar->_dimension_y + 4.0 && - car->_trkPos.toRight < 4.0 + fabs(nextCRinverse)*1000) - { + myoffset -= (float) (OVERTAKE_OFFSET_INC*rgtinc); + avoidmovt = 1; + } + else if (sidedist > car->_dimension_y + ocar->_dimension_y + 4.0 && + car->_trkPos.toRight < 4.0 + fabs(nextCRinverse)*1000) + { if (DebugMsg & debug_overtake) fprintf(stderr,"%s LFT %s, MOVING BACK TO LEFT %.3f\n",car->_name,ocar->_name,(float) (OVERTAKE_OFFSET_INC*lftinc)/2); - myoffset += (float) (OVERTAKE_OFFSET_INC*lftinc)/2; - if (!avoidmode) - avoidtime = MIN(simtime, avoidtime+deltaTime); - } + myoffset += (float) (OVERTAKE_OFFSET_INC*lftinc)/2; + if (!avoidmode) + avoidtime = MIN(simtime, avoidtime+deltaTime); + } else if (DebugMsg & debug_overtake) fprintf(stderr,"%s LFT %s, NO MOVEMENT\n",car->_name,ocar->_name); - } - } - } - } + } + } + } + } - if (!cancelovertake) - { - //if (ocar->_trkPos.toLeft > car->_trkPos.toLeft) - if (avoidingside == TR_RGT) - { - avoidrgtoffset = (float) MAX(avoidrgtoffset, ocar->_trkPos.toMiddle + (o->getWidth()+1.0f)); - avoidmode |= avoidright; - } - else - { - avoidlftoffset = (float) MIN(avoidlftoffset, ocar->_trkPos.toMiddle - (o->getWidth()+1.0f)); - avoidmode |= avoidleft; - } - - if ((avoidingside == TR_LFT && rInverse > 0.0) || - (avoidingside == TR_RGT && rInverse < 0.0)) - avoidtime = MIN(simtime, avoidtime + MIN(deltaTime*0.9, fabs(rInverse*1.2))); + if (!cancelovertake) + { + //if (ocar->_trkPos.toLeft > car->_trkPos.toLeft) + if (avoidingside == TR_RGT) + { + avoidrgtoffset = (float) MAX(avoidrgtoffset, ocar->_trkPos.toMiddle + (o->getWidth()+1.0f)); + avoidmode |= avoidright; + } + else + { + avoidlftoffset = (float) MIN(avoidlftoffset, ocar->_trkPos.toMiddle - (o->getWidth()+1.0f)); + avoidmode |= avoidleft; + } + + if ((avoidingside == TR_LFT && rInverse > 0.0) || + (avoidingside == TR_RGT && rInverse < 0.0)) + avoidtime = MIN(simtime, avoidtime + MIN(deltaTime*0.9, fabs(rInverse*1.2))); - myoffset = (float) (MAX(minoffset, MIN(maxoffset, myoffset))); + myoffset = (float) (MAX(minoffset, MIN(maxoffset, myoffset))); - if (!otry_success) - frontavoidtime = simtime; - } - } - } + if (!otry_success) + frontavoidtime = simtime; + } + } + } - if (!avoidmode) - { - o = NULL; + if (!avoidmode) + { + o = NULL; - // Let overlap or let less damaged team mate pass. - for (i = 0; i < opponents->getNOpponents(); i++) - { - // Let the teammate with less damage overtake to use slipstreaming. - // The position change happens when the damage difference is greater than - // TEAM_DAMAGE_CHANGE_LEAD. - if ((opponent[i].getState() & OPP_LETPASS)) - { - // Behind, larger distances are smaller ("more negative"). - if (opponent[i].getDistance() > mindist) { - mindist = opponent[i].getDistance(); - o = &opponent[i]; - } - } - } + // Let overlap or let less damaged team mate pass. + for (i = 0; i < opponents->getNOpponents(); i++) + { + // Let the teammate with less damage overtake to use slipstreaming. + // The position change happens when the damage difference is greater than + // TEAM_DAMAGE_CHANGE_LEAD. + if ((opponent[i].getState() & OPP_LETPASS)) + { + // Behind, larger distances are smaller ("more negative"). + if (opponent[i].getDistance() > mindist) { + mindist = opponent[i].getDistance(); + o = &opponent[i]; + } + } + } - if (o != NULL) - { - tCarElt *ocar = o->getCarPtr(); - float side = car->_trkPos.toMiddle - ocar->_trkPos.toMiddle; - float w = car->_trkPos.seg->width/WIDTHDIV-BORDER_OVERTAKE_MARGIN; + if (o != NULL) + { + tCarElt *ocar = o->getCarPtr(); + float side = car->_trkPos.toMiddle - ocar->_trkPos.toMiddle; + float w = car->_trkPos.seg->width/WIDTHDIV-BORDER_OVERTAKE_MARGIN; if (DebugMsg & debug_overtake) fprintf(stderr,"%s BEHIND %s (%d %d %d %d)\n",car->_name,ocar->_name,((o->getState() & OPP_LETPASS) && !o->isTeamMate()),(o->isTeamMate() && (car->_dammage - o->getDamage() > TEAM_DAMAGE_CHANGE_LEAD)),((o->getDistance() > -TEAM_REAR_DIST) && (o->getDistance() < -car->_dimension_x)),(car->race.laps == o->getCarPtr()->race.laps)); - if (side > 0.0f) { - if (myoffset < w) { - myoffset += (float) (OVERTAKE_OFFSET_INC*lftinc); - avoidmovt = 1; - } - } else { - if (myoffset > -w) { - myoffset -= (float) (OVERTAKE_OFFSET_INC*rgtinc); - avoidmovt = 1; - } - } + if (side > 0.0f) { + if (myoffset < w) { + myoffset += (float) (OVERTAKE_OFFSET_INC*lftinc); + avoidmovt = 1; + } + } else { + if (myoffset > -w) { + myoffset -= (float) (OVERTAKE_OFFSET_INC*rgtinc); + avoidmovt = 1; + } + } - avoidmode |= avoidback; + avoidmode |= avoidback; - if (ocar->_trkPos.toLeft > car->_trkPos.toLeft) - { - avoidrgtoffset = (float) MAX(avoidrgtoffset, ocar->_trkPos.toMiddle + (o->getWidth()+1.0f)); - avoidmode |= avoidright; - } - else - { - avoidlftoffset = (float) MIN(avoidlftoffset, ocar->_trkPos.toMiddle - (o->getWidth()+1.0f)); - avoidmode |= avoidleft; - } - - myoffset = (float) (MAX(minoffset, MIN(maxoffset, myoffset))); - } - } - } + if (ocar->_trkPos.toLeft > car->_trkPos.toLeft) + { + avoidrgtoffset = (float) MAX(avoidrgtoffset, ocar->_trkPos.toMiddle + (o->getWidth()+1.0f)); + avoidmode |= avoidright; + } + else + { + avoidlftoffset = (float) MIN(avoidlftoffset, ocar->_trkPos.toMiddle - (o->getWidth()+1.0f)); + avoidmode |= avoidleft; + } + + myoffset = (float) (MAX(minoffset, MIN(maxoffset, myoffset))); + } + } + } - if (mode == mode_avoiding && avoidmode == 0) - setMode(mode_correcting); - if (mode == mode_normal) - myoffset = (float) moffset; + if (mode == mode_avoiding && avoidmode == 0) + setMode(mode_correcting); + if (mode == mode_normal) + myoffset = (float) moffset; #if 1 - // no-one to avoid, work back towards raceline - if (mode == mode_correcting && (simtime > 15.0 || car->_speed_x > 20) && simtime > CorrectDelay) - { - double factor = 0.25;//(fabs(car->_trkPos.toMiddle) < car->_trkPos.seg->width/2 + 2.0 ? 0.25 : 1.0); - if (fabs(myoffset) > fabs(rldata->offset)) - { - //double inc = OVERTAKE_OFFSET_INC * MIN(lftinc, rgtinc) * factor; - if (myoffset < rldata->offset && myoffset < 2.0) - myoffset += (float) (MIN(rldata->offset-myoffset, OVERTAKE_OFFSET_INC * rgtinc/3 * factor)); - else if (myoffset > rldata->offset && myoffset > 2.0) - myoffset -= (float) (MIN(myoffset-rldata->offset, OVERTAKE_OFFSET_INC * lftinc/3 * factor)); - } + // no-one to avoid, work back towards raceline + if (mode == mode_correcting && (simtime > 15.0 || car->_speed_x > 20) && simtime > CorrectDelay) + { + double factor = 0.25;//(fabs(car->_trkPos.toMiddle) < car->_trkPos.seg->width/2 + 2.0 ? 0.25 : 1.0); + if (fabs(myoffset) > fabs(rldata->offset)) + { + //double inc = OVERTAKE_OFFSET_INC * MIN(lftinc, rgtinc) * factor; + if (myoffset < rldata->offset && myoffset < 2.0) + myoffset += (float) (MIN(rldata->offset-myoffset, OVERTAKE_OFFSET_INC * rgtinc/3 * factor)); + else if (myoffset > rldata->offset && myoffset > 2.0) + myoffset -= (float) (MIN(myoffset-rldata->offset, OVERTAKE_OFFSET_INC * lftinc/3 * factor)); + } - maxoffset = MIN(moffset+OVERTAKE_OFFSET_INC*lftinc/2, Width/2 - (car->_dimension_y+SideMargin)); - minoffset = MAX(moffset-OVERTAKE_OFFSET_INC*rgtinc/2, -(Width/2 - (car->_dimension_y+SideMargin))); - } + maxoffset = MIN(moffset+OVERTAKE_OFFSET_INC*lftinc/2, Width/2 - (car->_dimension_y+SideMargin)); + minoffset = MAX(moffset-OVERTAKE_OFFSET_INC*rgtinc/2, -(Width/2 - (car->_dimension_y+SideMargin))); + } #endif end_getoffset: - if (avoidmode) - setMode(mode_avoiding); + if (avoidmode) + setMode(mode_avoiding); - if (mode == mode_avoiding && !avoidmovt) - avoidtime = MIN(simtime, avoidtime+deltaTime*1.5); + if (mode == mode_avoiding && !avoidmovt) + avoidtime = MIN(simtime, avoidtime+deltaTime*1.5); -// minoffset = MAX(minoffset, MIN(1.5, rldata->offset)); -// maxoffset = MIN(maxoffset, MAX(track->width - 1.5, rldata->offset)); - { - double mo = myoffset; - myoffset = (float) (MAX(minoffset, MIN(maxoffset, myoffset))); - if (DebugMsg & debug_overtake) - if (mode != mode_normal) - { - fprintf(stderr,"mode=%d max=%.1f(%.1f) min=%.1f(%.1f) myoff=%.1f->%.1f->%.1f\n",mode,maxoffset,oldmax,minoffset,oldmin,car->_trkPos.toMiddle,mo,myoffset); - fflush(stderr); - } - } - return myoffset; +// minoffset = MAX(minoffset, MIN(1.5, rldata->offset)); +// maxoffset = MIN(maxoffset, MAX(track->width - 1.5, rldata->offset)); + { + double mo = myoffset; + myoffset = (float) (MAX(minoffset, MIN(maxoffset, myoffset))); + if (DebugMsg & debug_overtake) + if (mode != mode_normal) + { + fprintf(stderr,"mode=%d max=%.1f(%.1f) min=%.1f(%.1f) myoff=%.1f->%.1f->%.1f\n",mode,maxoffset,oldmax,minoffset,oldmin,car->_trkPos.toMiddle,mo,myoffset); + fflush(stderr); + } + } + return myoffset; } int Driver::checkSwitch( int side, Opponent *o, tCarElt *ocar ) { - double xdist = o->getDistance(); - double t_impact = MAX(0.0, MIN(10.0, o->getTimeImpact())); - if (car->_speed_x - ocar->_speed_x < MIN(5.0, xdist*3)) - t_impact *= (1.0 + (5.0 - (car->_speed_x - ocar->_speed_x))); - t_impact = MIN(3.0, MIN(t_impact, (5.0-(xdist-fabs(rldata->mInverse*1000)))/10)); + double xdist = o->getDistance(); + double t_impact = MAX(0.0, MIN(10.0, o->getTimeImpact())); + if (car->_speed_x - ocar->_speed_x < MIN(5.0, xdist*3)) + t_impact *= (1.0 + (5.0 - (car->_speed_x - ocar->_speed_x))); + t_impact = MIN(3.0, MIN(t_impact, (5.0-(xdist-fabs(rldata->mInverse*1000)))/10)); - double mcatchleft = MAX(1.0, MIN(track->width-1.0, car->_trkPos.toLeft - speedangle * (t_impact * 10))); - double ocatchleft = MAX(1.0, MIN(track->width-1.0, ocar->_trkPos.toLeft - o->getSpeedAngle() * (t_impact * 10))); - double ydist = mcatchleft-ocatchleft; - double sdiff = MAX(0.0, currentspeed - o->getSpeed()); - double radius = MIN(car->_dimension_y*3, fabs(nextCRinverse) * 200); - double speedchange = 0.0; + double mcatchleft = MAX(1.0, MIN(track->width-1.0, car->_trkPos.toLeft - speedangle * (t_impact * 10))); + double ocatchleft = MAX(1.0, MIN(track->width-1.0, ocar->_trkPos.toLeft - o->getSpeedAngle() * (t_impact * 10))); + double ydist = mcatchleft-ocatchleft; + double sdiff = MAX(0.0, currentspeed - o->getSpeed()); + double radius = MIN(car->_dimension_y*3, fabs(nextCRinverse) * 200); + double speedchange = 0.0; - if (prefer_side == side && rldata->speedchange < 0.0 && ocar->_pos > car->_pos) - speedchange = fabs(rldata->speedchange)*3; + if (prefer_side == side && rldata->speedchange < 0.0 && ocar->_pos > car->_pos) + speedchange = fabs(rldata->speedchange)*3; #if 0 - if (fabs(mcatchleft - ocatchleft) < car->_dimension_y + 1.5 + radius && - (fabs(mcatchleft - ocatchleft) < fabs(car->_trkPos.toLeft - ocar->_trkPos.toLeft) || - (side == TR_LFT && ocatchleft > car->_trkPos.seg->width - car->_dimension_y + 1.5 + radius) || - (side == TR_RGT && ocatchleft < car->_dimension_y + 1.5 + radius))) + if (fabs(mcatchleft - ocatchleft) < car->_dimension_y + 1.5 + radius && + (fabs(mcatchleft - ocatchleft) < fabs(car->_trkPos.toLeft - ocar->_trkPos.toLeft) || + (side == TR_LFT && ocatchleft > car->_trkPos.seg->width - car->_dimension_y + 1.5 + radius) || + (side == TR_RGT && ocatchleft < car->_dimension_y + 1.5 + radius))) #endif - { - double switchrad = 1.0 + (side == prefer_side ? radius * 4 : 0); + { + double switchrad = 1.0 + (side == prefer_side ? radius * 4 : 0); - switch (side) - { - case TR_RGT: + switch (side) + { + case TR_RGT: if (DebugMsg & debug_overtake) fprintf(stderr,"CHECKSWITCH: Rgt - ti=%.2f dm=%.1f o=%.2f->%.2f m=%.2f->%.2f\n",t_impact,deltamult,ocar->_trkPos.toLeft,ocatchleft,car->_trkPos.toLeft,mcatchleft); - if (nextCRinverse > 0.0) - radius = 0.0; - if ((side == prefer_side || - ocatchleft < (car->_dimension_y + 3.0 + radius + speedchange) * switchrad || - ocatchleft < (mcatchleft - 1.5) * switchrad) && - xdist > sdiff + ydist + MAX(0.0, angle*10) && - track->width - ocatchleft > (car->_dimension_y + 3.0 + radius + speedchange)) - { + if (nextCRinverse > 0.0) + radius = 0.0; + if ((side == prefer_side || + ocatchleft < (car->_dimension_y + 3.0 + radius + speedchange) * switchrad || + ocatchleft < (mcatchleft - 1.5) * switchrad) && + xdist > sdiff + ydist + MAX(0.0, angle*10) && + track->width - ocatchleft > (car->_dimension_y + 3.0 + radius + speedchange)) + { if (DebugMsg & debug_overtake) fprintf(stderr," Switch to his right (side=lft) - %d %d %d %d\n",(side==prefer_side),(ocatchleftsdiff+ydist+MAX(0.0, angle*10)),(track->width-ocatchleft>(car->_dimension_y+3+radius+speedchange))); - side = TR_LFT; - } - break; + side = TR_LFT; + } + break; - case TR_LFT: - default: + case TR_LFT: + default: if (DebugMsg & debug_overtake) fprintf(stderr,"CHECKSWITCH: Lft - ti=%.2f dm=%.1f o=%.2f->%.2f m=%.2f->%.2f\n",t_impact,deltamult,ocar->_trkPos.toLeft,ocatchleft,car->_trkPos.toLeft,mcatchleft); - if (nextCRinverse < 0.0) - radius = 0.0; - if ((side == prefer_side || - track->width-ocatchleft < (car->_dimension_y + 3.0 + radius + speedchange) * switchrad || - ocatchleft > (mcatchleft + 1.5) * switchrad) && - xdist > sdiff + (-ydist) + MAX(0.0, -angle*10) && - ocatchleft > (car->_dimension_y + 3.0 + radius + speedchange)) - { - side = TR_RGT; - } - break; - } - } + if (nextCRinverse < 0.0) + radius = 0.0; + if ((side == prefer_side || + track->width-ocatchleft < (car->_dimension_y + 3.0 + radius + speedchange) * switchrad || + ocatchleft > (mcatchleft + 1.5) * switchrad) && + xdist > sdiff + (-ydist) + MAX(0.0, -angle*10) && + ocatchleft > (car->_dimension_y + 3.0 + radius + speedchange)) + { + side = TR_RGT; + } + break; + } + } - return side; + return side; } // Update my private data every timestep. void Driver::update(tSituation *s) { - // Update global car data (shared by all instances) just once per timestep. - if (simtime != s->currentTime) { - simtime = s->currentTime; - cardata->update(); - mycardata->updateWalls(); - } - else - { - // always update my car - mycardata->update(); - mycardata->updateWalls(); + // Update global car data (shared by all instances) just once per timestep. + if (simtime != s->currentTime) { + simtime = s->currentTime; + cardata->update(); + mycardata->updateWalls(); + } + else + { + // always update my car + mycardata->update(); + mycardata->updateWalls(); - int nCars = cardata->getNCars(); + int nCars = cardata->getNCars(); - for (int i = 0; i < nCars; i++) - { - // update cars that are close to ours - SingleCardata *cdata = cardata->getCarData(i); - double mdist = car->_distFromStartLine; - double odist = (double) cdata->getDistFromStart(); + for (int i = 0; i < nCars; i++) + { + // update cars that are close to ours + SingleCardata *cdata = cardata->getCarData(i); + double mdist = car->_distFromStartLine; + double odist = (double) cdata->getDistFromStart(); - if (odist > track->length - 30 && mdist < 30) - mdist += track->length; - else if (mdist > track->length - 30 && odist < 30) - odist += track->length; + if (odist > track->length - 30 && mdist < 30) + mdist += track->length; + else if (mdist > track->length - 30 && odist < 30) + odist += track->length; - double dist = fabs(mdist - odist); - if (dist < 60.0) - cdata->update(); - } - } + double dist = fabs(mdist - odist); + if (dist < 60.0) + cdata->update(); + } + } - evalTrueSpeed(); + evalTrueSpeed(); - prefer_side = raceline->findNextCorner( &nextCRinverse ); + prefer_side = raceline->findNextCorner( &nextCRinverse ); - // Update the local data rest. - avgaccel_x += (car->_accel_x - avgaccel_x)/2; - prevspeedangle = speedangle; - speedangle = (float) -(mycardata->getTrackangle() - atan2(car->_speed_Y, car->_speed_X)); - NORM_PI_PI(speedangle); - mass = CARMASS + car->_fuel; - currentspeedsqr = car->_speed_x*car->_speed_x; - currentspeed = getSpeed(); - opponents->update(s, this, DebugMsg); - strategy->update(car, s); + // Update the local data rest. + avgaccel_x += (car->_accel_x - avgaccel_x)/2; + prevspeedangle = speedangle; + speedangle = (float) -(mycardata->getTrackangle() - atan2(car->_speed_Y, car->_speed_X)); + NORM_PI_PI(speedangle); + mass = CARMASS + car->_fuel; + currentspeedsqr = car->_speed_x*car->_speed_x; + currentspeed = getSpeed(); + opponents->update(s, this, DebugMsg); + strategy->update(car, s); - if (car->_state <= RM_CAR_STATE_PIT && !NoPit) - { + if (car->_state <= RM_CAR_STATE_PIT && !NoPit) + { #ifdef SPEED_DREAMS - float DLong, DLat; // Dist to Pit - RtDistToPit(car,track,&DLong,&DLat); + float DLong, DLat; // Dist to Pit + RtDistToPit(car,track,&DLong,&DLat); - if (DLong > 500) - pitStopChecked = false; + if (DLong > 500) + pitStopChecked = false; - if (!pit->getPitstop() - && (!pitStopChecked) - && (DLong < 500) - && (car->_distFromStartLine < pit->getNPitEntry() || car->_distFromStartLine > pit->getNPitEnd())) + if (!pit->getPitstop() + && (!pitStopChecked) + && (DLong < 500) + && (car->_distFromStartLine < pit->getNPitEntry() || car->_distFromStartLine > pit->getNPitEnd())) #else - if (!pit->getPitstop() && (car->_distFromStartLine < pit->getNPitEntry() || car->_distFromStartLine > pit->getNPitEnd())) + if (!pit->getPitstop() && (car->_distFromStartLine < pit->getNPitEntry() || car->_distFromStartLine > pit->getNPitEnd())) #endif - { - bool pitstop = strategy->needPitstop(car, s, opponents); - if (pitstop) - { - pit->setPitstop(pitstop); - pit->needPitstop(pitstop); - } - } + { + bool pitstop = strategy->needPitstop(car, s, opponents); + if (pitstop) + { + pit->setPitstop(pitstop); + pit->needPitstop(pitstop); + } + } - if (pit->getPitstop() && car->_pit) - { - pitpos = PIT_MID; + if (pit->getPitstop() && car->_pit) + { + pitpos = PIT_MID; - for (int i=0; igetNOpponents(); i++) - { - //int idx = opponent[i].getIndex(); - if (opponent[i].getTeam() != TEAM_FRIEND) continue; - if (opponent[i].getCarPtr() == car) continue; - if (opponent[i].getCarPtr()->_state > RM_CAR_STATE_PIT) - continue; + for (int i=0; igetNOpponents(); i++) + { + //int idx = opponent[i].getIndex(); + if (opponent[i].getTeam() != TEAM_FRIEND) continue; + if (opponent[i].getCarPtr() == car) continue; + if (opponent[i].getCarPtr()->_state > RM_CAR_STATE_PIT) + continue; - int opitpos = (int) opponent[i].getCarPtr()->_lightCmd; + int opitpos = (int) opponent[i].getCarPtr()->_lightCmd; - if (opitpos != PIT_NONE && car->_fuel > fuelperlap*1.5 && car->_trkPos.toLeft >= 0.0 && car->_trkPos.toLeft <= track->width) - { - // pit occupied & we've got enough fuel to go around again - pit->setPitstop( 0 ); - pitpos = PIT_NONE; - break; - } + if (opitpos != PIT_NONE && car->_fuel > fuelperlap*1.5 && car->_trkPos.toLeft >= 0.0 && car->_trkPos.toLeft <= track->width) + { + // pit occupied & we've got enough fuel to go around again + pit->setPitstop( 0 ); + pitpos = PIT_NONE; + break; + } - if (opponent[i].getCarPtr()->_pit->pos.seg == car->_pit->pos.seg) - { - // sharing a pit - if (opitpos == PIT_FRONT) - { - double pitloc = pit->getNPitLoc( PIT_MID ); - double myfrompit = pitloc - car->_distFromStartLine; - double opfrompit = pitloc - opponent[i].getCarPtr()->_distFromStartLine; - if (myfrompit < 0.0) myfrompit += track->length; - if (opfrompit < 0.0) opfrompit += track->length; + if (opponent[i].getCarPtr()->_pit->pos.seg == car->_pit->pos.seg) + { + // sharing a pit + if (opitpos == PIT_FRONT) + { + double pitloc = pit->getNPitLoc( PIT_MID ); + double myfrompit = pitloc - car->_distFromStartLine; + double opfrompit = pitloc - opponent[i].getCarPtr()->_distFromStartLine; + if (myfrompit < 0.0) myfrompit += track->length; + if (opfrompit < 0.0) opfrompit += track->length; - // work out who's closest to the pit & therefore should go in front - if (opfrompit > myfrompit) - { - pitpos = PIT_FRONT; - } - else - { - pitpos = PIT_BACK; // go in behind other car - } - } - else - { - pitpos = PIT_FRONT; // stop at end of pit space to leave room - } - } + // work out who's closest to the pit & therefore should go in front + if (opfrompit > myfrompit) + { + pitpos = PIT_FRONT; + } + else + { + pitpos = PIT_BACK; // go in behind other car + } + } + else + { + pitpos = PIT_FRONT; // stop at end of pit space to leave room + } + } - break; - } - } - else if (!pit->getInPit()) - pitpos = PIT_NONE; - } - else - { - pitpos = PIT_NONE; - } + break; + } + } + else if (!pit->getInPit()) + pitpos = PIT_NONE; + } + else + { + pitpos = PIT_NONE; + } #ifdef SPEED_DREAMS - if (pitpos == PIT_NONE) - RtTeamReleasePit(teamIndex); + if (pitpos == PIT_NONE) + RtTeamReleasePit(teamIndex); #else - car->_lightCmd = (char) pitpos; + car->_lightCmd = (char) pitpos; #endif - pit->update(); - alone = isAlone(); - simtime = s->currentTime; + pit->update(); + alone = isAlone(); + simtime = s->currentTime; - float trackangle = RtTrackSideTgAngleL(&(car->_trkPos)); - angle = trackangle - car->_yaw; - NORM_PI_PI(angle); - angle = -angle; + float trackangle = RtTrackSideTgAngleL(&(car->_trkPos)); + angle = trackangle - car->_yaw; + NORM_PI_PI(angle); + angle = -angle; } int Driver::isAlone() { - int i; + int i; - for (i = 0; i < opponents->getNOpponents(); i++) { + for (i = 0; i < opponents->getNOpponents(); i++) { #if 0 - if (opponent[i].getTeam() == TEAM_FRIEND) - continue; + if (opponent[i].getTeam() == TEAM_FRIEND) + continue; #endif - // not a friend - if we're avoiding then we're obviously not alone - if (mode == mode_avoiding) - return 0; + // not a friend - if we're avoiding then we're obviously not alone + if (mode == mode_avoiding) + return 0; - if ((opponent[i].getState() & (OPP_COLL | OPP_LETPASS)) || - ((opponent[i].getState() & (OPP_FRONT)) && opponent[i].getDistance() < MAX(50.0, car->_speed_x*1.5)) || - (fabs(opponent[i].getDistance()) < 50.0)) - { - return 0; // Not alone. - } - } - return 1; // Alone. + if ((opponent[i].getState() & (OPP_COLL | OPP_LETPASS)) || + ((opponent[i].getState() & (OPP_FRONT)) && opponent[i].getDistance() < MAX(50.0, car->_speed_x*1.5)) || + (fabs(opponent[i].getDistance()) < 50.0)) + { + return 0; // Not alone. + } + } + return 1; // Alone. } float Driver::stuckSteering( float steercmd ) { - if (stucksteer > 0.0f) - steercmd = (fabs(steercmd) + stucksteer) / 2; - else - steercmd = -(fabs(steercmd) + fabs(stucksteer)) / 2; - return steercmd; + if (stucksteer > 0.0f) + steercmd = (fabs(steercmd) + stucksteer) / 2; + else + steercmd = -(fabs(steercmd) + fabs(stucksteer)) / 2; + return steercmd; } float Driver::GetSafeStuckAccel() { - // see if wheels are on a bumpy surface - tTrackSeg *rgt_seg = car->_trkPos.seg; - tTrackSeg *lft_seg = car->_trkPos.seg; - double max_rough = 0.0f; - float accel = MAX(0.5f, 1.0f - fabs(angle)/3); - int rgt_off = 0, lft_off = 0; + // see if wheels are on a bumpy surface + tTrackSeg *rgt_seg = car->_trkPos.seg; + tTrackSeg *lft_seg = car->_trkPos.seg; + double max_rough = 0.0f; + float accel = MAX(0.5f, 1.0f - fabs(angle)/3); + int rgt_off = 0, lft_off = 0; - if ((car->priv.wheel[FRNT_RGT].seg != car->_trkPos.seg && car->priv.wheel[FRNT_RGT].seg->style == TR_PLAN && - car->priv.wheel[REAR_RGT].seg != car->_trkPos.seg && car->priv.wheel[FRNT_RGT].seg->style == TR_PLAN)) - { - rgt_seg = car->priv.wheel[REAR_RGT].seg; - if (rgt_seg->style == TR_PLAN && - (rgt_seg->surface->kFriction < car->_trkPos.seg->surface->kFriction*0.7 || - rgt_seg->surface->kRoughness > MAX(0.03, car->_trkPos.seg->surface->kRoughness*1.3) || - rgt_seg->surface->kRollRes > MAX(0.005, car->_trkPos.seg->surface->kRollRes*1.5))) - { - rgt_off = 1; - if (car->_trkPos.toRight < car->_dimension_y - 1.5) - rgt_off = 2; - max_rough = MAX(max_rough, rgt_seg->surface->kRoughness); - } - } + if ((car->priv.wheel[FRNT_RGT].seg != car->_trkPos.seg && car->priv.wheel[FRNT_RGT].seg->style == TR_PLAN && + car->priv.wheel[REAR_RGT].seg != car->_trkPos.seg && car->priv.wheel[FRNT_RGT].seg->style == TR_PLAN)) + { + rgt_seg = car->priv.wheel[REAR_RGT].seg; + if (rgt_seg->style == TR_PLAN && + (rgt_seg->surface->kFriction < car->_trkPos.seg->surface->kFriction*0.7 || + rgt_seg->surface->kRoughness > MAX(0.03, car->_trkPos.seg->surface->kRoughness*1.3) || + rgt_seg->surface->kRollRes > MAX(0.005, car->_trkPos.seg->surface->kRollRes*1.5))) + { + rgt_off = 1; + if (car->_trkPos.toRight < car->_dimension_y - 1.5) + rgt_off = 2; + max_rough = MAX(max_rough, rgt_seg->surface->kRoughness); + } + } - if ((car->priv.wheel[FRNT_LFT].seg != car->_trkPos.seg && car->priv.wheel[FRNT_LFT].seg->style == TR_PLAN && - car->priv.wheel[REAR_LFT].seg != car->_trkPos.seg && car->priv.wheel[REAR_LFT].seg->style == TR_PLAN)) - { - lft_seg = car->priv.wheel[REAR_LFT].seg; - if (lft_seg->style == TR_PLAN && - (lft_seg->surface->kFriction < car->_trkPos.seg->surface->kFriction*0.7 || - lft_seg->surface->kRoughness > MAX(0.03, car->_trkPos.seg->surface->kRoughness*1.3) || - lft_seg->surface->kRollRes > MAX(0.005, car->_trkPos.seg->surface->kRollRes*1.5))) - { - lft_off = 1; - if (car->_trkPos.toRight < car->_dimension_y - 1.5) - lft_off = 2; - max_rough = MAX(max_rough, lft_seg->surface->kRoughness); - } - } + if ((car->priv.wheel[FRNT_LFT].seg != car->_trkPos.seg && car->priv.wheel[FRNT_LFT].seg->style == TR_PLAN && + car->priv.wheel[REAR_LFT].seg != car->_trkPos.seg && car->priv.wheel[REAR_LFT].seg->style == TR_PLAN)) + { + lft_seg = car->priv.wheel[REAR_LFT].seg; + if (lft_seg->style == TR_PLAN && + (lft_seg->surface->kFriction < car->_trkPos.seg->surface->kFriction*0.7 || + lft_seg->surface->kRoughness > MAX(0.03, car->_trkPos.seg->surface->kRoughness*1.3) || + lft_seg->surface->kRollRes > MAX(0.005, car->_trkPos.seg->surface->kRollRes*1.5))) + { + lft_off = 1; + if (car->_trkPos.toRight < car->_dimension_y - 1.5) + lft_off = 2; + max_rough = MAX(max_rough, lft_seg->surface->kRoughness); + } + } - if (lft_off + rgt_off > 0 && (car->_speed_x + fabs(car->_yaw_rate*5) > 3.0)) - { - // at least one wheel on the bumpy stuff and we're moving - accel = MAX(0.2f, MIN(accel, (0.8f - (1.0+fabs(car->_yaw_rate)) * (max_rough*20)))); - } - else if (car->_speed_x > 5.0 && fabs(car->_steerCmd) > fabs(car->_yaw_rate)) - { - // understeering, reduce accel - accel = MAX(0.3f, accel - (fabs(car->_steerCmd) - fabs(car->_yaw_rate))); - } + if (lft_off + rgt_off > 0 && (car->_speed_x + fabs(car->_yaw_rate*5) > 3.0)) + { + // at least one wheel on the bumpy stuff and we're moving + accel = MAX(0.2f, MIN(accel, (0.8f - (1.0+fabs(car->_yaw_rate)) * (max_rough*20)))); + } + else if (car->_speed_x > 5.0 && fabs(car->_steerCmd) > fabs(car->_yaw_rate)) + { + // understeering, reduce accel + accel = MAX(0.3f, accel - (fabs(car->_steerCmd) - fabs(car->_yaw_rate))); + } - return accel; + return accel; } // Check if I'm stuck. bool Driver::isStuck() { - double toSide = MIN(car->_trkPos.toLeft, car->_trkPos.toRight); - double stangle = angle; - double fangle = fabs(angle); + double toSide = MIN(car->_trkPos.toLeft, car->_trkPos.toRight); + double stangle = angle; + double fangle = fabs(angle); - vec2f target = getTargetPoint(false, 0.0); - double targetAngle = atan2(target.y - car->_pos_Y, target.x - car->_pos_X); - double stuck_steer = calcSteer( targetAngle, 0 ); + vec2f target = getTargetPoint(false, 0.0); + double targetAngle = atan2(target.y - car->_pos_Y, target.x - car->_pos_X); + double stuck_steer = calcSteer( targetAngle, 0 ); - if (stangle < 1.0 && stangle > -0.3 && car->_trkPos.toLeft < 1.0) - stangle += MIN(0.5, car->_trkPos.toLeft / 5); - else if (stangle > -1.0 && stangle < 0.3 && car->_trkPos.toRight < 1.0) - stangle -= MIN(0.5, car->_trkPos.toRight / 5); + if (stangle < 1.0 && stangle > -0.3 && car->_trkPos.toLeft < 1.0) + stangle += MIN(0.5, car->_trkPos.toLeft / 5); + else if (stangle > -1.0 && stangle < 0.3 && car->_trkPos.toRight < 1.0) + stangle -= MIN(0.5, car->_trkPos.toRight / 5); - bool returning = ((car->_trkPos.toMiddle > 0.0 && speedangle < -0.2) || - (car->_trkPos.toMiddle < 0.0 && speedangle > 0.2)); - bool departing = ((car->_trkPos.toMiddle > 0.0 && speedangle > 0.2) || - (car->_trkPos.toMiddle < 0.0 && speedangle < -0.2)); - double toWall = toSide; + bool returning = ((car->_trkPos.toMiddle > 0.0 && speedangle < -0.2) || + (car->_trkPos.toMiddle < 0.0 && speedangle > 0.2)); + bool departing = ((car->_trkPos.toMiddle > 0.0 && speedangle > 0.2) || + (car->_trkPos.toMiddle < 0.0 && speedangle < -0.2)); + double toWall = toSide; - // how far to the nearest wall? - if (car->_trkPos.toMiddle < 0.0 && car->_trkPos.seg->side[TR_SIDE_RGT] != NULL) - { - tTrackSeg *seg = car->_trkPos.seg->side[TR_SIDE_RGT]; - if (seg->style == TR_PLAN) - { - toWall += seg->width; - if (seg->side[TR_SIDE_RGT]) - { - seg = seg->side[TR_SIDE_RGT]; - if (seg->style == TR_PLAN) - toWall += seg->width; - } - } - } - else if (car->_trkPos.toMiddle > 0.0 && car->_trkPos.seg->side[TR_SIDE_LFT] != NULL) - { - tTrackSeg *seg = car->_trkPos.seg->side[TR_SIDE_LFT]; - if (seg->style == TR_PLAN) - { - toWall += seg->width; - if (seg->side[TR_SIDE_LFT]) - { - seg = seg->side[TR_SIDE_LFT]; - if (seg->style == TR_PLAN) - toWall += seg->width; - } - } - } + // how far to the nearest wall? + if (car->_trkPos.toMiddle < 0.0 && car->_trkPos.seg->side[TR_SIDE_RGT] != NULL) + { + tTrackSeg *seg = car->_trkPos.seg->side[TR_SIDE_RGT]; + if (seg->style == TR_PLAN) + { + toWall += seg->width; + if (seg->side[TR_SIDE_RGT]) + { + seg = seg->side[TR_SIDE_RGT]; + if (seg->style == TR_PLAN) + toWall += seg->width; + } + } + } + else if (car->_trkPos.toMiddle > 0.0 && car->_trkPos.seg->side[TR_SIDE_LFT] != NULL) + { + tTrackSeg *seg = car->_trkPos.seg->side[TR_SIDE_LFT]; + if (seg->style == TR_PLAN) + { + toWall += seg->width; + if (seg->side[TR_SIDE_LFT]) + { + seg = seg->side[TR_SIDE_LFT]; + if (seg->style == TR_PLAN) + toWall += seg->width; + } + } + } - // update stopped timer - if (fabs(car->_speed_x) > 5.0) - stopped_timer = simtime; + // update stopped timer + if (fabs(car->_speed_x) > 5.0) + stopped_timer = simtime; - if (pit->getInPit()) - { - stuck = 0; - stuck_timer = simtime; - stucksteer = -100.0f; - } + if (pit->getInPit()) + { + stuck = 0; + stuck_timer = simtime; + stucksteer = -100.0f; + } - if (stuck) - { - // stuck - ok to be "unstuck"? - if (fangle < 0.7 && - toSide > 2.0 && - simtime - stuck_timer > 2.0) - { - stuck = 0; - stuck_timer = simtime; - stucksteer = -100.0f; - return false; - } + if (stuck) + { + // stuck - ok to be "unstuck"? + if (fangle < 0.7 && + toSide > 2.0 && + simtime - stuck_timer > 2.0) + { + stuck = 0; + stuck_timer = simtime; + stucksteer = -100.0f; + return false; + } - setMode( mode_correcting ); + setMode( mode_correcting ); - // still stuck - see if we should change gear. - if (stuck == STUCK_REVERSE) - { - // should we give up and go forwards? - if ((simtime - stuck_timer > (1.0 + fangle) && (fabs(car->_speed_x) < 2.0 || !returning)) || - (car->_trkPos.toMiddle > 0.0 && angle < 0.4 && angle > -2.4) || - (car->_trkPos.toMiddle < 0.0 && angle > -0.4 && angle < 2.4)) - { - stuck = STUCK_FORWARD; - stuck_timer = simtime; - } - } - else if (stuck == STUCK_FORWARD) - { - // should we try reverse? - if ((simtime - stuck_timer > MAX(4.0, car->_speed_x/2) && - (fabs(car->_speed_x) < 4.0 || (!returning && fabs(car->_yaw_rate) < 0.4))) || - (car->_trkPos.toRight < 0.0 + fangle && angle < -0.6 && angle > -2.4) || - (car->_trkPos.toLeft < 0.0 + fangle && angle > 0.6 && angle < 2.4)) - { - stuck = STUCK_REVERSE; - stuck_timer = simtime; - } - } - - last_stuck_time = simtime; - } - else if (getSpeed() < 10.0 || toSide < 2.0) - { - // not stuck - but are we? - if (simtime - last_stuck_time > 3.0 && // only get stuck if 3 seconds since we were last stuck - (fangle > MAX(1.0, 1.0 + toSide/5) || - simtime - stopped_timer > 4.0 || - (car->_trkPos.toLeft < 1.0 && car->_trkPos.toMiddle > rldata->offset + 2 && angle > 0.7) || - (car->_trkPos.toRight < 1.0 && car->_trkPos.toMiddle < rldata->offset - 2 && angle < -0.7))) - { - // yes, we're stuck - stuck_timer = last_stuck_time = simtime; - setMode( mode_correcting ); + // still stuck - see if we should change gear. + if (stuck == STUCK_REVERSE) + { + // should we give up and go forwards? + if ((simtime - stuck_timer > (1.0 + fangle) && (fabs(car->_speed_x) < 2.0 || !returning)) || + (car->_trkPos.toMiddle > 0.0 && angle < 0.4 && angle > -2.4) || + (car->_trkPos.toMiddle < 0.0 && angle > -0.4 && angle < 2.4)) + { + stuck = STUCK_FORWARD; + stuck_timer = simtime; + } + } + else if (stuck == STUCK_FORWARD) + { + // should we try reverse? + if ((simtime - stuck_timer > MAX(4.0, car->_speed_x/2) && + (fabs(car->_speed_x) < 4.0 || (!returning && fabs(car->_yaw_rate) < 0.4))) || + (car->_trkPos.toRight < 0.0 + fangle && angle < -0.6 && angle > -2.4) || + (car->_trkPos.toLeft < 0.0 + fangle && angle > 0.6 && angle < 2.4)) + { + stuck = STUCK_REVERSE; + stuck_timer = simtime; + } + } + + last_stuck_time = simtime; + } + else if (getSpeed() < 10.0 || toSide < 2.0) + { + // not stuck - but are we? + if (simtime - last_stuck_time > 3.0 && // only get stuck if 3 seconds since we were last stuck + (fangle > MAX(1.0, 1.0 + toSide/5) || + simtime - stopped_timer > 4.0 || + (car->_trkPos.toLeft < 1.0 && car->_trkPos.toMiddle > rldata->offset + 2 && angle > 0.7) || + (car->_trkPos.toRight < 1.0 && car->_trkPos.toMiddle < rldata->offset - 2 && angle < -0.7))) + { + // yes, we're stuck + stuck_timer = last_stuck_time = simtime; + setMode( mode_correcting ); - stuck = STUCK_REVERSE; + stuck = STUCK_REVERSE; - if ((fangle < 2.0 && currentspeed > 10.0) || - (angle < 0.0 && car->_trkPos.toMiddle > 0.0) || - (angle > 0.0 && car->_trkPos.toMiddle < 0.0) || - (fangle < 1.8 && toWall > 4.0 + fangle*3) || - (fabs(angle - speedangle) * 1.2 && car->_speed_x > 2.0)) - { - stuck = STUCK_FORWARD; - } - } - else - { - // free to keep driving - stucksteer = -100.0f; - stuck = 0; - return false; - } - } - else - { - // free to keep driving - stucksteer = -100.0f; - stuck = 0; - return false; - } + if ((fangle < 2.0 && currentspeed > 10.0) || + (angle < 0.0 && car->_trkPos.toMiddle > 0.0) || + (angle > 0.0 && car->_trkPos.toMiddle < 0.0) || + (fangle < 1.8 && toWall > 4.0 + fangle*3) || + (fabs(angle - speedangle) * 1.2 && car->_speed_x > 2.0)) + { + stuck = STUCK_FORWARD; + } + } + else + { + // free to keep driving + stucksteer = -100.0f; + stuck = 0; + return false; + } + } + else + { + // free to keep driving + stucksteer = -100.0f; + stuck = 0; + return false; + } - // seeing we're stuck, determine steering, braking, accel - if (fangle > 1.7) - { - stuck_steer = -stuck_steer; - if (stuck_steer > 0.0) - stuck_steer = 1.0; - else - stuck_steer = -1.0; - } - else if (car->_speed_x > 5.0 && fangle < 0.6 && stuck == STUCK_FORWARD && - ((car->_trkPos.toLeft < 2.0 && racesteer < stuck_steer) || - (car->_trkPos.toRight < 2.0 && racesteer > stuck_steer))) - { - stuck_steer += MAX(-0.15, MIN(0.15, racesteer - stuck_steer)); - } + // seeing we're stuck, determine steering, braking, accel + if (fangle > 1.7) + { + stuck_steer = -stuck_steer; + if (stuck_steer > 0.0) + stuck_steer = 1.0; + else + stuck_steer = -1.0; + } + else if (car->_speed_x > 5.0 && fangle < 0.6 && stuck == STUCK_FORWARD && + ((car->_trkPos.toLeft < 2.0 && racesteer < stuck_steer) || + (car->_trkPos.toRight < 2.0 && racesteer > stuck_steer))) + { + stuck_steer += MAX(-0.15, MIN(0.15, racesteer - stuck_steer)); + } - if (stucksteer < -99.0f) - { - stucksteer = stuck_steer; - } - else - { - if (stuck == STUCK_FORWARD && - ((stucksteer > 0.0 && stuck_steer < 0.0) || (stucksteer < 0.0 && stuck_steer > 0.0)) && - fabs(angle) < 1.6) - stucksteer = stuck_steer; - else if (stucksteer > 0.0) - stucksteer = fabs(stuck_steer); - else - stucksteer = -fabs(stuck_steer); - } + if (stucksteer < -99.0f) + { + stucksteer = stuck_steer; + } + else + { + if (stuck == STUCK_FORWARD && + ((stucksteer > 0.0 && stuck_steer < 0.0) || (stucksteer < 0.0 && stuck_steer > 0.0)) && + fabs(angle) < 1.6) + stucksteer = stuck_steer; + else if (stucksteer > 0.0) + stucksteer = fabs(stuck_steer); + else + stucksteer = -fabs(stuck_steer); + } - if (stuck == STUCK_REVERSE) - { - car->_steerCmd = -stucksteer*1.4; + if (stuck == STUCK_REVERSE) + { + car->_steerCmd = -stucksteer*1.4; - if (car->_speed_x > 3.0 || (toSide < 0.0 && departing)) - { - car->_accelCmd = 0.0f; - car->_brakeCmd = 0.4f; - car->_clutchCmd = 1.0f; - } - else - { - car->_accelCmd = MAX(0.3f, 0.7f + MIN(0.0f, car->_speed_x/40)); - car->_brakeCmd = 0.0f; - car->_clutchCmd = 0.0f; - } + if (car->_speed_x > 3.0 || (toSide < 0.0 && departing)) + { + car->_accelCmd = 0.0f; + car->_brakeCmd = 0.4f; + car->_clutchCmd = 1.0f; + } + else + { + car->_accelCmd = MAX(0.3f, 0.7f + MIN(0.0f, car->_speed_x/40)); + car->_brakeCmd = 0.0f; + car->_clutchCmd = 0.0f; + } - car->_gearCmd = -1; - } - else - { - car->_steerCmd = stucksteer; + car->_gearCmd = -1; + } + else + { + car->_steerCmd = stucksteer; - if (car->_speed_x < -3.0) - { - car->_accelCmd = 0.0f; - car->_brakeCmd = 0.4f; - car->_clutchCmd = 1.0f; - } - else - { - car->_brakeCmd = 0.0f; - car->_accelCmd = GetSafeStuckAccel(); - car->_accelCmd = MAX(car->_accelCmd/3, car->_accelCmd - fabs(stucksteer/2)); - if (car->_speed_x < 2.0 || fabs(car->_yaw_rate) < 0.5) - car->_accelCmd = MAX(0.3, car->_accelCmd); - car->_clutchCmd = 0.0f; - } + if (car->_speed_x < -3.0) + { + car->_accelCmd = 0.0f; + car->_brakeCmd = 0.4f; + car->_clutchCmd = 1.0f; + } + else + { + car->_brakeCmd = 0.0f; + car->_accelCmd = GetSafeStuckAccel(); + car->_accelCmd = MAX(car->_accelCmd/3, car->_accelCmd - fabs(stucksteer/2)); + if (car->_speed_x < 2.0 || fabs(car->_yaw_rate) < 0.5) + car->_accelCmd = MAX(0.3, car->_accelCmd); + car->_clutchCmd = 0.0f; + } - car->_gearCmd = 1; - } + car->_gearCmd = 1; + } - return true; + return true; } @@ -3458,390 +3454,390 @@ void Driver::initWheelPos() void Driver::initCa() { - char const *WheelSect[4] = {SECT_FRNTRGTWHEEL, SECT_FRNTLFTWHEEL, SECT_REARRGTWHEEL, SECT_REARLFTWHEEL}; - float rearwingarea = GfParmGetNum(car->_carHandle, SECT_REARWING, PRM_WINGAREA, (char*) NULL, 0.0f); - float rearwingangle = GfParmGetNum(car->_carHandle, SECT_REARWING, PRM_WINGANGLE, (char*) NULL, 0.0f); - float wingca = 1.23f*rearwingarea*sin(rearwingangle); + char const *WheelSect[4] = {SECT_FRNTRGTWHEEL, SECT_FRNTLFTWHEEL, SECT_REARRGTWHEEL, SECT_REARLFTWHEEL}; + float rearwingarea = GfParmGetNum(car->_carHandle, SECT_REARWING, PRM_WINGAREA, (char*) NULL, 0.0f); + float rearwingangle = GfParmGetNum(car->_carHandle, SECT_REARWING, PRM_WINGANGLE, (char*) NULL, 0.0f); + float wingca = 1.23f*rearwingarea*sin(rearwingangle); - float cl = GfParmGetNum(car->_carHandle, SECT_AERODYNAMICS, PRM_FCL, (char*) NULL, 0.0f) + - GfParmGetNum(car->_carHandle, SECT_AERODYNAMICS, PRM_RCL, (char*) NULL, 0.0f); - float h = 0.0f; - int i; - for (i = 0; i < 4; i++) - h += GfParmGetNum(car->_carHandle, WheelSect[i], PRM_RIDEHEIGHT, (char*) NULL, 0.20f); - h*= 1.5f; h = h*h; h = h*h; h = 2.0f * exp(-3.0f*h); - CA = h*cl + 4.0f*wingca; + float cl = GfParmGetNum(car->_carHandle, SECT_AERODYNAMICS, PRM_FCL, (char*) NULL, 0.0f) + + GfParmGetNum(car->_carHandle, SECT_AERODYNAMICS, PRM_RCL, (char*) NULL, 0.0f); + float h = 0.0f; + int i; + for (i = 0; i < 4; i++) + h += GfParmGetNum(car->_carHandle, WheelSect[i], PRM_RIDEHEIGHT, (char*) NULL, 0.20f); + h*= 1.5f; h = h*h; h = h*h; h = 2.0f * exp(-3.0f*h); + CA = h*cl + 4.0f*wingca; } // Compute aerodynamic drag coefficient CW. void Driver::initCw() { - float cx = GfParmGetNum(car->_carHandle, SECT_AERODYNAMICS, PRM_CX, (char*) NULL, 0.0f); - float frontarea = GfParmGetNum(car->_carHandle, SECT_AERODYNAMICS, PRM_FRNTAREA, (char*) NULL, 0.0f); - CW = 0.645f*cx*frontarea; + float cx = GfParmGetNum(car->_carHandle, SECT_AERODYNAMICS, PRM_CX, (char*) NULL, 0.0f); + float frontarea = GfParmGetNum(car->_carHandle, SECT_AERODYNAMICS, PRM_FRNTAREA, (char*) NULL, 0.0f); + CW = 0.645f*cx*frontarea; } // Init the friction coefficient of the the tires. void Driver::initTireMu() { - char const *WheelSect[4] = {SECT_FRNTRGTWHEEL, SECT_FRNTLFTWHEEL, SECT_REARRGTWHEEL, SECT_REARLFTWHEEL}; - float tm = FLT_MAX; - int i; + char const *WheelSect[4] = {SECT_FRNTRGTWHEEL, SECT_FRNTLFTWHEEL, SECT_REARRGTWHEEL, SECT_REARLFTWHEEL}; + float tm = FLT_MAX; + int i; - for (i = 0; i < 4; i++) { - tm = MIN(tm, GfParmGetNum(car->_carHandle, WheelSect[i], PRM_MU, (char*) NULL, 1.0f)); - } - TIREMU = tm; + for (i = 0; i < 4; i++) { + tm = MIN(tm, GfParmGetNum(car->_carHandle, WheelSect[i], PRM_MU, (char*) NULL, 1.0f)); + } + TIREMU = tm; } void Driver::GetSteerPoint( double lookahead, vec2f *rt, double offset, double time ) { - if (offset < -90.0 && mode != mode_normal) - offset = myoffset; + if (offset < -90.0 && mode != mode_normal) + offset = myoffset; - raceline->GetSteerPoint( lookahead, rt, offset, time ); + raceline->GetSteerPoint( lookahead, rt, offset, time ); } // Reduces the brake value such that it fits the speed (more downforce -> more braking). float Driver::filterBrakeSpeed(float brake) { - float weight = (CARMASS + car->_fuel)*G; - float maxForce = weight + CA*MAX_SPEED*MAX_SPEED; - float force = weight + CA*currentspeedsqr; - return brake*force/maxForce; + float weight = (CARMASS + car->_fuel)*G; + float maxForce = weight + CA*MAX_SPEED*MAX_SPEED; + float force = weight + CA*currentspeedsqr; + return brake*force/maxForce; } // Brake filter for pit stop. float Driver::filterBPit(float brake) { - if (pit->getPitstop() && !pit->getInPit()) { - float dl, dw; - RtDistToPit(car, track, &dl, &dw); - if (dl < PIT_BRAKE_AHEAD) { - float mu = car->_trkPos.seg->surface->kFriction*TIREMU*PIT_MU; - if (brakedist(0.0f, mu) > dl) { - return 1.0f; - } - } - } + if (pit->getPitstop() && !pit->getInPit()) { + float dl, dw; + RtDistToPit(car, track, &dl, &dw); + if (dl < PIT_BRAKE_AHEAD) { + float mu = car->_trkPos.seg->surface->kFriction*TIREMU*PIT_MU; + if (brakedist(0.0f, mu) > dl) { + return 1.0f; + } + } + } - if (pit->getInPit()) { - float s = pit->toSplineCoord(car->_distFromStartLine); - // Pit entry. - if (pit->getPitstop()) { - float mu = car->_trkPos.seg->surface->kFriction*TIREMU*PIT_MU; - if (s < pit->getNPitStart()) { - // Brake to pit speed limit. - float dist = pit->getNPitStart() - s; - if (brakedist(pit->getSpeedlimit(), mu) > dist) { - return 1.0f; - } - } else { - // Hold speed limit. - if (currentspeedsqr > pit->getSpeedlimitSqr()) { - return pit->getSpeedLimitBrake(currentspeedsqr); - } - } - // Brake into pit (speed limit 0.0 to stop) - float dist = pit->getNPitLoc(pitpos) - s; - if (pitpos != PIT_BACK && pit->isTimeout(dist)) { - pit->setPitstop(false); - return 0.0f; - } else { - if (brakedist(0.0f, mu) > dist) { - return 2.0f; - } else if (s > pit->getNPitLoc(pitpos)) { - // Stop in the pit. - return 2.0f; - } - } - } else { - // Pit exit. - if (s < pit->getNPitEnd()) { - // Pit speed limit. - if (currentspeedsqr > pit->getSpeedlimitSqr()) { - return pit->getSpeedLimitBrake(currentspeedsqr); - } - } - } - } + if (pit->getInPit()) { + float s = pit->toSplineCoord(car->_distFromStartLine); + // Pit entry. + if (pit->getPitstop()) { + float mu = car->_trkPos.seg->surface->kFriction*TIREMU*PIT_MU; + if (s < pit->getNPitStart()) { + // Brake to pit speed limit. + float dist = pit->getNPitStart() - s; + if (brakedist(pit->getSpeedlimit(), mu) > dist) { + return 1.0f; + } + } else { + // Hold speed limit. + if (currentspeedsqr > pit->getSpeedlimitSqr()) { + return pit->getSpeedLimitBrake(currentspeedsqr); + } + } + // Brake into pit (speed limit 0.0 to stop) + float dist = pit->getNPitLoc(pitpos) - s; + if (pitpos != PIT_BACK && pit->isTimeout(dist)) { + pit->setPitstop(false); + return 0.0f; + } else { + if (brakedist(0.0f, mu) > dist) { + return 2.0f; + } else if (s > pit->getNPitLoc(pitpos)) { + // Stop in the pit. + return 2.0f; + } + } + } else { + // Pit exit. + if (s < pit->getNPitEnd()) { + // Pit speed limit. + if (currentspeedsqr > pit->getSpeedlimitSqr()) { + return pit->getSpeedLimitBrake(currentspeedsqr); + } + } + } + } - return brake; + return brake; } // Brake filter for collision avoidance. float Driver::filterBColl(float brake) { - collision = 0.0f; + collision = 0.0f; - if (simtime < 1.5) - return brake; + if (simtime < 1.5) + return brake; - float mu = car->_trkPos.seg->surface->kFriction * BrakeMu; - int i; - float thisbrake = 0.0f; - for (i = 0; i < opponents->getNOpponents(); i++) - { - if ((opponent[i].getState() & OPP_COLL)) - { - float accel = 0.0f;//opponent[i].getCarPtr()->_accel_x / MAX(1.0, opponent[i].getTimeImpact()*2); - float ospeed = opponent[i].getSpeed() + accel; - float margin = MIN(0.3f, MAX(0.0f, 0.3f - opponent[i].getDistance())); - if ((opponent[i].getState() & OPP_SIDE_COLL) || - brakedist(ospeed, mu) + MIN(1.0, margin + MAX(0.0, (getSpeed()-ospeed)/9)) > opponent[i].getDistance() + accel) - { - accelcmd = 0.0f; - float thiscollision = MAX(0.01f, MIN(5.0f, opponent[i].getTimeImpact())); - //thiscollision = MAX(0.01f, MIN(thiscollision, opponent[i].getDistance()/2)); - if (collision) - collision = MIN(collision, thiscollision); - else - collision = thiscollision; - thisbrake = MAX(thisbrake, (0.3f + (5.0 - collision)/4) * brakeratio); + float mu = car->_trkPos.seg->surface->kFriction * BrakeMu; + int i; + float thisbrake = 0.0f; + for (i = 0; i < opponents->getNOpponents(); i++) + { + if ((opponent[i].getState() & OPP_COLL)) + { + float accel = 0.0f;//opponent[i].getCarPtr()->_accel_x / MAX(1.0, opponent[i].getTimeImpact()*2); + float ospeed = opponent[i].getSpeed() + accel; + float margin = MIN(0.3f, MAX(0.0f, 0.3f - opponent[i].getDistance())); + if ((opponent[i].getState() & OPP_SIDE_COLL) || + brakedist(ospeed, mu) + MIN(1.0, margin + MAX(0.0, (getSpeed()-ospeed)/9)) > opponent[i].getDistance() + accel) + { + accelcmd = 0.0f; + float thiscollision = MAX(0.01f, MIN(5.0f, opponent[i].getTimeImpact())); + //thiscollision = MAX(0.01f, MIN(thiscollision, opponent[i].getDistance()/2)); + if (collision) + collision = MIN(collision, thiscollision); + else + collision = thiscollision; + thisbrake = MAX(thisbrake, (0.3f + (5.0 - collision)/4) * brakeratio); if (DebugMsg & debug_brake) fprintf(stderr,"%s - %s BRAKE: ti=%.3f\n",car->_name,opponent[i].getCarPtr()->_name,opponent[i].getTimeImpact()); - } - } - } - return MAX(thisbrake, brake); + } + } + } + return MAX(thisbrake, brake); } // Antilocking filter for brakes. float Driver::filterABS(float brake) { - if (car->_speed_x < ABS_MINSPEED) return brake; - float origbrake = brake; - //float rearskid = MAX(0.0f, MAX(car->_skid[2], car->_skid[3]) - MAX(car->_skid[0], car->_skid[1])); - int i; - float slip = 0.0f; - for (i = 0; i < 4; i++) { - slip += car->_wheelSpinVel(i) * car->_wheelRadius(i); - } - //slip *= 1.0f + MAX(rearskid, MAX(fabs(car->_yaw_rate)/10, fabs(angle)/8)); - slip = car->_speed_x - slip/4.0f; - //if (collision) - // slip *= 0.25f; - if (origbrake == 2.0f) - slip *= 0.1f; + if (car->_speed_x < ABS_MINSPEED) return brake; + float origbrake = brake; + //float rearskid = MAX(0.0f, MAX(car->_skid[2], car->_skid[3]) - MAX(car->_skid[0], car->_skid[1])); + int i; + float slip = 0.0f; + for (i = 0; i < 4; i++) { + slip += car->_wheelSpinVel(i) * car->_wheelRadius(i); + } + //slip *= 1.0f + MAX(rearskid, MAX(fabs(car->_yaw_rate)/10, fabs(angle)/8)); + slip = car->_speed_x - slip/4.0f; + //if (collision) + // slip *= 0.25f; + if (origbrake == 2.0f) + slip *= 0.1f; - float absslip = (car->_speed_x < 20.0f ? MIN(AbsSlip, AbsRange/2) : AbsSlip); - if (slip > absslip) { - brake = brake - MIN(brake, (slip - absslip)/AbsRange); - } - brake = MAX(brake, MIN(origbrake, 0.1f)); + float absslip = (car->_speed_x < 20.0f ? MIN(AbsSlip, AbsRange/2) : AbsSlip); + if (slip > absslip) { + brake = brake - MIN(brake, (slip - absslip)/AbsRange); + } + brake = MAX(brake, MIN(origbrake, 0.1f)); - //brake = MAX(MIN(origbrake, collision ? 0.15f :0.05f), brake - MAX(fabs(angle), fabs(car->_yaw_rate) / 2)); - brake = (float) (MAX(MIN(origbrake, (collision ? MAX(0.05f, (5.0-collision)/30) : 0.05f)), brake - fabs(angle-speedangle)*0.3)); + //brake = MAX(MIN(origbrake, collision ? 0.15f :0.05f), brake - MAX(fabs(angle), fabs(car->_yaw_rate) / 2)); + brake = (float) (MAX(MIN(origbrake, (collision ? MAX(0.05f, (5.0-collision)/30) : 0.05f)), brake - fabs(angle-speedangle)*0.3)); - if (fbrakecmd) - brake = MAX(brake, fbrakecmd); + if (fbrakecmd) + brake = MAX(brake, fbrakecmd); - return brake; + return brake; } // TCL filter for accelerator pedal. float Driver::filterTCL(float accel) { - if (simtime < 3.0) - return accel; + if (simtime < 3.0) + return accel; - accel = MIN(1.0f, accel); - float accel1 = accel, accel2 = accel, accel3 = accel, accel4 = accel, accel5 = accel; + accel = MIN(1.0f, accel); + float accel1 = accel, accel2 = accel, accel3 = accel, accel4 = accel, accel5 = accel; - if (car->_speed_x > 10.0f && !pit->getInPit()) - { - tTrackSeg *seg = car->_trkPos.seg; - tTrackSeg *wseg0 = car->_wheelSeg(REAR_RGT); - tTrackSeg *wseg1 = car->_wheelSeg(REAR_LFT); - int count = 0; + if (car->_speed_x > 10.0f && !pit->getInPit()) + { + tTrackSeg *seg = car->_trkPos.seg; + tTrackSeg *wseg0 = car->_wheelSeg(REAR_RGT); + tTrackSeg *wseg1 = car->_wheelSeg(REAR_LFT); + int count = 0; - if (wseg0->surface->kRoughness > MAX(0.02, seg->surface->kRoughness*1.2)) - { - accel1 = (float) MAX(0.1f, accel1 - (wseg0->surface->kRoughness-(seg->surface->kRoughness*2.2)) * (wseg0->style == TR_CURB ? 2 : 10)); - if (fabs(car->_steerCmd) > 0.3f) - { - if (car->_steerCmd < 0.0) - car->_steerCmd = MIN(car->_steerCmd*0.3, car->_steerCmd + (wseg0->surface->kRoughness-(seg->surface->kRoughness*2.2)) * (wseg0->style == TR_CURB ? 2 : 10)); - else - car->_steerCmd = MAX(car->_steerCmd*0.3, car->_steerCmd + (wseg0->surface->kRoughness-(seg->surface->kRoughness*2.2)) * (wseg0->style == TR_CURB ? 2 : 10)); - } - } - if (wseg1->surface->kRoughness > MAX(0.02, seg->surface->kRoughness*1.2)) - { - accel1 = (float) MAX(0.1f, accel1 - (wseg1->surface->kRoughness-(seg->surface->kRoughness*2.2)) * (wseg1->style == TR_CURB ? 2 : 10)); - if (fabs(car->_steerCmd) > 0.3f) - { - if (car->_steerCmd < 0.0) - car->_steerCmd = MIN(car->_steerCmd*0.3, car->_steerCmd - (wseg0->surface->kRoughness-(seg->surface->kRoughness*2.2)) * (wseg0->style == TR_CURB ? 2 : 10)); - else - car->_steerCmd = MAX(car->_steerCmd*0.3, car->_steerCmd - (wseg0->surface->kRoughness-(seg->surface->kRoughness*2.2)) * (wseg0->style == TR_CURB ? 2 : 10)); - } - } + if (wseg0->surface->kRoughness > MAX(0.02, seg->surface->kRoughness*1.2)) + { + accel1 = (float) MAX(0.1f, accel1 - (wseg0->surface->kRoughness-(seg->surface->kRoughness*2.2)) * (wseg0->style == TR_CURB ? 2 : 10)); + if (fabs(car->_steerCmd) > 0.3f) + { + if (car->_steerCmd < 0.0) + car->_steerCmd = MIN(car->_steerCmd*0.3, car->_steerCmd + (wseg0->surface->kRoughness-(seg->surface->kRoughness*2.2)) * (wseg0->style == TR_CURB ? 2 : 10)); + else + car->_steerCmd = MAX(car->_steerCmd*0.3, car->_steerCmd + (wseg0->surface->kRoughness-(seg->surface->kRoughness*2.2)) * (wseg0->style == TR_CURB ? 2 : 10)); + } + } + if (wseg1->surface->kRoughness > MAX(0.02, seg->surface->kRoughness*1.2)) + { + accel1 = (float) MAX(0.1f, accel1 - (wseg1->surface->kRoughness-(seg->surface->kRoughness*2.2)) * (wseg1->style == TR_CURB ? 2 : 10)); + if (fabs(car->_steerCmd) > 0.3f) + { + if (car->_steerCmd < 0.0) + car->_steerCmd = MIN(car->_steerCmd*0.3, car->_steerCmd - (wseg0->surface->kRoughness-(seg->surface->kRoughness*2.2)) * (wseg0->style == TR_CURB ? 2 : 10)); + else + car->_steerCmd = MAX(car->_steerCmd*0.3, car->_steerCmd - (wseg0->surface->kRoughness-(seg->surface->kRoughness*2.2)) * (wseg0->style == TR_CURB ? 2 : 10)); + } + } #if 0 - if (wseg0->surface->kFriction < seg->surface->kFriction) - accel1 = (float) MAX(0.0f, accel1 - (seg->surface->kFriction - wseg0->surface->kFriction)); - if (wseg1->surface->kFriction < seg->surface->kFriction) - accel1 = (float) MAX(0.0f, accel1 - (seg->surface->kFriction - wseg1->surface->kFriction)); + if (wseg0->surface->kFriction < seg->surface->kFriction) + accel1 = (float) MAX(0.0f, accel1 - (seg->surface->kFriction - wseg0->surface->kFriction)); + if (wseg1->surface->kFriction < seg->surface->kFriction) + accel1 = (float) MAX(0.0f, accel1 - (seg->surface->kFriction - wseg1->surface->kFriction)); #endif - - if (wseg0->surface->kRollRes > MAX(0.01, seg->surface->kRollRes*1.2)) - accel1 = (float) MAX(0.0f, accel1 - (wseg0->surface->kRollRes - seg->surface->kRollRes*1.2)*4); - if (wseg1->surface->kRollRes > MAX(0.01, seg->surface->kRollRes*1.2)) - accel1 = (float) MAX(0.0f, accel1 - (wseg1->surface->kRollRes - seg->surface->kRollRes*1.2)*4); + + if (wseg0->surface->kRollRes > MAX(0.01, seg->surface->kRollRes*1.2)) + accel1 = (float) MAX(0.0f, accel1 - (wseg0->surface->kRollRes - seg->surface->kRollRes*1.2)*4); + if (wseg1->surface->kRollRes > MAX(0.01, seg->surface->kRollRes*1.2)) + accel1 = (float) MAX(0.0f, accel1 - (wseg1->surface->kRollRes - seg->surface->kRollRes*1.2)*4); - if (count) - { - if (mode != mode_normal && - ((seg->type == TR_RGT && seg->radius <= 200.0f && car->_trkPos.toLeft < 3.0f) || - (seg->type == TR_LFT && seg->radius <= 200.0f && car->_trkPos.toRight < 3.0f))) - count++; - accel1 = (float) MAX(0.0f, MIN(accel1, (1.0f-(0.25f*count)) - MAX(0.0f, (getSpeed()-car->_speed_x)/10.0f))); - } + if (count) + { + if (mode != mode_normal && + ((seg->type == TR_RGT && seg->radius <= 200.0f && car->_trkPos.toLeft < 3.0f) || + (seg->type == TR_LFT && seg->radius <= 200.0f && car->_trkPos.toRight < 3.0f))) + count++; + accel1 = (float) MAX(0.0f, MIN(accel1, (1.0f-(0.25f*count)) - MAX(0.0f, (getSpeed()-car->_speed_x)/10.0f))); + } - if (fabs(angle) > 1.0) - accel1 = (float) MIN(accel1, 1.0f - (fabs(angle)-1.0)*1.3); - } + if (fabs(angle) > 1.0) + accel1 = (float) MIN(accel1, 1.0f - (fabs(angle)-1.0)*1.3); + } - double turndecel = TurnDecel + rldata->decel; + double turndecel = TurnDecel + rldata->decel; #ifdef CONTROL_SKILL - turndecel += decel_adjust_perc; + turndecel += decel_adjust_perc; #endif - turndecel *= (mode == mode_normal ? 1 : 2); - if (fabs(car->_steerCmd) > 0.02 && turndecel > 0.0) - { - float decel = (float) ((fabs(car->_steerCmd)-0.02f) * (1.0f+fabs(car->_steerCmd)) * 0.7f); - decel *= (float) (turndecel); - if (mode != mode_normal) - { - decel *= 1.0 + rldata->adecel; - } - accel2 = (float) MIN(accel2, MAX(accel2*0.3, 1.0f-decel)); - } + turndecel *= (mode == mode_normal ? 1 : 2); + if (fabs(car->_steerCmd) > 0.02 && turndecel > 0.0) + { + float decel = (float) ((fabs(car->_steerCmd)-0.02f) * (1.0f+fabs(car->_steerCmd)) * 0.7f); + decel *= (float) (turndecel); + if (mode != mode_normal) + { + decel *= 1.0 + rldata->adecel; + } + accel2 = (float) MIN(accel2, MAX(accel2*0.3, 1.0f-decel)); + } - float slip = (this->*GET_DRIVEN_WHEEL_SPEED)() - fabs(car->_speed_x); - if (slip > TclSlip) { - accel3 = accel3 - MIN(accel3, (slip - TclSlip)/TclRange); - } + float slip = (this->*GET_DRIVEN_WHEEL_SPEED)() - fabs(car->_speed_x); + if (slip > TclSlip) { + accel3 = accel3 - MIN(accel3, (slip - TclSlip)/TclRange); + } - double yra = GetModD( tYawRateAccel, rldata->nextdiv ); - if (yra <= 0.0) - yra = YawRateAccel; + double yra = GetModD( tYawRateAccel, rldata->nextdiv ); + if (yra <= 0.0) + yra = YawRateAccel; - accel4 = MAX(0.0, accel4 - fabs(car->_yaw_rate - car->_steerCmd) * yra); + accel4 = MAX(0.0, accel4 - fabs(car->_yaw_rate - car->_steerCmd) * yra); - accel = MAX(accel/4, MIN(accel1, MIN(accel2, MIN(accel4, accel3)))); + accel = MAX(accel/4, MIN(accel1, MIN(accel2, MIN(accel4, accel3)))); - if (mode == mode_normal) - { - accel5 = MAX(0.0, accel5 - rldata->accel_redux); - accel = MIN(accel, accel5); - } + if (mode == mode_normal) + { + accel5 = MAX(0.0, accel5 - rldata->accel_redux); + accel = MIN(accel, accel5); + } - if (accel > 0.9f) - accel = 1.0f; + if (accel > 0.9f) + accel = 1.0f; - if (faccelcmd > 0.0f) - accel = MIN(accel, faccelcmd * 1.2f); + if (faccelcmd > 0.0f) + accel = MIN(accel, faccelcmd * 1.2f); - return accel; + return accel; } // Traction Control (TCL) setup. void Driver::initTCLfilter() { - char *traintype = (char *) GfParmGetStr(car->_carHandle, SECT_DRIVETRAIN, PRM_TYPE, VAL_TRANS_RWD); - if (strcmp(traintype, VAL_TRANS_RWD) == 0) { - GET_DRIVEN_WHEEL_SPEED = &Driver::filterTCL_RWD; - } else if (strcmp(traintype, VAL_TRANS_FWD) == 0) { - GET_DRIVEN_WHEEL_SPEED = &Driver::filterTCL_FWD; - } else if (strcmp(traintype, VAL_TRANS_4WD) == 0) { - GET_DRIVEN_WHEEL_SPEED = &Driver::filterTCL_4WD; - } + char *traintype = (char *) GfParmGetStr(car->_carHandle, SECT_DRIVETRAIN, PRM_TYPE, VAL_TRANS_RWD); + if (strcmp(traintype, VAL_TRANS_RWD) == 0) { + GET_DRIVEN_WHEEL_SPEED = &Driver::filterTCL_RWD; + } else if (strcmp(traintype, VAL_TRANS_FWD) == 0) { + GET_DRIVEN_WHEEL_SPEED = &Driver::filterTCL_FWD; + } else if (strcmp(traintype, VAL_TRANS_4WD) == 0) { + GET_DRIVEN_WHEEL_SPEED = &Driver::filterTCL_4WD; + } } // TCL filter plugin for rear wheel driven cars. float Driver::filterTCL_RWD() { - return (car->_wheelSpinVel(REAR_RGT) + car->_wheelSpinVel(REAR_LFT)) * - car->_wheelRadius(REAR_LFT) / 2.0f; + return (car->_wheelSpinVel(REAR_RGT) + car->_wheelSpinVel(REAR_LFT)) * + car->_wheelRadius(REAR_LFT) / 2.0f; } // TCL filter plugin for front wheel driven cars. float Driver::filterTCL_FWD() { - return (car->_wheelSpinVel(FRNT_RGT) + car->_wheelSpinVel(FRNT_LFT)) * - car->_wheelRadius(FRNT_LFT) / 2.0f; + return (car->_wheelSpinVel(FRNT_RGT) + car->_wheelSpinVel(FRNT_LFT)) * + car->_wheelRadius(FRNT_LFT) / 2.0f; } // TCL filter plugin for all wheel driven cars. float Driver::filterTCL_4WD() { - return ((car->_wheelSpinVel(FRNT_RGT) + car->_wheelSpinVel(FRNT_LFT)) * - car->_wheelRadius(FRNT_LFT) + - (car->_wheelSpinVel(REAR_RGT) + car->_wheelSpinVel(REAR_LFT)) * - car->_wheelRadius(REAR_LFT)) / 4.0f; + return ((car->_wheelSpinVel(FRNT_RGT) + car->_wheelSpinVel(FRNT_LFT)) * + car->_wheelRadius(FRNT_LFT) + + (car->_wheelSpinVel(REAR_RGT) + car->_wheelSpinVel(REAR_LFT)) * + car->_wheelRadius(REAR_LFT)) / 4.0f; } // Hold car on the track. float Driver::filterTrk(float accel) { - return accel; + return accel; - tTrackSeg* seg = car->_trkPos.seg; + tTrackSeg* seg = car->_trkPos.seg; - if (car->_speed_x < MAX_UNSTUCK_SPEED || // Too slow. - pit->getInPit() || // Pit stop. - car->_trkPos.toMiddle*speedangle > 0.0f) // Speedvector points to the inside of the turn. - { - return accel; - } + if (car->_speed_x < MAX_UNSTUCK_SPEED || // Too slow. + pit->getInPit() || // Pit stop. + car->_trkPos.toMiddle*speedangle > 0.0f) // Speedvector points to the inside of the turn. + { + return accel; + } - if (seg->type == TR_STR) { - float tm = fabs(car->_trkPos.toMiddle); - float w = (seg->width - car->_dimension_y)/2.0f ; - if (tm > w) { - return 0.0f; - } else { - return accel; - } - } else { - float sign = (seg->type == TR_RGT) ? -1.0f : 1.0f; - if (car->_trkPos.toMiddle*sign > 0.0f) { - return accel; - } else { - float tm = fabs(car->_trkPos.toMiddle); - float w = seg->width/WIDTHDIV; - if (tm > w) { - return 0.0f; - } else { - return accel; - } - } - } + if (seg->type == TR_STR) { + float tm = fabs(car->_trkPos.toMiddle); + float w = (seg->width - car->_dimension_y)/2.0f ; + if (tm > w) { + return 0.0f; + } else { + return accel; + } + } else { + float sign = (seg->type == TR_RGT) ? -1.0f : 1.0f; + if (car->_trkPos.toMiddle*sign > 0.0f) { + return accel; + } else { + float tm = fabs(car->_trkPos.toMiddle); + float w = seg->width/WIDTHDIV; + if (tm > w) { + return 0.0f; + } else { + return accel; + } + } + } } // Compute the needed distance to brake. float Driver::brakedist(float allowedspeed, float mu) { - float c = mu*G; - float d = (CA*mu + CW)/mass; - float v1sqr = currentspeedsqr; - float v2sqr = allowedspeed*allowedspeed; - return (-log((c + v2sqr*d)/(c + v1sqr*d))/(2.0f*d)) + 1.0; + float c = mu*G; + float d = (CA*mu + CW)/mass; + float v1sqr = currentspeedsqr; + float v2sqr = allowedspeed*allowedspeed; + return (-log((c + v2sqr*d)/(c + v1sqr*d))/(2.0f*d)) + 1.0; }