SuperTuxKart
Loading...
Searching...
No Matches
Classes | Public Member Functions | Protected Member Functions | Private Types | Private Member Functions | Private Attributes | List of all members
SkiddingAI Class Reference

This is the actual racing AI. More...

#include <skidding_ai.hpp>

Inheritance diagram for SkiddingAI:
Inheritance graph
[legend]

Classes

class  CrashTypes
 

Public Member Functions

 SkiddingAI (AbstractKart *kart)
 
 ~SkiddingAI ()
 Destructor, mostly to clean up debug data structures.
 
virtual void update (int ticks)
 This is the main entry point for the AI.
 
virtual void reset ()
 Resets the AI when a race is restarted.
 
virtual const irr::core::stringw & getNamePostfix () const
 Returns a name for the AI.
 
- Public Member Functions inherited from AIBaseLapController
 AIBaseLapController (AbstractKart *kart)
 This is the base class for all AIs.
 
virtual void reset ()
 
- Public Member Functions inherited from AIBaseController
 AIBaseController (AbstractKart *kart)
 
virtual void reset () OVERRIDE
 
virtual bool disableSlipstreamBonus () const OVERRIDE
 Certain AI levels will not receive a slipstream bonus in order to be not as hard.
 
virtual void crashed (const Material *m) OVERRIDE
 This is called when the kart crashed with the terrain.
 
virtual void crashed (const AbstractKart *k) OVERRIDE
 
virtual void handleZipper (bool play_sound) OVERRIDE
 
virtual void finishedRace (float time) OVERRIDE
 Called whan this controller's kart finishes the last lap.
 
virtual void collectedItem (const ItemState &item, float previous_energy=0) OVERRIDE
 
virtual void setPosition (int p) OVERRIDE
 
virtual bool isPlayerController () const OVERRIDE
 This function checks if this player is not an AI, i.e.
 
virtual bool isLocalPlayerController () const OVERRIDE
 This function checks if this is a local player.
 
virtual bool action (PlayerAction action, int value, bool dry_run=false) OVERRIDE
 Default: ignore actions.
 
virtual void skidBonusTriggered () OVERRIDE
 
virtual bool saveState (BareNetworkString *buffer) const OVERRIDE
 
virtual void rewindTo (BareNetworkString *buffer) OVERRIDE
 
void setNetworkAI (bool val)
 
virtual void update (int ticks) OVERRIDE
 
- Public Member Functions inherited from Controller
 Controller (AbstractKart *kart)
 Constructor, saves the kart pointer and a pointer to the KartControl of the kart.
 
virtual void reset ()=0
 
virtual void update (int ticks)=0
 
virtual void handleZipper (bool play_sound)=0
 
virtual void collectedItem (const ItemState &item, float previous_energy=0)=0
 
virtual void crashed (const AbstractKart *k)=0
 
virtual void crashed (const Material *m)=0
 
virtual void setPosition (int p)=0
 
virtual bool isLocalPlayerController () const =0
 This function checks if this is a local player.
 
virtual bool isPlayerController () const =0
 This function checks if this player is not an AI, i.e.
 
virtual bool disableSlipstreamBonus () const =0
 
virtual bool saveState (BareNetworkString *buffer) const =0
 
virtual void rewindTo (BareNetworkString *buffer)=0
 
virtual void rumble (float strength_low, float strength_high, uint16_t duration)
 
virtual void setControllerName (const std::string &name)
 Sets the controller name for this controller.
 
const std::string & getControllerName () const
 Returns the name of this controller.
 
virtual bool action (PlayerAction action, int value, bool dry_run=false)=0
 Default: ignore actions.
 
virtual void newLap (int lap)=0
 Callback whenever a new lap is triggered.
 
virtual void skidBonusTriggered ()=0
 
virtual void finishedRace (float time)=0
 Called whan this controller's kart finishes the last lap.
 
virtual KartControlgetControls ()
 Get a pointer on the kart controls.
 
void setControls (KartControl *kc)
 
