StockpileInfo(building_stockpilest *sp_) : sp(sp_) { MapExtras::MapCache mc; z = sp_->z; x1 = sp_->room.x; x2 = sp_->room.x + sp_->room.width; y1 = sp_->room.y; y2 = sp_->room.y + sp_->room.height; int e = 0; size = 0; free = 0; for (int y = y1; y < y2; y++) for (int x = x1; x < x2; x++) if (sp_->room.extents[e++] == 1) { size++; DFCoord cursor (x,y,z); uint32_t blockX = x / 16; uint32_t tileX = x % 16; uint32_t blockY = y / 16; uint32_t tileY = y % 16; MapExtras::Block * b = mc.BlockAt(cursor/16); if(b && b->is_valid()) { auto &block = *b->getRaw(); df::tile_occupancy &occ = block.occupancy[tileX][tileY]; if (!occ.bits.item) free++; } } }
command_result changelayer (color_ostream &out, std::vector <std::string> & parameters) { CoreSuspender suspend; string material; bool force = false; bool all_biomes = false; bool all_layers = false; bool verbose = false; warned = false; for(size_t i = 0; i < parameters.size();i++) { if(parameters[i] == "help" || parameters[i] == "?") { out.print(changelayer_help.c_str()); return CR_OK; } if(parameters[i] == "trouble") { out.print(changelayer_trouble.c_str()); return CR_OK; } if(parameters[i] == "force") force = true; if(parameters[i] == "all_biomes") all_biomes = true; if(parameters[i] == "all_layers") all_layers = true; if(parameters[i] == "verbose") verbose = true; } if (!Maps::IsValid()) { out.printerr("Map is not available!\n"); return CR_FAILURE; } if (parameters.empty()) { out.printerr("You need to specify a material!\n"); return CR_WRONG_USAGE; } material = parameters[0]; MaterialInfo mat_new; if (!mat_new.findInorganic(material)) { out.printerr("No such material!\n"); return CR_FAILURE; } // check if specified material is stone or gem or soil if (mat_new.inorganic->material.flags.is_set(material_flags::IS_METAL) || mat_new.inorganic->material.flags.is_set(material_flags::NO_STONE_STOCKPILE)) { out.printerr("Invalid material - you must select a type of stone or gem or soil.\n"); return CR_FAILURE; } MapExtras::MapCache mc; int32_t regionX, regionY, regionZ; Maps::getPosition(regionX,regionY,regionZ); int32_t cursorX, cursorY, cursorZ; Gui::getCursorCoords(cursorX,cursorY,cursorZ); if(cursorX == -30000) { out.printerr("No cursor; place cursor over tile.\n"); return CR_FAILURE; } DFCoord cursor (cursorX,cursorY,cursorZ); uint32_t blockX = cursorX / 16; uint32_t tileX = cursorX % 16; uint32_t blockY = cursorY / 16; uint32_t tileY = cursorY % 16; MapExtras::Block * b = mc.BlockAt(cursor/16); if(!b || !b->is_valid()) { out.printerr("No data.\n"); return CR_OK; } df::tile_designation des = b->DesignationAt(cursor%16); // get biome and geolayer at cursor position uint32_t biome = des.bits.biome; uint32_t layer = des.bits.geolayer_index; if(verbose) { out << "biome: " << biome << endl << "geolayer: " << layer << endl; } // there is no Maps::WriteGeology or whatever, and I didn't want to mess with the library and add it // so I copied the stuff which reads the geology information and modified it to be able to change it // // a more elegant solution would probably look like this: // 1) modify Maps::ReadGeology to accept and fill one more optional vector // where the geolayer ids of the 9 biomes are stored // 2) call ReadGeology here, modify the data in the vectors without having to do all that map stuff // 3) write Maps::WriteGeology, pass the vectors, let it do it's work // Step 1) is optional, but it would make implementing 3) easier. // Otherwise that "check which geo_index is used by biome X" loop would need to be done again. // no need to touch the same geology more than once // though it wouldn't matter much since there is not much data to be processed vector<uint16_t> v_geoprocessed; v_geoprocessed.clear(); // iterate over 8 surrounding regions + local region for (int i = eNorthWest; i < eBiomeCount; i++) { if(verbose) out << "---Biome: " << i; if(!all_biomes && i!=biome) { if(verbose) out << "-skipping" << endl; continue; } else { if(verbose) out << "-checking" << endl; } // check against worldmap boundaries, fix if needed // regionX is in embark squares // regionX/16 is in 16x16 embark square regions // i provides -1 .. +1 offset from the current region int bioRX = world->map.region_x / 16 + ((i % 3) - 1); if (bioRX < 0) bioRX = 0; if (bioRX >= world->world_data->world_width) bioRX = world->world_data->world_width - 1; int bioRY = world->map.region_y / 16 + ((i / 3) - 1); if (bioRY < 0) bioRY = 0; if (bioRY >= world->world_data->world_height) bioRY = world->world_data->world_height - 1; // get index into geoblock vector uint16_t geoindex = world->world_data->region_map[bioRX][bioRY].geo_index; if(verbose) out << "geoindex: " << geoindex << endl; bool skip = false; for(int g=0; g<v_geoprocessed.size(); g++) { if(v_geoprocessed.at(g)==geoindex) { if(verbose) out << "already processed" << endl; skip = true; break; } } if(skip) continue; v_geoprocessed.push_back(geoindex); /// geology blocks have a vector of layer descriptors // get the vector with pointer to layers df::world_geo_biome *geo_biome = df::world_geo_biome::find(geoindex); if (!geo_biome) { if(verbose) out << "no geology found here." << endl; continue; } vector <df::world_geo_layer*> &geolayers = geo_biome->layers; // complain if layer is out of range // geology has up to 16 layers currently, but can have less! if(layer >= geolayers.size() || layer < 0) { if(verbose) out << "layer out of range!"; continue; } // now let's actually write the new mat id to the layer(s) if(all_layers) { for (size_t j = 0; j < geolayers.size(); j++) { MaterialInfo mat_old; mat_old.decode(0, geolayers[j]->mat_index); if(conversionAllowed(out, mat_new, mat_old, force)) { if(verbose) out << "changing geolayer " << j << " from " << mat_old.getToken() << " to " << mat_new.getToken() << endl; geolayers[j]->mat_index = mat_new.index; } } } else { MaterialInfo mat_old; mat_old.decode(0, geolayers[layer]->mat_index); if(conversionAllowed(out, mat_new, mat_old, force)) { if(verbose) out << "changing geolayer " << layer << " from " << mat_old.getToken() << " to " << mat_new.getToken() << endl; geolayers[layer]->mat_index = mat_new.index; } } } out.print("Done.\n"); // Give control back to DF. return CR_OK; }
command_result prospector (color_ostream &con, vector <string> & parameters) { bool showHidden = false; bool showPlants = true; bool showValue = false; bool showHFS = false; for(size_t i = 0; i < parameters.size();i++) { if (parameters[i] == "all") { showHidden = true; } else if (parameters[i] == "value") { showValue = true; } else if (parameters[i] == "hell") { showHidden = showHFS = true; } else return CR_WRONG_USAGE; } CoreSuspender suspend; // Embark screen active: estimate using world geology data if (VIRTUAL_CAST_VAR(screen, df::viewscreen_choose_start_sitest, Core::getTopViewscreen())) return embark_prospector(con, screen, showHidden, showValue); if (!Maps::IsValid()) { con.printerr("Map is not available!\n"); return CR_FAILURE; } uint32_t x_max = 0, y_max = 0, z_max = 0; Maps::getSize(x_max, y_max, z_max); MapExtras::MapCache map; DFHack::Materials *mats = Core::getInstance().getMaterials(); DFHack::t_feature blockFeature; bool hasAquifer = false; MatMap baseMats; MatMap layerMats; MatMap veinMats; MatMap plantMats; MatMap treeMats; matdata liquidWater; matdata liquidMagma; matdata aquiferTiles; matdata hfsTiles; uint32_t vegCount = 0; 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 df::coord2d blockCoord(b_x, b_y); MapExtras::Block *b = map.BlockAt(DFHack::DFCoord(b_x, b_y, z)); if (!b || !b->is_valid()) { continue; } // Find features b->GetFeature(&blockFeature); int global_z = world->map.region_z + z; // Iterate over all the tiles in the block for(uint32_t y = 0; y < 16; y++) { for(uint32_t x = 0; x < 16; x++) { df::coord2d coord(x, y); df::tile_designation des = b->DesignationAt(coord); df::tile_occupancy occ = b->OccupancyAt(coord); // Skip hidden tiles if (!showHidden && des.bits.hidden) { continue; } // Check for aquifer if (des.bits.water_table) { hasAquifer = true; aquiferTiles.add(global_z); } // Check for liquid if (des.bits.flow_size) { if (des.bits.liquid_type == tile_liquid::Magma) liquidMagma.add(global_z); else liquidWater.add(global_z); } df::tiletype type = b->tiletypeAt(coord); df::tiletype_shape tileshape = tileShape(type); df::tiletype_material tilemat = tileMaterial(type); // We only care about these types switch (tileshape) { case tiletype_shape::WALL: case tiletype_shape::FORTIFICATION: break; case tiletype_shape::EMPTY: /* find the top of the HFS chamber */ if (tilemat == tiletype_material::AIR && des.bits.feature && des.bits.hidden && blockFeature.type == feature_type::glowing_pit) { hfsTiles.add(global_z); } default: continue; } // Count the material type baseMats[tilemat].add(global_z); // Find the type of the tile switch (tilemat) { case tiletype_material::SOIL: case tiletype_material::STONE: layerMats[b->layerMaterialAt(coord)].add(global_z); break; case tiletype_material::MINERAL: veinMats[b->veinMaterialAt(coord)].add(global_z); break; case tiletype_material::LAVA_STONE: // TODO ? break; default: break; } } } // Check plants this way, as the other way wasn't getting them all // and we can check visibility more easily here if (showPlants) { auto block = Maps::getBlock(b_x,b_y,z); stl::vector<df::plant *> *plants = block ? &block->plants : NULL; if(plants) { for (auto it = plants->begin(); it != plants->end(); it++) { const df::plant & plant = *(*it); df::coord2d loc(plant.pos.x, plant.pos.y); loc = loc % 16; if (showHidden || !b->DesignationAt(loc).bits.hidden) { if(plant.flags.bits.is_shrub) plantMats[plant.plant_id].add(global_z); else treeMats[plant.wood_id].add(global_z); } } } } // Block end } // block x // Clean uneeded memory map.trash(); } // block y } // z MatMap::const_iterator it; con << "Base materials:" << std::endl; for (it = baseMats.begin(); it != baseMats.end(); ++it) { con << std::setw(25) << ENUM_KEY_STR(tiletype_material,(df::tiletype_material)it->first) << " : " << it->second.count << std::endl; } if (liquidWater.count || liquidMagma.count) { con << std::endl << "Liquids:" << std::endl; if (liquidWater.count) { con << std::setw(25) << "WATER" << " : "; printMatdata(con, liquidWater); } if (liquidWater.count) { con << std::setw(25) << "MAGMA" << " : "; printMatdata(con, liquidMagma); } } con << std::endl << "Layer materials:" << std::endl; printMats<df::matgloss_stone, shallower>(con, layerMats, world->raws.matgloss.stone, showValue); printVeins(con, veinMats, mats, showValue); if (showPlants) { con << "Shrubs:" << std::endl; printMats<df::matgloss_plant, std::greater>(con, plantMats, world->raws.matgloss.plant, showValue); con << "Wood in trees:" << std::endl; printMats<df::matgloss_wood, std::greater>(con, treeMats, world->raws.matgloss.wood, showValue); } if (hasAquifer) { con << "Has aquifer"; if (aquiferTiles.count) { con << " : "; printMatdata(con, aquiferTiles); } else con << std::endl; } if (showHFS && hfsTiles.count) { con << "Has HFS : "; printMatdata(con, hfsTiles); } // Cleanup mats->Finish(); con << std::endl; return CR_OK; }
command_result df_probe (color_ostream &out, vector <string> & parameters) { //bool showBlock, showDesig, showOccup, showTile, showMisc; /* if (!parseOptions(parameters, showBlock, showDesig, showOccup, showTile, showMisc)) { out.printerr("Unknown parameters!\n"); return CR_FAILURE; } */ CoreSuspender suspend; DFHack::Materials *Materials = Core::getInstance().getMaterials(); std::vector<t_matglossInorganic> inorganic; bool hasmats = Materials->CopyInorganicMaterials(inorganic); if (!Maps::IsValid()) { out.printerr("Map is not available!\n"); return CR_FAILURE; } MapExtras::MapCache mc; int32_t regionX, regionY, regionZ; Maps::getPosition(regionX,regionY,regionZ); int32_t cursorX, cursorY, cursorZ; Gui::getCursorCoords(cursorX,cursorY,cursorZ); if(cursorX == -30000) { out.printerr("No cursor; place cursor over tile to probe.\n"); return CR_FAILURE; } DFCoord cursor (cursorX,cursorY,cursorZ); uint32_t blockX = cursorX / 16; uint32_t tileX = cursorX % 16; uint32_t blockY = cursorY / 16; uint32_t tileY = cursorY % 16; MapExtras::Block * b = mc.BlockAt(cursor/16); if(!b || !b->is_valid()) { out.printerr("No data.\n"); return CR_OK; } auto &block = *b->getRaw(); out.print("block addr: 0x%x\n\n", &block); /* if (showBlock) { out.print("block flags:\n"); print_bits<uint32_t>(block.blockflags.whole,out); out.print("\n\n"); } */ df::tiletype tiletype = mc.tiletypeAt(cursor); df::tile_designation &des = block.designation[tileX][tileY]; df::tile_occupancy &occ = block.occupancy[tileX][tileY]; /* if(showDesig) { out.print("designation\n"); print_bits<uint32_t>(block.designation[tileX][tileY].whole, out); out.print("\n\n"); } if(showOccup) { out.print("occupancy\n"); print_bits<uint32_t>(block.occupancy[tileX][tileY].whole, out); out.print("\n\n"); } */ // tiletype out.print("tiletype: "); describeTile(out, tiletype); out.print("static: "); describeTile(out, mc.staticTiletypeAt(cursor)); out.print("base: "); describeTile(out, mc.baseTiletypeAt(cursor)); out.print("temperature1: %d U\n",mc.temperature1At(cursor)); out.print("temperature2: %d U\n",mc.temperature2At(cursor)); int offset = block.region_offset[des.bits.biome]; int bx = clip_range(block.region_pos.x + (offset % 3) - 1, 0, world->world_data->world_width-1); int by = clip_range(block.region_pos.y + (offset / 3) - 1, 0, world->world_data->world_height-1); auto biome = &world->world_data->region_map[bx][by]; int sav = biome->savagery; int evi = biome->evilness; int sindex = sav > 65 ? 2 : sav < 33 ? 0 : 1; int eindex = evi > 65 ? 2 : evi < 33 ? 0 : 1; int surr = sindex + eindex * 3; const char* surroundings[] = { "Serene", "Mirthful", "Joyous Wilds", "Calm", "Wilderness", "Untamed Wilds", "Sinister", "Haunted", "Terrifying" }; // biome, geolayer out << "biome: " << des.bits.biome << " (" << "region id=" << biome->region_id << ", " << surroundings[surr] << ", " << "savagery " << biome->savagery << ", " << "evilness " << biome->evilness << ")" << std::endl; out << "geolayer: " << des.bits.geolayer_index << std::endl; int16_t base_rock = mc.layerMaterialAt(cursor); if(base_rock != -1) { out << "Layer material: " << dec << base_rock; if(hasmats) out << " / " << inorganic[base_rock].id << " / " << inorganic[base_rock].name << endl; else out << endl; } int16_t vein_rock = mc.veinMaterialAt(cursor); if(vein_rock != -1) { out << "Vein material (final): " << dec << vein_rock; if(hasmats) out << " / " << inorganic[vein_rock].id << " / " << inorganic[vein_rock].name << endl; else out << endl; } MaterialInfo minfo(mc.baseMaterialAt(cursor)); if (minfo.isValid()) out << "Base material: " << minfo.getToken() << " / " << minfo.toString() << endl; minfo.decode(mc.staticMaterialAt(cursor)); if (minfo.isValid()) out << "Static material: " << minfo.getToken() << " / " << minfo.toString() << endl; // liquids if(des.bits.flow_size) { if(des.bits.liquid_type == tile_liquid::Magma) out <<"magma: "; else out <<"water: "; out << des.bits.flow_size << std::endl; } if(des.bits.flow_forbid) out << "flow forbid" << std::endl; if(des.bits.pile) out << "stockpile?" << std::endl; if(des.bits.rained) out << "rained?" << std::endl; if(des.bits.smooth) out << "smooth?" << std::endl; if(des.bits.water_salt) out << "salty" << endl; if(des.bits.water_stagnant) out << "stagnant" << endl; #define PRINT_FLAG( FIELD, BIT ) out.print("%-16s= %c\n", #BIT , ( FIELD.bits.BIT ? 'Y' : ' ' ) ) PRINT_FLAG( des, hidden ); PRINT_FLAG( des, light ); PRINT_FLAG( des, outside ); PRINT_FLAG( des, subterranean ); PRINT_FLAG( des, water_table ); PRINT_FLAG( des, rained ); PRINT_FLAG( occ, monster_lair); df::coord2d pc(blockX, blockY); t_feature local; t_feature global; Maps::ReadFeatures(&block,&local,&global); PRINT_FLAG( des, feature_local ); if(local.type != -1) { out.print("%-16s", ""); out.print(" %4d", block.local_feature); out.print(" (%2d)", local.type); out.print(" addr 0x%X ", local.origin); out.print(" %s\n", sa_feature(local.type)); } PRINT_FLAG( des, feature_global ); if(global.type != -1) { out.print("%-16s", ""); out.print(" %4d", block.global_feature); out.print(" (%2d)", global.type); out.print(" %s\n", sa_feature(global.type)); } #undef PRINT_FLAG out << "local feature idx: " << block.local_feature << endl; out << "global feature idx: " << block.global_feature << endl; out << std::endl; if(block.occupancy[tileX][tileY].bits.no_grow) out << "no grow" << endl; for(size_t e=0; e<block.block_events.size(); e++) { df::block_square_event * blev = block.block_events[e]; df::block_square_event_type blevtype = blev->getType(); switch(blevtype) { case df::block_square_event_type::grass: { df::block_square_event_grassst * gr_ev = (df::block_square_event_grassst *)blev; if(gr_ev->amount[tileX][tileY] > 0) { out << "amount of grass: " << (int)gr_ev->amount[tileX][tileY] << endl; } break; } case df::block_square_event_type::world_construction: { df::block_square_event_world_constructionst * co_ev = (df::block_square_event_world_constructionst*)blev; uint16_t bits = co_ev->tile_bitmask[tileY]; out << "construction bits: " << bits << endl; break; } default: //out << "unhandled block event type!" << endl; break; } } return CR_OK; }
command_result prospector (color_ostream &con, vector <string> & parameters) { bool showHidden = false; bool showPlants = true; bool showSlade = true; bool showTemple = true; bool showValue = false; bool showTube = false; for(size_t i = 0; i < parameters.size();i++) { if (parameters[i] == "all") { showHidden = true; } else if (parameters[i] == "value") { showValue = true; } else if (parameters[i] == "hell") { showHidden = showTube = true; } else return CR_WRONG_USAGE; } CoreSuspender suspend; // Embark screen active: estimate using world geology data if (VIRTUAL_CAST_VAR(screen, df::viewscreen_choose_start_sitest, Core::getTopViewscreen())) return embark_prospector(con, screen, showHidden, showValue); if (!Maps::IsValid()) { con.printerr("Map is not available!\n"); return CR_FAILURE; } uint32_t x_max = 0, y_max = 0, z_max = 0; Maps::getSize(x_max, y_max, z_max); MapExtras::MapCache map; DFHack::Materials *mats = Core::getInstance().getMaterials(); DFHack::t_feature blockFeatureGlobal; DFHack::t_feature blockFeatureLocal; bool hasAquifer = false; bool hasDemonTemple = false; bool hasLair = false; MatMap baseMats; MatMap layerMats; MatMap veinMats; MatMap plantMats; MatMap treeMats; matdata liquidWater; matdata liquidMagma; matdata aquiferTiles; matdata tubeTiles; uint32_t vegCount = 0; 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 df::coord2d blockCoord(b_x, b_y); MapExtras::Block *b = map.BlockAt(DFHack::DFCoord(b_x, b_y, z)); if (!b || !b->is_valid()) { continue; } // Find features b->GetGlobalFeature(&blockFeatureGlobal); b->GetLocalFeature(&blockFeatureLocal); int global_z = world->map.region_z + z; // Iterate over all the tiles in the block for(uint32_t y = 0; y < 16; y++) { for(uint32_t x = 0; x < 16; x++) { df::coord2d coord(x, y); df::tile_designation des = b->DesignationAt(coord); df::tile_occupancy occ = b->OccupancyAt(coord); // Skip hidden tiles if (!showHidden && des.bits.hidden) { continue; } // Check for aquifer if (des.bits.water_table) { hasAquifer = true; aquiferTiles.add(global_z); } // Check for lairs if (occ.bits.monster_lair) { hasLair = true; } // Check for liquid if (des.bits.flow_size) { if (des.bits.liquid_type == tile_liquid::Magma) liquidMagma.add(global_z); else liquidWater.add(global_z); } df::tiletype type = b->tiletypeAt(coord); df::tiletype_shape tileshape = tileShape(type); df::tiletype_material tilemat = tileMaterial(type); // We only care about these types switch (tileshape) { case tiletype_shape::WALL: case tiletype_shape::FORTIFICATION: break; case tiletype_shape::EMPTY: /* A heuristic: tubes inside adamantine have EMPTY:AIR tiles which still have feature_local set. Also check the unrevealed status, so as to exclude any holes mined by the player. */ if (tilemat == tiletype_material::AIR && des.bits.feature_local && des.bits.hidden && blockFeatureLocal.type == feature_type::deep_special_tube) { tubeTiles.add(global_z); } default: continue; } // Count the material type baseMats[tilemat].add(global_z); // Find the type of the tile switch (tilemat) { case tiletype_material::SOIL: case tiletype_material::STONE: layerMats[b->layerMaterialAt(coord)].add(global_z); break; case tiletype_material::MINERAL: veinMats[b->veinMaterialAt(coord)].add(global_z); break; case tiletype_material::FEATURE: if (blockFeatureLocal.type != -1 && des.bits.feature_local) { if (blockFeatureLocal.type == feature_type::deep_special_tube && blockFeatureLocal.main_material == 0) // stone { veinMats[blockFeatureLocal.sub_material].add(global_z); } else if (showTemple && blockFeatureLocal.type == feature_type::deep_surface_portal) { hasDemonTemple = true; } } if (showSlade && blockFeatureGlobal.type != -1 && des.bits.feature_global && blockFeatureGlobal.type == feature_type::feature_underworld_from_layer && blockFeatureGlobal.main_material == 0) // stone { layerMats[blockFeatureGlobal.sub_material].add(global_z); } break; case tiletype_material::LAVA_STONE: // TODO ? break; default: break; } } } // Check plants this way, as the other way wasn't getting them all // and we can check visibility more easily here if (showPlants) { auto block = Maps::getBlockColumn(b_x,b_y); vector<df::plant *> *plants = block ? &block->plants : NULL; if(plants) { for (PlantList::const_iterator it = plants->begin(); it != plants->end(); it++) { const df::plant & plant = *(*it); if (plant.pos.z != z) continue; df::coord2d loc(plant.pos.x, plant.pos.y); loc = loc % 16; if (showHidden || !b->DesignationAt(loc).bits.hidden) { if(plant.flags.bits.is_shrub) plantMats[plant.material].add(global_z); else treeMats[plant.material].add(global_z); } } } } // Block end } // block x // Clean uneeded memory map.trash(); } // block y } // z MatMap::const_iterator it; con << "Base materials:" << std::endl; for (it = baseMats.begin(); it != baseMats.end(); ++it) { con << std::setw(25) << ENUM_KEY_STR(tiletype_material,(df::tiletype_material)it->first) << " : " << it->second.count << std::endl; } if (liquidWater.count || liquidMagma.count) { con << std::endl << "Liquids:" << std::endl; if (liquidWater.count) { con << std::setw(25) << "WATER" << " : "; printMatdata(con, liquidWater); } if (liquidWater.count) { con << std::setw(25) << "MAGMA" << " : "; printMatdata(con, liquidMagma); } } con << std::endl << "Layer materials:" << std::endl; printMats<df::inorganic_raw, shallower>(con, layerMats, world->raws.inorganics, showValue); printVeins(con, veinMats, mats, showValue); if (showPlants) { con << "Shrubs:" << std::endl; printMats<df::plant_raw, std::greater>(con, plantMats, world->raws.plants.all, showValue); con << "Wood in trees:" << std::endl; printMats<df::plant_raw, std::greater>(con, treeMats, world->raws.plants.all, showValue); } if (hasAquifer) { con << "Has aquifer"; if (aquiferTiles.count) { con << " : "; printMatdata(con, aquiferTiles); } else con << std::endl; } if (showTube && tubeTiles.count) { con << "Has HFS tubes : "; printMatdata(con, tubeTiles); } if (hasDemonTemple) { con << "Has demon temple" << std::endl; } if (hasLair) { con << "Has lair" << std::endl; } // Cleanup mats->Finish(); con << std::endl; return CR_OK; }