From 7705eada5ad24410f5302ad8711c44e1464220f7 Mon Sep 17 00:00:00 2001 From: PatrikLundell Date: Mon, 26 Feb 2018 18:31:33 +0100 Subject: [PATCH] Added magma/candy search + profile save/load. --- build/win64/install-debug.bat | 2 +- plugins/embark-assistant/defs.h | 24 ++- plugins/embark-assistant/finder_ui.cpp | 248 ++++++++++++++++++++++++- plugins/embark-assistant/help_ui.cpp | 26 ++- plugins/embark-assistant/matcher.cpp | 44 +++++ plugins/embark-assistant/survey.cpp | 28 ++- 6 files changed, 351 insertions(+), 21 deletions(-) diff --git a/build/win64/install-debug.bat b/build/win64/install-debug.bat index 0b8758461..64b5ae850 100644 --- a/build/win64/install-debug.bat +++ b/build/win64/install-debug.bat @@ -1,4 +1,4 @@ -call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" amd64 +call "D:\Program (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" amd64 cd VC2015 msbuild /m /p:Platform=x64 /p:Configuration=RelWithDebInfo INSTALL.vcxproj cd .. \ No newline at end of file diff --git a/plugins/embark-assistant/defs.h b/plugins/embark-assistant/defs.h index 79ad5dd5b..bea91dae6 100644 --- a/plugins/embark-assistant/defs.h +++ b/plugins/embark-assistant/defs.h @@ -33,6 +33,8 @@ namespace embark_assist { int16_t elevation; bool river_present = false; int16_t river_elevation = 100; + int8_t adamantine_level; // -1 = none, 0 .. 3 = cavern 1 .. magma sea. Currently not used beyond present/absent. + int8_t magma_level; // -1 = none, 0 .. 3 = cavern 3 .. surface/volcano int8_t biome_offset; uint8_t savagery_level; // 0 - 2 uint8_t evilness_level; // 0 - 2 @@ -42,7 +44,6 @@ namespace embark_assist { }; typedef std::array, 16> mid_level_tiles; -// typedef mid_level_tile mid_level_tiles[16][16]; struct region_tile_datum { bool surveyed = false; @@ -53,7 +54,6 @@ namespace embark_assist { uint8_t min_region_soil = 10; uint8_t max_region_soil = 0; bool waterfall = false; - river_sizes river_size; int16_t biome_index[10]; // Indexed through biome_offset; -1 = null, Index of region, [0] not used int16_t biome[10]; // Indexed through biome_offset; -1 = null, df::biome_type, [0] not used @@ -162,6 +162,22 @@ namespace embark_assist { Major }; +// enum class adamantine_ranges : int8_t { +// NA = -1, +// Cavern_1, +// Cavern_2, +// Cavern_3, +// Magma_Sea +// }; + + enum class magma_ranges : int8_t { + NA = -1, + Cavern_3, + Cavern_2, + Cavern_1, + Volcano + }; + enum class yes_no_ranges : int8_t { NA = -1, Yes, @@ -218,6 +234,10 @@ namespace embark_assist { yes_no_ranges evil_weather; // Will probably blow up with the magic release arcs... yes_no_ranges reanimation; yes_no_ranges thralling; + int8_t spire_count_min; // N/A(-1), 0-9 + int8_t spire_count_max; // N/A(-1), 0-9 + magma_ranges magma_min; + magma_ranges magma_max; int8_t biome_count_min; // N/A(-1), 1-9 int8_t biome_count_max; // N/A(-1), 1-9 int8_t region_type_1; // N/A(-1), df::world_region_type diff --git a/plugins/embark-assistant/finder_ui.cpp b/plugins/embark-assistant/finder_ui.cpp index feea89199..fdc4a57e8 100644 --- a/plugins/embark-assistant/finder_ui.cpp +++ b/plugins/embark-assistant/finder_ui.cpp @@ -1,3 +1,4 @@ +#include #include "Core.h" #include @@ -5,6 +6,7 @@ #include "Types.h" +#include "MemAccess.h" #include "df/biome_type.h" #include "df/inorganic_raw.h" #include "df/material_flags.h" @@ -19,6 +21,8 @@ using df::global::world; +#define profile_file_name ".\\data\\init\\embark_assistant_profile.txt" + namespace embark_assist { namespace finder_ui { @@ -45,6 +49,10 @@ namespace embark_assist { evil_weather, reanimation, thralling, + spire_count_min, + spire_count_max, + magma_min, + magma_max, biome_count_min, biome_count_max, region_type_1, @@ -136,6 +144,132 @@ namespace embark_assist { //========================================================================================================== + void save_profile() { + color_ostream_proxy out(Core::getInstance().getConsole()); + + FILE* outfile = fopen(profile_file_name, "w"); + fields i = first_fields; + + while (true) { + out.print("[%s:%i]\n", state->finder_list[static_cast(i)].text.c_str(), state->ui[static_cast(i)]->current_value); + fprintf(outfile, "[%s:%i]\n", state->finder_list[static_cast(i)].text.c_str(), state->ui[static_cast(i)]->current_value); + if (i == last_fields) { + break; // done + } + + i = static_cast (static_cast(i) + 1); + } + + fclose(outfile); + } + + //========================================================================================================== + + void load_profile() { + color_ostream_proxy out(Core::getInstance().getConsole()); + FILE* infile = fopen(profile_file_name, "r"); + + if (!infile) { + out.printerr("No profile file found at %s\n", profile_file_name); + return; + } + + fields i = first_fields; + char line[80]; + int count = 80; + bool found; + int value; + + while (true) { + + fgets(line, count, infile); + if (line[0] != '[') { + out.printerr("Failed to find token start '[' at line %i\n", static_cast(i)); + return; + } + + found = false; + + for (int k = 1; k < count; k++) { + if (line[k] == ':') { + for (int l = 1; l < k; l++) { + if (state->finder_list[static_cast(i)].text.c_str()[l - 1] != line[l]) { + out.printerr("Token mismatch of %s vs %s\n", line, state->finder_list[static_cast(i)].text.c_str()); + return; + } + } + if (!sscanf(&line[k + 1], "%i]", &value)) { + out.printerr("Value extraction failure from %s\n", line); + return; + } + + for (int l = 0; l < state->ui[static_cast(i)]->list.size(); l++) { + if (value == state->ui[static_cast(i)]->list[l].key) { + found = true; + break; + } + } + + if (!found) { + out.printerr("Value not found in plugin. Raw mismatch? %s\n", line); + return; + } + + break; + } + } + + if (!found) { + out.printerr("Value delimiter not found in %s\n", line); + return; + } + + if (i == last_fields) { + break; // done + } + + i = static_cast (static_cast(i) + 1); + } + + fclose(infile); + + // Checking done. No do the work. + + infile = fopen(profile_file_name, "r"); + i = first_fields; + + while (true) { + fgets(line, count, infile); + + for (int k = 1; k < count; k++) { + if (line[k] == ':') { + sscanf(&line[k + 1], "%i]", &value); + + state->ui[static_cast(i)]->current_value = value; + + for (int l = 0; l < state->ui[static_cast(i)]->list.size(); l++) { + if (value == state->ui[static_cast(i)]->list[l].key) { + state->ui[static_cast(i)]->current_display_value = l; + break; + } + } + + break; + } + } + + if (i == last_fields) { + break; // done + } + + i = static_cast (static_cast(i) + 1); + } + + fclose(infile); + } + + //========================================================================================================== + void ui_setup(embark_assist::defs::find_callbacks find_callback, uint16_t max_inorganic) { // color_ostream_proxy out(Core::getInstance().getConsole()); if (!embark_assist::finder_ui::state) { @@ -419,6 +553,56 @@ namespace embark_assist { break; + case fields::spire_count_min: + case fields::spire_count_max: + for (int16_t k = -1; k <= 9; k++) { + if (k == -1) { + element->list.push_back({ "N/A", k }); + } + else { + element->list.push_back({ std::to_string(k), k }); + } + } + + break; + + case fields::magma_min: + case fields::magma_max: + { + embark_assist::defs::magma_ranges k = embark_assist::defs::magma_ranges::NA; + while (true) { + switch (k) { + case embark_assist::defs::magma_ranges::NA: + element->list.push_back({ "N/A", static_cast(k) }); + break; + + case embark_assist::defs::magma_ranges::Cavern_3: + element->list.push_back({ "3:rd Cavern", static_cast(k) }); + break; + + case embark_assist::defs::magma_ranges::Cavern_2: + element->list.push_back({ "2:nd Cavern", static_cast(k) }); + break; + + case embark_assist::defs::magma_ranges::Cavern_1: + element->list.push_back({ "1:st Cavern", static_cast(k) }); + break; + + case embark_assist::defs::magma_ranges::Volcano: + element->list.push_back({ "Volcano", static_cast(k) }); + break; + } + + if (k == embark_assist::defs::magma_ranges::Volcano) { + break; + } + + k = static_cast (static_cast(k) + 1); + } + } + + break; + case fields::biome_count_min: case fields::biome_count_max: for (int16_t k = 0; k < 10; k++) { @@ -659,6 +843,22 @@ namespace embark_assist { state->finder_list.push_back({ "Max Soil", static_cast(i) }); break; + case fields::spire_count_min: + state->finder_list.push_back({ "Min Adamantine", static_cast(i) }); + break; + + case fields::spire_count_max: + state->finder_list.push_back({ "Max Adamantine", static_cast(i) }); + break; + + case fields::magma_min: + state->finder_list.push_back({ "Min Magma", static_cast(i) }); + break; + + case fields::magma_max: + state->finder_list.push_back({ "Max Magma", static_cast(i) }); + break; + case fields::biome_count_min: state->finder_list.push_back({ "Min Biome Count", static_cast(i) }); break; @@ -875,6 +1075,24 @@ namespace embark_assist { static_cast(state->ui[static_cast(i)]->current_value); break; + case fields::spire_count_min: + finder.spire_count_min = state->ui[static_cast(i)]->current_value; + break; + + case fields::spire_count_max: + finder.spire_count_max = state->ui[static_cast(i)]->current_value; + break; + + case fields::magma_min: + finder.magma_min = + static_cast(state->ui[static_cast(i)]->current_value); + break; + + case fields::magma_max: + finder.magma_max = + static_cast(state->ui[static_cast(i)]->current_value); + break; + case fields::biome_count_min: finder.biome_count_min = state->ui[static_cast(i)]->current_value; break; @@ -1015,17 +1233,25 @@ namespace embark_assist { state->ui[state->finder_list_focus]->current_index = 0; } } + } else if (input->count(df::interface_key::SELECT)) { if (!state->finder_list_active) { state->ui[state->finder_list_focus]->current_display_value = state->ui[state->finder_list_focus]->current_index; state->ui[state->finder_list_focus]->current_value = state->ui[state->finder_list_focus]->list[state->ui[state->finder_list_focus]->current_index].key; state->finder_list_active = true; } + } else if (input->count(df::interface_key::CUSTOM_F)) { input->clear(); Screen::dismiss(this); find(); return; + + } else if (input->count(df::interface_key::CUSTOM_S)) { // Save + save_profile(); + + } else if (input->count(df::interface_key::CUSTOM_L)) { // Load + load_profile(); } } @@ -1041,15 +1267,19 @@ namespace embark_assist { Screen::drawBorder("Embark Assistant Site Finder"); embark_assist::screen::paintString(lr_pen, 1, 1, "4/6"); - embark_assist::screen::paintString(white_pen, 4, 1, ":Shift list"); - embark_assist::screen::paintString(lr_pen, 16, 1, "8/2"); - embark_assist::screen::paintString(white_pen, 19, 1, ":Up/down"); - embark_assist::screen::paintString(lr_pen, 28, 1, "ENTER"); - embark_assist::screen::paintString(white_pen, 33, 1, ":Select item"); - embark_assist::screen::paintString(lr_pen, 46, 1, "f"); - embark_assist::screen::paintString(white_pen, 47, 1, ":Find"); - embark_assist::screen::paintString(lr_pen, 53, 1, "ESC"); - embark_assist::screen::paintString(white_pen, 56, 1, ":Abort"); + embark_assist::screen::paintString(white_pen, 4, 1, ":<->"); + embark_assist::screen::paintString(lr_pen, 9, 1, "8/2"); + embark_assist::screen::paintString(white_pen, 12, 1, ":Up/Down"); + embark_assist::screen::paintString(lr_pen, 21, 1, "ENTER"); + embark_assist::screen::paintString(white_pen, 26, 1, ":Select"); + embark_assist::screen::paintString(lr_pen, 34, 1, "f"); + embark_assist::screen::paintString(white_pen, 35, 1, ":Find"); + embark_assist::screen::paintString(lr_pen, 41, 1, "ESC"); + embark_assist::screen::paintString(white_pen, 44, 1, ":Abort"); + embark_assist::screen::paintString(lr_pen, 51, 1, "s"); + embark_assist::screen::paintString(white_pen, 52, 1, ":Save"); + embark_assist::screen::paintString(lr_pen, 58, 1, "l"); + embark_assist::screen::paintString(white_pen, 59, 1, ":Load"); for (uint16_t i = 0; i < state->finder_list.size(); i++) { if (i == state->finder_list_focus) { diff --git a/plugins/embark-assistant/help_ui.cpp b/plugins/embark-assistant/help_ui.cpp index 7be6b38d7..31a24e891 100644 --- a/plugins/embark-assistant/help_ui.cpp +++ b/plugins/embark-assistant/help_ui.cpp @@ -109,10 +109,10 @@ namespace embark_assist{ help_text.push_back("- Site find search. Richer set of selection criteria than the vanilla"); help_text.push_back(" DF Find that Embark Assistant suppresses (by using the same key)."); help_text.push_back(""); - help_text.push_back("The functionality requires a screen height of at least 42 lines to display"); + help_text.push_back("The functionality requires a screen height of at least 46 lines to display"); help_text.push_back("correctly (that's the height of the Finder screen), as fitting everything"); help_text.push_back("onto a standard 80*25 screen would be too challenging. The help is adjusted"); - help_text.push_back("to fit into onto an 80*42 screen."); + help_text.push_back("to fit into onto an 80*46 screen as well."); help_text.push_back("This help/info is split over several screens, and you can move between them"); help_text.push_back("using the TAB/Shift-TAB keys, and leave the help from any screen using ESC."); help_text.push_back(""); @@ -188,6 +188,9 @@ namespace embark_assist{ help_text.push_back("ENTER to select a value in the value list, entering it among the selections."); help_text.push_back("f to activate the Find functionality using the values in the middle column."); help_text.push_back("ESC to leave the screen without activating a Find operation."); + help_text.push_back("s/l is used to save/load search profile to/from embark_assistant_profile.txt"); + help_text.push_back("stored in .\\data\\init. There's some minor error detection that will refuse"); + help_text.push_back("to load a file that doesn't check out."); help_text.push_back("The X and Y dimensions are those of the embark to search for. Unlike DF"); help_text.push_back("itself these parameters are initiated to match the actual embark rectangle"); help_text.push_back("when a new search is initiated (prior results are cleared."); @@ -211,7 +214,7 @@ namespace embark_assist{ help_text.push_back("feature is Present in the embark, and entering the same value multiple"); help_text.push_back("times does nothing (the first match ticks all requirements off). It can be"); help_text.push_back("noted that all the Economic materials are found in the much longer Mineral"); - help_text.push_back("list. Note that Find is a fairly time consuming task (is it is in vanilla)."); + help_text.push_back("list. Note that Find is a fairly time consuming task (as it is in vanilla)."); break; case pages::Caveats: @@ -250,13 +253,18 @@ namespace embark_assist{ 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("Version 0.2 2018-02-25"); + help_text.push_back("- There's currently a DF bug that causes adamantine spires reaching"); + help_text.push_back(" that have been removed at world gen to fail to be generated. It's likely"); + help_text.push_back(" this bug also affects magma pools. This plugin does not address this."); + help_text.push_back("Version 0.3 2018-02-26"); break; } // Add control keys to first line. - embark_assist::screen::paintString(pen_lr, 1, 1, "TAB/Shift-TAB"); + embark_assist::screen::paintString(pen_lr, 1, 1, "TAB"); + embark_assist::screen::paintString(pen, 4, 1, "/"); + embark_assist::screen::paintString(pen_lr, 5, 1, "Shift-TAB"); embark_assist::screen::paintString(pen, 14, 1, ":Next/Previous Page"); embark_assist::screen::paintString(pen_lr, 34, 1, "ESC"); embark_assist::screen::paintString(pen, 37, 1, ":Leave Info/Help"); @@ -285,11 +293,15 @@ namespace embark_assist{ break; case pages::Finder: - embark_assist::screen::paintString(pen_lr, 1, 4, "4/6"); - embark_assist::screen::paintString(pen_lr, 1, 5, "8/2"); + embark_assist::screen::paintString(pen_lr, 1, 4, "4"); + embark_assist::screen::paintString(pen_lr, 3, 4, "6"); + embark_assist::screen::paintString(pen_lr, 1, 5, "8"); + embark_assist::screen::paintString(pen_lr, 3, 5, "2"); embark_assist::screen::paintString(pen_lr, 1, 6, "ENTER"); embark_assist::screen::paintString(pen_lr, 1, 7, "f"); embark_assist::screen::paintString(pen_lr, 1, 8, "ESC"); + embark_assist::screen::paintString(pen_lr, 1, 9, "s"); + embark_assist::screen::paintString(pen_lr, 3, 9, "l"); break; case pages::Caveats: diff --git a/plugins/embark-assistant/matcher.cpp b/plugins/embark-assistant/matcher.cpp index 484ee3cf8..eb73eda2c 100644 --- a/plugins/embark-assistant/matcher.cpp +++ b/plugins/embark-assistant/matcher.cpp @@ -51,6 +51,8 @@ namespace embark_assist { bool evil_weather_found = false; bool reanimation_found = false; bool thralling_found = false; + uint8_t spire_count = 0; + int8_t magma_level = -1; bool biomes[ENUM_LAST_ITEM(biome_type) + 1]; bool region_types[ENUM_LAST_ITEM(world_region_type) + 1]; uint8_t biome_count; @@ -199,6 +201,24 @@ namespace embark_assist { thralling_found = true; } + // Spires + if (mlt->at(i).at(k).adamantine_level != -1) { + spire_count++; + + if (finder->spire_count_max != -1 && + finder->spire_count_max < spire_count) return false; + } + + // Magma + if (mlt->at(i).at(k).magma_level != -1) { + if (mlt->at(i).at(k).magma_level > magma_level) + { + magma_level = mlt->at(i).at(k).magma_level; + if (finder->magma_max != embark_assist::defs::magma_ranges::NA && + static_cast(finder->magma_max) < magma_level) return false; + } + } + // Biomes biomes[survey_results->at(x).at(y).biome[mlt->at(i).at(k).biome_offset]] = true; @@ -292,6 +312,14 @@ namespace embark_assist { // Thralling if (finder->thralling == embark_assist::defs::yes_no_ranges::Yes && !thralling_found) return false; + // Spires + if (finder->spire_count_min != -1 && finder->spire_count_min > spire_count) return false; + if (finder->spire_count_max != -1 && finder->spire_count_max < spire_count) return false; + + // Magma + if (// finder->magma_min != embark_assist::defs::magma_ranges::NA && // This check is redundant. + finder->magma_min > static_cast(magma_level)) return false; + // Biomes if (finder->biome_count_min != -1 || finder->biome_count_max != -1) { @@ -612,6 +640,8 @@ namespace embark_assist { break; } + // Spire Count Min/Max + // Magma Min/Max // Biome Count Min (Can't do anything with Max at this level) if (finder->biome_count_min > tile->biome_count) return false; @@ -964,6 +994,8 @@ namespace embark_assist { break; } + // Spire Count Min/Max + // Magma Min/Max // Biome Count Min (Can't do anything with Max at this level) if (finder->biome_count_min > tile->biome_count) return false; @@ -1304,6 +1336,18 @@ uint16_t embark_assist::matcher::find(embark_assist::defs::match_iterators *iter return 0; } + if (iterator->finder.spire_count_max < iterator->finder.spire_count_min && + iterator->finder.spire_count_max != -1) { + out.printerr("matcher::find: Will never find any matches with max spires < min spires\n"); + return 0; + } + + if (iterator->finder.magma_max < iterator->finder.magma_min && + iterator->finder.magma_max != embark_assist::defs::magma_ranges::NA) { + out.printerr("matcher::find: Will never find any matches with max magma < min magma\n"); + return 0; + } + if (iterator->finder.biome_count_max < iterator->finder.biome_count_min && iterator->finder.biome_count_max != -1) { out.printerr("matcher::find: Will never find any matches with max biomes < min biomes\n"); diff --git a/plugins/embark-assistant/survey.cpp b/plugins/embark-assistant/survey.cpp index 15fd3883a..d11952ba9 100644 --- a/plugins/embark-assistant/survey.cpp +++ b/plugins/embark-assistant/survey.cpp @@ -14,6 +14,10 @@ #include "df/creature_interaction_effect_display_symbolst.h" #include "df/creature_interaction_effect_type.h" #include "df/feature_init.h" +#include "df/feature_init_deep_special_tubest.h" +#include "df/feature_init_magma_poolst.h" +#include "df/feature_init_volcanost.h" +#include "df/feature_type.h" #include "df/inorganic_flags.h" #include "df/inorganic_raw.h" #include "df/interaction.h" @@ -577,12 +581,33 @@ void embark_assist::survey::survey_mid_level_tile(embark_assist::defs::geo_data base_z = elevation - 1; features = details->features[i][k]; std::map layer_bottom, layer_top; + mlt->at(i).at(k).adamantine_level = -1; + mlt->at(i).at(k).magma_level = -1; end_check_l = static_cast(features.size()); for (size_t l = 0; l < end_check_l; l++) { auto feature = features[l]; - if (feature->layer != -1 && + if (feature->feature_idx != -1) { + switch (world_data->feature_map[x / 16][y / 16].features->feature_init[x % 16][y % 16][feature->feature_idx]->getType()) + { + case df::feature_type::deep_special_tube: + mlt->at(i).at(k).adamantine_level = world_data->feature_map[x / 16][y / 16].features->feature_init[x % 16][y % 16][feature->feature_idx]->start_depth; + break; + + case df::feature_type::magma_pool: + mlt->at(i).at(k).magma_level = 2 - world_data->feature_map[x / 16][y / 16].features->feature_init[x % 16][y % 16][feature->feature_idx]->start_depth; + break; + + case df::feature_type::volcano: + mlt->at(i).at(k).magma_level = 3; + break; + + default: + break; + } + } + else if (feature->layer != -1 && feature->min_z != -30000) { auto layer = world_data->underground_regions[feature->layer]; @@ -592,7 +617,6 @@ void embark_assist::survey::survey_mid_level_tile(embark_assist::defs::geo_data if (layer->type == df::world_underground_region::MagmaSea) { min_z = feature->min_z; // The features are individual per region tile - break; } } }