More fiddling. Almost kind of works.

develop
expwnent 2012-12-17 17:36:35 -05:00
parent 76fcf1c335
commit ef80dbacde
1 changed files with 121 additions and 11 deletions

@ -17,9 +17,13 @@
#include "df/map_block.h" #include "df/map_block.h"
#include "df/ui.h" #include "df/ui.h"
#include "df/unit.h" #include "df/unit.h"
#include "df/tiletype.h"
#include "df/tiletype_shape.h"
#include "df/tiletype_shape_basic.h"
#include "df/world.h" #include "df/world.h"
#include <algorithm> #include <algorithm>
#include <cstdlib>
#include <cstring> #include <cstring>
#include <map> #include <map>
#include <set> #include <set>
@ -94,7 +98,8 @@ DFhackCExport command_result plugin_onupdate ( color_ostream &out )
} }
};*/ };*/
const size_t costDim = 2; //cost is [path cost, dig cost, construct cost]. Minimize constructions, then minimize dig cost, then minimize path cost.
const size_t costDim = 3;
struct Cost { struct Cost {
int32_t cost[costDim]; int32_t cost[costDim];
@ -309,7 +314,7 @@ command_result diggingInvadersFunc(color_ostream& out, std::vector<std::string>&
} }
//find important edges //find important edges
set<Edge> importantEdges; list<Edge> importantEdges;
map<df::coord, int32_t> importance; map<df::coord, int32_t> importance;
for ( auto i = localPts.begin(); i != localPts.end(); i++ ) { for ( auto i = localPts.begin(); i != localPts.end(); i++ ) {
df::coord pt = *i; df::coord pt = *i;
@ -317,13 +322,13 @@ 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 ) if ( costMap[pt].cost[1] == 0 && costMap[pt].cost[2] == 0 )
continue; 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); 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,0)); importantEdges.push_front(Edge(pt,parent,0));
} }
pt = parent; pt = parent;
} }
@ -332,6 +337,34 @@ command_result diggingInvadersFunc(color_ostream& out, std::vector<std::string>&
for ( auto i = importantEdges.begin(); i != importantEdges.end(); i++ ) { for ( auto i = importantEdges.begin(); i != importantEdges.end(); i++ ) {
Edge e = *i; Edge e = *i;
df::coord pt1 = e.p1;
df::coord pt2 = e.p2;
if ( costMap[e.p2] < costMap[e.p1] ) {
pt1 = e.p2;
pt2 = e.p1;
}
df::building* building = Buildings::findAtTile(pt2);
if ( building != NULL ) {
out.print("%d\n", __LINE__);
building->flags.bits.almost_deleted = true;
//Buildings::deconstructImmediately(building);
out.print("%d\n", __LINE__);
} else {
df::map_block* block1 = Maps::getTileBlock(pt1);
df::map_block* block2 = Maps::getTileBlock(pt2);
df::tiletype* type1 = Maps::getTileType(pt1);
df::tiletype* type2 = Maps::getTileType(pt2);
df::tiletype_shape shape1 = ENUM_ATTR(tiletype, shape, *type1);
df::tiletype_shape shape2 = ENUM_ATTR(tiletype, shape, *type2);
if ( pt1.z != pt2.z && shape1 != df::enums::tiletype_shape::STAIR_DOWN && shape1 != df::enums::tiletype_shape::STAIR_UPDOWN ) {
block1->tiletype[pt2.x&0x0F][pt2.y&0x0F] = df::enums::tiletype::ConstructedStairUD;
}
if ( ENUM_ATTR(tiletype_shape, basic_shape, shape2) == df::enums::tiletype_shape_basic::Wall ) {
block2->tiletype[pt2.x&0x0F][pt2.y&0x0F] = df::enums::tiletype::ConstructedStairUD;
}
}
/*if ( e.p1.z == e.p2.z ) { /*if ( e.p1.z == e.p2.z ) {
}*/ }*/
@ -339,6 +372,7 @@ command_result diggingInvadersFunc(color_ostream& out, std::vector<std::string>&
importance[e.p2]++; importance[e.p2]++;
} }
#if 0
//dig important points //dig important points
for ( auto a = importance.begin(); a != importance.end(); a++ ) { for ( auto a = importance.begin(); a != importance.end(); a++ ) {
df::coord pos = (*a).first; df::coord pos = (*a).first;
@ -350,12 +384,6 @@ command_result diggingInvadersFunc(color_ostream& out, std::vector<std::string>&
df::map_block* block = Maps::getTileBlock(pos); df::map_block* block = Maps::getTileBlock(pos);
block->tiletype[pos.x&0x0F][pos.y&0x0F] = df::enums::tiletype::ConstructedStairUD; block->tiletype[pos.x&0x0F][pos.y&0x0F] = df::enums::tiletype::ConstructedStairUD;
} }
#if 0
/*for ( auto a = importantPoints.begin(); a != importantPoints.end(); a++ ) {
df::coord pos = (*a);
out.print("Important point: (%d,%d,%d)\n", pos.x,pos.y,pos.z);
}*/
#endif #endif
return CR_OK; return CR_OK;
@ -399,7 +427,89 @@ vector<Edge>* getEdgeSet(color_ostream &out, df::coord point, int32_t xMax, int3
Edge edge(point, neighbor, cost); Edge edge(point, neighbor, cost);
result->push_back(edge); result->push_back(edge);
} else { } else {
cost.cost[1] = 1; //cost.cost[1] = 1;
//find out WHY we can't walk there
//make it simple: don't deal with unallocated blocks
Maps::ensureTileBlock(point);
Maps::ensureTileBlock(neighbor);
df::tiletype* type1 = Maps::getTileType(point);
df::tiletype* type2 = Maps::getTileType(neighbor);
df::map_block* block1 = Maps::getTileBlock(point);
df::map_block* block2 = Maps::getTileBlock(neighbor);
df::tiletype_shape shape1 = ENUM_ATTR(tiletype, shape, *type1);
df::tiletype_shape shape2 = ENUM_ATTR(tiletype, shape, *type2);
{
df::building* building1 = Buildings::findAtTile(point);
df::building* building2 = Buildings::findAtTile(neighbor);
if ( building2 != NULL && building2 != building1 ) {
cost.cost[1] += 1;
if ( dz != 0 )
continue;
}
}
if ( shape2 == df::enums::tiletype_shape::EMPTY ) {
cost.cost[2] += 1;
} else {
if ( point.z == neighbor.z ) {
if ( ENUM_ATTR(tiletype_shape, walkable, shape2) ) {
if ( ENUM_ATTR(tiletype_shape, walkable, shape1 ) ) {
//exit(1);
//must be building impassible tile or something
//TODO: check
df::building* building = Buildings::findAtTile(neighbor);
if ( building != NULL )
cost.cost[1]+=1;
else {
building = Buildings::findAtTile(point);
if ( building == NULL ) {
//out.print("%s, %d: (%d,%d,%d), (%d,%d,%d)\n", __FILE__, __LINE__, point.x,point.y,point.z, neighbor.x,neighbor.y,neighbor.z);
//exit(1);
//TODO: deal with the silly RAMP_TOP condition
continue;
}
}
}
//this is fine: only charge once for digging through a wall
} else {
cost.cost[1] += 20;
}
} else {
bool ascending = neighbor.z > point.z;
/*df::tiletype_shape temp;
if ( neighbor.z > point.z ) {
temp = shape1;
shape1 = shape2;
shape2 = temp;
}*/
if ( point.x == neighbor.x && point.y == neighbor.y ) {
if ( ENUM_ATTR(tiletype_shape, basic_shape, shape2) == df::enums::tiletype_shape_basic::Stair ) {
if ( (ascending && ENUM_ATTR(tiletype_shape, passable_low, shape2)) || (!ascending && ENUM_ATTR(tiletype_shape, walkable_up, shape2)) ) {
//must be a forbidden hatch: TODO: check
cost.cost[1] += 1;
} else {
//too complicated
continue;
}
} else {
//bad!
if ( ENUM_ATTR(tiletype_shape, basic_shape, shape2) == df::enums::tiletype_shape_basic::Wall ) {
cost.cost[1] += 20;
} else if ( ENUM_ATTR(tiletype_shape, basic_shape, shape2) == df::enums::tiletype_shape_basic::Open ) {
cost.cost[2] += 1;
} else {
continue;
}
}
} else {
//too complicated
continue;
}
}
}
Edge edge(point, neighbor, cost); Edge edge(point, neighbor, cost);
result->push_back(edge); result->push_back(edge);
} }