Improve AI nitro usage
This commit is contained in:
parent
88c2ce7ee5
commit
bf1d8241e3
@ -175,6 +175,7 @@ void SkiddingAI::reset()
|
||||
m_avoid_item_close = false;
|
||||
m_skid_probability_state = SKID_PROBAB_NOT_YET;
|
||||
m_last_item_random = NULL;
|
||||
m_burster = false;
|
||||
|
||||
AIBaseLapController::reset();
|
||||
m_track_node = Graph::UNKNOWN_SECTOR;
|
||||
@ -2178,23 +2179,27 @@ void SkiddingAI::handleNitroAndZipper(float max_safe_speed)
|
||||
int nitro_skill = computeSkill(NITRO_SKILL);
|
||||
int item_skill = computeSkill(ITEM_SKILL);
|
||||
|
||||
//Nitro continue to be advantageous during the fadeout
|
||||
//Nitro continue to be advantageous during the fadeout (nitro ticks continue to tick in the negatives)
|
||||
int nitro_ticks = m_kart->getSpeedIncreaseTicksLeft(MaxSpeed::MS_INCREASE_NITRO);
|
||||
float nitro_time = ( stk_config->ticks2Time(nitro_ticks)
|
||||
float time_until_fadeout = ( stk_config->ticks2Time(nitro_ticks)
|
||||
+ m_kart->getKartProperties()->getNitroFadeOutTime() );
|
||||
float nitro_max_time = m_kart->getKartProperties()->getNitroDuration()
|
||||
+ m_kart->getKartProperties()->getNitroFadeOutTime();
|
||||
|
||||
// Because it takes some time after nitro activation to accelerate to the increased max speed,
|
||||
// the best moment for the next burst of nitro is not when the fade-out has
|
||||
// finished, but it is not either before the fade-out starts.
|
||||
float nitro_max_active = m_kart->getKartProperties()->getNitroDuration();
|
||||
float nitro_max_fadeout = m_kart->getKartProperties()->getNitroFadeOutTime();
|
||||
|
||||
//Nitro skill 0 : don't use
|
||||
//Nitro skill 1 : don't use if the kart is braking, on the ground, has finished the race, has no nitro,
|
||||
//Nitro skill 1 : don't use if the kart is braking, is not on the ground, has finished the race, has no nitro,
|
||||
// has a parachute or an anvil attached, or has a plunger in the face.
|
||||
// Otherwise, use it immediately
|
||||
//Nitro skill 2 : Don't use nitro if there is more than 1,2 seconds of effect/fadeout left. Use it when at
|
||||
// max speed or under 5 of speed (after rescue, etc.). Use it to pass bombs.
|
||||
//Nitro skill 2 : Don't use nitro if there is more than 35% of main effect left..
|
||||
// Use it when at max speed or under 5 of speed (after rescue, etc.). Use it to pass bombs.
|
||||
// Tries to builds a reserve of 4 energy to use towards the end
|
||||
//Nitro skill 3 : Same as level 2, but don't use until 0.5 seconds of effect/fadeout left, and don't use close
|
||||
//Nitro skill 3 : Same as level 2, but don't use until 10% of main effect left, and don't use close
|
||||
// to bad items, and has a target reserve of 8 energy
|
||||
//Nitro skill 4 : Same as level 3, but don't use until 0.05 seconds of effect/fadeout left and ignore the plunger
|
||||
//Nitro skill 4 : Same as level 3, but don't use until 50% of fadeout left and ignore the plunger
|
||||
// and has a target reserve of 12 energy
|
||||
|
||||
m_controls->setNitro(false);
|
||||
@ -2202,17 +2207,11 @@ void SkiddingAI::handleNitroAndZipper(float max_safe_speed)
|
||||
float energy_reserve = 0;
|
||||
|
||||
if (nitro_skill == 2)
|
||||
{
|
||||
energy_reserve = 4;
|
||||
}
|
||||
if (nitro_skill == 3)
|
||||
{
|
||||
else if (nitro_skill == 3)
|
||||
energy_reserve = 8;
|
||||
}
|
||||
if (nitro_skill == 4)
|
||||
{
|
||||
else if (nitro_skill == 4)
|
||||
energy_reserve = 12;
|
||||
}
|
||||
|
||||
// No point in building a big nitro reserve in nitro for FTL AIs,
|
||||
// just keep enough to help accelerating after an accident
|
||||
@ -2231,17 +2230,12 @@ void SkiddingAI::handleNitroAndZipper(float max_safe_speed)
|
||||
if(m_kart->getBlockedByPlungerTicks()>0)
|
||||
{
|
||||
if ((nitro_skill < 4) && (item_skill < 5))
|
||||
{
|
||||
return;
|
||||
}
|
||||
else if (nitro_skill < 4)
|
||||
{
|
||||
nitro_skill = 0;
|
||||
}
|
||||
else if (item_skill < 5)
|
||||
{
|
||||
item_skill = 0;
|
||||
}
|
||||
// No sle-if because the nitro_skill and item_skill conditions can happen together
|
||||
if (nitro_skill < 4)
|
||||
nitro_skill = 0;
|
||||
if (item_skill < 5)
|
||||
item_skill = 0;
|
||||
}
|
||||
|
||||
// Don't use nitro or zipper if it would make the kart go too fast
|
||||
@ -2265,38 +2259,10 @@ void SkiddingAI::handleNitroAndZipper(float max_safe_speed)
|
||||
{
|
||||
nitro_skill = 0;
|
||||
}
|
||||
|
||||
// Don't use nitro if there is already a nitro boost active
|
||||
// Nitro effect and fadeout varies between karts type from 2 to 4 seconds
|
||||
// So vary time according to kart properties
|
||||
if ((nitro_skill == 4) && nitro_time >= (nitro_max_time*0.01f) )
|
||||
{
|
||||
nitro_skill = 0;
|
||||
}
|
||||
else if ((nitro_skill == 3) && nitro_time >= (nitro_max_time*0.35f) )
|
||||
{
|
||||
nitro_skill = 0;
|
||||
}
|
||||
else if ((nitro_skill == 2) && nitro_time >= (nitro_max_time*0.5f) )
|
||||
{
|
||||
nitro_skill = 0;
|
||||
}
|
||||
|
||||
// If there are items to avoid close
|
||||
// Don't use zippers
|
||||
// Dont use nitro if nitro_skill is 3 or 4
|
||||
// (since going faster makes it harder to avoid items).
|
||||
if(m_avoid_item_close && (m_kart->getEnergy()==0 || nitro_skill == 0 || nitro_skill >= 3) )
|
||||
return;
|
||||
|
||||
// If basic AI, use nitro immediately
|
||||
|
||||
if (nitro_skill == 1)
|
||||
{
|
||||
m_controls->setNitro(true);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// If the AI has a lot of nitro, it should consume it without waiting for some fadeout
|
||||
bool big_reserve = false;
|
||||
|
||||
// Estimate time towards the end of the race.
|
||||
// Decreases the reserve size when there is an estimate of time remaining
|
||||
// to the end of less than 2,5 times the maximum nitro effect duration.
|
||||
@ -2307,42 +2273,58 @@ void SkiddingAI::handleNitroAndZipper(float max_safe_speed)
|
||||
if(nitro_skill >= 2 && energy_reserve > 0.0f)
|
||||
{
|
||||
float finish = m_world->getEstimatedFinishTime(m_kart->getWorldKartId()) - m_world->getTime();
|
||||
float max_time_effect = nitro_max_time / m_kart->getKartProperties()->getNitroConsumption()
|
||||
float max_time_effect = (nitro_max_active + nitro_max_fadeout) / m_kart->getKartProperties()->getNitroConsumption()
|
||||
* m_kart->getEnergy()*2; //the minimum burst consumes around 0.5 energy
|
||||
|
||||
|
||||
// The burster forces the AI to consume its reserve by series of 2 bursts
|
||||
// Otherwise the bursting differences of the various nitro skill wouldn't matter here
|
||||
// In short races, most AI nitro usage may be at the end with the reserve
|
||||
// FIXME : if there is a lot more nitro than can be used, use it by longer/more frequent bursts
|
||||
// FIXME : waiting for the end of the fade-out for the next burst is not optimal
|
||||
// as the kart loses nitro top speed time reaccelerating
|
||||
// FIXME : if the nitro reserve goes over 18, use as soon as practical
|
||||
float burster;
|
||||
|
||||
if ( nitro_time > 0)
|
||||
{
|
||||
burster = 2*nitro_max_time;
|
||||
}
|
||||
else
|
||||
{
|
||||
burster = 0;
|
||||
}
|
||||
if( (2.5f*max_time_effect) >= (finish - burster) )
|
||||
if(m_burster && time_until_fadeout >= 0)
|
||||
energy_reserve = 0;
|
||||
else if (m_burster)
|
||||
m_burster = false;
|
||||
|
||||
if( (2.5f*max_time_effect) >= finish )
|
||||
{
|
||||
// Absolute reduction to avoid small amount of unburned nitro at the end
|
||||
energy_reserve = (finish - burster)/(2.5f*max_time_effect/m_kart->getEnergy()) - 0.5f ;
|
||||
energy_reserve = std::min(energy_reserve, finish/(2.5f*max_time_effect/m_kart->getEnergy()) - 0.5f);
|
||||
}
|
||||
if( (1.8f*max_time_effect) >= finish || m_kart->getEnergy() >= 16)
|
||||
big_reserve = true;
|
||||
}
|
||||
|
||||
// Don't use nitro if there is already a nitro boost active
|
||||
// Nitro effect and fadeout may vary between karts type
|
||||
// So vary time according to kart properties
|
||||
if ( ((nitro_skill == 4) && time_until_fadeout >= (nitro_max_fadeout*0.50f) && !big_reserve)
|
||||
|| ((nitro_skill == 4) && time_until_fadeout >= (nitro_max_fadeout))
|
||||
|| ((nitro_skill == 3) && time_until_fadeout >= (nitro_max_fadeout + nitro_max_active*0.10f))
|
||||
|| ((nitro_skill == 2) && time_until_fadeout >= (nitro_max_fadeout + nitro_max_active*0.35f)))
|
||||
{
|
||||
nitro_skill = 0;
|
||||
}
|
||||
|
||||
// If trying to pass a bomb to a kart faster or far ahead, use nitro reserve
|
||||
if(m_kart->getAttachment()->getType() == Attachment::ATTACH_BOMB
|
||||
&& nitro_skill >= 2 && energy_reserve > 0.0f)
|
||||
{
|
||||
if (m_distance_ahead>10.0f || m_kart_ahead->getSpeed() > m_kart->getSpeed() )
|
||||
{
|
||||
energy_reserve = 0 ;
|
||||
energy_reserve = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// If this kart is the last kart, set nitro reserve to 2
|
||||
const unsigned int num_karts = m_world->getCurrentNumKarts();
|
||||
if(nitro_skill >= 2 && m_kart->getPosition()== (int)num_karts &&
|
||||
num_karts > 1 )
|
||||
{
|
||||
energy_reserve = 0;
|
||||
}
|
||||
|
||||
// TODO : if a kart behind and reasonably close goes faster
|
||||
// and it has a swatter, use nitro to try and dodge the swatter.
|
||||
|
||||
// Don't use nitro if building an energy reserve
|
||||
if (m_kart->getEnergy() <= energy_reserve)
|
||||
@ -2350,31 +2332,25 @@ void SkiddingAI::handleNitroAndZipper(float max_safe_speed)
|
||||
nitro_skill = 0;
|
||||
}
|
||||
|
||||
// If the kart is very slow (e.g. after rescue), use nitro
|
||||
if(nitro_skill > 0 && m_kart->getSpeed()<5 && m_kart->getSpeed()>2)
|
||||
// If basic AI, or if the kart is very slow (e.g. after rescue) but not too much (accident)
|
||||
// or if kart is near the base max speed, use nitro.
|
||||
// This last condition is to profit from the max speed increase
|
||||
// And because it means there should be no slowing down from, e.g. plungers
|
||||
// If the kart has a huge reserve and may not have enough time until the end to ue it,
|
||||
// relax the speed condition.
|
||||
if ( nitro_skill == 1
|
||||
|| (nitro_skill > 1 && ( (m_kart->getSpeed()<5 && m_kart->getSpeed()>2)
|
||||
|| (m_kart->getSpeed()> 0.96f*m_kart->getCurrentMaxSpeed())
|
||||
|| (m_kart->getSpeed()> 0.3f *m_kart->getCurrentMaxSpeed() && big_reserve))) )
|
||||
{
|
||||
m_controls->setNitro(true);
|
||||
return;
|
||||
}
|
||||
|
||||
// If kart is at max speed, use nitro
|
||||
// This is to profit from the max speed increase
|
||||
// And because it means there should be no slowing down from, e.g. plungers
|
||||
if (nitro_skill > 0 && m_kart->getSpeed() > 0.99f*m_kart->getCurrentMaxSpeed() )
|
||||
{
|
||||
m_controls->setNitro(true);
|
||||
return;
|
||||
m_burster = !m_burster;
|
||||
}
|
||||
|
||||
// If this kart is the last kart, and we have nitro, use it.
|
||||
// -------------------------------------------------
|
||||
const unsigned int num_karts = m_world->getCurrentNumKarts();
|
||||
if(nitro_skill > 0 && m_kart->getPosition()== (int)num_karts &&
|
||||
num_karts > 1 )
|
||||
{
|
||||
m_controls->setNitro(true);
|
||||
//TODO : for now we don't disable nitro use when close to bananas and gums,
|
||||
// because it hurts more often than not (when the bad item is avoided)
|
||||
if(m_avoid_item_close)
|
||||
return;
|
||||
}
|
||||
|
||||
// Use zipper
|
||||
if(m_kart->getPowerup()->getType() == PowerupManager::POWERUP_ZIPPER
|
||||
|
@ -190,6 +190,9 @@ private:
|
||||
/** Number of players ahead, used for rubber-banding. */
|
||||
int m_num_players_ahead;
|
||||
|
||||
/** This bool allows to make the AI use nitro by series of two bursts */
|
||||
bool m_burster;
|
||||
|
||||
/** A random number generator to decide if the AI should skid or not. */
|
||||
RandomGenerator m_random_skid;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user