diff options
author | Hop311 <Hop3114@gmail.com> | 2023-04-18 19:55:10 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-04-18 19:55:10 +0200 |
commit | ea077c8a7c78477bd247c7fbd21de13bcf2285e9 (patch) | |
tree | 0cc2be6ef3ab1f2af5c2806f60abe988ca6aa7b5 /extension/src/openvic2 | |
parent | 258a088018d36e987b3ffe4a9b418a6c21ad9217 (diff) | |
parent | 1fdd198f943a41468b03b2cdc62c24147f707239 (diff) |
Merge pull request #88 from OpenVic2Project/map-drawing
Further Map Stuff
Diffstat (limited to 'extension/src/openvic2')
-rw-r--r-- | extension/src/openvic2/Date.cpp | 181 | ||||
-rw-r--r-- | extension/src/openvic2/Date.hpp | 3 | ||||
-rw-r--r-- | extension/src/openvic2/Map.cpp | 132 | ||||
-rw-r--r-- | extension/src/openvic2/Map.hpp | 64 | ||||
-rw-r--r-- | extension/src/openvic2/Province.cpp | 19 | ||||
-rw-r--r-- | extension/src/openvic2/Province.hpp | 39 | ||||
-rw-r--r-- | extension/src/openvic2/Region.cpp | 24 | ||||
-rw-r--r-- | extension/src/openvic2/Region.hpp | 29 | ||||
-rw-r--r-- | extension/src/openvic2/Types.cpp | 13 | ||||
-rw-r--r-- | extension/src/openvic2/Types.hpp | 11 |
10 files changed, 308 insertions, 207 deletions
diff --git a/extension/src/openvic2/Date.cpp b/extension/src/openvic2/Date.cpp index 3c5b8d8..e1cef72 100644 --- a/extension/src/openvic2/Date.cpp +++ b/extension/src/openvic2/Date.cpp @@ -1,108 +1,115 @@ #include <sstream> #include "Date.hpp" -namespace OpenVic2 { - bool Timespan::operator< (Timespan const& other) const { return days < other.days; } - bool Timespan::operator> (Timespan const& other) const { return days > other.days; } - bool Timespan::operator<= (Timespan const& other) const { return days <= other.days; } - bool Timespan::operator>= (Timespan const& other) const { return days >= other.days; } - bool Timespan::operator== (Timespan const& other) const { return days == other.days; } - bool Timespan::operator!= (Timespan const& other) const { return days != other.days; } - - Timespan Timespan::operator+ (Timespan const& other) const { return Timespan(days + other.days); } - Timespan Timespan::operator- (Timespan const& other) const { return Timespan(days - other.days); } - Timespan Timespan::operator* (int64_t const& factor) const { return Timespan(days * factor); } - Timespan Timespan::operator/ (int64_t const& factor) const { return Timespan(days / factor); } - - Timespan& Timespan::operator+= (Timespan const& other) { - days += other.days; - return *this; - } - Timespan& Timespan::operator-= (Timespan const& other) { - days -= other.days; - return *this; - } +using namespace OpenVic2; + +bool Timespan::operator< (Timespan const& other) const { return days < other.days; } +bool Timespan::operator> (Timespan const& other) const { return days > other.days; } +bool Timespan::operator<= (Timespan const& other) const { return days <= other.days; } +bool Timespan::operator>= (Timespan const& other) const { return days >= other.days; } +bool Timespan::operator== (Timespan const& other) const { return days == other.days; } +bool Timespan::operator!= (Timespan const& other) const { return days != other.days; } + +Timespan Timespan::operator+ (Timespan const& other) const { return Timespan(days + other.days); } +Timespan Timespan::operator- (Timespan const& other) const { return Timespan(days - other.days); } +Timespan Timespan::operator* (int64_t const& factor) const { return Timespan(days * factor); } +Timespan Timespan::operator/ (int64_t const& factor) const { return Timespan(days / factor); } + +Timespan& Timespan::operator+= (Timespan const& other) { + days += other.days; + return *this; +} +Timespan& Timespan::operator-= (Timespan const& other) { + days -= other.days; + return *this; +} - Timespan fromYearZero(year_t year, month_t month, date_t day) { - int64_t daysElapsed = year * DAYS_IN_YEAR; - size_t daysSinceMonthStart = (day == 0) ? 0 : day - 1; //Underflow protection - for (size_t x = 0; x < month && x < MONTHS_IN_YEAR; x++) { - daysElapsed += DAYS_IN_MONTH[x]; - } - daysElapsed += daysSinceMonthStart; - return Timespan(daysElapsed); - } +Timespan::operator std::string() const { + return std::to_string(days); +} +std::ostream &operator<<(std::ostream &out, Timespan const& timespan) { + return out << static_cast<std::string>(timespan); +} - //This function is not set up to handle dates before Year 0 - YearMonthDayBundle toGregorianDate(Timespan const& timespan) { - year_t year = 0; - month_t month = 0; - date_t day = 0; +Timespan fromYearZero(year_t year, month_t month, date_t day) { + int64_t daysElapsed = year * DAYS_IN_YEAR; + size_t daysSinceMonthStart = (day == 0) ? 0 : day - 1; //Underflow protection + for (size_t x = 0; x < month && x < MONTHS_IN_YEAR; x++) { + daysElapsed += DAYS_IN_MONTH[x]; + } + daysElapsed += daysSinceMonthStart; + return Timespan(daysElapsed); +} - if (timespan >= 0) { - year = timespan.days / DAYS_IN_YEAR; - int64_t remainingDays = timespan.days % DAYS_IN_YEAR; +//This function is not set up to handle dates before Year 0 +YearMonthDayBundle toGregorianDate(Timespan const& timespan) { + year_t year = 0; + month_t month = 0; + date_t day = 0; - for (size_t x = 0; x < MONTHS_IN_YEAR && remainingDays >= DAYS_IN_MONTH[x]; x++) { - remainingDays -= DAYS_IN_MONTH[x]; - month++; - } + if (timespan >= 0) { + year = timespan.days / DAYS_IN_YEAR; + int64_t remainingDays = timespan.days % DAYS_IN_YEAR; - //Corrects month and day to be 1-indexed + for (size_t x = 0; x < MONTHS_IN_YEAR && remainingDays >= DAYS_IN_MONTH[x]; x++) { + remainingDays -= DAYS_IN_MONTH[x]; month++; - day++; } - return std::make_tuple(year, month, day); + + //Corrects month and day to be 1-indexed + month++; + day++; } + return std::make_tuple(year, month, day); +} - Date::Date(Timespan const& timespan) : ts(timespan) { updateDate(ts); } +Date::Date(Timespan const& timespan) : ts(timespan) { updateDate(ts); } - Date::Date(year_t year, month_t month, date_t day) { - ts = fromYearZero(year, month, day); - updateDate(ts); - } +Date::Date(year_t year, month_t month, date_t day) { + ts = fromYearZero(year, month, day); + updateDate(ts); +} - void Date::updateDate(Timespan const& timespan) { - gregorianDate = toGregorianDate(timespan); - } +void Date::updateDate(Timespan const& timespan) { + gregorianDate = toGregorianDate(timespan); +} - size_t Date::getDay() const { return std::get<2>(gregorianDate); } - size_t Date::getMonth() const { return std::get<1>(gregorianDate); } - size_t Date::getYear() const { return std::get<0>(gregorianDate); } +size_t Date::getDay() const { return std::get<2>(gregorianDate); } +size_t Date::getMonth() const { return std::get<1>(gregorianDate); } +size_t Date::getYear() const { return std::get<0>(gregorianDate); } - bool Date::operator< (Date const& other) const { return ts < other.ts; } - bool Date::operator> (Date const& other) const { return ts > other.ts; } - bool Date::operator<= (Date const& other) const { return ts <= other.ts; } - bool Date::operator>= (Date const& other) const { return ts >= other.ts; } - bool Date::operator== (Date const& other) const { return ts == other.ts; } - bool Date::operator!= (Date const& other) const { return ts != other.ts; } +bool Date::operator< (Date const& other) const { return ts < other.ts; } +bool Date::operator> (Date const& other) const { return ts > other.ts; } +bool Date::operator<= (Date const& other) const { return ts <= other.ts; } +bool Date::operator>= (Date const& other) const { return ts >= other.ts; } +bool Date::operator== (Date const& other) const { return ts == other.ts; } +bool Date::operator!= (Date const& other) const { return ts != other.ts; } - Date Date::operator+ (Timespan timespan) const { return Date(ts + timespan); } - Timespan Date::operator- (Date const& other) const { return ts - other.ts; } +Date Date::operator+ (Timespan timespan) const { return Date(ts + timespan); } +Timespan Date::operator- (Date const& other) const { return ts - other.ts; } - Date& Date::operator+= (Timespan const& timespan) { - ts += timespan; - updateDate(ts); - return *this; - } - Date& Date::operator-= (Timespan const& timespan) { - ts -= timespan; - updateDate(ts); - return *this; - } - Date Date::operator++ (int) { - Date oldCopy = *this; - (*this) += 1; - return oldCopy; - } +Date& Date::operator+= (Timespan const& timespan) { + ts += timespan; + updateDate(ts); + return *this; +} +Date& Date::operator-= (Timespan const& timespan) { + ts -= timespan; + updateDate(ts); + return *this; +} +Date Date::operator++ (int) { + Date oldCopy = *this; + (*this) += 1; + return oldCopy; +} - Date::operator std::string() const { - std::stringstream ss; - ss << getYear() << '.' << getMonth() << '.' << getDay(); - return ss.str(); - } - std::ostream &operator<<(std::ostream &out, Date const& date) { - return out << static_cast<std::string>(date); - } +Date::operator std::string() const { + std::stringstream ss; + ss << getYear() << '.' << getMonth() << '.' << getDay(); + return ss.str(); +} +std::ostream &operator<<(std::ostream &out, Date const& date) { + return out << static_cast<std::string>(date); } diff --git a/extension/src/openvic2/Date.hpp b/extension/src/openvic2/Date.hpp index 841b118..9ed5963 100644 --- a/extension/src/openvic2/Date.hpp +++ b/extension/src/openvic2/Date.hpp @@ -28,6 +28,9 @@ namespace OpenVic2 { Timespan& operator+= (Timespan const& other); Timespan& operator-= (Timespan const& other); + + explicit operator std::string() const; + friend std::ostream& operator<< (std::ostream& out, Timespan const& timespan); }; static constexpr size_t MONTHS_IN_YEAR = 12; diff --git a/extension/src/openvic2/Map.cpp b/extension/src/openvic2/Map.cpp index 1654189..0ac8091 100644 --- a/extension/src/openvic2/Map.cpp +++ b/extension/src/openvic2/Map.cpp @@ -1,14 +1,14 @@ #include "Map.hpp" #include <cassert> +#include <unordered_set> using namespace OpenVic2; static const std::string SEPARATOR = "\n - "; Mapmode::Mapmode(index_t new_index, std::string const& new_identifier, colour_func_t new_colour_func) - : index(new_index), identifier(new_identifier), colour_func(new_colour_func) { - assert(!identifier.empty()); + : HasIdentifier(new_identifier), index(new_index), colour_func(new_colour_func) { assert(colour_func != nullptr); } @@ -16,10 +16,6 @@ Mapmode::index_t Mapmode::get_index() const { return index; } -std::string const& Mapmode::get_identifier() const { - return identifier; -} - Mapmode::colour_func_t Mapmode::get_colour_func() const { return colour_func; } @@ -42,15 +38,15 @@ return_t Map::add_province(std::string const& identifier, Province::colour_t col return FAILURE; } Province new_province{ static_cast<Province::index_t>(provinces.size() + 1), identifier, colour }; - for (Province const& province : provinces) { - if (province.get_identifier() == identifier) { - error_message = "Duplicate province identifiers: " + province.to_string() + " and " + new_province.to_string(); - return FAILURE; - } - if (province.get_colour() == colour) { - error_message = "Duplicate province colours: " + province.to_string() + " and " + new_province.to_string(); - return FAILURE; - } + Province const* old_province = get_province_by_identifier(identifier); + if (old_province != nullptr) { + error_message = "Duplicate province identifiers: " + old_province->to_string() + " and " + new_province.to_string(); + return FAILURE; + } + old_province = get_province_by_colour(colour); + if (old_province != nullptr) { + error_message = "Duplicate province colours: " + old_province->to_string() + " and " + new_province.to_string(); + return FAILURE; } provinces.push_back(new_province); error_message = "Added province: " + new_province.to_string(); @@ -61,6 +57,29 @@ void Map::lock_provinces() { provinces_locked = true; } +return_t Map::set_water_province(std::string const& identifier, std::string& error_message) { + if (water_provinces_locked) { + error_message = "The map's water provinces have already been locked!"; + return FAILURE; + } + Province* province = get_province_by_identifier(identifier); + if (province == nullptr) { + error_message = "Unrecognised water province identifier: " + identifier; + return FAILURE; + } + if (province->is_water()) { + error_message = "Province " + identifier + " is already a water province!"; + return FAILURE; + } + province->water = true; + error_message = "Set province " + identifier + " as a water province"; + return SUCCESS; +} + +void Map::lock_water_provinces() { + water_provinces_locked = true; +} + return_t Map::add_region(std::string const& identifier, std::vector<std::string> const& province_identifiers, std::string& error_message) { if (regions_locked) { error_message = "The map's region list has already been locked!"; @@ -75,7 +94,7 @@ return_t Map::add_region(std::string const& identifier, std::vector<std::string> return FAILURE; } Region new_region{ identifier }; - error_message = "Error message for region: " + identifier; + error_message.clear(); for (std::string const& province_identifier : province_identifiers) { Province* province = get_province_by_identifier(province_identifier); if (province != nullptr) { @@ -90,28 +109,36 @@ return_t Map::add_region(std::string const& identifier, std::vector<std::string> error_message += regions[other_region_index].get_identifier(); else error_message += "an unknown region with index " + std::to_string(other_region_index); - } else new_region.provinces.push_back(province); + } else new_region.provinces.insert(province); } } else error_message += SEPARATOR + "Invalid province identifier " + province_identifier; } + return_t ret = SUCCESS; if (!new_region.get_province_count()) { error_message += SEPARATOR + "No valid provinces in region's list"; - return FAILURE; + ret = FAILURE; } - for (Region const& region : regions) { - if (region.get_identifier() == identifier) { - error_message += SEPARATOR + "Duplicate region identifiers: " + region.get_identifier() + " and " + identifier; - return FAILURE; + Region const* old_region = get_region_by_identifier(identifier); + if (old_region != nullptr) { + error_message += SEPARATOR + "Duplicate region identifiers: " + old_region->get_identifier() + " and " + identifier; + ret = FAILURE; + } + + if (ret == SUCCESS) { + regions.push_back(new_region); + // Used to detect provinces listed in multiple regions, will + // be corrected once regions is stable (i.e. lock_regions). + Region* tmp_region_index = reinterpret_cast<Region*>(regions.size()); + for (Province* province : new_region.get_provinces()) + province->region = tmp_region_index; + if (!error_message.empty()) { + error_message += SEPARATOR; + ret = FAILURE; } + error_message += "Added region: " + identifier; } - regions.push_back(new_region); - error_message += SEPARATOR + "Added region: " + identifier; - // Used to detect provinces listed in multiple regions, will - // be corrected once regions is stable (i.e. lock_regions). - Region* tmp_region_index = reinterpret_cast<Region*>(regions.size()); - for (Province* province : new_region.get_provinces()) - province->region = tmp_region_index; - return SUCCESS; + if (ret != SUCCESS) error_message = "Error message for region: " + identifier + error_message; + return ret; } void Map::lock_regions() { @@ -161,6 +188,20 @@ Province const* Map::get_province_by_colour(Province::colour_t colour) const { return nullptr; } +Region* Map::get_region_by_identifier(std::string const& identifier) { + if (!identifier.empty()) + for (Region& region : regions) + if (region.get_identifier() == identifier) return ®ion; + return nullptr; +} + +Region const* Map::get_region_by_identifier(std::string const& identifier) const { + if (!identifier.empty()) + for (Region const& region : regions) + if (region.get_identifier() == identifier) return ®ion; + return nullptr; +} + static Province::colour_t colour_at(uint8_t const* colour_data, int32_t idx) { return (colour_data[idx * 3] << 16) | (colour_data[idx * 3 + 1] << 8) | colour_data[idx * 3 + 2]; } @@ -188,17 +229,13 @@ return_t Map::generate_province_index_image(size_t new_width, size_t new_height, std::vector<bool> province_checklist(provinces.size()); return_t ret = SUCCESS; - - error_message = "Error message for province index image generation:"; + std::unordered_set<Province::colour_t> unrecognised_colours; + error_message.clear(); for (int32_t y = 0; y < height; ++y) { for (int32_t x = 0; x < width; ++x) { const int32_t idx = x + y * width; const Province::colour_t colour = colour_at(colour_data, idx); - if (colour == Province::NULL_COLOUR) { - province_index_image[idx] = Province::NULL_INDEX; - continue; - } if (x > 0) { const int32_t jdx = idx - 1; if (colour_at(colour_data, jdx) == colour) { @@ -220,8 +257,11 @@ return_t Map::generate_province_index_image(size_t new_width, size_t new_height, province_checklist[index - 1] = true; continue; } - error_message += SEPARATOR + "Unrecognised province colour " + Province::colour_to_hex_string(colour) + " at (" + std::to_string(x) + ", " + std::to_string(x) + ")"; - ret = FAILURE; + if (unrecognised_colours.find(colour) == unrecognised_colours.end()) { + unrecognised_colours.insert(colour); + error_message += SEPARATOR + "Unrecognised province colour " + Province::colour_to_hex_string(colour) + " at (" + std::to_string(x) + ", " + std::to_string(y) + ")"; + ret = FAILURE; + } province_index_image[idx] = Province::NULL_INDEX; } } @@ -233,7 +273,8 @@ return_t Map::generate_province_index_image(size_t new_width, size_t new_height, } } - error_message += SEPARATOR + "Generated province index image"; + if (!error_message.empty()) error_message = "Error message for province index image generation:" + error_message + SEPARATOR; + error_message += "Generated province index image"; return ret; } @@ -259,11 +300,10 @@ return_t Map::add_mapmode(std::string const& identifier, Mapmode::colour_func_t return FAILURE; } Mapmode new_mapmode{ mapmodes.size(), identifier, colour_func }; - for (Mapmode const& mapmode : mapmodes) { - if (mapmode.get_identifier() == identifier) { - error_message = "Duplicate mapmode identifiers: " + mapmode.get_identifier() + " and " + identifier; - return FAILURE; - } + Mapmode const* old_mapmode = get_mapmode_by_identifier(identifier); + if (old_mapmode != nullptr) { + error_message = "Duplicate mapmode identifiers: " + old_mapmode->get_identifier() + " and " + identifier; + return FAILURE; } mapmodes.push_back(new_mapmode); error_message = "Added mapmode: " + identifier; @@ -295,12 +335,14 @@ return_t Map::generate_mapmode_colours(Mapmode::index_t index, uint8_t* target, return FAILURE; } Mapmode const& mapmode = mapmodes[index]; - target += 3; // Skip past Province::NULL_INDEX + target += 4; // Skip past Province::NULL_INDEX for (Province const& province : provinces) { const Province::colour_t colour = mapmode.get_colour_func()(*this, province); *target++ = (colour >> 16) & 0xFF; *target++ = (colour >> 8) & 0xFF; *target++ = colour & 0xFF; + *target++ = province.is_water() ? 0 : 255; } + error_message = "Generated province colours for mapmode " + mapmode.get_identifier(); return SUCCESS; } diff --git a/extension/src/openvic2/Map.hpp b/extension/src/openvic2/Map.hpp index 42963c9..73ab8fd 100644 --- a/extension/src/openvic2/Map.hpp +++ b/extension/src/openvic2/Map.hpp @@ -1,75 +1,24 @@ #pragma once -#include <string> -#include <cstdint> #include <vector> #include <functional> -#include "Types.hpp" +#include "Region.hpp" namespace OpenVic2 { - struct Region; - struct Map; - /* REQUIREMENTS: - * MAP-43, MAP-47 - */ - struct Province { - friend struct Map; - - using colour_t = uint32_t; - using index_t = uint16_t; - - static const colour_t NULL_COLOUR = 0, MAX_COLOUR = 0xFFFFFF; - static const index_t NULL_INDEX = 0, MAX_INDEX = 0xFFFF; - private: - index_t index; - std::string identifier; - colour_t colour; - Region* region = nullptr; - - Province(index_t new_index, std::string const& new_identifier, colour_t new_colour); - public: - static std::string colour_to_hex_string(colour_t colour); - - index_t get_index() const; - std::string const& get_identifier() const; - colour_t get_colour() const; - Region* get_region() const; - std::string to_string() const; - }; - - /* REQUIREMENTS: - * MAP-6, MAP-44, MAP-48 - */ - struct Region { - friend struct Map; - private: - std::string identifier; - std::vector<Province*> provinces; - - Region(std::string const& new_identifier); - public: - std::string const& get_identifier() const; - size_t get_province_count() const; - bool contains_province(Province const* province) const; - std::vector<Province*> const& get_provinces() const; - }; - - struct Mapmode { + struct Mapmode : HasIdentifier { friend struct Map; using colour_func_t = std::function<Province::colour_t (Map const&, Province const&)>; using index_t = size_t; private: index_t index; - std::string identifier; colour_func_t colour_func; Mapmode(index_t new_index, std::string const& new_identifier, colour_func_t new_colour_func); public: index_t get_index() const; - std::string const& get_identifier() const; colour_func_t get_colour_func() const; }; @@ -80,7 +29,7 @@ namespace OpenVic2 { private: std::vector<Province> provinces; std::vector<Region> regions; - bool provinces_locked = false, regions_locked = false; + bool provinces_locked = false, water_provinces_locked = false, regions_locked = false; size_t width = 0, height = 0; std::vector<Province::index_t> province_index_image; @@ -88,10 +37,12 @@ namespace OpenVic2 { public: return_t add_province(std::string const& identifier, Province::colour_t colour, std::string& error_message); void lock_provinces(); + return_t set_water_province(std::string const& identifier, std::string& error_message); + void lock_water_provinces(); return_t add_region(std::string const& identifier, std::vector<std::string> const& province_identifiers, std::string& error_message); void lock_regions(); - size_t get_province_count() const; + size_t get_province_count() 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(std::string const& identifier); @@ -99,6 +50,9 @@ namespace OpenVic2 { Province* get_province_by_colour(Province::colour_t colour); Province const* get_province_by_colour(Province::colour_t colour) const; + Region* get_region_by_identifier(std::string const& identifier); + Region const* get_region_by_identifier(std::string const& identifier) const; + return_t generate_province_index_image(size_t new_width, size_t new_height, uint8_t const* colour_data, std::string& error_message); size_t get_width() const; size_t get_height() const; diff --git a/extension/src/openvic2/Province.cpp b/extension/src/openvic2/Province.cpp index 49f1b0e..7d55708 100644 --- a/extension/src/openvic2/Province.cpp +++ b/extension/src/openvic2/Province.cpp @@ -1,4 +1,4 @@ -#include "Map.hpp" +#include "Province.hpp" #include <cassert> #include <sstream> @@ -7,9 +7,8 @@ using namespace OpenVic2; Province::Province(index_t new_index, std::string const& new_identifier, colour_t new_colour) : - index(new_index), identifier(new_identifier), colour(new_colour) { + HasIdentifier(new_identifier), index(new_index), colour(new_colour) { assert(index != NULL_INDEX); - assert(!identifier.empty()); assert(colour != NULL_COLOUR); } @@ -23,10 +22,6 @@ Province::index_t Province::get_index() const { return index; } -std::string const& Province::get_identifier() const { - return identifier; -} - Province::colour_t Province::get_colour() const { return colour; } @@ -35,6 +30,14 @@ Region* Province::get_region() const { return region; } +bool Province::is_water() const { + return water; +} + +Province::life_rating_t Province::get_life_rating() const { + return life_rating; +} + std::string Province::to_string() const { - return "(#" + std::to_string(index) + ", " + identifier + ", 0x" + colour_to_hex_string(colour) + ")"; + return "(#" + std::to_string(index) + ", " + get_identifier() + ", 0x" + colour_to_hex_string(colour) + ")"; } diff --git a/extension/src/openvic2/Province.hpp b/extension/src/openvic2/Province.hpp new file mode 100644 index 0000000..deebd8c --- /dev/null +++ b/extension/src/openvic2/Province.hpp @@ -0,0 +1,39 @@ +#pragma once + +#include "Types.hpp" + +namespace OpenVic2 { + struct Region; + struct Map; + + /* REQUIREMENTS: + * MAP-5, MAP-8, MAP-43, MAP-47 + */ + struct Province : HasIdentifier { + friend struct Map; + + using colour_t = uint32_t; + using index_t = uint16_t; + using life_rating_t = int8_t; + + static const colour_t NULL_COLOUR = 0, MAX_COLOUR = 0xFFFFFF; + static const index_t NULL_INDEX = 0, MAX_INDEX = 0xFFFF; + private: + index_t index; + colour_t colour; + Region* region = nullptr; + bool water = false; + life_rating_t life_rating = 0; + + Province(index_t new_index, std::string const& new_identifier, colour_t new_colour); + public: + static std::string colour_to_hex_string(colour_t colour); + + index_t get_index() const; + colour_t get_colour() const; + Region* get_region() const; + bool is_water() const; + life_rating_t get_life_rating() const; + std::string to_string() const; + }; +} diff --git a/extension/src/openvic2/Region.cpp b/extension/src/openvic2/Region.cpp index 6ee05f5..67a75a9 100644 --- a/extension/src/openvic2/Region.cpp +++ b/extension/src/openvic2/Region.cpp @@ -1,26 +1,26 @@ -#include "Map.hpp" +#include "Region.hpp" #include <cassert> #include <algorithm> using namespace OpenVic2; -Region::Region(std::string const& new_identifier) : identifier(new_identifier) { - assert(!identifier.empty()); -} - -std::string const& Region::get_identifier() const { - return identifier; -} - -size_t Region::get_province_count() const { +size_t ProvinceSet::get_province_count() const { return provinces.size(); } -bool Region::contains_province(Province const* province) const { +bool ProvinceSet::contains_province(Province const* province) const { return province && std::find(provinces.begin(), provinces.end(), province) != provinces.end(); } -std::vector<Province*> const& Region::get_provinces() const { +std::set<Province*> const& ProvinceSet::get_provinces() const { return provinces; } + +Region::Region(std::string const& new_identifier) : HasIdentifier(new_identifier) {} + +Province::colour_t Region::get_colour() const { + if (provinces.empty()) return 0xFF0000; + Province const* province = *provinces.cbegin(); + return province->get_colour(); +} diff --git a/extension/src/openvic2/Region.hpp b/extension/src/openvic2/Region.hpp new file mode 100644 index 0000000..4ebabd1 --- /dev/null +++ b/extension/src/openvic2/Region.hpp @@ -0,0 +1,29 @@ +#pragma once + +#include <set> + +#include "Province.hpp" + +namespace OpenVic2 { + struct Map; + + struct ProvinceSet { + protected: + std::set<Province*> provinces; + public: + size_t get_province_count() const; + bool contains_province(Province const* province) const; + std::set<Province*> const& get_provinces() const; + }; + + /* REQUIREMENTS: + * MAP-6, MAP-44, MAP-48 + */ + struct Region : HasIdentifier, ProvinceSet { + friend struct Map; + private: + Region(std::string const& new_identifier); + public: + Province::colour_t get_colour() const; + }; +} diff --git a/extension/src/openvic2/Types.cpp b/extension/src/openvic2/Types.cpp new file mode 100644 index 0000000..67c7a21 --- /dev/null +++ b/extension/src/openvic2/Types.cpp @@ -0,0 +1,13 @@ +#include "Types.hpp" + +#include <cassert> + +using namespace OpenVic2; + +HasIdentifier::HasIdentifier(std::string const& new_identifier) : identifier(new_identifier) { + assert(!identifier.empty()); +} + +std::string const& HasIdentifier::get_identifier() const { + return identifier; +} diff --git a/extension/src/openvic2/Types.hpp b/extension/src/openvic2/Types.hpp index 0fb1c8b..bf5ee27 100644 --- a/extension/src/openvic2/Types.hpp +++ b/extension/src/openvic2/Types.hpp @@ -1,7 +1,18 @@ #pragma once +#include <string> + namespace OpenVic2 { using return_t = bool; // This mirrors godot::Error, where `OK = 0` and `FAILED = 1`. static const return_t SUCCESS = false, FAILURE = true; + + struct HasIdentifier { + private: + std::string identifier; + protected: + HasIdentifier(std::string const& new_identifier); + public: + std::string const& get_identifier() const; + }; } |