1
0
forked from 0ad/0ad

Change back the long pathfinder to take into account non-pathfinding classes, but only when reloading, to avoid impacting the performance.

Also make the GetPassabilityClasses functions use references instead of
wild allocations. Use a reference when passing pass classes to the AI
worker.

This was SVN commit r16833.
This commit is contained in:
Nicolas Auvray 2015-07-05 19:14:52 +00:00
parent 0e4e3754e9
commit 11c9471ad6
8 changed files with 67 additions and 38 deletions

View File

@ -482,7 +482,8 @@ public:
return true;
}
bool RunGamestateInit(const shared_ptr<ScriptInterface::StructuredClone>& gameState, const Grid<u16>& passabilityMap, const Grid<u8>& territoryMap, const std::map<std::string, pass_class_t>& passClassMasks)
bool RunGamestateInit(const shared_ptr<ScriptInterface::StructuredClone>& gameState, const Grid<u16>& passabilityMap, const Grid<u8>& territoryMap,
const std::map<std::string, pass_class_t>& nonPathfindingPassClassMasks, const std::map<std::string, pass_class_t>& pathfindingPassClassMasks)
{
// this will be run last by InitGame.Js, passing the full game representation.
// For now it will run for the shared Component.
@ -496,8 +497,10 @@ public:
ScriptInterface::ToJSVal(cx, &m_TerritoryMapVal, territoryMap);
m_PassabilityMap = passabilityMap;
m_PassClasses = passClassMasks;
m_LongPathfinder.Reload(passClassMasks, &m_PassabilityMap);
m_NonPathfindingPassClasses = nonPathfindingPassClassMasks;
m_PathfindingPassClasses = pathfindingPassClassMasks;
m_LongPathfinder.Reload(&m_PassabilityMap, nonPathfindingPassClassMasks, pathfindingPassClassMasks);
if (m_HasSharedComponent)
{
@ -517,7 +520,7 @@ public:
void StartComputation(const shared_ptr<ScriptInterface::StructuredClone>& gameState,
const Grid<u16>& passabilityMap, const GridUpdateInformation& dirtinessInformations,
const Grid<u8>& territoryMap, bool territoryMapDirty,
std::map<std::string, pass_class_t> passClassMasks)
const std::map<std::string, pass_class_t>& nonPathfindingPassClassMasks, const std::map<std::string, pass_class_t>& pathfindingPassClassMasks)
{
ENSURE(m_CommandsComputed);
@ -528,7 +531,7 @@ public:
{
m_PassabilityMap = passabilityMap;
if (dirtinessInformations.globallyDirty)
m_LongPathfinder.Reload(passClassMasks, &m_PassabilityMap);
m_LongPathfinder.Reload(&m_PassabilityMap, nonPathfindingPassClassMasks, pathfindingPassClassMasks);
else
m_LongPathfinder.Update(&m_PassabilityMap, dirtinessInformations.dirtinessGrid);
ScriptInterface::ToJSVal(cx, &m_PassabilityMapVal, m_PassabilityMap);
@ -658,7 +661,8 @@ public:
}
// AI pathfinder
SerializeMap<SerializeString, SerializeU16_Unbounded>()(serializer, "pass classes", m_PassClasses);
SerializeMap<SerializeString, SerializeU16_Unbounded>()(serializer, "non pathfinding pass classes", m_NonPathfindingPassClasses);
SerializeMap<SerializeString, SerializeU16_Unbounded>()(serializer, "pathfinding pass classes", m_PathfindingPassClasses);
serializer.NumberU16_Unbounded("pathfinder grid w", m_PassabilityMap.m_W);
serializer.NumberU16_Unbounded("pathfinder grid h", m_PassabilityMap.m_H);
serializer.RawBytes("pathfinder grid data", (const u8*)m_PassabilityMap.m_Data,
@ -745,13 +749,14 @@ public:
}
// AI pathfinder
SerializeMap<SerializeString, SerializeU16_Unbounded>()(deserializer, "pass classes", m_PassClasses);
SerializeMap<SerializeString, SerializeU16_Unbounded>()(deserializer, "non pathfinding pass classes", m_NonPathfindingPassClasses);
SerializeMap<SerializeString, SerializeU16_Unbounded>()(deserializer, "pathfinding pass classes", m_PathfindingPassClasses);
u16 mapW, mapH;
deserializer.NumberU16_Unbounded("pathfinder grid w", mapW);
deserializer.NumberU16_Unbounded("pathfinder grid h", mapH);
m_PassabilityMap = Grid<NavcellData>(mapW, mapH);
deserializer.RawBytes("pathfinder grid data", (u8*)m_PassabilityMap.m_Data, mapW*mapH*sizeof(NavcellData));
m_LongPathfinder.Reload(m_PassClasses, &m_PassabilityMap);
m_LongPathfinder.Reload(&m_PassabilityMap, m_NonPathfindingPassClasses, m_PathfindingPassClasses);
}
int getPlayerSize()
@ -866,7 +871,8 @@ private:
Grid<u8> m_TerritoryMap;
JS::PersistentRootedValue m_TerritoryMapVal;
std::map<std::string, pass_class_t> m_PassClasses;
std::map<std::string, pass_class_t> m_NonPathfindingPassClasses;
std::map<std::string, pass_class_t> m_PathfindingPassClasses;
LongPathfinder m_LongPathfinder;
bool m_CommandsComputed;
@ -1022,11 +1028,11 @@ public:
}
LoadPathfinderClasses(state);
std::map<std::string, pass_class_t> passClassMasks;
std::map<std::string, pass_class_t> nonPathfindingPassClassMasks, pathfindingPassClassMasks;
if (cmpPathfinder)
passClassMasks = cmpPathfinder->GetPassabilityClasses(true);
cmpPathfinder->GetPassabilityClasses(nonPathfindingPassClassMasks, pathfindingPassClassMasks);
m_Worker.RunGamestateInit(scriptInterface.WriteStructuredClone(state), *passabilityMap, *territoryMap, passClassMasks);
m_Worker.RunGamestateInit(scriptInterface.WriteStructuredClone(state), *passabilityMap, *territoryMap, nonPathfindingPassClassMasks, pathfindingPassClassMasks);
}
virtual void StartComputation()
@ -1074,14 +1080,14 @@ public:
}
LoadPathfinderClasses(state);
std::map<std::string, pass_class_t> passClassMasks;
std::map<std::string, pass_class_t> nonPathfindingPassClassMasks, pathfindingPassClassMasks;
if (cmpPathfinder)
passClassMasks = cmpPathfinder->GetPassabilityClasses(true);
cmpPathfinder->GetPassabilityClasses(nonPathfindingPassClassMasks, pathfindingPassClassMasks);
m_Worker.StartComputation(scriptInterface.WriteStructuredClone(state),
*passabilityMap, dirtinessInformations,
*territoryMap, territoryMapDirty,
passClassMasks);
nonPathfindingPassClassMasks, pathfindingPassClassMasks);
m_JustDeserialized = false;
}
@ -1170,7 +1176,8 @@ private:
JS::RootedValue classesVal(cx);
scriptInterface.Eval("({})", &classesVal);
std::map<std::string, pass_class_t> classes = cmpPathfinder->GetPassabilityClasses();
std::map<std::string, pass_class_t> classes;
cmpPathfinder->GetPassabilityClasses(classes);
for (std::map<std::string, pass_class_t>::iterator it = classes.begin(); it != classes.end(); ++it)
scriptInterface.SetProperty(classesVal, it->first.c_str(), it->second, true);

