implements findnameindexes

develop
belal 2010-02-19 10:36:54 -05:00
commit 8d78822f3d
16 changed files with 885 additions and 182 deletions

20
.gitignore vendored

@ -0,0 +1,20 @@
# linux backup files
*~
# compiled binaries
output/*
# this one is important, track it
!output/Memory.xml
# a file generated by cmake
library/config.h
# any build folders
build*/
#except for the real one
!build/
#ignore Kdevelop stuff
.kdev4

1
build/.gitignore vendored

@ -0,0 +1 @@
build-real

@ -37,11 +37,6 @@ TARGET_LINK_LIBRARIES(dfsuspend dfhack)
ADD_EXECUTABLE(dfitemdump dfitemdump.cpp)
TARGET_LINK_LIBRARIES(dfitemdump dfhack)
# digger - designate for digging by tile class
# Author: mizipzor
ADD_EXECUTABLE(dfdigger digger.cpp)
TARGET_LINK_LIBRARIES(dfdigger dfhack)
# hotkeynotedump - dumps the hotkeys and notes for the loaded map
# Author: belal
ADD_EXECUTABLE(dfhotkeynotedump hotkeynotedump.cpp)
@ -63,7 +58,6 @@ dfattachtest
dfbuildingsdump
dfcreaturedump
dfitemdump
dfdigger
dfexpbench
dfmaterialtest
dfposition

@ -1,110 +0,0 @@
// digger.cpp
// Usage: Call with a list of TileClass ids separated by a space,
// every (visible) tile on the map with that id will be designated for digging.
// NOTE currently only works with trees
// TODO add a sort of "sub-target" to dig() to make it able to designate stone as well
// TODO add proper cli
// TODO add interactive text based menu
#include <iostream>
#include <integers.h>
#include <vector>
#include <list>
#include <cstdlib>
using namespace std;
#include <DFTypes.h>
#include <DFTileTypes.h>
#include <DFHackAPI.h>
int vec_count(vector<uint16_t>& vec, uint16_t t)
{
int count = 0;
for (uint32_t i = 0; i < vec.size(); ++i)
{
if (vec[i] == t)
++count;
}
return count;
}
int dig(DFHack::API& DF, vector<uint16_t>& targets)
{
uint32_t x_max,y_max,z_max;
DFHack::t_designation designations[256];
uint16_t tiles[256];
uint32_t count = 0;
DF.getSize(x_max,y_max,z_max);
// 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);
// check all tiles, if type is in target list and its visible: designate for dig
for (uint32_t i = 0; i < 256; i++)
{
if (designations[i].bits.hidden == 0 &&
vec_count(targets, DFHack::tileTypeTable[tiles[i]].c) > 0)
{
//cout << "target found at: ";
//cout << x << "," << y << "," << z << "," << i << endl;
designations[i].bits.dig = DFHack::designation_default;
++count;
}
}
// write the designations back
// could probably be optimized in the cases where we dont changed anything
DF.WriteDesignations(x,y,z, (uint32_t *) designations);
}
}
}
}
return count;
}
int main (int argc, const char* argv[])
{
vector<uint16_t> targets;
for (int i = 1; i < argc; ++i)
{
targets.push_back(atoi(argv[i]));
}
if (targets.size() == 0)
{
cout << "Usage: Call with a list of TileClass ids separated by a space,\n";
cout << "every (visible) tile on the map with that id will be designated for digging.\n\n";
}
else
{
DFHack::API DF("Memory.xml");
if(!DF.Attach())
{
cerr << "DF not found" << endl;
return 1;
}
DF.InitMap();
int count = dig(DF, targets); // <-- important part
cout << count << " targets designated" << endl;
DF.Detach();
}
#ifndef LINUX_BUILD
cout << "Done. Press any key to continue" << endl;
cin.ignore();
#endif
return 0;
}

