diff --git a/examples/digger.cpp b/examples/digger.cpp index 1a4e8f556..958b7f089 100644 --- a/examples/digger.cpp +++ b/examples/digger.cpp @@ -8,12 +8,14 @@ // TODO add a sort of "sub-target" to dig() to make it able to designate stone as well // TODO add proper cli // TODO add interactive text based menu +// TODO add ability to mark num closest to cursor #include #include #include #include #include +#include using namespace std; #include @@ -31,48 +33,120 @@ int vec_count(vector& vec, uint16_t t) return count; } -int dig(DFHack::API& DF, vector& targets) +// manhattan distance +int source_distance(int sx, int sy, int sz, + int x, int y, int z, int i) { + // TODO changing x and y seems to be optimized away (?) + cout << x << " " << i << " " << i%16 << " " << x+(i%16) << endl; + + // handle the fact that x,y,z refers to a 16x16 grid + //x += i%16; + //y += i/16; + int dx = i%16; + int dy = i/16; + //x *= 16; + //y *= 16; + //x += dx; + //y += dy; + return abs(sx-(x+(i%16)))+abs(sy-(y+(i/16)))+abs(sz-z); +} + +struct DigTarget +{ + int source_distance; // the distance to the source coords, used for sorting + int x, y, z; // call read designations with these and you have the tile at i + int i; // 0 <= i <= 255 + + bool operator<(const DigTarget& o) { return source_distance < o.source_distance; } +}; + +int dig(DFHack::API& DF, + vector& targets, + int num = -1, + const int x_source = 0, + const int y_source = 0, + const int z_source = 0) +{ + if (num == 0) + return 0; // max limit of 0, nothing to do + uint32_t x_max,y_max,z_max; DFHack::t_designation designations[256]; uint16_t tiles[256]; - uint32_t count = 0; + //uint32_t count = 0; DF.getSize(x_max,y_max,z_max); + + // every tile found, will later be sorted by distance to source + vector candidates; // walk the map - for(uint32_t x = 0; x< x_max;x++) + for(uint32_t x = 0; x < x_max; x++) { - for(uint32_t y = 0; y< y_max;y++) + for(uint32_t y = 0; y < y_max; y++) { - for(uint32_t z = 0; z< z_max;z++) + for(uint32_t z = 0; z < z_max; z++) { + if (z != z_source) + continue; // hack to cut down on targets + if(DF.isValidBlock(x,y,z)) { // read block designations and tiletype DF.ReadDesignations(x,y,z, (uint32_t *) designations); DF.ReadTileTypes(x,y,z, (uint16_t *) tiles); - // check all tiles, if type is in target list and its visible: designate for dig + // search all tiles for dig targets: + // visible, not yet marked for dig and matching tile type for (uint32_t i = 0; i < 256; i++) { if (designations[i].bits.hidden == 0 && + designations[i].bits.dig == 0 && vec_count(targets, DFHack::tileTypeTable[tiles[i]].c) > 0) { //cout << "target found at: "; //cout << x << "," << y << "," << z << "," << i << endl; - designations[i].bits.dig = DFHack::designation_default; - ++count; + + //designations[i].bits.dig = DFHack::designation_default; + //++count; + + DigTarget dt; + dt.x = x; + dt.y = y; + dt.z = z; + dt.i = i; + dt.source_distance = source_distance( + x_source, y_source, z_source, + x, y, z, i); + candidates.push_back(dt); } } - - // write the designations back - // could probably be optimized in the cases where we dont changed anything - DF.WriteDesignations(x,y,z, (uint32_t *) designations); } } } } - return count; + + // TODO the following routine doesnt check if the tile is already marked for digging + + // if we found more tiles than was requested, sort them by distance to source, + // keep the front 'num' elements and drop the rest + if (num != -1 && candidates.size() > (unsigned int)num) + { + sort(candidates.begin(), candidates.end()); + candidates.resize(num); + } + num = candidates.size(); + + // mark the tiles for actual digging + for (vector::iterator i = candidates.begin(); i != candidates.end(); ++i) + { + // TODO this could probably be made much better, theres a big chance the trees are on the same grid + DF.ReadDesignations((*i).x, (*i).y, (*i).z, (uint32_t *) designations); + designations[(*i).i].bits.dig = DFHack::designation_default; + DF.WriteDesignations((*i).x, (*i).y, (*i).z, (uint32_t *) designations); + } + + return num; } int main (int argc, const char* argv[]) @@ -96,8 +170,17 @@ int main (int argc, const char* argv[]) return 1; } DF.InitMap(); + + // TODO hack until we have a proper cli to specify origin + int x_source = 134, y_source = 134, z_source = 16; // my wagon starts here; cut trees close to wagon + //DF.InitViewAndCursor(); + //if (!DF.getViewCoords(x_source, y_source, z_source)) + //{ + // cerr << "Enable cursor" << endl; + // return 1; + //} - int count = dig(DF, targets); // <-- important part + int count = dig(DF, targets, 10, x_source, y_source, z_source); // <-- important part cout << count << " targets designated" << endl; DF.Detach();