1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-20 20:23:03 +02:00

NKAI: water paths in graph

This commit is contained in:
Andrii Danylchenko 2024-02-11 15:27:56 +02:00
parent b236384356
commit fb6fd63a58
5 changed files with 62 additions and 7 deletions

View File

@ -373,6 +373,7 @@ void AIGateway::objectRemoved(const CGObjectInstance * obj, const PlayerColor &
return;
nullkiller->memory->removeFromMemory(obj);
nullkiller->baseGraph->removeObject(obj);
if(obj->ID == Obj::HERO && obj->tempOwner == playerID)
{

View File

@ -10,6 +10,7 @@
#include "StdInc.h"
#include "ObjectGraph.h"
#include "AIPathfinderConfig.h"
#include "../../../lib/CRandomGenerator.h"
#include "../../../CCallback.h"
#include "../../../lib/mapping/CMap.h"
#include "../Engine/Nullkiller.h"
@ -21,10 +22,10 @@ namespace NKAI
void ObjectGraph::updateGraph(const Nullkiller * ai)
{
auto cb = ai->cb;
auto mapSize = cb->getMapSize();
std::map<const CGHeroInstance *, HeroRole> actors;
std::map<const CGHeroInstance *, const CGObjectInstance *> actorObjectMap;
std::vector<CGBoat *> boats;
auto addObjectActor = [&](const CGObjectInstance * obj)
{
@ -37,8 +38,14 @@ void ObjectGraph::updateGraph(const Nullkiller * ai)
objectActor->pos = objectActor->convertFromVisitablePos(visitablePos);
objectActor->initObj(rng);
if(cb->getTile(visitablePos)->isWater())
{
boats.push_back(new CGBoat(objectActor->cb));
objectActor->boat = boats.back();
}
actorObjectMap[objectActor] = obj;
actors[objectActor] = obj->ID == Obj::TOWN ? HeroRole::MAIN : HeroRole::SCOUT;
actors[objectActor] = obj->ID == Obj::TOWN || obj->ID == Obj::SHIPYARD ? HeroRole::MAIN : HeroRole::SCOUT;
addObject(obj);
};
@ -85,6 +92,17 @@ void ObjectGraph::updateGraph(const Nullkiller * ai)
auto obj1 = actorObjectMap[path1.targetHero];
auto obj2 = actorObjectMap[path2.targetHero];
auto tile1 = cb->getTile(obj1->visitablePos());
auto tile2 = cb->getTile(obj2->visitablePos());
if(tile2->isWater() && !tile1->isWater())
{
auto linkTile = cb->getTile(pos);
if(!linkTile->isWater() || obj1->ID != Obj::BOAT || obj1->ID != Obj::SHIPYARD)
continue;
}
auto danger = ai->pathfinder->getStorage()->evaluateDanger(obj2->visitablePos(), path1.targetHero, true);
auto updated = nodes[obj1->visitablePos()].connections[obj2->visitablePos()].update(
@ -108,11 +126,16 @@ void ObjectGraph::updateGraph(const Nullkiller * ai)
}
});
for(auto h : actors)
for(auto h : actorObjectMap)
{
delete h.first;
}
for(auto boat : boats)
{
delete boat;
}
#if NKAI_GRAPH_TRACE_LEVEL >= 1
dumpToLog("graph");
#endif
@ -123,6 +146,21 @@ void ObjectGraph::addObject(const CGObjectInstance * obj)
nodes[obj->visitablePos()].init(obj);
}
void ObjectGraph::removeObject(const CGObjectInstance * obj)
{
nodes[obj->visitablePos()].objectExists = false;
if(obj->ID == Obj::BOAT)
{
vstd::erase_if(nodes[obj->visitablePos()].connections, [&](const std::pair<int3, ObjectLink> & link) -> bool
{
auto tile = cb->getTile(link.first, false);
return tile && tile->isWater();
});
}
}
void ObjectGraph::connectHeroes(const Nullkiller * ai)
{
for(auto obj : ai->memory->visitableObjs)
@ -170,7 +208,7 @@ void ObjectGraph::dumpToLog(std::string visualKey) const
node.second.danger);
#endif
logBuilder.addLine(node.first, tile.first);
logBuilder.addLine(tile.first, node.first);
}
}
});
@ -206,9 +244,7 @@ void GraphPaths::calculatePaths(const CGHeroInstance * targetHero, const Nullkil
graph.iterateConnections(pos.coord, [&](int3 target, ObjectLink o)
{
auto graphNode = graph.getNode(target);
auto targetNodeType = o.danger ? GrapthPathNodeType::BATTLE : pos.nodeType;
auto targetPointer = GraphPathNodePointer(target, targetNodeType);
auto & targetNode = getNode(targetPointer);

View File

@ -60,6 +60,7 @@ public:
void updateGraph(const Nullkiller * ai);
void addObject(const CGObjectInstance * obj);
void connectHeroes(const Nullkiller * ai);
void removeObject(const CGObjectInstance * obj);
void dumpToLog(std::string visualKey) const;
template<typename Func>

View File

@ -512,6 +512,20 @@ namespace vstd
}
}
//works for std::unordered_map, maybe something else
template<typename Key, typename Val, typename Predicate>
void erase_if(std::unordered_map<Key, Val> & container, Predicate pred)
{
auto itr = container.begin();
auto endItr = container.end();
while(itr != endItr)
{
auto tmpItr = itr++;
if(pred(*tmpItr))
container.erase(tmpItr);
}
}
template<typename InputRange, typename OutputIterator, typename Predicate>
OutputIterator copy_if(const InputRange &input, OutputIterator result, Predicate pred)
{

View File

@ -80,9 +80,12 @@ public:
auto pEnd = model->getTargetTileArea(end).topLeft();
auto viewPort = target.getRenderArea();
pStart.x += 3;
pEnd.x -= 3;
if(viewPort.isInside(pStart) && viewPort.isInside(pEnd))
{
target.drawLine(pStart, pEnd, ColorRGBA(255, 255, 0), ColorRGBA(255, 255, 0));
target.drawLine(pStart, pEnd, ColorRGBA(255, 255, 0), ColorRGBA(255, 0, 0));
}
}
};