diff options
| -rw-r--r-- | .gitignore | 2 | ||||
| -rw-r--r-- | build/build-MinGW32-debug.bat | 8 | ||||
| -rw-r--r-- | build/build-MinGW32-release-trace.bat | 10 | ||||
| -rw-r--r-- | build/build-MinGW32-release.bat | 8 | ||||
| -rw-r--r-- | build/generate-MSVC-2005.bat | 6 | ||||
| -rw-r--r-- | build/generate-MSVC-2008.bat | 6 | ||||
| -rw-r--r-- | build/generate-MSVC-2010.bat | 6 | ||||
| -rw-r--r-- | tools/playground/hellhole.cpp | 2566 | ||||
| -rw-r--r-- | tools/supported/probe.cpp | 336 |
9 files changed, 1474 insertions, 1474 deletions
@@ -29,5 +29,5 @@ dfhack/python/pydfhack/_pydfhack.so dfhack/python/PyDFHack.egg-info dfhack/python/build dfhack/python/dist -
+ /cmakeall.bat
\ No newline at end of file diff --git a/build/build-MinGW32-debug.bat b/build/build-MinGW32-debug.bat index e60ca721..ee622d5f 100644 --- a/build/build-MinGW32-debug.bat +++ b/build/build-MinGW32-debug.bat @@ -1,5 +1,5 @@ -mkdir build-real
-cd build-real
-cmake ..\.. -G"MinGW Makefiles" -DCMAKE_BUILD_TYPE:string=Debug
-mingw32-make
+mkdir build-real +cd build-real +cmake ..\.. -G"MinGW Makefiles" -DCMAKE_BUILD_TYPE:string=Debug +mingw32-make pause
\ No newline at end of file diff --git a/build/build-MinGW32-release-trace.bat b/build/build-MinGW32-release-trace.bat index ca7df86d..f75da5ff 100644 --- a/build/build-MinGW32-release-trace.bat +++ b/build/build-MinGW32-release-trace.bat @@ -1,6 +1,6 @@ -mkdir build-real
-cd build-real
-cmake ..\.. -G"MinGW Makefiles" -DCMAKE_BUILD_TYPE:string=Release --trace > trace-stdout.txt 2> trace-stderr.txt
-mingw32-make 2> log.txt
-pause
+mkdir build-real +cd build-real +cmake ..\.. -G"MinGW Makefiles" -DCMAKE_BUILD_TYPE:string=Release --trace > trace-stdout.txt 2> trace-stderr.txt +mingw32-make 2> log.txt +pause dir file.xxx
\ No newline at end of file diff --git a/build/build-MinGW32-release.bat b/build/build-MinGW32-release.bat index 18e5bcab..dd0dc6b8 100644 --- a/build/build-MinGW32-release.bat +++ b/build/build-MinGW32-release.bat @@ -1,5 +1,5 @@ -mkdir build-real
-cd build-real
-cmake ..\.. -G"MinGW Makefiles" -DCMAKE_BUILD_TYPE:string=Release
-mingw32-make 2> log.txt
+mkdir build-real +cd build-real +cmake ..\.. -G"MinGW Makefiles" -DCMAKE_BUILD_TYPE:string=Release +mingw32-make 2> log.txt pause
\ No newline at end of file diff --git a/build/generate-MSVC-2005.bat b/build/generate-MSVC-2005.bat index a187b466..35451e36 100644 --- a/build/generate-MSVC-2005.bat +++ b/build/generate-MSVC-2005.bat @@ -1,4 +1,4 @@ -mkdir build-real
-cd build-real
-cmake ..\.. -G"Visual Studio 8 2005"
+mkdir build-real +cd build-real +cmake ..\.. -G"Visual Studio 8 2005" pause
\ No newline at end of file diff --git a/build/generate-MSVC-2008.bat b/build/generate-MSVC-2008.bat index 79e95a8c..8d39368b 100644 --- a/build/generate-MSVC-2008.bat +++ b/build/generate-MSVC-2008.bat @@ -1,4 +1,4 @@ -mkdir build-real
-cd build-real
-cmake ..\.. -G"Visual Studio 9 2008"
+mkdir build-real +cd build-real +cmake ..\.. -G"Visual Studio 9 2008" pause
\ No newline at end of file diff --git a/build/generate-MSVC-2010.bat b/build/generate-MSVC-2010.bat index 50828f7e..588051bc 100644 --- a/build/generate-MSVC-2010.bat +++ b/build/generate-MSVC-2010.bat @@ -1,4 +1,4 @@ -mkdir build-real
-cd build-real
-cmake ..\.. -G"Visual Studio 10"
+mkdir build-real +cd build-real +cmake ..\.. -G"Visual Studio 10" pause
\ No newline at end of file diff --git a/tools/playground/hellhole.cpp b/tools/playground/hellhole.cpp index cc12554b..340d5169 100644 --- a/tools/playground/hellhole.cpp +++ b/tools/playground/hellhole.cpp @@ -1,1283 +1,1283 @@ -// Burn a hole straight to hell!
-
-#include <stdlib.h>
-#include <time.h>
-
-#include <iostream>
-#include <vector>
-#include <map>
-#include <stddef.h>
-#include <assert.h>
-#include <math.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdio.h>
-#include <limits.h>
-using namespace std;
-
-#include <DFHack.h>
-#include <dfhack/DFTileTypes.h>
-#include <dfhack/modules/Gui.h>
-using namespace DFHack;
-
-
-#ifdef LINUX_BUILD
-#include <unistd.h>
-void waitmsec (int delay)
-{
- usleep(delay);
-}
-#else
-#include <windows.h>
-void waitmsec (int delay)
-{
- Sleep(delay);
-}
-#endif
-
-#define minmax(MinV,V,MaxV) (max((MinV),min((MaxV),(V))))
-
-//User interaction enums.
-//Pit Type (these only have meaning within hellhole, btw)
-#define PITTYPEMACRO \
- X(pitTypeChasm,"Bottomless Chasm" ) \
- X(pitTypeEerie,"Bottomless Eerie Pit" ) \
- X(pitTypeFloor,"Pit with floor" ) \
- X(pitTypeSolid,"Solid Pillar" ) \
- X(pitTypeOasis,"Oasis Pit (ends at magma, no hell access)" ) \
- X(pitTypeOPool,"Oasis Pool, with partial aquifer (default 5 z-levels)" ) \
- X(pitTypeMagma,"Magma Pit (similar to volcano, no hell access)" ) \
- X(pitTypeMPool,"Magma Pool (default 5 z-levels)" )
-//end PITTYPEMACRO
-
-#define X(name,desc) name,
-enum e_pitType
-{
- pitTypeInvalid=-1,
- PITTYPEMACRO
- pitTypeCount,
-};
-#undef X
-
-
-#define X(name,desc) desc,
-const char * pitTypeDesc[pitTypeCount+1] =
-{
- PITTYPEMACRO
- ""
-};
-#undef X
-
-
-
-
-int getyesno( const char * msg , int default_value )
-{
- const int bufferlen=4;
- static char buf[bufferlen];
- memset(buf,0,bufferlen);
- while (-1)
- {
- if (msg) printf("\n%s (default=%s)\n:" , msg , (default_value?"yes":"no") );
- fflush(stdin);
- fgets(buf,bufferlen,stdin);
- switch (buf[0])
- {
- case 0:
- case 0x0d:
- case 0x0a:
- return default_value;
- case 'y':
- case 'Y':
- case 'T':
- case 't':
- case '1':
- return -1;
- case 'n':
- case 'N':
- case 'F':
- case 'f':
- case '0':
- return 0;
- }
- }
- return 0;
-}
-
-int getint( const char * msg , int min, int max, int default_value ) {
- const int bufferlen=16;
- static char buf[bufferlen];
- int n=0;
- memset(buf,0,bufferlen);
- while (-1)
- {
- if (msg) printf("\n%s (default=%d)\n:" , msg , default_value);
- fflush(stdin);
- fgets(buf,bufferlen,stdin);
- if ( !buf[0] || 0x0a==buf[0] || 0x0d==buf[0] )
- {
- return default_value;
- }
- if ( sscanf(buf,"%d", &n) )
- {
- if (n>=min && n<=max )
- {
- return n;
- }
- }
- }
-}
-
-int getint( const char * msg , int min, int max )
-{
- const int bufferlen=16;
- static char buf[bufferlen];
- int n=0;
- memset(buf,0,bufferlen);
- while (-1)
- {
- if (msg)
- {
- printf("\n%s \n:" , msg );
- }
- fflush(stdin);
- fgets(buf,bufferlen,stdin);
-
- if ( !buf[0] || 0x0a==buf[0] || 0x0d==buf[0] )
- {
- continue;
- }
- if ( sscanf(buf,"%d", &n) )
- {
- if (n>=min && n<=max )
- {
- return n;
- }
- }
- }
-}
-
-
-
-//Interactive, get pit type from user
-e_pitType selectPitType()
-{
- while ( -1 )
- {
- printf("Enter the type of hole to dig:\n" );
- for (int n=0;n<pitTypeCount;++n)
- {
- printf("%2d) %s\n", n, pitTypeDesc[n] );
- }
- printf(":");
- return (e_pitType)getint(NULL, 0, pitTypeCount-1 );
- }
-}
-
-
-void drawcircle(const int radius, unsigned char pattern[16][16], unsigned char v )
-{
- //Small circles get better randomness if handled manually
- if ( 1==radius )
- {
- pattern[7][7]=v;
- if ( (rand()&1) ) pattern[6][7]=v;
- if ( (rand()&1) ) pattern[8][7]=v;
- if ( (rand()&1) ) pattern[7][6]=v;
- if ( (rand()&1) ) pattern[7][8]=v;
-
- }
- else if ( 2==radius )
- {
- pattern[7][7]=v;
- pattern[7][5]=v;
- pattern[7][6]=v;
- pattern[7][8]=v;
- pattern[7][9]=v;
- pattern[6][7]=v;
- pattern[8][7]=v;
- pattern[9][7]=v;
- pattern[6][6]=v;
- pattern[6][8]=v;
- pattern[8][6]=v;
- pattern[8][8]=v;
- pattern[5][7]=v;
-
- if ( (rand()&1) ) pattern[6][5]=v;
- if ( (rand()&1) ) pattern[5][6]=v;
- if ( (rand()&1) ) pattern[8][5]=v;
- if ( (rand()&1) ) pattern[9][6]=v;
- if ( (rand()&1) ) pattern[6][9]=v;
- if ( (rand()&1) ) pattern[5][8]=v;
- if ( (rand()&1) ) pattern[8][9]=v;
- if ( (rand()&1) ) pattern[9][8]=v;
- }
- else
- {
- //radius 3 or larger, simple circle calculation.
- int x,y;
- for (y=0-radius; y<=radius; ++y)
- {
- for (x=0-radius; x<=radius; ++x)
- {
- if (x*x+y*y <= radius*radius + (rand()&31-8) )
- {
- pattern[ minmax(0,7+x,15) ][ minmax(0,7+y,15) ]=v;
- }
- }
- }
- //Prevent boxy patterns with a quick modification on edges
- if (rand()&1) pattern[ 7 ][ minmax(0,7+radius+1,15) ] = v;
- if (rand()&1) pattern[ 7 ][ minmax(0,7-radius-1,15) ] = v;
- if (rand()&1) pattern[ minmax(0,7+radius+1,15) ][ 7 ] = v;
- if (rand()&1) pattern[ minmax(0,7-radius-1,15) ][ 7 ] = v;
- }
-}
-
-//Check all neighbors for a given value n.
-//If found, and v>=0, replace with v.
-//Returns number of neighbors found.
-int checkneighbors(unsigned char pattern[16][16], int x, int y, unsigned char n , char v )
-{
- int r=0;
- if ( x>0 && y>0 && n==pattern[x-1][y-1] )
- {
- ++r;
- if (v>-1) pattern[x][y]=v;
- }
- if ( x>0 && n==pattern[x-1][y ] )
- {
- ++r;
- if (v>-1) pattern[x][y]=v;
- }
- if ( y>0 && n==pattern[x ][y-1] )
- {
- ++r;
- if (v>-1) pattern[x][y]=v;
- }
- if ( x<15 && n==pattern[x+1][y ] )
- {
- ++r;
- if (v>-1) pattern[x][y]=v;
- }
- if ( x<15 && y>0 && n==pattern[x+1][y-1] )
- {
- ++r;
- if (v>-1) pattern[x][y]=v;
- }
- if ( x<15 && y<15 && n==pattern[x+1][y+1] )
- {
- ++r;
- if (v>-1) pattern[x][y]=v;
- }
- if ( y<15 && n==pattern[x ][y+1] )
- {
- ++r;
- if (v>-1) pattern[x][y]=v;
- }
- if ( x>0 && y<15 && n==pattern[x-1][y+1] )
- {
- ++r;
- if (v>-1) pattern[x][y]=v;
- }
- return r;
-}
-//convenience
-int checkneighbors(unsigned char pattern[16][16], int x, int y, unsigned char n )
-{
- return checkneighbors(pattern,x,y,n,-1);
-}
-
-void settileat(unsigned char pattern[16][16], const unsigned char needle, const unsigned char v, const int index )
-{
- int ok=0;
- int safety=256*256;
- int y,x,i=0;
- //Scan for sequential index
- while ( !ok && --safety )
- {
- for (y=0 ; !ok && y<16 ; ++y )
- {
- for (x=0 ; !ok && x<16 ; ++x )
- {
- if ( needle==pattern[x][y] )
- {
- ++i;
- if ( index==i )
- {
- //Got it!
- pattern[x][y]=v;
- ok=-1;
- }
- }
- }
- }
- }
-}
-
-
-//FIXME: good candidate for adding to dfhack. Maybe the Maps should have those cached so they can be queried?
-//Is a given feature present at the given tile?
-int isfeature(
- vector<DFHack::t_feature> global_features,
- std::map <DFHack::planecoord, std::vector<DFHack::t_feature *> > local_features,
- const mapblock40d &block, const planecoord &pc, const int x, const int y, const e_feature Feat
-)
-{
- //const TileRow * tp;
- //tp = getTileTypeP(block.tiletypes[x][y]);
- const t_designation * d;
- d = &block.designation[x][y];
-
- if ( block.local_feature > -1 && d->bits.feature_local ) {
- if ( Feat==local_features[pc][block.local_feature]->type ) return Feat;
- }
- if ( block.global_feature > -1 && d->bits.feature_global ) {
- if ( Feat==global_features[block.global_feature].type ) return Feat;
- }
-
- return 0;
-}
-
-// FIXME: use block cache, break into manageable bits
-int main (void)
-{
- srand ( (unsigned int)time(NULL) );
-
- //Message of intent
- cout <<
- "DF Hole" << endl <<
- "This tool will instantly dig a chasm, pit, pipe, etc through hell, wherever your cursor is." << endl <<
- "This can not be undone! End program now if you don't want hellish fun." << endl
- ;
-
- //User selection of settings should have it own routine, a structure for settings, I know
- //sloppy mess, but this is just a demo utility.
-
- //Pit Types.
- e_pitType pittype = selectPitType();
-
- //Here are all the settings.
- //Default values are set here.
- int pitdepth=0;
- int roof=-1;
- int holeradius=6;
- int wallthickness=1;
- int wallpillar=1;
- int holepillar=1;
- int exposehell = 0;
- int fillmagma=0;
- int fillwater=0;
- int stopatmagma=0;
- int exposemagma=0;
- int aquify=0;
-
- //The Tile Type to use for the walls lining the hole
- //263 is semi-molten rock, 331 is obsidian
- uint32_t whell=263, wmolten=263, wmagma=331, wcave=331;
- //The Tile Type to use for the hole's floor at bottom of the map
- //35 is chasm, 42 is eerie pit , 340 is obsidian floor, 344 is featstone floor, 264 is 'magma flow' floor
- uint32_t floor=35, cap=340;
- int floorvar=0;
-
-
- //Modify default settings based on pit type.
- switch ( pittype )
- {
- case pitTypeChasm:
- floor=35;
- break;
- case pitTypeEerie:
- floor=42;
- break;
- case pitTypeFloor:
- floor=344;
- floorvar=3;
- break;
- case pitTypeSolid:
- holeradius=0;
- wallthickness=7;
- wallpillar=4;
- break;
- case pitTypeOasis:
- stopatmagma=-1;
- fillwater=-1;
- holeradius=5;
- wallthickness=2;
- //aquify=-1;
- floor=340;
- floorvar=3;
- break;
- case pitTypeOPool:
- pitdepth=5;
- fillwater=-1;
- holeradius=5;
- wallthickness=2;
- //aquify=-1;
- floor=340;
- floorvar=3;
- break;
- case pitTypeMagma:
- stopatmagma=-1;
- exposemagma=-1;
- wallthickness=2;
- fillmagma=-1;
- floor=264;
- break;
- case pitTypeMPool:
- pitdepth=5;
- wallthickness=2;
- fillmagma=-1;
- floor=340;
- floorvar=3;
- break;
- }
-
-
- //Should tiles be revealed?
- int reveal=0;
-
-
- int accept = getyesno("Use default settings?",1);
-
- while ( !accept )
- {
- //Pit Depth
- pitdepth = getint( "Enter max depth (0 for bottom of map)", 0, INT_MAX, pitdepth );
-
- //Hole Size
- holeradius = getint( "Enter hole radius, 0 to 16", 0, 16, holeradius );
-
- //Wall thickness
- wallthickness = getint( "Enter wall thickness, 0 to 16", 0, 16, wallthickness );
-
- //Obsidian Pillars
- holepillar = getint( "Number of Obsidian Pillars in hole, 0 to 255", 0, 255, holepillar );
- wallpillar = getint( "Number of Obsidian Pillars in wall, 0 to 255", 0, 255, wallpillar );
-
- //Open Hell?
- exposehell=getyesno("Expose the pit to hell (no walls in hell)?",exposehell);
-
- //Stop when magma sea is hit?
- stopatmagma=getyesno("Stop at magma sea?",stopatmagma);
- exposemagma=getyesno("Expose magma sea (no walls in magma)?",exposemagma);
-
- //Fill?
- fillmagma=getyesno("Fill with magma?",fillmagma);
- if (fillmagma) aquify=fillwater=0;
- fillwater=getyesno("Fill with water?",fillwater);
- //aquify=getyesno("Aquifer?",aquify);
-
-
- ///////////////////////////////////////////////////////////////////////////////////////////////
- //Print settings.
- //If a settings struct existed, this could be in a routine
- printf("Using Settings:\n");
- printf("Pit Type......: %d = %s\n", pittype, pitTypeDesc[pittype]);
- printf("Depth.........: %d\n", pitdepth);
- printf("Hole Radius...: %d\n", holeradius);
- printf("Wall Thickness: %d\n", wallthickness);
- printf("Pillars, Hole.: %d\n", holepillar);
- printf("Pillars, Wall.: %d\n", wallpillar);
- printf("Expose Hell...: %c\n", (exposehell?'Y':'N') );
- printf("Stop at Magma.: %c\n", (stopatmagma?'Y':'N') );
- printf("Expose Magma..: %c\n", (exposemagma?'Y':'N') );
- printf("Magma Fill....: %c\n", (fillmagma?'Y':'N') );
- printf("Water Fill....: %c\n", (fillwater?'Y':'N') );
- printf("Aquifer.......: %c\n", (aquify?'Y':'N') );
-
- accept = getyesno("Accept these settings?",1);
- }
-
-
- int64_t n;
- uint32_t x_max,y_max,z_max;
-
-
- //Pattern to dig
- unsigned char pattern[16][16];
-
-
- for (int regen=1;regen; )
- {
- regen=0;
-
- memset(pattern,0,sizeof(pattern));
-
- //Calculate a randomized circle.
- //These values found through experimentation.
- int x=0, y=0, n=0;
-
- //Two concentric irregular circles
- //Outer circle, solid.
- if ( wallthickness )
- {
- drawcircle(holeradius+wallthickness, pattern, 2);
- }
- //Inner circle, hole.
- if ( holeradius )
- {
- drawcircle(holeradius, pattern, 1);
- }
-
-
- //Post-process to be certain the wall totally encloses hole.
- if (wallthickness)
- {
- for (y=0;y<16;++y)
- {
- for (x=0;x<16;++x)
- {
- if ( 1==pattern[x][y] )
- {
- //No hole at edges.
- if ( x<1 || x>14 || y<1 || y>14 )
- {
- pattern[x][y]=2;
- }
- }
- else if ( 0==pattern[x][y] )
- {
- //check neighbors
- checkneighbors( pattern , x,y, 1, 2);
- }
- }
- }
- }
-
- //Makes sure that somewhere random gets a vertical pillar of rock which is safe
- //to dig stairs down, to permit access to anywhere within the pit from the top.
- for (n=holepillar; n ; --n)
- {
- settileat( pattern , 1 , 3 , rand()&255 );
- }
- for (n=wallpillar; n ; --n)
- {
- settileat( pattern , 2 , 3 , rand()&255 );
- }
-
- //Note:
- //At this point, the pattern holds:
- //0 for all tiles which will be ignored.
- //1 for all tiles set to empty pit space.
- //2 for all normal walls.
- //3 for the straight obsidian top-to-bottom wall.
- //4 is randomized between wall or floor (!not implemented!)
-
- printf("\nPattern:\n");
- const char patternkey[] = ".cW!?567890123";
-
- //Print the pattern
- for (y=0;y<16;++y)
- {
- for (x=0;x<16;++x)
- {
- cout << patternkey[ pattern[x][y] ];
- }
- cout << endl;
- }
- cout << endl;
-
- regen = !getyesno("Acceptable Pattern?",1);
- }
-
- //Post-process settings to fix problems here
- if (pitdepth<1)
- {
- pitdepth=INT_MAX;
- }
-
-
- ///////////////////////////////////////////////////////////////////////////////////////////////
-
-
- cerr << "Loading memory map..." << endl;
-
- //Connect to DF!
- DFHack::ContextManager DFMgr("Memory.xml");
- DFHack::Context *DF = DFMgr.getSingleContext();
-
-
-
- //Init
- cerr << "Attaching to DF..." << endl;
- try
- {
- DF->Attach();
- }
- catch (exception& e)
- {
- cerr << e.what() << endl;
- #ifndef LINUX_BUILD
- cin.ignore();
- #endif
- return 1;
- }
-
- // init the map
- DFHack::Maps *Mapz = DF->getMaps();
- if (!Mapz->Start())
- {
- cerr << "Can't init map. Exiting." << endl;
- #ifndef LINUX_BUILD
- cin.ignore();
- #endif
- return 1;
- }
-
- Mapz->getSize(x_max,y_max,z_max);
-
-
- //Get cursor
- int32_t cursorX, cursorY, cursorZ;
- DFHack::Position *Pos = DF->getPosition();
- Pos->getCursorCoords(cursorX,cursorY,cursorZ);
- if (-30000==cursorX)
- {
- cout << "No cursor position found. Exiting." << endl;
- #ifndef LINUX_BUILD
- cin.ignore();
- #endif
- return 1;
- }
-
- //Block coordinates
- int32_t bx=cursorX/16, by=cursorY/16, bz=cursorZ;
- //Tile coordinates within block
- int32_t tx=cursorX%16, ty=cursorY%16, tz=cursorZ;
-
- /*
- //Access the DF interface to pause the game.
- //Copied from the reveal tool.
- DFHack::Gui *Gui =DF->getGui();
- cout << "Pausing..." << endl;
- Gui->SetPauseState(true);
- DF->Resume();
- waitmsec(1000);
- DF->Suspend();
- */
-
- //Verify that every z-level at this location exists.
- for (int32_t Z = 0; Z<= bz ;Z++)
- {
- if ( ! Mapz->isValidBlock(bx,by,Z) )
- {
- cout << "This block does't exist! Exiting." << endl;
- #ifndef LINUX_BUILD
- cin.ignore();
- #endif
- return 1;
- }
- }
-
- //Get all the map features.
- vector<DFHack::t_feature> global_features;
- if (!Mapz->ReadGlobalFeatures(global_features))
- {
- cout << "Couldn't load global features! Probably a version problem." << endl;
- #ifndef LINUX_BUILD
- cin.ignore();
- #endif
- return 1;
- }
-
- std::map <DFHack::planecoord, std::vector<DFHack::t_feature *> > local_features;
- if (!Mapz->ReadLocalFeatures(local_features))
- {
- cout << "Couldn't load local features! Probably a version problem." << endl;
- #ifndef LINUX_BUILD
- cin.ignore();
- #endif
- return 1;
- }
-
- //Get info on current tile, to determine how to generate the pit
- mapblock40d topblock;
- Mapz->ReadBlock40d( bx, by, bz , &topblock );
- //Related block info
- planecoord pc;
- pc.dim.x=bx;
- pc.dim.y=by;
- mapblock40d block;
- const TileRow * tp;
- t_designation * d;
-
- //////////////////////////////////////
- //From top to bottom, dig this thing.
- //////////////////////////////////////
-
- //Top level, cap.
- //Might make this an option in the future
- //For now, no wall means no cap.
- if (wallthickness)
- {
- Mapz->ReadBlock40d( bx, by, bz , &block );
- for (uint32_t x=0;x<16;++x)
- {
- for (uint32_t y=0;y<16;++y)
- {
- if ( (pattern[x][y]>1) || (roof && pattern[x][y]) )
- {
- tp = getTileTypeP(block.tiletypes[x][y]);
- d = &block.designation[x][y];
- //Only modify this level if it's 'empty'
- if ( EMPTY != tp->c && RAMP_TOP != tp->c && STAIR_DOWN != tp->c && DFHack::TILE_STREAM_TOP != tp->s)
- {
- continue;
- }
-
- //Need a floor for empty space.
- if (reveal)
- {
- d->bits.hidden = 0; //topblock.designation[x][y].bits.hidden;
- }
- //Always clear the dig designation.
- d->bits.dig = designation_no;
- //unlock fluids, so they fall down the pit.
- d->bits.flow_forbid = d->bits.liquid_static=0;
- block.blockflags.bits.liquid_1 = block.blockflags.bits.liquid_2 = 1;
- //Remove aquifer, to prevent bugginess
- d->bits.water_table=0;
- //Set the tile.
- block.tiletypes[x][y] = cap + rand()%4;
- }
- }
- }
- //Write the block.
- Mapz->WriteBlockFlags(bx,by,bz, block.blockflags );
- Mapz->WriteDesignations(bx,by,bz, &block.designation );
- Mapz->WriteTileTypes(bx,by,bz, &block.tiletypes );
- Mapz->WriteDirtyBit(bx,by,bz,1);
- }
-
- ///////////////////////////////////////////////////////////////////////////////////////////////
- //All levels in between.
- int done=0;
- uint32_t t,v;
- int32_t z = bz-1;
- int32_t bottom = max(0,bz-pitdepth-1);
- assert( bottom>=0 && bottom<=bz );
- for ( ; !done && z>=bottom ; --z)
- {
- int watercount=0;
- int magmacount=0;
- int moltencount=0;
- int rockcount=0;
- int veincount=0;
- int emptycount=0;
- int hellcount=0;
- int templecount=0;
- int adamcount=0;
- int featcount=0;
- int tpat;
-
- cout << z << endl;
- assert( Mapz->isValidBlock(bx,by,z) );
- if (!Mapz->ReadBlock40d( bx, by, z , &block ))
- {
- cout << "Bad block! " << bx << "," << by << "," << z << endl;
- }
-
- //Pre-process this z-level, to get some tile statistics.
- for (int32_t x=0;x<16;++x)
- {
- for (int32_t y=0;y<16;++y)
- {
- t=0;
- tp = getTileTypeP(block.tiletypes[x][y]);
- d = &block.designation[x][y];
- tpat=pattern[x][y];
-
- //Tile type material categories
- switch ( tp->m )
- {
- case AIR:
- ++emptycount;
- break;
- case MAGMA:
- ++moltencount;
- break;
- case VEIN:
- ++veincount;
- break;
- case FEATSTONE:
- case HFS:
- case OBSIDIAN:
- //basicly, ignored.
- break;
- default:
- if ( EMPTY == tp->c || RAMP_TOP == tp->c || STAIR_DOWN == tp->c )
- {
- ++emptycount;
- }
- else
- {
- ++rockcount;
- }
- break;
- }
-
- //Magma and water
- if ( d->bits.flow_size )
- {
- if (d->bits.liquid_type)
- {
- ++magmacount;
- }
- else
- {
- ++watercount;
- }
- }
-
-
- //Check for Features
- if ( block.local_feature > -1 || block.global_feature > -1 )
- {
- //Count tiles which actually are in the feature.
- //It is possible for a block to have a feature, but no tiles to be feature.
- if ( d->bits.feature_global || d->bits.feature_local )
- {
- //All features
- ++featcount;
-
- if ( d->bits.feature_global && d->bits.feature_local )
- {
- cout << "warn:tile is global and local at same time!" << endl;
- }
-
- n=0;
- if ( block.global_feature > -1 && d->bits.feature_global )
- {
- n=global_features[block.global_feature].type;
- switch ( n )
- {
- case feature_Other:
- //no count
- break;
- case feature_Adamantine_Tube:
- ++adamcount;
- break;
- case feature_Underworld:
- ++hellcount;
- break;
- case feature_Hell_Temple:
- ++templecount;
- break;
- default:
- //something here. for debugging, it may be interesting to know.
- if (n) cout << '(' << n << ')';
- }
- }
-
- n=0;
- if ( block.local_feature > -1 && d->bits.feature_local )
- {
- n=local_features[pc][block.local_feature]->type;
- switch ( n )
- {
- case feature_Other:
- //no count
- break;
- case feature_Adamantine_Tube:
- ++adamcount;
- break;
- case feature_Underworld:
- ++hellcount;
- break;
- case feature_Hell_Temple:
- ++templecount;
- break;
- default:
- //something here. for debugging, it may be interesting to know.
- if (n) cout << '[' << n << ']';
- }
- }
- }
- }
- }
- }
-
-
- //If stopping at magma, and no no non-feature stone in this layer, and magma found, then we're either at
- //or below the magma sea / molten rock.
- if ( stopatmagma && (moltencount || magmacount) && (!exposemagma || !rockcount) )
- {
- //If not exposing magma, quit at the first sign of magma.
- //If exposing magma, quite once magma is exposed.
- done=-1;
- }
-
-
- /////////////////////////////////////////////////////////////////////////////////////////////////
- //Some checks, based on settings and stats collected
- //First check, are we at illegal depth?
- if ( !done && hellcount && stopatmagma )
- {
- //Panic!
- done=-1;
- tpat=0;
- cout << "error: illegal breach of hell!" << endl;
- }
-
- /////////////////////////////////////////////////////////////////////////////////////////////////
- //Actually process the current z-level.
- //These loops do the work.
- for (int32_t x=0;!done && x<16;++x)
- {
- for (int32_t y=0;!done && y<16;++y)
- {
- t=0;
- tp = getTileTypeP(block.tiletypes[x][y]);
- d = &block.designation[x][y];
- tpat=pattern[x][y];
-
- //Up front, remove aquifer, to prevent bugginess
- //It may be added back if aquify is set.
- d->bits.water_table=0;
-
- //Change behaviour based on settings and stats from this z-level
-
- //In hell?
- if ( tpat && tpat!=3 && isfeature(global_features, local_features,block,pc,x,y,feature_Underworld ) )
- {
- if ( exposehell )
- {
- tpat=0;
- }
- }
-
- //Expose magma?
- if ( tpat && tpat!=3 && exposemagma )
- {
- //Leave certain tiles unchanged.
- switch ( tp->m )
- {
- case HFS:
- case FEATSTONE:
- case MAGMA:
- tpat=0;
- default:
- break;
- }
- //Adamantine may be left unchanged...
- if ( isfeature(global_features, local_features,block,pc,x,y,feature_Adamantine_Tube ) )
- {
- tpat=0;
- }
- //Leave magma sea unchanged.
- if ( d->bits.flow_size && d->bits.liquid_type)
- {
- tpat=0;
- }
- }
-
-
- //For all situations...
- //Special modification for walls, always for adamantine.
- if ( isfeature(global_features, local_features,block,pc,x,y,feature_Adamantine_Tube ) )
- {
- if ( 2==pattern[x][y] || 3==pattern[x][y] )
- {
- tpat=2;
- }
- }
-
-
- //Border or space?
- switch (tpat)
- {
- case 0:
- continue;
- break;
- case 1:
- //Empty Space
- t=32;
- //d->bits.light = topblock.designation[x][y].bits.light;
- //d->bits.skyview = topblock.designation[x][y].bits.skyview;
- //d->bits.subterranean = topblock.designation[x][y].bits.subterranean;
-
- //Erase special markers?
- //d->bits.feature_global = d->bits.feature_local = 0;
-
- //Water? Magma?
- if (fillmagma || fillwater)
- {
- d->bits.flow_size=7;
- d->bits.water_stagnant = false;
- d->bits.water_salt = false;
- if (fillmagma)
- {
- d->bits.liquid_type=liquid_magma;
- }
- else
- {
- d->bits.liquid_type=liquid_water;
- }
- }
- else
- {
- //Otherwise, remove all liquids.
- d->bits.flow_size=0;
- d->bits.water_stagnant = false;
- d->bits.water_salt = false;
- d->bits.liquid_type = liquid_water;
- }
-
- break;
- case 2:
- //Wall.
- //First guess based on current material
- switch ( tp->m )
- {
- case OBSIDIAN:
- t=wmagma;
- break;
- case MAGMA:
- t=wmolten;
- break;
- case HFS:
- //t=whell;
- break;
- case VEIN:
- t=440; //Solid vein block
- break;
- case FEATSTONE:
- t=335; //Solid feature stone block
- break;
- default:
- t=wcave;
- }
- //Adamantine (a local feature) trumps veins.
- {
- //Local Feature?
- if ( block.local_feature > -1 )
- {
- switch ( n=local_features[pc][block.local_feature]->type )
- {
- case feature_Underworld:
- case feature_Hell_Temple:
- //Only adopt these if there is no global feature present
- if ( block.global_feature >-1 )
- {
- break;
- }
- case feature_Adamantine_Tube:
- //Always for adamantine, sometimes for others
- //Whatever the feature is made of. "featstone wall"
- d->bits.feature_global = 0;
- d->bits.feature_local = 1;
- t=335;
- break;
- }
- }
- //Global Feature?
- else if (block.global_feature > -1 && !d->bits.feature_local )
- {
- switch ( n=global_features[block.global_feature].type )
- {
- case feature_Adamantine_Tube:
- case feature_Underworld:
- case feature_Hell_Temple:
- //Whatever the feature is made of. "featstone wall"
- d->bits.feature_global = 1;
- t=335;
- break;
- }
- }
- }
-
- //Erase any liquids, as they cause problems.
- d->bits.flow_size=0;
- d->bits.water_stagnant = false;
- d->bits.water_salt = false;
- d->bits.liquid_type=liquid_water;
-
- //Placing an aquifer?
- //(bugged, these aquifers don't generate water!)
- if ( aquify )
- {
- //Only normal stone types can be aquified
- if ( tp->m!=MAGMA && tp->m!=FEATSTONE && tp->m!=HFS )
- {
- //Only place next to the hole.
- //If no hole, place in middle.
- if ( checkneighbors(pattern,x,y,1) || (7==x && 7==y) )
- {
- d->bits.water_table = 1;
- //t=265; //soil wall
- }
- }
- }
- break;
- case 3:
- ////No obsidian walls on bottom of map!
- //if(z<1 && (d->bits.feature_global || d->bits.feature_local) ) {
- // t=335;
- //}
-
- //Special wall, always sets to obsidian, to give a stairway
- t=331;
-
- //Erase special markers
- d->bits.feature_global = d->bits.feature_local = 0;
-
- //Erase any liquids, as they cause problems.
- d->bits.flow_size=0;
- d->bits.water_stagnant = false;
- d->bits.water_salt = false;
- d->bits.liquid_type=liquid_water;
- break;
- default:
- cout << ".error,bad pattern.";
- }
-
- //For all tiles.
- if (reveal)
- {
- d->bits.hidden = 0; //topblock.designation[x][y].bits.hidden;
- }
- //Always clear the dig designation.
- d->bits.dig=designation_no;
- //Make it underground, because it is capped
- d->bits.subterranean=1;
- d->bits.light=0;
- d->bits.skyview=0;
- //unlock fluids, so they fall down the pit.
- d->bits.flow_forbid = d->bits.liquid_static=0;
- block.blockflags.bits.liquid_1 = block.blockflags.bits.liquid_2 = 1;
- //Set the tile.
- block.tiletypes[x][y] = t;
-
- }
- }
-
- //Write the block.
- Mapz->WriteBlockFlags(bx,by,z, block.blockflags );
- Mapz->WriteDesignations(bx,by,z, &block.designation );
- Mapz->WriteTileTypes(bx,by,z, &block.tiletypes );
- Mapz->WriteDirtyBit(bx,by,z,1);
-
- }
-
- //Re-process the last z-level handled above.
- z++;
- assert( z>=0 );
-
-
- ///////////////////////////////////////////////////////////////////////////////////////////////
- //The bottom level is special.
- if (-1)
- {
- if (!Mapz->ReadBlock40d( bx, by, z , &block ))
- {
- cout << "Bad block! " << bx << "," << by << "," << z << endl;
- }
- for (uint32_t x=0;x<16;++x)
- {
- for (uint32_t y=0;y<16;++y)
- {
- t=floor;
- v=floorvar;
- tp = getTileTypeP(block.tiletypes[x][y]);
- d = &block.designation[x][y];
-
- if ( exposehell )
- {
- //Leave hell tiles unchanged when exposing hell.
- if ( isfeature(global_features,local_features,block,pc,x,y,feature_Underworld) )
- {
- continue;
- }
- }
-
- //Does expose magma need anything at this level?
- if ( exposemagma && stopatmagma )
- {
- continue;
- }
-
- switch (pattern[x][y])
- {
- case 0:
- continue;
- break;
- case 1:
- //Empty becomes floor.
-
- //Base floor type on the z-level first, features, then tile type.
- if (!z) {
- //Bottom of map, use the floor specified, always.
- break;
- }
-
- ////Only place floor where ground is already solid when exposing
- //if( EMPTY == tp->c || RAMP_TOP == tp->c || STAIR_DOWN == tp->c ){
- // continue;
- //}
-
- if ( d->bits.feature_global || d->bits.feature_global ) {
- //Feature Floor!
- t=344;
- break;
- }
-
- //Tile material check.
- switch ( tp->m )
- {
- case OBSIDIAN:
- t=340;
- v=3;
- break;
- case MAGMA:
- v=0;
- t=264; //magma flow
- break;
- case HFS:
- //should only happen at bottom of map
- break;
- case VEIN:
- t=441; //vein floor
- v=3;
- break;
- case FEATSTONE:
- t=344;
- v=3;
- break;
- }
-
- break;
- case 2:
- case 3:
- //Walls already drawn.
- //Ignore.
- continue;
- break;
- }
-
- //For all tiles.
- if (reveal) d->bits.hidden = 0; //topblock.designation[x][y].bits.hidden;
- //Always clear the dig designation.
- d->bits.dig=designation_no;
- //unlock fluids
- d->bits.flow_forbid = d->bits.liquid_static=0;
- block.blockflags.bits.liquid_1 = block.blockflags.bits.liquid_2 = 1;
-
- //Set the tile.
- block.tiletypes[x][y] = t + ( v ? rand()&v : 0 );
- }
- }
- //Write the block.
- Mapz->WriteBlockFlags(bx,by,z, block.blockflags );
- Mapz->WriteDesignations(bx,by,z, &block.designation );
- Mapz->WriteTileTypes(bx,by,z, &block.tiletypes );
- Mapz->WriteDirtyBit(bx,by,z,1);
- }
-
- DF->Detach();
-#ifndef LINUX_BUILD
- cout << "Done. Press any key to continue" << endl;
- cin.ignore();
-#endif
- return 0;
-}
+// Burn a hole straight to hell! + +#include <stdlib.h> +#include <time.h> + +#include <iostream> +#include <vector> +#include <map> +#include <stddef.h> +#include <assert.h> +#include <math.h> +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <limits.h> +using namespace std; + +#include <DFHack.h> +#include <dfhack/DFTileTypes.h> +#include <dfhack/modules/Gui.h> +using namespace DFHack; + + +#ifdef LINUX_BUILD +#include <unistd.h> +void waitmsec (int delay) +{ + usleep(delay); +} +#else +#include <windows.h> +void waitmsec (int delay) +{ + Sleep(delay); +} +#endif + +#define minmax(MinV,V,MaxV) (max((MinV),min((MaxV),(V)))) + +//User interaction enums. +//Pit Type (these only have meaning within hellhole, btw) +#define PITTYPEMACRO \ + X(pitTypeChasm,"Bottomless Chasm" ) \ + X(pitTypeEerie,"Bottomless Eerie Pit" ) \ + X(pitTypeFloor,"Pit with floor" ) \ + X(pitTypeSolid,"Solid Pillar" ) \ + X(pitTypeOasis,"Oasis Pit (ends at magma, no hell access)" ) \ + X(pitTypeOPool,"Oasis Pool, with partial aquifer (default 5 z-levels)" ) \ + X(pitTypeMagma,"Magma Pit (similar to volcano, no hell access)" ) \ + X(pitTypeMPool,"Magma Pool (default 5 z-levels)" ) +//end PITTYPEMACRO + +#define X(name,desc) name, +enum e_pitType +{ + pitTypeInvalid=-1, + PITTYPEMACRO + pitTypeCount, +}; +#undef X + + +#define X(name,desc) desc, +const char * pitTypeDesc[pitTypeCount+1] = +{ + PITTYPEMACRO + "" +}; +#undef X + + + + +int getyesno( const char * msg , int default_value ) +{ + const int bufferlen=4; + static char buf[bufferlen]; + memset(buf,0,bufferlen); + while (-1) + { + if (msg) printf("\n%s (default=%s)\n:" , msg , (default_value?"yes":"no") ); + fflush(stdin); + fgets(buf,bufferlen,stdin); + switch (buf[0]) + { + case 0: + case 0x0d: + case 0x0a: + return default_value; + case 'y': + case 'Y': + case 'T': + case 't': + case '1': + return -1; + case 'n': + case 'N': + case 'F': + case 'f': + case '0': + return 0; + } + } + return 0; +} + +int getint( const char * msg , int min, int max, int default_value ) { + const int bufferlen=16; + static char buf[bufferlen]; + int n=0; + memset(buf,0,bufferlen); + while (-1) + { + if (msg) printf("\n%s (default=%d)\n:" , msg , default_value); + fflush(stdin); + fgets(buf,bufferlen,stdin); + if ( !buf[0] || 0x0a==buf[0] || 0x0d==buf[0] ) + { + return default_value; + } + if ( sscanf(buf,"%d", &n) ) + { + if (n>=min && n<=max ) + { + return n; + } + } + } +} + +int getint( const char * msg , int min, int max ) +{ + const int bufferlen=16; + static char buf[bufferlen]; + int n=0; + memset(buf,0,bufferlen); + while (-1) + { + if (msg) + { + printf("\n%s \n:" , msg ); + } + fflush(stdin); + fgets(buf,bufferlen,stdin); + + if ( !buf[0] || 0x0a==buf[0] || 0x0d==buf[0] ) + { + continue; + } + if ( sscanf(buf,"%d", &n) ) + { + if (n>=min && n<=max ) + { + return n; + } + } + } +} + + + +//Interactive, get pit type from user +e_pitType selectPitType() +{ + while ( -1 ) + { + printf("Enter the type of hole to dig:\n" ); + for (int n=0;n<pitTypeCount;++n) + { + printf("%2d) %s\n", n, pitTypeDesc[n] ); + } + printf(":"); + return (e_pitType)getint(NULL, 0, pitTypeCount-1 ); + } +} + + +void drawcircle(const int radius, unsigned char pattern[16][16], unsigned char v ) +{ + //Small circles get better randomness if handled manually + if ( 1==radius ) + { + pattern[7][7]=v; + if ( (rand()&1) ) pattern[6][7]=v; + if ( (rand()&1) ) pattern[8][7]=v; + if ( (rand()&1) ) pattern[7][6]=v; + if ( (rand()&1) ) pattern[7][8]=v; + + } + else if ( 2==radius ) + { + pattern[7][7]=v; + pattern[7][5]=v; + pattern[7][6]=v; + pattern[7][8]=v; + pattern[7][9]=v; + pattern[6][7]=v; + pattern[8][7]=v; + pattern[9][7]=v; + pattern[6][6]=v; + pattern[6][8]=v; + pattern[8][6]=v; + pattern[8][8]=v; + pattern[5][7]=v; + + if ( (rand()&1) ) pattern[6][5]=v; + if ( (rand()&1) ) pattern[5][6]=v; + if ( (rand()&1) ) pattern[8][5]=v; + if ( (rand()&1) ) pattern[9][6]=v; + if ( (rand()&1) ) pattern[6][9]=v; + if ( (rand()&1) ) pattern[5][8]=v; + if ( (rand()&1) ) pattern[8][9]=v; + if ( (rand()&1) ) pattern[9][8]=v; + } + else + { + //radius 3 or larger, simple circle calculation. + int x,y; + for (y=0-radius; y<=radius; ++y) + { + for (x=0-radius; x<=radius; ++x) + { + if (x*x+y*y <= radius*radius + (rand()&31-8) ) + { + pattern[ minmax(0,7+x,15) ][ minmax(0,7+y,15) ]=v; + } + } + } + //Prevent boxy patterns with a quick modification on edges + if (rand()&1) pattern[ 7 ][ minmax(0,7+radius+1,15) ] = v; + if (rand()&1) pattern[ 7 ][ minmax(0,7-radius-1,15) ] = v; + if (rand()&1) pattern[ minmax(0,7+radius+1,15) ][ 7 ] = v; + if (rand()&1) pattern[ minmax(0,7-radius-1,15) ][ 7 ] = v; + } +} + +//Check all neighbors for a given value n. +//If found, and v>=0, replace with v. +//Returns number of neighbors found. +int checkneighbors(unsigned char pattern[16][16], int x, int y, unsigned char n , char v ) +{ + int r=0; + if ( x>0 && y>0 && n==pattern[x-1][y-1] ) + { + ++r; + if (v>-1) pattern[x][y]=v; + } + if ( x>0 && n==pattern[x-1][y ] ) + { + ++r; + if (v>-1) pattern[x][y]=v; + } + if ( y>0 && n==pattern[x ][y-1] ) + { + ++r; + if (v>-1) pattern[x][y]=v; + } + if ( x<15 && n==pattern[x+1][y ] ) + { + ++r; + if (v>-1) pattern[x][y]=v; + } + if ( x<15 && y>0 && n==pattern[x+1][y-1] ) + { + ++r; + if (v>-1) pattern[x][y]=v; + } + if ( x<15 && y<15 && n==pattern[x+1][y+1] ) + { + ++r; + if (v>-1) pattern[x][y]=v; + } + if ( y<15 && n==pattern[x ][y+1] ) + { + ++r; + if (v>-1) pattern[x][y]=v; + } + if ( x>0 && y<15 && n==pattern[x-1][y+1] ) + { + ++r; + if (v>-1) pattern[x][y]=v; + } + return r; +} +//convenience +int checkneighbors(unsigned char pattern[16][16], int x, int y, unsigned char n ) +{ + return checkneighbors(pattern,x,y,n,-1); +} + +void settileat(unsigned char pattern[16][16], const unsigned char needle, const unsigned char v, const int index ) +{ + int ok=0; + int safety=256*256; + int y,x,i=0; + //Scan for sequential index + while ( !ok && --safety ) + { + for (y=0 ; !ok && y<16 ; ++y ) + { + for (x=0 ; !ok && x<16 ; ++x ) + { + if ( needle==pattern[x][y] ) + { + ++i; + if ( index==i ) + { + //Got it! + pattern[x][y]=v; + ok=-1; + } + } + } + } + } +} + + +//FIXME: good candidate for adding to dfhack. Maybe the Maps should have those cached so they can be queried? +//Is a given feature present at the given tile? +int isfeature( + vector<DFHack::t_feature> global_features, + std::map <DFHack::planecoord, std::vector<DFHack::t_feature *> > local_features, + const mapblock40d &block, const planecoord &pc, const int x, const int y, const e_feature Feat +) +{ + //const TileRow * tp; + //tp = getTileTypeP(block.tiletypes[x][y]); + const t_designation * d; + d = &block.designation[x][y]; + + if ( block.local_feature > -1 && d->bits.feature_local ) { + if ( Feat==local_features[pc][block.local_feature]->type ) return Feat; + } + if ( block.global_feature > -1 && d->bits.feature_global ) { + if ( Feat==global_features[block.global_feature].type ) return Feat; + } + + return 0; +} + +// FIXME: use block cache, break into manageable bits +int main (void) +{ + srand ( (unsigned int)time(NULL) ); + + //Message of intent + cout << + "DF Hole" << endl << + "This tool will instantly dig a chasm, pit, pipe, etc through hell, wherever your cursor is." << endl << + "This can not be undone! End program now if you don't want hellish fun." << endl + ; + + //User selection of settings should have it own routine, a structure for settings, I know + //sloppy mess, but this is just a demo utility. + + //Pit Types. + e_pitType pittype = selectPitType(); + + //Here are all the settings. + //Default values are set here. + int pitdepth=0; + int roof=-1; + int holeradius=6; + int wallthickness=1; + int wallpillar=1; + int holepillar=1; + int exposehell = 0; + int fillmagma=0; + int fillwater=0; + int stopatmagma=0; + int exposemagma=0; + int aquify=0; + + //The Tile Type to use for the walls lining the hole + //263 is semi-molten rock, 331 is obsidian + uint32_t whell=263, wmolten=263, wmagma=331, wcave=331; + //The Tile Type to use for the hole's floor at bottom of the map + //35 is chasm, 42 is eerie pit , 340 is obsidian floor, 344 is featstone floor, 264 is 'magma flow' floor + uint32_t floor=35, cap=340; + int floorvar=0; + + + //Modify default settings based on pit type. + switch ( pittype ) + { + case pitTypeChasm: + floor=35; + break; + case pitTypeEerie: + floor=42; + break; + case pitTypeFloor: + floor=344; + floorvar=3; + break; + case pitTypeSolid: + holeradius=0; + wallthickness=7; + wallpillar=4; + break; + case pitTypeOasis: + stopatmagma=-1; + fillwater=-1; + holeradius=5; + wallthickness=2; + //aquify=-1; + floor=340; + floorvar=3; + break; + case pitTypeOPool: + pitdepth=5; + fillwater=-1; + holeradius=5; + wallthickness=2; + //aquify=-1; + floor=340; + floorvar=3; + break; + case pitTypeMagma: + stopatmagma=-1; + exposemagma=-1; + wallthickness=2; + fillmagma=-1; + floor=264; + break; + case pitTypeMPool: + pitdepth=5; + wallthickness=2; + fillmagma=-1; + floor=340; + floorvar=3; + break; + } + + + //Should tiles be revealed? + int reveal=0; + + + int accept = getyesno("Use default settings?",1); + + while ( !accept ) + { + //Pit Depth + pitdepth = getint( "Enter max depth (0 for bottom of map)", 0, INT_MAX, pitdepth ); + + //Hole Size + holeradius = getint( "Enter hole radius, 0 to 16", 0, 16, holeradius ); + + //Wall thickness + wallthickness = getint( "Enter wall thickness, 0 to 16", 0, 16, wallthickness ); + + //Obsidian Pillars + holepillar = getint( "Number of Obsidian Pillars in hole, 0 to 255", 0, 255, holepillar ); + wallpillar = getint( "Number of Obsidian Pillars in wall, 0 to 255", 0, 255, wallpillar ); + + //Open Hell? + exposehell=getyesno("Expose the pit to hell (no walls in hell)?",exposehell); + + //Stop when magma sea is hit? + stopatmagma=getyesno("Stop at magma sea?",stopatmagma); + exposemagma=getyesno("Expose magma sea (no walls in magma)?",exposemagma); + + //Fill? + fillmagma=getyesno("Fill with magma?",fillmagma); + if (fillmagma) aquify=fillwater=0; + fillwater=getyesno("Fill with water?",fillwater); + //aquify=getyesno("Aquifer?",aquify); + + + /////////////////////////////////////////////////////////////////////////////////////////////// + //Print settings. + //If a settings struct existed, this could be in a routine + printf("Using Settings:\n"); + printf("Pit Type......: %d = %s\n", pittype, pitTypeDesc[pittype]); + printf("Depth.........: %d\n", pitdepth); + printf("Hole Radius...: %d\n", holeradius); + printf("Wall Thickness: %d\n", wallthickness); + printf("Pillars, Hole.: %d\n", holepillar); + printf("Pillars, Wall.: %d\n", wallpillar); + printf("Expose Hell...: %c\n", (exposehell?'Y':'N') ); + printf("Stop at Magma.: %c\n", (stopatmagma?'Y':'N') ); + printf("Expose Magma..: %c\n", (exposemagma?'Y':'N') ); + printf("Magma Fill....: %c\n", (fillmagma?'Y':'N') ); + printf("Water Fill....: %c\n", (fillwater?'Y':'N') ); + printf("Aquifer.......: %c\n", (aquify?'Y':'N') ); + + accept = getyesno("Accept these settings?",1); + } + + + int64_t n; + uint32_t x_max,y_max,z_max; + + + //Pattern to dig + unsigned char pattern[16][16]; + + + for (int regen=1;regen; ) + { + regen=0; + + memset(pattern,0,sizeof(pattern)); + + //Calculate a randomized circle. + //These values found through experimentation. + int x=0, y=0, n=0; + + //Two concentric irregular circles + //Outer circle, solid. + if ( wallthickness ) + { + drawcircle(holeradius+wallthickness, pattern, 2); + } + //Inner circle, hole. + if ( holeradius ) + { + drawcircle(holeradius, pattern, 1); + } + + + //Post-process to be certain the wall totally encloses hole. + if (wallthickness) + { + for (y=0;y<16;++y) + { + for (x=0;x<16;++x) + { + if ( 1==pattern[x][y] ) + { + //No hole at edges. + if ( x<1 || x>14 || y<1 || y>14 ) + { + pattern[x][y]=2; + } + } + else if ( 0==pattern[x][y] ) + { + //check neighbors + checkneighbors( pattern , x,y, 1, 2); + } + } + } + } + + //Makes sure that somewhere random gets a vertical pillar of rock which is safe + //to dig stairs down, to permit access to anywhere within the pit from the top. + for (n=holepillar; n ; --n) + { + settileat( pattern , 1 , 3 , rand()&255 ); + } + for (n=wallpillar; n ; --n) + { + settileat( pattern , 2 , 3 , rand()&255 ); + } + + //Note: + //At this point, the pattern holds: + //0 for all tiles which will be ignored. + //1 for all tiles set to empty pit space. + //2 for all normal walls. + //3 for the straight obsidian top-to-bottom wall. + //4 is randomized between wall or floor (!not implemented!) + + printf("\nPattern:\n"); + const char patternkey[] = ".cW!?567890123"; + + //Print the pattern + for (y=0;y<16;++y) + { + for (x=0;x<16;++x) + { + cout << patternkey[ pattern[x][y] ]; + } + cout << endl; + } + cout << endl; + + regen = !getyesno("Acceptable Pattern?",1); + } + + //Post-process settings to fix problems here + if (pitdepth<1) + { + pitdepth=INT_MAX; + } + + + /////////////////////////////////////////////////////////////////////////////////////////////// + + + cerr << "Loading memory map..." << endl; + + //Connect to DF! + DFHack::ContextManager DFMgr("Memory.xml"); + DFHack::Context *DF = DFMgr.getSingleContext(); + + + + //Init + cerr << "Attaching to DF..." << endl; + try + { + DF->Attach(); + } + catch (exception& e) + { + cerr << e.what() << endl; + #ifndef LINUX_BUILD + cin.ignore(); + #endif + return 1; + } + + // init the map + DFHack::Maps *Mapz = DF->getMaps(); + if (!Mapz->Start()) + { + cerr << "Can't init map. Exiting." << endl; + #ifndef LINUX_BUILD + cin.ignore(); + #endif + return 1; + } + + Mapz->getSize(x_max,y_max,z_max); + + + //Get cursor + int32_t cursorX, cursorY, cursorZ; + DFHack::Position *Pos = DF->getPosition(); + Pos->getCursorCoords(cursorX,cursorY,cursorZ); + if (-30000==cursorX) + { + cout << "No cursor position found. Exiting." << endl; + #ifndef LINUX_BUILD + cin.ignore(); + #endif + return 1; + } + + //Block coordinates + int32_t bx=cursorX/16, by=cursorY/16, bz=cursorZ; + //Tile coordinates within block + int32_t tx=cursorX%16, ty=cursorY%16, tz=cursorZ; + + /* + //Access the DF interface to pause the game. + //Copied from the reveal tool. + DFHack::Gui *Gui =DF->getGui(); + cout << "Pausing..." << endl; + Gui->SetPauseState(true); + DF->Resume(); + waitmsec(1000); + DF->Suspend(); + */ + + //Verify that every z-level at this location exists. + for (int32_t Z = 0; Z<= bz ;Z++) + { + if ( ! Mapz->isValidBlock(bx,by,Z) ) + { + cout << "This block does't exist! Exiting." << endl; + #ifndef LINUX_BUILD + cin.ignore(); + #endif + return 1; + } + } + + //Get all the map features. + vector<DFHack::t_feature> global_features; + if (!Mapz->ReadGlobalFeatures(global_features)) + { + cout << "Couldn't load global features! Probably a version problem." << endl; + #ifndef LINUX_BUILD + cin.ignore(); + #endif + return 1; + } + + std::map <DFHack::planecoord, std::vector<DFHack::t_feature *> > local_features; + if (!Mapz->ReadLocalFeatures(local_features)) + { + cout << "Couldn't load local features! Probably a version problem." << endl; + #ifndef LINUX_BUILD + cin.ignore(); + #endif + return 1; + } + + //Get info on current tile, to determine how to generate the pit + mapblock40d topblock; + Mapz->ReadBlock40d( bx, by, bz , &topblock ); + //Related block info + planecoord pc; + pc.dim.x=bx; + pc.dim.y=by; + mapblock40d block; + const TileRow * tp; + t_designation * d; + + ////////////////////////////////////// + //From top to bottom, dig this thing. + ////////////////////////////////////// + + //Top level, cap. + //Might make this an option in the future + //For now, no wall means no cap. + if (wallthickness) + { + Mapz->ReadBlock40d( bx, by, bz , &block ); + for (uint32_t x=0;x<16;++x) + { + for (uint32_t y=0;y<16;++y) + { + if ( (pattern[x][y]>1) || (roof && pattern[x][y]) ) + { + tp = getTileTypeP(block.tiletypes[x][y]); + d = &block.designation[x][y]; + //Only modify this level if it's 'empty' + if ( EMPTY != tp->c && RAMP_TOP != tp->c && STAIR_DOWN != tp->c && DFHack::TILE_STREAM_TOP != tp->s) + { + continue; + } + + //Need a floor for empty space. + if (reveal) + { + d->bits.hidden = 0; //topblock.designation[x][y].bits.hidden; + } + //Always clear the dig designation. + d->bits.dig = designation_no; + //unlock fluids, so they fall down the pit. + d->bits.flow_forbid = d->bits.liquid_static=0; + block.blockflags.bits.liquid_1 = block.blockflags.bits.liquid_2 = 1; + //Remove aquifer, to prevent bugginess + d->bits.water_table=0; + //Set the tile. + block.tiletypes[x][y] = cap + rand()%4; + } + } + } + //Write the block. + Mapz->WriteBlockFlags(bx,by,bz, block.blockflags ); + Mapz->WriteDesignations(bx,by,bz, &block.designation ); + Mapz->WriteTileTypes(bx,by,bz, &block.tiletypes ); + Mapz->WriteDirtyBit(bx,by,bz,1); + } + + /////////////////////////////////////////////////////////////////////////////////////////////// + //All levels in between. + int done=0; + uint32_t t,v; + int32_t z = bz-1; + int32_t bottom = max(0,bz-pitdepth-1); + assert( bottom>=0 && bottom<=bz ); + for ( ; !done && z>=bottom ; --z) + { + int watercount=0; + int magmacount=0; + int moltencount=0; + int rockcount=0; + int veincount=0; + int emptycount=0; + int hellcount=0; + int templecount=0; + int adamcount=0; + int featcount=0; + int tpat; + + cout << z << endl; + assert( Mapz->isValidBlock(bx,by,z) ); + if (!Mapz->ReadBlock40d( bx, by, z , &block )) + { + cout << "Bad block! " << bx << "," << by << "," << z << endl; + } + + //Pre-process this z-level, to get some tile statistics. + for (int32_t x=0;x<16;++x) + { + for (int32_t y=0;y<16;++y) + { + t=0; + tp = getTileTypeP(block.tiletypes[x][y]); + d = &block.designation[x][y]; + tpat=pattern[x][y]; + + //Tile type material categories + switch ( tp->m ) + { + case AIR: + ++emptycount; + break; + case MAGMA: + ++moltencount; + break; + case VEIN: + ++veincount; + break; + case FEATSTONE: + case HFS: + case OBSIDIAN: + //basicly, ignored. + break; + default: + if ( EMPTY == tp->c || RAMP_TOP == tp->c || STAIR_DOWN == tp->c ) + { + ++emptycount; + } + else + { + ++rockcount; + } + break; + } + + //Magma and water + if ( d->bits.flow_size ) + { + if (d->bits.liquid_type) + { + ++magmacount; + } + else + { + ++watercount; + } + } + + + //Check for Features + if ( block.local_feature > -1 || block.global_feature > -1 ) + { + //Count tiles which actually are in the feature. + //It is possible for a block to have a feature, but no tiles to be feature. + if ( d->bits.feature_global || d->bits.feature_local ) + { + //All features + ++featcount; + + if ( d->bits.feature_global && d->bits.feature_local ) + { + cout << "warn:tile is global and local at same time!" << endl; + } + + n=0; + if ( block.global_feature > -1 && d->bits.feature_global ) + { + n=global_features[block.global_feature].type; + switch ( n ) + { + case feature_Other: + //no count + break; + case feature_Adamantine_Tube: + ++adamcount; + break; + case feature_Underworld: + ++hellcount; + break; + case feature_Hell_Temple: + ++templecount; + break; + default: + //something here. for debugging, it may be interesting to know. + if (n) cout << '(' << n << ')'; + } + } + + n=0; + if ( block.local_feature > -1 && d->bits.feature_local ) + { + n=local_features[pc][block.local_feature]->type; + switch ( n ) + { + case feature_Other: + //no count + break; + case feature_Adamantine_Tube: + ++adamcount; + break; + case feature_Underworld: + ++hellcount; + break; + case feature_Hell_Temple: + ++templecount; + break; + default: + //something here. for debugging, it may be interesting to know. + if (n) cout << '[' << n << ']'; + } + } + } + } + } + } + + + //If stopping at magma, and no no non-feature stone in this layer, and magma found, then we're either at + //or below the magma sea / molten rock. + if ( stopatmagma && (moltencount || magmacount) && (!exposemagma || !rockcount) ) + { + //If not exposing magma, quit at the first sign of magma. + //If exposing magma, quite once magma is exposed. + done=-1; + } + + + ///////////////////////////////////////////////////////////////////////////////////////////////// + //Some checks, based on settings and stats collected + //First check, are we at illegal depth? + if ( !done && hellcount && stopatmagma ) + { + //Panic! + done=-1; + tpat=0; + cout << "error: illegal breach of hell!" << endl; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////// + //Actually process the current z-level. + //These loops do the work. + for (int32_t x=0;!done && x<16;++x) + { + for (int32_t y=0;!done && y<16;++y) + { + t=0; + tp = getTileTypeP(block.tiletypes[x][y]); + d = &block.designation[x][y]; + tpat=pattern[x][y]; + + //Up front, remove aquifer, to prevent bugginess + //It may be added back if aquify is set. + d->bits.water_table=0; + + //Change behaviour based on settings and stats from this z-level + + //In hell? + if ( tpat && tpat!=3 && isfeature(global_features, local_features,block,pc,x,y,feature_Underworld ) ) + { + if ( exposehell ) + { + tpat=0; + } + } + + //Expose magma? + if ( tpat && tpat!=3 && exposemagma ) + { + //Leave certain tiles unchanged. + switch ( tp->m ) + { + case HFS: + case FEATSTONE: + case MAGMA: + tpat=0; + default: + break; + } + //Adamantine may be left unchanged... + if ( isfeature(global_features, local_features,block,pc,x,y,feature_Adamantine_Tube ) ) + { + tpat=0; + } + //Leave magma sea unchanged. + if ( d->bits.flow_size && d->bits.liquid_type) + { + tpat=0; + } + } + + + //For all situations... + //Special modification for walls, always for adamantine. + if ( isfeature(global_features, local_features,block,pc,x,y,feature_Adamantine_Tube ) ) + { + if ( 2==pattern[x][y] || 3==pattern[x][y] ) + { + tpat=2; + } + } + + + //Border or space? + switch (tpat) + { + case 0: + continue; + break; + case 1: + //Empty Space + t=32; + //d->bits.light = topblock.designation[x][y].bits.light; + //d->bits.skyview = topblock.designation[x][y].bits.skyview; + //d->bits.subterranean = topblock.designation[x][y].bits.subterranean; + + //Erase special markers? + //d->bits.feature_global = d->bits.feature_local = 0; + + //Water? Magma? + if (fillmagma || fillwater) + { + d->bits.flow_size=7; + d->bits.water_stagnant = false; + d->bits.water_salt = false; + if (fillmagma) + { + d->bits.liquid_type=liquid_magma; + } + else + { + d->bits.liquid_type=liquid_water; + } + } + else + { + //Otherwise, remove all liquids. + d->bits.flow_size=0; + d->bits.water_stagnant = false; + d->bits.water_salt = false; + d->bits.liquid_type = liquid_water; + } + + break; + case 2: + //Wall. + //First guess based on current material + switch ( tp->m ) + { + case OBSIDIAN: + t=wmagma; + break; + case MAGMA: + t=wmolten; + break; + case HFS: + //t=whell; + break; + case VEIN: + t=440; //Solid vein block + break; + case FEATSTONE: + t=335; //Solid feature stone block + break; + default: + t=wcave; + } + //Adamantine (a local feature) trumps veins. + { + //Local Feature? + if ( block.local_feature > -1 ) + { + switch ( n=local_features[pc][block.local_feature]->type ) + { + case feature_Underworld: + case feature_Hell_Temple: + //Only adopt these if there is no global feature present + if ( block.global_feature >-1 ) + { + break; + } + case feature_Adamantine_Tube: + //Always for adamantine, sometimes for others + //Whatever the feature is made of. "featstone wall" + d->bits.feature_global = 0; + d->bits.feature_local = 1; + t=335; + break; + } + } + //Global Feature? + else if (block.global_feature > -1 && !d->bits.feature_local ) + { + switch ( n=global_features[block.global_feature].type ) + { + case feature_Adamantine_Tube: + case feature_Underworld: + case feature_Hell_Temple: + //Whatever the feature is made of. "featstone wall" + d->bits.feature_global = 1; + t=335; + break; + } + } + } + + //Erase any liquids, as they cause problems. + d->bits.flow_size=0; + d->bits.water_stagnant = false; + d->bits.water_salt = false; + d->bits.liquid_type=liquid_water; + + //Placing an aquifer? + //(bugged, these aquifers don't generate water!) + if ( aquify ) + { + //Only normal stone types can be aquified + if ( tp->m!=MAGMA && tp->m!=FEATSTONE && tp->m!=HFS ) + { + //Only place next to the hole. + //If no hole, place in middle. + if ( checkneighbors(pattern,x,y,1) || (7==x && 7==y) ) + { + d->bits.water_table = 1; + //t=265; //soil wall + } + } + } + break; + case 3: + ////No obsidian walls on bottom of map! + //if(z<1 && (d->bits.feature_global || d->bits.feature_local) ) { + // t=335; + //} + + //Special wall, always sets to obsidian, to give a stairway + t=331; + + //Erase special markers + d->bits.feature_global = d->bits.feature_local = 0; + + //Erase any liquids, as they cause problems. + d->bits.flow_size=0; + d->bits.water_stagnant = false; + d->bits.water_salt = false; + d->bits.liquid_type=liquid_water; + break; + default: + cout << ".error,bad pattern."; + } + + //For all tiles. + if (reveal) + { + d->bits.hidden = 0; //topblock.designation[x][y].bits.hidden; + } + //Always clear the dig designation. + d->bits.dig=designation_no; + //Make it underground, because it is capped + d->bits.subterranean=1; + d->bits.light=0; + d->bits.skyview=0; + //unlock fluids, so they fall down the pit. + d->bits.flow_forbid = d->bits.liquid_static=0; + block.blockflags.bits.liquid_1 = block.blockflags.bits.liquid_2 = 1; + //Set the tile. + block.tiletypes[x][y] = t; + + } + } + + //Write the block. + Mapz->WriteBlockFlags(bx,by,z, block.blockflags ); + Mapz->WriteDesignations(bx,by,z, &block.designation ); + Mapz->WriteTileTypes(bx,by,z, &block.tiletypes ); + Mapz->WriteDirtyBit(bx,by,z,1); + + } + + //Re-process the last z-level handled above. + z++; + assert( z>=0 ); + + + /////////////////////////////////////////////////////////////////////////////////////////////// + //The bottom level is special. + if (-1) + { + if (!Mapz->ReadBlock40d( bx, by, z , &block )) + { + cout << "Bad block! " << bx << "," << by << "," << z << endl; + } + for (uint32_t x=0;x<16;++x) + { + for (uint32_t y=0;y<16;++y) + { + t=floor; + v=floorvar; + tp = getTileTypeP(block.tiletypes[x][y]); + d = &block.designation[x][y]; + + if ( exposehell ) + { + //Leave hell tiles unchanged when exposing hell. + if ( isfeature(global_features,local_features,block,pc,x,y,feature_Underworld) ) + { + continue; + } + } + + //Does expose magma need anything at this level? + if ( exposemagma && stopatmagma ) + { + continue; + } + + switch (pattern[x][y]) + { + case 0: + continue; + break; + case 1: + //Empty becomes floor. + + //Base floor type on the z-level first, features, then tile type. + if (!z) { + //Bottom of map, use the floor specified, always. + break; + } + + ////Only place floor where ground is already solid when exposing + //if( EMPTY == tp->c || RAMP_TOP == tp->c || STAIR_DOWN == tp->c ){ + // continue; + //} + + if ( d->bits.feature_global || d->bits.feature_global ) { + //Feature Floor! + t=344; + break; + } + + //Tile material check. + switch ( tp->m ) + { + case OBSIDIAN: + t=340; + v=3; + break; + case MAGMA: + v=0; + t=264; //magma flow + break; + case HFS: + //should only happen at bottom of map + break; + case VEIN: + t=441; //vein floor + v=3; + break; + case FEATSTONE: + t=344; + v=3; + break; + } + + break; + case 2: + case 3: + //Walls already drawn. + //Ignore. + continue; + break; + } + + //For all tiles. + if (reveal) d->bits.hidden = 0; //topblock.designation[x][y].bits.hidden; + //Always clear the dig designation. + d->bits.dig=designation_no; + //unlock fluids + d->bits.flow_forbid = d->bits.liquid_static=0; + block.blockflags.bits.liquid_1 = block.blockflags.bits.liquid_2 = 1; + + //Set the tile. + block.tiletypes[x][y] = t + ( v ? rand()&v : 0 ); + } + } + //Write the block. + Mapz->WriteBlockFlags(bx,by,z, block.blockflags ); + Mapz->WriteDesignations(bx,by,z, &block.designation ); + Mapz->WriteTileTypes(bx,by,z, &block.tiletypes ); + Mapz->WriteDirtyBit(bx,by,z,1); + } + + DF->Detach(); +#ifndef LINUX_BUILD + cout << "Done. Press any key to continue" << endl; + cin.ignore(); +#endif + return 0; +} diff --git a/tools/supported/probe.cpp b/tools/supported/probe.cpp index 9d8549e5..eb4ec284 100644 --- a/tools/supported/probe.cpp +++ b/tools/supported/probe.cpp @@ -1,168 +1,168 @@ -// Just show some position data
-
-#include <iostream>
-#include <iomanip>
-#include <climits>
-#include <vector>
-#include <sstream>
-#include <ctime>
-#include <cstdio>
-
-#define DFHACK_WANT_MISCUTILS 1
-#define DFHACK_WANT_TILETYPES 1
-#include <DFHack.h>
-
-using namespace DFHack;
-int main (int numargs, const char ** args)
-{
- DFHack::ContextManager DFMgr("Memory.xml");
- DFHack::Context *DF = DFMgr.getSingleContext();
-
- BEGIN_PROBE:
- try
- {
- DF->Attach();
- }
- catch (std::exception& e)
- {
- std::cerr << e.what() << std::endl;
- #ifndef LINUX_BUILD
- cin.ignore();
- #endif
- return 1;
- }
-
-
- DFHack::Position *Pos = DF->getPosition();
- DFHack::VersionInfo* mem = DF->getMemoryInfo();
- DFHack::Maps *Maps = DF->getMaps();
- DFHack::Process * p = DF->getProcess();
- OffsetGroup *mapsg = mem->getGroup("Maps");
- OffsetGroup *mapblockg = mapsg->getGroup("block");
- OffsetGroup *localfeatg = mapsg->getGroup("features")->getGroup("local");
-
- uint32_t region_x_offset = mapsg->getAddress("region_x");
- uint32_t region_y_offset = mapsg->getAddress("region_y");
- uint32_t region_z_offset = mapsg->getAddress("region_z");
-
- uint32_t designatus = mapblockg->getOffset("designation");
- uint32_t block_feature1 = mapblockg->getOffset("feature_local");
- uint32_t block_feature2 = mapblockg->getOffset("feature_global");
-
- uint32_t feature1_start_ptr = localfeatg->getAddress("start_ptr");
- int32_t regionX, regionY, regionZ;
-
- // read position of the region inside DF world
- p->readDWord (region_x_offset, (uint32_t &)regionX);
- p->readDWord (region_y_offset, (uint32_t &)regionY);
- p->readDWord (region_z_offset, (uint32_t &)regionZ);
-
- Maps->Start();
-
- vector<DFHack::t_feature> global_features;
- std::map <DFHack::planecoord, std::vector<DFHack::t_feature *> > local_features;
- Maps->ReadLocalFeatures(local_features);
- Maps->ReadGlobalFeatures(global_features);
-
- int32_t cursorX, cursorY, cursorZ;
- Pos->getCursorCoords(cursorX,cursorY,cursorZ);
- if(cursorX != -30000)
- {
- uint32_t blockX = cursorX / 16;
- uint32_t tileX = cursorX % 16;
- uint32_t blockY = cursorY / 16;
- uint32_t tileY = cursorY % 16;
- t_temperatures tmpb1, tmpb2;
- mapblock40d block;
- if(Maps->ReadBlock40d(blockX,blockY,cursorZ,&block))
- {
- Maps->ReadTemperatures(blockX,blockY,cursorZ,&tmpb1, &tmpb2);
- printf("block addr: 0x%x\n", block.origin);
- int16_t tiletype = block.tiletypes[tileX][tileY];
- naked_designation &des = block.designation[tileX][tileY].bits;
- uint32_t &desw = block.designation[tileX][tileY].whole;
- print_bits<uint32_t>(block.designation[tileX][tileY].whole,std::cout);
- std::cout << endl;
- print_bits<uint32_t>(block.occupancy[tileX][tileY].whole,std::cout);
- std::cout << endl;
-
- // tiletype
- std::cout <<"tiletype: " << tiletype;
- if(tileTypeTable[tiletype].name)
- std::cout << " = " << tileTypeTable[tiletype].name << std::endl;
-
- printf("%-10s: %4d %s\n","Class",tileTypeTable[tiletype].c,TileClassString[ tileTypeTable[tiletype].c ] , 0);
- printf("%-10s: %4d %s\n","Material",tileTypeTable[tiletype].c,TileMaterialString[ tileTypeTable[tiletype].m ] , 0);
- printf("%-10s: %4d %s\n","Special",tileTypeTable[tiletype].c,TileSpecialString[ tileTypeTable[tiletype].s ] , 0);
- printf("%-10s: %4d\n","Variant",tileTypeTable[tiletype].v , 0);
- printf("%-10s: %s\n","Direction",tileTypeTable[tiletype].d.getStr() , 0);
-
-
- std::cout << std::endl;
- std::cout <<"temperature1: " << tmpb1[tileX][tileY] << " U" << std::endl;
- std::cout <<"temperature2: " << tmpb2[tileX][tileY] << " U" << std::endl;
-
- // biome, geolayer
- std::cout << "biome: " << des.biome << std::endl;
- std::cout << "geolayer: " << des.geolayer_index << std::endl;
-
- // liquids
- if(des.flow_size)
- {
- if(des.liquid_type == DFHack::liquid_magma)
- std::cout <<"magma: ";
- else std::cout <<"water: ";
- std::cout << des.flow_size << std::endl;
- }
- if(des.flow_forbid)
- std::cout << "flow forbid" << std::endl;
- if(des.pile)
- std::cout << "stockpile?" << std::endl;
- if(des.rained)
- std::cout << "rained?" << std::endl;
- if(des.smooth)
- std::cout << "smooth?" << std::endl;
- uint32_t designato = block.origin + designatus + (tileX * 16 + tileY) * sizeof(t_designation);
- printf("designation offset: 0x%x\n", designato);
-
- #define PRINT_FLAG( X ) printf("%-16s= %c\n", #X , ( des.X ? 'Y' : ' ' ) )
- PRINT_FLAG( hidden );
- PRINT_FLAG( light );
- PRINT_FLAG( skyview );
- PRINT_FLAG( subterranean );
- PRINT_FLAG( water_table );
- //PRINT_FLAG( rained );
-
- planecoord pc;
- pc.dim.x=blockX; pc.dim.y=blockY;
-
- PRINT_FLAG( feature_local );
- if( des.feature_local )
- {
- printf("%-16s %4d (%2d) %s\n", "",
- block.local_feature,
- local_features[pc][block.local_feature]->type,
- sa_feature[local_features[pc][block.local_feature]->type]
- );
- }
-
- PRINT_FLAG( feature_global );
- if( des.feature_global ){
- printf("%-16s %4d (%2d) %s\n", "",
- block.global_feature,
- global_features[block.global_feature].type,
- sa_feature[global_features[block.global_feature].type]
- );
- }
- #undef PRINT_FLAG
- std::cout << std::endl;
- }
- }
- DF->Detach();
- #ifndef LINUX_BUILD
- std::cout << "Press any key to refresh..." << std::endl;
- cin.ignore();
- goto BEGIN_PROBE;
- #endif
- return 0;
-}
+// Just show some position data + +#include <iostream> +#include <iomanip> +#include <climits> +#include <vector> +#include <sstream> +#include <ctime> +#include <cstdio> + +#define DFHACK_WANT_MISCUTILS 1 +#define DFHACK_WANT_TILETYPES 1 +#include <DFHack.h> + +using namespace DFHack; +int main (int numargs, const char ** args) +{ + DFHack::ContextManager DFMgr("Memory.xml"); + DFHack::Context *DF = DFMgr.getSingleContext(); + + BEGIN_PROBE: + try + { + DF->Attach(); + } + catch (std::exception& e) + { + std::cerr << e.what() << std::endl; + #ifndef LINUX_BUILD + cin.ignore(); + #endif + return 1; + } + + + DFHack::Position *Pos = DF->getPosition(); + DFHack::VersionInfo* mem = DF->getMemoryInfo(); + DFHack::Maps *Maps = DF->getMaps(); + DFHack::Process * p = DF->getProcess(); + OffsetGroup *mapsg = mem->getGroup("Maps"); + OffsetGroup *mapblockg = mapsg->getGroup("block"); + OffsetGroup *localfeatg = mapsg->getGroup("features")->getGroup("local"); + + uint32_t region_x_offset = mapsg->getAddress("region_x"); + uint32_t region_y_offset = mapsg->getAddress("region_y"); + uint32_t region_z_offset = mapsg->getAddress("region_z"); + + uint32_t designatus = mapblockg->getOffset("designation"); + uint32_t block_feature1 = mapblockg->getOffset("feature_local"); + uint32_t block_feature2 = mapblockg->getOffset("feature_global"); + + uint32_t feature1_start_ptr = localfeatg->getAddress("start_ptr"); + int32_t regionX, regionY, regionZ; + + // read position of the region inside DF world + p->readDWord (region_x_offset, (uint32_t &)regionX); + p->readDWord (region_y_offset, (uint32_t &)regionY); + p->readDWord (region_z_offset, (uint32_t &)regionZ); + + Maps->Start(); + + vector<DFHack::t_feature> global_features; + std::map <DFHack::planecoord, std::vector<DFHack::t_feature *> > local_features; + Maps->ReadLocalFeatures(local_features); + Maps->ReadGlobalFeatures(global_features); + + int32_t cursorX, cursorY, cursorZ; + Pos->getCursorCoords(cursorX,cursorY,cursorZ); + if(cursorX != -30000) + { + uint32_t blockX = cursorX / 16; + uint32_t tileX = cursorX % 16; + uint32_t blockY = cursorY / 16; + uint32_t tileY = cursorY % 16; + t_temperatures tmpb1, tmpb2; + mapblock40d block; + if(Maps->ReadBlock40d(blockX,blockY,cursorZ,&block)) + { + Maps->ReadTemperatures(blockX,blockY,cursorZ,&tmpb1, &tmpb2); + printf("block addr: 0x%x\n", block.origin); + int16_t tiletype = block.tiletypes[tileX][tileY]; + naked_designation &des = block.designation[tileX][tileY].bits; + uint32_t &desw = block.designation[tileX][tileY].whole; + print_bits<uint32_t>(block.designation[tileX][tileY].whole,std::cout); + std::cout << endl; + print_bits<uint32_t>(block.occupancy[tileX][tileY].whole,std::cout); + std::cout << endl; + + // tiletype + std::cout <<"tiletype: " << tiletype; + if(tileTypeTable[tiletype].name) + std::cout << " = " << tileTypeTable[tiletype].name << std::endl; + + printf("%-10s: %4d %s\n","Class",tileTypeTable[tiletype].c,TileClassString[ tileTypeTable[tiletype].c ] , 0); + printf("%-10s: %4d %s\n","Material",tileTypeTable[tiletype].c,TileMaterialString[ tileTypeTable[tiletype].m ] , 0); + printf("%-10s: %4d %s\n","Special",tileTypeTable[tiletype].c,TileSpecialString[ tileTypeTable[tiletype].s ] , 0); + printf("%-10s: %4d\n","Variant",tileTypeTable[tiletype].v , 0); + printf("%-10s: %s\n","Direction",tileTypeTable[tiletype].d.getStr() , 0); + + + std::cout << std::endl; + std::cout <<"temperature1: " << tmpb1[tileX][tileY] << " U" << std::endl; + std::cout <<"temperature2: " << tmpb2[tileX][tileY] << " U" << std::endl; + + // biome, geolayer + std::cout << "biome: " << des.biome << std::endl; + std::cout << "geolayer: " << des.geolayer_index << std::endl; + + // liquids + if(des.flow_size) + { + if(des.liquid_type == DFHack::liquid_magma) + std::cout <<"magma: "; + else std::cout <<"water: "; + std::cout << des.flow_size << std::endl; + } + if(des.flow_forbid) + std::cout << "flow forbid" << std::endl; + if(des.pile) + std::cout << "stockpile?" << std::endl; + if(des.rained) + std::cout << "rained?" << std::endl; + if(des.smooth) + std::cout << "smooth?" << std::endl; + uint32_t designato = block.origin + designatus + (tileX * 16 + tileY) * sizeof(t_designation); + printf("designation offset: 0x%x\n", designato); + + #define PRINT_FLAG( X ) printf("%-16s= %c\n", #X , ( des.X ? 'Y' : ' ' ) ) + PRINT_FLAG( hidden ); + PRINT_FLAG( light ); + PRINT_FLAG( skyview ); + PRINT_FLAG( subterranean ); + PRINT_FLAG( water_table ); + //PRINT_FLAG( rained ); + + planecoord pc; + pc.dim.x=blockX; pc.dim.y=blockY; + + PRINT_FLAG( feature_local ); + if( des.feature_local ) + { + printf("%-16s %4d (%2d) %s\n", "", + block.local_feature, + local_features[pc][block.local_feature]->type, + sa_feature[local_features[pc][block.local_feature]->type] + ); + } + + PRINT_FLAG( feature_global ); + if( des.feature_global ){ + printf("%-16s %4d (%2d) %s\n", "", + block.global_feature, + global_features[block.global_feature].type, + sa_feature[global_features[block.global_feature].type] + ); + } + #undef PRINT_FLAG + std::cout << std::endl; + } + } + DF->Detach(); + #ifndef LINUX_BUILD + std::cout << "Press any key to refresh..." << std::endl; + cin.ignore(); + goto BEGIN_PROBE; + #endif + return 0; +} |
