Added magma/candy search + profile save/load.

develop
PatrikLundell 2018-02-26 18:31:33 +01:00
parent 2277c4ee4e
commit 7705eada5a
6 changed files with 351 additions and 21 deletions

@ -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 ..

@ -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<std::array<mid_level_tile, 16>, 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

@ -1,3 +1,4 @@
#include <stdio.h>
#include "Core.h"
#include <Console.h>
@ -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<int8_t>(i)].text.c_str(), state->ui[static_cast<int8_t>(i)]->current_value);
fprintf(outfile, "[%s:%i]\n", state->finder_list[static_cast<int8_t>(i)].text.c_str(), state->ui[static_cast<int8_t>(i)]->current_value);
if (i == last_fields) {
break; // done
}
i = static_cast <fields>(static_cast<int8_t>(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<int8_t>(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<int8_t>(i)].text.c_str()[l - 1] != line[l]) {
out.printerr("Token mismatch of %s vs %s\n", line, state->finder_list[static_cast<int8_t>(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<int8_t>(i)]->list.size(); l++) {
if (value == state->ui[static_cast<int8_t>(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 <fields>(static_cast<int8_t>(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<int8_t>(i)]->current_value = value;
for (int l = 0; l < state->ui[static_cast<int8_t>(i)]->list.size(); l++) {
if (value == state->ui[static_cast<int8_t>(i)]->list[l].key) {
state->ui[static_cast<int8_t>(i)]->current_display_value = l;
break;
}
}
break;
}
}
if (i == last_fields) {
break; // done
}
i = static_cast <fields>(static_cast<int8_t>(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<int8_t>(k) });
break;
case embark_assist::defs::magma_ranges::Cavern_3:
element->list.push_back({ "3:rd Cavern", static_cast<int8_t>(k) });
break;
case embark_assist::defs::magma_ranges::Cavern_2:
element->list.push_back({ "2:nd Cavern", static_cast<int8_t>(k) });
break;
case embark_assist::defs::magma_ranges::Cavern_1:
element->list.push_back({ "1:st Cavern", static_cast<int8_t>(k) });
break;
case embark_assist::defs::magma_ranges::Volcano:
element->list.push_back({ "Volcano", static_cast<int8_t>(k) });
break;
}
if (k == embark_assist::defs::magma_ranges::Volcano) {
break;
}
k = static_cast <embark_assist::defs::magma_ranges>(static_cast<int8_t>(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<int8_t>(i) });
break;
case fields::spire_count_min:
state->finder_list.push_back({ "Min Adamantine", static_cast<int8_t>(i) });
break;
case fields::spire_count_max:
state->finder_list.push_back({ "Max Adamantine", static_cast<int8_t>(i) });
break;
case fields::magma_min:
state->finder_list.push_back({ "Min Magma", static_cast<int8_t>(i) });
break;
case fields::magma_max:
state->finder_list.push_back({ "Max Magma", static_cast<int8_t>(i) });
break;
case fields::biome_count_min:
state->finder_list.push_back({ "Min Biome Count", static_cast<int8_t>(i) });
break;
@ -875,6 +1075,24 @@ namespace embark_assist {
static_cast<embark_assist::defs::soil_ranges>(state->ui[static_cast<uint8_t>(i)]->current_value);
break;
case fields::spire_count_min:
finder.spire_count_min = state->ui[static_cast<uint8_t>(i)]->current_value;
break;
case fields::spire_count_max:
finder.spire_count_max = state->ui[static_cast<uint8_t>(i)]->current_value;
break;
case fields::magma_min:
finder.magma_min =
static_cast<embark_assist::defs::magma_ranges>(state->ui[static_cast<uint8_t>(i)]->current_value);
break;
case fields::magma_max:
finder.magma_max =
static_cast<embark_assist::defs::magma_ranges>(state->ui[static_cast<uint8_t>(i)]->current_value);
break;
case fields::biome_count_min:
finder.biome_count_min = state->ui[static_cast<uint8_t>(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) {

@ -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:

@ -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<int8_t>(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<embark_assist::defs::magma_ranges>(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");

@ -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<int, int> 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<uint16_t>(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;
}
}
}