virtual bool canGetAchievements () const
 Only local players can get achievements.
 
virtual core::stringw getName (bool include_handicap_string=true) const
 Display name of the controller.
 
AbstractKartgetKart () const
 Returns the kart controlled by this controller.
 

Protected Member Functions

virtual unsigned int getNextSector (unsigned int index)
 Returns the pre-computed successor of a graph node.
 
- Protected Member Functions inherited from AIBaseLapController
virtual void update (int ticks)
 Updates the ai base controller each time step.
 
virtual unsigned int getNextSector (unsigned int index)
 Returns the next sector of the given sector index.
 
virtual void newLap (int lap)
 Triggers a recomputation of the path to use, so that the AI does not always use the same way.
 
float steerToAngle (const unsigned int sector, const float angle)
 This function steers towards a given angle.
 
void computePath ()
 Computes a path for the AI to follow.
 
virtual void raceFinished ()
 Nothing special to do when the race is finished.
 
- Protected Member Functions inherited from AIBaseController
void setControllerName (const std::string &name) OVERRIDE
 In debug mode when the user specified –ai-debug on the command line set the name of the controller as on-screen text, so that the different AI controllers can be distinguished.
 
float steerToPoint (const Vec3 &point)
 Computes the steering angle to reach a certain point.
 
float normalizeAngle (float angle)
 Normalises an angle to be between -pi and _ pi.
 
