Merge commit 'origin' into bartavelle

develop
simon 2010-04-26 10:21:04 +02:00
commit 91c8adbaf1
30 changed files with 1299 additions and 241 deletions

@ -66,6 +66,10 @@ API::~API()
bool API::Attach() bool API::Attach()
{ {
if(d->p != NULL)
{
return d->p->suspend();
}
// detach all processes, destroy manager // detach all processes, destroy manager
if (d->pm == 0) if (d->pm == 0)
{ {

@ -227,7 +227,7 @@ void memory_info::setProfession (const string & key, const string & value)
uint32_t keyInt = strtol(key.c_str(), NULL, 10); uint32_t keyInt = strtol(key.c_str(), NULL, 10);
if(d->professions.size() <= keyInt) if(d->professions.size() <= keyInt)
{ {
d->professions.resize(keyInt+1); d->professions.resize(keyInt+1,"");
} }
d->professions[keyInt] = value; d->professions[keyInt] = value;
} }

@ -78,14 +78,22 @@ namespace DFHack
class DFHACK_EXPORT MissingMemoryDefinition : public std::exception class DFHACK_EXPORT MissingMemoryDefinition : public std::exception
{ {
public: public:
MissingMemoryDefinition(const char* _type, const char* _key) : type(_type), key(_key) {} MissingMemoryDefinition(const char* _type, const char* _key) : type(_type), key(_key)
{
std::stringstream s;
s << "memory definition missing: type " << type << " key " << key;
full = s.str();
}
// Used by functios using integer keys, such as getTrait // Used by functios using integer keys, such as getTrait
MissingMemoryDefinition(const char* _type, uint32_t _key) : type(_type) MissingMemoryDefinition(const char* _type, uint32_t _key) : type(_type)
{ {
// FIXME fancy hex printer goes here std::stringstream s1;
s1 << _key;
key = s1.str();
std::stringstream s; std::stringstream s;
s << _key; s << "memory definition missing: type " << type << " key " << key;
key = s.str(); full = s.str();
} }
virtual ~MissingMemoryDefinition() throw(){}; virtual ~MissingMemoryDefinition() throw(){};
@ -102,14 +110,13 @@ namespace DFHack
// trait // trait
// traitname // traitname
// labor // labor
std::string full;
const std::string type; const std::string type;
std::string key; std::string key;
virtual const char* what() const throw() virtual const char* what() const throw()
{ {
std::stringstream s; return full.c_str();
s << "memory definition missing: type " << type << " key " << key;
return s.str().c_str();
} }
}; };
@ -117,9 +124,16 @@ namespace DFHack
class DFHACK_EXPORT MemoryXmlParse : public std::exception class DFHACK_EXPORT MemoryXmlParse : public std::exception
{ {
public: public:
MemoryXmlParse(const char* _desc, int _id, int _row, int _col) : MemoryXmlParse(const char* _desc, int _id, int _row, int _col)
desc(_desc), id(_id), row(_row), col(_col) {} :desc(_desc), id(_id), row(_row), col(_col)
{
std::stringstream s;
s << "error " << id << ": " << desc << ", at row " << row << " col " << col;
full = s.str();
}
std::string full;
const std::string desc; const std::string desc;
const int id; const int id;
const int row; const int row;
@ -129,26 +143,27 @@ namespace DFHack
virtual const char* what() const throw() virtual const char* what() const throw()
{ {
std::stringstream s; return full.c_str();
s << "error " << id << ": " << desc << ", at row " << row << " col " << col;
return s.str().c_str();
} }
}; };
class DFHACK_EXPORT MemoryXmlBadAttribute : public std::exception class DFHACK_EXPORT MemoryXmlBadAttribute : public std::exception
{ {
public: public:
MemoryXmlBadAttribute(const char* _attr) : attr(_attr) {} MemoryXmlBadAttribute(const char* _attr) : attr(_attr)
{
std::stringstream s;
s << "attribute is either missing or invalid: " << attr;
full = s.str();
}
std::string full;
std::string attr; std::string attr;
virtual ~MemoryXmlBadAttribute() throw(){}; virtual ~MemoryXmlBadAttribute() throw(){};
virtual const char* what() const throw() virtual const char* what() const throw()
{ {
std::stringstream s; return full.c_str();
s << "attribute is either missing or invalid: " << attr;
return s.str().c_str();
} }
}; };
@ -168,46 +183,58 @@ namespace DFHack
class DFHACK_EXPORT MemoryXmlNoDFExtractor : public std::exception class DFHACK_EXPORT MemoryXmlNoDFExtractor : public std::exception
{ {
public: public:
MemoryXmlNoDFExtractor(const char* _name) : name(_name) {} MemoryXmlNoDFExtractor(const char* _name) : name(_name)
{
std::stringstream s;
s << "DFExtractor != " << name;
full = s.str();
}
virtual ~MemoryXmlNoDFExtractor() throw(){}; virtual ~MemoryXmlNoDFExtractor() throw(){};
std::string name; std::string name;
std::string full;
virtual const char* what() const throw() virtual const char* what() const throw()
{ {
std::stringstream s; return full.c_str();
s << "DFExtractor != " << name;
return s.str().c_str();
} }
}; };
class DFHACK_EXPORT MemoryXmlUnderspecifiedEntry : public std::exception class DFHACK_EXPORT MemoryXmlUnderspecifiedEntry : public std::exception
{ {
public: public:
MemoryXmlUnderspecifiedEntry(const char * _where) : where(_where) {} MemoryXmlUnderspecifiedEntry(const char * _where) : where(_where)
{
std::stringstream s;
s << "underspecified MemInfo entry, each entry needs to set both the name attribute and have a value. parent: " << where;
full = s.str();
}
virtual ~MemoryXmlUnderspecifiedEntry() throw(){}; virtual ~MemoryXmlUnderspecifiedEntry() throw(){};
std::string where; std::string where;
std::string full;
virtual const char* what() const throw() virtual const char* what() const throw()
{ {
std::stringstream s; return full.c_str();
s << "underspecified MemInfo entry, each entry needs to set both the name attribute and have a value. parent: " << where;
return s.str().c_str();
} }
}; };
class DFHACK_EXPORT MemoryXmlUnknownType : public std::exception class DFHACK_EXPORT MemoryXmlUnknownType : public std::exception
{ {
public: public:
MemoryXmlUnknownType(const char* _type) : type(_type) {} MemoryXmlUnknownType(const char* _type) : type(_type)
{
std::stringstream s;
s << "unknown MemInfo type: " << type;
full = s.str();
}
virtual ~MemoryXmlUnknownType() throw(){}; virtual ~MemoryXmlUnknownType() throw(){};
std::string type; std::string type;
std::string full;
virtual const char* what() const throw() virtual const char* what() const throw()
{ {
std::stringstream s; return full.c_str();
s << "unknown MemInfo type: " << type;
return s.str().c_str();
} }
}; };
@ -224,16 +251,20 @@ namespace DFHack
class DFHACK_EXPORT SHMLockingError : public std::exception class DFHACK_EXPORT SHMLockingError : public std::exception
{ {
public: public:
SHMLockingError(const char* _type) : type(_type) {} SHMLockingError(const char* _type) : type(_type)
{
std::stringstream s;
s << "SHM locking error: " << type;
full = s.str();
}
virtual ~SHMLockingError() throw(){}; virtual ~SHMLockingError() throw(){};
std::string type; std::string type;
std::string full;
virtual const char* what() const throw() virtual const char* what() const throw()
{ {
std::stringstream s; return full.c_str();
s << "SHM locking error: " << type;
return s.str().c_str();
} }
}; };
class DFHACK_EXPORT MemoryAccessDenied : public std::exception class DFHACK_EXPORT MemoryAccessDenied : public std::exception
@ -241,9 +272,6 @@ namespace DFHack
public: public:
MemoryAccessDenied() {} MemoryAccessDenied() {}
virtual ~MemoryAccessDenied() throw(){}; virtual ~MemoryAccessDenied() throw(){};
std::string type;
virtual const char* what() const throw() virtual const char* what() const throw()
{ {
return "SHM ACCESS DENIED"; return "SHM ACCESS DENIED";
@ -254,9 +282,6 @@ namespace DFHack
public: public:
SHMVersionMismatch() {} SHMVersionMismatch() {}
virtual ~SHMVersionMismatch() throw(){}; virtual ~SHMVersionMismatch() throw(){};
std::string type;
virtual const char* what() const throw() virtual const char* what() const throw()
{ {
return "SHM VERSION MISMATCH"; return "SHM VERSION MISMATCH";
@ -267,9 +292,6 @@ namespace DFHack
public: public:
SHMAttachFailure() {} SHMAttachFailure() {}
virtual ~SHMAttachFailure() throw(){}; virtual ~SHMAttachFailure() throw(){};
std::string type;
virtual const char* what() const throw() virtual const char* what() const throw()
{ {
return "SHM ATTACH FAILURE"; return "SHM ATTACH FAILURE";

@ -12,6 +12,36 @@ namespace DFHack
T Y P E S T Y P E S
***************************************************************************/ ***************************************************************************/
enum e_feature
{
feature_Adamantine_Tube,
feature_Underworld,
// add stuff here, don't reorder or delete
feature_Other = 10000,
};
union planecoord
{
uint32_t xy;
struct
{
uint16_t x;
uint16_t y;
} dim;
bool operator<(const planecoord &other) const
{
if(other.xy < xy) return true;
return false;
}
};
struct t_feature
{
e_feature type;
int16_t main_material;
int32_t sub_material;
bool discovered; // placeholder.
uint32_t origin;
};
struct t_vein struct t_vein
{ {
uint32_t vtable; uint32_t vtable;
@ -210,6 +240,8 @@ namespace DFHack
biome_indices40d biome_indices; biome_indices40d biome_indices;
uint32_t origin; // the address where it came from uint32_t origin; // the address where it came from
t_blockflags blockflags; t_blockflags blockflags;
int16_t global_feature;
int16_t local_feature;
} mapblock40d; } mapblock40d;
/*************************************************************************** /***************************************************************************
@ -259,7 +291,14 @@ namespace DFHack
} }
*/ */
bool ReadGeology( std::vector < std::vector <uint16_t> >& assign ); bool ReadGeology( std::vector < std::vector <uint16_t> >& assign );
vector <t_feature> global_features;
// map between feature address and the read object
map <uint32_t, t_feature> local_feature_store;
// map between mangled coords and pointer to feature
bool ReadGlobalFeatures( std::vector <t_feature> & features);
bool ReadLocalFeatures( std::map <planecoord, std::vector<t_feature *> > & local_features );
/* /*
* BLOCK DATA * BLOCK DATA
*/ */

@ -54,6 +54,10 @@ struct Maps::Private
Process * owner; Process * owner;
bool Inited; bool Inited;
bool Started; bool Started;
// map between feature address and the read object
map <uint32_t, t_feature> local_feature_store;
vector<uint16_t> v_geology[eBiomeCount]; vector<uint16_t> v_geology[eBiomeCount];
}; };
@ -77,8 +81,28 @@ Maps::Maps(APIPrivate* _d)
off.occupancy_offset = mem->getOffset("map_data_occupancy"); off.occupancy_offset = mem->getOffset("map_data_occupancy");
off.biome_stuffs = mem->getOffset ("map_data_biome_stuffs"); off.biome_stuffs = mem->getOffset ("map_data_biome_stuffs");
off.veinvector = mem->getOffset ("map_data_vein_vector"); off.veinvector = mem->getOffset ("map_data_vein_vector");
off.local_feature_offset = mem->getOffset ("map_data_feature_local");
off.global_feature_offset = mem->getOffset ("map_data_feature_global");
off.temperature1_offset = mem->getOffset ("map_data_temperature1_offset"); off.temperature1_offset = mem->getOffset ("map_data_temperature1_offset");
off.temperature2_offset = mem->getOffset ("map_data_temperature2_offset"); off.temperature2_offset = mem->getOffset ("map_data_temperature2_offset");
off.region_x_offset = mem->getAddress ("region_x");
off.region_y_offset = mem->getAddress ("region_y");
off.region_z_offset = mem->getAddress ("region_z");
off.world_regions = mem->getAddress ("ptr2_region_array");
off.region_size = mem->getHexValue ("region_size");
off.region_geo_index_offset = mem->getOffset ("region_geo_index_off");
off.geolayer_geoblock_offset = mem->getOffset ("geolayer_geoblock_offset");
off.world_geoblocks_vector = mem->getAddress ("geoblock_vector");
off.type_inside_geolayer = mem->getOffset ("type_inside_geolayer");
off.world_size_x = mem->getAddress ("world_size_x");
off.world_size_y = mem->getAddress ("world_size_y");
// these can fail and will be found when looking at the actual veins later // these can fail and will be found when looking at the actual veins later
// basically a cache // basically a cache
@ -138,6 +162,11 @@ bool Maps::Start()
//return false; //return false;
} }
// read position of the region inside DF world
p->readDWord (off.region_x_offset, d->regionX);
p->readDWord (off.region_y_offset, d->regionY);
p->readDWord (off.region_z_offset, d->regionZ);
// alloc array for pointers to all blocks // alloc array for pointers to all blocks
d->block = new uint32_t[mx*my*mz]; d->block = new uint32_t[mx*my*mz];
uint32_t *temp_x = new uint32_t[mx]; uint32_t *temp_x = new uint32_t[mx];
@ -157,6 +186,7 @@ bool Maps::Start()
} }
delete [] temp_x; delete [] temp_x;
delete [] temp_y; delete [] temp_y;
d->Started = true;
return true; return true;
} }
@ -168,8 +198,10 @@ void Maps::getSize (uint32_t& x, uint32_t& y, uint32_t& z)
z = d->z_block_count; z = d->z_block_count;
} }
// invalidates local and global features!
bool Maps::Finish() bool Maps::Finish()
{ {
d->local_feature_store.clear();
if (d->block != NULL) if (d->block != NULL)
{ {
delete [] d->block; delete [] d->block;
@ -219,6 +251,8 @@ bool Maps::ReadBlock40d(uint32_t x, uint32_t y, uint32_t z, mapblock40d * buffer
p->read (addr + d->offsets.designation_offset, sizeof (buffer->designation), (uint8_t *) buffer->designation); p->read (addr + d->offsets.designation_offset, sizeof (buffer->designation), (uint8_t *) buffer->designation);
p->read (addr + d->offsets.occupancy_offset, sizeof (buffer->occupancy), (uint8_t *) buffer->occupancy); p->read (addr + d->offsets.occupancy_offset, sizeof (buffer->occupancy), (uint8_t *) buffer->occupancy);
p->read (addr + d->offsets.biome_stuffs, sizeof (biome_indices40d), (uint8_t *) buffer->biome_indices); p->read (addr + d->offsets.biome_stuffs, sizeof (biome_indices40d), (uint8_t *) buffer->biome_indices);
p->readWord(addr + d->offsets.global_feature_offset, (uint16_t&) buffer->global_feature);
p->readWord(addr + d->offsets.local_feature_offset, (uint16_t&)buffer->local_feature);
buffer->origin = addr; buffer->origin = addr;
uint32_t addr_of_struct = p->readDWord(addr); uint32_t addr_of_struct = p->readDWord(addr);
buffer->blockflags.whole = p->readDWord(addr_of_struct); buffer->blockflags.whole = p->readDWord(addr_of_struct);
@ -557,45 +591,26 @@ bool Maps::ReadGeology (vector < vector <uint16_t> >& assign)
memory_info * minfo = d->d->offset_descriptor; memory_info * minfo = d->d->offset_descriptor;
Process *p = d->owner; Process *p = d->owner;
// get needed addresses and offsets. Now this is what I call crazy. // get needed addresses and offsets. Now this is what I call crazy.
int region_x_offset = minfo->getAddress ("region_x");
int region_y_offset = minfo->getAddress ("region_y");
int region_z_offset = minfo->getAddress ("region_z");
int world_regions = minfo->getAddress ("ptr2_region_array");
int region_size = minfo->getHexValue ("region_size");
int region_geo_index_offset = minfo->getOffset ("region_geo_index_off");
int world_geoblocks_vector = minfo->getAddress ("geoblock_vector");
int world_size_x = minfo->getAddress ("world_size_x");
int world_size_y = minfo->getAddress ("world_size_y");
int geolayer_geoblock_offset = minfo->getOffset ("geolayer_geoblock_offset");
int type_inside_geolayer = minfo->getOffset ("type_inside_geolayer");
uint32_t regionX, regionY, regionZ;
uint16_t worldSizeX, worldSizeY; uint16_t worldSizeX, worldSizeY;
Server::Maps::maps_offsets &off = d->offsets;
// read position of the region inside DF world
p->readDWord (region_x_offset, regionX);
p->readDWord (region_y_offset, regionY);
p->readDWord (region_z_offset, regionZ);
// get world size // get world size
p->readWord (world_size_x, worldSizeX); p->readWord (off.world_size_x, worldSizeX);
p->readWord (world_size_y, worldSizeY); p->readWord (off.world_size_y, worldSizeY);
// get pointer to first part of 2d array of regions // get pointer to first part of 2d array of regions
uint32_t regions = p->readDWord (world_regions); uint32_t regions = p->readDWord (off.world_regions);
// read the geoblock vector // read the geoblock vector
DfVector <uint32_t> geoblocks (d->d->p, world_geoblocks_vector); DfVector <uint32_t> geoblocks (d->d->p, off.world_geoblocks_vector);
// iterate over 8 surrounding regions + local region // iterate over 8 surrounding regions + local region
for (int i = eNorthWest; i < eBiomeCount; i++) for (int i = eNorthWest; i < eBiomeCount; i++)
{ {
// check against worldmap boundaries, fix if needed // check against worldmap boundaries, fix if needed
int bioRX = regionX / 16 + (i % 3) - 1; int bioRX = d->regionX / 16 + (i % 3) - 1;
if (bioRX < 0) bioRX = 0; if (bioRX < 0) bioRX = 0;
if (bioRX >= worldSizeX) bioRX = worldSizeX - 1; if (bioRX >= worldSizeX) bioRX = worldSizeX - 1;
int bioRY = regionY / 16 + (i / 3) - 1; int bioRY = d->regionY / 16 + (i / 3) - 1;
if (bioRY < 0) bioRY = 0; if (bioRY < 0) bioRY = 0;
if (bioRY >= worldSizeY) bioRY = worldSizeY - 1; if (bioRY >= worldSizeY) bioRY = worldSizeY - 1;
@ -607,7 +622,7 @@ bool Maps::ReadGeology (vector < vector <uint16_t> >& assign)
// get index into geoblock vector // get index into geoblock vector
uint16_t geoindex; uint16_t geoindex;
p->readWord (geoX + bioRY*region_size + region_geo_index_offset, geoindex); p->readWord (geoX + bioRY*off.region_size + off.region_geo_index_offset, geoindex);
/// geology blocks are assigned to regions from a vector /// geology blocks are assigned to regions from a vector
// get the geoblock from the geoblock vector using the geoindex // get the geoblock from the geoblock vector using the geoindex
@ -616,7 +631,7 @@ bool Maps::ReadGeology (vector < vector <uint16_t> >& assign)
/// geology blocks have a vector of layer descriptors /// geology blocks have a vector of layer descriptors
// get the vector with pointer to layers // get the vector with pointer to layers
DfVector <uint32_t> geolayers (p, geoblock_off + geolayer_geoblock_offset); // let's hope DfVector <uint32_t> geolayers (p, geoblock_off + off.geolayer_geoblock_offset); // let's hope
// make sure we don't load crap // make sure we don't load crap
assert (geolayers.size() > 0 && geolayers.size() <= 16); assert (geolayers.size() > 0 && geolayers.size() <= 16);
@ -628,7 +643,7 @@ bool Maps::ReadGeology (vector < vector <uint16_t> >& assign)
// read pointer to a layer // read pointer to a layer
uint32_t geol_offset = geolayers[j]; uint32_t geol_offset = geolayers[j];
// read word at pointer + 2, store in our geology vectors // read word at pointer + 2, store in our geology vectors
d->v_geology[i].push_back (p->readWord (geol_offset + type_inside_geolayer)); d->v_geology[i].push_back (p->readWord (geol_offset + off.type_inside_geolayer));
} }
} }
assign.clear(); assign.clear();
@ -639,3 +654,138 @@ bool Maps::ReadGeology (vector < vector <uint16_t> >& assign)
} }
return true; return true;
} }
bool Maps::ReadLocalFeatures( std::map <planecoord, std::vector<t_feature *> > & local_features )
{
// can't be used without a map!
if(!d->block)
return false;
Process * p = d->owner;
memory_info * mem = p->getDescriptor();
// deref pointer to the humongo-structure
uint32_t base = p->readDWord(mem->getAddress("local_feature_start_ptr"));
uint32_t sizeof_vec = mem->getHexValue("sizeof_vector");
const uint32_t sizeof_elem = 16;
const uint32_t offset_elem = 4;
const uint32_t main_mat_offset = 0x30;
const uint32_t sub_mat_offset = 0x34;
local_features.clear();
for(uint32_t blockX = 0; blockX < d->x_block_count; blockX ++)
for(uint32_t blockY = 0; blockY < d->x_block_count; blockY ++)
{
//uint64_t block48_x = blockX / 3 + d->regionX;
//uint16_t region_x_plus8 = ( block48_x + 8 ) / 16;
// region X coord offset by 8 big blocks (48x48 tiles)
uint16_t region_x_plus8 = ( (blockX / 3 ) + d->regionX /*+ 8*/ ) / 16;
//((BYTE4(region_x_local) & 0xF) + (_DWORD)region_x_local) >> 4;
//int16_t region_x_local = (blockX / 3) + d->regionX;
//int16_t region_x_plus8 = ((region_x_local & 0xF) + region_x_local) >> 4;
// plain region Y coord
uint64_t region_y_local = ( (blockY / 3) + d->regionY ) / 16;
// this is just a few pointers to arrays of 16B (4 DWORD) structs
uint32_t array_elem = p->readDWord(base + (region_x_plus8 / 16) * 4);
// 16B structs, second DWORD of the struct is a pointer
uint32_t wtf = p->readDWord(array_elem + ( sizeof_elem * (region_y_local/16)) + offset_elem);
if(wtf)
{
// wtf + sizeof(vector<ptr>) * crap;
uint32_t feat_vector = wtf + sizeof_vec * (16 * (region_x_plus8 % 16) + (region_y_local % 16));
DfVector<uint32_t> p_features(p, feat_vector);
uint32_t size = p_features.size();
planecoord pc;
pc.dim.x = blockX;
pc.dim.y = blockY;
std::vector<t_feature *> tempvec;
for(uint32_t i = 0; i < size; i++)
{
uint32_t cur_ptr = p_features[i];
map <uint32_t, t_feature>::iterator it;
it = d->local_feature_store.find(cur_ptr);
// do we already have the feature?
if(it != d->local_feature_store.end())
{
// push pointer to existing feature
tempvec.push_back(&((*it).second));
}
// no?
else
{
// create, add to store
t_feature tftemp;
tftemp.discovered = false; //= p->readDWord(cur_ptr + 4);
tftemp.origin = cur_ptr;
string name = p->readClassName(p->readDWord( cur_ptr ));
if(name == "feature_init_deep_special_tubest")
{
tftemp.main_material = p->readWord( cur_ptr + main_mat_offset );
tftemp.sub_material = p->readDWord( cur_ptr + sub_mat_offset );
tftemp.type = feature_Adamantine_Tube;
}
else
{
tftemp.main_material = -1;
tftemp.sub_material = -1;
tftemp.type = feature_Other;
}
d->local_feature_store[cur_ptr] = tftemp;
// push pointer
tempvec.push_back(&(d->local_feature_store[cur_ptr]));
}
}
local_features[pc] = tempvec;
}
}
return true;
}
bool Maps::ReadGlobalFeatures( std::vector <t_feature> & features)
{
// can't be used without a map!
if(!d->block)
return false;
Process * p = d->owner;
memory_info * mem = p->getDescriptor();
uint32_t global_feature_vector = mem->getAddress("global_feature_vector");
uint32_t global_feature_funcptr = mem->getOffset("global_feature_funcptr_");
const uint32_t main_mat_offset = 0x34;
const uint32_t sub_mat_offset = 0x38;
DfVector<uint32_t> p_features (p,global_feature_vector);
features.clear();
uint32_t size = p_features.size();
features.reserve(size);
for(uint32_t i = 0; i < size; i++)
{
t_feature temp;
uint32_t feat_ptr = p->readDWord(p_features[i] + global_feature_funcptr );
temp.origin = feat_ptr;
//temp.discovered = p->readDWord( feat_ptr + 4 ); // maybe, placeholder
temp.discovered = false;
// FIXME: use the memory_info cache mechanisms
string name = p->readClassName(p->readDWord( feat_ptr));
if(name == "feature_init_underworld_from_layerst")
{
temp.main_material = p->readWord( feat_ptr + main_mat_offset );
temp.sub_material = p->readDWord( feat_ptr + sub_mat_offset );
temp.type = feature_Underworld;
}
else
{
temp.main_material = -1;
temp.sub_material = -1;
temp.type = feature_Other;
}
features.push_back(temp);
}
return true;
}

