diff options
| author | Petr Mrázek | 2011-06-20 05:08:21 +0200 |
|---|---|---|
| committer | Petr Mrázek | 2011-06-20 05:08:21 +0200 |
| commit | b41ab40bb6eb44d00c2eca64a6ca54168e446d5f (patch) | |
| tree | 105f106597c4872c3dc153717420318fa1142884 /plugins/prospector.cpp | |
| parent | c6dc4900d2c3032ef282d5e8bc4219ece375e447 (diff) | |
| download | dfhack-b41ab40bb6eb44d00c2eca64a6ca54168e446d5f.tar.gz dfhack-b41ab40bb6eb44d00c2eca64a6ca54168e446d5f.tar.bz2 dfhack-b41ab40bb6eb44d00c2eca64a6ca54168e446d5f.tar.xz | |
Prospector plugin tool thing. How to pass them parameters?
Diffstat (limited to 'plugins/prospector.cpp')
| -rw-r--r-- | plugins/prospector.cpp | 381 |
1 files changed, 381 insertions, 0 deletions
diff --git a/plugins/prospector.cpp b/plugins/prospector.cpp new file mode 100644 index 00000000..6439c5a4 --- /dev/null +++ b/plugins/prospector.cpp @@ -0,0 +1,381 @@ +// Produces a list of materials available on the map. +// Options: +// -a : show unrevealed tiles +// -p : don't show plants +// -s : don't show slade +// -t : don't show demon temple + +//#include <cstdlib> +#include <iostream> +#include <iomanip> +#include <map> +#include <algorithm> +#include <vector> + +using namespace std; +#include <DFHack.h> +#include <dfhack/extra/MapExtras.h> +#include <dfhack/extra/termutil.h> +#include <dfhack/Core.h> + +typedef std::map<int16_t, unsigned int> MatMap; +typedef std::vector< pair<int16_t, unsigned int> > MatSorter; + +typedef std::vector<DFHack::t_feature> FeatureList; +typedef std::vector<DFHack::t_feature*> FeatureListPointer; +typedef std::map<DFHack::DFCoord, FeatureListPointer> FeatureMap; +typedef std::vector<DFHack::df_plant *> PlantList; +/* +bool parseOptions(int argc, char **argv, bool &showHidden, bool &showPlants, + bool &showSlade, bool &showTemple) +{ + char c; + xgetopt opt(argc, argv, "apst"); + opt.opterr = 0; + while ((c = opt()) != -1) + { + switch (c) + { + case 'a': + showHidden = true; + break; + case 'p': + showPlants = false; + break; + case 's': + showSlade = false; + break; + case 't': + showTemple = false; + 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; + } + } + return true; +} +*/ +template<template <typename> class P = std::greater > +struct compare_pair_second +{ + template<class T1, class T2> + bool operator()(const std::pair<T1, T2>& left, const std::pair<T1, T2>& right) + { + return P<T2>()(left.second, right.second); + } +}; + + +void printMats(MatMap &mat, std::vector<DFHack::t_matgloss> &materials) +{ + unsigned int total = 0; + MatSorter sorting_vector; + for (MatMap::const_iterator it = mat.begin(); it != mat.end(); ++it) + { + sorting_vector.push_back(*it); + } + std::sort(sorting_vector.begin(), sorting_vector.end(), compare_pair_second<>()); + for (MatSorter::const_iterator it = sorting_vector.begin(); it != sorting_vector.end(); ++it) + { + if(it->first >= materials.size()) + { + cerr << "Bad index: " << it->first << " out of " << materials.size() << endl; + continue; + } + DFHack::t_matgloss mat = materials[it->first]; + std::cout << std::setw(25) << mat.id << " : " << it->second << std::endl; + total += it->second; + } + + std::cout << ">>> TOTAL = " << total << std::endl << std::endl; +} + +DFhackCExport const char * plugin_name ( void ) +{ + return "prospector"; +} + +DFhackCExport int plugin_run (DFHack::Core * c) +{ + bool showHidden = true; + bool showPlants = true; + bool showSlade = true; + bool showTemple = true; +/* + if (!parseOptions(argc, argv, showHidden, showPlants, showSlade, showTemple)) + { + return -1; + } +*/ + uint32_t x_max = 0, y_max = 0, z_max = 0; + c->Suspend(); + DFHack::Maps *maps = c->getMaps(); + if (!maps->Start()) + { + std::cerr << "Cannot get map info!" << std::endl; + c->Resume(); + return 1; + } + maps->getSize(x_max, y_max, z_max); + MapExtras::MapCache map(maps); + + DFHack::Materials *mats = c->getMaterials(); + if (!mats->ReadInorganicMaterials()) + { + std::cerr << "Unable to read inorganic material definitons!" << std::endl; + c->Resume(); + return 1; + } + if (showPlants && !mats->ReadOrganicMaterials()) + { + std::cerr << "Unable to read organic material definitons; plants won't be listed!" << std::endl; + showPlants = false; + } + + FeatureList globalFeatures; + FeatureMap localFeatures; + DFHack::t_feature *blockFeatureGlobal = 0; + DFHack::t_feature *blockFeatureLocal = 0; + + bool hasAquifer = false; + bool hasDemonTemple = false; + bool hasLair = false; + MatMap baseMats; + MatMap layerMats; + MatMap veinMats; + MatMap plantMats; + MatMap treeMats; + + if (!(showSlade && maps->ReadGlobalFeatures(globalFeatures))) + { + std::cerr << "Unable to read global features; slade won't be listed!" << std::endl; + } + + if (!maps->ReadLocalFeatures(localFeatures)) + { + std::cerr << "Unable to read local features; adamantine " + << (showTemple ? "and demon temples " : "") + << "won't be listed!" << std::endl; + } + + uint32_t vegCount = 0; + DFHack::Vegetation *veg = c->getVegetation(); + if (showPlants && !veg->Start()) + { + std::cerr << "Unable to read vegetation; plants won't be listed!" << std::endl; + } + + for(uint32_t z = 0; z < z_max; z++) + { + for(uint32_t b_y = 0; b_y < y_max; b_y++) + { + for(uint32_t b_x = 0; b_x < x_max; b_x++) + { + // Get the map block + DFHack::DFCoord blockCoord(b_x, b_y); + MapExtras::Block *b = map.BlockAt(DFHack::DFCoord(b_x, b_y, z)); + if (!b || !b->valid) + { + continue; + } + + { // Find features + uint16_t index = b->raw.global_feature; + if (index != -1 && index < globalFeatures.size()) + { + blockFeatureGlobal = &globalFeatures[index]; + } + + 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]; + } + } + } + + // Iterate over all the tiles in the block + for(uint32_t y = 0; y < 16; y++) + { + for(uint32_t x = 0; x < 16; x++) + { + DFHack::DFCoord coord(x, y); + DFHack::t_designation des = b->DesignationAt(coord); + DFHack::t_occupancy occ = b->OccupancyAt(coord); + + // Skip hidden tiles + if (!showHidden && des.bits.hidden) + { + continue; + } + + // Check for aquifer + if (des.bits.water_table) + { + hasAquifer = true; + } + + // Check for lairs + if (occ.bits.monster_lair) + { + hasLair = true; + } + + uint16_t type = b->TileTypeAt(coord); + const DFHack::TileRow *info = DFHack::getTileRow(type); + + if (!info) + { + std::cerr << "Bad type: " << type << std::endl; + continue; + } + + // We only care about these types + switch (info->shape) + { + case DFHack::WALL: + case DFHack::PILLAR: + case DFHack::FORTIFICATION: + break; + default: + continue; + } + + // Count the material type + baseMats[info->material]++; + + // Find the type of the tile + switch (info->material) + { + case DFHack::SOIL: + case DFHack::STONE: + layerMats[b->baseMaterialAt(coord)]++; + break; + case DFHack::VEIN: + veinMats[b->veinMaterialAt(coord)]++; + break; + case DFHack::FEATSTONE: + if (blockFeatureLocal && des.bits.feature_local) + { + if (blockFeatureLocal->type == DFHack::feature_Adamantine_Tube + && blockFeatureLocal->main_material == 0) // stone + { + veinMats[blockFeatureLocal->sub_material]++; + } + else if (showTemple + && blockFeatureLocal->type == DFHack::feature_Hell_Temple) + { + hasDemonTemple = true; + } + } + + if (showSlade && blockFeatureGlobal && des.bits.feature_global + && blockFeatureGlobal->type == DFHack::feature_Underworld + && blockFeatureGlobal->main_material == 0) // stone + { + layerMats[blockFeatureGlobal->sub_material]++; + } + break; + case DFHack::OBSIDIAN: + // TODO ? + break; + } + } + } + + // Check plants this way, as the other way wasn't getting them all + // and we can check visibility more easily here + if (showPlants) + { + PlantList * plants; + if (maps->ReadVegetation(b_x, b_y, z, plants)) + { + for (PlantList::const_iterator it = plants->begin(); it != plants->end(); it++) + { + const DFHack::df_plant & plant = *(*it); + DFHack::DFCoord loc(plant.x, plant.y); + loc = loc % 16; + if (showHidden || !b->DesignationAt(loc).bits.hidden) + { + if(plant.is_shrub) + plantMats[plant.material]++; + else + treeMats[plant.material]++; + } + } + } + } + // Block end + } // block x + + // Clean uneeded memory + map.trash(); + } // block y + } // z + + MatMap::const_iterator it; + + std::cout << "Base materials:" << std::endl; + for (it = baseMats.begin(); it != baseMats.end(); ++it) + { + std::cout << std::setw(25) << DFHack::TileMaterialString[it->first] << " : " << it->second << std::endl; + } + + std::cout << std::endl << "Layer materials:" << std::endl; + printMats(layerMats, mats->inorganic); + + std::cout << "Vein materials:" << std::endl; + printMats(veinMats, mats->inorganic); + + if (showPlants) + { + std::cout << "Shrubs:" << std::endl; + printMats(plantMats, mats->organic); + std::cout << "Wood in trees:" << std::endl; + printMats(treeMats, mats->organic); + } + + if (hasAquifer) + { + std::cout << "Has aquifer" << std::endl; + } + + if (hasDemonTemple) + { + std::cout << "Has demon temple" << std::endl; + } + + if (hasLair) + { + std::cout << "Has lair" << std::endl; + } + + // Cleanup + if (showPlants) + { + veg->Finish(); + } + mats->Finish(); + maps->Finish(); + c->Resume(); + std::cout << std::endl; + return 0; +} |