bool isStuck () const
 This can be called to detect if the kart is stuck (i.e.
 
void determineTurnRadius (const Vec3 &end, Vec3 *center, float *radius) const
 Determine the center point and radius of a circle given two points on the circle and the tangent at the first point.
 
virtual void setSteering (float angle, float dt)
 Converts the steering angle to a lr steering in the range of -1 to 1.
 
virtual bool canSkid (float steer_fraction)=0
 Return true if AI can skid now.
 

Private Types

enum  { SKID_PROBAB_NOT_YET , SKID_PROBAB_NO_SKID , SKID_PROBAB_SKID }
 This implements a simple finite state machine: it starts in NOT_YET. More...
 
enum  SkillType { ITEM_SKILL , NITRO_SKILL }
 This is used by computeSkill to know what skill is used.
 
enum  { PSA_DEFAULT , PSA_NEW }
 Determines the algorithm to use to select the point-to-aim-for There are two different Point Selection Algorithms: More...
 

Private Member Functions

void handleRaceStart ()
 
void handleAccelerationAndBraking (int ticks)
 Determines if the AI should accelerate or not, and if not if it should brake.
 
void handleSteering (float dt)
 Decides in which direction to steer.
 
int computeSkill (SkillType type)
 Returns the AI skill value used by the kart.
 
void handleItems (const float dt, const Vec3 *aim_point, int last_node, int item_skill)
 Handle all items depending on the chosen strategy.
 
void handleBubblegum (int item_skill, const std::vector< const ItemState * > &items_to_collect, const std::vector< const ItemState * > &items_to_avoid)
 Handle bubblegum depending on the chosen strategy Level 2 : Use the shield immediately after a wait time Level 3 : Use the shield against flyables except cakes.
 
void handleCake (int item_skill)
 Handle cake depending on the chosen strategy Level 2 : Use the cake against any close vulnerable enemy, with priority to those ahead and close, check if the enemy is roughly ahead.
 
void handleBowling (int item_skill)
 Handle the bowling ball depending on the chosen strategy Level 2 : Use the bowling ball against enemies straight ahead or straight behind, and not invulnerable, with a 5 second delay Level 3 : Only 3 seconds of delay Level 4 : Same as level 3 Level 5 : Level 4 and don't fire on a shielded kart if we're just behind (gum)
 
void handleSwatter (int item_skill)
 Handle the swatter depending on the chosen strategy Level 2 : Use the swatter immediately after a wait time Level 3 : Use the swatter when enemies are close Level 4 : Level 3 and use the swatter to remove bad attachments Level 5 : Level 4 and use against bomb only when the timer ends.
 
void handleSwitch (int item_skill, const std::vector< const ItemState * > &items_to_collect, const std::vector< const ItemState * > &items_to_avoid)
 Handle switch depending on the chosen strategy Level 2 : Use the switch after a wait time Level 3 : Same as level 2 but don't fire if close to a good item Level 4 : Same as level 3 and fire if very close to a bad item Level 5 : Use if it makes a better item available, or if very close to a bad item.
 
void handleRescue (const float dt)
 
void handleBraking (float max_turn_speed, float min_speed)
 This function decides if the AI should brake.
 
void handleNitroAndZipper (float max_safe_speed)
 Decides wether to use nitro and zipper or not.
 
void computeNearestKarts ()
 Determines the closest karts just behind and in front of this kart.
 
void handleItemCollectionAndAvoidance (Vec3 *aim_point, int last_node)
 Decides if the currently selected aim at point (as determined by handleSteering) should be changed in order to collect/avoid an item.
 
bool handleSelectedItem (Vec3 kart_aim_direction, Vec3 *aim_point)
 This function is called when the AI is trying to hit an item that is pre-selected to be collected.
 
bool steerToAvoid (const std::vector< const ItemState * > &items_to_avoid, const core::line3df &line_to_target, Vec3 *aim_point)
 Decides if steering is necessary to avoid bad items.
 
bool hitBadItemWhenAimAt (const ItemState *item, const std::vector< const ItemState * > &items_to_avoid)
 Returns true if the AI would hit any of the listed bad items when trying to drive towards the specified item.
 
void evaluateItems (const ItemState *item, Vec3 kart_aim_direction, std::vector< const ItemState * > *items_to_avoid, std::vector< const ItemState * > *items_to_collect)
 This subroutine decides if the specified item should be collected, avoided, or ignored.
 
void checkCrashes (const Vec3 &pos)
 
void findNonCrashingPointNew (Vec3 *result, int *last_node)
 This is a new version of findNonCrashingPoint, which at this stage is slightly inferior (though faster and more correct) than the original version - the original code cuts corner more aggressively than this version (and in most cases cuting the corner does not end in a collision, so it's actually faster).
 
void findNonCrashingPoint (Vec3 *result, int *last_node)
 This is basically the original AI algorithm.
 
void determineTrackDirection ()
 Determines the direction of the track ahead of the kart: 0 indicates straight, +1 right turn, -1 left turn.
 
virtual bool canSkid (float steer_fraction)
 Determines if the kart should skid.
 
virtual void setSteering (float angle, float dt)
 Converts the steering angle to a lr steering in the range of -1 to 1.
 
void handleCurve ()
 If the kart is at/in a curve, determine the turn radius.
 

Private Attributes

class SkiddingAI::CrashTypes m_crashes
 
RaceManager::AISuperPower m_superpower
 
AbstractKartm_kart_ahead
 Pointer to the closest kart ahead of this kart.
 
float m_distance_ahead
 Distance to the kart ahead.
 
AbstractKartm_kart_behind
 Pointer to the closest kart behind this kart.
 
float m_distance_behind
 Distance to the kard behind.
 
float m_distance_leader
 Distance to the leader kart (used only in FTL) If this kart is leader, contains a high value to avoid the leader slowing down.
 
int m_start_delay
 The actual start delay used in ticks.
 
float m_time_since_last_shot
 Time an item has been collected and not used.
 
float m_time_since_stuck
 
int m_start_kart_crash_direction
 Direction of crash: -1 = left, 1 = right, 0 = no crash.
 
DriveNode::DirectionType m_current_track_direction
 The direction of the track where the kart is on atm.
 
float m_current_curve_radius
 The radius of the curve the kart is currently driving.
 
Vec3 m_curve_center
 Stores the center of the curve (if the kart is in a curve, otherwise undefined).
 
unsigned int m_last_direction_node
 The index of the last node with the same direction as the current node the kart is on.
 
const ItemStatem_item_to_collect
 If set an item that the AI should aim for.
 
bool m_avoid_item_close
 True if items to avoid are close by.
 
float m_distance_to_player
 Distance to the player, used for rubber-banding.
 
int m_num_players_ahead
 Number of players ahead, used for rubber-banding.
 
bool m_burster
 This bool allows to make the AI use nitro by series of two bursts.
 
RandomGenerator m_random_skid
 A random number generator to decide if the AI should skid or not.
 
enum SkiddingAI:: { ... }  m_skid_probability_state
 This implements a simple finite state machine: it starts in NOT_YET.
 
const ItemStatem_last_item_random
 The last item selected for collection, for which a probability was determined.
 
bool m_really_collect_item
 True if m_last_item_random was randomly selected to be collected.
 
RandomGenerator m_random_collect_item
 A random number generator for collecting items.
 
enum SkiddingAI:: { ... }  m_point_selection_algorithm
 Determines the algorithm to use to select the point-to-aim-for There are two different Point Selection Algorithms:
 
ItemManagerm_item_manager
 

Additional Inherited Members

- Static Public Member Functions inherited from AIBaseController
static void enableDebug ()
 
static void setTestAI (int n)
 
static int getTestAI ()
 
- Protected Attributes inherited from AIBaseLapController
int m_track_node
 The current node the kart is on.
 
LinearWorldm_world
 Keep a pointer to world.
 
std::vector< int > m_successor_index
 Which of the successors of a node was selected by the AI.
 
std::vector< int > m_next_node_index
 For each node in the graph this list contains the chosen next node.
 
std::vector< std::vector< int > > m_all_look_aheads
 For each graph node this list contains a list of the next X graph nodes.
 
- Protected Attributes inherited from AIBaseController
bool m_enabled_network_ai
 
float m_kart_length
 Length of the kart, storing it here saves many function calls.
 
float m_kart_width
 Cache width of kart.
 
Trackm_track
 Keep a pointer to the track to reduce calls.
 
const AIPropertiesm_ai_properties
 A pointer to the AI properties for this kart.
 
- Protected Attributes inherited from Controller
AbstractKartm_kart
 Pointer to the kart that is controlled by this controller.
 
KartControlm_controls
 A pointer to the main controller, from which the kart takes it commands.
 
std::string m_controller_name
 The name of the controller, mainly used for debugging purposes.
 
- Static Protected Attributes inherited from AIBaseController
static bool m_ai_debug = false
 
static int m_test_ai = 0
 Stores the '–test-ai=n' command line parameter: It indicates which fraction of the AIs are going to be the test AI: 1 means only to use the TestAI, 2 means every second AI will be test etc.
 

Detailed Description

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:

Member Enumeration Documentation

◆ anonymous enum

anonymous enum
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 (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 the random decision is only done once.

◆ anonymous enum

anonymous enum
private

Determines the algorithm to use to select the point-to-aim-for There are two 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. findNonCrashingPointNew() A newly designed algorithm, which is faster than a fixed version of findNonCrashingPoint, but does not give as good results as the 'buggy' one.

So far the default one has by far the best performance, even though it has bugs.

Member Function Documentation

◆ canSkid()

bool SkiddingAI::canSkid ( float  steer_fraction)
privatevirtual

Determines if the kart should skid.

The base implementation enables skidding

Parameters
steer_fractionThe steering fraction as computed by the AIBaseLapController.
Returns
True if the kart should skid.

Implements AIBaseController.

◆ computeNearestKarts()

void SkiddingAI::computeNearestKarts ( )
private

Determines the closest karts just behind and in front of this kart.

The 'closeness' is for now simply based on the position, i.e. if a kart is more than one lap behind or ahead, it is not considered to be closest.

◆ evaluateItems()

void SkiddingAI::evaluateItems ( const ItemState item,
Vec3  kart_aim_direction,
std::vector< const ItemState * > *  items_to_avoid,
std::vector< const ItemState * > *  items_to_collect 
)
private

This subroutine decides if the specified item should be collected, 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.

Parameters
itemThe item which is considered for picking/avoidance.
kart_aim_angleThe angle of the line from the kart to the aim point. If aim_angle==kart_heading then the kart is driving towards the item.
item_to_avoidA pointer to a previously selected item to avoid (NULL if no item was avoided so far).
item_to_collectA pointer to a previously selected item to collect.

◆ findNonCrashingPoint()

void SkiddingAI::findNonCrashingPoint ( Vec3 aim_position,
int *  last_node 
)
private

This is basically the original AI algorithm.

It is clearly buggy:

  1. the test:
    distance + m_kart_width * 0.5f
             > DriveGraph::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:
    DriveGraph::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) which takes some time - so it is actually mostly on track. Since this algoritm (so far) ends up with by far the best AI behaviour, it is for now the default).

Parameters
aim_positionOn exit contains the point the AI should aim at.
last_nodeOn exit contais the graph node the AI is aiming at.

◆ findNonCrashingPointNew()

void SkiddingAI::findNonCrashingPointNew ( Vec3 result,
int *  last_node 
)
private

This is a new version of findNonCrashingPoint, which at this stage is slightly inferior (though faster and more correct) than the original version - the original code cuts corner more aggressively than this version (and in most cases cuting the corner does not end in a collision, so it's actually faster).

This version find the point furthest ahead which can be reached by travelling in a straight direction from the current location of the kart. This is done by using two lines: one from the kart to the lower left side of the next quad, and one from the kart to the lower right side of the next quad. The area between those two lines can be reached by the kart in a straight line, and will not go off track (assuming that the kart is on track). Then the next quads are 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

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 right line can be reached without getting off track. Which point the kart aims at then depends on the direction of the track: if there is a left turn, the kart will aim to the left point (and vice versa for right turn) - slightly offset by the width of the kart to avoid that the kart is getting off track.

Parameters
aim_positionThe point to aim for, i.e. the point that can be driven to in a straight line.
last_nodeThe graph node index in which the aim_position is.

◆ getNamePostfix()

const irr::core::stringw & SkiddingAI::getNamePostfix ( ) const
virtual

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.

◆ getNextSector()

unsigned int SkiddingAI::getNextSector ( unsigned int  index)
protectedvirtual

Returns the pre-computed successor of a graph node.

Parameters
indexThe index of the graph node for which the successor is searched.

Reimplemented from AIBaseLapController.

◆ handleAccelerationAndBraking()

void SkiddingAI::handleAccelerationAndBraking ( int  ticks)
private

Determines if the AI should accelerate or not, and if not if it should brake.

Parameters
ticksTime step size. //TODO : make acceleration steering aware

◆ handleBowling()

void SkiddingAI::handleBowling ( int  item_skill)
private

Handle the bowling ball depending on the chosen strategy Level 2 : Use the bowling ball against enemies straight ahead or straight behind, and not invulnerable, with a 5 second delay Level 3 : Only 3 seconds of delay Level 4 : Same as level 3 Level 5 : Level 4 and don't fire on a shielded kart if we're just behind (gum)

Parameters
item_skillThe skill with which to use the item

◆ handleBraking()

void SkiddingAI::handleBraking ( float  max_turn_speed,
float  min_speed 
)
private

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).

◆ handleBubblegum()

void SkiddingAI::handleBubblegum ( int  item_skill,
const std::vector< const ItemState * > &  items_to_collect,
const std::vector< const ItemState * > &  items_to_avoid 
)
private

Handle bubblegum depending on the chosen strategy Level 2 : Use the shield immediately after a wait time Level 3 : Use the shield against flyables except cakes.

Use the shield against bad attachments and plunger. Use the bubble gum against an enemy close behind, except if holding a swatter. Level 4 : Level 3, and protect against cakes too, and use before hitting gum/banana Level 5 : Level 4, and use before hitting item box, and let plunger hit (can use the shield after), and use against bomb only when the timer ends

Parameters
item_skillThe skill with which to use the item
items_to_collectThe list of close good items
items_to_avoidThe list of close bad items

◆ handleCake()

void SkiddingAI::handleCake ( int  item_skill)
private

Handle cake depending on the chosen strategy Level 2 : Use the cake against any close vulnerable enemy, with priority to those ahead and close, check if the enemy is roughly ahead.

Level 3 : Level 2 and don't fire on slower karts Level 4 : Level 3 and fire if the kart has a swatter which may hit us Level 5 : Level 4 and don't fire on a shielded kart if we're just behind (gum)

Parameters
item_skillThe skill with which to use the item

◆ handleItemCollectionAndAvoidance()

void SkiddingAI::handleItemCollectionAndAvoidance ( Vec3 aim_point,
int  last_node 
)
private

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 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 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 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 was selected to be collected because the AI was hitting it anyway. Then the aim_point changes, and the selected item is not that close anymore. In many cases it is better to keep on aiming for the items (otherwise the aiming will not have much benefit and mostly only results in collecting items that are on long straights). At this stage because of phase 2) it is certain that no item-to-avoid will be hit. The function handleSelectedItem() evaluates if it is still 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 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 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 the driving direction is not changed and the function returns. Otherwise, i.e. no items-to-avoid will be hit, it is evaluated if the kart is (atm) going to hit it anyway. In this case, the item is selected (see phase 2 and 3). If on the other hand the item is not too far our of the way, aim_point is adjusted to drive towards this item (but it is not selected, so the item will be discarded if the kart is getting too far away from it). Ideally later as the kart is steering towards this item the item will be selected.
Parameters
aim_pointCurrently selected point to aim at. If the AI should try to collect an item, this value will be changed.
last_nodeIndex of the graph node on which the aim_point is.

