From a09764e77bcb92c65e9c0f7ada7231c3ebb13f43 Mon Sep 17 00:00:00 2001 From: expwnent Date: Tue, 18 Dec 2012 15:22:21 -0500 Subject: [PATCH] Digging Invaders: more optimizations. --- plugins/diggingInvaders/diggingInvaders.cpp | 112 +++++++++++++------- 1 file changed, 76 insertions(+), 36 deletions(-) diff --git a/plugins/diggingInvaders/diggingInvaders.cpp b/plugins/diggingInvaders/diggingInvaders.cpp index 5a15351d9..4f4f317d3 100644 --- a/plugins/diggingInvaders/diggingInvaders.cpp +++ b/plugins/diggingInvaders/diggingInvaders.cpp @@ -33,6 +33,14 @@ #include #include #include + +#define HASHMAP 1 +#if HASHMAP +#include +#include + +#endif + using namespace std; using namespace DFHack; @@ -65,7 +73,7 @@ DFhackCExport command_result plugin_shutdown ( color_ostream &out ) } //cost is [path cost, building destruction cost, dig cost, construct cost]. Minimize constructions, then minimize dig cost, then minimize path cost. -const size_t costDim = 4; +const size_t costDim = 3; struct Cost { int32_t cost[costDim]; @@ -107,6 +115,10 @@ struct Cost { return true; } + bool operator<=(const Cost& c) const { + return *this == c || *this < c; + } + bool operator!=(const Cost& c) const { return !( *this == c); } @@ -156,14 +168,32 @@ public: }; vector* getEdgeSet(color_ostream &out, df::coord point, MapExtras::MapCache& cache, int32_t xMax, int32_t yMax, int32_t zMax); + +#if HASHMAP +df::coord getRoot(df::coord point, unordered_map& rootMap); +#else df::coord getRoot(df::coord point, map& rootMap); +#endif + +struct PointHash { + size_t operator()(const df::coord c) const { + return c.x * 65537 + c.y * 17 + c.z; + } +}; class PointComp { public: +#if HASHMAP + unordered_map *pointCost; + PointComp(unordered_map *p): pointCost(p) { + + } +#else map *pointCost; PointComp(map *p): pointCost(p) { } +#endif int32_t operator()(df::coord p1, df::coord p2) { if ( p1 == p2 ) return 0; @@ -183,7 +213,7 @@ public: } }; -bool important(df::coord pos, map >& edges, df::coord prev, set& importantPoints, set& importantEdges); +//bool important(df::coord pos, map >& edges, df::coord prev, set& importantPoints, set& importantEdges); void doDiggingInvaders(color_ostream& out, void* ptr); command_result diggingInvadersFunc(color_ostream& out, std::vector& parameters) { @@ -196,10 +226,18 @@ command_result diggingInvadersFunc(color_ostream& out, std::vector& void doDiggingInvaders(color_ostream& out, void* ptr) { CoreSuspender suspend; +#if HASHMAP + unordered_set invaderPts; + unordered_set localPts; + unordered_map parentMap; + unordered_map costMap; +#else set invaderPts; set localPts; map parentMap; map costMap; +#endif + PointComp comp(&costMap); set fringe(comp); uint32_t xMax, yMax, zMax; @@ -231,7 +269,11 @@ void doDiggingInvaders(color_ostream& out, void* ptr) { } int32_t localPtsFound = 0; +#if HASHMAP + unordered_set closedSet; +#else set closedSet; +#endif clock_t t0 = clock(); clock_t totalEdgeTime = 0; @@ -249,7 +291,7 @@ void doDiggingInvaders(color_ostream& out, void* ptr) { localPtsFound++; if ( localPtsFound >= localPts.size() ) break; - if ( costMap[pt].cost[1] > 0 || costMap[pt].cost[2] > 0 || costMap[pt].cost[3] > 0 ) + if ( costMap[pt].cost[1] > 0 || costMap[pt].cost[2] > 0 /*|| costMap[pt].cost[3] > 0*/ ) break; } @@ -262,12 +304,19 @@ void doDiggingInvaders(color_ostream& out, void* ptr) { df::coord& other = e.p1; if ( other == pt ) other = e.p2; - if ( costMap.find(other) == costMap.end() || costMap[other] > myCost + e.cost ) { - fringe.erase(other); - costMap[other] = myCost + e.cost; - fringe.insert(other); - parentMap[other] = pt; + //if ( closedSet.find(other) != closedSet.end() ) + // continue; + auto i = costMap.find(other); + if ( i != costMap.end() ) { + Cost& cost = (*i).second; + if ( cost <= myCost + e.cost ) { + continue; + } + fringe.erase((*i).first); } + costMap[other] = myCost + e.cost; + fringe.insert(other); + parentMap[other] = pt; } delete myEdges; } @@ -339,38 +388,20 @@ void doDiggingInvaders(color_ostream& out, void* ptr) { return; Cost cost = costMap[where]; - int32_t cost_tick = 0; - for ( size_t a = 0; a < costDim; a++ ) { - cost_tick += cost.cost[a]; - } + float cost_tick = 0; + cost_tick += cost.cost[0]; + cost_tick += cost.cost[1] / (float)destroySpeed; + cost_tick += cost.cost[2] / (float)digSpeed; EventManager::EventHandler handle(doDiggingInvaders); Plugin* me = Core::getInstance().getPluginManager()->getPluginByName("diggingInvaders"); - EventManager::registerTick(handle, cost_tick, me); + EventManager::registerTick(handle, (int32_t)cost_tick, me); df::global::world->reindex_pathfinding = true; } -bool important(df::coord pos, map >& edges, df::coord prev, set& importantPoints, set& importantEdges) { - //glob_out->print("oh my glob; (%d,%d,%d)\n", pos.x,pos.y,pos.z); - set& myEdges = edges[pos]; - bool result = importantPoints.find(pos) != importantPoints.end(); - for ( auto i = myEdges.begin(); i != myEdges.end(); i++ ) { - Edge e = *i; - df::coord other = e.p1; - if ( other == pos ) - other = e.p2; - if ( other == prev ) - continue; - if ( important(other, edges, pos, importantPoints, importantEdges) ) { - result = true; - importantEdges.insert(e); - } - } - return result; -} int32_t getDestroyCost(df::building* building) { - return 1000 / destroySpeed; + return 10000; #if 0 if ( building->mat_type != 0 ) { cerr << "Error " << __FILE__ << ", " << __LINE__ << endl; @@ -384,7 +415,7 @@ int32_t getDestroyCost(df::building* building) { int32_t getDigCost(MapExtras::MapCache& cache, df::coord point) { //TODO: check for constructions - return 10000 / digSpeed; + return 1000000; #if 0 df::tiletype* type = Maps::getTileType(point); df::enums::tiletype_material::tiletype_material ttmat = ENUM_ATTR(tiletype, material, *type); @@ -400,15 +431,16 @@ int32_t getDigCost(MapExtras::MapCache& cache, df::coord point) { } int32_t getDeconstructCost(df::coord point) { - return 10000 / deconstructSpeed; + return 1000000; } int32_t getConstructCost(df::coord point) { - return 100000 / constructSpeed; + return 10000000; } vector* getEdgeSet(color_ostream &out, df::coord point, MapExtras::MapCache& cache, int32_t xMax, int32_t yMax, int32_t zMax) { vector* result = new vector; + result->reserve(26); for ( int32_t dx = -1; dx <= 1; dx++ ) { for ( int32_t dy = -1; dy <= 1; dy++ ) { @@ -426,6 +458,13 @@ vector* getEdgeSet(color_ostream &out, df::coord point, MapExtras::MapCach Edge edge(point, neighbor, cost); result->push_back(edge); } else { +#if 0 + { + cost.cost[1] = 1; + result->push_back(Edge(point,neighbor,cost)); + continue; + } +#endif //cost.cost[1] = 1; //find out WHY we can't walk there //make it simple: don't deal with unallocated blocks @@ -450,7 +489,8 @@ vector* getEdgeSet(color_ostream &out, df::coord point, MapExtras::MapCach } if ( shape2 == df::enums::tiletype_shape::EMPTY ) { - cost.cost[3] += getConstructCost(neighbor); + //cost.cost[3] += getConstructCost(neighbor); + continue; } else { if ( point.z == neighbor.z ) { if ( ENUM_ATTR(tiletype_shape, walkable, shape2) ) {