Improve AI nitro usage

This commit is contained in:
Alayan 2019-02-26 16:05:08 +01:00
parent 88c2ce7ee5
commit bf1d8241e3
2 changed files with 76 additions and 97 deletions

View File

@ -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

View File

@ -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;