123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155 |
- /*
- * ObjectGraph.cpp, part of VCMI engine
- *
- * Authors: listed in file AUTHORS in main folder
- *
- * License: GNU General Public License v2.0 or later
- * Full text of license available in license.txt file, in main folder
- *
- */
- #include "StdInc.h"
- #include "ObjectGraph.h"
- #include "ObjectGraphCalculator.h"
- #include "AIPathfinderConfig.h"
- #include "../../../lib/CRandomGenerator.h"
- #include "../../../lib/mapping/CMap.h"
- #include "../Engine/Nullkiller.h"
- #include "../../../lib/logging/VisualLogger.h"
- #include "Actions/QuestAction.h"
- #include "../pforeach.h"
- #include "Actions/BoatActions.h"
- namespace NKAI
- {
- bool ObjectGraph::tryAddConnection(
- const int3 & from,
- const int3 & to,
- float cost,
- uint64_t danger)
- {
- auto result = nodes[from].connections[to].update(cost, danger);
- auto & connection = nodes[from].connections[to];
- if(result && isVirtualBoat(to) && !connection.specialAction)
- {
- connection.specialAction = std::make_shared<AIPathfinding::BuildBoatActionFactory>(virtualBoats[to]);
- }
- return result;
- }
- void ObjectGraph::removeConnection(const int3 & from, const int3 & to)
- {
- nodes[from].connections.erase(to);
- }
- void ObjectGraph::updateGraph(const Nullkiller * ai)
- {
- auto cb = ai->cb;
- ObjectGraphCalculator calculator(this, ai);
- calculator.setGraphObjects();
- calculator.calculateConnections();
- calculator.addMinimalDistanceJunctions();
- calculator.calculateConnections();
- if(NKAI_GRAPH_TRACE_LEVEL >= 1)
- dumpToLog("graph");
- }
- void ObjectGraph::addObject(const CGObjectInstance * obj)
- {
- if(!hasNodeAt(obj->visitablePos()))
- nodes[obj->visitablePos()].init(obj);
- }
- void ObjectGraph::addVirtualBoat(const int3 & pos, const CGObjectInstance * shipyard)
- {
- if(!isVirtualBoat(pos))
- {
- virtualBoats[pos] = shipyard->id;
- }
- }
- void ObjectGraph::registerJunction(const int3 & pos)
- {
- if(!hasNodeAt(pos))
- nodes[pos].initJunction();
- }
- void ObjectGraph::removeObject(const CGObjectInstance * obj)
- {
- nodes[obj->visitablePos()].objectExists = false;
- if(obj->ID == Obj::BOAT && !isVirtualBoat(obj->visitablePos()))
- {
- 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)
- {
- if(obj && obj->ID == Obj::HERO)
- {
- addObject(obj);
- }
- }
- for(auto & node : nodes)
- {
- auto pos = node.first;
- auto paths = ai->pathfinder->getPathInfo(pos);
- for(AIPath & path : paths)
- {
- if(path.getFirstBlockedAction())
- continue;
- auto heroPos = path.targetHero->visitablePos();
- nodes[pos].connections[heroPos].update(
- std::max(0.0f, path.movementCost()),
- path.getPathDanger());
- nodes[heroPos].connections[pos].update(
- std::max(0.0f, path.movementCost()),
- path.getPathDanger());
- }
- }
- }
- void ObjectGraph::dumpToLog(std::string visualKey) const
- {
- logVisual->updateWithLock(visualKey, [&](IVisualLogBuilder & logBuilder)
- {
- for(auto & tile : nodes)
- {
- for(auto & node : tile.second.connections)
- {
- if(NKAI_GRAPH_TRACE_LEVEL >= 2)
- {
- logAi->trace(
- "%s -> %s: %f !%d",
- node.first.toString(),
- tile.first.toString(),
- node.second.cost,
- node.second.danger);
- }
- logBuilder.addLine(tile.first, node.first);
- }
- }
- });
- }
- }
|