Merge remote-tracking branch 'PatrikLundell/embark-assistant' into develop

Also move changelog entries to misc improvements per #1383
develop
lethosor 2018-12-27 16:52:30 -05:00
commit 3e2c898e1a
8 changed files with 170 additions and 55 deletions

@ -54,6 +54,10 @@ changelog.txt uses a syntax similar to RST, with a few special sequences:
## Misc Improvements
- `devel/export-dt-ini`: added viewscreen offsets for DT 40.1.2
- `embark-assistant`:
- added match indicator display on the right ("World") map
- changed 'c'ancel to abort find if it's under way and clear results if not, allowing use of partial surveys.
- added Coal as a search criterion, as well as a coal indication as current embark selection info.
- `labormanager`: now takes nature value into account when assigning jobs
## Internals

@ -28,6 +28,7 @@ namespace embark_assist {
bool clay = false;
bool sand = false;
bool flux = false;
bool coal = false;
int8_t soil_depth;
int8_t offset;
int16_t elevation;
@ -51,6 +52,7 @@ namespace embark_assist {
uint16_t clay_count = 0;
uint16_t sand_count = 0;
uint16_t flux_count = 0;
uint16_t coal_count = 0;
uint8_t min_region_soil = 10;
uint8_t max_region_soil = 0;
bool waterfall = false;
@ -90,6 +92,7 @@ namespace embark_assist {
bool clay_absent = true;
bool sand_absent = true;
bool flux_absent = true;
bool coal_absent = true;
std::vector<bool> possible_metals;
std::vector<bool> possible_economics;
std::vector<bool> possible_minerals;
@ -113,6 +116,7 @@ namespace embark_assist {
bool clay;
bool sand;
bool flux;
bool coal;
std::vector<uint16_t> metals;
std::vector<uint16_t> economics;
std::vector<uint16_t> minerals;
@ -253,6 +257,7 @@ namespace embark_assist {
present_absent_ranges clay;
present_absent_ranges sand;
present_absent_ranges flux;
present_absent_ranges coal;
soil_ranges soil_min;
all_present_ranges soil_min_everywhere;
soil_ranges soil_max;

@ -143,7 +143,7 @@ DFhackCExport command_result plugin_init (color_ostream &out, std::vector <Plugi
" the embark rectangle as well as normally undisplayed sites in the\n"
" current embark region. It also has a site selection tool with more\n"
" options than DF's vanilla search tool. For detailed help invoke the\n"
" in game info screen. Requires 46 lines to display properly.\n"
" in game info screen. Prefers 46 lines to display properly.\n"
));
return CR_OK;
}

@ -44,6 +44,7 @@ namespace embark_assist {
clay,
sand,
flux,
coal,
soil_min,
soil_min_everywhere,
soil_max,
@ -508,6 +509,7 @@ namespace embark_assist {
case fields::clay:
case fields::sand:
case fields::flux:
case fields::coal:
{
embark_assist::defs::present_absent_ranges k = embark_assist::defs::present_absent_ranges::NA;
while (true) {
@ -993,6 +995,10 @@ namespace embark_assist {
state->finder_list.push_back({ "Flux", static_cast<int8_t>(i) });
break;
case fields::coal:
state->finder_list.push_back({ "Coal", static_cast<int8_t>(i) });
break;
case fields::soil_min:
state->finder_list.push_back({ "Min Soil", static_cast<int8_t>(i) });
break;
@ -1228,6 +1234,11 @@ namespace embark_assist {
static_cast<embark_assist::defs::present_absent_ranges>(state->ui[static_cast<uint8_t>(i)]->current_value);
break;
case fields::coal:
finder.coal =
static_cast<embark_assist::defs::present_absent_ranges>(state->ui[static_cast<uint8_t>(i)]->current_value);
break;
case fields::soil_min:
finder.soil_min =
static_cast<embark_assist::defs::soil_ranges>(state->ui[static_cast<uint8_t>(i)]->current_value);

@ -127,8 +127,8 @@ namespace embark_assist{
help_text.push_back("Main screen control keys used by the Embark Assistant:");
help_text.push_back("i: Info/Help. Brings up this display.");
help_text.push_back("f: Brings up the Find Embark screen. See the Find page for more information.");
help_text.push_back("c: Clears the results of a Find operation, and also cancels an operation if");
help_text.push_back(" one is under way.");
help_text.push_back("c: Clears the results of a Find operation, or cancels an operation if one is");
help_text.push_back(" under way (at which time a second 'c' clears it).");
help_text.push_back("q: Quits the Embark Assistant and brings you back to the vanilla DF interface.");
help_text.push_back(" It can be noted that the Embark Assistant automatically cancels itself");
help_text.push_back(" when DF leaves the embark screen either through <ESC>Abort Game or by");
@ -171,8 +171,8 @@ namespace embark_assist{
help_text.push_back("A list of all economic minerals present in the embark. Both clays and flux");
help_text.push_back("stones are economic, so they show up here as well.");
help_text.push_back("In addition to the above, the Find functionality can also produce blinking");
help_text.push_back("overlays over the region map and the middle world map to indicate where");
help_text.push_back("matching embarks are found. The region display marks the top left corner of");
help_text.push_back("overlays over the Local, Region, and World maps to indicate where");
help_text.push_back("matching embarks are found. The Local display marks the top left corner of");
help_text.push_back("a matching embark rectangle as a matching tile.");
break;
@ -257,14 +257,13 @@ namespace embark_assist{
help_text.push_back("- The geo information is gathered by code which is essentially a");
help_text.push_back(" copy of parts of prospector's code adapted for this plugin.");
help_text.push_back("- Clay determination is made by finding the reaction MAKE_CLAY_BRICKS.");
help_text.push_back(" Flux determination is made by finding the reaction PIG_IRON_MAKING.");
help_text.push_back("- Right world map overlay not implemented as author has failed to");
help_text.push_back(" emulate the sizing logic exactly.");
help_text.push_back("- Flux determination is made by finding the reaction PIG_IRON_MAKING.");
help_text.push_back("- Coal is detected by finding COAL producing reactions on minerals.");
help_text.push_back("- There's currently a DF bug (#0010267) that causes adamantine spires");
help_text.push_back(" reaching caverns that have been removed at world gen to fail to be");
help_text.push_back(" generated at all. It's likely this bug also affects magma pools.");
help_text.push_back(" This plugin does not address this but scripts can correct it.");
help_text.push_back("Version 0.5 2018-07-13");
help_text.push_back("Version 0.8 2018-12-04");
break;
}

@ -46,6 +46,7 @@ namespace embark_assist {
bool clay_found = false;
bool sand_found = false;
bool flux_found = false;
bool coal_found = false;
uint8_t max_soil = 0;
bool uneven = false;
int16_t min_temperature = survey_results->at(x).at(y).min_temperature[mlt->at(start_x).at(start_y).biome_offset];
@ -174,6 +175,12 @@ namespace embark_assist {
flux_found = true;
}
// Coal
if (mlt->at(i).at(k).coal) {
if (finder->coal == embark_assist::defs::present_absent_ranges::Absent) return false;
coal_found = true;
}
// Min Soil
if (finder->soil_min != embark_assist::defs::soil_ranges::NA &&
mlt->at(i).at(k).soil_depth < static_cast<uint16_t>(finder->soil_min) &&
@ -335,6 +342,9 @@ namespace embark_assist {
// Flux
if (finder->flux == embark_assist::defs::present_absent_ranges::Present && !flux_found) return false;
// Coal
if (finder->coal == embark_assist::defs::present_absent_ranges::Present && !coal_found) return false;
// Min Soil
if (finder->soil_min != embark_assist::defs::soil_ranges::NA &&
finder->soil_min_everywhere == embark_assist::defs::all_present_ranges::Present &&
@ -571,6 +581,7 @@ namespace embark_assist {
case embark_assist::defs::present_absent_ranges::Present:
if (tile->clay_count == 0) return false;
break;
case embark_assist::defs::present_absent_ranges::Absent:
if (tile->clay_count > 256 - embark_size) return false;
break;
@ -584,6 +595,7 @@ namespace embark_assist {
case embark_assist::defs::present_absent_ranges::Present:
if (tile->sand_count == 0) return false;
break;
case embark_assist::defs::present_absent_ranges::Absent:
if (tile->sand_count > 256 - embark_size) return false;
break;
@ -597,11 +609,26 @@ namespace embark_assist {
case embark_assist::defs::present_absent_ranges::Present:
if (tile->flux_count == 0) return false;
break;
case embark_assist::defs::present_absent_ranges::Absent:
if (tile->flux_count > 256 - embark_size) return false;
break;
}
// Coal
switch (finder->coal) {
case embark_assist::defs::present_absent_ranges::NA:
break; // No restriction
case embark_assist::defs::present_absent_ranges::Present:
if (tile->coal_count == 0) return false;
break;
case embark_assist::defs::present_absent_ranges::Absent:
if (tile->coal_count > 256 - embark_size) return false;
break;
}
// Soil Min
switch (finder->soil_min) {
case embark_assist::defs::soil_ranges::NA:
@ -1027,6 +1054,7 @@ namespace embark_assist {
case embark_assist::defs::present_absent_ranges::Present:
if (tile->clay_count == 0) return false;
break;
case embark_assist::defs::present_absent_ranges::Absent:
if (tile->clay_count == 256) return false;
break;
@ -1040,6 +1068,7 @@ namespace embark_assist {
case embark_assist::defs::present_absent_ranges::Present:
if (tile->sand_count == 0) return false;
break;
case embark_assist::defs::present_absent_ranges::Absent:
if (tile->sand_count == 256) return false;
break;
@ -1053,11 +1082,26 @@ namespace embark_assist {
case embark_assist::defs::present_absent_ranges::Present:
if (tile->flux_count == 0) return false;
break;
case embark_assist::defs::present_absent_ranges::Absent:
if (tile->flux_count == 256) return false;
break;
}
// Coal
switch (finder->coal) {
case embark_assist::defs::present_absent_ranges::NA:
break; // No restriction
case embark_assist::defs::present_absent_ranges::Present:
if (tile->coal_count == 0) return false;
break;
case embark_assist::defs::present_absent_ranges::Absent:
if (tile->coal_count == 256) return false;
break;
}
// Soil Min
switch (finder->soil_min) {
case embark_assist::defs::soil_ranges::NA:
@ -1518,11 +1562,11 @@ uint16_t embark_assist::matcher::find(embark_assist::defs::match_iterators *iter
preliminary_matches = preliminary_world_match(survey_results, &iterator->finder, match_results);
if (preliminary_matches == 0) {
out.printerr("matcher::find: Preliminarily matching world tiles: %i\n", preliminary_matches);
out.printerr("matcher::find: Preliminarily matching World Tiles: %i\n", preliminary_matches);
return 0;
}
else {
out.print("matcher::find: Preliminarily matching world tiles: %i\n", preliminary_matches);
out.print("matcher::find: Preliminarily matching World Tiles: %i\n", preliminary_matches);
}
while (screen->location.region_pos.x != 0 || screen->location.region_pos.y != 0) {

@ -48,7 +48,7 @@ namespace embark_assist {
std::vector<display_strings> embark_info;
Screen::Pen region_match_grid[16][16];
Screen::Pen local_match_grid[16][16];
pen_column *world_match_grid = nullptr;
uint16_t match_count = 0;
@ -60,26 +60,15 @@ namespace embark_assist {
//====================================================================
/* // Attempt to replicate the DF logic for sizing the right world map. This
// code seems to compute the values correctly, but the author hasn't been
// able to apply them at the same time as DF does to 100%.
// DF seems to round down on 0.5 values.
df::coord2d world_dimension_size(uint16_t available_screen, uint16_t map_size) {
uint16_t result;
for (uint16_t factor = 1; factor < 17; factor++) {
result = map_size / factor;
if ((map_size - result * factor) * 2 != factor) {
result = (map_size + factor / 2) / factor;
}
// Logic for sizing the World map to the right.
df::coord2d world_dimension_size(uint16_t map_size, uint16_t region_size) {
uint16_t factor = (map_size - 1 + region_size - 1) / region_size;
uint16_t result = (map_size + ((factor - 1) / 2)) / factor;
if (result > region_size) { result = region_size; }
if (result <= available_screen) {
return {result, factor};
}
}
return{16, 16}; // Should never get here.
return{ result, factor};
}
*/
//====================================================================
class ViewscreenOverlay : public df::viewscreen_choose_start_sitest
@ -114,9 +103,13 @@ namespace embark_assist {
state->embark_update();
}
else if (input->count(df::interface_key::CUSTOM_C)) {
state->match_active = false;
state->matching = false;
state->clear_match_callback();
if (state->matching) {
state->matching = false;
}
else {
state->match_active = false;
state->clear_match_callback();
}
}
else if (input->count(df::interface_key::CUSTOM_F)) {
if (!state->match_active && !state->matching) {
@ -155,6 +148,7 @@ namespace embark_assist {
Screen::Pen pen_lr(' ', COLOR_LIGHTRED);
Screen::Pen pen_w(' ', COLOR_WHITE);
Screen::Pen pen_g(' ', COLOR_GREY);
Screen::paintString(pen_lr, width - 28, 20, DFHack::Screen::getKeyDisplay(df::interface_key::CUSTOM_I).c_str(), false);
Screen::paintString(pen_w, width - 27, 20, ": Embark Assistant Info", false);
@ -166,6 +160,7 @@ namespace embark_assist {
Screen::paintString(pen_w, width - 27, 23, ": Quit Embark Assistant", false);
Screen::paintString(pen_w, width - 28, 25, "Matching World Tiles:", false);
Screen::paintString(empty_pen, width - 6, 25, to_string(state->match_count), false);
Screen::paintString(pen_g, width - 28, 26, "(Those on the Region Map)", false);
if (height > 25) { // Mask the vanilla DF find help as it's overridden.
Screen::paintString(pen_w, 50, height - 2, " ", false);
@ -221,29 +216,22 @@ namespace embark_assist {
for (uint8_t i = 0; i < 16; i++) {
for (uint8_t k = 0; k < 16; k++) {
if (state->region_match_grid[i][k].ch) {
Screen::paintTile(state->region_match_grid[i][k], i + 1, k + 2);
if (state->local_match_grid[i][k].ch) {
Screen::paintTile(state->local_match_grid[i][k], i + 1, k + 2);
}
}
}
/* // Stuff for trying to replicate the DF right world map sizing logic. Close, but not there.
Screen::Pen pen(' ', COLOR_YELLOW);
// Boundaries of the top level world map
Screen::paintString(pen, width / 2 - 5, 2, "X", false); // Marks UL corner of right world map. Constant
// Screen::paintString(pen, width - 30, 2, "X", false); // Marks UR corner of right world map area.
// Screen::paintString(pen, width / 2 - 5, height - 8, "X", false); // BL corner of right world map area.
// Screen::paintString(pen, width - 30, height - 8, "X", false); // BR corner of right world map area.
uint16_t l_width = width - 30 - (width / 2 - 5) + 1; // Horizontal space available for right world map.
uint16_t l_height = height - 8 - 2 + 1; // Vertical space available for right world map.
df::coord2d size_factor_x = world_dimension_size(l_width, world->worldgen.worldgen_parms.dim_x);
df::coord2d size_factor_y = world_dimension_size(l_height, world->worldgen.worldgen_parms.dim_y);
Screen::paintString(pen, width / 2 - 5 + size_factor_x.x - 1, 2, "X", false);
Screen::paintString(pen, width / 2 - 5, 2 + size_factor_y.x - 1, "X", false);
Screen::paintString(pen, width / 2 - 5 + size_factor_x.x - 1, 2 + size_factor_y.x - 1, "X", false);
*/
df::coord2d size_factor_x = world_dimension_size(world->worldgen.worldgen_parms.dim_x, width / 2 - 24);
df::coord2d size_factor_y = world_dimension_size(world->worldgen.worldgen_parms.dim_y, height - 9);
for (uint16_t i = 0; i < world->worldgen.worldgen_parms.dim_x; i++) {
for (uint16_t k = 0; k < world->worldgen.worldgen_parms.dim_y; k++) {
if (state->world_match_grid[i][k].ch) {
Screen::paintTile(state->world_match_grid[i][k], width / 2 - 5 + min(size_factor_x.x - 1, i / size_factor_x.y), 2 + min(size_factor_y.x - 1, k / size_factor_y.y));
}
}
}
}
if (state->matching) {
@ -351,6 +339,10 @@ void embark_assist::overlay::set_embark(embark_assist::defs::site_infos *site_in
state->embark_info.push_back({ Screen::Pen(' ', COLOR_RED), "Clay" });
}
if (site_info->coal) {
state->embark_info.push_back({ Screen::Pen(' ', COLOR_GREY), "Coal" });
}
state->embark_info.push_back({ Screen::Pen(' ', COLOR_BROWN), "Soil " + std::to_string(site_info->min_soil) + " - " + std::to_string(site_info->max_soil) });
if (site_info->flat) {
@ -390,11 +382,11 @@ void embark_assist::overlay::set_mid_level_tile_match(embark_assist::defs::mlt_m
for (uint8_t i = 0; i < 16; i++) {
for (uint8_t k = 0; k < 16; k++) {
if (mlt_matches[i][k]) {
state->region_match_grid[i][k] = green_x_pen;
state->local_match_grid[i][k] = green_x_pen;
}
else {
state->region_match_grid[i][k] = empty_pen;
state->local_match_grid[i][k] = empty_pen;
}
}
}
@ -411,7 +403,7 @@ void embark_assist::overlay::clear_match_results() {
for (uint8_t i = 0; i < 16; i++) {
for (uint8_t k = 0; k < 16; k++) {
state->region_match_grid[i][k] = empty_pen;
state->local_match_grid[i][k] = empty_pen;
}
}
}

@ -10,6 +10,7 @@
#include "modules/Materials.h"
#include "DataDefs.h"
#include "df/builtin_mats.h"
#include "df/coord2d.h"
#include "df/creature_interaction_effect.h"
#include "df/creature_interaction_effect_display_symbolst.h"
@ -34,6 +35,9 @@
#include "df/interaction_target_materialst.h"
#include "df/material_common.h"
#include "df/reaction.h"
#include "df/reaction_product.h"
#include "df/reaction_product_itemst.h"
#include "df/reaction_product_type.h"
#include "df/region_map_entry.h"
#include "df/syndrome.h"
#include "df/viewscreen.h"
@ -66,6 +70,7 @@ namespace embark_assist {
struct states {
uint16_t clay_reaction = -1;
uint16_t flux_reaction = -1;
std::vector<uint16_t> coals;
uint16_t x;
uint16_t y;
uint8_t local_min_x;
@ -104,6 +109,19 @@ namespace embark_assist {
out.printerr("The reaction 'PIG_IRON_MAKING' was not found, so flux can't be identified.\n");
}
for (uint16_t i = 0; i < world->raws.inorganics.size(); i++) {
for (uint16_t k = 0; k < world->raws.inorganics[i]->economic_uses.size(); k++) {
for (uint16_t l = 0; l < world->raws.reactions.reactions[world->raws.inorganics[i]->economic_uses[k]]->products.size(); l++) {
df::reaction_product_itemst *product = static_cast<df::reaction_product_itemst*>(world->raws.reactions.reactions[world->raws.inorganics[i]->economic_uses[k]]->products[l]);
if (product->mat_type == df::builtin_mats::COAL) {
state->coals.push_back(i);
break;
}
}
}
}
for (uint16_t i = 0; i < world_data->geo_biomes.size(); i++) {
geo_summary->at(i).possible_metals.resize(state->max_inorganic);
geo_summary->at(i).possible_economics.resize(state->max_inorganic);
@ -154,6 +172,13 @@ namespace embark_assist {
}
}
for (uint16_t l = 0; l < state->coals.size(); l++) {
if (layer->mat_index == state->coals[l]) {
geo_summary->at(i).coal_absent = false;
break;
}
}
size = (uint16_t)layer->vein_mat.size();
for (uint16_t l = 0; l < size; l++) {
@ -176,6 +201,14 @@ namespace embark_assist {
geo_summary->at(i).flux_absent = false;
}
}
for (uint16_t m = 0; m < state->coals.size(); m++) {
if (vein== state->coals[m]) {
geo_summary->at(i).coal_absent = false;
break;
}
}
}
}
@ -531,6 +564,7 @@ void embark_assist::survey::high_level_world_survey(embark_assist::defs::geo_dat
results.clay_count = 0;
results.sand_count = 0;
results.flux_count = 0;
results.coal_count = 0;
results.min_region_soil = 10;
results.max_region_soil = 0;
results.waterfall = false;
@ -576,6 +610,7 @@ void embark_assist::survey::high_level_world_survey(embark_assist::defs::geo_dat
if (!geo_summary->at(geo_index).clay_absent) results.clay_count++;
if (!geo_summary->at(geo_index).sand_absent) results.sand_count++;
if (!geo_summary->at(geo_index).flux_absent) results.flux_count++;
if (!geo_summary->at(geo_index).coal_absent) results.coal_count++;
if (geo_summary->at(geo_index).soil_size < results.min_region_soil)
results.min_region_soil = geo_summary->at(geo_index).soil_size;
@ -614,6 +649,8 @@ void embark_assist::survey::high_level_world_survey(embark_assist::defs::geo_dat
if (results.clay_count == offset_count) results.clay_count = 256;
if (results.sand_count == offset_count) results.sand_count = 256;
if (results.flux_count == offset_count) results.flux_count = 256;
if (results.coal_count == offset_count) results.coal_count = 256;
for (uint8_t l = 0; l < 3; l++) {
if (results.savagery_count[l] == offset_count) results.savagery_count[l] = 256;
if (results.evilness_count[l] == offset_count) results.evilness_count[l] = 256;
@ -776,6 +813,8 @@ void embark_assist::survey::survey_mid_level_tile(embark_assist::defs::geo_data
mlt->at(i).at(k).clay = false;
mlt->at(i).at(k).sand = false;
mlt->at(i).at(k).flux = false;
mlt->at(i).at(k).coal = false;
if (max_soil_depth == 0) {
mlt->at(i).at(k).soil_depth = 0;
}
@ -869,6 +908,13 @@ void embark_assist::survey::survey_mid_level_tile(embark_assist::defs::geo_data
mlt->at(i).at(k).flux = true;
}
}
for (uint16_t m = 0; m < state->coals.size(); m++) {
if (layer->mat_index == state->coals [m]) {
mlt->at(i).at(k).coal = true;
break;
}
}
}
end_check_m = static_cast<uint16_t>(layer->vein_mat.size());
@ -895,6 +941,13 @@ void embark_assist::survey::survey_mid_level_tile(embark_assist::defs::geo_data
mlt->at(i).at(k).flux = true;
}
}
for (uint16_t n = 0; n < state->coals.size(); n++) {
if (layer->vein_mat [m] == state->coals[n]) {
mlt->at(i).at(k).coal = true;
break;
}
}
}
}
@ -911,6 +964,7 @@ void embark_assist::survey::survey_mid_level_tile(embark_assist::defs::geo_data
survey_results->at(x).at(y).clay_count = 0;
survey_results->at(x).at(y).sand_count = 0;
survey_results->at(x).at(y).flux_count = 0;
survey_results->at(x).at(y).coal_count = 0;
survey_results->at(x).at(y).min_region_soil = 10;
survey_results->at(x).at(y).max_region_soil = 0;
survey_results->at(x).at(y).savagery_count[0] = 0;
@ -929,6 +983,7 @@ void embark_assist::survey::survey_mid_level_tile(embark_assist::defs::geo_data
if (mlt->at(i).at(k).clay) { survey_results->at(x).at(y).clay_count++; }
if (mlt->at(i).at(k).sand) { survey_results->at(x).at(y).sand_count++; }
if (mlt->at(i).at(k).flux) { survey_results->at(x).at(y).flux_count++; }
if (mlt->at(i).at(k).coal) { survey_results->at(x).at(y).coal_count++; }
if (mlt->at(i).at(k).soil_depth < survey_results->at(x).at(y).min_region_soil) {
survey_results->at(x).at(y).min_region_soil = mlt->at(i).at(k).soil_depth;
@ -1170,6 +1225,7 @@ void embark_assist::survey::survey_embark(embark_assist::defs::mid_level_tiles *
site_info->clay = false;
site_info->sand = false;
site_info->flux = false;
site_info->coal = false;
site_info->metals.clear();
site_info->economics.clear();
site_info->metals.clear();
@ -1222,6 +1278,10 @@ void embark_assist::survey::survey_embark(embark_assist::defs::mid_level_tiles *
site_info->flux = true;
}
if (mlt->at(i).at(k).coal) {
site_info->coal = true;
}
for (uint16_t l = 0; l < state->max_inorganic; l++) {
metals[l] = metals[l] || mlt->at(i).at(k).metals[l];
economics[l] = economics[l] || mlt->at(i).at(k).economics[l];