diff --git a/tools/supported/probe.cpp b/tools/supported/probe.cpp index 1da2618a0..44f1ee75c 100644 --- a/tools/supported/probe.cpp +++ b/tools/supported/probe.cpp @@ -13,15 +13,101 @@ using namespace std; #define DFHACK_WANT_TILETYPES 1 #include #include +#include #include +bool parseOptions(int argc, char **argv, bool &showBlock, bool &showDesig, + bool &showOccup, bool &showTile, bool &showMisc) +{ + // With no options set, show everything. + showBlock = true; + showDesig = true; + showOccup = true; + showTile = true; + showMisc = true; + + bool _showBlock = false; + bool _showDesig = false; + bool _showOccup = false; + bool _showTile = false; + bool _showMisc = false; + + char c; + xgetopt opt(argc, argv, "bdotm"); + opt.opterr = 0; + while ((c = opt()) != -1) + { + switch (c) + { + case 'b': + _showBlock = true; + break; + case 'd': + _showDesig = true; + break; + case 'o': + _showOccup = true; + break; + case 't': + _showTile = true; + break; + case 'm': + _showMisc = true; + break; + + case '?': + switch (opt.optopt) + { + // For when we take arguments + default: + if (isprint(opt.optopt)) + std::cerr << "Unknown option -" << opt.optopt << "!" + << std::endl; + else + std::cerr << "Unknown option character " << (int) opt.optopt << "!" + << std::endl; + } + default: + // Um..... + return false; + } + } + + // If any options set, show only those requested via options. + if(_showBlock || _showDesig || _showOccup || _showTile || _showMisc) + { + showBlock = false; + showDesig = false; + showOccup = false; + showTile = false; + showMisc = false; + + showBlock = _showBlock; + showDesig = _showDesig; + showOccup = _showOccup; + showTile = _showTile; + showMisc = _showMisc; + } + + return true; +} + + using namespace DFHack; -int main (int numargs, const char ** args) +int main (int numargs, char ** args) { bool temporary_terminal = TemporaryTerminal(); DFHack::ContextManager DFMgr("Memory.xml"); DFHack::Context *DF = DFMgr.getSingleContext(); + bool showBlock, showDesig, showOccup, showTile, showMisc; + + if (!parseOptions(numargs, args, showBlock, showDesig, showOccup, + showTile, showMisc)) + { + return -1; + } + BEGIN_PROBE: try { @@ -73,7 +159,12 @@ int main (int numargs, const char ** args) int32_t cursorX, cursorY, cursorZ; Gui->getCursorCoords(cursorX,cursorY,cursorZ); - if(cursorX != -30000) + if(cursorX == -30000) + { + std::cerr << "No cursor; place cursor over tile to probe." + << endl; + } + else { DFCoord cursor (cursorX,cursorY,cursorZ); @@ -86,121 +177,160 @@ int main (int numargs, const char ** args) mapblock40d & block = b->raw; if(b) { - printf("block addr: 0x%x\n", block.origin); + printf("block addr: 0x%x\n\n", block.origin); + + if (showBlock) + { + printf("block flags:\n"); + print_bits(block.blockflags.whole,std::cout); + std::cout << endl << endl; + } + int16_t tiletype = mc.tiletypeAt(cursor); naked_designation &des = block.designation[tileX][tileY].bits; uint32_t designato = block.origin + designatus + (tileX * 16 + tileY) * sizeof(t_designation); uint32_t occupr = block.origin + occup + (tileX * 16 + tileY) * sizeof(t_occupancy); - printf("designation offset: 0x%x\n", designato); - print_bits(block.designation[tileX][tileY].whole,std::cout); - std::cout << endl; - - printf("occupancy offset: 0x%x\n", occupr); - print_bits(block.occupancy[tileX][tileY].whole,std::cout); - std::cout << endl; - - // tiletype - std::cout <<"tiletype: " << tiletype; - if(tileName(tiletype)) - std::cout << " = " << tileName(tiletype) << std::endl; - - DFHack::TileShape shape = tileShape(tiletype); - DFHack::TileMaterial material = tileMaterial(tiletype); - DFHack::TileSpecial special = tileSpecial(tiletype); - printf("%-10s: %4d %s\n","Class" ,shape, TileShapeString[ shape ]); - printf("%-10s: %4d %s\n","Material" ,material,TileMaterialString[ material ]); - printf("%-10s: %4d %s\n","Special" ,special, TileSpecialString[ special ]); - printf("%-10s: %4d\n" ,"Variant" ,tileVariant(tiletype)); - printf("%-10s: %s\n" ,"Direction",tileDirection(tiletype).getStr()); - - std::cout << std::endl; - std::cout <<"temperature1: " << mc.temperature1At(cursor) << " U" << std::endl; - std::cout <<"temperature2: " << mc.temperature2At(cursor) << " U" << std::endl; - - // biome, geolayer - std::cout << "biome: " << des.biome << std::endl; - std::cout << "geolayer: " << des.geolayer_index << std::endl; - int16_t base_rock = mc.baseMaterialAt(cursor); - if(base_rock != -1) + if(showDesig) { - cout << "Layer material: " << dec << base_rock; - if(hasmats) - cout << " / " << Materials->inorganic[base_rock].id << " / " << Materials->inorganic[base_rock].name << endl; - else - cout << endl; + printf("designation offset: 0x%x\n", designato); + print_bits(block.designation[tileX][tileY].whole, + std::cout); + std::cout << endl << endl; } - int16_t vein_rock = mc.veinMaterialAt(cursor); - if(vein_rock != -1) + + if(showOccup) { - cout << "Vein material (final): " << dec << vein_rock; - if(hasmats) - cout << " / " << Materials->inorganic[vein_rock].id << " / " << Materials->inorganic[vein_rock].name << endl; - else - cout << endl; + printf("occupancy offset: 0x%x\n", occupr); + print_bits(block.occupancy[tileX][tileY].whole, + std::cout); + std::cout << endl << endl; } - // liquids - if(des.flow_size) + + if(showTile) { - if(des.liquid_type == DFHack::liquid_magma) - std::cout <<"magma: "; - else std::cout <<"water: "; - std::cout << des.flow_size << std::endl; + // tiletype + std::cout <<"tiletype: " << tiletype; + if(tileName(tiletype)) + std::cout << " = " << tileName(tiletype) << std::endl; + + DFHack::TileShape shape = tileShape(tiletype); + DFHack::TileMaterial material = tileMaterial(tiletype); + DFHack::TileSpecial special = tileSpecial(tiletype); + printf("%-10s: %4d %s\n","Class" ,shape, + TileShapeString[ shape ]); + printf("%-10s: %4d %s\n","Material" , + material,TileMaterialString[ material ]); + printf("%-10s: %4d %s\n","Special" , + special, TileSpecialString[ special ]); + printf("%-10s: %4d\n" ,"Variant" , + tileVariant(tiletype)); + printf("%-10s: %s\n" ,"Direction", + tileDirection(tiletype).getStr()); + + std::cout << 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; - printf("biomestuffs: 0x%x\n", block.origin + biomus); - - #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 ); - - DFCoord pc(blockX, blockY); - - if(have_features) + + if(showMisc) { - t_feature * local = 0; - t_feature * global = 0; - Maps->ReadFeatures(&(b->raw),&local,&global); - PRINT_FLAG( feature_local ); - if(local) + std::cout <<"temperature1: " << mc.temperature1At(cursor) + << " U" << std::endl; + std::cout <<"temperature2: " << mc.temperature2At(cursor) + << " U" << std::endl; + + // biome, geolayer + std::cout << "biome: " << des.biome << std::endl; + std::cout << "geolayer: " << des.geolayer_index + << std::endl; + int16_t base_rock = mc.baseMaterialAt(cursor); + if(base_rock != -1) { - printf("%-16s", ""); - printf(" %4d", block.local_feature); - printf(" (%2d)", local->type); - printf(" addr 0x%X ", local->origin); - printf(" %s\n", sa_feature(local->type)); + cout << "Layer material: " << dec << base_rock; + if(hasmats) + cout << " / " << Materials->inorganic[base_rock].id + << " / " + << Materials->inorganic[base_rock].name + << endl; + else + cout << endl; } - PRINT_FLAG( feature_global ); - if(global) + int16_t vein_rock = mc.veinMaterialAt(cursor); + if(vein_rock != -1) { - printf("%-16s", ""); - printf(" %4d", block.global_feature); - printf(" (%2d)", global->type); - printf(" %s\n", sa_feature(global->type)); + cout << "Vein material (final): " << dec << vein_rock; + if(hasmats) + cout << " / " << Materials->inorganic[vein_rock].id + << " / " + << Materials->inorganic[vein_rock].name + << endl; + else + cout << 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; + printf("biomestuffs: 0x%x\n", block.origin + biomus); + +#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 ); + + DFCoord pc(blockX, blockY); + + if(have_features) + { + t_feature * local = 0; + t_feature * global = 0; + Maps->ReadFeatures(&(b->raw),&local,&global); + PRINT_FLAG( feature_local ); + if(local) + { + printf("%-16s", ""); + printf(" %4d", block.local_feature); + printf(" (%2d)", local->type); + printf(" addr 0x%X ", local->origin); + printf(" %s\n", sa_feature(local->type)); + } + PRINT_FLAG( feature_global ); + if(global) + { + printf("%-16s", ""); + printf(" %4d", block.global_feature); + printf(" (%2d)", global->type); + printf(" %s\n", sa_feature(global->type)); + } + } + else + { + PRINT_FLAG( feature_local ); + PRINT_FLAG( feature_global ); + } +#undef PRINT_FLAG + cout << "local feature idx: " << block.local_feature + << endl; + cout << "global feature idx: " << block.global_feature + << endl; + cout << "mystery: " << block.mystery << endl; + std::cout << std::endl; } - else - { - PRINT_FLAG( feature_local ); - PRINT_FLAG( feature_global ); - } - #undef PRINT_FLAG - cout << "local feature idx: " << block.local_feature << endl; - cout << "global feature idx: " << block.global_feature << endl; - cout << "mystery: " << block.mystery << endl; - std::cout << std::endl; } } } diff --git a/tools/supported/reveal.cpp b/tools/supported/reveal.cpp index 9c64dde13..86e1f3146 100644 --- a/tools/supported/reveal.cpp +++ b/tools/supported/reveal.cpp @@ -6,8 +6,13 @@ using namespace std; #include +#include +#include #include +typedef std::vector FeatureListPointer; +typedef std::map FeatureMap; + #ifdef LINUX_BUILD #include void waitmsec (int delay) @@ -23,6 +28,39 @@ void waitmsec (int delay) #endif #include +/* + * Anything that might reveal Hell is unsafe. + */ +bool isSafe(uint32_t x, uint32_t y, uint32_t z, DFHack::Maps *Maps, + MapExtras::MapCache &cache, FeatureMap localFeatures) +{ + DFHack::t_feature *blockFeatureLocal = NULL; + + DFHack::DFCoord blockCoord(x, y); + MapExtras::Block *b = cache.BlockAt(DFHack::DFCoord(x, y, z)); + + uint16_t index = b->raw.local_feature; + FeatureMap::const_iterator it = localFeatures.find(blockCoord); + if (it != localFeatures.end()) + { + FeatureListPointer features = it->second; + + if (index != -1 && index < features.size()) + { + blockFeatureLocal = features[index]; + } + } + + if (blockFeatureLocal == NULL) + return true; + + // Adamantine tubes and temples lead to Hell, and Hell *is* Hell. + if (blockFeatureLocal->type != DFHack::feature_Other) + return false; + + return true; +} + struct hideblock { uint32_t x; @@ -31,8 +69,39 @@ struct hideblock uint8_t hiddens [16][16]; }; -int main (void) +int main (int argc, char *argv[]) { + bool doSafe = false; + + char c; + xgetopt opt(argc, argv, "s"); + opt.opterr = 0; + + while ((c = opt()) != -1) + { + switch (c) + { + case 's': + doSafe = true; + break; + case '?': + switch (opt.optopt) + { + // For when we take arguments + default: + if (isprint(opt.optopt)) + std::cerr << "Unknown option -" << opt.optopt << "!" + << std::endl; + else + std::cerr << "Unknown option character " << (int) opt.optopt << "!" + << std::endl; + } + default: + // Um..... + return 1; + } + } + bool temporary_terminal = TemporaryTerminal(); uint32_t x_max,y_max,z_max; DFHack::designations40d designations; @@ -52,6 +121,7 @@ int main (void) } DFHack::Maps *Maps =DF->getMaps(); DFHack::World *World =DF->getWorld(); + // walk the map, save the hide bits, reveal. cout << "Pausing..." << endl; @@ -64,6 +134,8 @@ int main (void) waitmsec(1000); DF->Suspend(); + cout << "Revealing, please wait..." << endl; + // init the map if(!Maps->Start()) { @@ -73,19 +145,36 @@ int main (void) return 1; } - cout << "Revealing, please wait..." << endl; + MapExtras::MapCache cache(Maps); + FeatureMap localFeatures; + + if(doSafe && !Maps->ReadLocalFeatures(localFeatures)) + { + std::cerr << "Unable to read local features; can't reveal map " + << "safely" << std::endl; + if(temporary_terminal) + cin.ignore(); + return 1; + } Maps->getSize(x_max,y_max,z_max); vector hidesaved; - for(uint32_t x = 0; x< x_max;x++) + // We go from the top z-level down, stopping as soon as we encounter + // something that might lead to Hell, so the player can unpause without + // spawning demons. + bool quit = false; + for(uint32_t z = z_max - 1; z > 0 && !quit;z--) { - for(uint32_t y = 0; y< y_max;y++) + for(uint32_t y = 0; y < y_max;y++) { - for(uint32_t z = 0; z< z_max;z++) + for(uint32_t x = 0; x < x_max;x++) { if(Maps->isValidBlock(x,y,z)) { + if (doSafe && !isSafe(x, y, z, Maps, cache, localFeatures)) + quit = true; + hideblock hb; hb.x = x; hb.y = y; @@ -108,7 +197,10 @@ int main (void) // FIXME: force game pause here! DF->Detach(); cout << "Map revealed. The game has been paused for you." << endl; - cout << "Unpausing can unleash the forces of hell!" << endl << endl; + if (doSafe) + cout << "Unpausing *WON'T* reveal hell." << endl << endl; + else + cout << "Unpausing can unleash the forces of hell!" << endl << endl; cout << "Press any key to unreveal." << endl; cout << "Close to keep the map revealed !!FOREVER!!" << endl; cin.ignore();