◆ handleItems()

void SkiddingAI::handleItems ( const float  dt,
const Vec3 aim_point,
int  last_node,
int  item_skill 
)
private

Handle all items depending on the chosen strategy.

Level 0 "AI" : do nothing (not used by default) Level 1 "AI" : use items after a random time Level 2 to 5 AI : strategy detailed before each item Each successive level is overall stronger (5 the strongest, 2 the weakest of non-random strategies), but two levels may share a strategy for a given item.

Parameters
dtTime step size. STATE: shield on -> avoid usage of offensive items (with certain tolerance) STATE: swatter on -> avoid usage of shield

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.

Parameters
dtTime step size. TODO: Implications of Bubble-Shield for AI's powerup-handling

STATE: shield on -> avoid usage of offensive items (with certain tolerance) STATE: swatter on -> avoid usage of shield

◆ handleNitroAndZipper()

void SkiddingAI::handleNitroAndZipper ( float  max_safe_speed)
private

Decides wether to use nitro and zipper or not.

Decides wether to use nitro or not.

◆ handleSelectedItem()

bool SkiddingAI::handleSelectedItem ( Vec3  kart_aim_direction,
Vec3 aim_point 
)
private

This function is called when the AI is trying to hit an item that is pre-selected to be collected.

The AI only evaluates if it's still feasible/useful to try to collect this item, or abandon it (and then look for a new item). At item is unselected if the kart has passed it (so collecting it would require the kart to reverse).