View File

@ -216,19 +216,20 @@ pass_class_t CCmpPathfinder::GetPassabilityClass(const std::string& name)
return m_PassClassMasks[name];
}
std::map<std::string, pass_class_t> CCmpPathfinder::GetPassabilityClasses()
void CCmpPathfinder::GetPassabilityClasses(std::map<std::string, pass_class_t>& passClasses) const
{
return m_PassClassMasks;
passClasses = m_PassClassMasks;
}
std::map<std::string, pass_class_t> CCmpPathfinder::GetPassabilityClasses(bool pathfindingClasses)
void CCmpPathfinder::GetPassabilityClasses(std::map<std::string, pass_class_t>& nonPathfindingPassClasses, std::map<std::string, pass_class_t>& pathfindingPassClasses) const
{
std::map<std::string, pass_class_t> passabilityClasses;
for (auto& pair : m_PassClassMasks)
if ((GetPassabilityFromMask(pair.second)->m_Obstructions == PathfinderPassability::PATHFINDING) == pathfindingClasses)
passabilityClasses[pair.first] = pair.second;
return passabilityClasses;
{
if ((GetPassabilityFromMask(pair.second)->m_Obstructions == PathfinderPassability::PATHFINDING))
pathfindingPassClasses[pair.first] = pair.second;
else
nonPathfindingPassClasses[pair.first] = pair.second;
}
}
const PathfinderPassability* CCmpPathfinder::GetPassabilityFromMask(pass_class_t passClass) const
@ -520,7 +521,11 @@ void CCmpPathfinder::UpdateGrid()
// Update the long-range pathfinder
if (m_ObstructionsDirty.globallyDirty)
m_LongPathfinder.Reload(GetPassabilityClasses(true), m_Grid);
{
std::map<std::string, pass_class_t> nonPathfindingPassClasses, pathfindingPassClasses;
GetPassabilityClasses(nonPathfindingPassClasses, pathfindingPassClasses);
m_LongPathfinder.Reload(m_Grid, nonPathfindingPassClasses, pathfindingPassClasses);
}
else
m_LongPathfinder.Update(m_Grid, m_ObstructionsDirty.dirtinessGrid);
}

