2010-02-13 16:34:18 -07:00
|
|
|
// digger.cpp
|
|
|
|
|
|
|
|
// Usage: Call with a list of TileClass ids separated by a space,
|
|
|
|
// every (visible) tile on the map with that id will be designated for digging.
|
|
|
|
|
2010-02-16 12:45:05 -07:00
|
|
|
// NOTE currently only works with trees
|
|
|
|
|
|
|
|
// 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
|
2010-02-17 11:21:23 -07:00
|
|
|
// TODO add ability to mark num closest to cursor
|
2010-02-16 12:45:05 -07:00
|
|
|
|
2010-02-13 16:34:18 -07:00
|
|
|
#include <iostream>
|
|
|
|
#include <integers.h>
|
|
|
|
#include <vector>
|
|
|
|
#include <list>
|
|
|
|
#include <cstdlib>
|
2010-02-17 11:21:23 -07:00
|
|
|
#include <algorithm>
|
2010-02-13 16:34:18 -07:00
|
|
|
using namespace std;
|
|
|
|
|
|
|
|
#include <DFTypes.h>
|
|
|
|
#include <DFTileTypes.h>
|
|
|
|
#include <DFHackAPI.h>
|
|
|
|
|
|
|
|
int vec_count(vector<uint16_t>& vec, uint16_t t)
|
|
|
|
{
|
|
|
|
int count = 0;
|
|
|
|
for (uint32_t i = 0; i < vec.size(); ++i)
|
|
|
|
{
|
|
|
|
if (vec[i] == t)
|
|
|
|
++count;
|
|
|
|
}
|
|
|
|
return count;
|
|
|
|
}
|
|
|
|
|
2010-02-17 12:08:34 -07:00
|
|
|
//// 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);
|
|
|
|
//}
|
|
|
|
|
|
|
|
int manhattan_distance(int x, int y, int z, int xx, int yy, int zz)
|
2010-02-13 16:34:18 -07:00
|
|
|
{
|
2010-02-17 12:08:34 -07:00
|
|
|
return abs(x-xx)+abs(y-yy)+abs(z-zz);
|
2010-02-17 11:21:23 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
struct DigTarget
|
|
|
|
{
|
|
|
|
int source_distance; // the distance to the source coords, used for sorting
|
2010-02-17 12:08:34 -07:00
|
|
|
int x, y, z;
|
2010-02-17 11:21:23 -07:00
|
|
|
bool operator<(const DigTarget& o) { return source_distance < o.source_distance; }
|
|
|
|
};
|
|
|
|
|
|
|
|
int dig(DFHack::API& DF,
|
|
|
|
vector<uint16_t>& 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
|
|
|
|
|
2010-02-13 16:34:18 -07:00
|
|
|
uint32_t x_max,y_max,z_max;
|
2010-02-17 12:08:34 -07:00
|
|
|
DFHack::t_designation designations[16][16];
|
|
|
|
uint16_t tiles[16][16];
|
2010-02-17 11:21:23 -07:00
|
|
|
//uint32_t count = 0;
|
2010-02-13 16:34:18 -07:00
|
|
|
DF.getSize(x_max,y_max,z_max);
|
2010-02-17 11:21:23 -07:00
|
|
|
|
|
|
|
// every tile found, will later be sorted by distance to source
|
|
|
|
vector<DigTarget> candidates;
|
2010-02-17 12:08:34 -07:00
|
|
|
|
|
|
|
cout << "============================" << endl;
|
|
|
|
cout << "source is " << x_source << " " << y_source << " " << z_source << endl;
|
2010-02-13 16:34:18 -07:00
|
|
|
|
|
|
|
// walk the map
|
2010-02-17 11:21:23 -07:00
|
|
|
for(uint32_t x = 0; x < x_max; x++)
|
2010-02-13 16:34:18 -07:00
|
|
|
{
|
2010-02-17 11:21:23 -07:00
|
|
|
for(uint32_t y = 0; y < y_max; y++)
|
2010-02-13 16:34:18 -07:00
|
|
|
{
|
2010-02-17 11:21:23 -07:00
|
|
|
for(uint32_t z = 0; z < z_max; z++)
|
2010-02-13 16:34:18 -07:00
|
|
|
{
|
2010-02-17 11:21:23 -07:00
|
|
|
if (z != z_source)
|
|
|
|
continue; // hack to cut down on targets
|
|
|
|
|
2010-02-13 16:34:18 -07:00
|
|
|
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);
|
|
|
|
|
2010-02-17 11:21:23 -07:00
|
|
|
// search all tiles for dig targets:
|
|
|
|
// visible, not yet marked for dig and matching tile type
|
2010-02-17 12:08:34 -07:00
|
|
|
for(uint32_t lx = 0; lx < 16; lx++)
|
|
|
|
{
|
|
|
|
for(uint32_t ly = 0; ly < 16; ly++)
|
|
|
|
{
|
|
|
|
if (designations[lx][ly].bits.hidden == 0 &&
|
|
|
|
designations[lx][ly].bits.dig == 0 &&
|
|
|
|
vec_count(targets, DFHack::tileTypeTable[tiles[lx][ly]].c) > 0)
|
|
|
|
{
|
|
|
|
//cout << "target found at: ";
|
|
|
|
//cout << x << "," << y << "," << z << "," << i << endl;
|
|
|
|
|
|
|
|
//designations[i].bits.dig = DFHack::designation_default;
|
|
|
|
//++count;
|
|
|
|
|
|
|
|
DigTarget dt;
|
|
|
|
dt.x = x+lx;
|
|
|
|
dt.y = y+ly;
|
|
|
|
dt.z = z;
|
|
|
|
dt.source_distance = manhattan_distance(
|
|
|
|
x_source, y_source, z_source,
|
|
|
|
//x, y, z, i);
|
|
|
|
x+lx, y+ly, z);
|
|
|
|
candidates.push_back(dt);
|
|
|
|
|
|
|
|
cout << "target found at " << x+lx << " " << y+ly << " " << z;
|
|
|
|
cout << ", " << dt.source_distance << " tiles to source" << endl;
|
|
|
|
}
|
|
|
|
} // local y
|
|
|
|
} // local x
|
2010-02-13 16:34:18 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2010-02-17 11:21:23 -07:00
|
|
|
|
|
|
|
// 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();
|
|
|
|
|
2010-02-17 12:08:34 -07:00
|
|
|
cout << "============================" << endl;
|
|
|
|
cout << "source is " << x_source << " " << y_source << " " << z_source << endl;
|
|
|
|
|
2010-02-17 11:21:23 -07:00
|
|
|
// mark the tiles for actual digging
|
|
|
|
for (vector<DigTarget>::iterator i = candidates.begin(); i != candidates.end(); ++i)
|
|
|
|
{
|
2010-02-17 12:08:34 -07:00
|
|
|
int world_x = (*i).x/16;
|
|
|
|
int world_y = (*i).y/16;
|
|
|
|
int world_z = (*i).z;
|
|
|
|
|
|
|
|
int local_x = (*i).x-world_x;
|
|
|
|
int local_y = (*i).y-world_y;
|
|
|
|
|
|
|
|
cout << "designating at " << world_x+local_x << " " << world_y+local_y << " " << (*i).z;
|
|
|
|
cout << ", " << (*i).source_distance << " tiles to source" << endl;
|
|
|
|
|
2010-02-17 11:21:23 -07:00
|
|
|
// TODO this could probably be made much better, theres a big chance the trees are on the same grid
|
2010-02-17 12:08:34 -07:00
|
|
|
DF.ReadDesignations(world_x, world_y, world_z, (uint32_t *) designations);
|
|
|
|
designations[local_x][local_y].bits.dig = DFHack::designation_default;
|
|
|
|
DF.WriteDesignations(world_x, world_y, world_z, (uint32_t *) designations);
|
2010-02-17 11:21:23 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
return num;
|
2010-02-13 16:34:18 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
int main (int argc, const char* argv[])
|
|
|
|
{
|
|
|
|
vector<uint16_t> targets;
|
|
|
|
for (int i = 1; i < argc; ++i)
|
|
|
|
{
|
|
|
|
targets.push_back(atoi(argv[i]));
|
|
|
|
}
|
|
|
|
if (targets.size() == 0)
|
|
|
|
{
|
|
|
|
cout << "Usage: Call with a list of TileClass ids separated by a space,\n";
|
|
|
|
cout << "every (visible) tile on the map with that id will be designated for digging.\n\n";
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
DFHack::API DF("Memory.xml");
|
|
|
|
if(!DF.Attach())
|
|
|
|
{
|
|
|
|
cerr << "DF not found" << endl;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
DF.InitMap();
|
2010-02-17 11:21:23 -07:00
|
|
|
|
|
|
|
// 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;
|
|
|
|
//}
|
2010-02-13 16:34:18 -07:00
|
|
|
|
2010-02-17 11:21:23 -07:00
|
|
|
int count = dig(DF, targets, 10, x_source, y_source, z_source); // <-- important part
|
2010-02-13 16:34:18 -07:00
|
|
|
cout << count << " targets designated" << endl;
|
|
|
|
|
|
|
|
DF.Detach();
|
|
|
|
}
|
|
|
|
#ifndef LINUX_BUILD
|
|
|
|
cout << "Done. Press any key to continue" << endl;
|
|
|
|
cin.ignore();
|
|
|
|
#endif
|
|
|
|
return 0;
|
|
|
|
}
|