Precondition
m_item_to_collect is defined
Parameters
kart_aim_angleThe angle towards the current aim_point.
aim_pointThe current aim_point.
last_node
Returns
True if th AI should still aim for the pre-selected item.

◆ handleSteering()

void SkiddingAI::handleSteering ( float  dt)
private

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

Parameters
dtTime step size.

◆ handleSwatter()

void SkiddingAI::handleSwatter ( int  item_skill)
private

Handle the swatter depending on the chosen strategy Level 2 : Use the swatter immediately after a wait time Level 3 : Use the swatter when enemies are close Level 4 : Level 3 and use the swatter to remove bad attachments Level 5 : Level 4 and use against bomb only when the timer ends.

Parameters
item_skillThe skill with which to use the item

◆ handleSwitch()

void SkiddingAI::handleSwitch ( int  item_skill,
const std::vector< const ItemState * > &  items_to_collect,
const std::vector< const ItemState * > &  items_to_avoid 
)
private

Handle switch depending on the chosen strategy Level 2 : Use the switch after a wait time Level 3 : Same as level 2 but don't fire if close to a good item Level 4 : Same as level 3 and fire if very close to a bad item Level 5 : Use if it makes a better item available, or if very close to a bad item.

Don't use it if too close of a good item.

Parameters
item_skillThe skill with which to use the item
items_to_collectThe list of close good items
items_to_avoidThe list of close bad items

