Make rubber-banding distances different between AI karts (#3256)
* Don't generate IRC alerts * Differentiated rubber-banding * Fix #3222 * Small simplification * Use master's version * Fix typo * Use std::sort * Remove useless function call test_ai is only used for profiling without human players
This commit is contained in:
parent
c4cb0201df
commit
30c1e0ca6d
@ -295,10 +295,12 @@
|
||||
distance ahead, the value for the largest distance is used,
|
||||
and similarly if the kart is more than the minimum value
|
||||
behind).
|
||||
speed-cap: Fraction of maximum speed the kart should drive
|
||||
at. Used to slow down karts that are ahead of the player.
|
||||
Note that setting this to a value >1 does NOT increase
|
||||
the speed the kart can drive at!
|
||||
first-speed-cap: Fraction of maximum speed the first AI kart
|
||||
should drive at. Used to slow down karts that are ahead of
|
||||
the player. Note that setting this to a value >1 does NOT
|
||||
increase the speed the kart can drive at!
|
||||
last-speed-cap: same as first-speed-cap, but for last AI kart.
|
||||
AI karts in-between use an average of it with first-speed-cap.
|
||||
collect-item-probability: Probability of the AI actually
|
||||
trying to collect an item (if an item is selected for
|
||||
collection in the first place).
|
||||
@ -315,7 +317,8 @@
|
||||
item-skill="1"
|
||||
collect-avoid-items="false"
|
||||
handle-bomb="false"
|
||||
speed-cap="-10:1.0 -5:0.9 5:0.8 20:0.7 50:0.6"
|
||||
first-speed-cap="-100:1.0 -50:0.9 0:0.85 100:0.65"
|
||||
last-speed-cap="-150:0.92 -50:0.75 50:0.6"
|
||||
max-item-angle="0.7" max-item-angle-high-speed="0.3"
|
||||
bad-item-closeness="6"
|
||||
collect-item-probability="0:0"
|
||||
@ -333,7 +336,8 @@
|
||||
item-skill="2"
|
||||
collect-avoid-items="true"
|
||||
handle-bomb="false"
|
||||
speed-cap="10:1.0 50:0.8"
|
||||
first-speed-cap="20:1.0 60:0.9 100:0.85"
|
||||
last-speed-cap="-50:0.94 0:0.85 100:0.75"
|
||||
max-item-angle="0.7" max-item-angle-high-speed="0.3"
|
||||
bad-item-closeness="6"
|
||||
collect-item-probability="-10:1.0 0:0"
|
||||
@ -351,7 +355,8 @@
|
||||
item-skill="3"
|
||||
collect-avoid-items="true"
|
||||
handle-bomb="true"
|
||||
speed-cap="20:1.0 50:0.8"
|
||||
first-speed-cap="50:1.0 150:0.9"
|
||||
last-speed-cap="0:0.96 80:0.8"
|
||||
max-item-angle="0.7" max-item-angle-high-speed="0.3"
|
||||
bad-item-closeness="6"
|
||||
collect-item-probability="10:1.0 20:0"
|
||||
@ -369,7 +374,8 @@
|
||||
item-skill="4"
|
||||
collect-avoid-items="true"
|
||||
handle-bomb="true"
|
||||
speed-cap="0:1.0"
|
||||
first-speed-cap="0:1.0"
|
||||
last-speed-cap="0:1.0"
|
||||
max-item-angle="0.7" max-item-angle-high-speed="0.3"
|
||||
bad-item-closeness="6"
|
||||
collect-item-probability="0:1.0"
|
||||
|
@ -64,7 +64,8 @@ void AIProperties::load(const XMLNode *ai_node)
|
||||
ai_node->get("collect-item-probability", &m_collect_item_probability );
|
||||
ai_node->get("straight-length-for-zipper",&m_straight_length_for_zipper);
|
||||
ai_node->get("rb-skid-probability", &m_skid_probability );
|
||||
ai_node->get("speed-cap", &m_speed_cap );
|
||||
ai_node->get("first-speed-cap", &m_first_speed_cap );
|
||||
ai_node->get("last-speed-cap", &m_last_speed_cap );
|
||||
ai_node->get("item-skill", &m_item_usage_skill );
|
||||
ai_node->get("collect-avoid-items", &m_collect_avoid_items );
|
||||
ai_node->get("handle-bomb", &m_handle_bomb );
|
||||
@ -108,7 +109,7 @@ void AIProperties::checkAllSet(const std::string &filename) const
|
||||
Log::fatal("AIProperties", "No skid probability defined.");
|
||||
}
|
||||
|
||||
if(m_speed_cap.size()==0)
|
||||
if(m_first_speed_cap.size()==0 || m_last_speed_cap.size()==0)
|
||||
{
|
||||
Log::fatal("AIProperties", "No speed cap defined.");
|
||||
}
|
||||
@ -120,4 +121,18 @@ void AIProperties::checkAllSet(const std::string &filename) const
|
||||
|
||||
} // checkAllSet
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the fraction of maximum speed the AI should drive at, depending
|
||||
* on the distance from the player. */
|
||||
float AIProperties::getSpeedCap(float distance, int ai_position, int num_ai) const
|
||||
{
|
||||
float wfirst = 1.0f;
|
||||
if (num_ai >= 2)
|
||||
wfirst = 1.0f - ( (float) (ai_position-1) / (float) (num_ai-1) );
|
||||
|
||||
return wfirst * m_first_speed_cap.get(distance)
|
||||
+(1-wfirst) * m_last_speed_cap.get(distance);
|
||||
} // getSpeedCap
|
||||
|
||||
/* EOF */
|
||||
|
@ -78,7 +78,8 @@ protected:
|
||||
InterpolationArray m_skid_probability;
|
||||
|
||||
/** To cap maximum speed if the kart is ahead of the player. */
|
||||
InterpolationArray m_speed_cap;
|
||||
InterpolationArray m_first_speed_cap;
|
||||
InterpolationArray m_last_speed_cap;
|
||||
|
||||
/** To determine the probability of selecting an item. */
|
||||
InterpolationArray m_collect_item_probability;
|
||||
@ -146,10 +147,8 @@ public:
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the fraction of maximum speed the AI should drive at, depending
|
||||
* on the distance from the player. */
|
||||
float getSpeedCap(float distance) const
|
||||
{
|
||||
return m_speed_cap.get(distance);
|
||||
} // getSpeedCap
|
||||
float getSpeedCap(float distance, int ai_position, int num_ai) const;
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the probability to collect an item depending on the distance
|
||||
* to the first player kart. */
|
||||
|
@ -308,9 +308,16 @@ void SkiddingAI::update(int ticks)
|
||||
// Get information that is needed by more than 1 of the handling funcs
|
||||
computeNearestKarts();
|
||||
|
||||
int num_ai = m_world->getNumKarts() - race_manager->getNumPlayers();
|
||||
int position_among_ai = m_kart->getPosition() - m_num_players_ahead;
|
||||
|
||||
float speed_cap = m_ai_properties->getSpeedCap(m_distance_to_player,
|
||||
position_among_ai,
|
||||
num_ai);
|
||||
|
||||
m_kart->setSlowdown(MaxSpeed::MS_DECREASE_AI,
|
||||
m_ai_properties->getSpeedCap(m_distance_to_player),
|
||||
/*fade_in_time*/0);
|
||||
speed_cap, /*fade_in_time*/0);
|
||||
|
||||
//Detect if we are going to crash with the track and/or kart
|
||||
checkCrashes(m_kart->getXYZ());
|
||||
determineTrackDirection();
|
||||
@ -1965,23 +1972,58 @@ void SkiddingAI::computeNearestKarts()
|
||||
-m_world->getOverallDistance(m_kart_behind->getWorldKartId());
|
||||
}
|
||||
|
||||
// Compute distance to nearest player kart
|
||||
float max_overall_distance = 0.0f;
|
||||
// Compute distance to target player kart
|
||||
|
||||
float target_overall_distance = 0.0f;
|
||||
float own_overall_distance = m_world->getOverallDistance(m_kart->getWorldKartId());
|
||||
m_num_players_ahead = 0;
|
||||
|
||||
unsigned int n = ProfileWorld::isProfileMode()
|
||||
? 0 : race_manager->getNumPlayers();
|
||||
|
||||
std::vector<float> overall_distance;
|
||||
// Get the players distances
|
||||
for(unsigned int i=0; i<n; i++)
|
||||
{
|
||||
unsigned int kart_id =
|
||||
m_world->getPlayerKart(i)->getWorldKartId();
|
||||
if(m_world->getOverallDistance(kart_id)>max_overall_distance)
|
||||
max_overall_distance = m_world->getOverallDistance(kart_id);
|
||||
unsigned int kart_id = m_world->getPlayerKart(i)->getWorldKartId();
|
||||
overall_distance.push_back(m_world->getOverallDistance(kart_id));
|
||||
}
|
||||
|
||||
// Sort the list
|
||||
std::sort(overall_distance.begin(), overall_distance.end());
|
||||
|
||||
for(unsigned int i=0; i<n; i++)
|
||||
{
|
||||
if(overall_distance[i]>own_overall_distance)
|
||||
m_num_players_ahead++;
|
||||
}
|
||||
|
||||
if(ProfileWorld::isProfileMode())
|
||||
target_overall_distance = 999999.9f; // force best driving
|
||||
// In higher difficulties, rubber band towards the first player,
|
||||
// if at all (SuperTux has currently no rubber banding at all)
|
||||
else if (race_manager->getDifficulty() == RaceManager::DIFFICULTY_HARD ||
|
||||
race_manager->getDifficulty() == RaceManager::DIFFICULTY_BEST)
|
||||
{
|
||||
target_overall_distance = overall_distance[n-1]; // Highest player distance
|
||||
}
|
||||
// Distribute the AIs to players
|
||||
else
|
||||
{
|
||||
int num_ai = m_world->getNumKarts() - race_manager->getNumPlayers();
|
||||
int position_among_ai = m_kart->getPosition() - m_num_players_ahead;
|
||||
// Converts a position among AI to a position among players
|
||||
float ideal_target = ((position_among_ai-1) / ((float) num_ai-1)
|
||||
* ((float) race_manager->getNumPlayers()-1)) + 1.0f;
|
||||
// Substract 1 as index start from 0 and add 0.5 to get rounding
|
||||
// The cast truncate the decimals, so it won't go over n-1
|
||||
// as the highest possible ideal_target is n
|
||||
int target_index = (int) (ideal_target - 0.5f);
|
||||
assert (target_index >= 0 && target_index <= n-1);
|
||||
target_overall_distance = overall_distance[target_index];
|
||||
}
|
||||
if(max_overall_distance==0.0f)
|
||||
max_overall_distance = 999999.9f; // force best driving
|
||||
// Now convert 'maximum overall distance' to distance to player.
|
||||
m_distance_to_player =
|
||||
m_world->getOverallDistance(m_kart->getWorldKartId())
|
||||
- max_overall_distance;
|
||||
m_distance_to_player = own_overall_distance - target_overall_distance;
|
||||
} // computeNearestKarts
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -180,6 +180,9 @@ private:
|
||||
/** Distance to the player, used for rubber-banding. */
|
||||
float m_distance_to_player;
|
||||
|
||||
/** Number of players ahead, used for rubber-banding. */
|
||||
int m_num_players_ahead;
|
||||
|
||||
/** A random number generator to decide if the AI should skid or not. */
|
||||
RandomGenerator m_random_skid;
|
||||
|
||||
|
@ -313,10 +313,7 @@ void SkiddingAI::update(int ticks)
|
||||
|
||||
// Get information that is needed by more than 1 of the handling funcs
|
||||
computeNearestKarts();
|
||||
|
||||
m_kart->setSlowdown(MaxSpeed::MS_DECREASE_AI,
|
||||
m_ai_properties->getSpeedCap(m_distance_to_player),
|
||||
/*fade_in_time*/0);
|
||||
|
||||
//Detect if we are going to crash with the track and/or kart
|
||||
checkCrashes(m_kart->getXYZ());
|
||||
determineTrackDirection();
|
||||
|
Loading…
x
Reference in New Issue
Block a user