View File

@ -144,8 +144,10 @@ public:
virtual pass_class_t GetPassabilityClass(const std::string& name);
virtual std::map<std::string, pass_class_t> GetPassabilityClasses();
virtual std::map<std::string, pass_class_t> GetPassabilityClasses(bool pathfindingClasses);
virtual void GetPassabilityClasses(std::map<std::string, pass_class_t>& passClasses) const;
virtual void GetPassabilityClasses(
std::map<std::string, pass_class_t>& nonPathfindingPassClasses,
std::map<std::string, pass_class_t>& pathfindingPassClasses) const;
const PathfinderPassability* GetPassabilityFromMask(pass_class_t passClass) const;

View File

@ -53,12 +53,14 @@ public:
/**
* Get the list of all known passability classes.
*/
virtual std::map<std::string, pass_class_t> GetPassabilityClasses() = 0;
virtual void GetPassabilityClasses(std::map<std::string, pass_class_t>& passClasses) const = 0;
/**
* Get the list of pathfinding passability classes, or all others.
* Get the list of passability classes, separating pathfinding classes and others.
*/
virtual std::map<std::string, pass_class_t> GetPassabilityClasses(bool pathfindingClasses) = 0;
virtual void GetPassabilityClasses(
std::map<std::string, pass_class_t>& nonPathfindingPassClasses,
std::map<std::string, pass_class_t>& pathfindingPassClasses) const = 0;
/**
* Get the tag for a given passability class name.

View File

@ -247,11 +247,16 @@ void HierarchicalPathfinder::SetDebugOverlay(bool enabled, const CSimContext* si
}
}
void HierarchicalPathfinder::Recompute(const std::map<std::string, pass_class_t>& passClassMasks, Grid<NavcellData>* grid)
void HierarchicalPathfinder::Recompute(Grid<NavcellData>* grid,
const std::map<std::string, pass_class_t>& nonPathfindingPassClassMasks,
const std::map<std::string, pass_class_t>& pathfindingPassClassMasks)
{
PROFILE3("Hierarchical Recompute");
m_PassClassMasks = passClassMasks;
m_PassClassMasks = pathfindingPassClassMasks;
std::map<std::string, pass_class_t> allPassClasses = m_PassClassMasks;
allPassClasses.insert(nonPathfindingPassClassMasks.begin(), nonPathfindingPassClassMasks.end());
m_W = grid->m_W;
m_H = grid->m_H;
@ -265,7 +270,7 @@ void HierarchicalPathfinder::Recompute(const std::map<std::string, pass_class_t>
m_Chunks.clear();
m_Edges.clear();
for (auto& passClassMask : passClassMasks)
for (auto& passClassMask : allPassClasses)
{
pass_class_t passClass = passClassMask.second;

View File

@ -79,7 +79,11 @@ public:
void SetDebugOverlay(bool enabled, const CSimContext* simContext);
void Recompute(const std::map<std::string, pass_class_t>& passClassMasks, Grid<NavcellData>* passabilityGrid);
// Non-pathfinding grids will never be recomputed on calling HierarchicalPathfinder::Update
void Recompute(Grid<NavcellData>* passabilityGrid,
const std::map<std::string, pass_class_t>& nonPathfindingPassClassMasks,
const std::map<std::string, pass_class_t>& pathfindingPassClassMasks);
void Update(Grid<NavcellData>* grid, const Grid<u8>& dirtinessGrid);
RegionID Get(u16 i, u16 j, pass_class_t passClass);
@ -164,6 +168,7 @@ private:
std::map<pass_class_t, EdgesMap> m_Edges;
// Passability classes for which grids will be updated when calling Update
std::map<std::string, pass_class_t> m_PassClassMasks;
void AddDebugEdges(pass_class_t passClass);

View File

@ -183,7 +183,9 @@ public:
m_DebugPassClass = passClass;
}
void Reload(const std::map<std::string, pass_class_t>& passClassMasks, Grid<NavcellData>* passabilityGrid)
void Reload(Grid<NavcellData>* passabilityGrid,
const std::map<std::string, pass_class_t>& nonPathfindingPassClassMasks,
const std::map<std::string, pass_class_t>& pathfindingPassClassMasks)
{
m_Grid = passabilityGrid;
ASSERT(passabilityGrid->m_H == passabilityGrid->m_W);
@ -191,7 +193,7 @@ public:
m_JumpPointCache.clear();
m_PathfinderHier.Recompute(passClassMasks, passabilityGrid);
m_PathfinderHier.Recompute(passabilityGrid, nonPathfindingPassClassMasks, pathfindingPassClassMasks);
}
void Update(Grid<NavcellData>* passabilityGrid, const Grid<u8>& dirtinessGrid)

View File

@ -137,10 +137,11 @@ QUERYHANDLER(GetTerrainPassabilityClasses)
CmpPtr<ICmpPathfinder> cmpPathfinder(*AtlasView::GetView_Game()->GetSimulation2(), SYSTEM_ENTITY);
if (cmpPathfinder)
{
std::map<std::string, pass_class_t> classes = cmpPathfinder->GetPassabilityClasses(false);
std::map<std::string, pass_class_t> nonPathfindingClasses, pathfindingClasses;
cmpPathfinder->GetPassabilityClasses(nonPathfindingClasses, pathfindingClasses);
std::vector<std::wstring> classNames;
for (std::map<std::string, pass_class_t>::iterator it = classes.begin(); it != classes.end(); ++it)
for (std::map<std::string, pass_class_t>::iterator it = nonPathfindingClasses.begin(); it != nonPathfindingClasses.end(); ++it)
classNames.push_back(CStr(it->first).FromUTF8());
msg->classNames = classNames;
}