@ -272,11 +272,12 @@ main(int argc, char *argv[])
finish(0);
}
// FIXME: could fail on small forts
int cursorX = x_max/2 - 1;
int cursorY = y_max/2 - 1;
int cursorZ = z_max/2 - 1;
// FIXME: could fail on small forts
int vein = 0;
// walk the map!
@ -318,13 +319,15 @@ main(int argc, char *argv[])
cursorY = max(cursorY, 0);
cursorZ = max(cursorZ, 0);
cursorX = min(cursorX, x_max - 3);
cursorY = min(cursorY, y_max - 3);
cursorZ = min(cursorZ, z_max - 3);
cursorX = min(cursorX, x_max - 1);
cursorY = min(cursorY, y_max - 1);
cursorZ = min(cursorZ, z_max - 1);
DF.Suspend();
for(int i = 0; i < 3; i++)
for(int j = 0; j < 3; j++)
for(int i = -1; i <= 1; i++)
{
for(int j = -1; j <= 1; j++)
{
if(DF.isValidBlock(cursorX+i,cursorY+j,cursorZ))
{
// read data
@ -338,22 +341,24 @@ main(int argc, char *argv[])
color = pickColor(tiletypes[x][y]);
if(designations[x][y].bits.hidden)
{
puttile(x+i*16,y+j*16,tiletypes[x][y], color);
puttile(x+(i+1)*16,y+(j+1)*16,tiletypes[x][y], color);
}
else
{
attron(A_STANDOUT);
puttile(x+i*16,y+j*16,tiletypes[x][y], color);
puttile(x+(i+1)*16,y+(j+1)*16,tiletypes[x][y], color);
attroff(A_STANDOUT);
}
}
}
if(i == 1 && j == 1)
if(i == 0 && j == 0)
{
veinVector.clear();
DF.ReadVeins(cursorX+i,cursorY+j,cursorZ,veinVector);
}
}
}
}
gotoxy(0,48);
cprintf("arrow keys, PGUP, PGDN = navigate");
gotoxy(0,49);
@ -361,7 +366,7 @@ main(int argc, char *argv[])
gotoxy(0,50);
if(vein == veinVector.size()) vein = veinVector.size() - 1;
if(vein < -1) vein = -1;
cprintf("X %d/%d, Y %d/%d, Z %d/%d. Vein %d of %d",cursorX + 1,x_max,cursorY + 1,y_max,cursorZ + 1,z_max,vein+1,veinVector.size());
cprintf("X %d/%d, Y %d/%d, Z %d/%d. Vein %d of %d",cursorX+1,x_max,cursorY+1,y_max,cursorZ,z_max,vein+1,veinVector.size());
if(!veinVector.empty())
{
if(vein != -1 && vein < veinVector.size())
@ -402,6 +407,8 @@ main(int argc, char *argv[])
}
}
}
gotoxy(0,52);
cprintf("%s",stonetypes[veinVector[vein].type].name);
}
gotoxy(0,51);
cprintf("%s, address 0x%x",str.c_str(),veinVector[vein].address_of);