◆ hitBadItemWhenAimAt()

bool SkiddingAI::hitBadItemWhenAimAt ( const ItemState item,
const std::vector< const ItemState * > &  items_to_avoid 
)
private

Returns true if the AI would hit any of the listed bad items when trying to drive towards the specified item.

Parameters
itemThe item the AI is evaluating for collection.
items_to_aovidA list of bad items close by. All of these needs to be avoided.
Returns
True if it would hit any of the bad items.

◆ reset()

void SkiddingAI::reset ( )
virtual

Resets the AI when a race is restarted.

Reimplemented from AIBaseLapController.

◆ setSteering()

void SkiddingAI::setSteering ( float  angle,
float  dt 
)
privatevirtual

Converts the steering angle to a lr steering in the range of -1 to 1.

If the steering angle is too great, it will also trigger skidding. This function uses a 'time till full steer' value specifying the time it takes for the wheel to reach full left/right steering similar to player karts when using a digital input device. The parameter is defined in the kart properties and helps somewhat to make AI karts more 'pushable' (since otherwise the karts counter-steer to fast). It also takes the effect of a plunger into account by restricting the actual steer angle to 50% of the maximum.

Parameters
angleSteering angle.
dtTime step.

Reimplemented from AIBaseController.

◆ steerToAvoid()

