From df4de4a3332832a69651474b9dae504d1d7187f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Mr=C3=A1zek?= Date: Tue, 16 Mar 2010 22:12:05 +0100 Subject: [PATCH] Detach in API destructor --- library/DFHackAPI.cpp | 12 +- tools/digger.cpp | 714 +++++++++++++++++++++--------------------- 2 files changed, 365 insertions(+), 361 deletions(-) diff --git a/library/DFHackAPI.cpp b/library/DFHackAPI.cpp index ff1b71a20..f2d31b21d 100644 --- a/library/DFHackAPI.cpp +++ b/library/DFHackAPI.cpp @@ -187,6 +187,8 @@ API::API (const string path_to_xml) API::~API() { + // FIXME: call all finishread* methods here + Detach(); delete d; } @@ -1056,7 +1058,7 @@ bool API::ReadSettlement(const int32_t index, t_settlement & settlement) // read pointer from vector at position uint32_t temp = * (uint32_t *) d->p_settlements->at (index); 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_local_xy_offset, 4 * sizeof(int16_t), (uint8_t *) &settlement.local_x1); return true; @@ -1069,7 +1071,7 @@ bool API::ReadCurrentSettlement(t_settlement & settlement) uint32_t temp = * (uint32_t *) d->p_current_settlement->at(0); 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_local_xy_offset, 4 * sizeof(int16_t), (uint8_t *) &settlement.local_x1); 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); // names d->readName(furball.name,temp + d->creature_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.squad_name, temp + d->creature_squad_name_offset); + d->readName(furball.artifact_name, temp + d->creature_artifact_name_offset); // custom profession 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() { + if(!d->p) + return false; if (!d->p->detach()) { return false; diff --git a/tools/digger.cpp b/tools/digger.cpp index 5f4017905..4020f0e00 100644 --- a/tools/digger.cpp +++ b/tools/digger.cpp @@ -1,357 +1,357 @@ -// digger.cpp - -// NOTE currently only works with trees - -// TODO add a sort of "sub-target" to dig() to make it able to designate stone as well - -#include -#include -#include -#include -#include -#include -#include -using namespace std; - -#include -#include -#include -#include - -// counts the occurances of a certain element in a vector -// used to determine of a given tile is a target -int vec_count(vector& vec, uint16_t t) -{ - int count = 0; - for (uint32_t i = 0; i < vec.size(); ++i) - { - if (vec[i] == t) - ++count; - } - return count; -} - -// splits a string on a certain char -// -// src is the string to split -// delim is the delimiter to split the string around -// tokens is filled with every occurance between delims -void string_split(vector& tokens, const std::string& src, const std::string& delim) -{ - std::string::size_type start = 0; - std::string::size_type end; - while (true) - { - end = src.find(delim, start); - tokens.push_back(src.substr(start, end - start)); - if (end == std::string::npos) // last token handled - break; - start = end + delim.size(); // skip next delim - } -} - -// this is used to parse the command line options -void parse_int_csv(vector& targets, const std::string& src) -{ - std::string::size_type start = 0; - std::string::size_type end; - while (true) - { - end = src.find(",", start); - targets.push_back(atoi(src.substr(start, end - start).c_str())); - if (end == std::string::npos) // last token handled - break; - start = end + 1; // skip next delim - } -} - -struct DigTarget -{ - DigTarget() : - source_distance(0), - grid_x(0), grid_y(0), - local_x(0), local_y(0), - real_x(0), real_y(0), z(0) - { - } - - DigTarget( - int realx, int realy, int _z, - int sourcex, int sourcey, int sourcez) : - real_x(realx), real_y(realy), z(_z) - { - grid_x = realx/16; - grid_y = realy/16; - - local_x = realx%16; - local_y = realy%16; - - source_distance = manhattan_distance( - real_x, real_y, z, - sourcex, sourcey, sourcez); - } - - DigTarget( - int gridx, int gridy, int _z, - int localx, int localy, - int sourcex, int sourcey, int sourcez) : - grid_x(gridx), grid_y(gridy), - local_x(localx), local_y(localy), - z(_z) - { - real_x = (grid_x*16)+local_x; - real_y = (grid_y*16)+local_y; - - source_distance = manhattan_distance( - real_x, real_y, z, - sourcex, sourcey, sourcez); - } - - int source_distance; // the distance to the source coords, used for sorting - - 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 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 - - bool operator<(const DigTarget& o) const { return source_distance < o.source_distance; } - -private: - // calculates the manhattan distance between two coords - 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); - } -}; - -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, - bool verbose = false) -{ - if (num == 0) - return 0; // max limit of 0, nothing to do - - uint32_t x_max,y_max,z_max; - DFHack::t_designation designations[16][16]; - uint16_t tiles[16][16]; - DF.getSize(x_max,y_max,z_max); - - // every tile found, will later be sorted by distance to source - vector candidates; - - if (verbose) - cout << "source is " << x_source << " " << y_source << " " << z_source << endl; - - // walk the map - for(uint32_t x = 0; x < x_max; x++) - { - for(uint32_t y = 0; y < y_max; y++) - { - for(uint32_t z = 0; z < z_max; z++) - { - 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); - - // search all tiles for dig targets: - // visible, not yet marked for dig and matching tile type - 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) - { - DigTarget dt( - x, y, z, - lx, ly, - x_source, y_source, z_source); - candidates.push_back(dt); - - if (verbose) - { - cout << "target found at " << dt.real_x << " " << dt.real_y << " " << dt.z; - cout << ", " << dt.source_distance << " tiles to source" << endl; - } - } - } // local y - } // local x - } - } - } - } - - // 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(); - - if (verbose) - cout << "=== proceeding to designating targets ===" << endl; - - // mark the tiles for actual digging - for (vector::const_iterator i = candidates.begin(); i != candidates.end(); ++i) - { - if (verbose) - { - cout << "designating at " << (*i).real_x << " " << (*i).real_y << " " << (*i).z; - 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 - 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; - 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 - DF.WriteDirtyBit((*i).grid_x, (*i).grid_y, (*i).z, true); - } - - return num; -} - -void test() -{ - ////////////////////////// - // DigTarget - { - DigTarget dt( - 20, 35, 16, - 10, 12, 14); - - assert(dt.grid_x == 1); - assert(dt.grid_y == 2); - - assert(dt.local_x == 4); - assert(dt.local_y == 3); - - assert(dt.real_x == 20); - assert(dt.real_y == 35); - - assert(dt.z == 16); - assert(dt.source_distance == 35); - } - { - DigTarget dt( - 2, 4, 16, - 5, 10, - 10, 12, 14); - - assert(dt.grid_x == 2); - assert(dt.grid_y == 4); - - assert(dt.local_x == 5); - assert(dt.local_y == 10); - - assert(dt.real_x == 37); - assert(dt.real_y == 74); - - assert(dt.z == 16); - assert(dt.source_distance == 91); - } - - ////////////////////////// - // string splitter - { - vector tokens; - string src = "10,9,11"; - string delim = ","; - string_split(tokens, src, delim); - - assert(tokens.size() == 3); - assert(tokens[0] == "10"); - assert(tokens[1] == "9"); - assert(tokens[2] == "11"); - } - { - vector tokens; - string src = "10"; - string delim = ","; - string_split(tokens, src, delim); - - assert(tokens.size() == 1); - assert(tokens[0] == "10"); - } - { - vector targets; - parse_int_csv(targets, "9,10"); - assert(targets[0] == 9); - assert(targets[1] == 10); - } -} - -int main (int argc, char** argv) -{ - //test(); - - // Command line options - string s_targets; - string s_origin; - bool verbose; - int max; - argstream as(argc,argv); - - 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('t',"targets",s_targets,"What kinds of tile we should designate, format: type1,type2") - >>parameter('m',"max",max,"The maximum limit of designated targets") - >>help(); - - // some commands need extra care - vector targets; - parse_int_csv(targets, s_targets); - - vector origin; - parse_int_csv(origin, s_origin); - - // sane check - if (!as.isOk()) - { - cout << as.errorLog(); - } - else if (targets.size() == 0 || origin.size() != 3) - { - cout << as.usage(); - } - else - { - DFHack::API DF("Memory.xml"); - if(DF.Attach()) - { - if (DF.InitMap()) - { - int count = dig(DF, targets, 10, origin[0],origin[1],origin[2], verbose); - cout << count << " targets designated" << endl; - - if (!DF.Detach()) - { - cerr << "Unable to detach DF process" << endl; - } - } - else - { - cerr << "Unable to init map" << endl; - } - } - else - { - cerr << "Unable to attach to DF process" << endl; - } - } -#ifndef LINUX_BUILD - cout << "Done. Press any key to continue" << endl; - cin.ignore(); -#endif - return 0; -} +// digger.cpp + +// NOTE currently only works with trees + +// TODO add a sort of "sub-target" to dig() to make it able to designate stone as well + +#include +#include +#include +#include +#include +#include +#include +using namespace std; + +#include +#include +#include +#include + +// counts the occurances of a certain element in a vector +// used to determine of a given tile is a target +int vec_count(vector& vec, uint16_t t) +{ + int count = 0; + for (uint32_t i = 0; i < vec.size(); ++i) + { + if (vec[i] == t) + ++count; + } + return count; +} + +// splits a string on a certain char +// +// src is the string to split +// delim is the delimiter to split the string around +// tokens is filled with every occurance between delims +void string_split(vector& tokens, const std::string& src, const std::string& delim) +{ + std::string::size_type start = 0; + std::string::size_type end; + while (true) + { + end = src.find(delim, start); + tokens.push_back(src.substr(start, end - start)); + if (end == std::string::npos) // last token handled + break; + start = end + delim.size(); // skip next delim + } +} + +// this is used to parse the command line options +void parse_int_csv(vector& targets, const std::string& src) +{ + std::string::size_type start = 0; + std::string::size_type end; + while (true) + { + end = src.find(",", start); + targets.push_back(atoi(src.substr(start, end - start).c_str())); + if (end == std::string::npos) // last token handled + break; + start = end + 1; // skip next delim + } +} + +struct DigTarget +{ + DigTarget() : + source_distance(0), + grid_x(0), grid_y(0), + local_x(0), local_y(0), + real_x(0), real_y(0), z(0) + { + } + + DigTarget( + int realx, int realy, int _z, + int sourcex, int sourcey, int sourcez) : + real_x(realx), real_y(realy), z(_z) + { + grid_x = realx/16; + grid_y = realy/16; + + local_x = realx%16; + local_y = realy%16; + + source_distance = manhattan_distance( + real_x, real_y, z, + sourcex, sourcey, sourcez); + } + + DigTarget( + int gridx, int gridy, int _z, + int localx, int localy, + int sourcex, int sourcey, int sourcez) : + grid_x(gridx), grid_y(gridy), + local_x(localx), local_y(localy), + z(_z) + { + real_x = (grid_x*16)+local_x; + real_y = (grid_y*16)+local_y; + + source_distance = manhattan_distance( + real_x, real_y, z, + sourcex, sourcey, sourcez); + } + + int source_distance; // the distance to the source coords, used for sorting + + 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 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 + + bool operator<(const DigTarget& o) const { return source_distance < o.source_distance; } + +private: + // calculates the manhattan distance between two coords + 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); + } +}; + +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, + bool verbose = false) +{ + if (num == 0) + return 0; // max limit of 0, nothing to do + + uint32_t x_max,y_max,z_max; + DFHack::t_designation designations[16][16]; + uint16_t tiles[16][16]; + DF.getSize(x_max,y_max,z_max); + + // every tile found, will later be sorted by distance to source + vector candidates; + + if (verbose) + cout << "source is " << x_source << " " << y_source << " " << z_source << endl; + + // walk the map + for(uint32_t x = 0; x < x_max; x++) + { + for(uint32_t y = 0; y < y_max; y++) + { + for(uint32_t z = 0; z < z_max; z++) + { + 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); + + // search all tiles for dig targets: + // visible, not yet marked for dig and matching tile type + 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) + { + DigTarget dt( + x, y, z, + lx, ly, + x_source, y_source, z_source); + candidates.push_back(dt); + + if (verbose) + { + cout << "target found at " << dt.real_x << " " << dt.real_y << " " << dt.z; + cout << ", " << dt.source_distance << " tiles to source" << endl; + } + } + } // local y + } // local x + } + } + } + } + + // 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(); + + if (verbose) + cout << "=== proceeding to designating targets ===" << endl; + + // mark the tiles for actual digging + for (vector::const_iterator i = candidates.begin(); i != candidates.end(); ++i) + { + if (verbose) + { + cout << "designating at " << (*i).real_x << " " << (*i).real_y << " " << (*i).z; + 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 + 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; + 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 + DF.WriteDirtyBit((*i).grid_x, (*i).grid_y, (*i).z, true); + } + + return num; +} + +void test() +{ + ////////////////////////// + // DigTarget + { + DigTarget dt( + 20, 35, 16, + 10, 12, 14); + + assert(dt.grid_x == 1); + assert(dt.grid_y == 2); + + assert(dt.local_x == 4); + assert(dt.local_y == 3); + + assert(dt.real_x == 20); + assert(dt.real_y == 35); + + assert(dt.z == 16); + assert(dt.source_distance == 35); + } + { + DigTarget dt( + 2, 4, 16, + 5, 10, + 10, 12, 14); + + assert(dt.grid_x == 2); + assert(dt.grid_y == 4); + + assert(dt.local_x == 5); + assert(dt.local_y == 10); + + assert(dt.real_x == 37); + assert(dt.real_y == 74); + + assert(dt.z == 16); + assert(dt.source_distance == 91); + } + + ////////////////////////// + // string splitter + { + vector tokens; + string src = "10,9,11"; + string delim = ","; + string_split(tokens, src, delim); + + assert(tokens.size() == 3); + assert(tokens[0] == "10"); + assert(tokens[1] == "9"); + assert(tokens[2] == "11"); + } + { + vector tokens; + string src = "10"; + string delim = ","; + string_split(tokens, src, delim); + + assert(tokens.size() == 1); + assert(tokens[0] == "10"); + } + { + vector targets; + parse_int_csv(targets, "9,10"); + assert(targets[0] == 9); + assert(targets[1] == 10); + } +} + +int main (int argc, char** argv) +{ + //test(); + + // Command line options + string s_targets; + string s_origin; + bool verbose; + int max; + argstream as(argc,argv); + + 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('t',"targets",s_targets,"What kinds of tile we should designate, format: type1,type2") + >>parameter('m',"max",max,"The maximum limit of designated targets") + >>help(); + + // some commands need extra care + vector targets; + parse_int_csv(targets, s_targets); + + vector origin; + parse_int_csv(origin, s_origin); + + // sane check + if (!as.isOk()) + { + cout << as.errorLog(); + } + else if (targets.size() == 0 || origin.size() != 3) + { + cout << as.usage(); + } + else + { + DFHack::API DF("Memory.xml"); + if(DF.Attach()) + { + if (DF.InitMap()) + { + int count = dig(DF, targets, 10, origin[0],origin[1],origin[2], verbose); + cout << count << " targets designated" << endl; + + if (!DF.Detach()) + { + cerr << "Unable to detach DF process" << endl; + } + } + else + { + cerr << "Unable to init map" << endl; + } + } + else + { + cerr << "Unable to attach to DF process" << endl; + } + } +#ifndef LINUX_BUILD + cout << "Done. Press any key to continue" << endl; + cin.ignore(); +#endif + return 0; +}