@ -19,6 +19,8 @@ md5/md5wrapper.h
tinyxml/tinystr.h
tinyxml/tinyxml.h
gopt/gopt.h
../shmserver/shms.h
)
@ -33,6 +35,7 @@ tinyxml/tinystr.cpp
tinyxml/tinyxml.cpp
tinyxml/tinyxmlerror.cpp
tinyxml/tinyxmlparser.cpp
gopt/gopt.c
)
SET(PROJECT_HDRS_LINUX

@ -83,14 +83,14 @@ public:
uint32_t item_material_offset;
uint32_t note_foreground_offset;
uint32_t note_background_offset;
uint32_t note_name_offset;
uint32_t note_xyz_offset;
uint32_t hotkey_start;
uint32_t hotkey_mode_offset;
uint32_t hotkey_xyz_offset;
uint32_t hotkey_size;
uint32_t note_foreground_offset;
uint32_t note_background_offset;
uint32_t note_name_offset;
uint32_t note_xyz_offset;
uint32_t hotkey_start;
uint32_t hotkey_mode_offset;
uint32_t hotkey_xyz_offset;
uint32_t hotkey_size;
uint32_t dwarf_lang_table_offset;
@ -107,8 +107,8 @@ public:
bool cursorWindowInited;
bool viewSizeInited;
bool itemsInited;
bool notesInited;
bool hotkeyInited;
bool notesInited;
bool hotkeyInited;
bool nameTablesInited;
@ -118,7 +118,7 @@ public:
DfVector *p_bld;
DfVector *p_veg;
DfVector *p_itm;
DfVector *p_notes;
DfVector *p_notes;
};
API::API (const string path_to_xml)
@ -134,8 +134,8 @@ API::API (const string path_to_xml)
d->cursorWindowInited = false;
d->viewSizeInited = false;
d->itemsInited = false;
d->notesInited = false;
d->hotkeyInited = false;
d->notesInited = false;
d->hotkeyInited = false;
d->pm = NULL;
}
@ -221,9 +221,18 @@ bool API::DestroyMap()
bool API::isValidBlock (uint32_t x, uint32_t y, uint32_t z)
{
if (x < 0 || x >= d->x_block_count || y < 0 || y >= d->y_block_count || z < 0 || z >= d->z_block_count)
return false;
return d->block[x*d->y_block_count*d->z_block_count + y*d->z_block_count + z] != 0;
}
uint32_t API::getBlockPtr (uint32_t x, uint32_t y, uint32_t z)
{
if (x < 0 || x >= d->x_block_count || y < 0 || y >= d->y_block_count || z < 0 || z >= d->z_block_count)
return 0;
return d->block[x*d->y_block_count*d->z_block_count + y*d->z_block_count + z];
}
// 256 * sizeof(uint16_t)
bool API::ReadTileTypes (uint32_t x, uint32_t y, uint32_t z, uint16_t *buffer)
{
@ -851,7 +860,7 @@ bool API::InitReadCreatures( uint32_t &numcreatures )
&& d->creature_labors_offset
&& d->creature_happiness_offset
&& d->creature_traits_offset
// && d->creature_likes_offset
// && d->creature_likes_offset
)
{
d->p_cre = new DfVector (d->p->readVector (creatures, 4));
@ -872,9 +881,9 @@ bool API::InitReadNotes( uint32_t &numnotes )
memory_info * minfo = d->offset_descriptor;
int notes = d->offset_descriptor->getAddress ("notes");
d->note_foreground_offset = minfo->getOffset ("note_foreground");
d->note_background_offset = minfo->getOffset ("note_background");
d->note_name_offset = minfo->getOffset ("note_name");
d->note_xyz_offset = minfo->getOffset ("note_xyz");
d->note_background_offset = minfo->getOffset ("note_background");
d->note_name_offset = minfo->getOffset ("note_name");
d->note_xyz_offset = minfo->getOffset ("note_xyz");
if (notes
&& d->note_foreground_offset
@ -901,25 +910,25 @@ bool API::ReadNote (const int32_t &index, t_note & note)
assert (d->notesInited);
// read pointer from vector at position
uint32_t temp = * (uint32_t *) d->p_notes->at (index);
note.symbol = g_pProcess->readByte(temp);
note.foreground = g_pProcess->readWord(temp + d->note_foreground_offset);
note.background = g_pProcess->readWord(temp + d->note_background_offset);
d->p->readSTLString (temp + d->note_name_offset, note.name, 128);
g_pProcess->read (temp + d->note_xyz_offset, 3*sizeof (uint16_t), (uint8_t *) &note.x);
return true;
note.symbol = g_pProcess->readByte(temp);
note.foreground = g_pProcess->readWord(temp + d->note_foreground_offset);
note.background = g_pProcess->readWord(temp + d->note_background_offset);
d->p->readSTLString (temp + d->note_name_offset, note.name, 128);
g_pProcess->read (temp + d->note_xyz_offset, 3*sizeof (uint16_t), (uint8_t *) &note.x);
return true;
}
bool API::InitReadHotkeys( )
{
memory_info * minfo = d->offset_descriptor;
d->hotkey_start = minfo->getAddress("hotkey_start");
d->hotkey_start = minfo->getAddress("hotkey_start");
d->hotkey_mode_offset = minfo->getOffset ("hotkey_mode");
d->hotkey_xyz_offset = minfo->getOffset("hotkey_xyz");
d->hotkey_size = minfo->getHexValue("hotkey_size");
d->hotkey_xyz_offset = minfo->getOffset("hotkey_xyz");
d->hotkey_size = minfo->getHexValue("hotkey_size");
if (d->hotkey_start && d->hotkey_mode_offset && d->hotkey_size)
{
d->hotkeyInited = true;
return true;
d->hotkeyInited = true;
return true;
}
else
{
@ -930,15 +939,15 @@ bool API::InitReadHotkeys( )
bool API::ReadHotkeys(t_hotkey hotkeys[])
{
assert (d->hotkeyInited);
uint32_t currHotkey = d->hotkey_start;
for(uint32_t i = 0 ; i < NUM_HOTKEYS ;i++)
{
d->p->readSTLString(currHotkey,hotkeys[i].name,10);
hotkeys[i].mode = g_pProcess->readWord(currHotkey+d->hotkey_mode_offset);
g_pProcess->read (currHotkey + d->hotkey_xyz_offset, 3*sizeof (int32_t), (uint8_t *) &hotkeys[i].x);
currHotkey+=d->hotkey_size;
}
return true;
uint32_t currHotkey = d->hotkey_start;
for(uint32_t i = 0 ; i < NUM_HOTKEYS ;i++)
{
d->p->readSTLString(currHotkey,hotkeys[i].name,10);
hotkeys[i].mode = g_pProcess->readWord(currHotkey+d->hotkey_mode_offset);
g_pProcess->read (currHotkey + d->hotkey_xyz_offset, 3*sizeof (int32_t), (uint8_t *) &hotkeys[i].x);
currHotkey+=d->hotkey_size;
}
return true;
}
// returns index of creature actually read or -1 if no creature can be found
int32_t API::ReadCreatureInBox (int32_t index, t_creature & furball,

@ -128,6 +128,10 @@ namespace DFHack
* Return false/0 on failure, buffer allocated by client app, 256 items long
*/
bool isValidBlock(uint32_t blockx, uint32_t blocky, uint32_t blockz);
/**
* Get the address of a block or 0 if block is not valid
*/
uint32_t getBlockPtr (uint32_t x, uint32_t y, uint32_t z);
bool ReadTileTypes(uint32_t blockx, uint32_t blocky, uint32_t blockz, uint16_t *buffer); // 256 * sizeof(uint16_t)
bool WriteTileTypes(uint32_t blockx, uint32_t blocky, uint32_t blockz, uint16_t *buffer); // 256 * sizeof(uint16_t)
@ -172,12 +176,12 @@ namespace DFHack
bool InitViewAndCursor();
bool InitReadNotes( uint32_t & numnotes );
bool ReadNote(const int32_t &index, t_note & note);
void FinishReadNotes();
bool InitReadNotes( uint32_t & numnotes );
bool ReadNote(const int32_t &index, t_note & note);
void FinishReadNotes();
bool InitReadHotkeys( );
bool ReadHotkeys(t_hotkey hotkeys[]);
bool InitReadHotkeys( );
bool ReadHotkeys(t_hotkey hotkeys[]);
bool getViewCoords (int32_t &x, int32_t &y, int32_t &z);
bool setViewCoords (const int32_t &x, const int32_t &y, const int32_t &z);

@ -73,7 +73,7 @@ bool ProcessEnumerator::findProcessess()
if(p->isIdentified())
{
d->processes.push_back(p);
return true;
return true;
}
else
{
@ -103,7 +103,7 @@ bool ProcessEnumerator::findProcessess()
else
{
//FIXME delete q;
q = 0;
q = 0;
}
}
if(d->processes.size())

@ -756,22 +756,22 @@ struct t_viewscreen
struct t_note
{
char symbol;
uint16_t foreground;
uint16_t background;
char name[128];
uint16_t x;
uint16_t y;
uint16_t z;
uint16_t foreground;
uint16_t background;
char name[128];
uint16_t x;
uint16_t y;
uint16_t z;
};
#define NUM_HOTKEYS 16
struct t_hotkey
{
char name[10];
int16_t mode;
int32_t x;
int32_t y;
int32_t z;
char name[10];
int16_t mode;
int32_t x;
int32_t y;
int32_t z;
};
}// namespace DFHack

@ -0,0 +1,265 @@
/* gopt.c version 8.1: tom.viza@gmail.com PUBLIC DOMAIN 2003-8 */
/*
I, Tom Vajzovic, am the author of this software and its documentation and
permanently abandon all copyright and other intellectual property rights in
them, including the right to be identified as the author.
I am fairly certain that this software does what the documentation says it
does, but I cannot guarantee that it does, or that it does what you think it
should, and I cannot guarantee that it will not have undesirable side effects.
You are free to use, modify and distribute this software as you please, but
you do so at your own risk. If you remove or hide this warning then you are
responsible for any problems encountered by people that you make the software
available to.
Before modifying or distributing this software I ask that you would please
read http://www.purposeful.co.uk/tfl/
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "gopt.h"
#ifdef USE_SYSEXITS
#include <sysexits.h>
#else
#define EX_OSERR EXIT_FAILURE
#define EX_USAGE EXIT_FAILURE
#endif
struct opt_spec_s {
int key;
int flags;
const char *shorts;
const char* const *longs;
};
typedef struct opt_spec_s opt_spec_t;
struct opt_s {
int key;
const char *arg;
};
typedef struct opt_s opt_t;
void *gopt_sort( int *argc, const char **argv, const void *opt_specs ){
void *opts;
{{{
const char* const *arg_p= argv + 1;
size_t opt_count= 1;
for( ; *arg_p; ++arg_p )
if( '-' == (*arg_p)[0] && (*arg_p)[1] )
if( '-' == (*arg_p)[1] )
if( (*arg_p)[2] )
++opt_count;
else
break;
else {
const opt_spec_t *opt_spec_p= (const opt_spec_t*)opt_specs;
for( ; opt_spec_p-> key; ++opt_spec_p )
if( strchr( opt_spec_p-> shorts, (*arg_p)[1] )){
opt_count+= opt_spec_p-> flags & GOPT_ARG ? 1 : strlen( (*arg_p) + 1 );
break;
}
}
opts= malloc( opt_count * sizeof(opt_t) );
}}}
{
const char **arg_p= argv + 1;
const char **next_operand= arg_p;
opt_t *next_option= (opt_t*)opts;
if( ! opts ){
perror( argv[0] );
exit( EX_OSERR );
}
for( ; *arg_p; ++arg_p )
if( '-' == (*arg_p)[0] && (*arg_p)[1] )
if( '-' == (*arg_p)[1] )
if( (*arg_p)[2] )
{{{
const opt_spec_t *opt_spec_p= (const opt_spec_t*)opt_specs;
const char* const *longs= opt_spec_p-> longs;
next_option-> key= 0;
while( *longs ){
const char *option_cp= (*arg_p) + 2;
const char *name_cp= *longs;
while( *option_cp && *option_cp == *name_cp ){
++option_cp;
++name_cp;
}
if( '=' == *option_cp || !*option_cp ){
if( *name_cp ){
if( next_option-> key ){
fprintf( stderr, "%s: --%.*s: abbreviated option is ambiguous\n", argv[0], (int)( option_cp -( (*arg_p) + 2 )), (*arg_p) + 2 );
free( opts );
exit( EX_USAGE );
}
next_option-> key= opt_spec_p-> key;
}
else {
next_option-> key= opt_spec_p-> key;
goto found_long;
}
}
if( !*++longs ){
++opt_spec_p;
if( opt_spec_p-> key )
longs= opt_spec_p-> longs;
}
}
if( ! next_option-> key ){
fprintf( stderr, "%s: --%.*s: unknown option\n", argv[0], (int)strcspn( (*arg_p) + 2, "=" ), (*arg_p) + 2 );
free( opts );
exit( EX_USAGE );
}
for( opt_spec_p= (const opt_spec_t*)opt_specs; opt_spec_p-> key != next_option-> key; ++opt_spec_p );
found_long:
if( !( opt_spec_p-> flags & GOPT_REPEAT )){
const opt_t *opt_p= (const opt_t*)opts;
for( ; opt_p != next_option; ++opt_p )
if( opt_p-> key == opt_spec_p-> key ){
fprintf( stderr, "%s: --%.*s: option may not be repeated (in any long or short form)\n", argv[0], (int)strcspn( (*arg_p) + 2, "=" ), (*arg_p) + 2 );
free( opts );
exit( EX_USAGE );
}
}
if( opt_spec_p-> flags & GOPT_ARG ){
next_option-> arg= strchr( (*arg_p) + 2, '=' ) + 1;
if( (char*)0 + 1 == next_option-> arg ){
++arg_p;
if( !*arg_p || '-' == (*arg_p)[0] && (*arg_p)[1] ){
fprintf( stderr, "%s: --%s: option requires an option argument\n", argv[0], (*(arg_p-1)) + 2 );
free( opts );
exit( EX_USAGE );
}
next_option-> arg= *arg_p;
}
}
else {
if( strchr( (*arg_p) + 2, '=' )){
fprintf( stderr, "%s: --%.*s: option may not take an option argument\n", argv[0], (int)strcspn( (*arg_p) + 2, "=" ), (*arg_p) + 2 );
free( opts );
exit( EX_USAGE );
}
next_option-> arg= NULL;
}
++next_option;
}}}
else {
for( ++arg_p; *arg_p; ++arg_p )
*next_operand++= *arg_p;
break;
}
else
{{{
const char *short_opt= (*arg_p) + 1;
for( ;*short_opt; ++short_opt ){
const opt_spec_t *opt_spec_p= (const opt_spec_t*)opt_specs;
for( ; opt_spec_p-> key; ++opt_spec_p )
if( strchr( opt_spec_p-> shorts, *short_opt )){
if( !( opt_spec_p-> flags & GOPT_REPEAT )){
const opt_t *opt_p= (const opt_t*)opts;
for( ; opt_p != next_option; ++opt_p )
if( opt_p-> key == opt_spec_p-> key ){
fprintf( stderr, "%s: -%c: option may not be repeated (in any long or short form)\n", argv[0], *short_opt );
free( opts );
exit( EX_USAGE );
}
}
next_option-> key= opt_spec_p-> key;
if( opt_spec_p-> flags & GOPT_ARG ){
if( short_opt[1] )
next_option-> arg= short_opt + 1;
else {
++arg_p;
if( !*arg_p || '-' == (*arg_p)[0] && (*arg_p)[1] ){
fprintf( stderr, "%s: -%c: option requires an option argument\n", argv[0], *short_opt );
free( opts );
exit( EX_USAGE );
}
next_option-> arg= *arg_p;
}
++next_option;
goto break_2;
}
next_option-> arg= NULL;
++next_option;
goto continue_2;
}
fprintf( stderr, "%s: -%c: unknown option\n", argv[0], *short_opt );
free( opts );
exit( EX_USAGE );
continue_2: 0;
}
break_2: 0;
}}}
else
*next_operand++= *arg_p;
next_option-> key= 0;
*next_operand= NULL;
*argc= next_operand - argv;
}
return opts;
}
size_t gopt( const void *vptr_opts, int key ){
const opt_t *opts= (const opt_t*)vptr_opts;
size_t count= 0;
for( ; opts-> key; ++opts )
count+= opts-> key == key;
return count;
}
size_t gopt_arg( const void *vptr_opts, int key, const char **arg ){
const opt_t *opts= (const opt_t*)vptr_opts;
size_t count= 0;
for( ; opts-> key; ++opts )
if( opts-> key == key ){
if( ! count )
*arg= opts-> arg;
++count;
}
return count;
}
const char *gopt_arg_i( const void *vptr_opts, int key, size_t i ){
const opt_t *opts= (const opt_t*)vptr_opts;
for( ; opts-> key; ++opts )
if( opts-> key == key ){
if( ! i )
return opts-> arg;
--i;
}
return NULL;
}
size_t gopt_args( const void *vptr_opts, int key, const char **args, size_t args_len ){
const char **args_stop= args + args_len;
const char **args_ptr= args;
const opt_t *opts= (const opt_t*)vptr_opts;
for( ; opts-> key; ++opts )
if( opts-> key == key ){
if( args_stop == args_ptr )
return args_len + gopt( opts, key );
*args_ptr++= opts-> arg;
}
if( args_stop != args_ptr )
*args_ptr= NULL;
return args_ptr - args;
}
void gopt_free( void *vptr_opts ){
free( vptr_opts );
}

@ -0,0 +1,60 @@
/* gopt.h version 8.1: tom.viza@gmail.com PUBLIC DOMAIN 2003-8 */
/*
I, Tom Vajzovic, am the author of this software and its documentation and
permanently abandon all copyright and other intellectual property rights in
them, including the right to be identified as the author.
I am fairly certain that this software does what the documentation says it
does, but I cannot guarantee that it does, or that it does what you think it
should, and I cannot guarantee that it will not have undesirable side effects.
You are free to use, modify and distribute this software as you please, but
you do so at your own risk. If you remove or hide this warning then you are
responsible for any problems encountered by people that you make the software
available to.
Before modifying or distributing this software I ask that you would please
read http://www.purposeful.co.uk/tfl/
*/
#ifndef GOPT_H_INCLUDED
#define GOPT_H_INCLUDED
#define GOPT_ONCE 0
#define GOPT_REPEAT 1
#define GOPT_NOARG 0
#define GOPT_ARG 2
#define gopt_start(...) (const void*)( const struct { int k; int f; const char *s; const char*const*l; }[]){ __VA_ARGS__, {0}}
#define gopt_option(k,f,s,l) { k, f, s, l }
#define gopt_shorts( ... ) (const char*)(const char[]){ __VA_ARGS__, 0 }
#define gopt_longs( ... ) (const char**)(const char*[]){ __VA_ARGS__, NULL }
void *gopt_sort( int *argc, const char **argv, const void *opt_specs );
/* returns a pointer for use in the following calls
* prints to stderr and call exit() on error
*/
size_t gopt( const void *opts, int key );
/* returns the number of times the option was specified
* which will be 0 or 1 unless GOPT_REPEAT was used
*/
size_t gopt_arg( const void *opts, int key, const char **arg );
/* returns the number of times the option was specified
* writes a pointer to the option argument from the first (or only) occurance to *arg
*/
const char *gopt_arg_i( const void *opts, int key, size_t i );
/* returns a pointer to the ith (starting at zero) occurance
* of the option, or NULL if it was not specified that many times
*/
size_t gopt_args( const void *opts, int key, const char **args, size_t args_len );
/* returns the number of times the option was specified
* writes pointers to the option arguments in the order of occurance to args[].
* writes at most args_len pointers
* if the return value is less than args_len, also writes a null pointer
*/
void gopt_free( void *opts );
/* releases memory allocated in the corresponding call to gopt_sort()
* opts can no longer be used
*/
#endif /* GOPT_H_INCLUDED */

3
output/.gitignore vendored

@ -0,0 +1,3 @@
Debug
Release
RelWithDebInfo

@ -26,10 +26,19 @@ TARGET_LINK_LIBRARIES(dfincremental dfhack)
ADD_EXECUTABLE(dfbauxite dfbauxite.cpp)
TARGET_LINK_LIBRARIES(dfbauxite dfhack)
# digger - designate for digging by tile class
# Author: mizipzor
ADD_EXECUTABLE(dfdigger digger.cpp)
TARGET_LINK_LIBRARIES(dfdigger dfhack)
# itemdesignator - change some item designations (dump, forbid, on-fire) for all items of a given type and material
ADD_EXECUTABLE(dfitemdesignator itemdesignator.cpp)
TARGET_LINK_LIBRARIES(dfitemdesignator dfhack)
ADD_EXECUTABLE(dffindnameindexes findnameindexes.cpp)
TARGET_LINK_LIBRARIES(dffindnameindexes dfhack)
IF(UNIX)
install(TARGETS
dfreveal

@ -0,0 +1,354 @@
// digger.cpp
// Usage: Call with a list of TileClass ids separated by a space,
// every (visible) tile on the map with that id will be designated for digging.
// NOTE currently only works with trees
// TODO add a sort of "sub-target" to dig() to make it able to designate stone as well
// TODO add proper cli
// TODO add interactive text based menu
// TODO add ability to mark num closest to cursor
#include <iostream>
#include <integers.h>
#include <vector>
#include <list>
#include <cstdlib>
#include <algorithm>
#include <assert.h>
using namespace std;
#include <DFTypes.h>
#include <DFTileTypes.h>
#include <DFHackAPI.h>
int vec_count(vector<uint16_t>& vec, uint16_t t)
{
int count = 0;
for (uint32_t i = 0; i < vec.size(); ++i)
{
if (vec[i] == t)
++count;
}
return count;
}
//// manhattan distance
//int source_distance(int sx, int sy, int sz,
// int x, int y, int z, int i)
//{
// // TODO changing x and y seems to be optimized away (?)
// cout << x << " " << i << " " << i%16 << " " << x+(i%16) << endl;
//
// // handle the fact that x,y,z refers to a 16x16 grid
// //x += i%16;
// //y += i/16;
// int dx = i%16;
// int dy = i/16;
// //x *= 16;
// //y *= 16;
// //x += dx;
// //y += dy;
// return abs(sx-(x+(i%16)))+abs(sy-(y+(i/16)))+abs(sz-z);
//}
int manhattan_distance(int x, int y, int z, int xx, int yy, int zz)
{
return abs(x-xx)+abs(y-yy)+abs(z-zz);
}
struct DigTarget
{
//public:
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) :
//grid_x(realx/16), grid_y(realy/16),
//local_x(realx%16), local_y(realy%16),
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) :
//source_distance(manhattan_distance(
// realx, realy, realz,
// sourcex, sourcey, sourcez)),
grid_x(gridx), grid_y(gridy),
local_x(localx), local_y(localy),
z(_z)
//real_x(realx), real_y(realy), real_z(realz)
{
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 source_distance() const { return _source_distance; }
int grid_x, grid_y;
int local_x, local_y;
int real_x, real_y;
int z;
//int index;
//const bool valid;
bool operator<(const DigTarget& o) const { return source_distance < o.source_distance; }
//private:
// int source_x, source_y, source_z;
// int _source_distance;
};
int dig(DFHack::API& DF,
vector<uint16_t>& targets,
int num = -1,
const int x_source = 0,
const int y_source = 0,
const int z_source = 0)
{
if (num == 0)
return 0; // max limit of 0, nothing to do
uint32_t x_max,y_max,z_max;
DFHack::t_designation designations[16][16];
uint16_t tiles[16][16];
//uint32_t count = 0;
DF.getSize(x_max,y_max,z_max);
// every tile found, will later be sorted by distance to source
vector<DigTarget> candidates;
cout << "============================" << endl;
cout << "source is " << x_source << " " << y_source << " " << z_source << endl;
//int debugmaxx = 0;
//int debugmaxy = 0;
// 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 (z != z_source)
continue; // hack to cut down on targets
if(DF.isValidBlock(x,y,z))
{
// read block designations and tiletype
DF.ReadDesignations(x,y,z, (uint32_t *) designations);
DF.ReadTileTypes(x,y,z, (uint16_t *) tiles);
// 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)
{
//cout << "target found at: ";
//cout << x << "," << y << "," << z << "," << i << endl;
//designations[i].bits.dig = DFHack::designation_default;
//++count;
//int realx = (x*16)+lx;
//int realy = (y*16)+ly;
candidates.push_back(DigTarget(
x, y, z,
lx, ly,
x_source, y_source, z_source));
//cout << "target found at " << world_x << " " << world_y << " " << z;
//cout << ", " << dt->source_distance << " tiles to source" << endl;
//if (world_x > debugmaxx)
// debugmaxx = world_x;
//if (world_y > debugmaxy)
// debugmaxy = world_y;
}
} // local y
} // local x
}
}
}
}
// TODO the following routine doesnt check if the tile is already marked for digging
// if we found more tiles than was requested, sort them by distance to source,
// keep the front 'num' elements and drop the rest
if (num != -1 && candidates.size() > (unsigned int)num)
{
sort(candidates.begin(), candidates.end());
candidates.resize(num);
}
num = candidates.size();
cout << "============================" << endl;
cout << "source is " << x_source << " " << y_source << " " << z_source << endl;
// mark the tiles for actual digging
for (vector<DigTarget>::const_iterator i = candidates.begin(); i != candidates.end(); ++i)
{
//int grid_x = (*i).x/16;
//int grid_y = (*i).y/16;
//int z = (*i).z;
//int local_x = (*i).x%grid_x;
//int local_y = (*i).y%grid_y;
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
// TODO move into function in DigTarget
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);
}
//cout << debugmaxx << " " << debugmaxy << endl;
return num;
}
void test()
{
{
DigTarget dt;
//assert(!dt.valid);
}
{
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);
//assert(dt.valid);
}
{
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);
//assert(dt.valid);
}
//{ // sorting
// DigTarget a(
// 20, 35, 16,
// 10, 12, 14);
// DigTarget b(
// 2, 4, 16,
// 5, 10,
// 10, 12, 14);
// vector<DigTarget> v;
// v.push_back(b);
// v.push_back(a);
// sort(v.begin(), v.end());
// assert(*(v.begin()) == a);
//}
}
int main (int argc, const char* argv[])
{
test();
vector<uint16_t> targets;
for (int i = 1; i < argc; ++i)
{
targets.push_back(atoi(argv[i]));
}
if (targets.size() == 0)
{
cout << "Usage: Call with a list of TileClass ids separated by a space,\n";
cout << "every (visible) tile on the map with that id will be designated for digging.\n\n";
}
else
{
DFHack::API DF("Memory.xml");
if(!DF.Attach())
{
cerr << "DF not found" << endl;
return 1;
}
DF.InitMap();
// TODO hack until we have a proper cli to specify origin
int x_source = 134, y_source = 134, z_source = 16; // my wagon starts here; cut trees close to wagon
//DF.InitViewAndCursor();
//if (!DF.getViewCoords(x_source, y_source, z_source))
//{
// cerr << "Enable cursor" << endl;
// return 1;
//}
int count = dig(DF, targets, 10, x_source, y_source, z_source); // <-- important part
cout << count << " targets designated" << endl;
DF.Detach();
}
#ifndef LINUX_BUILD
cout << "Done. Press any key to continue" << endl;
cin.ignore();
#endif
return 0;
}

