1 //
2 // SuperTuxKart - a fun racing game with go-kart
3 // Copyright (C) 2006-2009 Eduardo Hernandez Munoz
4 // Copyright (C) 2009-2015 Joerg Henrichs
5 //
6 // This program is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU General Public License
8 // as published by the Free Software Foundation; either version 3
9 // of the License, or (at your option) any later version.
10 //
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
15 //
16 // You should have received a copy of the GNU General Public License
17 // along with this program; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19
20 #include "karts/controller/ai_base_lap_controller.hpp"
21
22 #include <assert.h>
23
24 #include "karts/abstract_kart.hpp"
25 #include "karts/kart_properties.hpp"
26 #include "karts/controller/ai_properties.hpp"
27 #include "modes/linear_world.hpp"
28 #include "tracks/drive_graph.hpp"
29 #include "tracks/track.hpp"
30 #include "utils/constants.hpp"
31
32
33 /**
34 This is the base class for all AIs. At this stage there are two similar
35 AIs: one is the SkiddingAI, which is the AI used in lap based races
36 (including follow-the-leader mode), the other one is the end controller,
37 I.e. the controller that takes over from a player (or AI) when the race is
38 finished.
39
40 This base class defines some basic operations:
41 - It takes care on which part of the DriveGraph the AI currently is.
42 - It determines which path the AI should take (in case of shortcuts
43 or forks in the road).
44
45 At race start and every time a new lap is started, the AI will compute the
46 path the kart is taking this lap (computePath). At this stage the decision
47 which road in case of shortcut to take is purely random. It stores the
48 information in two arrays:
49 m_successor_index[i] stores which successor to take from node i.
50 The successor is a number between 0 and number_of_successors - 1.
51 m_next_node_index[i] stores the actual index of the graph node that
52 follows after node i.
53 Depending on operation one of the other data is more useful, so this
54 class stores both information to avoid looking it up over and over.
55 Once this is done (still in computePath), the array m_all_look_aheads is
56 computed. This array stores for each quad a list of the next (atm) 10 quads.
57 This is used when the AI is selecting where to drive next, and it will just
58 pass the list of next quads to findRoadSector.
59
60 Note that the quad graph information is stored for every quad in the quad
61 graph, even if the quad is not on the path chosen. This is necessary since
62 it can happen that a kart ends up on a path not choses (e.g. perhaps it was
63 pushed on that part, or couldn't get a sharp corner).
64
65 In update(), which gets called one per frame per AI, this object will
66 determine the quad the kart is currently on (which is then used to determine
67 where the kart will be driving to). This uses the m_all_look_aheads to
68 speed up this process (since the kart is likely to be either on the same
69 quad as it was before, or the next quad in the m_all_look_aheads list).
70
71 It will also check if the kart is stuck:
72 this is done by maintaining a list of times when the kart hits the track. If
73 (atm) more than 3 collisions happen in 1.5 seconds, the kart is considered
74 stuck and will trigger a rescue (due to the pushback from the track it will
75 take some time if a kart is really stuck before it will hit the track again).
76
77 This base class also contains some convenience functions which are useful
78 in all AIs, e.g.:
79 - steerToPoint: determine the steering angle to use depending on the
80 current location and the point the kart is driving to.
81 - normalizeAngle: To normalise the steering angle to be in [-PI,PI].
82 - setSteering: Converts the steering angle into a steering fraction
83 in [-1,1].
84
85 */
AIBaseLapController(AbstractKart * kart)86 AIBaseLapController::AIBaseLapController(AbstractKart *kart)
87 : AIBaseController(kart)
88 {
89
90 if (!RaceManager::get()->isBattleMode() &&
91 RaceManager::get()->getMinorMode()!=RaceManager::MINOR_MODE_SOCCER)
92 {
93 m_world = dynamic_cast<LinearWorld*>(World::getWorld());
94 m_track = Track::getCurrentTrack();
95 computePath();
96 }
97 else
98 {
99 // Those variables are not defined in a battle mode (m_world is
100 // a linear world, since it assumes the existance of drivelines)
101 m_world = NULL;
102 m_track = NULL;
103 m_next_node_index.clear();
104 m_all_look_aheads.clear();
105 m_successor_index.clear();
106 } // if battle mode
107 // Don't call our own setControllerName, since this will add a
108 // billboard showing 'AIBaseLapController' to the kar.
109 Controller::setControllerName("AIBaseLapController");
110 } // AIBaseLapController
111
112 //-----------------------------------------------------------------------------
reset()113 void AIBaseLapController::reset()
114 {
115 AIBaseController::reset();
116 } // reset
117
118
119
120 //-----------------------------------------------------------------------------
121 /** Triggers a recomputation of the path to use, so that the AI does not
122 * always use the same way.
123 */
newLap(int lap)124 void AIBaseLapController::newLap(int lap)
125 {
126 if(lap>0)
127 {
128 computePath();
129 }
130 } // newLap
131
132 //-----------------------------------------------------------------------------
133 /** Computes a path for the AI to follow. This function is called at race
134 * start and every time a new lap is started. Recomputing the path every
135 * time will mean that the kart will not always take the same path, but
136 * (potentially) vary from lap to lap. At this stage the decision is done
137 * randomly. The AI could be improved by collecting more information about
138 * each branch of a track, and selecting the 'appropriate' one (e.g. if the
139 * AI is far ahead, chose a longer/slower path).
140 */
computePath()141 void AIBaseLapController::computePath()
142 {
143 m_next_node_index.resize(DriveGraph::get()->getNumNodes());
144 m_successor_index.resize(DriveGraph::get()->getNumNodes());
145 std::vector<unsigned int> next;
146 for(unsigned int i=0; i<DriveGraph::get()->getNumNodes(); i++)
147 {
148 next.clear();
149 // Get all successors the AI is allowed to take.
150 DriveGraph::get()->getSuccessors(i, next, /*for_ai*/true);
151 // In case of short cuts hidden for the AI it can be that a node
152 // might not have a successor (since the first and last edge of
153 // a hidden shortcut is ignored). Since in the case that the AI
154 // ends up on a short cut (e.g. by accident) and doesn't have an
155 // allowed way to drive, it should still be able to drive, so add
156 // the non-AI successors of that node in this case.
157 if(next.size()==0)
158 DriveGraph::get()->getSuccessors(i, next, /*for_ai*/false);
159 // For now pick one part on random, which is not adjusted during the
160 // race. Long term statistics might be gathered to determine the
161 // best way, potentially depending on race position etc.
162 int r = rand();
163 int indx = (int)( r / ((float)(RAND_MAX)+1.0f) * next.size() );
164 // In case of rounding errors0
165 if(indx>=(int)next.size()) indx--;
166 m_successor_index[i] = indx;
167 assert(indx <(int)next.size() && indx>=0);
168 m_next_node_index[i] = next[indx];
169 }
170
171 const unsigned int look_ahead=10;
172 // Now compute for each node in the graph the list of the next 'look_ahead'
173 // graph nodes. This is the list of node that is tested in checkCrashes.
174 // If the look_ahead is too big, the AI can skip loops (see
175 // Graph::findRoadSector for details), if it's too short the AI won't
176 // find too good a driveline. Note that in general this list should
177 // be computed recursively, but since the AI for now is using only
178 // (randomly picked) path this is fine
179 m_all_look_aheads.resize(DriveGraph::get()->getNumNodes());
180 for(unsigned int i=0; i<DriveGraph::get()->getNumNodes(); i++)
181 {
182 std::vector<int> l;
183 int current = i;
184 for(unsigned int j=0; j<look_ahead; j++)
185 {
186 assert(current < (int)m_next_node_index.size());
187 l.push_back(m_next_node_index[current]);
188 current = m_next_node_index[current];
189 } // for j<look_ahead
190 m_all_look_aheads[i] = l;
191 }
192 } // computePath
193
194 //-----------------------------------------------------------------------------
195 /** Updates the ai base controller each time step. Note that any calls to
196 * isStuck() must be done before update is called, since update will call
197 * AIBaseController::update() which will reset the isStuck flag!
198 * \param ticks Number of physics time steps - should be 1.
199 */
update(int ticks)200 void AIBaseLapController::update(int ticks)
201 {
202 AIBaseController::update(ticks);
203 if(DriveGraph::get() && m_world)
204 {
205 // Update the current node:
206 int old_node = m_track_node;
207 if(m_track_node!=Graph::UNKNOWN_SECTOR)
208 {
209 DriveGraph::get()->findRoadSector(m_kart->getXYZ(), &m_track_node,
210 &m_all_look_aheads[m_track_node]);
211 }
212 // If we can't find a proper place on the track, to a broader search
213 // on off-track locations.
214 if(m_track_node==Graph::UNKNOWN_SECTOR)
215 {
216 m_track_node = DriveGraph::get()->findOutOfRoadSector(m_kart->getXYZ());
217 }
218 // IF the AI is off track (or on a branch of the track it did not
219 // select to be on), keep the old position.
220 if(m_track_node==Graph::UNKNOWN_SECTOR ||
221 m_next_node_index[m_track_node]==-1)
222 m_track_node = old_node;
223 }
224 } // update
225
226 //-----------------------------------------------------------------------------
227 /** Returns the next sector of the given sector index. This is used
228 * for branches in the quad graph to select which way the AI kart should
229 * go. This is a very simple implementation that always returns the first
230 * successor, but it can be overridden to allow a better selection.
231 * \param index Index of the graph node for which the successor is searched.
232 * \return Returns the successor of this graph node.
233 */
getNextSector(unsigned int index)234 unsigned int AIBaseLapController::getNextSector(unsigned int index)
235 {
236 std::vector<unsigned int> successors;
237 DriveGraph::get()->getSuccessors(index, successors);
238 return successors[0];
239 } // getNextSector
240
241 //-----------------------------------------------------------------------------
242 /** This function steers towards a given angle. It also takes a plunger
243 ** attached to this kart into account by modifying the actual steer angle
244 * somewhat to simulate driving without seeing.
245 */
steerToAngle(const unsigned int sector,const float add_angle)246 float AIBaseLapController::steerToAngle(const unsigned int sector,
247 const float add_angle)
248 {
249 float angle = DriveGraph::get()->getAngleToNext(sector,
250 getNextSector(sector));
251
252 //Desired angle minus current angle equals how many angles to turn
253 float steer_angle = angle - m_kart->getHeading();
254
255 if(m_kart->getBlockedByPlungerTicks()>0)
256 steer_angle += add_angle*0.2f;
257 else
258 steer_angle += add_angle;
259 steer_angle = normalizeAngle( steer_angle );
260
261 return steer_angle;
262 } // steerToAngle
263