Allow changing the various levels of AI mostly using
the stk_config file. Note at this stage no tuning of easy or medium level was done, this version should behave the same as the hard-coded version. git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/trunk@11736 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
parent
6058c3bcfc
commit
ecc1212c11
@ -215,6 +215,23 @@
|
|||||||
reduce-turn-min="0.2" reduce-turn-max="0.8"/>
|
reduce-turn-min="0.2" reduce-turn-max="0.8"/>
|
||||||
|
|
||||||
<!-- Kart-specific settings used by the AI.
|
<!-- Kart-specific settings used by the AI.
|
||||||
|
use-slipstream: if the AI should try to overtake karts using slipstream.
|
||||||
|
false-start-probability: Probability of a false start.
|
||||||
|
min/max-start-delay: Minimum and maximum start delay.
|
||||||
|
See http://www.humanbenchmark.com/tests/reactiontime/stats.php
|
||||||
|
Average reaction time is around 0.215 s.
|
||||||
|
nitro-usage: "none", "some", "all": if nitro should be used, and
|
||||||
|
how much the AI should try to use it good.
|
||||||
|
non-random-item-usage: If true, use items in a sophisticated way,
|
||||||
|
otherwise use items randomly.
|
||||||
|
collect-avoid-items: if the AI should collect and avoid items,
|
||||||
|
or just ignore them.
|
||||||
|
handle-bomb: If the AI should actively try to pass on a bomb.
|
||||||
|
skidding-threshold: only for old-style skidding: when sharp turn
|
||||||
|
should be triggered. Smaller values means it will sharp turn
|
||||||
|
earlier, resulting in better driving in thight curves.
|
||||||
|
|
||||||
|
|
||||||
max-item-angle: Items that would need more than this change in
|
max-item-angle: Items that would need more than this change in
|
||||||
direction are not considered for collection.
|
direction are not considered for collection.
|
||||||
time-full-steer is the time for the AI to go from neutral steering to
|
time-full-steer is the time for the AI to go from neutral steering to
|
||||||
@ -254,13 +271,50 @@
|
|||||||
Note that setting this to a value >1 does NOT increase
|
Note that setting this to a value >1 does NOT increase
|
||||||
the speed the kart can drive at!
|
the speed the kart can drive at!
|
||||||
-->
|
-->
|
||||||
<ai max-item-angle="0.7" max-item-angle-high-speed="0.3"
|
<ai>
|
||||||
time-full-steer="0.1"
|
<easy use-slipstream="false"
|
||||||
bad-item-closeness="6"
|
false-start-probability="0.08"
|
||||||
straight-length-for-zipper="35"
|
min-start-delay="0.3" max-start-delay="0.5"
|
||||||
rb-skid-probability="-50:1.0 -20:0.7 20:0.2 50:0.0"
|
nitro-usage="none"
|
||||||
speed-cap="10:1.0 50:0.8"/>
|
non-random-item-usage="false"
|
||||||
|
collect-avoid-items="false"
|
||||||
|
handle-bomb="false"
|
||||||
|
skidding-threshold="4.0"
|
||||||
|
max-item-angle="0.7" max-item-angle-high-speed="0.3"
|
||||||
|
time-full-steer="0.1"
|
||||||
|
bad-item-closeness="6"
|
||||||
|
straight-length-for-zipper="35"
|
||||||
|
rb-skid-probability="-50:1.0 -20:0.7 20:0.2 50:0.0"
|
||||||
|
speed-cap="10:1.0 50:0.8"/>
|
||||||
|
<medium use-slipstream="false"
|
||||||
|
false-start-probability="0.04"
|
||||||
|
min-start-delay="0.25" max-start-delay="0.4"
|
||||||
|
nitro-usage="some"
|
||||||
|
non-random-item-usage="false"
|
||||||
|
collect-avoid-items="true"
|
||||||
|
handle-bomb="false"
|
||||||
|
skidding-threshold="3.0"
|
||||||
|
max-item-angle="0.7" max-item-angle-high-speed="0.3"
|
||||||
|
time-full-steer="0.1"
|
||||||
|
bad-item-closeness="6"
|
||||||
|
straight-length-for-zipper="35"
|
||||||
|
rb-skid-probability="-50:1.0 -20:0.7 20:0.2 50:0.0"
|
||||||
|
speed-cap="10:1.0 50:0.8"/>
|
||||||
|
<hard use-slipstream="true"
|
||||||
|
false-start-probability="0.01"
|
||||||
|
min-start-delay="0.15" max-start-delay="0.28"
|
||||||
|
nitro-usage="all"
|
||||||
|
non-random-item-usage="false"
|
||||||
|
collect-avoid-items="true"
|
||||||
|
handle-bomb="true"
|
||||||
|
skidding-threshold="2.0"
|
||||||
|
max-item-angle="0.7" max-item-angle-high-speed="0.3"
|
||||||
|
time-full-steer="0.1"
|
||||||
|
bad-item-closeness="6"
|
||||||
|
straight-length-for-zipper="35"
|
||||||
|
rb-skid-probability="-50:1.0 -20:0.7 20:0.2 50:0.0"
|
||||||
|
speed-cap="10:1.0 50:0.8"/>
|
||||||
|
</ai>
|
||||||
<!-- Slipstream: length: How far behind a kart slipstream works
|
<!-- Slipstream: length: How far behind a kart slipstream works
|
||||||
collect-time: How many seconds of sstream give maximum benefit
|
collect-time: How many seconds of sstream give maximum benefit
|
||||||
use-time: How long the benefit will last.
|
use-time: How long the benefit will last.
|
||||||
|
@ -38,7 +38,8 @@ AIBaseController::AIBaseController(AbstractKart *kart,
|
|||||||
m_kart = kart;
|
m_kart = kart;
|
||||||
m_kart_length = m_kart->getKartLength();
|
m_kart_length = m_kart->getKartLength();
|
||||||
m_kart_width = m_kart->getKartWidth();
|
m_kart_width = m_kart->getKartWidth();
|
||||||
m_ai_properties = m_kart->getKartProperties()->getAIProperties();
|
m_ai_properties =
|
||||||
|
m_kart->getKartProperties()->getAIPropertiesForDifficulty();
|
||||||
|
|
||||||
if(race_manager->getMinorMode()!=RaceManager::MINOR_MODE_3_STRIKES)
|
if(race_manager->getMinorMode()!=RaceManager::MINOR_MODE_3_STRIKES)
|
||||||
{
|
{
|
||||||
@ -283,19 +284,6 @@ float AIBaseController::steerToAngle(const unsigned int sector,
|
|||||||
return steer_angle;
|
return steer_angle;
|
||||||
} // steerToAngle
|
} // steerToAngle
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
/** Sets when skidding will be used: when the ratio of steering angle to
|
|
||||||
* maximumn steering angle is larger than the fraction set here,
|
|
||||||
* skidding will be used. This is used to set more aggressive skidding
|
|
||||||
* for higher level AIs.
|
|
||||||
* \param f Fraction with which steering angle / max steering angle is
|
|
||||||
* compared to determine if skidding is used.
|
|
||||||
*/
|
|
||||||
void AIBaseController::setSkiddingFraction(float f)
|
|
||||||
{
|
|
||||||
m_skidding_threshold = f;
|
|
||||||
} // setSkiddingFactor
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
/** Computes the steering angle to reach a certain point. The function will
|
/** Computes the steering angle to reach a certain point. The function will
|
||||||
* request steering by setting the steering angle to maximum steer angle
|
* request steering by setting the steering angle to maximum steer angle
|
||||||
@ -331,9 +319,11 @@ float AIBaseController::steerToPoint(const Vec3 &point)
|
|||||||
// steer function will request skidding. 0.1 is added in case
|
// steer function will request skidding. 0.1 is added in case
|
||||||
// of floating point errors.
|
// of floating point errors.
|
||||||
if(lc.getX()>0)
|
if(lc.getX()>0)
|
||||||
return m_kart->getMaxSteerAngle()*m_skidding_threshold+0.1f;
|
return m_kart->getMaxSteerAngle()
|
||||||
|
*m_ai_properties->m_skidding_threshold+0.1f;
|
||||||
else
|
else
|
||||||
return -m_kart->getMaxSteerAngle()*m_skidding_threshold-0.1f;
|
return -m_kart->getMaxSteerAngle()
|
||||||
|
*m_ai_properties->m_skidding_threshold-0.1f;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now compute the nexessary radius for the turn. After getting the
|
// Now compute the nexessary radius for the turn. After getting the
|
||||||
@ -354,9 +344,11 @@ float AIBaseController::steerToPoint(const Vec3 &point)
|
|||||||
// If the wheel base is too long (i.e. the minimum radius is too large
|
// If the wheel base is too long (i.e. the minimum radius is too large
|
||||||
// to actually reach the target), make sure that skidding is used
|
// to actually reach the target), make sure that skidding is used
|
||||||
if(sin_steer_angle <= -1.0f)
|
if(sin_steer_angle <= -1.0f)
|
||||||
return -m_kart->getMaxSteerAngle()*m_skidding_threshold-0.1f;
|
return -m_kart->getMaxSteerAngle()
|
||||||
|
*m_ai_properties->m_skidding_threshold-0.1f;
|
||||||
if(sin_steer_angle >= 1.0f)
|
if(sin_steer_angle >= 1.0f)
|
||||||
return m_kart->getMaxSteerAngle()*m_skidding_threshold+0.1f;
|
return m_kart->getMaxSteerAngle()
|
||||||
|
*m_ai_properties->m_skidding_threshold+0.1f;
|
||||||
float steer_angle = asin(sin_steer_angle);
|
float steer_angle = asin(sin_steer_angle);
|
||||||
|
|
||||||
// After doing the exact computation, we now return an 'oversteered'
|
// After doing the exact computation, we now return an 'oversteered'
|
||||||
@ -456,5 +448,5 @@ bool AIBaseController::doSkid(float steer_fraction)
|
|||||||
|
|
||||||
// Otherwise return if we need a sharp turn (which is
|
// Otherwise return if we need a sharp turn (which is
|
||||||
// for the old skidding implementation).
|
// for the old skidding implementation).
|
||||||
return fabsf(steer_fraction)>=m_skidding_threshold;
|
return fabsf(steer_fraction)>=m_ai_properties->m_skidding_threshold;
|
||||||
} // doSkid
|
} // doSkid
|
||||||
|
@ -34,12 +34,6 @@ class Vec3;
|
|||||||
class AIBaseController : public Controller
|
class AIBaseController : public Controller
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
/** The minimum steering angle at which the AI adds skidding. Lower values
|
|
||||||
* tend to improve the line the AI is driving. This is used to adjust for
|
|
||||||
* different AI levels.
|
|
||||||
*/
|
|
||||||
float m_skidding_threshold;
|
|
||||||
|
|
||||||
/** Stores the last N times when a collision happened. This is used
|
/** Stores the last N times when a collision happened. This is used
|
||||||
* to detect when the AI is stuck, i.e. N collisions happened in
|
* to detect when the AI is stuck, i.e. N collisions happened in
|
||||||
* a certain period of time. */
|
* a certain period of time. */
|
||||||
@ -91,7 +85,6 @@ protected:
|
|||||||
float steerToAngle (const unsigned int sector, const float angle);
|
float steerToAngle (const unsigned int sector, const float angle);
|
||||||
float steerToPoint (const Vec3 &point);
|
float steerToPoint (const Vec3 &point);
|
||||||
float normalizeAngle(float angle);
|
float normalizeAngle(float angle);
|
||||||
void setSkiddingFraction(float f);
|
|
||||||
void computePath();
|
void computePath();
|
||||||
virtual bool doSkid(float steer_fraction);
|
virtual bool doSkid(float steer_fraction);
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
|
@ -25,15 +25,33 @@ float AIProperties::UNDEFINED = -99.9f;
|
|||||||
|
|
||||||
/** Constructor. Sets all properties to the special UNDEFINED value.
|
/** Constructor. Sets all properties to the special UNDEFINED value.
|
||||||
*/
|
*/
|
||||||
AIProperties::AIProperties()
|
AIProperties::AIProperties(RaceManager::Difficulty difficulty)
|
||||||
: m_skid_probability(/*decreasing*/false)
|
: m_skid_probability(/*decreasing*/false)
|
||||||
, m_speed_cap(/*decreasing*/true)
|
, m_speed_cap(/*decreasing*/true)
|
||||||
{
|
{
|
||||||
|
switch(difficulty)
|
||||||
|
{
|
||||||
|
case RaceManager::DIFFICULTY_EASY: m_ident="easy"; break;
|
||||||
|
case RaceManager::DIFFICULTY_MEDIUM: m_ident="medium"; break;
|
||||||
|
case RaceManager::DIFFICULTY_HARD: m_ident="hard"; break;
|
||||||
|
default: m_ident=""; break;
|
||||||
|
}
|
||||||
|
|
||||||
m_max_item_angle = UNDEFINED;
|
m_max_item_angle = UNDEFINED;
|
||||||
m_max_item_angle_high_speed = UNDEFINED;
|
m_max_item_angle_high_speed = UNDEFINED;
|
||||||
m_time_full_steer = UNDEFINED;
|
m_time_full_steer = UNDEFINED;
|
||||||
m_bad_item_closeness_2 = UNDEFINED;
|
m_bad_item_closeness_2 = UNDEFINED;
|
||||||
m_straight_length_for_zipper = UNDEFINED;
|
m_straight_length_for_zipper = UNDEFINED;
|
||||||
|
m_skidding_threshold = UNDEFINED;
|
||||||
|
m_min_start_delay = UNDEFINED;
|
||||||
|
m_max_start_delay = UNDEFINED;
|
||||||
|
m_false_start_probability = UNDEFINED;
|
||||||
|
m_make_use_of_slipstream = false;
|
||||||
|
m_collect_avoid_items = false;
|
||||||
|
m_handle_bomb = false;
|
||||||
|
m_item_usage_non_random = false;
|
||||||
|
m_nitro_usage = NITRO_NONE;
|
||||||
|
|
||||||
} // AIProperties
|
} // AIProperties
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
@ -42,6 +60,7 @@ AIProperties::AIProperties()
|
|||||||
*/
|
*/
|
||||||
void AIProperties::load(const XMLNode *ai_node)
|
void AIProperties::load(const XMLNode *ai_node)
|
||||||
{
|
{
|
||||||
|
ai_node->get("use-slipstream", &m_make_use_of_slipstream );
|
||||||
ai_node->get("max-item-angle", &m_max_item_angle );
|
ai_node->get("max-item-angle", &m_max_item_angle );
|
||||||
ai_node->get("max-item-angle-high-speed", &m_max_item_angle_high_speed );
|
ai_node->get("max-item-angle-high-speed", &m_max_item_angle_high_speed );
|
||||||
ai_node->get("time-full-steer", &m_time_full_steer );
|
ai_node->get("time-full-steer", &m_time_full_steer );
|
||||||
@ -49,7 +68,28 @@ void AIProperties::load(const XMLNode *ai_node)
|
|||||||
ai_node->get("straight-length-for-zipper",&m_straight_length_for_zipper);
|
ai_node->get("straight-length-for-zipper",&m_straight_length_for_zipper);
|
||||||
ai_node->get("rb-skid-probability", &m_skid_probability );
|
ai_node->get("rb-skid-probability", &m_skid_probability );
|
||||||
ai_node->get("speed-cap", &m_speed_cap );
|
ai_node->get("speed-cap", &m_speed_cap );
|
||||||
|
ai_node->get("non-random-item-usage", &m_item_usage_non_random );
|
||||||
|
ai_node->get("collect-avoid-items", &m_collect_avoid_items );
|
||||||
|
ai_node->get("handle-bomb", &m_handle_bomb );
|
||||||
|
ai_node->get("skidding-threshold", &m_skidding_threshold );
|
||||||
|
ai_node->get("false-start-probability", &m_false_start_probability );
|
||||||
|
ai_node->get("min-start-delay", &m_min_start_delay );
|
||||||
|
ai_node->get("max-start-delay", &m_max_start_delay );
|
||||||
|
|
||||||
|
std::string s;
|
||||||
|
ai_node->get("nitro-usage", &s);
|
||||||
|
if(s=="none")
|
||||||
|
m_nitro_usage = NITRO_NONE;
|
||||||
|
else if(s=="some")
|
||||||
|
m_nitro_usage = NITRO_SOME;
|
||||||
|
else if(s=="all")
|
||||||
|
m_nitro_usage = NITRO_ALL;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("Incorrect nitro-usage '%s' in AI '%s'.\n",s.c_str(),
|
||||||
|
m_ident.c_str());
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
// We actually need the square of the distance later
|
// We actually need the square of the distance later
|
||||||
m_bad_item_closeness_2 *= m_bad_item_closeness_2;
|
m_bad_item_closeness_2 *= m_bad_item_closeness_2;
|
||||||
|
|
||||||
@ -62,15 +102,21 @@ void AIProperties::load(const XMLNode *ai_node)
|
|||||||
*/
|
*/
|
||||||
void AIProperties::checkAllSet(const std::string &filename) const
|
void AIProperties::checkAllSet(const std::string &filename) const
|
||||||
{
|
{
|
||||||
#define CHECK_NEG( a,str_a) if(a<=UNDEFINED) { \
|
#define CHECK_NEG( a,str_a) if(a<=UNDEFINED) { \
|
||||||
fprintf(stderr,"Missing default value for '%s' in '%s'.\n", \
|
fprintf(stderr,"Missing default value for '%s' in '%s' " \
|
||||||
str_a,filename.c_str());exit(-1); \
|
"'for AI '%s'.\n", \
|
||||||
|
str_a,filename.c_str(), \
|
||||||
|
m_ident.c_str());exit(-1); \
|
||||||
}
|
}
|
||||||
CHECK_NEG(m_max_item_angle, "max-item-angle" );
|
CHECK_NEG(m_max_item_angle, "max-item-angle" );
|
||||||
CHECK_NEG(m_max_item_angle_high_speed, "max-item-angle-high-speed" );
|
CHECK_NEG(m_max_item_angle_high_speed, "max-item-angle-high-speed" );
|
||||||
CHECK_NEG(m_time_full_steer, "time-full-steer" );
|
CHECK_NEG(m_time_full_steer, "time-full-steer" );
|
||||||
CHECK_NEG(m_bad_item_closeness_2, "bad-item-closeness" );
|
CHECK_NEG(m_bad_item_closeness_2, "bad-item-closeness" );
|
||||||
CHECK_NEG(m_straight_length_for_zipper,"straight-length-for-zipper");
|
CHECK_NEG(m_straight_length_for_zipper,"straight-length-for-zipper");
|
||||||
|
CHECK_NEG(m_skidding_threshold, "skidding-threshold" );
|
||||||
|
CHECK_NEG(m_false_start_probability, "false-start-probability" );
|
||||||
|
CHECK_NEG(m_min_start_delay, "min-start-delay" );
|
||||||
|
CHECK_NEG(m_max_start_delay, "max-start-delay" );
|
||||||
|
|
||||||
if(m_skid_probability.size()==0)
|
if(m_skid_probability.size()==0)
|
||||||
{
|
{
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
#ifndef HEADER_AI_PROPERTIES_HPP
|
#ifndef HEADER_AI_PROPERTIES_HPP
|
||||||
#define HEADER_AI_PROPERTIES_HPP
|
#define HEADER_AI_PROPERTIES_HPP
|
||||||
|
|
||||||
|
#include "race/race_manager.hpp"
|
||||||
#include "utils/interpolation_array.hpp"
|
#include "utils/interpolation_array.hpp"
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
@ -76,9 +77,44 @@ protected:
|
|||||||
/** To cap maximum speed if the kart is ahead of the player. */
|
/** To cap maximum speed if the kart is ahead of the player. */
|
||||||
InterpolationArray m_speed_cap;
|
InterpolationArray m_speed_cap;
|
||||||
|
|
||||||
|
/** Probability of a false start. Note that Nolok in boss battle will never
|
||||||
|
* have a false start. */
|
||||||
|
float m_false_start_probability;
|
||||||
|
|
||||||
|
/** Minimum start delay. */
|
||||||
|
float m_min_start_delay;
|
||||||
|
|
||||||
|
/** Maximum start delay. */
|
||||||
|
float m_max_start_delay;
|
||||||
|
|
||||||
|
/** True if the AI should avtively try to make use of slipstream. */
|
||||||
|
bool m_make_use_of_slipstream;
|
||||||
|
|
||||||
|
/** Actively collect and avoid items. */
|
||||||
|
bool m_collect_avoid_items;
|
||||||
|
|
||||||
|
/** If the AI should actively try to pass on a bomb. */
|
||||||
|
bool m_handle_bomb;
|
||||||
|
|
||||||
|
/** True if items should be used better (i.e. non random). */
|
||||||
|
bool m_item_usage_non_random;
|
||||||
|
|
||||||
|
/** How the AI uses nitro. */
|
||||||
|
enum {NITRO_NONE, NITRO_SOME, NITRO_ALL} m_nitro_usage;
|
||||||
|
|
||||||
|
/** TODO: ONLY USE FOR OLD SKIDDING! CAN BE REMOVED once the new skidding
|
||||||
|
* works as expected.
|
||||||
|
* The minimum steering angle at which the AI adds skidding. Lower values
|
||||||
|
* tend to improve the line the AI is driving. This is used to adjust for
|
||||||
|
* different AI levels. */
|
||||||
|
float m_skidding_threshold;
|
||||||
|
|
||||||
|
/** An identifier like 'easy', 'medium' or 'hard' for this data set. */
|
||||||
|
std::string m_ident;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
AIProperties();
|
AIProperties(RaceManager::Difficulty difficulty);
|
||||||
void load(const XMLNode *skid_node);
|
void load(const XMLNode *skid_node);
|
||||||
void checkAllSet(const std::string &filename) const;
|
void checkAllSet(const std::string &filename) const;
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
|
@ -71,7 +71,6 @@ DefaultAIController::DefaultAIController(AbstractKart *kart)
|
|||||||
m_min_steps = 1;
|
m_min_steps = 1;
|
||||||
m_nitro_level = NITRO_NONE;
|
m_nitro_level = NITRO_NONE;
|
||||||
m_handle_bomb = false;
|
m_handle_bomb = false;
|
||||||
setSkiddingFraction(4.0f);
|
|
||||||
break;
|
break;
|
||||||
case RaceManager::DIFFICULTY_MEDIUM:
|
case RaceManager::DIFFICULTY_MEDIUM:
|
||||||
m_wait_for_players = true;
|
m_wait_for_players = true;
|
||||||
@ -84,7 +83,6 @@ DefaultAIController::DefaultAIController(AbstractKart *kart)
|
|||||||
m_min_steps = 1;
|
m_min_steps = 1;
|
||||||
m_nitro_level = NITRO_SOME;
|
m_nitro_level = NITRO_SOME;
|
||||||
m_handle_bomb = true;
|
m_handle_bomb = true;
|
||||||
setSkiddingFraction(3.0f);
|
|
||||||
break;
|
break;
|
||||||
case RaceManager::DIFFICULTY_HARD:
|
case RaceManager::DIFFICULTY_HARD:
|
||||||
m_wait_for_players = false;
|
m_wait_for_players = false;
|
||||||
@ -100,7 +98,6 @@ DefaultAIController::DefaultAIController(AbstractKart *kart)
|
|||||||
m_min_steps = 2;
|
m_min_steps = 2;
|
||||||
m_nitro_level = NITRO_ALL;
|
m_nitro_level = NITRO_ALL;
|
||||||
m_handle_bomb = true;
|
m_handle_bomb = true;
|
||||||
setSkiddingFraction(2.0f);
|
|
||||||
break;
|
break;
|
||||||
case RaceManager::DIFFICULTY_COUNT:
|
case RaceManager::DIFFICULTY_COUNT:
|
||||||
assert(0); // keep the compiler happy
|
assert(0); // keep the compiler happy
|
||||||
|
@ -97,7 +97,6 @@ EndController::EndController(AbstractKart *kart, StateManager::ActivePlayer *pla
|
|||||||
|
|
||||||
m_max_handicap_accel = 1.0f;
|
m_max_handicap_accel = 1.0f;
|
||||||
m_min_steps = 2;
|
m_min_steps = 2;
|
||||||
setSkiddingFraction(1.3f);
|
|
||||||
|
|
||||||
#ifdef AI_DEBUG
|
#ifdef AI_DEBUG
|
||||||
m_debug_sphere = irr_driver->getSceneManager()->addSphereSceneNode(1);
|
m_debug_sphere = irr_driver->getSceneManager()->addSphereSceneNode(1);
|
||||||
|
@ -74,7 +74,6 @@ PresentAI::PresentAI(AbstractKart *kart)
|
|||||||
m_min_steps = 1;
|
m_min_steps = 1;
|
||||||
m_nitro_level = NITRO_NONE;
|
m_nitro_level = NITRO_NONE;
|
||||||
m_handle_bomb = false;
|
m_handle_bomb = false;
|
||||||
setSkiddingFraction(4.0f);
|
|
||||||
break;
|
break;
|
||||||
case RaceManager::DIFFICULTY_MEDIUM:
|
case RaceManager::DIFFICULTY_MEDIUM:
|
||||||
m_wait_for_players = true;
|
m_wait_for_players = true;
|
||||||
@ -87,7 +86,6 @@ PresentAI::PresentAI(AbstractKart *kart)
|
|||||||
m_min_steps = 1;
|
m_min_steps = 1;
|
||||||
m_nitro_level = NITRO_SOME;
|
m_nitro_level = NITRO_SOME;
|
||||||
m_handle_bomb = true;
|
m_handle_bomb = true;
|
||||||
setSkiddingFraction(3.0f);
|
|
||||||
break;
|
break;
|
||||||
case RaceManager::DIFFICULTY_HARD:
|
case RaceManager::DIFFICULTY_HARD:
|
||||||
m_wait_for_players = false;
|
m_wait_for_players = false;
|
||||||
@ -103,7 +101,6 @@ PresentAI::PresentAI(AbstractKart *kart)
|
|||||||
m_min_steps = 2;
|
m_min_steps = 2;
|
||||||
m_nitro_level = NITRO_ALL;
|
m_nitro_level = NITRO_ALL;
|
||||||
m_handle_bomb = true;
|
m_handle_bomb = true;
|
||||||
setSkiddingFraction(2.0f);
|
|
||||||
break;
|
break;
|
||||||
case RaceManager::DIFFICULTY_COUNT:
|
case RaceManager::DIFFICULTY_COUNT:
|
||||||
assert(0); // keep the compiler happy
|
assert(0); // keep the compiler happy
|
||||||
|
@ -81,56 +81,8 @@ SkiddingAI::SkiddingAI(AbstractKart *kart)
|
|||||||
{
|
{
|
||||||
reset();
|
reset();
|
||||||
|
|
||||||
switch( race_manager->getDifficulty())
|
m_superpower = race_manager->getAISuperPower();
|
||||||
{
|
|
||||||
case RaceManager::DIFFICULTY_EASY:
|
|
||||||
m_wait_for_players = true;
|
|
||||||
m_make_use_of_slipstream = false;
|
|
||||||
m_max_handicap_speed = 0.9f;
|
|
||||||
m_false_start_probability = 0.08f;
|
|
||||||
m_min_start_delay = 0.3f;
|
|
||||||
m_max_start_delay = 0.5f;
|
|
||||||
m_min_steps = 1;
|
|
||||||
m_item_tactic = IT_TEN_SECONDS;
|
|
||||||
m_nitro_level = NITRO_NONE;
|
|
||||||
m_item_behaviour = ITEM_COLLECT_NONE;
|
|
||||||
m_handle_bomb = false;
|
|
||||||
setSkiddingFraction(4.0f);
|
|
||||||
break;
|
|
||||||
case RaceManager::DIFFICULTY_MEDIUM:
|
|
||||||
m_wait_for_players = true;
|
|
||||||
m_make_use_of_slipstream = false;
|
|
||||||
m_max_handicap_speed = 0.95f;
|
|
||||||
m_false_start_probability = 0.04f;
|
|
||||||
m_min_start_delay = 0.25f;
|
|
||||||
m_max_start_delay = 0.4f;
|
|
||||||
m_min_steps = 1;
|
|
||||||
m_item_tactic = IT_CALCULATE;
|
|
||||||
m_nitro_level = NITRO_SOME;
|
|
||||||
m_item_behaviour = ITEM_COLLECT_NONE;
|
|
||||||
m_handle_bomb = true;
|
|
||||||
setSkiddingFraction(3.0f);
|
|
||||||
break;
|
|
||||||
case RaceManager::DIFFICULTY_HARD:
|
|
||||||
m_wait_for_players = false;
|
|
||||||
m_make_use_of_slipstream = true;
|
|
||||||
m_max_handicap_speed = 1.0f;
|
|
||||||
m_item_tactic = IT_CALCULATE;
|
|
||||||
m_false_start_probability = 0.01f;
|
|
||||||
// See http://www.humanbenchmark.com/tests/reactiontime/stats.php
|
|
||||||
// Average reaction time is around 0.215 s, so using .15 as minimum
|
|
||||||
// gives an AI average slightly above the human average
|
|
||||||
m_min_start_delay = 0.15f;
|
|
||||||
m_max_start_delay = 0.28f;
|
|
||||||
m_min_steps = 2;
|
|
||||||
m_nitro_level = NITRO_ALL;
|
|
||||||
m_item_behaviour = ITEM_COLLECT_PRIORITY;
|
|
||||||
m_handle_bomb = true;
|
|
||||||
setSkiddingFraction(2.0f);
|
|
||||||
break;
|
|
||||||
case RaceManager::DIFFICULTY_COUNT:
|
|
||||||
assert(0); // keep the compiler happy
|
|
||||||
}
|
|
||||||
m_point_selection_algorithm = PSA_DEFAULT;
|
m_point_selection_algorithm = PSA_DEFAULT;
|
||||||
setControllerName("Skidding");
|
setControllerName("Skidding");
|
||||||
|
|
||||||
@ -149,11 +101,6 @@ SkiddingAI::SkiddingAI(AbstractKart *kart)
|
|||||||
setControllerName(name);
|
setControllerName(name);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
m_superpower = race_manager->getAISuperPower();
|
|
||||||
if (m_superpower == RaceManager::SUPERPOWER_NOLOK_BOSS)
|
|
||||||
{
|
|
||||||
m_false_start_probability = 0.0f;
|
|
||||||
}
|
|
||||||
#ifdef AI_DEBUG
|
#ifdef AI_DEBUG
|
||||||
for(unsigned int i=0; i<4; i++)
|
for(unsigned int i=0; i<4; i++)
|
||||||
{
|
{
|
||||||
@ -183,10 +130,7 @@ SkiddingAI::SkiddingAI(AbstractKart *kart)
|
|||||||
#endif
|
#endif
|
||||||
#ifdef AI_DEBUG_KART_HEADING
|
#ifdef AI_DEBUG_KART_HEADING
|
||||||
irr::video::SColor c;
|
irr::video::SColor c;
|
||||||
if(m_item_behaviour == ITEM_COLLECT_PRIORITY)
|
c = irr::video::SColor(128, 0, 0, 128);
|
||||||
c = irr::video::SColor(128, 0, 0, 128);
|
|
||||||
else
|
|
||||||
c = irr::video::SColor(128, 0, 128, 0);
|
|
||||||
m_curve[CURVE_KART] = new ShowCurve(0.5f, 0.5f, c);
|
m_curve[CURVE_KART] = new ShowCurve(0.5f, 0.5f, c);
|
||||||
#endif
|
#endif
|
||||||
#ifdef AI_DEBUG_NEW_FIND_NON_CRASHING
|
#ifdef AI_DEBUG_NEW_FIND_NON_CRASHING
|
||||||
@ -199,10 +143,7 @@ SkiddingAI::SkiddingAI(AbstractKart *kart)
|
|||||||
video::SColor(128, 0, 128, 0));
|
video::SColor(128, 0, 128, 0));
|
||||||
#ifdef AI_DEBUG_KART_AIM
|
#ifdef AI_DEBUG_KART_AIM
|
||||||
irr::video::SColor c1;
|
irr::video::SColor c1;
|
||||||
if(m_item_behaviour == ITEM_COLLECT_PRIORITY)
|
c1 = irr::video::SColor(128, 0, 0, 128);
|
||||||
c1 = irr::video::SColor(128, 0, 0, 128);
|
|
||||||
else
|
|
||||||
c1 = irr::video::SColor(128, 0, 128, 0);
|
|
||||||
|
|
||||||
m_curve[CURVE_AIM] = new ShowCurve(0.5f, 0.5f, c1);
|
m_curve[CURVE_AIM] = new ShowCurve(0.5f, 0.5f, c1);
|
||||||
#endif
|
#endif
|
||||||
@ -370,7 +311,7 @@ void SkiddingAI::update(float dt)
|
|||||||
// Special behaviour if we have a bomb attach: try to hit the kart ahead
|
// Special behaviour if we have a bomb attach: try to hit the kart ahead
|
||||||
// of us.
|
// of us.
|
||||||
bool commands_set = false;
|
bool commands_set = false;
|
||||||
if(m_handle_bomb &&
|
if(m_ai_properties->m_handle_bomb &&
|
||||||
m_kart->getAttachment()->getType()==Attachment::ATTACH_BOMB &&
|
m_kart->getAttachment()->getType()==Attachment::ATTACH_BOMB &&
|
||||||
m_kart_ahead )
|
m_kart_ahead )
|
||||||
{
|
{
|
||||||
@ -595,7 +536,7 @@ void SkiddingAI::handleSteering(float dt)
|
|||||||
|
|
||||||
// Potentially adjust the point to aim for in order to either
|
// Potentially adjust the point to aim for in order to either
|
||||||
// aim to collect item, or steer to avoid a bad item.
|
// aim to collect item, or steer to avoid a bad item.
|
||||||
if(m_item_behaviour!=ITEM_COLLECT_NONE)
|
if(m_ai_properties->m_collect_avoid_items)
|
||||||
handleItemCollectionAndAvoidance(&aim_point, last_node);
|
handleItemCollectionAndAvoidance(&aim_point, last_node);
|
||||||
|
|
||||||
steer_angle = steerToPoint(aim_point);
|
steer_angle = steerToPoint(aim_point);
|
||||||
@ -1176,7 +1117,7 @@ void SkiddingAI::handleItems(const float dt)
|
|||||||
|
|
||||||
// Tactic 1: wait ten seconds, then use item
|
// Tactic 1: wait ten seconds, then use item
|
||||||
// -----------------------------------------
|
// -----------------------------------------
|
||||||
if(m_item_tactic==IT_TEN_SECONDS)
|
if(!m_ai_properties->m_item_usage_non_random)
|
||||||
{
|
{
|
||||||
if( m_time_since_last_shot > 10.0f )
|
if( m_time_since_last_shot > 10.0f )
|
||||||
{
|
{
|
||||||
@ -1424,18 +1365,6 @@ void SkiddingAI::handleAcceleration( const float dt)
|
|||||||
}
|
}
|
||||||
|
|
||||||
m_controls->m_accel = stk_config->m_ai_acceleration;
|
m_controls->m_accel = stk_config->m_ai_acceleration;
|
||||||
if(!m_wait_for_players)
|
|
||||||
return;
|
|
||||||
|
|
||||||
//Find if any player is ahead of this kart
|
|
||||||
for(unsigned int i = 0; i < race_manager->getNumPlayers(); ++i )
|
|
||||||
{
|
|
||||||
if( m_kart->getPosition() > m_world->getPlayerKart(i)->getPosition() )
|
|
||||||
{
|
|
||||||
m_controls->m_accel = m_max_handicap_speed;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} // handleAcceleration
|
} // handleAcceleration
|
||||||
|
|
||||||
@ -1446,11 +1375,17 @@ void SkiddingAI::handleRaceStart()
|
|||||||
{
|
{
|
||||||
// Each kart starts at a different, random time, and the time is
|
// Each kart starts at a different, random time, and the time is
|
||||||
// smaller depending on the difficulty.
|
// smaller depending on the difficulty.
|
||||||
m_start_delay = m_min_start_delay
|
m_start_delay = m_ai_properties->m_min_start_delay
|
||||||
+ (float) rand() / RAND_MAX * (m_max_start_delay-m_min_start_delay);
|
+ (float) rand() / RAND_MAX
|
||||||
|
* (m_ai_properties->m_max_start_delay -
|
||||||
|
m_ai_properties->m_min_start_delay);
|
||||||
|
|
||||||
|
float false_start_probability =
|
||||||
|
m_superpower == RaceManager::SUPERPOWER_NOLOK_BOSS
|
||||||
|
? 0.0f : m_ai_properties->m_false_start_probability;
|
||||||
|
|
||||||
// Now check for a false start. If so, add 1 second penalty time.
|
// Now check for a false start. If so, add 1 second penalty time.
|
||||||
if(rand() < RAND_MAX * m_false_start_probability)
|
if(rand() < RAND_MAX * false_start_probability)
|
||||||
{
|
{
|
||||||
m_start_delay+=stk_config->m_penalty_time;
|
m_start_delay+=stk_config->m_penalty_time;
|
||||||
return;
|
return;
|
||||||
@ -1499,15 +1434,17 @@ void SkiddingAI::handleNitroAndZipper()
|
|||||||
// Don't compute nitro usage if we don't have nitro or are not supposed
|
// Don't compute nitro usage if we don't have nitro or are not supposed
|
||||||
// to use it, and we don't have a zipper or are not supposed to use
|
// to use it, and we don't have a zipper or are not supposed to use
|
||||||
// it (calculated).
|
// it (calculated).
|
||||||
if( (m_kart->getEnergy()==0 || m_nitro_level==NITRO_NONE) &&
|
if( (m_kart->getEnergy()==0 ||
|
||||||
|
m_ai_properties->m_nitro_usage==AIProperties::NITRO_NONE) &&
|
||||||
(m_kart->getPowerup()->getType()!=PowerupManager::POWERUP_ZIPPER ||
|
(m_kart->getPowerup()->getType()!=PowerupManager::POWERUP_ZIPPER ||
|
||||||
m_item_tactic==IT_TEN_SECONDS ) )
|
!m_ai_properties->m_item_usage_non_random ) )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// If there are items to avoid close, and we only have zippers, don't
|
// If there are items to avoid close, and we only have zippers, don't
|
||||||
// use them (since this make it harder to avoid items).
|
// use them (since this make it harder to avoid items).
|
||||||
if(m_avoid_item_close &&
|
if(m_avoid_item_close &&
|
||||||
(m_kart->getEnergy()==0|| m_nitro_level==NITRO_NONE) )
|
(m_kart->getEnergy()==0 ||
|
||||||
|
m_ai_properties->m_nitro_usage==AIProperties::NITRO_NONE) )
|
||||||
return;
|
return;
|
||||||
// If a parachute or anvil is attached, the nitro doesn't give much
|
// If a parachute or anvil is attached, the nitro doesn't give much
|
||||||
// benefit. Better wait till later.
|
// benefit. Better wait till later.
|
||||||
@ -1538,10 +1475,12 @@ void SkiddingAI::handleNitroAndZipper()
|
|||||||
// anyway. Since the kart is faster with nitro, estimate a 50% time
|
// anyway. Since the kart is faster with nitro, estimate a 50% time
|
||||||
// decrease (additionally some nitro will be saved when top speed
|
// decrease (additionally some nitro will be saved when top speed
|
||||||
// is reached).
|
// is reached).
|
||||||
if(m_world->getLapForKart(m_kart->getWorldKartId())==race_manager->getNumLaps()-1 &&
|
if(m_world->getLapForKart(m_kart->getWorldKartId())
|
||||||
m_nitro_level == NITRO_ALL)
|
==race_manager->getNumLaps()-1 &&
|
||||||
|
m_ai_properties->m_nitro_usage == AIProperties::NITRO_ALL)
|
||||||
{
|
{
|
||||||
float finish = m_world->getEstimatedFinishTime(m_kart->getWorldKartId());
|
float finish =
|
||||||
|
m_world->getEstimatedFinishTime(m_kart->getWorldKartId());
|
||||||
if( 1.5f*m_kart->getEnergy() >= finish - m_world->getTime() )
|
if( 1.5f*m_kart->getEnergy() >= finish - m_world->getTime() )
|
||||||
{
|
{
|
||||||
m_controls->m_nitro = true;
|
m_controls->m_nitro = true;
|
||||||
@ -1569,7 +1508,8 @@ void SkiddingAI::handleNitroAndZipper()
|
|||||||
m_kart_behind->getSpeed() > m_kart->getSpeed() )
|
m_kart_behind->getSpeed() > m_kart->getSpeed() )
|
||||||
{
|
{
|
||||||
// Only prevent overtaking on highest level
|
// Only prevent overtaking on highest level
|
||||||
m_controls->m_nitro = m_nitro_level==NITRO_ALL;
|
m_controls->m_nitro = m_ai_properties->m_nitro_usage
|
||||||
|
== AIProperties::NITRO_ALL;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1597,7 +1537,7 @@ void SkiddingAI::handleNitroAndZipper()
|
|||||||
void SkiddingAI::checkCrashes(const Vec3& pos )
|
void SkiddingAI::checkCrashes(const Vec3& pos )
|
||||||
{
|
{
|
||||||
int steps = int( m_kart->getVelocityLC().getZ() / m_kart_length );
|
int steps = int( m_kart->getVelocityLC().getZ() / m_kart_length );
|
||||||
if( steps < m_min_steps ) steps = m_min_steps;
|
if( steps < 2 ) steps = 2;
|
||||||
|
|
||||||
// The AI drives significantly better with more steps, so for now
|
// The AI drives significantly better with more steps, so for now
|
||||||
// add 5 additional steps.
|
// add 5 additional steps.
|
||||||
@ -1613,7 +1553,8 @@ void SkiddingAI::checkCrashes(const Vec3& pos )
|
|||||||
// If slipstream should be handled actively, trigger overtaking the
|
// If slipstream should be handled actively, trigger overtaking the
|
||||||
// kart which gives us slipstream if slipstream is ready
|
// kart which gives us slipstream if slipstream is ready
|
||||||
const SlipStream *slip=m_kart->getSlipstream();
|
const SlipStream *slip=m_kart->getSlipstream();
|
||||||
if(m_make_use_of_slipstream && slip->isSlipstreamReady() &&
|
if(m_ai_properties->m_make_use_of_slipstream &&
|
||||||
|
slip->isSlipstreamReady() &&
|
||||||
slip->getSlipstreamTarget())
|
slip->getSlipstreamTarget())
|
||||||
{
|
{
|
||||||
//printf("%s overtaking %s\n", m_kart->getIdent().c_str(),
|
//printf("%s overtaking %s\n", m_kart->getIdent().c_str(),
|
||||||
|
@ -46,21 +46,6 @@ namespace irr
|
|||||||
class SkiddingAI : public AIBaseController
|
class SkiddingAI : public AIBaseController
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
/** How the AI uses nitro. */
|
|
||||||
enum {NITRO_NONE, NITRO_SOME, NITRO_ALL} m_nitro_level;
|
|
||||||
|
|
||||||
/** Determines if the AI should prefer collecting items over avoiding
|
|
||||||
* items, or avoiding over collecting. */
|
|
||||||
enum {ITEM_COLLECT_NONE, ITEM_COLLECT_PRIORITY, ITEM_AVOID_PRIORITY}
|
|
||||||
m_item_behaviour;
|
|
||||||
|
|
||||||
enum ItemTactic
|
|
||||||
{
|
|
||||||
IT_TEN_SECONDS, //Fire after 10 seconds have passed, since the item
|
|
||||||
//was grabbed.
|
|
||||||
IT_CALCULATE //Aim carefully, check for enough space for boosters,
|
|
||||||
//and that other conditions are meet before firing.
|
|
||||||
};
|
|
||||||
|
|
||||||
class CrashTypes
|
class CrashTypes
|
||||||
{
|
{
|
||||||
@ -72,38 +57,7 @@ private:
|
|||||||
void clear() {m_road = false; m_kart = -1;}
|
void clear() {m_road = false; m_kart = -1;}
|
||||||
} m_crashes;
|
} m_crashes;
|
||||||
|
|
||||||
RaceManager::AISuperPower m_superpower;
|
RaceManager::AISuperPower m_superpower;
|
||||||
|
|
||||||
/*Difficulty handling variables*/
|
|
||||||
/** Chance of a false start. */
|
|
||||||
float m_false_start_probability;
|
|
||||||
/** The minimum delay time before a AI kart starts. */
|
|
||||||
float m_min_start_delay;
|
|
||||||
/** The maximum delay time before an AI kart starts. */
|
|
||||||
float m_max_start_delay;
|
|
||||||
/** The actual start delay used. */
|
|
||||||
float m_start_delay;
|
|
||||||
|
|
||||||
/** Minimum number of steps to check. If 0, the AI doesn't even has check
|
|
||||||
* around the kart, if 1, it checks around the kart always, and more
|
|
||||||
* than that will check the remaining number of steps in front of the
|
|
||||||
* kart, always. */
|
|
||||||
int m_min_steps;
|
|
||||||
/** If true, the acceleration is decreased when the AI is in a better
|
|
||||||
* position than all the human players. */
|
|
||||||
bool m_wait_for_players;
|
|
||||||
|
|
||||||
/** The allowed maximum speed in percent of the kart's maximum speed. */
|
|
||||||
float m_max_handicap_speed;
|
|
||||||
|
|
||||||
/** How are items going to be used? */
|
|
||||||
ItemTactic m_item_tactic;
|
|
||||||
|
|
||||||
/** True if the kart should try to pass on a bomb to another kart. */
|
|
||||||
bool m_handle_bomb;
|
|
||||||
|
|
||||||
/** True if the AI should avtively try to make use of slipstream. */
|
|
||||||
bool m_make_use_of_slipstream;
|
|
||||||
|
|
||||||
/*General purpose variables*/
|
/*General purpose variables*/
|
||||||
|
|
||||||
@ -121,6 +75,9 @@ private:
|
|||||||
/** Distance to the kard behind. */
|
/** Distance to the kard behind. */
|
||||||
float m_distance_behind;
|
float m_distance_behind;
|
||||||
|
|
||||||
|
/** The actual start delay used. */
|
||||||
|
float m_start_delay;
|
||||||
|
|
||||||
/** Time an item has been collected and not used. */
|
/** Time an item has been collected and not used. */
|
||||||
float m_time_since_last_shot;
|
float m_time_since_last_shot;
|
||||||
|
|
||||||
|
@ -106,13 +106,15 @@ KartProperties::KartProperties(const std::string &filename)
|
|||||||
if (filename != "")
|
if (filename != "")
|
||||||
{
|
{
|
||||||
m_skidding_properties = NULL;
|
m_skidding_properties = NULL;
|
||||||
m_ai_properties = NULL;
|
for(unsigned int i=0; i<RaceManager::DIFFICULTY_COUNT; i++)
|
||||||
|
m_ai_properties[i]= NULL;
|
||||||
load(filename, "kart");
|
load(filename, "kart");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_skidding_properties = new SkiddingProperties();
|
m_skidding_properties = new SkiddingProperties();
|
||||||
m_ai_properties = new AIProperties();
|
for(unsigned int i=0; i<RaceManager::DIFFICULTY_COUNT; i++)
|
||||||
|
m_ai_properties[i]= new AIProperties((RaceManager::Difficulty)i);
|
||||||
}
|
}
|
||||||
} // KartProperties
|
} // KartProperties
|
||||||
|
|
||||||
@ -123,8 +125,9 @@ KartProperties::~KartProperties()
|
|||||||
delete m_kart_model;
|
delete m_kart_model;
|
||||||
if(m_skidding_properties)
|
if(m_skidding_properties)
|
||||||
delete m_skidding_properties;
|
delete m_skidding_properties;
|
||||||
if(m_ai_properties)
|
for(unsigned int i=0; i<RaceManager::DIFFICULTY_COUNT; i++)
|
||||||
delete m_ai_properties;
|
if(m_ai_properties[i])
|
||||||
|
delete m_ai_properties[i];
|
||||||
} // ~KartProperties
|
} // ~KartProperties
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
@ -138,14 +141,18 @@ void KartProperties::copyFrom(const KartProperties *source)
|
|||||||
{
|
{
|
||||||
*this = *source;
|
*this = *source;
|
||||||
|
|
||||||
// After the memcpy the two skidding properties will share pointers.
|
// After the memcpy any pointers will be shared.
|
||||||
// So all pointer variables need to be separately allocated and assigned.
|
// So all pointer variables need to be separately allocated and assigned.
|
||||||
m_skidding_properties = new SkiddingProperties();
|
m_skidding_properties = new SkiddingProperties();
|
||||||
assert(m_skidding_properties);
|
assert(m_skidding_properties);
|
||||||
m_ai_properties = new AIProperties();
|
|
||||||
assert(m_ai_properties);
|
|
||||||
*m_skidding_properties = *source->m_skidding_properties;
|
*m_skidding_properties = *source->m_skidding_properties;
|
||||||
*m_ai_properties = *source->m_ai_properties;
|
|
||||||
|
for(unsigned int i=0; i<RaceManager::DIFFICULTY_COUNT; i++)
|
||||||
|
{
|
||||||
|
m_ai_properties[i] = new AIProperties((RaceManager::Difficulty)i);
|
||||||
|
assert(m_ai_properties);
|
||||||
|
*m_ai_properties[i] = *source->m_ai_properties[i];
|
||||||
|
}
|
||||||
} // copyFrom
|
} // copyFrom
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
@ -317,7 +324,12 @@ void KartProperties::getAllData(const XMLNode * root)
|
|||||||
|
|
||||||
if(const XMLNode *ai_node = root->getNode("ai"))
|
if(const XMLNode *ai_node = root->getNode("ai"))
|
||||||
{
|
{
|
||||||
m_ai_properties->load(ai_node);
|
const XMLNode *easy = ai_node->getNode("easy");
|
||||||
|
m_ai_properties[RaceManager::DIFFICULTY_EASY]->load(easy);
|
||||||
|
const XMLNode *medium = ai_node->getNode("medium");
|
||||||
|
m_ai_properties[RaceManager::DIFFICULTY_MEDIUM]->load(medium);
|
||||||
|
const XMLNode *hard = ai_node->getNode("hard");
|
||||||
|
m_ai_properties[RaceManager::DIFFICULTY_HARD]->load(hard);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(const XMLNode *slipstream_node = root->getNode("slipstream"))
|
if(const XMLNode *slipstream_node = root->getNode("slipstream"))
|
||||||
@ -649,7 +661,8 @@ void KartProperties::checkAllSet(const std::string &filename)
|
|||||||
CHECK_NEG(m_explosion_radius, "explosion radius" );
|
CHECK_NEG(m_explosion_radius, "explosion radius" );
|
||||||
|
|
||||||
m_skidding_properties->checkAllSet(filename);
|
m_skidding_properties->checkAllSet(filename);
|
||||||
m_ai_properties->checkAllSet(filename);
|
for(unsigned int i=0; i<RaceManager::DIFFICULTY_COUNT; i++)
|
||||||
|
m_ai_properties[i]->checkAllSet(filename);
|
||||||
} // checkAllSet
|
} // checkAllSet
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
@ -65,8 +65,9 @@ private:
|
|||||||
|
|
||||||
/** AI Properties for this kart, as a separate object in order to
|
/** AI Properties for this kart, as a separate object in order to
|
||||||
* reduce dependencies (and therefore compile time) when changing
|
* reduce dependencies (and therefore compile time) when changing
|
||||||
* any AI property. */
|
* any AI property. There is one separate object for each
|
||||||
AIProperties *m_ai_properties;
|
* difficulty. */
|
||||||
|
AIProperties *m_ai_properties[RaceManager::DIFFICULTY_COUNT];
|
||||||
|
|
||||||
/** The absolute path of the icon texture to use. */
|
/** The absolute path of the icon texture to use. */
|
||||||
Material *m_icon_material;
|
Material *m_icon_material;
|
||||||
@ -629,10 +630,13 @@ public:
|
|||||||
|
|
||||||
/** Returns a pointer to the skidding properties. */
|
/** Returns a pointer to the skidding properties. */
|
||||||
const SkiddingProperties *getSkiddingProperties() const
|
const SkiddingProperties *getSkiddingProperties() const
|
||||||
{ return m_skidding_properties; }
|
{ return m_skidding_properties; }
|
||||||
|
|
||||||
/** Returns a pointer to the AI properties. */
|
/** Returns a pointer to the AI properties. */
|
||||||
const AIProperties *getAIProperties() const { return m_ai_properties; }
|
const AIProperties *getAIPropertiesForDifficulty() const
|
||||||
|
{
|
||||||
|
return m_ai_properties[race_manager->getDifficulty()];
|
||||||
|
} // getAIProperties
|
||||||
|
|
||||||
/** Returns ratio of current speed to max speed at which the gear will
|
/** Returns ratio of current speed to max speed at which the gear will
|
||||||
* change (for our simualated gears = simple change of engine power). */
|
* change (for our simualated gears = simple change of engine power). */
|
||||||
|
Loading…
Reference in New Issue
Block a user