bool SkiddingAI::steerToAvoid ( const std::vector< const ItemState * > &  items_to_avoid,
const core::line3df &  line_to_target,
Vec3 aim_point 
)
private

Decides if steering is necessary to avoid bad items.

If so, it modifies the aim_point and returns true.

Parameters
items_to_avoidList of items to avoid.
line_to_targetThe 2d line from the current kart position to the current aim point.
aim_pointThe point the AI is steering towards (not taking items into account).
Returns
True if steering is necessary to avoid an item.

◆ update()

void SkiddingAI::update ( int  ticks)
virtual

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.

Reimplemented from AIBaseLapController.

Member Data Documentation

◆ m_avoid_item_close

bool SkiddingAI::m_avoid_item_close
private

True if items to avoid are close by.

Used to avoid using zippers (which would make it more difficult to avoid items).

◆ m_current_curve_radius

float SkiddingAI::m_current_curve_radius
private

The radius of the curve the kart is currently driving.

Undefined when being on a straigt section.

◆ m_kart_ahead

AbstractKart* SkiddingAI::m_kart_ahead
private

Pointer to the closest kart ahead of this kart.

NULL if this kart is first.

◆ m_kart_behind

AbstractKart* SkiddingAI::m_kart_behind
private

Pointer to the closest kart behind this kart.

NULL if this kart is last.

◆ m_last_direction_node

unsigned int SkiddingAI::m_last_direction_node
private

The index of the last node with the same direction as the current node the kart is on.

If kart is in a left turn, this will be the last node that is still turning left etc.

◆ 

enum { ... } SkiddingAI::m_point_selection_algorithm

Determines the algorithm to use to select the point-to-aim-for There are two 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. findNonCrashingPointNew() A newly designed algorithm, which is faster than a fixed version of findNonCrashingPoint, but does not give as good results as the 'buggy' one.

So far the default one has by far the best performance, even though it has bugs.

◆ 

enum { ... } SkiddingAI::m_skid_probability_state

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 (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 the random decision is only done once.


The documentation for this class was generated from the following files: