Detach in API destructor

develop
Petr Mrázek 2010-03-16 22:12:05 +01:00
parent ff27cdb2f3
commit df4de4a333
2 changed files with 365 additions and 361 deletions

@ -187,6 +187,8 @@ API::API (const string path_to_xml)
API::~API() API::~API()
{ {
// FIXME: call all finishread* methods here
Detach();
delete d; delete d;
} }
@ -1056,7 +1058,7 @@ bool API::ReadSettlement(const int32_t index, t_settlement & settlement)
// read pointer from vector at position // read pointer from vector at position
uint32_t temp = * (uint32_t *) d->p_settlements->at (index); uint32_t temp = * (uint32_t *) d->p_settlements->at (index);
settlement.origin = temp; settlement.origin = temp;
d->readName(settlement.name, temp + d->settlement_name_offset); d->readName(settlement.name, temp + d->settlement_name_offset);
g_pProcess->read(temp + d->settlement_world_xy_offset, 2 * sizeof(int16_t), (uint8_t *) &settlement.world_x); g_pProcess->read(temp + d->settlement_world_xy_offset, 2 * sizeof(int16_t), (uint8_t *) &settlement.world_x);
g_pProcess->read(temp + d->settlement_local_xy_offset, 4 * sizeof(int16_t), (uint8_t *) &settlement.local_x1); g_pProcess->read(temp + d->settlement_local_xy_offset, 4 * sizeof(int16_t), (uint8_t *) &settlement.local_x1);
return true; return true;
@ -1069,7 +1071,7 @@ bool API::ReadCurrentSettlement(t_settlement & settlement)
uint32_t temp = * (uint32_t *) d->p_current_settlement->at(0); uint32_t temp = * (uint32_t *) d->p_current_settlement->at(0);
settlement.origin = temp; settlement.origin = temp;
d->readName(settlement.name, temp + d->settlement_name_offset); d->readName(settlement.name, temp + d->settlement_name_offset);
g_pProcess->read(temp + d->settlement_world_xy_offset, 2 * sizeof(int16_t), (uint8_t *) &settlement.world_x); g_pProcess->read(temp + d->settlement_world_xy_offset, 2 * sizeof(int16_t), (uint8_t *) &settlement.world_x);
g_pProcess->read(temp + d->settlement_local_xy_offset, 4 * sizeof(int16_t), (uint8_t *) &settlement.local_x1); g_pProcess->read(temp + d->settlement_local_xy_offset, 4 * sizeof(int16_t), (uint8_t *) &settlement.local_x1);
return true; return true;
@ -1196,8 +1198,8 @@ bool API::ReadCreature (const int32_t index, t_creature & furball)
g_pProcess->readDWord (temp + d->creature_flags2_offset, furball.flags2.whole); g_pProcess->readDWord (temp + d->creature_flags2_offset, furball.flags2.whole);
// names // names
d->readName(furball.name,temp + d->creature_name_offset); d->readName(furball.name,temp + d->creature_name_offset);
d->readName(furball.squad_name, temp + d->creature_squad_name_offset); d->readName(furball.squad_name, temp + d->creature_squad_name_offset);
d->readName(furball.artifact_name, temp + d->creature_artifact_name_offset); d->readName(furball.artifact_name, temp + d->creature_artifact_name_offset);
// custom profession // custom profession
fill_char_buf (furball.custom_profession, d->p->readSTLString (temp + d->creature_custom_profession_offset)); fill_char_buf (furball.custom_profession, d->p->readSTLString (temp + d->creature_custom_profession_offset));
@ -1439,6 +1441,8 @@ bool API::Attach()
bool API::Detach() bool API::Detach()
{ {
if(!d->p)
return false;
if (!d->p->detach()) if (!d->p->detach())
{ {
return false; return false;

@ -1,357 +1,357 @@
// digger.cpp // digger.cpp
// NOTE currently only works with trees // 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 a sort of "sub-target" to dig() to make it able to designate stone as well
#include <iostream> #include <iostream>
#include <integers.h> #include <integers.h>
#include <vector> #include <vector>
#include <list> #include <list>
#include <cstdlib> #include <cstdlib>
#include <algorithm> #include <algorithm>
#include <assert.h> #include <assert.h>
using namespace std; using namespace std;
#include <DFTypes.h> #include <DFTypes.h>
#include <DFTileTypes.h> #include <DFTileTypes.h>
#include <DFHackAPI.h> #include <DFHackAPI.h>
#include <argstream/argstream.h> #include <argstream/argstream.h>
// counts the occurances of a certain element in a vector // counts the occurances of a certain element in a vector
// used to determine of a given tile is a target // used to determine of a given tile is a target
int vec_count(vector<uint16_t>& vec, uint16_t t) int vec_count(vector<uint16_t>& vec, uint16_t t)
{ {
int count = 0; int count = 0;
for (uint32_t i = 0; i < vec.size(); ++i) for (uint32_t i = 0; i < vec.size(); ++i)
{ {
if (vec[i] == t) if (vec[i] == t)
++count; ++count;
} }
return count; return count;
} }
// splits a string on a certain char // splits a string on a certain char
// //
// src is the string to split // src is the string to split
// delim is the delimiter to split the string around // delim is the delimiter to split the string around
// tokens is filled with every occurance between delims // tokens is filled with every occurance between delims
void string_split(vector<string>& tokens, const std::string& src, const std::string& delim) void string_split(vector<string>& tokens, const std::string& src, const std::string& delim)
{ {
std::string::size_type start = 0; std::string::size_type start = 0;
std::string::size_type end; std::string::size_type end;
while (true) while (true)
{ {
end = src.find(delim, start); end = src.find(delim, start);
tokens.push_back(src.substr(start, end - start)); tokens.push_back(src.substr(start, end - start));
if (end == std::string::npos) // last token handled if (end == std::string::npos) // last token handled
break; break;
start = end + delim.size(); // skip next delim start = end + delim.size(); // skip next delim
} }
} }
// this is used to parse the command line options // this is used to parse the command line options
void parse_int_csv(vector<uint16_t>& targets, const std::string& src) void parse_int_csv(vector<uint16_t>& targets, const std::string& src)
{ {
std::string::size_type start = 0; std::string::size_type start = 0;
std::string::size_type end; std::string::size_type end;
while (true) while (true)
{ {
end = src.find(",", start); end = src.find(",", start);
targets.push_back(atoi(src.substr(start, end - start).c_str())); targets.push_back(atoi(src.substr(start, end - start).c_str()));
if (end == std::string::npos) // last token handled if (end == std::string::npos) // last token handled
break; break;
start = end + 1; // skip next delim start = end + 1; // skip next delim
} }
} }
struct DigTarget struct DigTarget
{ {
DigTarget() : DigTarget() :
source_distance(0), source_distance(0),
grid_x(0), grid_y(0), grid_x(0), grid_y(0),
local_x(0), local_y(0), local_x(0), local_y(0),
real_x(0), real_y(0), z(0) real_x(0), real_y(0), z(0)
{ {
} }
DigTarget( DigTarget(
int realx, int realy, int _z, int realx, int realy, int _z,
int sourcex, int sourcey, int sourcez) : int sourcex, int sourcey, int sourcez) :
real_x(realx), real_y(realy), z(_z) real_x(realx), real_y(realy), z(_z)
{ {
grid_x = realx/16; grid_x = realx/16;
grid_y = realy/16; grid_y = realy/16;
local_x = realx%16; local_x = realx%16;
local_y = realy%16; local_y = realy%16;
source_distance = manhattan_distance( source_distance = manhattan_distance(
real_x, real_y, z, real_x, real_y, z,
sourcex, sourcey, sourcez); sourcex, sourcey, sourcez);
} }
DigTarget( DigTarget(
int gridx, int gridy, int _z, int gridx, int gridy, int _z,
int localx, int localy, int localx, int localy,
int sourcex, int sourcey, int sourcez) : int sourcex, int sourcey, int sourcez) :
grid_x(gridx), grid_y(gridy), grid_x(gridx), grid_y(gridy),
local_x(localx), local_y(localy), local_x(localx), local_y(localy),
z(_z) z(_z)
{ {
real_x = (grid_x*16)+local_x; real_x = (grid_x*16)+local_x;
real_y = (grid_y*16)+local_y; real_y = (grid_y*16)+local_y;
source_distance = manhattan_distance( source_distance = manhattan_distance(
real_x, real_y, z, real_x, real_y, z,
sourcex, sourcey, sourcez); sourcex, sourcey, sourcez);
} }
int source_distance; // the distance to the source coords, used for sorting int source_distance; // the distance to the source coords, used for sorting
int grid_x, grid_y; // what grid the target is in int grid_x, grid_y; // what grid the target is in
int local_x, local_y; // on what coord in the grid the target is in (0-16) int local_x, local_y; // on what coord in the grid the target is in (0-16)
int real_x, real_y; // real coordinates for target, thats grid*16+local int real_x, real_y; // real coordinates for target, thats grid*16+local
int z; // z position for target, stored plain since there arent z grids int z; // z position for target, stored plain since there arent z grids
bool operator<(const DigTarget& o) const { return source_distance < o.source_distance; } bool operator<(const DigTarget& o) const { return source_distance < o.source_distance; }
private: private:
// calculates the manhattan distance between two coords // calculates the manhattan distance between two coords
int manhattan_distance(int x, int y, int z, int xx, int yy, int zz) int manhattan_distance(int x, int y, int z, int xx, int yy, int zz)
{ {
return abs(x-xx)+abs(y-yy)+abs(z-zz); return abs(x-xx)+abs(y-yy)+abs(z-zz);
} }
}; };
int dig(DFHack::API& DF, int dig(DFHack::API& DF,
vector<uint16_t>& targets, vector<uint16_t>& targets,
int num = -1, int num = -1,
const int x_source = 0, const int x_source = 0,
const int y_source = 0, const int y_source = 0,
const int z_source = 0, const int z_source = 0,
bool verbose = false) bool verbose = false)
{ {
if (num == 0) if (num == 0)
return 0; // max limit of 0, nothing to do return 0; // max limit of 0, nothing to do
uint32_t x_max,y_max,z_max; uint32_t x_max,y_max,z_max;
DFHack::t_designation designations[16][16]; DFHack::t_designation designations[16][16];
uint16_t tiles[16][16]; uint16_t tiles[16][16];
DF.getSize(x_max,y_max,z_max); DF.getSize(x_max,y_max,z_max);
// every tile found, will later be sorted by distance to source // every tile found, will later be sorted by distance to source
vector<DigTarget> candidates; vector<DigTarget> candidates;
if (verbose) if (verbose)
cout << "source is " << x_source << " " << y_source << " " << z_source << endl; cout << "source is " << x_source << " " << y_source << " " << z_source << endl;
// walk the map // 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(DF.isValidBlock(x,y,z)) if(DF.isValidBlock(x,y,z))
{ {
// read block designations and tiletype // read block designations and tiletype
DF.ReadDesignations(x,y,z, (uint32_t *) designations); DF.ReadDesignations(x,y,z, (uint32_t *) designations);
DF.ReadTileTypes(x,y,z, (uint16_t *) tiles); DF.ReadTileTypes(x,y,z, (uint16_t *) tiles);
// search all tiles for dig targets: // search all tiles for dig targets:
// visible, not yet marked for dig and matching tile type // visible, not yet marked for dig and matching tile type
for(uint32_t lx = 0; lx < 16; lx++) for(uint32_t lx = 0; lx < 16; lx++)
{ {
for(uint32_t ly = 0; ly < 16; ly++) for(uint32_t ly = 0; ly < 16; ly++)
{ {
if (designations[lx][ly].bits.hidden == 0 && if (designations[lx][ly].bits.hidden == 0 &&
designations[lx][ly].bits.dig == 0 && designations[lx][ly].bits.dig == 0 &&
vec_count(targets, DFHack::tileTypeTable[tiles[lx][ly]].c) > 0) vec_count(targets, DFHack::tileTypeTable[tiles[lx][ly]].c) > 0)
{ {
DigTarget dt( DigTarget dt(
x, y, z, x, y, z,
lx, ly, lx, ly,
x_source, y_source, z_source); x_source, y_source, z_source);
candidates.push_back(dt); candidates.push_back(dt);
if (verbose) if (verbose)
{ {
cout << "target found at " << dt.real_x << " " << dt.real_y << " " << dt.z; cout << "target found at " << dt.real_x << " " << dt.real_y << " " << dt.z;
cout << ", " << dt.source_distance << " tiles to source" << endl; cout << ", " << dt.source_distance << " tiles to source" << endl;
} }
} }
} // local y } // local y
} // local x } // local x
} }
} }
} }
} }
// if we found more tiles than was requested, sort them by distance to source, // if we found more tiles than was requested, sort them by distance to source,
// keep the front 'num' elements and drop the rest // keep the front 'num' elements and drop the rest
if (num != -1 && candidates.size() > (unsigned int)num) if (num != -1 && candidates.size() > (unsigned int)num)
{ {
sort(candidates.begin(), candidates.end()); sort(candidates.begin(), candidates.end());
candidates.resize(num); candidates.resize(num);
} }
num = candidates.size(); num = candidates.size();
if (verbose) if (verbose)
cout << "=== proceeding to designating targets ===" << endl; cout << "=== proceeding to designating targets ===" << endl;
// mark the tiles for actual digging // mark the tiles for actual digging
for (vector<DigTarget>::const_iterator i = candidates.begin(); i != candidates.end(); ++i) for (vector<DigTarget>::const_iterator i = candidates.begin(); i != candidates.end(); ++i)
{ {
if (verbose) if (verbose)
{ {
cout << "designating at " << (*i).real_x << " " << (*i).real_y << " " << (*i).z; cout << "designating at " << (*i).real_x << " " << (*i).real_y << " " << (*i).z;
cout << ", " << (*i).source_distance << " tiles to source" << endl; cout << ", " << (*i).source_distance << " tiles to source" << endl;
} }
// TODO this could probably be made much better, theres a big chance the trees are on the same grid // TODO this could probably be made much better, theres a big chance the trees are on the same grid
DF.ReadDesignations((*i).grid_x, (*i).grid_y, (*i).z, (uint32_t *) designations); DF.ReadDesignations((*i).grid_x, (*i).grid_y, (*i).z, (uint32_t *) designations);
designations[(*i).local_x][(*i).local_y].bits.dig = DFHack::designation_default; designations[(*i).local_x][(*i).local_y].bits.dig = DFHack::designation_default;
DF.WriteDesignations((*i).grid_x, (*i).grid_y, (*i).z, (uint32_t *) designations); DF.WriteDesignations((*i).grid_x, (*i).grid_y, (*i).z, (uint32_t *) designations);
// Mark as dirty so the jobs are properly picked up by the dwarves // Mark as dirty so the jobs are properly picked up by the dwarves
DF.WriteDirtyBit((*i).grid_x, (*i).grid_y, (*i).z, true); DF.WriteDirtyBit((*i).grid_x, (*i).grid_y, (*i).z, true);
} }
return num; return num;
} }
void test() void test()
{ {
////////////////////////// //////////////////////////
// DigTarget // DigTarget
{ {
DigTarget dt( DigTarget dt(
20, 35, 16, 20, 35, 16,
10, 12, 14); 10, 12, 14);
assert(dt.grid_x == 1); assert(dt.grid_x == 1);
assert(dt.grid_y == 2); assert(dt.grid_y == 2);
assert(dt.local_x == 4); assert(dt.local_x == 4);
assert(dt.local_y == 3); assert(dt.local_y == 3);
assert(dt.real_x == 20); assert(dt.real_x == 20);
assert(dt.real_y == 35); assert(dt.real_y == 35);
assert(dt.z == 16); assert(dt.z == 16);
assert(dt.source_distance == 35); assert(dt.source_distance == 35);
} }
{ {
DigTarget dt( DigTarget dt(
2, 4, 16, 2, 4, 16,
5, 10, 5, 10,
10, 12, 14); 10, 12, 14);
assert(dt.grid_x == 2); assert(dt.grid_x == 2);
assert(dt.grid_y == 4); assert(dt.grid_y == 4);
assert(dt.local_x == 5); assert(dt.local_x == 5);
assert(dt.local_y == 10); assert(dt.local_y == 10);
assert(dt.real_x == 37); assert(dt.real_x == 37);
assert(dt.real_y == 74); assert(dt.real_y == 74);
assert(dt.z == 16); assert(dt.z == 16);
assert(dt.source_distance == 91); assert(dt.source_distance == 91);
} }
////////////////////////// //////////////////////////
// string splitter // string splitter
{ {
vector<string> tokens; vector<string> tokens;
string src = "10,9,11"; string src = "10,9,11";
string delim = ","; string delim = ",";
string_split(tokens, src, delim); string_split(tokens, src, delim);
assert(tokens.size() == 3); assert(tokens.size() == 3);
assert(tokens[0] == "10"); assert(tokens[0] == "10");
assert(tokens[1] == "9"); assert(tokens[1] == "9");
assert(tokens[2] == "11"); assert(tokens[2] == "11");
} }
{ {
vector<string> tokens; vector<string> tokens;
string src = "10"; string src = "10";
string delim = ","; string delim = ",";
string_split(tokens, src, delim); string_split(tokens, src, delim);
assert(tokens.size() == 1); assert(tokens.size() == 1);
assert(tokens[0] == "10"); assert(tokens[0] == "10");
} }
{ {
vector<uint16_t> targets; vector<uint16_t> targets;
parse_int_csv(targets, "9,10"); parse_int_csv(targets, "9,10");
assert(targets[0] == 9); assert(targets[0] == 9);
assert(targets[1] == 10); assert(targets[1] == 10);
} }
} }
int main (int argc, char** argv) int main (int argc, char** argv)
{ {
//test(); //test();
// Command line options // Command line options
string s_targets; string s_targets;
string s_origin; string s_origin;
bool verbose; bool verbose;
int max; int max;
argstream as(argc,argv); argstream as(argc,argv);
as >>option('v',"verbose",verbose,"Active verbose mode") as >>option('v',"verbose",verbose,"Active verbose mode")
>>parameter('o',"origin",s_origin,"Close to where we should designate targets, format: x,y,z") >>parameter('o',"origin",s_origin,"Close to where we should designate targets, format: x,y,z")
>>parameter('t',"targets",s_targets,"What kinds of tile we should designate, format: type1,type2") >>parameter('t',"targets",s_targets,"What kinds of tile we should designate, format: type1,type2")
>>parameter('m',"max",max,"The maximum limit of designated targets") >>parameter('m',"max",max,"The maximum limit of designated targets")
>>help(); >>help();
// some commands need extra care // some commands need extra care
vector<uint16_t> targets; vector<uint16_t> targets;
parse_int_csv(targets, s_targets); parse_int_csv(targets, s_targets);
vector<uint16_t> origin; vector<uint16_t> origin;
parse_int_csv(origin, s_origin); parse_int_csv(origin, s_origin);
// sane check // sane check
if (!as.isOk()) if (!as.isOk())
{ {
cout << as.errorLog(); cout << as.errorLog();
} }
else if (targets.size() == 0 || origin.size() != 3) else if (targets.size() == 0 || origin.size() != 3)
{ {
cout << as.usage(); cout << as.usage();
} }
else else
{ {
DFHack::API DF("Memory.xml"); DFHack::API DF("Memory.xml");
if(DF.Attach()) if(DF.Attach())
{ {
if (DF.InitMap()) if (DF.InitMap())
{ {
int count = dig(DF, targets, 10, origin[0],origin[1],origin[2], verbose); int count = dig(DF, targets, 10, origin[0],origin[1],origin[2], verbose);
cout << count << " targets designated" << endl; cout << count << " targets designated" << endl;
if (!DF.Detach()) if (!DF.Detach())
{ {
cerr << "Unable to detach DF process" << endl; cerr << "Unable to detach DF process" << endl;
} }
} }
else else
{ {
cerr << "Unable to init map" << endl; cerr << "Unable to init map" << endl;
} }
} }
else else
{ {
cerr << "Unable to attach to DF process" << endl; cerr << "Unable to attach to DF process" << endl;
} }
} }
#ifndef LINUX_BUILD #ifndef LINUX_BUILD
cout << "Done. Press any key to continue" << endl; cout << "Done. Press any key to continue" << endl;
cin.ignore(); cin.ignore();
#endif #endif
return 0; return 0;
} }