@ -29,6 +29,7 @@ distribution.
#include <string> #include <string>
#include "DFTypes.h" #include "DFTypes.h"
#include "DFHackAPI.h" #include "DFHackAPI.h"
#include "DF_Imports.cpp"
#include "DF_MemInfo.cpp" #include "DF_MemInfo.cpp"
#include "DF_Position.cpp" #include "DF_Position.cpp"
#include "DF_Material.cpp" #include "DF_Material.cpp"
@ -54,6 +55,11 @@ struct DF_API
PyObject* construction; PyObject* construction;
PyObject* vegetation; PyObject* vegetation;
PyObject* gui; PyObject* gui;
PyObject* map_type;
PyObject* vegetation_type;
PyObject* gui_type;
DFHack::API* api_Ptr; DFHack::API* api_Ptr;
}; };
@ -87,6 +93,10 @@ static int DF_API_init(DF_API* self, PyObject* args, PyObject* kwds)
self->vegetation = NULL; self->vegetation = NULL;
self->gui = NULL; self->gui = NULL;
self->map_type = (PyObject*)&DF_Map_type;
self->vegetation_type = (PyObject*)&DF_Vegetation_type;
self->gui_type = (PyObject*)&DF_GUI_type;
if(!PyArg_ParseTuple(args, "s", &memFileString)) if(!PyArg_ParseTuple(args, "s", &memFileString))
return -1; return -1;
@ -310,7 +320,7 @@ static PyObject* DF_API_getMap(DF_API* self, void* closure)
{ {
if(self->api_Ptr != NULL) if(self->api_Ptr != NULL)
{ {
self->map = PyObject_Call((PyObject*)&DF_Map_type, NULL, NULL); self->map = PyObject_CallObject(self->map_type, NULL);
if(self->map != NULL) if(self->map != NULL)
{ {
@ -397,7 +407,7 @@ static PyObject* DF_API_getVegetation(DF_API* self, void* closure)
{ {
if(self->api_Ptr != NULL) if(self->api_Ptr != NULL)
{ {
self->vegetation = PyObject_Call((PyObject*)&DF_Vegetation_type, NULL, NULL); self->vegetation = PyObject_CallObject(self->vegetation_type, NULL);
if(self->vegetation != NULL) if(self->vegetation != NULL)
{ {
@ -426,7 +436,7 @@ static PyObject* DF_API_getGUI(DF_API* self, void* closure)
{ {
if(self->api_Ptr != NULL) if(self->api_Ptr != NULL)
{ {
self->gui = PyObject_Call((PyObject*)&DF_GUI_type, NULL, NULL); self->gui = PyObject_CallObject(self->gui_type, NULL);
if(self->gui != NULL) if(self->gui != NULL)
{ {
@ -446,6 +456,81 @@ static PyObject* DF_API_getGUI(DF_API* self, void* closure)
Py_RETURN_NONE; Py_RETURN_NONE;
} }
static PyObject* DF_API_getMapType(DF_API* self, void* closure)
{
return self->map_type;
}
static int DF_API_setMapType(DF_API* self, PyObject* value)
{
if(PyType_Check(value) <= 0)
{
PySys_WriteStdout("failed type check");
PyErr_SetString(PyExc_TypeError, "value must be a type object");
return -1;
}
if(PyObject_IsSubclass(value, (PyObject*)&DF_Map_type) <= 0)
{
PySys_WriteStdout("failed subclass check");
PyErr_SetString(PyExc_TypeError, "value must be descended from pydfhack._MapManager");
return -1;
}
self->map_type = value;
return 0;
}
static PyObject* DF_API_getVegetationType(DF_API* self, void* closure)
{
return self->vegetation_type;
}
static int DF_API_setVegetationType(DF_API* self, PyObject* value)
{
if(PyType_Check(value) <= 0)
{
PySys_WriteStdout("failed type check");
PyErr_SetString(PyExc_TypeError, "value must be a type object");
return -1;
}
if(PyObject_IsSubclass(value, (PyObject*)&DF_Vegetation_type) <= 0)
{
PySys_WriteStdout("failed subclass check");
PyErr_SetString(PyExc_TypeError, "value must be descended from pydfhack._VegetationManager");
return -1;
}
self->vegetation_type = value;
return 0;
}
static PyObject* DF_API_getGUIType(DF_API* self, void* closure)
{
return self->gui_type;
}
static int DF_API_setGUIType(DF_API* self, PyObject* value)
{
if(PyType_Check(value) <= 0)
{
PySys_WriteStdout("failed type check");
PyErr_SetString(PyExc_TypeError, "value must be a type object");
return -1;
}
if(PyObject_IsSubclass(value, (PyObject*)&DF_GUI_type) <= 0)
{
PySys_WriteStdout("failed subclass check");
PyErr_SetString(PyExc_TypeError, "value must be descended from pydfhack._GUIManager");
return -1;
}
self->gui_type = value;
return 0;
}
static PyGetSetDef DF_API_getterSetters[] = static PyGetSetDef DF_API_getterSetters[] =
{ {
{"is_attached", (getter)DF_API_getIsAttached, NULL, "is_attached", NULL}, {"is_attached", (getter)DF_API_getIsAttached, NULL, "is_attached", NULL},
@ -459,6 +544,9 @@ static PyGetSetDef DF_API_getterSetters[] =
{"constructions", (getter)DF_API_getConstruction, NULL, "constructions", NULL}, {"constructions", (getter)DF_API_getConstruction, NULL, "constructions", NULL},
{"vegetation", (getter)DF_API_getVegetation, NULL, "vegetation", NULL}, {"vegetation", (getter)DF_API_getVegetation, NULL, "vegetation", NULL},
{"gui", (getter)DF_API_getGUI, NULL, "gui", NULL}, {"gui", (getter)DF_API_getGUI, NULL, "gui", NULL},
{"_map_mgr_type", (getter)DF_API_getMapType, (setter)DF_API_setMapType, "_map_mgr_type", NULL},
{"_vegetation_mgr_type", (getter)DF_API_getVegetationType, (setter)DF_API_setVegetationType, "_vegetation_mgr_type", NULL},
{"_gui_mgr_type", (getter)DF_API_getGUIType, (setter)DF_API_setGUIType, "_gui_mgr_type", NULL},
{NULL} // Sentinel {NULL} // Sentinel
}; };
@ -565,7 +653,7 @@ static PyTypeObject DF_API_type =
{ {
PyObject_HEAD_INIT(NULL) PyObject_HEAD_INIT(NULL)
0, /*ob_size*/ 0, /*ob_size*/
"pydfhack.API", /*tp_name*/ "pydfhack._API", /*tp_name*/
sizeof(DF_API), /*tp_basicsize*/ sizeof(DF_API), /*tp_basicsize*/
0, /*tp_itemsize*/ 0, /*tp_itemsize*/
(destructor)DF_API_dealloc, /*tp_dealloc*/ (destructor)DF_API_dealloc, /*tp_dealloc*/
@ -584,7 +672,7 @@ static PyTypeObject DF_API_type =
0, /*tp_setattro*/ 0, /*tp_setattro*/
0, /*tp_as_buffer*/ 0, /*tp_as_buffer*/
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
"pydfhack API objects", /* tp_doc */ "pydfhack _API objects", /* tp_doc */
0, /* tp_traverse */ 0, /* tp_traverse */
0, /* tp_clear */ 0, /* tp_clear */
0, /* tp_richcompare */ 0, /* tp_richcompare */

@ -26,6 +26,12 @@ distribution.
#define __DFBUILDINGS__ #define __DFBUILDINGS__
#include "Python.h" #include "Python.h"
#include <map>
#include <string>
using namespace std;
#include "DFTypes.h"
#include "modules/Buildings.h" #include "modules/Buildings.h"
#include "DF_Helpers.cpp" #include "DF_Helpers.cpp"
@ -38,22 +44,40 @@ static PyObject* BuildBuilding(DFHack::t_building& building)
t_dict = PyDict_New(); t_dict = PyDict_New();
temp = PyInt_FromLong(building.origin); temp = Py_BuildValue("(si)(si)(si)(sO)(s((ii)(ii)i))", \
DICTADD(t_dict, "origin", temp); "origin", building.origin, \
"vtable", building.vtable, \
"type", building.type, \
"material", BuildMatglossPair(building.material), \
"bounds", Py_BuildValue("(ii)(ii)i", building.x1, building.y1, building.x2, building.y2, building.z));
temp = PyInt_FromLong(building.vtable); PyDict_MergeFromSeq2(t_dict, temp, 0);
DICTADD(t_dict, "vtable", temp);
temp = PyInt_FromLong(building.type); return t_dict;
DICTADD(t_dict, "type", temp); }
temp = BuildMatglossPair(building.material); static DFHack::t_building ReverseBuildBuilding(PyObject* bDict)
DICTADD(t_dict, "material", temp); {
PyObject* temp;
uint32_t x1, y1, x2, y2, z;
DFHack::t_building building;
temp = PyTuple_Pack(2, PyTuple_Pack(2, building.x1, building.y1), PyTuple_Pack(2, building.x2, building.y2)); building.origin = (uint32_t)PyInt_AsLong(PyDict_GetItemString(bDict, "origin"));
DICTADD(t_dict, "bounds", temp); building.vtable = (uint32_t)PyInt_AsLong(PyDict_GetItemString(bDict, "vtable"));
building.material = ReverseBuildMatglossPair(PyDict_GetItemString(bDict, "material"));
building.type = (uint32_t)PyInt_AsLong(PyDict_GetItemString(bDict, "type"));
return t_dict; temp = PyDict_GetItemString(bDict, "bounds");
PyArg_ParseTuple(temp, "(ii)(ii)i", &x1, &y1, &x2, &y2, &z);
building.x1 = x1;
building.y1 = y1;
building.x2 = x2;
building.y2 = y2;
building.z = z;
return building;
} }
struct DF_Building struct DF_Building
@ -151,11 +175,53 @@ static PyObject* DF_Building_Read(DF_Building* self, PyObject* args)
Py_RETURN_NONE; Py_RETURN_NONE;
} }
static PyObject* DF_Building_ReadCustomWorkshopTypes(DF_Building* self, PyObject* args)
{
PyObject* bDict;
std::map<uint32_t, string> bTypes;
std::map<uint32_t, string>::iterator bIter;
if(self->b_Ptr != NULL)
{
if(self->b_Ptr->ReadCustomWorkshopTypes(bTypes))
{
bDict = PyDict_New();
for(bIter = bTypes.begin(); bIter != bTypes.end(); bIter++)
{
PyObject* temp = Py_BuildValue("is", (*bIter).first, (*bIter).second.c_str());
PyDict_MergeFromSeq2(bDict, temp, 1);
}
return bDict;
}
}
Py_RETURN_NONE;
}
static PyObject* DF_Building_GetCustomWorkshopType(DF_Building* self, PyObject* args)
{
DFHack::t_building building;
if(self->b_Ptr != NULL)
{
building = ReverseBuildBuilding(args);
return PyInt_FromLong(self->b_Ptr->GetCustomWorkshopType(building));
}
Py_RETURN_NONE;
}
static PyMethodDef DF_Building_methods[] = static PyMethodDef DF_Building_methods[] =
{ {
{"Start", (PyCFunction)DF_Building_Start, METH_NOARGS, ""}, {"Start", (PyCFunction)DF_Building_Start, METH_NOARGS, ""},
{"Finish", (PyCFunction)DF_Building_Finish, METH_NOARGS, ""}, {"Finish", (PyCFunction)DF_Building_Finish, METH_NOARGS, ""},
{"Read", (PyCFunction)DF_Building_Read, METH_VARARGS, ""}, {"Read", (PyCFunction)DF_Building_Read, METH_VARARGS, ""},
{"Read_Custom_Workshop_Types", (PyCFunction)DF_Building_ReadCustomWorkshopTypes, METH_NOARGS, ""},
{"Get_Custom_Workshop_Type", (PyCFunction)DF_Building_GetCustomWorkshopType, METH_VARARGS, ""},
{NULL} // Sentinel {NULL} // Sentinel
}; };

@ -178,7 +178,7 @@ static PyTypeObject DF_Construction_type =
{ {
PyObject_HEAD_INIT(NULL) PyObject_HEAD_INIT(NULL)
0, /*ob_size*/ 0, /*ob_size*/
"pydfhack.Construction", /*tp_name*/ "pydfhack._ConstructionManager", /*tp_name*/
sizeof(DF_Construction), /*tp_basicsize*/ sizeof(DF_Construction), /*tp_basicsize*/
0, /*tp_itemsize*/ 0, /*tp_itemsize*/
(destructor)DF_Construction_dealloc, /*tp_dealloc*/ (destructor)DF_Construction_dealloc, /*tp_dealloc*/
@ -197,7 +197,7 @@ static PyTypeObject DF_Construction_type =
0, /*tp_setattro*/ 0, /*tp_setattro*/
0, /*tp_as_buffer*/ 0, /*tp_as_buffer*/
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
"pydfhack Construction objects", /* tp_doc */ "pydfhack ConstructionManager object", /* tp_doc */
0, /* tp_traverse */ 0, /* tp_traverse */
0, /* tp_clear */ 0, /* tp_clear */
0, /* tp_richcompare */ 0, /* tp_richcompare */

@ -26,6 +26,7 @@ distribution.
#define __DFCREATURES__ #define __DFCREATURES__
#include "Python.h" #include "Python.h"
#include "stdio.h"
#include "DFTypes.h" #include "DFTypes.h"
#include "modules/Creatures.h" #include "modules/Creatures.h"
#include "DF_CreatureType.cpp" #include "DF_CreatureType.cpp"
@ -155,12 +156,76 @@ static PyObject* DF_CreatureManager_ReadCreatureInBox(DF_CreatureManager* self,
Py_RETURN_NONE; Py_RETURN_NONE;
} }
static PyObject* DF_CreatureManager_GetDwarfRaceIndex(DF_CreatureManager* self, PyObject* args)
{
if(self->creature_Ptr != NULL)
{
return PyInt_FromLong(self->creature_Ptr->GetDwarfRaceIndex());
}
Py_RETURN_NONE;
}
static PyObject* DF_CreatureManager_GetDwarfCivId(DF_CreatureManager* self, PyObject* args)
{
if(self->creature_Ptr != NULL)
{
return PyInt_FromLong(self->creature_Ptr->GetDwarfCivId());
}
Py_RETURN_NONE;
}
static PyObject* DF_CreatureManager_WriteLabors(DF_CreatureManager* self, PyObject* args)
{
int32_t index;
PyObject* laborList;
if(self->creature_Ptr != NULL)
{
uint8_t laborArray[NUM_CREATURE_LABORS];
if(!PyArg_ParseTuple(args, "iO", &index, &laborList))
return NULL;
if(!PyList_Check(laborList))
{
PyErr_SetString(PyExc_TypeError, "argument 2 must be a list");
return NULL;
}
if(PyList_Size(laborList) < NUM_CREATURE_LABORS)
{
char errBuff[50];
sprintf(errBuff, "list must contain at least %u entries", NUM_CREATURE_LABORS);
PyErr_SetString(PyExc_StandardError, errBuff);
return NULL;
}
for(int i = 0; i < NUM_CREATURE_LABORS; i++)
laborArray[i] = (uint8_t)PyInt_AsLong(PyList_GET_ITEM(laborList, i));
if(self->creature_Ptr->WriteLabors(index, laborArray))
Py_RETURN_TRUE;
else
Py_RETURN_FALSE;
}
Py_RETURN_NONE;
}
static PyMethodDef DF_CreatureManager_methods[] = static PyMethodDef DF_CreatureManager_methods[] =
{ {
{"Start", (PyCFunction)DF_CreatureManager_Start, METH_NOARGS, ""}, {"Start", (PyCFunction)DF_CreatureManager_Start, METH_NOARGS, ""},
{"Finish", (PyCFunction)DF_CreatureManager_Finish, METH_NOARGS, ""}, {"Finish", (PyCFunction)DF_CreatureManager_Finish, METH_NOARGS, ""},
{"Read_Creature", (PyCFunction)DF_CreatureManager_ReadCreature, METH_VARARGS, ""}, {"Read_Creature", (PyCFunction)DF_CreatureManager_ReadCreature, METH_VARARGS, ""},
{"Read_Creature_In_Box", (PyCFunction)DF_CreatureManager_ReadCreatureInBox, METH_VARARGS, ""}, {"Read_Creature_In_Box", (PyCFunction)DF_CreatureManager_ReadCreatureInBox, METH_VARARGS, ""},
{"Write_Labors", (PyCFunction)DF_CreatureManager_WriteLabors, METH_VARARGS, ""},
{"Get_Dwarf_Race_Index", (PyCFunction)DF_CreatureManager_GetDwarfRaceIndex, METH_NOARGS, ""},
{"Get_Dwarf_Civ_id", (PyCFunction)DF_CreatureManager_GetDwarfCivId, METH_NOARGS, ""},
{NULL} // Sentinel {NULL} // Sentinel
}; };

@ -26,6 +26,7 @@ distribution.
#define __DFGUI__ #define __DFGUI__
#include "Python.h" #include "Python.h"
#include "DFTypes.h"
#include "modules/Gui.h" #include "modules/Gui.h"
using namespace DFHack; using namespace DFHack;
@ -163,7 +164,7 @@ static PyTypeObject DF_GUI_type =
{ {
PyObject_HEAD_INIT(NULL) PyObject_HEAD_INIT(NULL)
0, /*ob_size*/ 0, /*ob_size*/
"pydfhack.GUI", /*tp_name*/ "pydfhack._GUIManager", /*tp_name*/
sizeof(DF_GUI), /*tp_basicsize*/ sizeof(DF_GUI), /*tp_basicsize*/
0, /*tp_itemsize*/ 0, /*tp_itemsize*/
(destructor)DF_GUI_dealloc, /*tp_dealloc*/ (destructor)DF_GUI_dealloc, /*tp_dealloc*/
@ -182,7 +183,7 @@ static PyTypeObject DF_GUI_type =
0, /*tp_setattro*/ 0, /*tp_setattro*/
0, /*tp_as_buffer*/ 0, /*tp_as_buffer*/
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
"pydfhack GUI objects", /* tp_doc */ "pydfhack GUIManager object", /* tp_doc */
0, /* tp_traverse */ 0, /* tp_traverse */
0, /* tp_clear */ 0, /* tp_clear */
0, /* tp_richcompare */ 0, /* tp_richcompare */

@ -28,24 +28,86 @@ distribution.
#include "Python.h" #include "Python.h"
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <vector>
using namespace std;
#include "DFTypes.h" #include "DFTypes.h"
#include "DF_Imports.cpp" #include "DF_Imports.cpp"
using namespace DFHack; using namespace DFHack;
#include "modules/Creatures.h" #include "modules/Creatures.h"
#include "modules/Materials.h"
#define DICTADD(d, name, item) PyDict_SetItemString(d, name, item); Py_DECREF(item) #define DICTADD(d, name, item) PyDict_SetItemString(d, name, item); Py_DECREF(item)
#define OBJSET(o, name, item) PyObject_SetAttrString(o, name, item); Py_DECREF(item) #define OBJSET(o, name, item) PyObject_SetAttrString(o, name, item); Py_DECREF(item)
static PyObject* BuildTileColor(uint16_t fore, uint16_t back, uint16_t bright)
{
PyObject *tObj, *args;
args = Py_BuildValue("iii", fore, back, bright);
tObj = PyObject_CallObject(TileColor_type, args);
Py_DECREF(args);
return tObj;
}
static PyObject* BuildPosition2D(uint16_t x, uint16_t y)
{
PyObject *posObj, *args;
args = Py_BuildValue("ii", x, y);
posObj = PyObject_CallObject(Position2D_type, args);
Py_DECREF(args);
return posObj;
}
static PyObject* BuildPosition3D(uint16_t x, uint16_t y, uint16_t z)
{
PyObject *posObj, *args;
args = Py_BuildValue("iii", x, y, z);
posObj = PyObject_CallObject(Position3D_type, args);
Py_DECREF(args);
return posObj;
}
static PyObject* BuildMatglossPair(DFHack::t_matglossPair& matgloss) static PyObject* BuildMatglossPair(DFHack::t_matglossPair& matgloss)
{ {
return Py_BuildValue("ii", matgloss.type, matgloss.index); return Py_BuildValue("ii", matgloss.type, matgloss.index);
} }
static DFHack::t_matglossPair ReverseBuildMatglossPair(PyObject* mObj)
{
DFHack::t_matglossPair mPair;
mPair.type = (int16_t)PyInt_AsLong(PyTuple_GetItem(mObj, 0));
mPair.index = (int32_t)PyInt_AsLong(PyTuple_GetItem(mObj, 1));
return mPair;
}
static PyObject* BuildSkill(DFHack::t_skill& skill) static PyObject* BuildSkill(DFHack::t_skill& skill)
{ {
return Py_BuildValue("III", skill.id, skill.experience, skill.rating); PyObject *args, *skillObj;
args = Py_BuildValue("III", skill.id, skill.experience, skill.rating);
skillObj = PyObject_CallObject(Skill_type, args);
Py_DECREF(args);
return skillObj;
} }
static PyObject* BuildSkillList(DFHack::t_skill (&skills)[256], uint8_t numSkills) static PyObject* BuildSkillList(DFHack::t_skill (&skills)[256], uint8_t numSkills)
@ -65,24 +127,20 @@ static PyObject* BuildJob(DFHack::t_job& job)
static PyObject* BuildAttribute(DFHack::t_attrib& at) static PyObject* BuildAttribute(DFHack::t_attrib& at)
{ {
return Py_BuildValue("IIIIIII", at.level, at.field_4, at.field_8, at.field_C, at.leveldiff, at.field_14, at.field_18); PyObject *args, *attrObj;
}
static PyObject* BuildItemType(DFHack::t_itemType& item) args = Py_BuildValue("IIIIIII", at.level, at.field_4, at.field_8, at.field_C, at.leveldiff, at.field_14, at.field_18);
{
PyObject *id, *name;
if(item.id[0]) attrObj = PyObject_CallObject(Attribute_type, args);
id = PyString_FromString(item.id);
else
id = PyString_FromString("");
if(item.name[0]) Py_DECREF(args);
name = PyString_FromString(item.name);
else
name = PyString_FromString("");
return Py_BuildValue("OO", id, name); return attrObj;
}
static PyObject* BuildItemType(DFHack::t_itemType& item)
{
return Py_BuildValue("ss", item.id, item.name);
} }
static PyObject* BuildLike(DFHack::t_like& like) static PyObject* BuildLike(DFHack::t_like& like)
@ -97,19 +155,20 @@ static PyObject* BuildLike(DFHack::t_like& like)
static PyObject* BuildNote(DFHack::t_note& note) static PyObject* BuildNote(DFHack::t_note& note)
{ {
PyObject* noteObj; PyObject* noteObj;
PyObject *args, *name, *position; PyObject *args, *position;
if(note.name[0]) args = Py_BuildValue("III", note.x, note.y, note.z);
name = PyString_FromString(note.name);
else
name = PyString_FromString("");
position = Py_BuildValue("III", note.x, note.y, note.z); position = PyObject_CallObject(Position3D_type, args);
args = Py_BuildValue("cIIsO", note.symbol, note.foreground, note.background, name, position); Py_DECREF(args);
args = Py_BuildValue("cIIsO", note.symbol, note.foreground, note.background, note.name, position);
noteObj = PyObject_CallObject(Note_type, args); noteObj = PyObject_CallObject(Note_type, args);
Py_DECREF(args);
return noteObj; return noteObj;
} }
@ -235,33 +294,36 @@ static DFHack::t_name ReverseBuildName(PyObject* nameObj)
static PyObject* BuildSettlement(DFHack::t_settlement& settlement) static PyObject* BuildSettlement(DFHack::t_settlement& settlement)
{ {
PyObject* setDict; PyObject* setObj;
PyObject *local_pos1, *local_pos2; PyObject *world_pos, *local_pos, *args;
PyObject* temp;
setDict = PyDict_New(); args = Py_BuildValue("ii", settlement.world_x, settlement.world_y);
temp = PyInt_FromLong(settlement.origin); world_pos = PyObject_CallObject(Position2D_type, args);
DICTADD(setDict, "origin", temp);
temp = BuildName(settlement.name); Py_DECREF(args);
DICTADD(setDict, "name", temp);
temp = Py_BuildValue("ii", settlement.world_x, settlement.world_y); args = Py_BuildValue("iiii", settlement.local_x1, settlement.local_y1, settlement.local_x2, settlement.local_y2);
DICTADD(setDict, "world_pos", temp);
local_pos1 = Py_BuildValue("ii", settlement.local_x1, settlement.local_y1); local_pos = PyObject_CallObject(Rectangle_type, args);
local_pos2 = Py_BuildValue("ii", settlement.local_x2, settlement.local_y2);
temp = Py_BuildValue("OO", local_pos1, local_pos2); Py_DECREF(args);
DICTADD(setDict, "local_pos", temp);
return setDict; args = Py_BuildValue("iOOO", settlement.origin, BuildName(settlement.name), world_pos, local_pos);
setObj = PyObject_CallObject(Settlement_type, args);
Py_DECREF(args);
return setObj;
} }
static PyObject* BuildSoul(DFHack::t_soul& soul) static PyObject* BuildSoul(DFHack::t_soul& soul)
{ {
PyObject *soulDict, *skillList, *temp; PyObject *soulDict, *skillList, *temp, *emptyArgs;
PyObject* soulObj;
emptyArgs = Py_BuildValue("()");
soulDict = PyDict_New(); soulDict = PyDict_New();
@ -307,7 +369,11 @@ static PyObject* BuildSoul(DFHack::t_soul& soul)
temp = BuildAttribute(soul.social_awareness); temp = BuildAttribute(soul.social_awareness);
DICTADD(soulDict, "social_awareness", temp); DICTADD(soulDict, "social_awareness", temp);
return soulDict; soulObj = PyObject_Call(Soul_type, emptyArgs, soulDict);
Py_DECREF(emptyArgs);
return soulObj;
} }
#endif #endif

@ -43,10 +43,23 @@ static PyObject* MapBlock40d_type = NULL;
static PyObject* Vein_type = NULL; static PyObject* Vein_type = NULL;
static PyObject* FrozenLiquidVein_type = NULL; static PyObject* FrozenLiquidVein_type = NULL;
static PyObject* SpatterVein_type = NULL; static PyObject* SpatterVein_type = NULL;
static PyObject* Position2D_type = NULL;
static PyObject* Position3D_type = NULL;
static PyObject* Rectangle_type = NULL;
static PyObject* Settlement_type = NULL;
static PyObject* Attribute_type = NULL;
static PyObject* Skill_type = NULL;
static PyObject* Soul_type = NULL;
static PyObject* Tree_type = NULL;
static PyObject* CreatureCaste_type = NULL;
static PyObject* Matgloss_type = NULL;
static PyObject* DescriptorColor_type = NULL;
static PyObject* CreatureTypeEx_type = NULL;
static PyObject* TileColor_type = NULL;
static void DoImports() static void DoImports()
{ {
if(TypesModule == NULL) if(FlagsModule == NULL)
{ {
FlagsModule = PyImport_ImportModule("pydfhackflags"); FlagsModule = PyImport_ImportModule("pydfhackflags");
@ -56,7 +69,9 @@ static void DoImports()
OccupancyFlags_type = PyObject_GetAttrString(FlagsModule, "OccupancyFlags"); OccupancyFlags_type = PyObject_GetAttrString(FlagsModule, "OccupancyFlags");
ItemFlags_type = PyObject_GetAttrString(FlagsModule, "ItemFlags"); ItemFlags_type = PyObject_GetAttrString(FlagsModule, "ItemFlags");
BlockFlags_type = PyObject_GetAttrString(FlagsModule, "BlockFlags"); BlockFlags_type = PyObject_GetAttrString(FlagsModule, "BlockFlags");
}
if(TypesModule == NULL)
{
TypesModule = PyImport_ImportModule("pydftypes"); TypesModule = PyImport_ImportModule("pydftypes");
Note_type = PyObject_GetAttrString(TypesModule, "Note"); Note_type = PyObject_GetAttrString(TypesModule, "Note");
@ -66,6 +81,19 @@ static void DoImports()
Vein_type = PyObject_GetAttrString(TypesModule, "Vein"); Vein_type = PyObject_GetAttrString(TypesModule, "Vein");
FrozenLiquidVein_type = PyObject_GetAttrString(TypesModule, "FrozenLiquidVein"); FrozenLiquidVein_type = PyObject_GetAttrString(TypesModule, "FrozenLiquidVein");
SpatterVein_type = PyObject_GetAttrString(TypesModule, "SpatterVein"); SpatterVein_type = PyObject_GetAttrString(TypesModule, "SpatterVein");
Position2D_type = PyObject_GetAttrString(TypesModule, "Position2D");
Position3D_type = PyObject_GetAttrString(TypesModule, "Position3D");
Rectangle_type = PyObject_GetAttrString(TypesModule, "Rectangle");
Settlement_type = PyObject_GetAttrString(TypesModule, "Settlement");
Attribute_type = PyObject_GetAttrString(TypesModule, "Attribute");
Skill_type = PyObject_GetAttrString(TypesModule, "Skill");
Soul_type = PyObject_GetAttrString(TypesModule, "Soul");
Tree_type = PyObject_GetAttrString(TypesModule, "Tree");
CreatureCaste_type = PyObject_GetAttrString(TypesModule, "CreatureCaste");
Matgloss_type = PyObject_GetAttrString(TypesModule, "Matgloss");
DescriptorColor_type = PyObject_GetAttrString(TypesModule, "DescriptorColor");
CreatureTypeEx_type = PyObject_GetAttrString(TypesModule, "CreatureTypeEx");
TileColor_type = PyObject_GetAttrString(TypesModule, "TileColor");
} }
} }

@ -31,6 +31,7 @@ distribution.
using namespace std; using namespace std;
#include "DFTypes.h"
#include "modules/Maps.h" #include "modules/Maps.h"
#include "DF_Imports.cpp" #include "DF_Imports.cpp"
#include "DF_Helpers.cpp" #include "DF_Helpers.cpp"
@ -301,10 +302,10 @@ static void ReverseBuildDesignations40d(PyObject* list, DFHack::designations40d&
for(int i = 0; i < 16; i++) for(int i = 0; i < 16; i++)
{ {
innerList = PyList_GetItem(list, i); innerList = PyList_GET_ITEM(list, i);
for(int j = 0; j < 16; j++) for(int j = 0; j < 16; j++)
des[i][j].whole = (uint32_t)PyInt_AsLong(PyList_GET_ITEM(innerList, j)); des[i][j].whole = (uint32_t)PyInt_AS_LONG(PyList_GET_ITEM(innerList, j));
} }
} }
@ -591,11 +592,11 @@ static PyObject* DF_Map_WriteDesignations(DF_Map* self, PyObject* args)
if(!PyArg_ParseTuple(args, "IIIO", &x, &y, &z, &desList)) if(!PyArg_ParseTuple(args, "IIIO", &x, &y, &z, &desList))
return NULL; return NULL;
designations40d des; DFHack::designations40d writeDes;
ReverseBuildDesignations40d(desList, des); ReverseBuildDesignations40d(desList, writeDes);
if(self->m_Ptr->WriteDesignations(x, y, z, &des)) if(self->m_Ptr->WriteDesignations(x, y, z, &writeDes))
Py_RETURN_TRUE; Py_RETURN_TRUE;
else else
Py_RETURN_FALSE; Py_RETURN_FALSE;
@ -817,7 +818,7 @@ static PyTypeObject DF_Map_type =
{ {
PyObject_HEAD_INIT(NULL) PyObject_HEAD_INIT(NULL)
0, /*ob_size*/ 0, /*ob_size*/
"pydfhack.Map", /*tp_name*/ "pydfhack._MapManager", /*tp_name*/
sizeof(DF_Map), /*tp_basicsize*/ sizeof(DF_Map), /*tp_basicsize*/
0, /*tp_itemsize*/ 0, /*tp_itemsize*/
(destructor)DF_Map_dealloc, /*tp_dealloc*/ (destructor)DF_Map_dealloc, /*tp_dealloc*/
@ -836,7 +837,7 @@ static PyTypeObject DF_Map_type =
0, /*tp_setattro*/ 0, /*tp_setattro*/
0, /*tp_as_buffer*/ 0, /*tp_as_buffer*/
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
"pydfhack Map objects", /* tp_doc */ "pydfhack MapManager object", /* tp_doc */
0, /* tp_traverse */ 0, /* tp_traverse */
0, /* tp_clear */ 0, /* tp_clear */
0, /* tp_richcompare */ 0, /* tp_richcompare */

@ -31,6 +31,8 @@ distribution.
using namespace std; using namespace std;
#include "modules/Materials.h" #include "modules/Materials.h"
#include "DF_Imports.cpp"
#include "DF_Helpers.cpp"
using namespace DFHack; using namespace DFHack;
@ -44,48 +46,16 @@ struct DF_Material
static PyObject* BuildMatgloss(t_matgloss& matgloss) static PyObject* BuildMatgloss(t_matgloss& matgloss)
{ {
PyObject* matDict; PyObject* matObj;
PyObject* temp; PyObject* args;
matDict = PyDict_New();
if(matgloss.id[0])
temp = PyString_FromString(matgloss.id);
else
temp = PyString_FromString("");
PyDict_SetItemString(matDict, "id", temp);
Py_DECREF(temp);
temp = PyInt_FromLong(matgloss.fore);
PyDict_SetItemString(matDict, "fore", temp);
Py_DECREF(temp);
temp = PyInt_FromLong(matgloss.back);
PyDict_SetItemString(matDict, "back", temp); args = Py_BuildValue("siiis", matgloss.id, matgloss.fore, matgloss.back, matgloss.bright, matgloss.name);
Py_DECREF(temp); matObj = PyObject_CallObject(Matgloss_type, args);
temp = PyInt_FromLong(matgloss.bright); Py_DECREF(args);
PyDict_SetItemString(matDict, "bright", temp); return matObj;
Py_DECREF(temp);
if(matgloss.name[0])
temp = PyString_FromString(matgloss.name);
else
temp = PyString_FromString("");
PyDict_SetItemString(matDict, "name", temp);
Py_DECREF(temp);
return matDict;
} }
static PyObject* BuildMatglossPlant(t_matglossPlant& matgloss) static PyObject* BuildMatglossPlant(t_matglossPlant& matgloss)
@ -145,6 +115,106 @@ static PyObject* BuildMatglossList(std::vector<t_matgloss> & matVec)
return matList; return matList;
} }
static PyObject* BuildDescriptorColor(t_descriptor_color& color)
{
PyObject* descObj;
PyObject* args;
args = Py_BuildValue("sfffs", color.id, color.r, color.v, color.b, color.name);
descObj = PyObject_CallObject(DescriptorColor_type, args);
Py_DECREF(args);
return descObj;
}
static PyObject* BuildDescriptorColorList(std::vector<t_descriptor_color>& colors)
{
PyObject* colorList;
std::vector<t_descriptor_color>::iterator colorIter;
colorList = PyList_New(0);
for(colorIter = colors.begin(); colorIter != colors.end(); colorIter++)
{
PyObject* color = BuildDescriptorColor(*colorIter);
PyList_Append(colorList, color);
Py_DECREF(colorList);
}
return colorList;
}
static PyObject* BuildCreatureCaste(t_creaturecaste& caste)
{
PyObject* casteObj;
PyObject* args;
args = Py_BuildValue("ssss", caste.rawname, caste.singular, caste.plural, caste.adjective);
casteObj = PyObject_CallObject(CreatureCaste_type, args);
Py_DECREF(args);
return casteObj;
}
static PyObject* BuildCreatureCasteList(std::vector<t_creaturecaste>& castes)
{
PyObject* casteList;
std::vector<t_creaturecaste>::iterator casteIter;
casteList = PyList_New(0);
for(casteIter = castes.begin(); casteIter != castes.end(); casteIter++)
{
PyObject* caste = BuildCreatureCaste(*casteIter);
PyList_Append(casteList, caste);
Py_DECREF(caste);
}
return casteList;
}
static PyObject* BuildCreatureTypeEx(t_creaturetype& creature)
{
PyObject* cObj;
PyObject* args;
args = Py_BuildValue("sOiO", creature.rawname, BuildCreatureCasteList(creature.castes), creature.tile_character, \
BuildTileColor(creature.tilecolor.fore, creature.tilecolor.back, creature.tilecolor.bright));
cObj = PyObject_CallObject(CreatureTypeEx_type, args);
Py_DECREF(args);
return cObj;
}
static PyObject* BuildCreatureTypeExList(std::vector<t_creaturetype>& creatures)
{
PyObject* creatureList;
std::vector<t_creaturetype>::iterator creatureIter;
creatureList = PyList_New(0);
for(creatureIter = creatures.begin(); creatureIter != creatures.end(); creatureIter++)
{
PyObject* creature = BuildCreatureTypeEx(*creatureIter);
PyList_Append(creatureList, creature);
Py_DECREF(creature);
}
return creatureList;
}
// API type Allocation, Deallocation, and Initialization // API type Allocation, Deallocation, and Initialization
static PyObject* DF_Material_new(PyTypeObject* type, PyObject* args, PyObject* kwds) static PyObject* DF_Material_new(PyTypeObject* type, PyObject* args, PyObject* kwds)
@ -266,6 +336,36 @@ static PyObject* DF_Material_ReadCreatureTypes(DF_Material* self, PyObject* args
Py_RETURN_NONE; Py_RETURN_NONE;
} }
static PyObject* DF_Material_ReadCreatureTypesEx(DF_Material* self, PyObject* args)
{
if(self->mat_Ptr != NULL)
{
std::vector<DFHack::t_creaturetype> creatureVec;
if(self->mat_Ptr->ReadCreatureTypesEx(creatureVec))
{
return BuildCreatureTypeExList(creatureVec);
}
}
Py_RETURN_NONE;
}
static PyObject* DF_Material_ReadDescriptorColors(DF_Material* self, PyObject* args)
{
if(self->mat_Ptr != NULL)
{
std::vector<DFHack::t_descriptor_color> colorVec;
if(self->mat_Ptr->ReadDescriptorColors(colorVec))
{
return BuildDescriptorColorList(colorVec);
}
}
Py_RETURN_NONE;
}
static PyMethodDef DF_Material_methods[] = static PyMethodDef DF_Material_methods[] =
{ {
{"Read_Inorganic_Materials", (PyCFunction)DF_Material_ReadInorganicMaterials, METH_NOARGS, ""}, {"Read_Inorganic_Materials", (PyCFunction)DF_Material_ReadInorganicMaterials, METH_NOARGS, ""},
@ -273,6 +373,8 @@ static PyMethodDef DF_Material_methods[] =
{"Read_Wood_Materials", (PyCFunction)DF_Material_ReadWoodMaterials, METH_NOARGS, ""}, {"Read_Wood_Materials", (PyCFunction)DF_Material_ReadWoodMaterials, METH_NOARGS, ""},
{"Read_Plant_Materials", (PyCFunction)DF_Material_ReadPlantMaterials, METH_NOARGS, ""}, {"Read_Plant_Materials", (PyCFunction)DF_Material_ReadPlantMaterials, METH_NOARGS, ""},
{"Read_Creature_Types", (PyCFunction)DF_Material_ReadCreatureTypes, METH_NOARGS, ""}, {"Read_Creature_Types", (PyCFunction)DF_Material_ReadCreatureTypes, METH_NOARGS, ""},
{"Read_Creature_Types_Ex", (PyCFunction)DF_Material_ReadCreatureTypesEx, METH_NOARGS, ""},
{"Read_Descriptor_Colors", (PyCFunction)DF_Material_ReadDescriptorColors, METH_NOARGS, ""},
{NULL} //Sentinel {NULL} //Sentinel
}; };

@ -31,7 +31,9 @@ distribution.
using namespace std; using namespace std;
#include "DFTypes.h"
#include "modules/Translation.h" #include "modules/Translation.h"
#include "DF_Helpers.cpp"
using namespace DFHack; using namespace DFHack;
@ -237,7 +239,7 @@ static PyTypeObject DF_Translate_type =
{ {
PyObject_HEAD_INIT(NULL) PyObject_HEAD_INIT(NULL)
0, /*ob_size*/ 0, /*ob_size*/
"pydfhack.Translate", /*tp_name*/ "pydfhack._TranslationManager", /*tp_name*/
sizeof(DF_Translate), /*tp_basicsize*/ sizeof(DF_Translate), /*tp_basicsize*/
0, /*tp_itemsize*/ 0, /*tp_itemsize*/
(destructor)DF_Translate_dealloc, /*tp_dealloc*/ (destructor)DF_Translate_dealloc, /*tp_dealloc*/
@ -256,7 +258,7 @@ static PyTypeObject DF_Translate_type =
0, /*tp_setattro*/ 0, /*tp_setattro*/
0, /*tp_as_buffer*/ 0, /*tp_as_buffer*/
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
"pydfhack Translate objects", /* tp_doc */ "pydfhack TranslationManager object", /* tp_doc */
0, /* tp_traverse */ 0, /* tp_traverse */
0, /* tp_clear */ 0, /* tp_clear */
0, /* tp_richcompare */ 0, /* tp_richcompare */

@ -33,24 +33,16 @@ using namespace DFHack;
static PyObject* BuildTree(DFHack::t_tree& tree) static PyObject* BuildTree(DFHack::t_tree& tree)
{ {
PyObject* t_dict; PyObject* t_Obj;
PyObject* temp; PyObject* args;
t_dict = PyDict_New(); args = Py_BuildValue("iiOi", tree.type, tree.material, BuildPosition3D(tree.x, tree.y, tree.z), tree.address);
temp = PyInt_FromLong(tree.type); t_Obj = PyObject_CallObject(Tree_type, args);
DICTADD(t_dict, "type", temp);
temp = PyInt_FromLong(tree.material); Py_DECREF(args);
DICTADD(t_dict, "material", temp);
temp = PyTuple_Pack(3, tree.x, tree.y, tree.z); return t_Obj;
DICTADD(t_dict, "position", temp);
temp = PyInt_FromLong(tree.address);
DICTADD(t_dict, "address", temp);
return t_dict;
} }
struct DF_Vegetation struct DF_Vegetation

@ -0,0 +1,43 @@
import time
import math
import pydfapi
df = pydfapi.API("Memory.xml")
def test_attach():
if not df.Attach():
print "Unable to attach!"
return False
elif not df.Detach():
print "Unable to detach!"
return False
else:
return True
def suspend_test():
print "Testing suspend/resume"
df.Attach()
t1 = time.time()
for i in xrange(1000):
df.Suspend()
if i % 10 == 0:
print "%i%%" % (i / 10,)
df.Resume()
t2 = time.time()
df.Detach()
print "suspend tests done in %0.9f seconds" % (t2 - t1,)
if __name__ == "__main__":
if test_attach():
suspend_test()
print "Done. Press any key to continue"
raw_input()

@ -0,0 +1,36 @@
_splatter_dict = { 0 : "Rock",
1 : "Amber",
2 : "Coral",
3 : "Green Glass",
4 : "Clear Glass",
5 : "Crystal Glass",
6 : "Ice",
7 : "Coal",
8 : "Potash",
9 : "Ash",
10 : "Pearlash",
11 : "Lye",
12 : "Mud",
13 : "Vomit",
14 : "Salt",
15 : "Filth",
16 : "Frozen? Filth",
18 : "Grime",
0xF2 : "Very Specific Blood (references a named creature)" }
def get_splatter_type(mat1, mat2, creature_types):
from cStringIO import StringIO
if mat1 in _splatter_dict:
return _splatter_dict[mat1]
elif mat1 == 0x2A or mat1 == 0x2B:
splatter = StringIO()
if mat2 != -1:
splatter.write(creature_types[mat2]["id"] + " ")
splatter.write("Blood")
return splatter.getvalue()
else:
return "Unknown"

@ -0,0 +1,22 @@
import sys
import pydfapi
df = pydfapi.API("Memory.xml")
if not df.Attach():
print "Unable to attach!"
print "Press any key to continue"
raw_input()
sys.exit(1)
pos = df.position
print "view coords: %s" % (pos.view_coords,)
print "cursor coords: %s" % (pos.cursor_coords,)
print "window size: %s" % (pos.window_size,)
if not df.Detach():
print "Unable to detach!"
print "Done. Press any key to continue"
raw_input()

@ -0,0 +1,8 @@
import sys
from cStringIO import StringIO
import pydfapi
df = pydfapi.API("Memory.xml")
def print_settlement(settlement, english_words, foreign_words):
s = StringIO()

@ -0,0 +1,38 @@
import pydfapi
if __name__ == "__main__":
df = pydfapi.API("Memory.xml")
if not df.Attach():
print "Unable to attach!"
return False
print "Attached, DF should be suspended now"
raw_input()
df.Resume()
print "Resumed, DF should be running"
raw_input()
df.Suspend()
print "Suspended, DF should be suspended now"
raw_input()
df.Resume()
print "Resumed, testing ForceResume. Suspend using SysInternals Process Explorer"
raw_input()
df.Force_Resume()
print "ForceResumed. DF should be running."
raw_input()
if not df.Detach():
print "Can't detach from DF"
return False
print "Detached, DF should be running again"
raw_input()

@ -0,0 +1,66 @@
import sys
from cStringIO import StringIO
import pydfapi
df = pydfapi.API("Memory.xml")
if not df.Attach():
print "Unable to attach!\nPress any key to continue"
raw_input()
sys.exit(1)
pos = df.position
veg = df.vegetation
mat = df.materials
organics = mat.Read_Organic_Materials()
x, y, z = pos.cursor_coords
num_vegs = veg.Start()
if x == -30000:
print "----==== Trees ====----"
for i in xrange(num_vegs):
tree = veg.Read(i)
t_x, t_y, t_z = tree["position"]
print "%f/%f/%f, %f:%f" % (t_x, t_y, t_z, tree["type"], tree["material"])
else:
print "----==== Tree at %i/%i/%i" % (x, y, z)
for i in xrange(num_vegs):
tree = veg.Read(i)
t_x, t_y, t_z = tree["position"]
t_type = tree["address"]
if t_x == x and t_y == y and t_z == z:
s = StringIO()
s.write("%f:%f = " % (tree["type"], tree["material"]))
if t_type in (1, 3):
s.write("near-water ")
s.write("%i " % (organics[tree["material"]]["id"]),)
if t_type in (0, 1):
s.write("tree\n")
elif t_type in (2, 3):
s.write("shrub\n")
print s.getvalue()
print "Address: 0x%x" % (tree["address"],)
break
veg.Finish()
if not df.Detach():
print "Unable to detach!"
print "Done. Press any key to continue"
raw_input()

@ -0,0 +1,21 @@
from pydfhack import *
class API(_API):
def __init__(self, *args, **kwds):
_API.__init__(self, args, kwds)
self._map_mgr_type = Map
self._vegetation_mgr_type = Vegetation
self._gui_mgr_type = GUI
class Map(_MapManager):
def __init__(self, *args, **kwds):
_MapManager.__init__(self, args, kwds)
class Vegetation(_VegetationManager):
def __init__(self, *args, **kwds):
_VegetationManager.__init__(self, args, kwds)
class GUI(_GUIManager):
def __init__(self, *args, **kwds):
_GUIManager.__init__(self, args, kwds)

@ -117,18 +117,18 @@ PyMODINIT_FUNC initpydfhack(void)
Py_INCREF(&DF_Map_type); Py_INCREF(&DF_Map_type);
Py_INCREF(&DF_GUI_type); Py_INCREF(&DF_GUI_type);
PyModule_AddObject(module, "API", (PyObject*)&DF_API_type); PyModule_AddObject(module, "_API", (PyObject*)&DF_API_type);
PyModule_AddObject(module, "MemInfo", (PyObject*)&DF_MemInfo_type); PyModule_AddObject(module, "_MemInfo", (PyObject*)&DF_MemInfo_type);
PyModule_AddObject(module, "Position", (PyObject*)&DF_Position_type); PyModule_AddObject(module, "_PositionManager", (PyObject*)&DF_Position_type);
PyModule_AddObject(module, "Materials", (PyObject*)&DF_Material_type); PyModule_AddObject(module, "_MaterialsManager", (PyObject*)&DF_Material_type);
PyModule_AddObject(module, "Creature_Base", (PyObject*)&DF_Creature_Base_type); PyModule_AddObject(module, "_Creature_Base", (PyObject*)&DF_Creature_Base_type);
PyModule_AddObject(module, "CreatureManager", (PyObject*)&DF_CreatureManager_type); PyModule_AddObject(module, "_CreatureManager", (PyObject*)&DF_CreatureManager_type);
PyModule_AddObject(module, "Translate", (PyObject*)&DF_Translate_type); PyModule_AddObject(module, "_TranslationManager", (PyObject*)&DF_Translate_type);
PyModule_AddObject(module, "Vegetation", (PyObject*)&DF_Vegetation_type); PyModule_AddObject(module, "_VegetationManager", (PyObject*)&DF_Vegetation_type);
PyModule_AddObject(module, "Building", (PyObject*)&DF_Building_type); PyModule_AddObject(module, "_BuildingManager", (PyObject*)&DF_Building_type);
PyModule_AddObject(module, "ConstructionManager", (PyObject*)&DF_Construction_type); PyModule_AddObject(module, "_ConstructionManager", (PyObject*)&DF_Construction_type);
PyModule_AddObject(module, "Map", (PyObject*)&DF_Map_type); PyModule_AddObject(module, "_MapManager", (PyObject*)&DF_Map_type);
PyModule_AddObject(module, "GUI", (PyObject*)&DF_GUI_type); PyModule_AddObject(module, "_GUIManager", (PyObject*)&DF_GUI_type);
DoImports(); DoImports();

@ -18,8 +18,8 @@ class DesignationStruct(Structure):
("traffic", c_uint, 2), ("traffic", c_uint, 2),
("flow_forbid", c_uint, 1), ("flow_forbid", c_uint, 1),
("liquid_static", c_uint, 1), ("liquid_static", c_uint, 1),
("moss", c_uint, 1), ("feature_local", c_uint, 1),
("feature_present", c_uint, 1), ("feature_global", c_uint, 1),
("liquid_character", c_uint, 2)] ("liquid_character", c_uint, 2)]
class DesignationFlags(Union): class DesignationFlags(Union):
@ -29,6 +29,9 @@ class DesignationFlags(Union):
def __init__(self, initial = 0): def __init__(self, initial = 0):
self.whole = initial self.whole = initial
def __int__(self):
return self.whole
class OccupancyStruct(Structure): class OccupancyStruct(Structure):
_fields_ = [("building", c_uint, 3), _fields_ = [("building", c_uint, 3),
("unit", c_uint, 1), ("unit", c_uint, 1),
@ -43,6 +46,9 @@ class OccupancyFlags(Union):
def __init__(self, initial = 0): def __init__(self, initial = 0):
self.whole = initial self.whole = initial
def __int__(self):
return self.whole
class CreatureStruct1(Structure): class CreatureStruct1(Structure):
_fields_ = [("move_state", c_uint, 1), _fields_ = [("move_state", c_uint, 1),
("dead", c_uint, 1), ("dead", c_uint, 1),
@ -84,6 +90,9 @@ class CreatureFlags1(Union):
def __init__(self, initial = 0): def __init__(self, initial = 0):
self.whole = initial self.whole = initial
def __int__(self):
return self.whole
class CreatureStruct2(Structure): class CreatureStruct2(Structure):
_fields_ = [("swimming", c_uint, 1), _fields_ = [("swimming", c_uint, 1),
("sparring", c_uint, 1), ("sparring", c_uint, 1),
@ -125,6 +134,9 @@ class CreatureFlags2(Union):
def __init__(self, initial = 0): def __init__(self, initial = 0):
self.whole = initial self.whole = initial
def __int__(self):
return self.whole
class ItemStruct(Structure): class ItemStruct(Structure):
_fields_ = [("on_ground", c_uint, 1), _fields_ = [("on_ground", c_uint, 1),
("in_job", c_uint, 1), ("in_job", c_uint, 1),
@ -166,6 +178,9 @@ class ItemFlags(Union):
def __init__(self, initial = 0): def __init__(self, initial = 0):
self.whole = initial self.whole = initial
def __int__(self):
return self.whole
dig_types = { "no" : 0, dig_types = { "no" : 0,
"default" : 1, "default" : 1,
"ud_stair" : 2, "ud_stair" : 2,
@ -193,3 +208,6 @@ class BlockFlags(Union):
def __init__(self, inital = 0): def __init__(self, inital = 0):
self.whole = initial self.whole = initial
def __int__(self):
return self.whole

@ -1,16 +1,31 @@
from collections import namedtuple from collections import namedtuple
Position2D = namedtuple("Position2D", "x, y")
Position3D = namedtuple("Position3D", "x, y, z")
Rectangle = namedtuple("Rectangle", "x1, y1, x2, y2")
Note = namedtuple("Note", "symbol, foreground, background, name, position") Note = namedtuple("Note", "symbol, foreground, background, name, position")
Construction = namedtuple("Construction", "position, form, unk_8, mat_type, mat_idx, unk3, unk4, unk5, unk6, origin") Construction = namedtuple("Construction", "position, form, unk_8, mat_type, mat_idx, unk3, unk4, unk5, unk6, origin")
Vein = namedtuple("Vein", "vtable, type, flags, address, assignment") Vein = namedtuple("Vein", "vtable, type, flags, address, assignment")
FrozenLiquidVein = namedtuple("FrozenLiquidVein", "vtable, address, tiles") FrozenLiquidVein = namedtuple("FrozenLiquidVein", "vtable, address, tiles")
SpatterVein = namedtuple("SpatterVein", "vtable, address, mat1, unk1, mat2, mat3, intensity") SpatterVein = namedtuple("SpatterVein", "vtable, address, mat1, unk1, mat2, mat3, intensity")
Settlement = namedtuple("Settlement", "origin, name, world_pos, local_pos")
Attribute = namedtuple("Attribute", "level, field_4, field_8, field_C, leveldiff, field_14, field_18");
Skill = namedtuple("Skill", "id, experience, rating")
Tree = namedtuple("Tree", "type, material, position, address")
CreatureCaste = namedtuple("CreatureCaste", "rawname, singular, plural, adjective")
Matgloss = namedtuple("Matgloss", "id, fore, back, bright, name")
DescriptorColor = namedtuple("DescriptorColor", "id, r, v, b, name")
CreatureTypeEx = namedtuple("CreatureTypeEx", "rawname, castes, tile_character, tilecolor")
TileColor = namedtuple("TileColor", "fore, back, bright")
class Name(object): class Name(object):
__slots__ = ["first_name", "nickname", "language", "has_name", "words", "parts_of_speech"] __slots__ = ["first_name", "nickname", "language", "has_name", "words", "parts_of_speech"]
class Soul(object): class Soul(object):
pass def __init__(self, *args, **kwds):
if kwds:
for k, v in kwds.iteritems():
self.__dict__[k] = v
class MapBlock40d(object): class MapBlock40d(object):
pass pass

@ -2,9 +2,10 @@
from distutils.core import setup, Extension from distutils.core import setup, Extension
e = Extension("pydfhack", e = Extension("pydfhack",
sources=["DF_MemInfo.cpp", "DF_API.cpp", "pydfhack.cpp"], sources=["DF_API.cpp", "DF_Buildings.cpp", "DF_Constructions.cpp", "DF_CreatureManager.cpp", "DF_GUI.cpp", "DF_Maps.cpp", "DF_Material.cpp", "DF_Position.cpp", "DF_Translate.cpp", "DF_Vegetation.cpp", "pydfhack.cpp"],
include_dirs=["..\\", "..\\include", "..\\depends\\md5", "..\\depends\\tinyxml"], include_dirs=["..\\", "..\\include", "..\\depends\\md5", "..\\depends\\tinyxml"],
library_dirs=["..\\..\\output"], library_dirs=["..\\..\\output"],
#extra_compile_args=["-w"],
libraries=["libdfhack"], libraries=["libdfhack"],
export_symbols=["initpydfhack", "ReadRaw", "WriteRaw"]) export_symbols=["initpydfhack", "ReadRaw", "WriteRaw"])

@ -42,6 +42,9 @@ typedef struct
uint32_t x_count_offset;// = d->offset_descriptor->getAddress ("x_count"); uint32_t x_count_offset;// = d->offset_descriptor->getAddress ("x_count");
uint32_t y_count_offset;// = d->offset_descriptor->getAddress ("y_count"); uint32_t y_count_offset;// = d->offset_descriptor->getAddress ("y_count");
uint32_t z_count_offset;// = d->offset_descriptor->getAddress ("z_count"); uint32_t z_count_offset;// = d->offset_descriptor->getAddress ("z_count");
/*
Block
*/
uint32_t tile_type_offset;// = d->offset_descriptor->getOffset ("type"); uint32_t tile_type_offset;// = d->offset_descriptor->getOffset ("type");
uint32_t designation_offset;// = d->offset_descriptor->getOffset ("designation"); uint32_t designation_offset;// = d->offset_descriptor->getOffset ("designation");
uint32_t occupancy_offset;// = d->offset_descriptor->getOffset ("occupancy"); uint32_t occupancy_offset;// = d->offset_descriptor->getOffset ("occupancy");
@ -49,23 +52,27 @@ typedef struct
uint32_t veinvector;// = d->offset_descriptor->getOffset ("v_vein"); uint32_t veinvector;// = d->offset_descriptor->getOffset ("v_vein");
uint32_t temperature1_offset; uint32_t temperature1_offset;
uint32_t temperature2_offset; uint32_t temperature2_offset;
uint32_t global_feature_offset;
uint32_t local_feature_offset;
uint32_t vein_mineral_vptr; uint32_t vein_mineral_vptr;
uint32_t vein_ice_vptr; uint32_t vein_ice_vptr;
uint32_t vein_spatter_vptr; uint32_t vein_spatter_vptr;
/* /*
GEOLOGY GEOLOGY
*/
uint32_t region_x_offset;// = minfo->getAddress ("region_x"); uint32_t region_x_offset;// = minfo->getAddress ("region_x");
uint32_t region_y_offset;// = minfo->getAddress ("region_y"); uint32_t region_y_offset;// = minfo->getAddress ("region_y");
uint32_t region_z_offset;// = minfo->getAddress ("region_z"); uint32_t region_z_offset;// = minfo->getAddress ("region_z");
uint32_t world_offset;// = minfo->getAddress ("world");
uint32_t world_regions_offset;// = minfo->getOffset ("w_regions_arr"); uint32_t world_regions;// mem->getAddress ("ptr2_region_array");
uint32_t region_size;// = minfo->getHexValue ("region_size"); uint32_t region_size;// = minfo->getHexValue ("region_size");
uint32_t region_geo_index_offset;// = minfo->getOffset ("region_geo_index_off"); uint32_t region_geo_index_offset;// = minfo->getOffset ("region_geo_index_off");
uint32_t world_geoblocks_offset;// = minfo->getOffset ("w_geoblocks"); uint32_t world_geoblocks_vector;// = minfo->getOffset ("geoblock_vector");
uint32_t world_size_x;// = minfo->getOffset ("world_size_x"); uint32_t world_size_x;// = minfo->getOffset ("world_size_x");
uint32_t world_size_y;// = minfo->getOffset ("world_size_y"); uint32_t world_size_y;// = minfo->getOffset ("world_size_y");
uint32_t geolayer_geoblock_offset;// = minfo->getOffset ("geolayer_geoblock_offset"); uint32_t geolayer_geoblock_offset;// = minfo->getOffset ("geolayer_geoblock_offset");
*/ uint32_t type_inside_geolayer;// = mem->getOffset ("type_inside_geolayer");
} maps_offsets; } maps_offsets;
typedef struct typedef struct

@ -281,6 +281,7 @@ void hexdump (DFHack::API& DF, uint32_t address, uint32_t length, int filenum)
// blockaddr = address of the block // blockaddr = address of the block
// blockX, blockY = local map X and Y coords in 16x16 of the block // blockX, blockY = local map X and Y coords in 16x16 of the block
// printX, printX = where to print stuff on the screen // printX, printX = where to print stuff on the screen
/*
void do_features(Process* p, uint32_t blockaddr, uint32_t blockX, uint32_t blockY, int printX, int printY, vector<DFHack::t_matgloss> &stonetypes) void do_features(Process* p, uint32_t blockaddr, uint32_t blockX, uint32_t blockY, int printX, int printY, vector<DFHack::t_matgloss> &stonetypes)
{ {
memory_info* mem = p->getDescriptor(); memory_info* mem = p->getDescriptor();
@ -337,19 +338,11 @@ void do_features(Process* p, uint32_t blockaddr, uint32_t blockX, uint32_t block
gotoxy(printX,printY+6); gotoxy(printX,printY+6);
cprintf("local feature vector: 0x%x\n", feat_vector); cprintf("local feature vector: 0x%x\n", feat_vector);
DfVector<uint32_t> p_features(p, feat_vector); DfVector<uint32_t> p_features(p, feat_vector);
/* gotoxy(printX,printY + 7);
for(int k = 0 ; k < p_features.size();k++)
{
printf("feature %d addr: 0x%x\n", k, p_features[k]);
string name = p->readClassName(p->readDWord( p_features[k] ));
cout << name << endl;
}
*/
gotoxy(printX,printY+7);
cprintf("feature %d addr: 0x%x\n", idx, p_features[idx]); cprintf("feature %d addr: 0x%x\n", idx, p_features[idx]);
if(idx >= p_features.size()) if(idx >= p_features.size())
{ {
gotoxy(printX,printY+8); gotoxy(printX,printY + 8);
cprintf("ERROR, out of vector bounds."); cprintf("ERROR, out of vector bounds.");
} }
else else
@ -418,8 +411,91 @@ void do_features(Process* p, uint32_t blockaddr, uint32_t blockX, uint32_t block
} }
} }
} }
*/
void do_features(API& DF, mapblock40d * block, uint32_t blockX, uint32_t blockY, int printX, int printY, vector<DFHack::t_matgloss> &stonetypes)
{
Maps * Maps = DF.getMaps();
Process * p = DF.getProcess();
if(!Maps)
return;
vector<DFHack::t_feature> global_features;
std::map <DFHack::planecoord, std::vector<DFHack::t_feature *> > local_features;
if(!Maps->ReadGlobalFeatures(global_features))
return;
if(!Maps->ReadLocalFeatures(local_features))
return;
planecoord pc;
pc.dim.x = blockX;
pc.dim.y = blockY;
int16_t idx =block->global_feature;
if(idx != -1)
{
t_feature &ftr =global_features[idx];
gotoxy(printX,printY);
cprintf( "global feature present: %d @ 0x%x\n", idx, ftr.origin);
if(ftr.discovered )
{
gotoxy(printX,printY+1);
cprintf("You've discovered it already!");
}
if(ftr.type == feature_Underworld)
{
char * matname = "unknown";
// is stone?
if(ftr.main_material == 0)
{
matname = stonetypes[ftr.sub_material].id;
}
gotoxy(printX,printY+2);
cprintf("Underworld, material %d/%d : %s", ftr.main_material, ftr.sub_material, matname);
}
else
{
gotoxy(printX,printY+2);
string name = p->readClassName(p->readDWord( ftr.origin ));
cprintf("%s", name.c_str());
}
}
idx =block->local_feature;
if(idx != -1)
{
vector <t_feature *> &ftrv = local_features[pc];
if(idx < ftrv.size())
{
t_feature & ftr = *ftrv[idx];
gotoxy(printX,printY + 4);
cprintf( "local feature present: %d @ 0x%x\n", idx, ftr.origin);
if(ftr.discovered )
{
gotoxy(printX,printY+ 5);
cprintf("You've discovered it already!");
}
if(ftr.type == feature_Adamantine_Tube)
{
char * matname = "unknown";
// is stone?
if(ftr.main_material == 0)
{
matname = stonetypes[ftr.sub_material].id;
}
gotoxy(printX,printY+6);
cprintf("Underworld, material %d/%d : %s", ftr.main_material, ftr.sub_material, matname);
}
else
{
gotoxy(printX,printY+6);
string name = p->readClassName(p->readDWord( ftr.origin ));
cprintf("%s", name.c_str());
}
}
else
{
gotoxy(printX,printY + 4);
cprintf( "local feature vector overflow: %d", idx);
}
}
}
main(int argc, char *argv[]) main(int argc, char *argv[])
{ {
@ -677,7 +753,7 @@ main(int argc, char *argv[])
// extra processing of the block in the middle // extra processing of the block in the middle
if(i == 0 && j == 0) if(i == 0 && j == 0)
{ {
do_features(p, Block->origin, cursorX, cursorY, 50,10, stonetypes); do_features(DF, Block, cursorX, cursorY, 50,10, stonetypes);
// read veins // read veins
Maps->ReadVeins(cursorX+i,cursorY+j,cursorZ,&veinVector,&IceVeinVector,&splatter); Maps->ReadVeins(cursorX+i,cursorY+j,cursorZ,&veinVector,&IceVeinVector,&splatter);

@ -49,12 +49,18 @@ int main (int argc, const char* argv[])
showhidden = true; showhidden = true;
#endif #endif
uint32_t x_max,y_max,z_max; uint32_t x_max,y_max,z_max;
/*
DFHack::tiletypes40d tiletypes; DFHack::tiletypes40d tiletypes;
DFHack::designations40d designations; DFHack::designations40d designations;
DFHack::biome_indices40d regionoffsets; DFHack::biome_indices40d regionoffsets;
*/
DFHack::mapblock40d Block;
map <int16_t, uint32_t> materials; map <int16_t, uint32_t> materials;
materials.clear(); materials.clear();
vector<DFHack::t_matgloss> stonetypes; vector<DFHack::t_matgloss> stonetypes;
vector<DFHack::t_feature> global_features;
std::map <DFHack::planecoord, std::vector<DFHack::t_feature *> > local_features;
vector< vector <uint16_t> > layerassign; vector< vector <uint16_t> > layerassign;
DFHack::API DF("Memory.xml"); DFHack::API DF("Memory.xml");
@ -86,6 +92,23 @@ int main (int argc, const char* argv[])
} }
Maps->getSize(x_max,y_max,z_max); Maps->getSize(x_max,y_max,z_max);
if(!Maps->ReadGlobalFeatures(global_features))
{
cerr << "Can't get global features." << endl;
#ifndef LINUX_BUILD
cin.ignore();
#endif
return 1;
}
if(!Maps->ReadLocalFeatures(local_features))
{
cerr << "Can't get local features." << endl;
#ifndef LINUX_BUILD
cin.ignore();
#endif
return 1;
}
// get stone matgloss mapping // get stone matgloss mapping
if(!Mats->ReadInorganicMaterials(stonetypes)) if(!Mats->ReadInorganicMaterials(stonetypes))
{ {
@ -122,8 +145,9 @@ int main (int argc, const char* argv[])
continue; continue;
// read data // read data
Maps->ReadTileTypes(x,y,z, &tiletypes); Maps->ReadBlock40d(x,y,z, &Block);
Maps->ReadDesignations(x,y,z, &designations); //Maps->ReadTileTypes(x,y,z, &tiletypes);
//Maps->ReadDesignations(x,y,z, &designations);
memset(tempvein, -1, sizeof(tempvein)); memset(tempvein, -1, sizeof(tempvein));
veins.clear(); veins.clear();
@ -131,24 +155,24 @@ int main (int argc, const char* argv[])
if(showbaselayers) if(showbaselayers)
{ {
Maps->ReadRegionOffsets(x,y,z, &regionoffsets); //Maps->ReadRegionOffsets(x,y,z, &regionoffsets);
// get the layer materials // get the layer materials
for(uint32_t xx = 0;xx<16;xx++) for(uint32_t xx = 0;xx<16;xx++)
{ {
for (uint32_t yy = 0; yy< 16;yy++) for (uint32_t yy = 0; yy< 16;yy++)
{ {
uint8_t test = designations[xx][yy].bits.biome; uint8_t test = Block.designation[xx][yy].bits.biome;
if(test > maximum_regionoffset) if(test > maximum_regionoffset)
maximum_regionoffset = test; maximum_regionoffset = test;
if( test >= sizeof(regionoffsets)) if( test >= sizeof(Block.biome_indices))
{ {
num_overflows++; num_overflows++;
continue; continue;
} }
tempvein[xx][yy] = tempvein[xx][yy] =
layerassign layerassign
[regionoffsets[test]] [Block.biome_indices[test]]
[designations[xx][yy].bits.geolayer_index]; [Block.designation[xx][yy].bits.geolayer_index];
} }
} }
} }
@ -172,6 +196,56 @@ int main (int argc, const char* argv[])
} }
} }
} }
// global feature overrides
int16_t idx = Block.global_feature;
if( idx != -1 && uint16_t(idx) < global_features.size() && global_features[idx].type == DFHack::feature_Underworld)
{
for(uint32_t xi = 0 ; xi< 16 ; xi++) for(uint32_t yi = 0 ; yi< 16 ; yi++)
{
if(Block.designation[xi][yi].bits.feature_global)
{
if(global_features[idx].main_material == 0) // stone
{
tempvein[xi][yi] = global_features[idx].sub_material;
}
else
{
tempvein[xi][yi] = -1;
}
}
}
}
idx = Block.local_feature;
if( idx != -1 )
{
DFHack::planecoord pc;
pc.dim.x = x;
pc.dim.y = y;
std::map <DFHack::planecoord, std::vector<DFHack::t_feature *> >::iterator it;
it = local_features.find(pc);
if(it != local_features.end())
{
std::vector<DFHack::t_feature *>& vectr = (*it).second;
if(uint16_t(idx) < vectr.size() && vectr[idx]->type == DFHack::feature_Adamantine_Tube)
for(uint32_t xi = 0 ; xi< 16 ; xi++) for(uint32_t yi = 0 ; yi< 16 ; yi++)
{
if(Block.designation[xi][yi].bits.feature_local && DFHack::isWallTerrain(Block.tiletypes[xi][yi]))
{
if(vectr[idx]->main_material == 0) // stone
{
tempvein[xi][yi] = vectr[idx]->sub_material;
}
else
{
tempvein[xi][yi] = -1;
}
}
}
}
}
// count the material types // count the material types
for(uint32_t xi = 0 ; xi< 16 ; xi++) for(uint32_t xi = 0 ; xi< 16 ; xi++)
{ {
@ -179,7 +253,7 @@ int main (int argc, const char* argv[])
{ {
// hidden tiles are ignored unless '-a' is provided on the command line // hidden tiles are ignored unless '-a' is provided on the command line
// non-wall tiles are ignored // non-wall tiles are ignored
if( (designations[xi][yi].bits.hidden && !showhidden) || !DFHack::isWallTerrain(tiletypes[xi][yi])) if( (Block.designation[xi][yi].bits.hidden && !showhidden) || !DFHack::isWallTerrain(Block.tiletypes[xi][yi]))
continue; continue;
if(tempvein[xi][yi] < 0) if(tempvein[xi][yi] < 0)
continue; continue;
@ -199,7 +273,7 @@ int main (int argc, const char* argv[])
} }
// print report // print report
cout << "Maximal regionoffset seen: " << maximum_regionoffset << "."; cout << "Maximal regionoffset seen: " << maximum_regionoffset << ".";
if(maximum_regionoffset >= sizeof(regionoffsets) ) if(maximum_regionoffset >= sizeof(Block.biome_indices) )
{ {
cout << " This is above the regionoffsets array size!" << endl; cout << " This is above the regionoffsets array size!" << endl;
cout << "Number of overflows: " << num_overflows; cout << "Number of overflows: " << num_overflows;
@ -209,7 +283,14 @@ int main (int argc, const char* argv[])
map<int16_t, uint32_t>::iterator p; map<int16_t, uint32_t>::iterator p;
for(p = materials.begin(); p != materials.end(); p++) for(p = materials.begin(); p != materials.end(); p++)
{ {
cout << stonetypes[p->first].id << " : " << p->second << endl; if(p->first == -1)
{
cout << "Non-stone" << " : " << p->second << endl;
}
else
{
cout << stonetypes[p->first].id << " : " << p->second << endl;
}
} }
DF.Detach(); DF.Detach();
#ifndef LINUX_BUILD #ifndef LINUX_BUILD