Digging invaders: multi-dimensional edge cost: always prefer walking over digging, no matter how far.

develop
expwnent 2012-12-17 14:22:45 -05:00
parent 94673e447d
commit 76fcf1c335
1 changed files with 78 additions and 27 deletions

@ -20,6 +20,7 @@
#include "df/world.h" #include "df/world.h"
#include <algorithm> #include <algorithm>
#include <cstring>
#include <map> #include <map>
#include <set> #include <set>
#include <vector> #include <vector>
@ -93,13 +94,68 @@ DFhackCExport command_result plugin_onupdate ( color_ostream &out )
} }
};*/ };*/
const size_t costDim = 2;
struct Cost {
int32_t cost[costDim];
Cost() {
memset(cost, 0, costDim*sizeof(int32_t));
}
Cost( int32_t costIn[costDim] ) {
memcpy(cost, costIn, costDim*sizeof(int32_t));
}
Cost(const Cost& c) {
memcpy(cost, c.cost, costDim*sizeof(int32_t));
}
Cost( int32_t i ) {
memset(cost, 0, costDim*sizeof(int32_t));
cost[0] = i;
}
bool operator>(const Cost& c) const {
for ( size_t a = 0; a < costDim; a++ ) {
if ( cost[costDim-1-a] != c.cost[costDim-1-a] )
return cost[costDim-1-a] > c.cost[costDim-1-a];
}
return false;
}
bool operator<(const Cost& c) const {
for ( size_t a = 0; a < costDim; a++ ) {
if ( cost[costDim-1-a] != c.cost[costDim-1-a] )
return cost[costDim-1-a] < c.cost[costDim-1-a];
}
return false;
}
bool operator==(const Cost& c) const {
for ( size_t a = 0; a < costDim; a++ ) {
if ( cost[a] != c.cost[a] )
return false;
}
return true;
}
bool operator!=(const Cost& c) const {
return !( *this == c);
}
Cost operator+(const Cost& c) const {
Cost result(*this);
for ( size_t a = 0; a < costDim; a++ ) {
result.cost[a] += c.cost[a];
}
return result;
}
};
class Edge { class Edge {
public: public:
//static map<df::coord, int32_t> pointCost; //static map<df::coord, int32_t> pointCost;
df::coord p1; df::coord p1;
df::coord p2; df::coord p2;
int32_t cost; Cost cost;
Edge(df::coord p1In, df::coord p2In, int32_t costIn): cost(costIn) { Edge(df::coord p1In, df::coord p2In, Cost costIn): cost(costIn) {
if ( p2In < p1In ) { if ( p2In < p1In ) {
p1 = p2In; p1 = p2In;
p2 = p1In; p2 = p1In;
@ -126,16 +182,6 @@ public:
return p2 < e.p2; return p2 < e.p2;
return false; return false;
} }
/*bool operator<(const Edge e) const {
int32_t pCost = max(pointCost[p1], pointCost[p2]) + cost;
int32_t e_pCost = max(pointCost[e.p1], pointCost[e.p2]) + e.cost;
if ( pCost != e_pCost )
return pCost < e_pCost;
if ( p1 != e.p1 )
return p1 < e.p1;
return p2 < e.p2;
}*/
}; };
vector<Edge>* getEdgeSet(color_ostream &out, df::coord point, int32_t xMax, int32_t yMax, int32_t zMax); vector<Edge>* getEdgeSet(color_ostream &out, df::coord point, int32_t xMax, int32_t yMax, int32_t zMax);
@ -143,23 +189,23 @@ df::coord getRoot(df::coord point, map<df::coord, df::coord>& rootMap);
class PointComp { class PointComp {
public: public:
map<df::coord, int32_t> *pointCost; map<df::coord, Cost> *pointCost;
PointComp(map<df::coord, int32_t> *p): pointCost(p) { PointComp(map<df::coord, Cost> *p): pointCost(p) {
} }
int32_t operator()(df::coord p1, df::coord p2) { int32_t operator()(df::coord p1, df::coord p2) {
if ( p1 == p2 ) return 0; if ( p1 == p2 ) return 0;
map<df::coord, int32_t>::iterator i1 = pointCost->find(p1); auto i1 = pointCost->find(p1);
map<df::coord, int32_t>::iterator i2 = pointCost->find(p2); auto i2 = pointCost->find(p2);
if ( i1 == pointCost->end() && i2 == pointCost->end() ) if ( i1 == pointCost->end() && i2 == pointCost->end() )
return p1 < p2; return p1 < p2;
if ( i1 == pointCost->end() ) if ( i1 == pointCost->end() )
return 1; return true;
if ( i2 == pointCost->end() ) if ( i2 == pointCost->end() )
return -1; return false;
int32_t c1 = (*i1).second; Cost c1 = (*i1).second;
int32_t c2 = (*i2).second; Cost c2 = (*i2).second;
if ( c1 != c2 ) if ( c1 != c2 )
return c1 < c2; return c1 < c2;
return p1 < p2; return p1 < p2;
@ -177,7 +223,7 @@ command_result diggingInvadersFunc(color_ostream& out, std::vector<std::string>&
set<df::coord> invaderPts; set<df::coord> invaderPts;
set<df::coord> localPts; set<df::coord> localPts;
map<df::coord, df::coord> parentMap; map<df::coord, df::coord> parentMap;
map<df::coord, int32_t> costMap; map<df::coord, Cost> costMap;
PointComp comp(&costMap); PointComp comp(&costMap);
set<df::coord, PointComp> fringe(comp); set<df::coord, PointComp> fringe(comp);
uint32_t xMax, yMax, zMax; uint32_t xMax, yMax, zMax;
@ -232,7 +278,7 @@ command_result diggingInvadersFunc(color_ostream& out, std::vector<std::string>&
localPtsFound++; localPtsFound++;
if ( localPtsFound >= localPts.size() ) if ( localPtsFound >= localPts.size() )
break; break;
if ( costMap[pt] > 0 ) if ( costMap[pt].cost[1] > 0 )
break; break;
} }
@ -245,7 +291,7 @@ command_result diggingInvadersFunc(color_ostream& out, std::vector<std::string>&
} }
delete edges; delete edges;
} }
int32_t myCost = costMap[pt]; Cost myCost = costMap[pt];
set<Edge>& myEdges = edgeSet[pt]; set<Edge>& myEdges = edgeSet[pt];
for ( auto a = myEdges.begin(); a != myEdges.end(); a++ ) { for ( auto a = myEdges.begin(); a != myEdges.end(); a++ ) {
Edge e = *a; Edge e = *a;
@ -271,13 +317,17 @@ command_result diggingInvadersFunc(color_ostream& out, std::vector<std::string>&
continue; continue;
if ( parentMap.find(pt) == parentMap.end() ) if ( parentMap.find(pt) == parentMap.end() )
continue; continue;
if ( costMap[pt].cost[1] == 0 )
continue;
while ( parentMap.find(pt) != parentMap.end() ) { while ( parentMap.find(pt) != parentMap.end() ) {
out.print("(%d,%d,%d)\n", pt.x, pt.y, pt.z);
df::coord parent = parentMap[pt]; df::coord parent = parentMap[pt];
if ( !Maps::canWalkBetween(pt, parent) ) { if ( !Maps::canWalkBetween(pt, parent) ) {
importantEdges.insert(Edge(pt,parent,1)); importantEdges.insert(Edge(pt,parent,0));
} }
pt = parent; pt = parent;
} }
break;
} }
for ( auto i = importantEdges.begin(); i != importantEdges.end(); i++ ) { for ( auto i = importantEdges.begin(); i != importantEdges.end(); i++ ) {
@ -343,13 +393,14 @@ vector<Edge>* getEdgeSet(color_ostream &out, df::coord point, int32_t xMax, int3
continue; continue;
if ( dx == 0 && dy == 0 && dz == 0 ) if ( dx == 0 && dy == 0 && dz == 0 )
continue; continue;
int32_t cost = 0; Cost cost = 1;
//if ( dz != 0 ) cost++; //if ( dz != 0 ) cost++;
if ( Maps::canWalkBetween(point, neighbor) ) { if ( Maps::canWalkBetween(point, neighbor) ) {
Edge edge(point, neighbor, cost+0); Edge edge(point, neighbor, cost);
result->push_back(edge); result->push_back(edge);
} else { } else {
Edge edge(point, neighbor, cost+1); cost.cost[1] = 1;
Edge edge(point, neighbor, cost);
result->push_back(edge); result->push_back(edge);
} }
} }