Improved handling of using the same quad more than once

(note: since esp. findOutOfRoadSector is not yet
converted to use the quad graph structure, bugs and
crashes can occur in some circumstances).


git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/branches/irrlicht@3539 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
hikerstk 2009-05-24 10:58:45 +00:00
parent 1f362f88b0
commit b5d7d2b506
5 changed files with 52 additions and 36 deletions

View File

@ -70,6 +70,26 @@ DefaultRobot::DefaultRobot(const std::string& kart_name,
m_successor_index.push_back(indx);
m_next_quad_index.push_back(next[indx]);
}
const int look_ahead=10;
// Now compute for each node in the graph the list of the next 'look_ahead'
// graph nodes. This is the list of node that is tested in checkCrashes.
// If the look_ahead is too big, the AI can skip loops (see
// QuadGraph::findRoadSector for details), if it's too short the AI won't
// find too good a driveline. Note that in general this list should
// be computed recursively, but since the AI for now is using only
// (randomly picked) path this is fine
m_all_look_aheads.reserve(m_quad_graph->getNumNodes());
for(unsigned int i=0; i<m_quad_graph->getNumNodes(); i++)
{
std::vector<int> l;
int current = i;
for(unsigned int j=0; j<look_ahead; j++)
{
l.push_back(m_next_quad_index[current]);
current = m_next_quad_index[current];
} // for j<look_ahead
m_all_look_aheads.push_back(l);
}
m_world = dynamic_cast<LinearWorld*>(RaceManager::getWorld());
assert(m_world != NULL);
@ -133,6 +153,8 @@ void DefaultRobot::update(float dt)
m_controls.m_look_back = false;
m_controls.m_nitro = false;
m_track_sector = m_world->m_kart_info[ getWorldKartId() ].m_track_sector;
if(m_successor_index[m_track_sector]!=0)
printf("XX");
// The client does not do any AI computations.
if(network_manager->getMode()==NetworkManager::NW_CLIENT)
{
@ -844,8 +866,12 @@ void DefaultRobot::checkCrashes( const int STEPS, const Vec3& pos )
}
/*Find if we crash with the drivelines*/
m_track->getQuadGraph().findRoadSector(step_coord, &m_sector,
/* max look ahead */ 10);
if(m_sector!=QuadGraph::UNKNOWN_SECTOR)
m_track->getQuadGraph().findRoadSector(step_coord, &m_sector,
/* sectors to test*/ &m_all_look_aheads[m_sector]);
else
m_track->getQuadGraph().findRoadSector(step_coord, &m_sector);
#undef SHOW_FUTURE_PATH
#ifdef SHOW_FUTURE_PATH

View File

@ -133,6 +133,9 @@ private:
* m_next_quad_index[i] = (i+1) % size;
* but if a branch is possible, the AI will select one option here. */
std::vector<int> m_next_quad_index;
/** For each graph node this list contains a list of the next X
* graph nodes. */
std::vector<std::vector<int> > m_all_look_aheads;
float m_time_since_stuck;
int m_start_kart_crash_direction; //-1 = left, 1 = right, 0 = no crash.

View File

@ -66,6 +66,8 @@ GraphNode::GraphNode(unsigned int index)
*/
void GraphNode::addSuccessor(unsigned int to)
{
if(m_index==4 || m_index==5)
printf("XX");
m_vertices.push_back(to);
// m_index is the quad index, so we use m_all_quads
const Quad &this_quad = m_all_quads->getQuad(m_index);

View File

@ -76,9 +76,9 @@ void QuadGraph::load(const std::string &filename)
// The graph file exist, so read it in. The graph file must first contain
// the node definitions, before the edges can be set.
for(unsigned int i=0; i<xml->getNumNodes(); i++)
for(unsigned int node_index=0; node_index<xml->getNumNodes(); node_index++)
{
const XMLNode *xml_node = xml->getNode(i);
const XMLNode *xml_node = xml->getNode(node_index);
// First graph node definitions:
// -----------------------------
if(xml_node->getName()=="node-list")
@ -247,38 +247,20 @@ void QuadGraph::spatialToTrack(Vec3 *dst, const Vec3& xyz,
* \param XYZ Position for which the segment should be determined.
* \param sector Contains the previous sector (as a shortcut, since usually
* the sector is the same as the last one), and on return the result
* \param max_lookahead Maximum number of graph nodes that are to be searched
* from the current sector number. This is used by the AI to make sure
* the AI does not skip any parts of the track (e.g. if the graph has
* a loop, the AI code skip the whole loop otherwise and continue
* on the normal path). Only used ith sector is not UNKNOWN_SECTOR.
* Defaults to -1, which indicates to use all graph nodes. The actual
* value might depend on the track, the size of the drivelines etc.
* \param all_sectors If this is not NULL, it is a list of all sectors to
* test. This is used by the AI to make sure that it ends up on the
* selected way in case of a branch, and also to make sure that it
* doesn't skip e.g. a loop (see explanation below for details).
*/
void QuadGraph::findRoadSector(const Vec3& xyz, int *sector,
int max_lookahead) const
std::vector<int> *all_sectors) const
{
if(*sector!=UNKNOWN_SECTOR)
// Most likely the kart will still be on the sector it was before,
// so this simple case is tested first.
if(*sector!=UNKNOWN_SECTOR && getQuad(*sector).pointInQuad(xyz) )
{
// Most likely the kart will still be on the sector it was before,
// so this simple case is tested first.
if(getQuad(*sector).pointInQuad(xyz) )
return;
// Then check all immediate neighbours. If it's any of them,
// immediately return without any further tests.
const GraphNode &node = *m_all_nodes[*sector];
for(unsigned int i=0; i<node.getNumberOfSuccessors(); i++)
{
int succ = node.getSuccessor(i);
if(getQuad(succ).pointInQuad(xyz))
{
*sector = succ;
return;
} // if pointInQuad
} // for i<node.getNumberOfSuccessors()
} // if *sector!=UNKNOWN_SECTOR
return;
} // if still on same quad
// Now we search through all graph nodes, starting with
// the current one
@ -294,13 +276,16 @@ void QuadGraph::findRoadSector(const Vec3& xyz, int *sector,
// and the track is supposed to be driven: ABCDEBF, the AI might find
// the node on F, and then keep on going straight ahead instead of
// using the loop at all.
unsigned int max_count = (*sector!=UNKNOWN_SECTOR && max_lookahead>0)
? max_lookahead
unsigned int max_count = (*sector!=UNKNOWN_SECTOR && all_sectors!=NULL)
? all_sectors->size()
: m_all_nodes.size();
*sector = UNKNOWN_SECTOR;
for(unsigned int i=0; i<max_count; i++)
{
indx = indx<(int)m_all_nodes.size()-1 ? indx +1 : 0;
if(all_sectors)
indx = (*all_sectors)[i];
else
indx = indx<(int)m_all_nodes.size()-1 ? indx +1 : 0;
const Quad &q = getQuad(indx);
float dist = xyz.getZ() - q.getMinHeight();
// While negative distances are unlikely, we allow some small netative

View File

@ -55,7 +55,7 @@ public:
void spatialToTrack(Vec3 *dst, const Vec3& xyz,
const int sector) const;
void findRoadSector(const Vec3& XYZ, int *sector,
int max_lookahead=-1) const;
std::vector<int> *all_sectors=NULL) const;
/** Returns the number of nodes in the graph. */
unsigned int getNumNodes() const { return m_all_nodes.size(); }