From 3cd1d62ec00690a1b29070dd4903754e8f089a21 Mon Sep 17 00:00:00 2001 From: Hop311 Date: Wed, 6 Sep 2023 23:54:09 +0100 Subject: NodeTools cleanup+province definition csv loading --- src/openvic/map/Map.cpp | 125 ++++++++++++++++++++++++++++++++++++++++--- src/openvic/map/Map.hpp | 12 +++++ src/openvic/map/Province.cpp | 22 ++++++++ src/openvic/map/Province.hpp | 4 ++ src/openvic/map/Region.cpp | 12 ++++- src/openvic/map/Region.hpp | 3 +- 6 files changed, 168 insertions(+), 10 deletions(-) (limited to 'src/openvic/map') diff --git a/src/openvic/map/Map.cpp b/src/openvic/map/Map.cpp index c9dd9d2..439338b 100644 --- a/src/openvic/map/Map.cpp +++ b/src/openvic/map/Map.cpp @@ -31,8 +31,8 @@ Map::Map() : provinces { "provinces" }, mapmodes { "mapmodes" } {} return_t Map::add_province(const std::string_view identifier, colour_t colour) { - if (provinces.size() >= Province::MAX_INDEX) { - Logger::error("The map's province list is full - there can be at most ", Province::MAX_INDEX, " provinces"); + if (provinces.size() >= max_provinces) { + Logger::error("The map's province list is full - maximum number of provinces is ", max_provinces, " (this can be at most ", Province::MAX_INDEX, ")"); return FAILURE; } if (identifier.empty()) { @@ -40,7 +40,7 @@ return_t Map::add_province(const std::string_view identifier, colour_t colour) { return FAILURE; } if (colour == NULL_COLOUR || colour > MAX_COLOUR_RGB) { - Logger::error("Invalid province colour for ", identifier, ": ", Province::colour_to_hex_string(colour)); + Logger::error("Invalid province colour for ", identifier, ": ", colour_to_hex_string(colour)); return FAILURE; } Province new_province { identifier, colour, static_cast(provinces.size() + 1) }; @@ -79,9 +79,20 @@ return_t Map::set_water_province(const std::string_view identifier) { return SUCCESS; } +return_t Map::set_water_province_list(std::vector const& list) { + return_t ret = SUCCESS; + water_provinces.reserve(water_provinces.size() + list.size()); + for (std::string_view const& identifier : list) { + if (set_water_province(identifier) != SUCCESS) { + ret = FAILURE; + } + } + return ret; +} + void Map::lock_water_provinces() { water_provinces.lock(); - Logger::info("Locked water provinces after registering ", water_provinces.get_province_count()); + Logger::info("Locked water provinces after registering ", water_provinces.size()); } return_t Map::add_region(const std::string_view identifier, std::vector const& province_identifiers) { @@ -117,7 +128,7 @@ return_t Map::add_region(const std::string_view identifier, std::vector const& Map::get_provinces() const { + return provinces.get_items(); +} + Province* Map::get_province_by_index(Province::index_t index) { return index != Province::NULL_INDEX ? provinces.get_item_by_index(index - 1) : nullptr; } @@ -169,6 +184,23 @@ Province::index_t Map::get_province_index_at(size_t x, size_t y) const { return Province::NULL_INDEX; } +return_t Map::set_max_provinces(Province::index_t new_max_provinces) { + if (new_max_provinces <= Province::NULL_INDEX) { + Logger::error("Trying to set max province count to an invalid value ", new_max_provinces, " (must be greater than ", Province::NULL_INDEX, ")"); + return FAILURE; + } + if (!provinces.empty() || provinces.is_locked()) { + Logger::error("Trying to set max province count to ", new_max_provinces, " after provinces have already been added and/or locked"); + return FAILURE; + } + max_provinces = new_max_provinces; + return SUCCESS; +} + +Province::index_t Map::get_max_provinces() const { + return max_provinces; +} + void Map::set_selected_province(Province::index_t index) { if (index > get_province_count()) { Logger::error("Trying to set selected province to an invalid index ", index, " (max index is ", get_province_count(), ")"); @@ -194,6 +226,14 @@ Region const* Map::get_region_by_identifier(const std::string_view identifier) c return regions.get_item_by_identifier(identifier); } +size_t Map::get_region_count() const { + return regions.size(); +} + +std::vector const& Map::get_regions() const { + return regions.get_items(); +} + static colour_t colour_at(uint8_t const* colour_data, int32_t idx) { idx *= 3; return (colour_data[idx] << 16) | (colour_data[idx + 1] << 8) | colour_data[idx + 2]; @@ -240,7 +280,7 @@ return_t Map::generate_province_shape_image(size_t new_width, size_t new_height, if (unrecognised_terrain_colours.find(terrain_colour) == unrecognised_terrain_colours.end()) { unrecognised_terrain_colours.insert(terrain_colour); if (detailed_errors) { - Logger::error("Unrecognised terrain colour ", Province::colour_to_hex_string(terrain_colour), + Logger::error("Unrecognised terrain colour ", colour_to_hex_string(terrain_colour), " at (", x, ", ", y, ")"); } } @@ -271,7 +311,7 @@ return_t Map::generate_province_shape_image(size_t new_width, size_t new_height, if (unrecognised_province_colours.find(province_colour) == unrecognised_province_colours.end()) { unrecognised_province_colours.insert(province_colour); if (detailed_errors) { - Logger::error("Unrecognised province colour ", Province::colour_to_hex_string(province_colour), + Logger::error("Unrecognised province colour ", colour_to_hex_string(province_colour), " at (", x, ", ", y, ")"); } } @@ -335,6 +375,10 @@ size_t Map::get_mapmode_count() const { return mapmodes.size(); } +std::vector const& Map::get_mapmodes() const { + return mapmodes.get_items(); +} + Mapmode const* Map::get_mapmode_by_index(size_t index) const { return mapmodes.get_item_by_index(index); } @@ -418,3 +462,70 @@ void Map::tick(Date const& today) { for (Province& province : provinces.get_items()) province.tick(today); } + +using namespace ovdl::csv; + +static return_t validate_province_definitions_header(LineObject const& header) { + static const std::vector standard_header { "province", "red", "green", "blue" }; + for (size_t i = 0; i < standard_header.size(); ++i) { + const std::string_view val = header.get_value_for(i); + if (i == 0 && val.empty()) break; + if (val != standard_header[i]) return FAILURE; + } + return SUCCESS; +} + +static return_t parse_province_colour(colour_t& colour, std::array components) { + return_t ret = SUCCESS; + colour = NULL_COLOUR; + for (std::string_view& c : components) { + colour <<= 8; + if (c.ends_with('.')) c.remove_suffix(1); + bool successful = false; + uint64_t val = StringUtils::string_to_uint64(c, &successful, 10); + if (successful && val <= 255) { + colour |= val; + } else { + ret = FAILURE; + } + } + return ret; +} + +return_t Map::load_province_definitions(std::vector const& lines) { + if (lines.empty()) { + Logger::error("No header or entries in province definition file!"); + return FAILURE; + } + { + LineObject const& header = lines.front(); + if (validate_province_definitions_header(header) != SUCCESS) { + Logger::error("Non-standard province definition file header - make sure this is not a province definition: ", header); + } + } + if (lines.size() <= 1) { + Logger::error("No entries in province definition file!"); + return FAILURE; + } + provinces.reserve(lines.size() - 1); + return_t ret = SUCCESS; + std::for_each(lines.begin() + 1, lines.end(), + [this, &ret](LineObject const& line) -> void { + const std::string_view identifier = line.get_value_for(0); + if (!identifier.empty()) { + colour_t colour; + if (parse_province_colour(colour, { + line.get_value_for(1), + line.get_value_for(2), + line.get_value_for(3) + }) != SUCCESS) { + Logger::error("Error reading colour in province definition: ", line); + ret = FAILURE; + } + if (add_province(identifier, colour) != SUCCESS) ret = FAILURE; + } + } + ); + lock_provinces(); + return ret; +} diff --git a/src/openvic/map/Map.hpp b/src/openvic/map/Map.hpp index 26c07c8..0a2c7c6 100644 --- a/src/openvic/map/Map.hpp +++ b/src/openvic/map/Map.hpp @@ -2,6 +2,8 @@ #include +#include + #include "openvic/map/Region.hpp" namespace OpenVic { @@ -53,6 +55,7 @@ namespace OpenVic { size_t width = 0, height = 0; std::vector province_shape_image; colour_index_map_t colour_index_map; + Province::index_t max_provinces = Province::MAX_INDEX; Province::index_t selected_province = Province::NULL_INDEX; Pop::pop_size_t highest_province_population, total_map_population; @@ -65,22 +68,28 @@ namespace OpenVic { return_t add_province(const std::string_view identifier, colour_t colour); void lock_provinces(); return_t set_water_province(const std::string_view identifier); + return_t set_water_province_list(std::vector const& list); void lock_water_provinces(); return_t add_region(const std::string_view identifier, std::vector const& province_identifiers); void lock_regions(); size_t get_province_count() const; + std::vector const& get_provinces() const; Province* get_province_by_index(Province::index_t index); Province const* get_province_by_index(Province::index_t index) const; Province* get_province_by_identifier(const std::string_view identifier); Province const* get_province_by_identifier(const std::string_view identifier) const; Province::index_t get_province_index_at(size_t x, size_t y) const; + return_t set_max_provinces(Province::index_t new_max_provinces); + Province::index_t get_max_provinces() const; void set_selected_province(Province::index_t index); Province::index_t get_selected_province_index() const; Province const* get_selected_province() const; Region* get_region_by_identifier(const std::string_view identifier); Region const* get_region_by_identifier(const std::string_view identifier) const; + size_t get_region_count() const; + std::vector const& get_regions() const; return_t generate_province_shape_image(size_t new_width, size_t new_height, uint8_t const* colour_data, uint8_t const* terrain_data, terrain_variant_map_t const& terrain_variant_map, bool detailed_errors); @@ -91,6 +100,7 @@ namespace OpenVic { return_t add_mapmode(const std::string_view identifier, Mapmode::colour_func_t colour_func); void lock_mapmodes(); size_t get_mapmode_count() const; + std::vector const& get_mapmodes() const; Mapmode const* get_mapmode_by_index(Mapmode::index_t index) const; Mapmode const* get_mapmode_by_identifier(const std::string_view identifier) const; static constexpr size_t MAPMODE_COLOUR_SIZE = 4; @@ -105,5 +115,7 @@ namespace OpenVic { void update_state(Date const& today); void tick(Date const& today); + + return_t load_province_definitions(std::vector const& lines); }; } diff --git a/src/openvic/map/Province.cpp b/src/openvic/map/Province.cpp index f4588d4..7d03604 100644 --- a/src/openvic/map/Province.cpp +++ b/src/openvic/map/Province.cpp @@ -5,6 +5,7 @@ #include using namespace OpenVic; +using namespace OpenVic::NodeTools; Province::Province(const std::string_view new_identifier, colour_t new_colour, index_t new_index) : HasIdentifierAndColour { new_identifier, new_colour, false }, @@ -45,6 +46,10 @@ Building const* Province::get_building_by_identifier(const std::string_view iden return buildings.get_item_by_identifier(identifier); } +size_t Province::get_building_count() const { + return buildings.size(); +} + std::vector const& Province::get_buildings() const { return buildings.get_items(); } @@ -65,6 +70,15 @@ std::string Province::to_string() const { return stream.str(); } +return_t Province::load_pop_list(PopManager const& pop_manager, ast::NodeCPtr root) { + return expect_list_reserve_length( + pops, + [this, &pop_manager](ast::NodeCPtr pop_node) -> return_t { + return pop_manager.load_pop_into_province(*this, pop_node); + } + )(root); +} + return_t Province::add_pop(Pop&& pop) { if (!is_water()) { pops.push_back(std::move(pop)); @@ -79,6 +93,14 @@ void Province::clear_pops() { pops.clear(); } +size_t Province::get_pop_count() const { + return pops.size(); +} + +std::vector const& Province::get_pops() const { + return pops; +} + Pop::pop_size_t Province::get_total_population() const { return total_population; } diff --git a/src/openvic/map/Province.hpp b/src/openvic/map/Province.hpp index 527a6fe..364bbf8 100644 --- a/src/openvic/map/Province.hpp +++ b/src/openvic/map/Province.hpp @@ -45,13 +45,17 @@ namespace OpenVic { void lock_buildings(); void reset_buildings(); Building const* get_building_by_identifier(const std::string_view identifier) const; + size_t get_building_count() const; std::vector const& get_buildings() const; return_t expand_building(const std::string_view building_type_identifier); Good const* get_rgo() const; std::string to_string() const; + return_t load_pop_list(PopManager const& pop_manager, ast::NodeCPtr root); return_t add_pop(Pop&& pop); void clear_pops(); + size_t get_pop_count() const; + std::vector const& get_pops() const; Pop::pop_size_t get_total_population() const; distribution_t const& get_pop_type_distribution() const; distribution_t const& get_culture_distribution() const; diff --git a/src/openvic/map/Region.cpp b/src/openvic/map/Region.cpp index 8ea45f0..6372e15 100644 --- a/src/openvic/map/Region.cpp +++ b/src/openvic/map/Region.cpp @@ -24,7 +24,7 @@ void ProvinceSet::lock(bool log) { Logger::error("Failed to lock province set - already locked!"); } else { locked = true; - if (log) Logger::info("Locked province set with ", get_province_count(), " provinces"); + if (log) Logger::info("Locked province set with ", size(), " provinces"); } } @@ -37,10 +37,18 @@ void ProvinceSet::reset() { locked = false; } -size_t ProvinceSet::get_province_count() const { +size_t ProvinceSet::size() const { return provinces.size(); } +void ProvinceSet::reserve(size_t size) { + if (locked) { + Logger::error("Failed to reserve space for ", size, " items in province set - already locked!"); + } else { + provinces.reserve(size); + } +} + bool ProvinceSet::contains_province(Province const* province) const { return province && std::find(provinces.begin(), provinces.end(), province) != provinces.end(); } diff --git a/src/openvic/map/Region.hpp b/src/openvic/map/Region.hpp index 9b5b914..e67edaa 100644 --- a/src/openvic/map/Region.hpp +++ b/src/openvic/map/Region.hpp @@ -14,7 +14,8 @@ namespace OpenVic { void lock(bool log = false); bool is_locked() const; void reset(); - size_t get_province_count() const; + size_t size() const; + void reserve(size_t size); bool contains_province(Province const* province) const; std::vector const& get_provinces() const; }; -- cgit v1.2.3-56-ga3b1