@ -0,0 +1,84 @@
// Map cleaner. Removes all the snow, mud spills, blood and vomit from map tiles.
#include <iostream>
#include <iomanip>
#include <integers.h>
#include <vector>
#include <algorithm>
#include <sstream>
using namespace std;
#include <DFTypes.h>
#include <DFHackAPI.h>
// returns a lower case version of the string
string tolower (const string & s)
{
string d (s);
transform (d.begin (), d.end (), d.begin (), (int(*)(int)) tolower);
return d;
}
string groupBy2(const string & s)
{
string d;
for(int i =2;i<s.length();i++){
if(i%2==0)
{
d+= s.substr(i-2,2) + " ";
}
}
d+=s.substr(s.length()-2,2);
return(d);
}
uint32_t endian_swap(uint32_t x)
{
x = (x>>24) |
((x<<8) & 0x00FF0000) |
((x>>8) & 0x0000FF00) |
(x<<24);
return x;
}
int main (void)
{
DFHack::API DF ("Memory.xml");
if(!DF.Attach())
{
cerr << "DF not found" << endl;
return 1;
}
map< string, vector<string> > names;
if(!DF.InitReadNameTables(names))
{
cerr << "Could not get Names" << endl;
return 1;
}
string input;
DF.ForceResume();
cout << "\nSelect Name to search or q to Quit" << endl;
getline (cin, input);
while(input != "q"){
for( map< string, vector<string> >::iterator it = names.begin();it != names.end(); it++){
for(uint32_t i = 0; i < it->second.size(); i++){
uint32_t found = input.find(tolower(it->second[i]));
if(found != string::npos){
stringstream value;
value << setfill('0') << setw(8) << hex << endian_swap(i);
cout << it->first << " " << it->second[i] << " " << groupBy2(value.str()) << endl;
}
}
}
DF.Resume();
getline(cin,input);
}
DF.Detach();
DF.FinishReadNameTables();
#ifndef LINUX_BUILD
cout << "Done. Press any key to continue" << endl;
cin.ignore();
#endif
return 0;
}