Improved doxygen documentation.
git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/trunk@12570 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
@@ -31,6 +31,59 @@
|
||||
|
||||
bool AIBaseController::m_ai_debug = false;
|
||||
|
||||
/**
|
||||
This is the base class for all AIs. At this stage there are two similar
|
||||
AIs: one is the SkiddingAI, which is the AI used in lap based races
|
||||
(including follow-the-leader mode), the other one is the end controller,
|
||||
I.e. the controller that takes over from a player (or AI) when the race is
|
||||
finished.
|
||||
|
||||
This base class defines some basic operations:
|
||||
- It takes care on which part of the QuadGraph the AI currently is.
|
||||
- It determines which path the AI should take (in case of shortcuts
|
||||
or forks in the road).
|
||||
|
||||
At race start and every time a new lap is started, the AI will compute the
|
||||
path the kart is taking this lap (computePath). At this stage the decision
|
||||
which road in case of shortcut to take is purely random. It stores the
|
||||
information in two arrays:
|
||||
m_successor_index[i] stores which successor to take from node i.
|
||||
The successor is a number between 0 and number_of_successors - 1.
|
||||
m_next_node_index[i] stores the actual index of the graph node that
|
||||
follows after node i.
|
||||
Depending on operation one of the other data is more useful, so this
|
||||
class stores both information to avoid looking it up over and over.
|
||||
Once this is done (still in computePath), the array m_all_look_aheads is
|
||||
computed. This array stores for each quad a list of the next (atm) 10 quads.
|
||||
This is used when the AI is selecting where to drive next, and it will just
|
||||
pass the list of next quads to findRoadSector.
|
||||
|
||||
Note that the quad graph information is stored for every quad in the quad
|
||||
graph, even if the quad is not on the path chosen. This is necessary since
|
||||
it can happen that a kart ends up on a path not choses (e.g. perhaps it was
|
||||
pushed on that part, or couldn't get a sharp corner).
|
||||
|
||||
In update(), which gets called one per frame per AI, this object will
|
||||
determine the quad the kart is currently on (which is then used to determine
|
||||
where the kart will be driving to). This uses the m_all_look_aheads to
|
||||
speed up this process (since the kart is likely to be either on the same
|
||||
quad as it was before, or the next quad in the m_all_look_aheads list).
|
||||
|
||||
It will also check if the kart is stuck:
|
||||
this is done by maintaining a list of times when the kart hits the track. If
|
||||
(atm) more than 3 collisions happen in 1.5 seconds, the kart is considered
|
||||
stuck and will trigger a rescue (due to the pushback from the track it will
|
||||
take some time if a kart is really stuck before it will hit the track again).
|
||||
|
||||
This base class also contains some convenience functions which are useful
|
||||
in all AIs, e.g.:
|
||||
- steerToPoint: determine the steering angle to use depending on the
|
||||
current location and the point the kart is driving to.
|
||||
- normalizeAngle: To normalise the steering angle to be in [-PI,PI].
|
||||
- setSteering: Converts the steering angle into a steering fraction
|
||||
in [-1,1].
|
||||
|
||||
*/
|
||||
AIBaseController::AIBaseController(AbstractKart *kart,
|
||||
StateManager::ActivePlayer *player)
|
||||
: Controller(kart, player)
|
||||
@@ -97,7 +150,13 @@ void AIBaseController::newLap(int lap)
|
||||
} // newLap
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Computes a path for the AI to follow.
|
||||
/** Computes a path for the AI to follow. This function is called at race
|
||||
* start and every time a new lap is started. Recomputing the path every
|
||||
* time will mean that the kart will not always take the same path, but
|
||||
* (potentially) vary from lap to lap. At this stage the decision is done
|
||||
* randomly. The AI could be improved by collecting more information about
|
||||
* each branch of a track, and selecting the 'appropriate' one (e.g. if the
|
||||
* AI is far ahead, chose a longer/slower path).
|
||||
*/
|
||||
void AIBaseController::computePath()
|
||||
{
|
||||
@@ -250,7 +309,7 @@ void AIBaseController::crashed(const Material *m)
|
||||
/** Returns the next sector of the given sector index. This is used
|
||||
* for branches in the quad graph to select which way the AI kart should
|
||||
* go. This is a very simple implementation that always returns the first
|
||||
* successor.
|
||||
* successor, but it can be overridden to allow a better selection.
|
||||
* \param index Index of the graph node for which the successor is searched.
|
||||
* \return Returns the successor of this graph node.
|
||||
*/
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
//The AI debugging works best with just 1 AI kart, so set the number of karts
|
||||
//to 2 in main.cpp with quickstart and run supertuxkart with the arg -N.
|
||||
#ifdef DEBUG
|
||||
// Enable AeI graphical debugging
|
||||
// Enable AI graphical debugging
|
||||
# undef AI_DEBUG
|
||||
// Shows left and right lines when using new findNonCrashing function
|
||||
# undef AI_DEBUG_NEW_FIND_NON_CRASHING
|
||||
@@ -36,22 +36,6 @@
|
||||
|
||||
#include "karts/controller/skidding_ai.hpp"
|
||||
|
||||
#ifdef AI_DEBUG
|
||||
# include "irrlicht.h"
|
||||
using namespace irr;
|
||||
#endif
|
||||
|
||||
#if defined(WIN32) && !defined(__CYGWIN__) && !defined(__MINGW32__)
|
||||
# define isnan _isnan
|
||||
#else
|
||||
# include <math.h>
|
||||
#endif
|
||||
|
||||
#include <cstdlib>
|
||||
#include <ctime>
|
||||
#include <cstdio>
|
||||
#include <iostream>
|
||||
|
||||
#ifdef AI_DEBUG
|
||||
# include "graphics/irr_driver.hpp"
|
||||
#endif
|
||||
@@ -76,17 +60,81 @@
|
||||
#include "tracks/track.hpp"
|
||||
#include "utils/constants.hpp"
|
||||
|
||||
#ifdef AI_DEBUG
|
||||
# include "irrlicht.h"
|
||||
using namespace irr;
|
||||
#endif
|
||||
|
||||
#if defined(WIN32) && !defined(__CYGWIN__) && !defined(__MINGW32__)
|
||||
# define isnan _isnan
|
||||
#else
|
||||
# include <math.h>
|
||||
#endif
|
||||
|
||||
#include <cstdlib>
|
||||
#include <ctime>
|
||||
#include <cstdio>
|
||||
#include <iostream>
|
||||
|
||||
/**
|
||||
\brief This is the actual racing AI.
|
||||
|
||||
The main entry point, called once per frame for each AI, is update().
|
||||
After handling some standard cases (race start, AI being rescued)
|
||||
the AI does the following steps:
|
||||
- compute nearest karts (one ahead and one behind)
|
||||
- check if the kart is about to crash with another kart or the
|
||||
track. This is done by simply testing a certain number of timesteps
|
||||
ahead and estimating the future position of any kart by using
|
||||
current_position + velocity * time
|
||||
(so turns are not taken into account). It also checks if the kart
|
||||
would be outside the quad graph, which indicates a 'collision with
|
||||
track' (though technically this only means the kart would be off track).
|
||||
This information is stored in the m_crashes data structure.
|
||||
- Determine track direction (straight, left, or right), which the
|
||||
function determineTrackDirection stores in m_current_track_direction
|
||||
- If the kart has a bomb attached, it will try to hit the kart ahead,
|
||||
using nitro if necessary. The kart will aim at the target kart,
|
||||
nothing els is done (idea: if the kart has a plunger, fire it).
|
||||
- Otherwise, the AI will:
|
||||
- set acceleration (handleAcceleration)
|
||||
- decide where to steer to (handleSteering): it will first check if it
|
||||
is outside of the track, and if so, steer towards the center of the
|
||||
next quad. If it was detected that the AI is going to hit another
|
||||
kart, it will try to avoid this. Otherwise it will aim at the center
|
||||
of the quad furthest away so that a straight line from the current
|
||||
position to this center is on track (see findNonCrashingPoint).
|
||||
There are actually three different implementations of this, but the
|
||||
(somewhat buggy) default one results in reality with the best AI
|
||||
behaviour.
|
||||
- decide if to try to collect or avoid items (handeItems).
|
||||
It considers all items on quads between the current quad of the kart
|
||||
and the quad the AI is aiming at (see handleSteering). If it finds
|
||||
an item to collect, it pre-selects this items, which means it will
|
||||
not select another item for collection until this pre-selected item
|
||||
is clearly uncollectable (gone or too far out of the way). This avoids
|
||||
problems that the AI is between two items it can collects, and keeps
|
||||
switching between both items, at the end missing both.
|
||||
- detects if the AI is stuck and needs rescue (handleRescue)
|
||||
- decides if it needs to brake (handlebraking)
|
||||
- decides if nitro or zipper should be used
|
||||
- Finally, it checks if it has a zipper but selected to use nitro, and
|
||||
under certain circumstances will use zipper instead of nitro.
|
||||
|
||||
*/
|
||||
SkiddingAI::SkiddingAI(AbstractKart *kart)
|
||||
: AIBaseController(kart)
|
||||
{
|
||||
reset();
|
||||
|
||||
// Determine if this AI has superpowers, which happens e.g.
|
||||
// for the final race challenge against nolok.
|
||||
m_superpower = race_manager->getAISuperPower();
|
||||
|
||||
m_point_selection_algorithm = PSA_DEFAULT;
|
||||
setControllerName("Skidding");
|
||||
|
||||
// Use this define in order to compare the impact of collecting items
|
||||
// Use this define in order to compare the different algorithms that
|
||||
// select the next point to steer at.
|
||||
#undef COMPARE_AIS
|
||||
#ifdef COMPARE_AIS
|
||||
std::string name("");
|
||||
@@ -101,6 +149,8 @@ SkiddingAI::SkiddingAI(AbstractKart *kart)
|
||||
setControllerName(name);
|
||||
#endif
|
||||
|
||||
|
||||
// Draw various spheres on the track for an AI
|
||||
#ifdef AI_DEBUG
|
||||
for(unsigned int i=0; i<4; i++)
|
||||
{
|
||||
@@ -170,6 +220,8 @@ SkiddingAI::~SkiddingAI()
|
||||
} // ~SkiddingAI
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Resets the AI when a race is restarted.
|
||||
*/
|
||||
void SkiddingAI::reset()
|
||||
{
|
||||
m_time_since_last_shot = 0.0f;
|
||||
@@ -204,9 +256,13 @@ void SkiddingAI::reset()
|
||||
} // reset
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Returns a name for the AI.
|
||||
* This is used in profile mode when comparing different AI implementations
|
||||
* to be able to distinguish them from each other.
|
||||
*/
|
||||
const irr::core::stringw& SkiddingAI::getNamePostfix() const
|
||||
{
|
||||
// Static to avoid returning the address of a temporary stringq
|
||||
// Static to avoid returning the address of a temporary string.
|
||||
static irr::core::stringw name="(default)";
|
||||
return name;
|
||||
} // getNamePostfix
|
||||
@@ -222,8 +278,10 @@ unsigned int SkiddingAI::getNextSector(unsigned int index)
|
||||
} // getNextSector
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//TODO: if the AI is crashing constantly, make it move backwards in a straight
|
||||
//line, then move forward while turning.
|
||||
/** This is the main entry point for the AI.
|
||||
* It is called once per frame for each AI and determines the behaviour of
|
||||
* the AI, e.g. steering, accelerating/braking, firing.
|
||||
*/
|
||||
void SkiddingAI::update(float dt)
|
||||
{
|
||||
// This is used to enable firing an item backwards.
|
||||
@@ -285,13 +343,13 @@ void SkiddingAI::update(float dt)
|
||||
return;
|
||||
}
|
||||
|
||||
// If the kart needs to be rescued, do it now (and nothing else)
|
||||
if(isStuck() && !m_kart->getKartAnimation())
|
||||
{
|
||||
new RescueAnimation(m_kart);
|
||||
AIBaseController::update(dt);
|
||||
return;
|
||||
}
|
||||
// If the kart needs to be rescued, do it now (and nothing else)
|
||||
if(isStuck() && !m_kart->getKartAnimation())
|
||||
{
|
||||
new RescueAnimation(m_kart);
|
||||
AIBaseController::update(dt);
|
||||
return;
|
||||
}
|
||||
|
||||
if( m_world->isStartPhase() )
|
||||
{
|
||||
@@ -375,6 +433,13 @@ void SkiddingAI::update(float dt)
|
||||
} // update
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** This function decides if the AI should brake.
|
||||
* The decision can be based on race mode (e.g. in follow the leader the AI
|
||||
* will brake if it is ahead of the leader). Otherwise it will depend on
|
||||
* the direction the AI is facing (if it's not facing in the track direction
|
||||
* it will brake in order to make it easier to re-align itself), and
|
||||
* estimated curve radius (brake to avoid being pushed out of a curve).
|
||||
*/
|
||||
void SkiddingAI::handleBraking()
|
||||
{
|
||||
m_controls->m_brake = false;
|
||||
@@ -441,10 +506,10 @@ void SkiddingAI::handleBraking()
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Decides in which direction to steer. If the kart is off track, it will
|
||||
* steer towards the center of the track. Otherwise it will call
|
||||
* findNonCrashingPoint to determine a point to aim for. Then it will
|
||||
* evaluate items to see if it should aim for any items or try to avoid
|
||||
* item, and potentially adjust the aim-at point, before computing the
|
||||
* steer towards the center of the track. Otherwise it will call one of
|
||||
* the findNonCrashingPoint() functions to determine a point to aim for. Then
|
||||
* it will evaluate items to see if it should aim for any items or try to
|
||||
* avoid item, and potentially adjust the aim-at point, before computing the
|
||||
* steer direction to arrive at the currently aim-at point.
|
||||
* \param dt Time step size.
|
||||
*/
|
||||
@@ -523,7 +588,7 @@ void SkiddingAI::handleSteering(float dt)
|
||||
break;
|
||||
case PSA_NEW: findNonCrashingPointNew(&aim_point, &last_node);
|
||||
break;
|
||||
case PSA_DEFAULT:findNonCrashingPointDefault(&aim_point, &last_node);
|
||||
case PSA_DEFAULT:findNonCrashingPoint(&aim_point, &last_node);
|
||||
break;
|
||||
}
|
||||
#ifdef AI_DEBUG
|
||||
@@ -551,19 +616,19 @@ void SkiddingAI::handleSteering(float dt)
|
||||
/** Decides if the currently selected aim at point (as determined by
|
||||
* handleSteering) should be changed in order to collect/avoid an item.
|
||||
* There are 5 potential phases:
|
||||
* 1) Collect all items close by and sort them by items-to-avoid and
|
||||
* 1. Collect all items close by and sort them by items-to-avoid and
|
||||
* items-to-collect. 'Close by' are all items between the current
|
||||
* graph node the kart is on and the graph node the aim_point is on.
|
||||
* The function evaluateItems() filters those items: atm all items-to-avoid
|
||||
* are collected, and all items-to-collect that are not too far away from
|
||||
* the intended driving direction (i.e. don't require a too sharp steering
|
||||
* change).
|
||||
* 2) If a pre-selected item (see phase 5) exists, and items-to-avoid which
|
||||
* 2. If a pre-selected item (see phase 5) exists, and items-to-avoid which
|
||||
* might get hit if the pre-selected item is collected, the pre-selected
|
||||
* item is unselected. This can happens if e.g. items-to-avoid are behind
|
||||
* the pre-selected items on a different graph node and were therefore not
|
||||
* evaluated then the now pre-selected item was selected initially.
|
||||
* 3) If a pre-selected item exists, the kart will steer towards it. The AI
|
||||
* 3. If a pre-selected item exists, the kart will steer towards it. The AI
|
||||
* does a much better job of collecting items if after selecting an item
|
||||
* it tries to collect this item even if it doesn't fulfill the original
|
||||
* conditions to be selected in the first place anymore. Example: An item
|
||||
@@ -577,11 +642,11 @@ void SkiddingAI::handleSteering(float dt)
|
||||
* feasible to collect them item (if the kart has already passed the item
|
||||
* it won't reverse to collect it). If the item is still to be aimed for,
|
||||
* adjust the aim_point and return.
|
||||
* 4) Make sure to avoid any items-to-avoid. The function steerToAvoid
|
||||
* 4. Make sure to avoid any items-to-avoid. The function steerToAvoid
|
||||
* selects a new aim point if otherwise an item-to-avoid would be hit.
|
||||
* If this is the case, aim_point is adjused and control returns to the
|
||||
* caller.
|
||||
* 5) Try to collect an item-to-collect. Select the closest item to the
|
||||
* 5. Try to collect an item-to-collect. Select the closest item to the
|
||||
* kart (which in case of a row of items will be the item the kart
|
||||
* is roughly driving towards to anyway). It is then tested if the kart
|
||||
* would hit any item-to-avoid when driving towards this item - if so
|
||||
@@ -1000,9 +1065,10 @@ bool SkiddingAI::steerToAvoid(const std::vector<const Item *> &items_to_avoid,
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** This subroutine decides if the specified item should be collected,
|
||||
* avoided, or ignored (i.e. not interesting). It can use the state of the
|
||||
* kart, e.g. depending on what item is available atm, how much nitro it has,
|
||||
* etc. Though atm it picks the first good item, and tries to avoid.
|
||||
* avoided, or ignored. It can potentially use the state of the
|
||||
* kart to make this decision, e.g. depending on what item the kart currently
|
||||
* has, how much nitro it has etc. Though atm it picks the first good item,
|
||||
* and tries to avoid any bad items on the track.
|
||||
* \param item The item which is considered for picking/avoidance.
|
||||
* \param kart_aim_angle The angle of the line from the kart to the aim point.
|
||||
* If aim_angle==kart_heading then the kart is driving towards the
|
||||
@@ -1114,10 +1180,11 @@ void SkiddingAI::evaluateItems(const Item *item, float kart_aim_angle,
|
||||
} // evaluateItems
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Handle all items depending on the chosen strategy: Either (low level AI)
|
||||
* just use an item after 10 seconds, or do a much better job on higher level
|
||||
* AI - e.g. aiming at karts ahead/behind, wait an appropriate time before
|
||||
* using multiple items etc.
|
||||
/** Handle all items depending on the chosen strategy.
|
||||
* Either (low level AI) just use an item after 10 seconds, or do a much
|
||||
* better job on higher level AI - e.g. aiming at karts ahead/behind, wait an
|
||||
* appropriate time before using multiple items etc.
|
||||
* \param dt Time step size.
|
||||
*/
|
||||
void SkiddingAI::handleItems(const float dt)
|
||||
{
|
||||
@@ -1371,6 +1438,9 @@ void SkiddingAI::computeNearestKarts()
|
||||
} // computeNearestKarts
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Determines if the AI should accelerate or not.
|
||||
* \param dt Time step size.
|
||||
*/
|
||||
void SkiddingAI::handleAcceleration( const float dt)
|
||||
{
|
||||
//Do not accelerate until we have delayed the start enough
|
||||
@@ -1426,6 +1496,9 @@ void SkiddingAI::handleRaceStart()
|
||||
} // handleRaceStart
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//TODO: if the AI is crashing constantly, make it move backwards in a straight
|
||||
//line, then move forward while turning.
|
||||
|
||||
void SkiddingAI::handleRescue(const float dt)
|
||||
{
|
||||
// check if kart is stuck
|
||||
@@ -1673,12 +1746,13 @@ void SkiddingAI::checkCrashes(const Vec3& pos )
|
||||
* tested: New left/right lines are computed. If the new left line is to
|
||||
* the right of the old left line, the new left line becomes the current
|
||||
* left line:
|
||||
*
|
||||
* X The new left line connecting kart to X will be to the right
|
||||
* of the old left line, so the available area for the kart
|
||||
* \ / will be dictated by the new left line.
|
||||
* \ /
|
||||
* kart
|
||||
|
||||
\ X The new left line connecting kart to X will be to the right
|
||||
\ / of the old left line, so the available area for the kart
|
||||
\ / will be dictated by the new left line.
|
||||
\ /
|
||||
kart
|
||||
|
||||
* Similarly for the right side. This will narrow down the available area
|
||||
* the kart can aim at, till finally the left and right line overlap.
|
||||
* All points between the connection of the two end points of the left and
|
||||
@@ -1778,7 +1852,7 @@ void SkiddingAI::findNonCrashingPointNew(Vec3 *result, int *last_node)
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Find the sector that at the longest distance from the kart, that can be
|
||||
* driven to without crashing with the track, then find towards which of
|
||||
* the two edges of the track is closest to the next curve after wards,
|
||||
* the two edges of the track is closest to the next curve afterwards,
|
||||
* and return the position of that edge.
|
||||
* \param aim_position The point to aim for, i.e. the point that can be
|
||||
* driven to in a straight line.
|
||||
@@ -1853,18 +1927,21 @@ void SkiddingAI::findNonCrashingPointFixed(Vec3 *aim_position, int *last_node)
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** This is basically the original AI algorithm. It is clearly buggy:
|
||||
* 1) the test:
|
||||
* distance + m_kart_width * 0.5f
|
||||
* > QuadGraph::get()->getNode(*last_node).getPathWidth() )\
|
||||
* 1. the test:
|
||||
*
|
||||
* distance + m_kart_width * 0.5f
|
||||
* > QuadGraph::get()->getNode(*last_node).getPathWidth() )
|
||||
*
|
||||
* is incorrect, it should compare with getPathWith*0.5f (since distance
|
||||
* is the distance from the center, i.e. it is half the path width if
|
||||
* the point is at the edge).
|
||||
* 2) the test:
|
||||
* 2. the test:
|
||||
* QuadGraph::get()->spatialToTrack(&step_track_coord, step_coord,
|
||||
* *last_node );
|
||||
* in the for loop tests always against distance from the same
|
||||
* graph node (*last_node), while de-fact the loop will test points
|
||||
* on various graph nodes.
|
||||
*
|
||||
* This results in this algorithm often picking points to aim at that
|
||||
* would actually force the kart off track. But in reality the kart has
|
||||
* to turn (and does not immediate in one frame change its direction)
|
||||
@@ -1874,7 +1951,7 @@ void SkiddingAI::findNonCrashingPointFixed(Vec3 *aim_position, int *last_node)
|
||||
* \param aim_position On exit contains the point the AI should aim at.
|
||||
* \param last_node On exit contais the graph node the AI is aiming at.
|
||||
*/
|
||||
void SkiddingAI::findNonCrashingPointDefault(Vec3 *aim_position, int *last_node)
|
||||
void SkiddingAI::findNonCrashingPoint(Vec3 *aim_position, int *last_node)
|
||||
{
|
||||
#ifdef AI_DEBUG_KART_HEADING
|
||||
const Vec3 eps(0,0.5f,0);
|
||||
@@ -1955,7 +2032,7 @@ void SkiddingAI::findNonCrashingPointFixed(Vec3 *aim_position, int *last_node)
|
||||
*last_node = target_sector;
|
||||
} // for i<100
|
||||
*aim_position = QuadGraph::get()->getQuadOfNode(*last_node).getCenter();
|
||||
} // findNonCrashingPointDefault
|
||||
} // findNonCrashingPoint
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Determines the direction of the track ahead of the kart: 0 indicates
|
||||
@@ -2308,12 +2385,12 @@ void SkiddingAI::setSteering(float angle, float dt)
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Determine the center point and radius of a circle given two points on
|
||||
* the ccircle and the tangent at the first point. This is done as follows:
|
||||
* 1) Determine the line going through the center point start+end, which is
|
||||
* 1. Determine the line going through the center point start+end, which is
|
||||
* orthogonal to the vector from start to end. This line goes through the
|
||||
* center of the circle.
|
||||
* 2) Determine the line going through the first point and is orthogonal
|
||||
* 2. Determine the line going through the first point and is orthogonal
|
||||
* to the given tangent.
|
||||
* 3) The intersection of these two lines is the center of the circle.
|
||||
* 3. The intersection of these two lines is the center of the circle.
|
||||
* \param start First point.
|
||||
* \param tangent Tangent at first point.
|
||||
* \param end Second point on circle.
|
||||
|
||||
@@ -117,8 +117,8 @@ private:
|
||||
|
||||
/** This implements a simple finite state machine: it starts in
|
||||
* NOT_YET. The first time the AI decides to skid, the state is changed
|
||||
* randomly (dependeng on skid probability) to N_SKID or SKID.
|
||||
* As long as the AI keeps on deciding the skid, the state remains
|
||||
* randomly (depending on skid probability) to NO_SKID or SKID.
|
||||
* As long as the AI keeps on deciding to skid, the state remains
|
||||
* unchanged (so no new random decision is made) till it decides
|
||||
* not to skid. In which case the state is set to NOT_YET again.
|
||||
* This guarantees that for each 'skidable' section of the track
|
||||
@@ -136,13 +136,17 @@ private:
|
||||
/** A random number generator for collecting items. */
|
||||
RandomGenerator m_random_collect_item;
|
||||
|
||||
/** Which of the three Point Selection Algorithms (i.e.
|
||||
* findNoNCrashingPoint* functions) to use:
|
||||
* the default (which is actually slightly buggy, but so far best one
|
||||
* (after handling of 90 degree turns was added)
|
||||
* the fixed one (which fixes one problem of the buggy algorithm),
|
||||
* the new algorithm (see findNonCrashingPoint* for details).
|
||||
* So far the default one has by far the best performance. */
|
||||
/** \brief Determines the algorithm to use to select the point-to-aim-for
|
||||
* There are three different Point Selection Algorithms:
|
||||
* 1. findNonCrashingPoint() is the default (which is actually slightly
|
||||
* buggy, but so far best one (after handling of 90 degree turns was
|
||||
* added)
|
||||
* 2. findNonCrashingPointFixed() which fixes the bugs of the default
|
||||
* algorithm
|
||||
* 3. findNonCrashingPointNew()
|
||||
*
|
||||
* So far the default one has by far the best performance, even though
|
||||
* it has bugs. */
|
||||
enum {PSA_DEFAULT, PSA_FIXED, PSA_NEW}
|
||||
m_point_selection_algorithm;
|
||||
|
||||
@@ -188,7 +192,7 @@ private:
|
||||
void checkCrashes(const Vec3& pos);
|
||||
void findNonCrashingPointFixed(Vec3 *result, int *last_node);
|
||||
void findNonCrashingPointNew(Vec3 *result, int *last_node);
|
||||
void findNonCrashingPointDefault(Vec3 *result, int *last_node);
|
||||
void findNonCrashingPoint(Vec3 *result, int *last_node);
|
||||
|
||||
void determineTrackDirection();
|
||||
void determineTurnRadius(const Vec3 &start,
|
||||
|
||||
Reference in New Issue
Block a user