diff --git a/docs/changelog.txt b/docs/changelog.txt index ee21058ea..13576cee0 100644 --- a/docs/changelog.txt +++ b/docs/changelog.txt @@ -52,6 +52,7 @@ changelog.txt uses a syntax similar to RST, with a few special sequences: - `buildingplan`: new global settings for whether generic building materials should match blocks, boulders, logs, and/or bars. defaults are everything but bars. - `quickfort`: The Dreamfort sample blueprints now have complete walkthroughs for each fort level and importable orders that automate basic fort stock management - `quickfort`: More blueprints have been added to the blueprints library: several bedroom layouts, the Saracen Crypts, and the complete fortress example from Python Quickfort: TheQuickFortress +- `embark-assistant`: split the lair types displayed on the local map into mound, burrow, and lair ## API - `buildingplan`: added Lua interface API diff --git a/plugins/embark-assistant/defs.h b/plugins/embark-assistant/defs.h index 7d85eb6be..5c9a2c23e 100644 --- a/plugins/embark-assistant/defs.h +++ b/plugins/embark-assistant/defs.h @@ -3,6 +3,7 @@ #include #include #include +#include "df/biome_type.h" #include "df/world_region_type.h" using namespace std; @@ -31,6 +32,35 @@ namespace embark_assist { const uint8_t Light_Aquifer_Bit = 2; const uint8_t Heavy_Aquifer_Bit = 4; + namespace directions { + enum directions { + Northwest, + North, + Northeast, + West, + Center, + East, + Southwest, + South, + Southeast + }; + }; + + namespace offset_directions { + enum offset_directions { + NA, // 0 isn't used for offsets + Southwest, + South, + Southeast, + West, + Center, + East, + Northwest, + North, + Northeast + }; + }; + enum class tree_levels : int8_t { None, Very_Scarce, @@ -66,9 +96,12 @@ namespace embark_assist { struct region_tile_datum { bool surveyed = false; bool survey_completed = false; - bool neighboring_clay = false; // These elements are updated after the survey by checking if there are any border MLTs in neighboring tiles that would would provide the resource - bool neighboring_sand = false; // if they actually provided an incursion. This allows the code to add these potential tiles to the ones checked. - uint8_t neighboring_aquifer = Clear_Aquifer_Bits; + bool neighboring_clay = false; // These elements are updated after the survey by checking if there are any border MLTs in neighboring tiles that + bool neighboring_sand = false; // provide the resource through an incursion. + bool neighboring_biomes[ENUM_LAST_ITEM(biome_type) + 1]; + bool neighboring_region_types[ENUM_LAST_ITEM(world_region_type) + 1]; + bool neighboring_savagery[3]; + bool neighboring_evilness[3]; uint8_t aquifer = Clear_Aquifer_Bits; uint16_t clay_count = 0; uint16_t sand_count = 0; diff --git a/plugins/embark-assistant/embark-assistant.cpp b/plugins/embark-assistant/embark-assistant.cpp index 2c7021239..7a0b678a8 100644 --- a/plugins/embark-assistant/embark-assistant.cpp +++ b/plugins/embark-assistant/embark-assistant.cpp @@ -314,7 +314,19 @@ command_result embark_assistant(color_ostream &out, std::vector & embark_assist::main::state->survey_results[i][k].survey_completed = false; embark_assist::main::state->survey_results[i][k].neighboring_clay = false; embark_assist::main::state->survey_results[i][k].neighboring_sand = false; - embark_assist::main::state->survey_results[i][k].neighboring_aquifer = embark_assist::defs::Clear_Aquifer_Bits; + for (uint8_t l = 0; l <= ENUM_LAST_ITEM(biome_type); l++) { + embark_assist::main::state->survey_results[i][k].neighboring_biomes[l] = false; + } + + for (uint8_t l = 0; l <= ENUM_LAST_ITEM(world_region_type); l++) { + embark_assist::main::state->survey_results[i][k].neighboring_region_types[l] = false; + } + + for (uint8_t l = 0; l < 2; l++) { + embark_assist::main::state->survey_results[i][k].neighboring_savagery[l] = false; + embark_assist::main::state->survey_results[i][k].neighboring_evilness[l] = false; + } + embark_assist::main::state->survey_results[i][k].aquifer = embark_assist::defs::Clear_Aquifer_Bits; embark_assist::main::state->survey_results[i][k].clay_count = 0; embark_assist::main::state->survey_results[i][k].sand_count = 0; diff --git a/plugins/embark-assistant/help_ui.cpp b/plugins/embark-assistant/help_ui.cpp index fb394270a..e2988f8b7 100644 --- a/plugins/embark-assistant/help_ui.cpp +++ b/plugins/embark-assistant/help_ui.cpp @@ -157,7 +157,9 @@ namespace embark_assist{ help_text.push_back("C: Camp"); help_text.push_back("c: Cave. Only displayed if the DF worldgen parameter does not display caves."); help_text.push_back("i: Important Location. The author doesn't actually know what those are."); - help_text.push_back("l: Lair"); + help_text.push_back("m: Lair (Simple Mound)"); + help_text.push_back("b: Lair (Simple Burrow)"); + help_text.push_back("l: Lair (Wilderness Location)"); help_text.push_back("L: Labyrinth"); help_text.push_back("M: Monument. The author is unsure how/if this is broken down further."); help_text.push_back("S: Shrine"); @@ -338,7 +340,7 @@ namespace embark_assist{ help_text.push_back(" the N, followed by the one to the W, and lastly the one acting as the"); help_text.push_back(" reference. This means there's a risk embarks with such 'trouble' corners"); help_text.push_back(" may get affected corner(s) evaluated incorrectly."); - help_text.push_back("Version 0.11 2020-03-03"); + help_text.push_back("Version 0.12 2020-11-17"); break; } @@ -367,11 +369,13 @@ namespace embark_assist{ embark_assist::screen::paintString(site_pen, 1, 4, "C"); embark_assist::screen::paintString(site_pen, 1, 5, "c"); embark_assist::screen::paintString(site_pen, 1, 6, "i"); - embark_assist::screen::paintString(site_pen, 1, 7, "l"); - embark_assist::screen::paintString(site_pen, 1, 8, "L"); - embark_assist::screen::paintString(site_pen, 1, 9, "M"); - embark_assist::screen::paintString(site_pen, 1, 10, "S"); - embark_assist::screen::paintString(site_pen, 1, 11, "V"); + embark_assist::screen::paintString(site_pen, 1, 7, "m"); + embark_assist::screen::paintString(site_pen, 1, 8, "b"); + embark_assist::screen::paintString(site_pen, 1, 9, "l"); + embark_assist::screen::paintString(site_pen, 1, 10, "L"); + embark_assist::screen::paintString(site_pen, 1, 11, "M"); + embark_assist::screen::paintString(site_pen, 1, 12, "S"); + embark_assist::screen::paintString(site_pen, 1, 13, "V"); break; case pages::Finder: diff --git a/plugins/embark-assistant/matcher.cpp b/plugins/embark-assistant/matcher.cpp index 1cdbce11e..3e2675e1d 100644 --- a/plugins/embark-assistant/matcher.cpp +++ b/plugins/embark-assistant/matcher.cpp @@ -408,42 +408,42 @@ namespace embark_assist { // Logic can be implemented with modulo and division, but that's harder to read. switch (from_direction) { - case 0: + case embark_assist::defs::directions::Northwest: fetch_i = i - 1; fetch_k = k - 1; break; - case 1: + case embark_assist::defs::directions::North: fetch_k = k - 1; break; - case 2: + case embark_assist::defs::directions::Northeast: fetch_i = i + 1; fetch_k = k - 1; break; - case 3: + case embark_assist::defs::directions::West: fetch_i = i - 1; break; - case 4: + case embark_assist::defs::directions::Center: return; // Own tile provides the data, so there's no incursion. break; - case 5: + case embark_assist::defs::directions::East: fetch_i = i + 1; break; - case 6: + case embark_assist::defs::directions::Southwest: fetch_i = i - 1; fetch_k = k + 1; break; - case 7: + case embark_assist::defs::directions::South: fetch_k = k + 1; break; - case 8: + case embark_assist::defs::directions::Southeast: fetch_i = i + 1; fetch_k = k + 1; } @@ -910,7 +910,7 @@ namespace embark_assist { else { process_embark_incursion_mid_level_tile (embark_assist::survey::translate_corner(survey_results, - 4, + embark_assist::defs::directions::Center, x, y, i, @@ -958,7 +958,7 @@ namespace embark_assist { else { process_embark_incursion_mid_level_tile (embark_assist::survey::translate_corner(survey_results, - 5, + embark_assist::defs::directions::East, x, y, i, @@ -983,7 +983,7 @@ namespace embark_assist { else { process_embark_incursion_mid_level_tile (embark_assist::survey::translate_corner(survey_results, - 7, + embark_assist::defs::directions::South, x, y, i, @@ -1031,7 +1031,7 @@ namespace embark_assist { else { process_embark_incursion_mid_level_tile (embark_assist::survey::translate_corner(survey_results, - 8, + embark_assist::defs::directions::Southeast, x, y, i, @@ -1058,7 +1058,7 @@ namespace embark_assist { else if (k > start_y) { // We've already covered the NW corner of the NW, with its complications. process_embark_incursion_mid_level_tile (embark_assist::survey::translate_corner(survey_results, - 4, + embark_assist::defs::directions::Center, x, y, start_x, @@ -1104,7 +1104,7 @@ namespace embark_assist { else if (k < start_y + finder->y_dim - 1) { // We've already covered the SW corner of the SW tile, with its complicatinons. process_embark_incursion_mid_level_tile (embark_assist::survey::translate_corner(survey_results, - 7, + embark_assist::defs::directions::South, x, y, start_x, @@ -1127,7 +1127,7 @@ namespace embark_assist { else if (k > start_y) { // We've already covered the NE tile's NE corner, with its complications. process_embark_incursion_mid_level_tile (embark_assist::survey::translate_corner(survey_results, - 5, + embark_assist::defs::directions::East, x, y, start_x + finder->x_dim - 1, @@ -1173,7 +1173,7 @@ namespace embark_assist { else if (k < start_y + finder->y_dim - 1) { // We've already covered the SE tile's SE corner, with its complications. process_embark_incursion_mid_level_tile (embark_assist::survey::translate_corner(survey_results, - 8, + embark_assist::defs::directions::Southeast, x, y, start_x + finder->x_dim - 1, @@ -1450,7 +1450,7 @@ namespace embark_assist { break; case embark_assist::defs::evil_savagery_values::Present: - if (tile->savagery_count[i] == 0) { + if (tile->savagery_count[i] == 0 && !tile->neighboring_savagery[i]) { if (trace) out.print("matcher::world_tile_match: Savagery Present (%i, %i)\n", x, y); return false; } @@ -1480,7 +1480,7 @@ namespace embark_assist { break; case embark_assist::defs::evil_savagery_values::Present: - if (tile->evilness_count[i] == 0) { + if (tile->evilness_count[i] == 0 && !tile->neighboring_evilness[i]) { if (trace) out.print("matcher::world_tile_match: Evil Present (%i, %i)\n", x, y); return false; } @@ -1518,16 +1518,16 @@ namespace embark_assist { break; case embark_assist::defs::aquifer_ranges::None_Plus_Light: - if (!((tile->aquifer | tile->neighboring_aquifer) & embark_assist::defs::None_Aquifer_Bit) || - !((tile->aquifer | tile->neighboring_aquifer) & embark_assist::defs::Light_Aquifer_Bit)) { + if (!(tile->aquifer & embark_assist::defs::None_Aquifer_Bit) || + !(tile->aquifer & embark_assist::defs::Light_Aquifer_Bit)) { if (trace) out.print("matcher::world_tile_match: Aquifer None_Plus_Light (%i, %i)\n", x, y); return false; } break; case embark_assist::defs::aquifer_ranges::None_Plus_At_Least_Light: - if (!((tile->aquifer | tile->neighboring_aquifer) & embark_assist::defs::None_Aquifer_Bit) || - ((tile->aquifer | tile->neighboring_aquifer) == embark_assist::defs::None_Aquifer_Bit)) { + if (!(tile->aquifer & embark_assist::defs::None_Aquifer_Bit) || + (tile->aquifer == embark_assist::defs::None_Aquifer_Bit)) { if (trace) out.print("matcher::world_tile_match: Aquifer None_Plus_At_Least_Light (%i, %i)\n", x, y); return false; } @@ -1541,38 +1541,38 @@ namespace embark_assist { break; case embark_assist::defs::aquifer_ranges::At_Least_Light: - if ((tile->aquifer | tile->neighboring_aquifer) == embark_assist::defs::None_Aquifer_Bit) { + if (tile->aquifer == embark_assist::defs::None_Aquifer_Bit) { if (trace) out.print("matcher::world_tile_match: Aquifer At_Least_Light (%i, %i)\n", x, y); return false; } break; case embark_assist::defs::aquifer_ranges::None_Plus_Heavy: - if (!((tile->aquifer | tile->neighboring_aquifer) & embark_assist::defs::None_Aquifer_Bit) || - !((tile->aquifer | tile->neighboring_aquifer) & embark_assist::defs::Heavy_Aquifer_Bit)) { + if (!(tile->aquifer & embark_assist::defs::None_Aquifer_Bit) || + !(tile->aquifer & embark_assist::defs::Heavy_Aquifer_Bit)) { if (trace) out.print("matcher::world_tile_match: Aquifer None_Plus_Heavy (%i, %i)\n", x, y); return false; } break; case embark_assist::defs::aquifer_ranges::At_Most_Light_Plus_Heavy: - if ((tile->aquifer | tile->neighboring_aquifer) == embark_assist::defs::Heavy_Aquifer_Bit || - !((tile->aquifer | tile->neighboring_aquifer) & embark_assist::defs::Heavy_Aquifer_Bit)) { + if (tile->aquifer == embark_assist::defs::Heavy_Aquifer_Bit || + !(tile->aquifer & embark_assist::defs::Heavy_Aquifer_Bit)) { if (trace) out.print("matcher::world_tile_match: Aquifer At_Most_Light_Plus_Heavy (%i, %i)\n", x, y); return false; } break; case embark_assist::defs::aquifer_ranges::Light_Plus_Heavy: - if (!((tile->aquifer | tile->neighboring_aquifer) & embark_assist::defs::Light_Aquifer_Bit) || - !((tile->aquifer | tile->neighboring_aquifer) & embark_assist::defs::Heavy_Aquifer_Bit)) { + if (!(tile->aquifer & embark_assist::defs::Light_Aquifer_Bit) || + !(tile->aquifer & embark_assist::defs::Heavy_Aquifer_Bit)) { if (trace) out.print("matcher::world_tile_match: Aquifer Light_Plus_Heavy (%i, %i)\n", x, y); return false; } break; case embark_assist::defs::aquifer_ranges::None_Light_Heavy: - if ((tile->aquifer | tile->neighboring_aquifer) != + if (tile->aquifer != (embark_assist::defs::None_Aquifer_Bit | embark_assist::defs::Light_Aquifer_Bit | embark_assist::defs::Heavy_Aquifer_Bit)) { if (trace) out.print("matcher::world_tile_match: Aquifer None_Light_Heavy (%i, %i)\n", x, y); return false; @@ -2056,20 +2056,7 @@ namespace embark_assist { // Region Type 1 if (finder->region_type_1 != -1) { - found = false; - - for (uint8_t k = 1; k < 10; k++) { - if (tile->biome_index[k] != -1) { - if (world_data->regions[tile->biome_index[k]]->type == finder->region_type_1) { - found = true; - break; - } - } - - if (found) break; - } - - if (!found) { + if (!tile->neighboring_region_types[finder->region_type_1]) { if (trace) out.print("matcher::world_tile_match: Region_Type_1 (%i, %i)\n", x, y); return false; } @@ -2077,20 +2064,7 @@ namespace embark_assist { // Region Type 2 if (finder->region_type_2 != -1) { - found = false; - - for (uint8_t k = 1; k < 10; k++) { - if (tile->biome_index[k] != -1) { - if (world_data->regions[tile->biome_index[k]]->type == finder->region_type_2) { - found = true; - break; - } - } - - if (found) break; - } - - if (!found) { + if (!tile->neighboring_region_types[finder->region_type_2]) { if (trace) out.print("matcher::world_tile_match: Region_Type_2 (%i, %i)\n", x, y); return false; } @@ -2098,20 +2072,7 @@ namespace embark_assist { // Region Type 3 if (finder->region_type_3 != -1) { - found = false; - - for (uint8_t k = 1; k < 10; k++) { - if (tile->biome_index[k] != -1) { - if (world_data->regions[tile->biome_index[k]]->type == finder->region_type_3) { - found = true; - break; - } - } - - if (found) break; - } - - if (!found) { + if (!tile->neighboring_region_types[finder->region_type_3]) { if (trace) out.print("matcher::world_tile_match: Region_Type_3 (%i, %i)\n", x, y); return false; } @@ -2119,16 +2080,7 @@ namespace embark_assist { // Biome 1 if (finder->biome_1 != -1) { - found = false; - - for (uint8_t i = 1; i < 10; i++) { - if (tile->biome[i] == finder->biome_1) { - found = true; - break; - } - } - - if (!found) { + if (!tile->neighboring_biomes[finder->biome_1]) { if (trace) out.print("matcher::world_tile_match: Biome_1 (%i, %i)\n", x, y); return false; } @@ -2136,33 +2088,15 @@ namespace embark_assist { // Biome 2 if (finder->biome_2 != -1) { - found = false; - - for (uint8_t i = 1; i < 10; i++) { - if (tile->biome[i] == finder->biome_2) { - found = true; - break; - } - } - - if (!found) { + if (!tile->neighboring_biomes[finder->biome_2]) { if (trace) out.print("matcher::world_tile_match: Biome_2 (%i, %i)\n", x, y); return false; } } - + // Biome 3 if (finder->biome_3 != -1) { - found = false; - - for (uint8_t i = 1; i < 10; i++) { - if (tile->biome[i] == finder->biome_3) { - found = true; - break; - } - } - - if (!found) { + if (!tile->neighboring_biomes[finder->biome_3]) { if (trace) out.print("matcher::world_tile_match: Biome_3 (%i, %i)\n", x, y); return false; } @@ -2798,6 +2732,22 @@ namespace embark_assist { finder, match_results); } + + //======================================================================================= + + void merge_incursion_into_world_tile(embark_assist::defs::region_tile_datum* current, + embark_assist::defs::region_tile_datum* target_tile, + embark_assist::defs::mid_level_tile* target_mlt) { + df::world_data* world_data = world->world_data; + + current->aquifer |= target_mlt->aquifer; + current->neighboring_sand |= target_mlt->sand; + current->neighboring_clay |= target_mlt->clay; + if (current->min_region_soil > target_mlt->soil_depth) current->min_region_soil = target_mlt->soil_depth; + if (current->max_region_soil < target_mlt->soil_depth) current->max_region_soil = target_mlt->soil_depth; + current->neighboring_biomes[target_tile->biome[target_mlt->biome_offset]] = true; + current->neighboring_region_types[world_data->regions[target_tile->biome_index[target_mlt->biome_offset]]->type] = true; + } } } @@ -2899,6 +2849,7 @@ uint16_t embark_assist::matcher::find(embark_assist::defs::match_iterators *iter embark_assist::defs::match_results *match_results) { color_ostream_proxy out(Core::getInstance().getConsole()); + df::world_data* world_data = world->world_data; auto screen = Gui::getViewscreenByType(0); uint16_t x_end; uint16_t y_end; @@ -3159,76 +3110,227 @@ uint16_t embark_assist::matcher::find(embark_assist::defs::match_iterators *iter for (uint16_t k = 0; k < world->worldgen.worldgen_parms.dim_y; k++) { embark_assist::defs::region_tile_datum* current = &survey_results->at(i).at(k); - if (i > 0 && k > 0) { - embark_assist::defs::region_tile_datum* target = &survey_results->at(i - 1).at(k - 1); + for (uint8_t l = 0; l < 16; l++) { + // Start with the north row west corners + + switch (embark_assist::survey::translate_corner(survey_results, + embark_assist::defs::directions::Center, + i, + k, + l, + 0)) { + + case embark_assist::defs::directions::Northwest: + { + if (l == 0) { + embark_assist::defs::region_tile_datum* target_tile = &survey_results->at(i - 1).at(k - 1); + merge_incursion_into_world_tile(current, target_tile, &target_tile->south_row[15]); + } + else { + embark_assist::defs::region_tile_datum* target_tile = &survey_results->at(i).at(k - 1); + merge_incursion_into_world_tile(current, target_tile, &target_tile->south_row[l - 1]); + } + break; + } - current->neighboring_sand |= target->south_row [15].sand; - current->neighboring_clay |= target->south_row[15].clay; - current->neighboring_aquifer |= target->south_row[15].aquifer; - } + case embark_assist::defs::directions::North: + { + embark_assist::defs::region_tile_datum* target_tile = &survey_results->at(i).at(k - 1); + merge_incursion_into_world_tile(current, target_tile, &target_tile->south_row[l]); + break; + } + + case embark_assist::defs::directions::West: + { + if (l == 0) { + embark_assist::defs::region_tile_datum* target_tile = &survey_results->at(i - 1).at(k); + merge_incursion_into_world_tile(current, target_tile, &target_tile->east_column[0]); + } + break; + } + // Only legal remaining result is Center, and we don't need to do anything for that case. + } - if (k > 0) { - embark_assist::defs::region_tile_datum* target = &survey_results->at(i).at(k - 1); + // North row edges - for (uint16_t l = 0; l < 16; l++) { - current->neighboring_sand |= target->south_row[l].sand; - current->neighboring_clay |= target->south_row[l].clay; - current->neighboring_aquifer |= target->south_row[l].aquifer; + if (embark_assist::survey::translate_ns_edge(survey_results, + true, + i, + k, + l, + 0) == embark_assist::defs::directions::North) { + + embark_assist::defs::region_tile_datum* target_tile = &survey_results->at(i).at(k - 1); + merge_incursion_into_world_tile(current, target_tile, &target_tile->south_row[l]); } - } - if (i < world->worldgen.worldgen_parms.dim_x - 1 && k > 0) { - embark_assist::defs::region_tile_datum* target = &survey_results->at(i + 1).at(k - 1); + // North row east corners + switch (embark_assist::survey::translate_corner(survey_results, + embark_assist::defs::directions::East, + i, + k, + l, + 0)) { + + case embark_assist::defs::directions::North: + { + embark_assist::defs::region_tile_datum* target_tile = &survey_results->at(i).at(k - 1); + merge_incursion_into_world_tile(current, target_tile, &target_tile->south_row[l]); + break; + } + case embark_assist::defs::directions::Northeast: + { + if (l == 15) { + embark_assist::defs::region_tile_datum* target_tile = &survey_results->at(i + 1).at(k - 1); + merge_incursion_into_world_tile(current, target_tile, &target_tile->south_row[0]); + } + else { + embark_assist::defs::region_tile_datum* target_tile = &survey_results->at(i).at(k - 1); + merge_incursion_into_world_tile(current, target_tile, &target_tile->south_row[l + 1]); + } + break; + } - current->neighboring_sand |= target->south_row[0].sand; - current->neighboring_clay |= target->south_row[0].clay; - current->neighboring_aquifer |= target->south_row[0].aquifer; - } + case embark_assist::defs::directions::East: + { + if (l == 15) { + embark_assist::defs::region_tile_datum* target_tile = &survey_results->at(i + 1).at(k); + merge_incursion_into_world_tile(current, target_tile, &target_tile->west_column[0]); + } + break; + } + + // Only legal remaining result is Center, and we don't need to do anything for that case. + } + // West column - if (i > 0) { - embark_assist::defs::region_tile_datum* target = &survey_results->at(i - 1).at(k); + if (embark_assist::survey::translate_ew_edge(survey_results, + true, + i, + k, + 0, + l) == embark_assist::defs::directions::West) { - for (uint16_t l = 0; l < 16; l++) { - current->neighboring_sand |= target->east_column[l].sand; - current->neighboring_clay |= target->east_column[l].clay; - current->neighboring_aquifer |= target->east_column[l].aquifer; + embark_assist::defs::region_tile_datum* target_tile = &survey_results->at(i - 1).at(k); + merge_incursion_into_world_tile(current, target_tile, &target_tile->east_column[l]); } - } - if (i < world->worldgen.worldgen_parms.dim_x - 1) { - embark_assist::defs::region_tile_datum* target = &survey_results->at(i + 1).at(k); + // East column - for (uint16_t l = 0; l < 16; l++) { - current->neighboring_sand |= target->west_column[l].sand; - current->neighboring_clay |= target->west_column[l].clay; - current->neighboring_aquifer |= target->west_column[l].aquifer; + if (embark_assist::survey::translate_ew_edge(survey_results, + false, + i, + k, + 15, + l) == embark_assist::defs::directions::East) { + embark_assist::defs::region_tile_datum* target_tile = &survey_results->at(i + 1).at(k); + merge_incursion_into_world_tile(current, target_tile, &target_tile->west_column[l]); + } + + // South row west corners + + switch (embark_assist::survey::translate_corner(survey_results, + embark_assist::defs::directions::South, + i, + k, + l, + 15)) { + + case embark_assist::defs::directions::West: + { + if (l == 0) { + embark_assist::defs::region_tile_datum* target_tile = &survey_results->at(i - 1).at(k); + merge_incursion_into_world_tile(current, target_tile, &target_tile->east_column[15]); + } + break; } - } - if (i > 0 && k < world->worldgen.worldgen_parms.dim_y - 1) { - embark_assist::defs::region_tile_datum* target = &survey_results->at(i - 1).at(k + 1); + case embark_assist::defs::directions::Southwest: + { + if (l == 0) { + embark_assist::defs::region_tile_datum* target_tile = &survey_results->at(i - 1).at(k + 1); + merge_incursion_into_world_tile(current, target_tile, &target_tile->north_row[15]); + } + else { + embark_assist::defs::region_tile_datum* target_tile = &survey_results->at(i).at(k + 1); + merge_incursion_into_world_tile(current, target_tile, &target_tile->north_row[l - 1]); + } + break; + } - current->neighboring_sand |= target->north_row[15].sand; - current->neighboring_clay |= target->north_row[15].clay; - current->neighboring_aquifer |= target->north_row[15].aquifer; - } + case embark_assist::defs::directions::South: + { + embark_assist::defs::region_tile_datum* target_tile = &survey_results->at(i).at(k + 1); + merge_incursion_into_world_tile(current, target_tile, &target_tile->north_row[l]); + break; + } + // Only legal remaining result is Center, and we don't need to do anything for that case. + } - if (k < world->worldgen.worldgen_parms.dim_y - 1) { - embark_assist::defs::region_tile_datum* target = &survey_results->at(i).at(k + 1); + // South row edges - for (uint16_t l = 0; l < 16; l++) { - current->neighboring_sand |= target->north_row[l].sand; - current->neighboring_clay |= target->north_row[l].clay; - current->neighboring_aquifer |= target->north_row[l].aquifer; + if (embark_assist::survey::translate_ns_edge(survey_results, + false, + i, + k, + l, + 15) == embark_assist::defs::directions::South) { + + embark_assist::defs::region_tile_datum* target_tile = &survey_results->at(i).at(k + 1); + merge_incursion_into_world_tile(current, target_tile, &target_tile->north_row[l]); + } + + // South row east corners + + switch (embark_assist::survey::translate_corner(survey_results, + embark_assist::defs::directions::Southeast, + i, + k, + l, + 15)) { + + case embark_assist::defs::directions::East: + { + if (l == 15) { + embark_assist::defs::region_tile_datum* target_tile = &survey_results->at(i + 1).at(k); + merge_incursion_into_world_tile(current, target_tile, &target_tile->west_column[15]); + } + break; + } + + case embark_assist::defs::directions::South: + { + embark_assist::defs::region_tile_datum* target_tile = &survey_results->at(i).at(k + 1); + merge_incursion_into_world_tile(current, target_tile, &target_tile->north_row[l]); + break; } - } - if (i < world->worldgen.worldgen_parms.dim_x - 1 && k < world->worldgen.worldgen_parms.dim_y - 1) { - embark_assist::defs::region_tile_datum* target = &survey_results->at(i + 1).at(k + 1); + case embark_assist::defs::directions::Southeast: + { + if (l == 15) { + embark_assist::defs::region_tile_datum* target_tile = &survey_results->at(i + 1).at(k + 1); + merge_incursion_into_world_tile(current, target_tile, &target_tile->north_row[0]); + } + else { + embark_assist::defs::region_tile_datum* target_tile = &survey_results->at(i).at(k + 1); + merge_incursion_into_world_tile(current, target_tile, &target_tile->north_row[l + 1]); + } + break; + } + } + } + + // The complete set of biomes and region types is stored in the "neighboring" elements, which is a little misleading. + for (uint8_t l = 0; l < 10; l++) { + if (current->biome_index[l] != -1) { + current->neighboring_biomes[current->biome[l]] = true; + current->neighboring_region_types[world_data->regions[current->biome_index[l]]->type] = true; + } + } - current->neighboring_sand |= target->north_row[0].sand; - current->neighboring_clay |= target->north_row[0].clay; - current->neighboring_aquifer |= target->north_row[0].aquifer; + current->biome_count = 0; + for (uint8_t l = 0; l <= ENUM_LAST_ITEM(biome_type); l++) { + if (current->neighboring_biomes[l]) current->biome_count++; } survey_results->at(i).at(k).survey_completed = true; // A bit wasteful to add a flag to every entry when only the very first one is ever read... diff --git a/plugins/embark-assistant/survey.cpp b/plugins/embark-assistant/survey.cpp index dfe87f51e..eaea5fc15 100644 --- a/plugins/embark-assistant/survey.cpp +++ b/plugins/embark-assistant/survey.cpp @@ -567,42 +567,42 @@ namespace embark_assist { // Logic can be implemented with modulo and division, but that's harder to read. switch (from_direction) { - case 0: + case embark_assist::defs::directions::Northwest: fetch_i = i - 1; fetch_k = k - 1; break; - case 1: + case embark_assist::defs::directions::North: fetch_k = k - 1; break; - case 2: + case embark_assist::defs::directions::Northeast: fetch_i = i + 1; fetch_k = k - 1; break; - case 3: + case embark_assist::defs::directions::West: fetch_i = i - 1; break; - case 4: + case embark_assist::defs::directions::Center: return; // Own tile provides the data, so there's no incursion. break; - case 5: + case embark_assist::defs::directions::East: fetch_i = i + 1; break; - case 6: + case embark_assist::defs::directions::Southwest: fetch_i = i - 1; fetch_k = k + 1; break; - case 7: + case embark_assist::defs::directions::South: fetch_k = k + 1; break; - case 8: + case embark_assist::defs::directions::Southeast: fetch_i = i + 1; fetch_k = k + 1; break; @@ -803,9 +803,21 @@ void embark_assist::survey::high_level_world_survey(embark_assist::defs::geo_dat auto &results = survey_results->at(i).at(k); results.surveyed = false; results.survey_completed = false; - results.neighboring_sand = false; results.neighboring_clay = false; - results.neighboring_aquifer = embark_assist::defs::Clear_Aquifer_Bits; + results.neighboring_sand = false; + for (uint8_t l = 0; l <= ENUM_LAST_ITEM(biome_type); l++) { + results.neighboring_biomes[l] = false; + } + + for (uint8_t l = 0; l <= ENUM_LAST_ITEM(world_region_type); l++) { + results.neighboring_region_types[l] = false; + } + + for (uint8_t l = 0; l < 2; l++) { + results.neighboring_savagery[l] = false; + results.neighboring_evilness[l] = false; + } + results.aquifer = embark_assist::defs::Clear_Aquifer_Bits; results.clay_count = 0; results.sand_count = 0; @@ -903,10 +915,23 @@ void embark_assist::survey::high_level_world_survey(embark_assist::defs::geo_dat } } - results.biome_count = 0; - for (uint8_t l = 1; l < 10; l++) { - if (results.biome[l] != -1) results.biome_count++; + bool biomes[ENUM_LAST_ITEM(biome_type) + 1]; + for (uint8_t l = 0; l <= ENUM_LAST_ITEM(biome_type); l++) { + biomes[l] = false; + } + + for (uint8_t l = 1; l < 10; l++) + { + if (results.biome[l] != -1) { + biomes[results.biome[l]] = true; + } } + int count = 0; + for (uint8_t l = 0; l <= ENUM_LAST_ITEM(biome_type); l++) { + if (biomes[l]) count++; + } + + results.biome_count = count; if (results.clay_count == offset_count) results.clay_count = 256; if (results.sand_count == offset_count) results.sand_count = 256; @@ -1511,41 +1536,41 @@ df::coord2d embark_assist::survey::apply_offset(uint16_t x, uint16_t y, int8_t o result.y = y; switch (offset) { - case 1: + case embark_assist::defs::offset_directions::Southwest: result.x--; result.y++; break; - case 2: + case embark_assist::defs::offset_directions::South: result.y++; break; - case 3: + case embark_assist::defs::offset_directions::Southeast: result.x++; result.y++; break; - case 4: + case embark_assist::defs::offset_directions::West: result.x--; break; - case 5: + case embark_assist::defs::offset_directions::Center: break; // Center. No change - case 6: + case embark_assist::defs::offset_directions::East: result.x++; break; - case 7: + case embark_assist::defs::offset_directions::Northwest: result.x--; result.y--; break; - case 8: + case embark_assist::defs::offset_directions::North: result.y--; break; - case 9: + case embark_assist::defs::offset_directions::Northeast: result.x++; result.y--; break; @@ -1650,12 +1675,12 @@ uint8_t embark_assist::survey::translate_corner(embark_assist::defs::world_tile int8_t w_region_type_level; int8_t home_region_type_level; - if (corner_location == 4) { // We're the reference. No change. + if (corner_location == embark_assist::defs::directions::Center) { // We're the reference. No change. } - else if (corner_location == 5) { // Tile to the east is the reference + else if (corner_location == embark_assist::defs::directions::East) { // Tile to the east is the reference effective_i = i + 1; } - else if (corner_location == 7) { // Tile to the south is the reference + else if (corner_location == embark_assist::defs::directions::South) { // Tile to the south is the reference effective_k = k + 1; } else { // 8, tile to the southeast is the reference. @@ -1667,9 +1692,13 @@ uint8_t embark_assist::survey::translate_corner(embark_assist::defs::world_tile if (effective_x == world_data->world_width) { if (effective_y == world_data->world_height) { // Only the SE corner of the SE most tile of the world can reference this. - return 4; + return embark_assist::defs::directions::Center; } else { // East side corners of the east edge of the world + if (effective_y == 0 && effective_k == 0) { // North edge of the world. Only one alternative exists. + return embark_assist::defs::directions::Center; + } + nw_region_type = embark_assist::survey::region_type_of(survey_results, x, y, effective_i - 1, effective_k - 1); w_region_type = embark_assist::survey::region_type_of(survey_results, x, y, effective_i - 1, effective_k); @@ -1696,18 +1725,18 @@ uint8_t embark_assist::survey::translate_corner(embark_assist::defs::world_tile } if (nw_region_type_level < w_region_type_level) { - return 4; + return embark_assist::defs::directions::Center; } else if (nw_region_type_level > w_region_type_level) { - return 1; + return embark_assist::defs::directions::North; } // Neither tile will automatically yield to the other - if (corner_location == 5) { - return 1; + if (corner_location == embark_assist::defs::directions::East) { + return embark_assist::defs::directions::North; } - else { // Can only be corner_location == 8 - return 4; + else { // Can only be corner_location == embark_assist::defs::SE + return embark_assist::defs::directions::Center; } } } @@ -1738,18 +1767,18 @@ uint8_t embark_assist::survey::translate_corner(embark_assist::defs::world_tile } if (nw_region_type_level < n_region_type_level) { - return 4; + return embark_assist::defs::directions::Center; } else if (nw_region_type_level > n_region_type_level) { - return 5; + return embark_assist::defs::directions::East; } // Neither tile will automatically yield to the other - if (corner_location == 7) { - return 4; + if (corner_location == embark_assist::defs::directions::South) { + return embark_assist::defs::directions::Center; } - else { // Can only be corner_location == 8 - return 5; + else { // Can only be corner_location == embark_assist::defs::directions::Southeast + return embark_assist::defs::directions::East; } } @@ -1814,7 +1843,7 @@ uint8_t embark_assist::survey::translate_corner(embark_assist::defs::world_tile if (effective_x == 0 && effective_i == 0) { // West edge of the world if (effective_y == 0 && effective_k == 0) { - return 4; // Only a single reference to this info, the own tile. + return embark_assist::defs::directions::Center; // Only a single reference to this info, the own tile. } else { nw_region_type_level = -1; // Knock out the unreachable corners @@ -1826,8 +1855,8 @@ uint8_t embark_assist::survey::translate_corner(embark_assist::defs::world_tile nw_region_type_level = -1; // Knock out the unreachable corners n_region_type_level = -1; - if (corner_location == 4 && effective_corner == 1) { // The logic below would select the wrong alternative. - effective_corner = 3; + if (corner_location == embark_assist::defs::directions::Center && effective_corner == embark_assist::defs::directions::North) { // The logic below would select the wrong alternative. + effective_corner = embark_assist::defs::directions::West; } } @@ -1986,6 +2015,8 @@ uint8_t embark_assist::survey::translate_ns_edge(embark_assist::defs::world_tile df::world_region_type south_region_type; if (own_edge) { + if (y == 0 && k == 0) return embark_assist::defs::directions::Center; // There's nothing to the north, so we fall back on our own tile. + effective_edge = world_data->region_details[0]->edges.biome_x[i][k]; south_region_type = embark_assist::survey::region_type_of(survey_results, x, y, i, k); north_region_type = embark_assist::survey::region_type_of(survey_results, x, y, i, k - 1); @@ -1994,9 +2025,10 @@ uint8_t embark_assist::survey::translate_ns_edge(embark_assist::defs::world_tile if (k < 15) { // We're still within the same world tile effective_edge = world_data->region_details[0]->edges.biome_x[i][k + 1]; } - else { // Getting the data from the world tile to the south + else { + // Getting the data from the world tile to the south if (y + 1 == world_data->world_height) { - return 4; // There's nothing to the south, so we fall back on our own tile. + return embark_assist::defs::directions::Center; // There's nothing to the south, so we fall back on our own tile. } effective_edge = survey_results->at(x).at(y + 1).north_row_biome_x[i]; @@ -2039,18 +2071,18 @@ uint8_t embark_assist::survey::translate_ns_edge(embark_assist::defs::world_tile if (effective_edge == 0) { if (own_edge) { - return 1; + return embark_assist::defs::directions::North; } else { - return 4; + return embark_assist::defs::directions::Center; } } else { if (own_edge) { - return 4; + return embark_assist::defs::directions::Center; } else { - return 7; + return embark_assist::defs::directions::South; } } } @@ -2070,6 +2102,7 @@ uint8_t embark_assist::survey::translate_ew_edge(embark_assist::defs::world_tile df::world_region_type east_region_type; if (own_edge) { + if (x == 0 && i == 0) return embark_assist::defs::directions::Center; // There's nothing to the west, so we fall back on our own tile. effective_edge = world_data->region_details[0]->edges.biome_y[i][k]; east_region_type = embark_assist::survey::region_type_of(survey_results, x, y, i, k); west_region_type = embark_assist::survey::region_type_of(survey_results, x, y, i - 1, k); @@ -2080,7 +2113,7 @@ uint8_t embark_assist::survey::translate_ew_edge(embark_assist::defs::world_tile } else { // Getting the data from the world tile to the east if (x + 1 == world_data->world_width) { - return 4; // There's nothing to the east, so we fall back on our own tile. + return embark_assist::defs::directions::Center; // There's nothing to the east, so we fall back on our own tile. } effective_edge = survey_results->at(x + 1).at(y).west_column_biome_y[k]; @@ -2121,18 +2154,18 @@ uint8_t embark_assist::survey::translate_ew_edge(embark_assist::defs::world_tile } if (effective_edge == 0) { if (own_edge) { - return 3; + return embark_assist::defs::directions::West; } else { - return 4; + return embark_assist::defs::directions::Center; } } else { if (own_edge) { - return 4; + return embark_assist::defs::directions::Center; } else { - return 5; + return embark_assist::defs::directions::East; } } } @@ -2190,7 +2223,12 @@ void embark_assist::survey::survey_region_sites(embark_assist::defs::site_lists break; case df::lair_type::SIMPLE_MOUND: + site_list->push_back({ (uint8_t)site->rgn_min_x , (uint8_t)site->rgn_min_y, 'm' }); + break; + case df::lair_type::SIMPLE_BURROW: + site_list->push_back({ (uint8_t)site->rgn_min_x , (uint8_t)site->rgn_min_y, 'b' }); + break; case df::lair_type::WILDERNESS_LOCATION: site_list->push_back({ (uint8_t)site->rgn_min_x , (uint8_t)site->rgn_min_y, 'l' }); break; @@ -2375,7 +2413,7 @@ void embark_assist::survey::survey_embark(embark_assist::defs::mid_level_tiles * else { process_embark_incursion_mid_level_tile (translate_corner(survey_results, - 4, + embark_assist::defs::directions::Center, x, y, i, @@ -2415,7 +2453,7 @@ void embark_assist::survey::survey_embark(embark_assist::defs::mid_level_tiles * else { process_embark_incursion_mid_level_tile (translate_corner(survey_results, - 5, + embark_assist::defs::directions::East, x, y, i, @@ -2436,7 +2474,7 @@ void embark_assist::survey::survey_embark(embark_assist::defs::mid_level_tiles * else { process_embark_incursion_mid_level_tile (translate_corner(survey_results, - 7, + embark_assist::defs::directions::South, x, y, i, @@ -2476,7 +2514,7 @@ void embark_assist::survey::survey_embark(embark_assist::defs::mid_level_tiles * else { process_embark_incursion_mid_level_tile (translate_corner(survey_results, - 8, + embark_assist::defs::directions::Southeast, x, y, i, @@ -2497,7 +2535,7 @@ void embark_assist::survey::survey_embark(embark_assist::defs::mid_level_tiles * else if (k > state->local_min_y) { // We've already covered the NW corner of the NW, with its complications. process_embark_incursion_mid_level_tile (translate_corner(survey_results, - 4, + embark_assist::defs::directions::Center, x, y, state->local_min_x, @@ -2535,7 +2573,7 @@ void embark_assist::survey::survey_embark(embark_assist::defs::mid_level_tiles * else if (k < state->local_max_y) { // We've already covered the SW corner of the SW tile, with its complicatinons. process_embark_incursion_mid_level_tile (translate_corner(survey_results, - 7, + embark_assist::defs::directions::South, x, y, state->local_min_x, @@ -2554,7 +2592,7 @@ void embark_assist::survey::survey_embark(embark_assist::defs::mid_level_tiles * else if (k > state->local_min_y) { // We've already covered the NE tile's NE corner, with its complications. process_embark_incursion_mid_level_tile (translate_corner(survey_results, - 5, + embark_assist::defs::directions::East, x, y, state->local_max_x, @@ -2592,7 +2630,7 @@ void embark_assist::survey::survey_embark(embark_assist::defs::mid_level_tiles * else if (k < state->local_max_y) { // We've already covered the SE tile's SE corner, with its complications. process_embark_incursion_mid_level_tile (translate_corner(survey_results, - 8, + embark_assist::defs::directions::Southeast, x, y, state->local_max_x,