aboutsummaryrefslogtreecommitdiff
path: root/src/openvic-simulation
diff options
context:
space:
mode:
Diffstat (limited to 'src/openvic-simulation')
-rw-r--r--src/openvic-simulation/GameManager.cpp160
-rw-r--r--src/openvic-simulation/GameManager.hpp9
-rw-r--r--src/openvic-simulation/country/CountryInstance.cpp112
-rw-r--r--src/openvic-simulation/country/CountryInstance.hpp56
-rw-r--r--src/openvic-simulation/dataloader/Dataloader.cpp32
-rw-r--r--src/openvic-simulation/dataloader/NodeTools.cpp6
-rw-r--r--src/openvic-simulation/economy/Building.cpp316
-rw-r--r--src/openvic-simulation/economy/Building.hpp171
-rw-r--r--src/openvic-simulation/economy/BuildingInstance.cpp52
-rw-r--r--src/openvic-simulation/economy/BuildingInstance.hpp33
-rw-r--r--src/openvic-simulation/economy/BuildingType.cpp114
-rw-r--r--src/openvic-simulation/economy/BuildingType.hpp89
-rw-r--r--src/openvic-simulation/economy/EconomyManager.hpp2
-rw-r--r--src/openvic-simulation/economy/Good.cpp14
-rw-r--r--src/openvic-simulation/economy/Good.hpp4
-rw-r--r--src/openvic-simulation/economy/ProductionType.cpp4
-rw-r--r--src/openvic-simulation/economy/ProductionType.hpp2
-rw-r--r--src/openvic-simulation/history/CountryHistory.hpp2
-rw-r--r--src/openvic-simulation/history/HistoryManager.hpp4
-rw-r--r--src/openvic-simulation/history/HistoryMap.hpp15
-rw-r--r--src/openvic-simulation/history/ProvinceHistory.cpp16
-rw-r--r--src/openvic-simulation/history/ProvinceHistory.hpp9
-rw-r--r--src/openvic-simulation/interface/GUI.cpp12
-rw-r--r--src/openvic-simulation/interface/GUI.hpp10
-rw-r--r--src/openvic-simulation/map/Map.cpp52
-rw-r--r--src/openvic-simulation/map/Map.hpp18
-rw-r--r--src/openvic-simulation/map/Province.cpp201
-rw-r--r--src/openvic-simulation/map/Province.hpp87
-rw-r--r--src/openvic-simulation/map/Region.cpp13
-rw-r--r--src/openvic-simulation/map/Region.hpp3
-rw-r--r--src/openvic-simulation/map/TerrainType.hpp2
-rw-r--r--src/openvic-simulation/military/LeaderTrait.hpp2
-rw-r--r--src/openvic-simulation/military/Wargoal.cpp2
-rw-r--r--src/openvic-simulation/military/Wargoal.hpp4
-rw-r--r--src/openvic-simulation/misc/Define.cpp25
-rw-r--r--src/openvic-simulation/misc/Define.hpp7
-rw-r--r--src/openvic-simulation/misc/Modifier.cpp (renamed from src/openvic-simulation/Modifier.cpp)40
-rw-r--r--src/openvic-simulation/misc/Modifier.hpp (renamed from src/openvic-simulation/Modifier.hpp)13
-rw-r--r--src/openvic-simulation/politics/NationalFocus.hpp18
-rw-r--r--src/openvic-simulation/politics/NationalValue.hpp2
-rw-r--r--src/openvic-simulation/pop/Culture.cpp15
-rw-r--r--src/openvic-simulation/pop/Culture.hpp6
-rw-r--r--src/openvic-simulation/pop/Pop.hpp2
-rw-r--r--src/openvic-simulation/pop/Religion.cpp14
-rw-r--r--src/openvic-simulation/pop/Religion.hpp2
-rw-r--r--src/openvic-simulation/types/Colour.hpp2
-rw-r--r--src/openvic-simulation/types/Date.cpp4
-rw-r--r--src/openvic-simulation/types/Date.hpp2
-rw-r--r--src/openvic-simulation/types/IdentifierRegistry.hpp26
-rw-r--r--src/openvic-simulation/types/fixed_point/FixedPointMap.hpp48
50 files changed, 883 insertions, 971 deletions
diff --git a/src/openvic-simulation/GameManager.cpp b/src/openvic-simulation/GameManager.cpp
index 427fbb1..397b729 100644
--- a/src/openvic-simulation/GameManager.cpp
+++ b/src/openvic-simulation/GameManager.cpp
@@ -37,18 +37,31 @@ void GameManager::tick() {
set_needs_update();
}
-bool GameManager::setup() {
+bool GameManager::reset() {
session_start = time(nullptr);
clock.reset();
- today = { 1836 };
+ today = {};
economy_manager.get_good_manager().reset_to_defaults();
- bool ret = map.setup(economy_manager.get_building_manager(), pop_manager);
+ bool ret = map.reset(economy_manager.get_building_manager());
set_needs_update();
return ret;
}
-Date GameManager::get_today() const {
- return today;
+bool GameManager::load_bookmark(Bookmark const* new_bookmark) {
+ bool ret = reset();
+ bookmark = new_bookmark;
+ if (bookmark == nullptr) {
+ return ret;
+ }
+ Logger::info("Loading bookmark ", bookmark->get_name(), " with start date ", bookmark->get_date());
+ if (!define_manager.in_game_period(bookmark->get_date())) {
+ Logger::warning("Bookmark date ", bookmark->get_date(), " is not in the game's time period!");
+ }
+ today = bookmark->get_date();
+ ret &= map.apply_history_to_provinces(history_manager.get_province_manager(), today);
+ // TODO - apply country history
+ // TODO - apply pop history
+ return ret;
}
bool GameManager::expand_building(Province::index_t province_index, std::string_view building_type_identifier) {
@@ -61,14 +74,58 @@ bool GameManager::expand_building(Province::index_t province_index, std::string_
return province->expand_building(building_type_identifier);
}
-static constexpr colour_t LOW_ALPHA_VALUE = float_to_alpha_value(0.4f);
-static constexpr colour_t HIGH_ALPHA_VALUE = float_to_alpha_value(0.7f);
+static constexpr colour_t ALPHA_VALUE = float_to_alpha_value(0.5f);
+
+static constexpr Mapmode::base_stripe_t combine_base_stripe(colour_t base, colour_t stripe) {
+ return (static_cast<Mapmode::base_stripe_t>(stripe) << (sizeof(colour_t) * 8)) | base;
+}
-static colour_t default_colour(Province const& province) {
- /* Nice looking colours to blend with the terrain textures */
- static constexpr colour_t LAND_COLOUR = 0x0D7017;
- static constexpr colour_t WATER_COLOUR = 0x4287F5;
- return LOW_ALPHA_VALUE | (province.get_water() ? WATER_COLOUR : LAND_COLOUR);
+static constexpr Mapmode::base_stripe_t make_solid_base_stripe(colour_t colour) {
+ return combine_base_stripe(colour, colour);
+}
+
+static constexpr auto make_solid_base_stripe_func(auto func) {
+ return [func](Map const& map, Province const& province) -> Mapmode::base_stripe_t {
+ return make_solid_base_stripe(func(map, province));
+ };
+}
+
+template<std::derived_from<HasColour> T>
+static constexpr Mapmode::base_stripe_t get_colour_mapmode(T const* item) {
+ return item != nullptr ? make_solid_base_stripe(ALPHA_VALUE | item->get_colour()) : NULL_COLOUR;
+}
+
+template<std::derived_from<HasColour> T>
+static constexpr auto get_colour_mapmode(T const*(Province::*get_item)() const) {
+ return [get_item](Map const& map, Province const& province) -> Mapmode::base_stripe_t {
+ T const* item = (province.*get_item)();
+ return item != nullptr ? make_solid_base_stripe(ALPHA_VALUE | item->get_colour()) : NULL_COLOUR;
+ };
+}
+
+template<std::derived_from<HasColour> T>
+static constexpr Mapmode::base_stripe_t shaded_mapmode(fixed_point_map_t<T const*> const& map) {
+ const std::pair<fixed_point_map_const_iterator_t<T const*>, fixed_point_map_const_iterator_t<T const*>> largest =
+ get_largest_two_items(map);
+ if (largest.first != map.end()) {
+ const colour_t base_colour = ALPHA_VALUE | largest.first->first->get_colour();
+ if (largest.second != map.end()) {
+ /* If second largest is at least a third... */
+ if (largest.second->second * 3 >= get_total(map)) {
+ const colour_t stripe_colour = ALPHA_VALUE | largest.second->first->get_colour();
+ return combine_base_stripe(base_colour, stripe_colour);
+ }
+ }
+ return make_solid_base_stripe(base_colour);
+ }
+ return NULL_COLOUR;
+}
+
+template<std::derived_from<HasColour> T>
+static constexpr auto shaded_mapmode(fixed_point_map_t<T const*> const&(Province::*get_map)() const) {
+ return [get_map](Map const& map, Province const& province) -> Mapmode::base_stripe_t {
+ return shaded_mapmode((province.*get_map)());
+ };
}
bool GameManager::load_hardcoded_defines() {
@@ -78,87 +135,76 @@ bool GameManager::load_hardcoded_defines() {
const std::vector<mapmode_t> mapmodes {
{
"mapmode_terrain",
- [](Map const&, Province const& province) -> colour_t {
- return default_colour(province);
+ [](Map const&, Province const& province) -> Mapmode::base_stripe_t {
+ return NULL_COLOUR;
}
},
{
+ "mapmode_political", get_colour_mapmode(&Province::get_owner)
+ },
+ {
"mapmode_province",
- [](Map const&, Province const& province) -> colour_t {
- return HIGH_ALPHA_VALUE | province.get_colour();
- }
+ make_solid_base_stripe_func([](Map const&, Province const& province) -> colour_t {
+ return ALPHA_VALUE | province.get_colour();
+ })
},
{
- "mapmode_region",
- [](Map const&, Province const& province) -> colour_t {
- Region const* region = province.get_region();
- return region != nullptr ? HIGH_ALPHA_VALUE | region->get_colour() : default_colour(province);
- }
+ "mapmode_region", get_colour_mapmode(&Province::get_region)
},
{
"mapmode_index",
- [](Map const& map, Province const& province) -> colour_t {
+ make_solid_base_stripe_func([](Map const& map, Province const& province) -> colour_t {
const colour_t f = fraction_to_colour_byte(province.get_index(), map.get_province_count() + 1);
- return HIGH_ALPHA_VALUE | (f << 16) | (f << 8) | f;
- }
+ return ALPHA_VALUE | (f << 16) | (f << 8) | f;
+ })
},
{
- "mapmode_terrain_type",
- [](Map const& map, Province const& province) -> colour_t {
- TerrainType const* terrarin_type = province.get_terrain_type();
- return terrarin_type != nullptr ? HIGH_ALPHA_VALUE | terrarin_type->get_colour() : default_colour(province);
- }
+ "mapmode_terrain_type", get_colour_mapmode(&Province::get_terrain_type)
},
{
- "mapmode_rgo",
- [](Map const& map, Province const& province) -> colour_t {
- Good const* rgo = province.get_rgo();
- return rgo != nullptr ? HIGH_ALPHA_VALUE | rgo->get_colour() : default_colour(province);
- }
+ "mapmode_rgo", get_colour_mapmode(&Province::get_rgo)
},
{
"mapmode_infrastructure",
- [](Map const& map, Province const& province) -> colour_t {
- BuildingInstance const* railroad = province.get_building_by_identifier("building_railroad");
+ make_solid_base_stripe_func([](Map const& map, Province const& province) -> colour_t {
+ BuildingInstance const* railroad = province.get_building_by_identifier("railroad");
if (railroad != nullptr) {
- colour_t val = fraction_to_colour_byte(railroad->get_current_level(),
- railroad->get_building().get_max_level() + 1, 0.5f, 1.0f);
+ colour_t val = fraction_to_colour_byte(railroad->get_level(),
+ railroad->get_building_type().get_max_level() + 1, 0.5f, 1.0f);
switch (railroad->get_expansion_state()) {
- case ExpansionState::CannotExpand:
+ case BuildingInstance::ExpansionState::CannotExpand:
val <<= 16;
break;
- case ExpansionState::CanExpand:
+ case BuildingInstance::ExpansionState::CanExpand:
break;
default:
val <<= 8;
break;
}
- return HIGH_ALPHA_VALUE | val;
+ return ALPHA_VALUE | val;
}
- return default_colour(province);
- }
+ return NULL_COLOUR;
+ })
},
{
"mapmode_population",
- [](Map const& map, Province const& province) -> colour_t {
- return HIGH_ALPHA_VALUE | (fraction_to_colour_byte(province.get_total_population(), map.get_highest_province_population() + 1, 0.1f, 1.0f) << 8);
- }
+ make_solid_base_stripe_func([](Map const& map, Province const& province) -> colour_t {
+ // TODO - explore non-linear scaling to have more variation among non-massive provinces
+ // TODO - when selecting a province, only show the population of provinces controlled (or owned?)
+ // by the same country, relative to the most populous province in that set of provinces
+ return ALPHA_VALUE | (fraction_to_colour_byte(
+ province.get_total_population(), map.get_highest_province_population() + 1, 0.1f, 1.0f
+ ) << 8);
+ })
},
{
- "mapmode_culture",
- [](Map const& map, Province const& province) -> colour_t {
- HasIdentifierAndColour const* largest = get_largest_item(province.get_culture_distribution()).first;
- return largest != nullptr ? HIGH_ALPHA_VALUE | largest->get_colour() : default_colour(province);
- }
+ "mapmode_culture", shaded_mapmode(&Province::get_culture_distribution)
},
{
- "mapmode_religion",
- [](Map const& map, Province const& province) -> colour_t {
- HasIdentifierAndColour const* largest = get_largest_item(province.get_religion_distribution()).first;
- return largest != nullptr ? HIGH_ALPHA_VALUE | largest->get_colour() : default_colour(province);
- }
+ "mapmode_religion", shaded_mapmode(&Province::get_religion_distribution)
}
};
+
for (mapmode_t const& mapmode : mapmodes) {
ret &= map.add_mapmode(mapmode.first, mapmode.second);
}
diff --git a/src/openvic-simulation/GameManager.hpp b/src/openvic-simulation/GameManager.hpp
index 6be2938..cd86716 100644
--- a/src/openvic-simulation/GameManager.hpp
+++ b/src/openvic-simulation/GameManager.hpp
@@ -1,7 +1,7 @@
#pragma once
#include "openvic-simulation/GameAdvancementHook.hpp"
-#include "openvic-simulation/Modifier.hpp"
+#include "openvic-simulation/misc/Modifier.hpp"
#include "openvic-simulation/country/Country.hpp"
#include "openvic-simulation/economy/EconomyManager.hpp"
#include "openvic-simulation/history/HistoryManager.hpp"
@@ -29,7 +29,8 @@ namespace OpenVic {
GameAdvancementHook clock;
time_t session_start; /* SS-54, as well as allowing time-tracking */
- Date today;
+ Bookmark const* PROPERTY(bookmark);
+ Date PROPERTY(today);
state_updated_func_t state_updated;
bool needs_update;
@@ -52,9 +53,9 @@ namespace OpenVic {
REF_GETTERS(ui_manager)
REF_GETTERS(clock)
- bool setup();
+ bool reset();
+ bool load_bookmark(Bookmark const* new_bookmark);
- Date get_today() const;
bool expand_building(Province::index_t province_index, std::string_view building_type_identifier);
/* Hardcoded data for defining things for which parsing from files has
diff --git a/src/openvic-simulation/country/CountryInstance.cpp b/src/openvic-simulation/country/CountryInstance.cpp
index a14f0f0..d4f9be7 100644
--- a/src/openvic-simulation/country/CountryInstance.cpp
+++ b/src/openvic-simulation/country/CountryInstance.cpp
@@ -3,77 +3,77 @@
using namespace OpenVic;
bool CountryInstance::add_accepted_culture(Culture const* new_accepted_culture) {
- if(std::find(accepted_cultures.begin(), accepted_cultures.end(), new_accepted_culture) != accepted_cultures.end()) {
- Logger::warning("Attempted to add accepted culture ", new_accepted_culture->get_identifier(), " to country ", base_country->get_identifier(), ": already present!");
- return false;
- }
- accepted_cultures.push_back(new_accepted_culture);
- return true;
+ if(std::find(accepted_cultures.begin(), accepted_cultures.end(), new_accepted_culture) != accepted_cultures.end()) {
+ Logger::warning("Attempted to add accepted culture ", new_accepted_culture->get_identifier(), " to country ", base_country->get_identifier(), ": already present!");
+ return false;
+ }
+ accepted_cultures.push_back(new_accepted_culture);
+ return true;
}
bool CountryInstance::remove_accepted_culture(Culture const* culture_to_remove) {
- auto existing_entry = std::find(accepted_cultures.begin(), accepted_cultures.end(), culture_to_remove);
- if (existing_entry == accepted_cultures.end()) {
- Logger::warning("Attempted to remove accepted culture ", culture_to_remove->get_identifier(), " from country ", base_country->get_identifier(), ": not present!");
- return false;
- }
- accepted_cultures.erase(existing_entry);
- return true;
+ auto existing_entry = std::find(accepted_cultures.begin(), accepted_cultures.end(), culture_to_remove);
+ if (existing_entry == accepted_cultures.end()) {
+ Logger::warning("Attempted to remove accepted culture ", culture_to_remove->get_identifier(), " from country ", base_country->get_identifier(), ": not present!");
+ return false;
+ }
+ accepted_cultures.erase(existing_entry);
+ return true;
}
void CountryInstance::add_to_upper_house(Ideology const* party, fixed_point_t popularity) {
- upper_house[party] = popularity;
+ upper_house[party] = popularity;
}
bool CountryInstance::remove_from_upper_house(Ideology const* party) {
- return upper_house.erase(party) == 1;
+ return upper_house.erase(party) == 1;
}
bool CountryInstance::add_reform(Reform const* new_reform) {
- if (std::find(reforms.begin(), reforms.end(), new_reform) != reforms.end()) {
- Logger::warning("Attempted to add reform ", new_reform->get_identifier(), " to country ", base_country->get_identifier(), ": already present!");
- return false;
- }
- reforms.push_back(new_reform);
- return true;
+ if (std::find(reforms.begin(), reforms.end(), new_reform) != reforms.end()) {
+ Logger::warning("Attempted to add reform ", new_reform->get_identifier(), " to country ", base_country->get_identifier(), ": already present!");
+ return false;
+ }
+ reforms.push_back(new_reform);
+ return true;
}
bool CountryInstance::remove_reform(Reform const* reform_to_remove) {
- auto existing_entry = std::find(reforms.begin(), reforms.end(), reform_to_remove);
- if (existing_entry == reforms.end()) {
- Logger::warning("Attempted to remove reform ", reform_to_remove->get_identifier(), " from country ", base_country->get_identifier(), ": not present!");
- return false;
- }
- reforms.erase(existing_entry);
- return true;
+ auto existing_entry = std::find(reforms.begin(), reforms.end(), reform_to_remove);
+ if (existing_entry == reforms.end()) {
+ Logger::warning("Attempted to remove reform ", reform_to_remove->get_identifier(), " from country ", base_country->get_identifier(), ": not present!");
+ return false;
+ }
+ reforms.erase(existing_entry);
+ return true;
}
-void CountryInstance::apply_history_to_country(CountryHistoryMap const& history, Date date) {
- auto entries = history.get_entries(date);
+bool CountryInstance::apply_history_to_country(CountryHistoryMap const& history, Date date) {
+ accepted_cultures.clear();
+ upper_house.clear();
+ reforms.clear();
- accepted_cultures.clear();
- upper_house.clear();
- reforms.clear();
-
- for (CountryHistoryEntry const* entry : entries) {
- if (entry->get_primary_culture()) primary_culture = *entry->get_primary_culture();
- for (const auto culture : entry->get_accepted_cultures()) {
- add_accepted_culture(culture);
- }
- if (entry->get_religion()) religion = *entry->get_religion();
- if (entry->get_ruling_party()) ruling_party = *entry->get_ruling_party();
- if (entry->get_last_election()) last_election = *entry->get_last_election();
- for (const auto& party : entry->get_upper_house()) {
- add_to_upper_house(party.first, party.second);
- }
- if (entry->get_capital()) capital = *entry->get_capital();
- if (entry->get_government_type()) government_type = *entry->get_government_type();
- if (entry->get_plurality()) plurality = *entry->get_plurality();
- if (entry->get_national_value()) national_value = *entry->get_national_value();
- if (entry->get_civilised()) civilised = *entry->get_civilised();
- if (entry->get_prestige()) prestige = *entry->get_prestige();
- for (const auto reform : entry->get_reforms()) {
- add_reform(reform);
- }
- }
-} \ No newline at end of file
+ bool ret = true;
+ for (CountryHistoryEntry const* entry : history.get_entries_up_to(date)) {
+ if (entry->get_primary_culture()) primary_culture = *entry->get_primary_culture();
+ for (Culture const* culture : entry->get_accepted_cultures()) {
+ ret &= add_accepted_culture(culture);
+ }
+ if (entry->get_religion()) religion = *entry->get_religion();
+ if (entry->get_ruling_party()) ruling_party = *entry->get_ruling_party();
+ if (entry->get_last_election()) last_election = *entry->get_last_election();
+ for (auto const& [ideology, popularity] : entry->get_upper_house()) {
+ add_to_upper_house(ideology, popularity);
+ }
+ if (entry->get_capital()) capital = *entry->get_capital();
+ if (entry->get_government_type()) government_type = *entry->get_government_type();
+ if (entry->get_plurality()) plurality = *entry->get_plurality();
+ if (entry->get_national_value()) national_value = *entry->get_national_value();
+ if (entry->get_civilised()) civilised = *entry->get_civilised();
+ if (entry->get_prestige()) prestige = *entry->get_prestige();
+ for (Reform const* reform : entry->get_reforms()) {
+ ret &= add_reform(reform);
+ }
+ }
+ return ret;
+}
diff --git a/src/openvic-simulation/country/CountryInstance.hpp b/src/openvic-simulation/country/CountryInstance.hpp
index 6510ecf..98c6e90 100644
--- a/src/openvic-simulation/country/CountryInstance.hpp
+++ b/src/openvic-simulation/country/CountryInstance.hpp
@@ -6,34 +6,34 @@
#include "openvic-simulation/utility/Getters.hpp"
namespace OpenVic {
- /* Representation of an existing country that is currently in-game. */
- struct CountryInstance {
- private:
- Country const* PROPERTY_RW(base_country);
- Culture const* PROPERTY_RW(primary_culture);
- std::vector<Culture const*> PROPERTY(accepted_cultures);
- Religion const* PROPERTY_RW(religion);
- CountryParty const* PROPERTY_RW(ruling_party);
- Date PROPERTY_RW(last_election);
- decimal_map_t<Ideology const*> PROPERTY(upper_house);
- Province const* PROPERTY_RW(capital);
- GovernmentType const* PROPERTY_RW(government_type);
- fixed_point_t PROPERTY_RW(plurality);
- NationalValue const* PROPERTY_RW(national_value);
- bool PROPERTY_RW(civilised);
- fixed_point_t PROPERTY_RW(prestige);
- std::vector<Reform const*> PROPERTY(reforms); // TODO: should be map of reform groups to active reforms: must set defaults & validate applied history
- // TODO: Military units + OOBs; will probably need an extensible deployment class
+ /* Representation of an existing country that is currently in-game. */
+ struct CountryInstance {
+ private:
+ Country const* PROPERTY_RW(base_country);
+ Culture const* PROPERTY_RW(primary_culture);
+ std::vector<Culture const*> PROPERTY(accepted_cultures);
+ Religion const* PROPERTY_RW(religion);
+ CountryParty const* PROPERTY_RW(ruling_party);
+ Date PROPERTY_RW(last_election);
+ fixed_point_map_t<Ideology const*> PROPERTY(upper_house);
+ Province const* PROPERTY_RW(capital);
+ GovernmentType const* PROPERTY_RW(government_type);
+ fixed_point_t PROPERTY_RW(plurality);
+ NationalValue const* PROPERTY_RW(national_value);
+ bool PROPERTY_RW(civilised);
+ fixed_point_t PROPERTY_RW(prestige);
+ std::vector<Reform const*> PROPERTY(reforms); // TODO: should be map of reform groups to active reforms: must set defaults & validate applied history
+ // TODO: Military units + OOBs; will probably need an extensible deployment class
- public:
- bool add_accepted_culture(Culture const* new_accepted_culture);
- bool remove_accepted_culture(Culture const* culture_to_remove);
- /* Add or modify a party in the upper house. */
- void add_to_upper_house(Ideology const* party, fixed_point_t popularity);
- bool remove_from_upper_house(Ideology const* party);
- bool add_reform(Reform const* new_reform);
- bool remove_reform(Reform const* reform_to_remove);
+ public:
+ bool add_accepted_culture(Culture const* new_accepted_culture);
+ bool remove_accepted_culture(Culture const* culture_to_remove);
+ /* Add or modify a party in the upper house. */
+ void add_to_upper_house(Ideology const* party, fixed_point_t popularity);
+ bool remove_from_upper_house(Ideology const* party);
+ bool add_reform(Reform const* new_reform);
+ bool remove_reform(Reform const* reform_to_remove);
- void apply_history_to_country(CountryHistoryMap const& history, Date date);
- };
+ bool apply_history_to_country(CountryHistoryMap const& history, Date date);
+ };
} // namespace OpenVic
diff --git a/src/openvic-simulation/dataloader/Dataloader.cpp b/src/openvic-simulation/dataloader/Dataloader.cpp
index d36799f..f86fab6 100644
--- a/src/openvic-simulation/dataloader/Dataloader.cpp
+++ b/src/openvic-simulation/dataloader/Dataloader.cpp
@@ -849,6 +849,10 @@ bool Dataloader::load_defines(GameManager& game_manager) const {
static const std::string religion_file = "common/religion.txt";
static const std::string leader_traits_file = "common/traits.txt";
static const std::string cb_types_file = "common/cb_types.txt";
+ static const std::string crime_modifiers_file = "common/crime.txt";
+ static const std::string event_modifiers_file = "common/event_modifiers.txt";
+ static const std::string static_modifiers_file = "common/static_modifiers.txt";
+ static const std::string triggered_modifiers_file = "common/triggered_modifiers.txt";
bool ret = true;
@@ -860,6 +864,30 @@ bool Dataloader::load_defines(GameManager& game_manager) const {
Logger::error("Failed to set up modifier effects!");
ret = false;
}
+ if (!game_manager.get_modifier_manager().load_crime_modifiers(
+ parse_defines(lookup_file(crime_modifiers_file)).get_file_node()
+ )) {
+ Logger::error("Failed to load crime modifiers!");
+ ret = false;
+ }
+ if (!game_manager.get_modifier_manager().load_event_modifiers(
+ parse_defines(lookup_file(event_modifiers_file)).get_file_node()
+ )) {
+ Logger::error("Failed to load event modifiers!");
+ ret = false;
+ }
+ if (!game_manager.get_modifier_manager().load_static_modifiers(
+ parse_defines(lookup_file(static_modifiers_file)).get_file_node()
+ )) {
+ Logger::error("Failed to load static modifiers!");
+ ret = false;
+ }
+ if (!game_manager.get_modifier_manager().load_triggered_modifiers(
+ parse_defines(lookup_file(triggered_modifiers_file)).get_file_node()
+ )) {
+ Logger::error("Failed to load triggered modifiers!");
+ ret = false;
+ }
if (!game_manager.get_define_manager().load_defines_file(parse_lua_defines(lookup_file(defines_file)).get_file_node())) {
Logger::error("Failed to load defines!");
ret = false;
@@ -959,7 +987,9 @@ bool Dataloader::load_defines(GameManager& game_manager) const {
Logger::error("Failed to load wargoals!");
ret = false;
}
- if (!game_manager.get_history_manager().load_bookmark_file(parse_defines(lookup_file(bookmark_file)).get_file_node())) {
+ if (!game_manager.get_history_manager().get_bookmark_manager().load_bookmark_file(
+ parse_defines(lookup_file(bookmark_file)).get_file_node()
+ )) {
Logger::error("Failed to load bookmarks!");
ret = false;
}
diff --git a/src/openvic-simulation/dataloader/NodeTools.cpp b/src/openvic-simulation/dataloader/NodeTools.cpp
index c412f33..19f5dd7 100644
--- a/src/openvic-simulation/dataloader/NodeTools.cpp
+++ b/src/openvic-simulation/dataloader/NodeTools.cpp
@@ -206,7 +206,11 @@ node_callback_t NodeTools::expect_fvec2(callback_t<fvec2_t> callback) {
node_callback_t NodeTools::expect_assign(key_value_callback_t callback) {
return _expect_type<ast::AssignNode>([callback](ast::AssignNode const& assign_node) -> bool {
- return callback(assign_node._name, assign_node._initializer.get());
+ const bool ret = callback(assign_node._name, assign_node._initializer.get());
+ if (!ret) {
+ Logger::error("Callback failed for assign node with key: ", assign_node._name);
+ }
+ return ret;
});
}
diff --git a/src/openvic-simulation/economy/Building.cpp b/src/openvic-simulation/economy/Building.cpp
deleted file mode 100644
index bade4a5..0000000
--- a/src/openvic-simulation/economy/Building.cpp
+++ /dev/null
@@ -1,316 +0,0 @@
-#include "Building.hpp"
-
-#include "openvic-simulation/map/Province.hpp" //imported here so the hpp doesn't get circular imports
-
-using namespace OpenVic;
-using namespace OpenVic::NodeTools;
-
-Building::Building(
- std::string_view identifier, BuildingType const& type, ARGS
-) : HasIdentifier { identifier }, type { type }, modifier { std::move(modifier) }, on_completion { on_completion },
- completion_size { completion_size }, max_level { max_level }, goods_cost { std::move(goods_cost) }, cost { cost },
- build_time { build_time }, visibility { visibility }, on_map { on_map }, default_enabled { default_enabled },
- production_type { production_type }, pop_build_factory { pop_build_factory }, strategic_factory { strategic_factory },
- advanced_factory { advanced_factory }, fort_level { fort_level }, naval_capacity { naval_capacity },
- colonial_points { std::move(colonial_points) }, in_province { in_province }, one_per_state { one_per_state },
- colonial_range { colonial_range }, infrastructure { infrastructure }, spawn_railway_track { spawn_railway_track },
- sail { sail }, steam { steam }, capital { capital }, port { port } {}
-
-BuildingType const& Building::get_type() const {
- return type;
-}
-
-ModifierValue const& Building::get_modifier() const {
- return modifier;
-}
-
-std::string_view Building::get_on_completion() const {
- return on_completion;
-}
-
-fixed_point_t Building::get_completion_size() const {
- return completion_size;
-}
-
-Building::level_t Building::get_max_level() const {
- return max_level;
-}
-
-Good::good_map_t const& Building::get_goods_cost() const {
- return goods_cost;
-}
-
-fixed_point_t Building::get_cost() const {
- return cost;
-}
-
-Timespan Building::get_build_time() const {
- return build_time;
-}
-
-bool Building::has_visibility() const {
- return visibility;
-}
-
-bool Building::is_on_map() const {
- return on_map;
-}
-
-bool Building::is_default_enabled() const {
- return default_enabled;
-}
-
-ProductionType const* Building::get_production_type() const {
- return production_type;
-}
-
-bool Building::is_pop_built_factory() const {
- return pop_build_factory;
-}
-
-bool Building::is_strategic_factory() const {
- return strategic_factory;
-}
-
-bool Building::is_advanced_factory() const {
- return advanced_factory;
-}
-
-Building::level_t Building::get_fort_level() const {
- return fort_level;
-}
-
-uint64_t Building::get_naval_capacity() const {
- return naval_capacity;
-}
-
-std::vector<fixed_point_t> const& Building::get_colonial_points() const {
- return colonial_points;
-}
-
-bool Building::is_in_province() const {
- return in_province;
-}
-
-bool Building::is_one_per_state() const {
- return one_per_state;
-}
-
-fixed_point_t Building::get_colonial_range() const {
- return colonial_range;
-}
-
-fixed_point_t Building::get_infrastructure() const {
- return infrastructure;
-}
-
-bool Building::spawned_railway_track() const {
- return spawn_railway_track;
-}
-
-BuildingType::BuildingType(std::string_view new_identifier) : HasIdentifier { new_identifier } {}
-
-BuildingInstance::BuildingInstance(Building const& building)
- : HasIdentifier { building.get_identifier() }, building { building } {}
-
-Building const& BuildingInstance::get_building() const {
- return building;
-}
-
-bool BuildingInstance::_can_expand() const {
- return level < building.get_max_level();
-}
-
-BuildingInstance::level_t BuildingInstance::get_current_level() const {
- return level;
-}
-
-void BuildingInstance::set_level(BuildingInstance::level_t new_level) {
- level = new_level;
-}
-
-ExpansionState BuildingInstance::get_expansion_state() const {
- return expansion_state;
-}
-
-Date BuildingInstance::get_start_date() const {
- return start;
-}
-
-Date BuildingInstance::get_end_date() const {
- return end;
-}
-
-float BuildingInstance::get_expansion_progress() const {
- return expansion_progress;
-}
-
-bool BuildingInstance::expand() {
- if (expansion_state == ExpansionState::CanExpand) {
- expansion_state = ExpansionState::Preparing;
- expansion_progress = 0.0f;
- return true;
- }
- return false;
-}
-
-/* REQUIREMENTS:
- * MAP-71, MAP-74, MAP-77
- */
-void BuildingInstance::update_state(Date today) {
- switch (expansion_state) {
- case ExpansionState::Preparing:
- start = today;
- end = start + building.get_build_time();
- break;
- case ExpansionState::Expanding:
- expansion_progress = static_cast<double>(today - start) / static_cast<double>(end - start);
- break;
- default: expansion_state = _can_expand() ? ExpansionState::CanExpand : ExpansionState::CannotExpand;
- }
-}
-
-void BuildingInstance::tick(Date today) {
- if (expansion_state == ExpansionState::Preparing) {
- expansion_state = ExpansionState::Expanding;
- }
- if (expansion_state == ExpansionState::Expanding) {
- if (end <= today) {
- level++;
- expansion_state = ExpansionState::CannotExpand;
- }
- }
-}
-
-BuildingManager::BuildingManager() : building_types { "building types" }, buildings { "buildings" } {}
-
-bool BuildingManager::add_building_type(std::string_view identifier) {
- if (identifier.empty()) {
- Logger::error("Invalid building type identifier - empty!");
- return false;
- }
- return building_types.add_item({ identifier }, duplicate_ignore_callback);
-}
-
-bool BuildingManager::add_building(std::string_view identifier, BuildingType const* type, ARGS) {
- if (identifier.empty()) {
- Logger::error("Invalid building identifier - empty!");
- return false;
- }
- if (type == nullptr) {
- Logger::error("Invalid building type for ", identifier, ": null");
- return false;
- }
-
- return buildings.add_item({
- identifier, *type, std::move(modifier), on_completion, completion_size, max_level, std::move(goods_cost),
- cost, build_time, visibility, on_map, default_enabled, production_type, pop_build_factory, strategic_factory,
- advanced_factory, fort_level, naval_capacity, std::move(colonial_points), in_province, one_per_state,
- colonial_range, infrastructure, spawn_railway_track, sail, steam, capital, port
- });
-}
-
-bool BuildingManager::load_buildings_file(
- GoodManager const& good_manager, ProductionTypeManager const& production_type_manager, ModifierManager& modifier_manager,
- ast::NodeCPtr root
-) {
- bool ret = expect_dictionary_reserve_length(buildings, [this](std::string_view, ast::NodeCPtr value) -> bool {
- return expect_key("type", expect_identifier(
- std::bind(&BuildingManager::add_building_type, this, std::placeholders::_1)
- ))(value);
- })(root);
- lock_building_types();
-
- ret &= expect_dictionary(
- [this, &good_manager, &production_type_manager, &modifier_manager](std::string_view key, ast::NodeCPtr value) -> bool {
- BuildingType const* type = nullptr;
- ProductionType const* production_type = nullptr;
- std::string_view on_completion;
- fixed_point_t completion_size = 0, cost = 0, infrastructure = 0, colonial_range = 0;
- Building::level_t max_level = 0, fort_level = 0;
- Good::good_map_t goods_cost;
- Timespan build_time;
- bool visibility = false, on_map = false, default_enabled = false, pop_build_factory = false;
- bool strategic_factory = false, advanced_factory = false;
- bool in_province = false, one_per_state = false, spawn_railway_track = false, sail = false, steam = false;
- bool capital = false, port = false;
- uint64_t naval_capacity = 0;
- std::vector<fixed_point_t> colonial_points;
- ModifierValue modifier;
-
- bool ret = modifier_manager.expect_modifier_value_and_keys(move_variable_callback(modifier),
- "type", ONE_EXACTLY, expect_building_type_identifier(assign_variable_callback_pointer(type)),
- "on_completion", ZERO_OR_ONE, expect_identifier(assign_variable_callback(on_completion)),
- "completion_size", ZERO_OR_ONE, expect_fixed_point(assign_variable_callback(completion_size)),
- "max_level", ONE_EXACTLY, expect_uint(assign_variable_callback(max_level)),
- "goods_cost", ONE_EXACTLY, good_manager.expect_good_decimal_map(move_variable_callback(goods_cost)),
- "cost", ZERO_OR_MORE, expect_fixed_point(assign_variable_callback(cost)),
- "time", ONE_EXACTLY, expect_days(assign_variable_callback(build_time)),
- "visibility", ONE_EXACTLY, expect_bool(assign_variable_callback(visibility)),
- "onmap", ONE_EXACTLY, expect_bool(assign_variable_callback(on_map)),
- "default_enabled", ZERO_OR_ONE, expect_bool(assign_variable_callback(default_enabled)),
- "production_type", ZERO_OR_ONE, production_type_manager.expect_production_type_identifier(
- assign_variable_callback_pointer(production_type)),
- "pop_build_factory", ZERO_OR_ONE, expect_bool(assign_variable_callback(pop_build_factory)),
- "strategic_factory", ZERO_OR_ONE, expect_bool(assign_variable_callback(strategic_factory)),
- "advanced_factory", ZERO_OR_ONE, expect_bool(assign_variable_callback(advanced_factory)),
- "fort_level", ZERO_OR_ONE, expect_uint(assign_variable_callback(fort_level)),
- "naval_capacity", ZERO_OR_ONE, expect_uint(assign_variable_callback(naval_capacity)),
- "colonial_points", ZERO_OR_ONE, expect_list(expect_fixed_point(
- [&colonial_points](fixed_point_t points) -> bool {
- colonial_points.push_back(points);
- return true;
- }
- )),
- "province", ZERO_OR_ONE, expect_bool(assign_variable_callback(in_province)),
- "one_per_state", ZERO_OR_ONE, expect_bool(assign_variable_callback(one_per_state)),
- "colonial_range", ZERO_OR_ONE, expect_fixed_point(assign_variable_callback(colonial_range)),
- "infrastructure", ZERO_OR_ONE, expect_fixed_point(assign_variable_callback(infrastructure)),
- "spawn_railway_track", ZERO_OR_ONE, expect_bool(assign_variable_callback(spawn_railway_track)),
- "sail", ZERO_OR_ONE, expect_bool(assign_variable_callback(sail)),
- "steam", ZERO_OR_ONE, expect_bool(assign_variable_callback(steam)),
- "capital", ZERO_OR_ONE, expect_bool(assign_variable_callback(capital)),
- "port", ZERO_OR_ONE, expect_bool(assign_variable_callback(port))
- )(value);
-
- ret &= add_building(
- key, type, std::move(modifier), on_completion, completion_size, max_level, std::move(goods_cost), cost,
- build_time, visibility, on_map, default_enabled, production_type, pop_build_factory, strategic_factory,
- advanced_factory, fort_level, naval_capacity, std::move(colonial_points), in_province, one_per_state,
- colonial_range, infrastructure, spawn_railway_track, sail, steam, capital, port
- );
-
- return ret;
- }
- )(root);
- lock_buildings();
-
- for (Building const& building : buildings.get_items()) {
- std::string max_modifier_prefix = "max_";
- std::string min_modifier_prefix = "min_build_";
- modifier_manager.add_modifier_effect(
- max_modifier_prefix.append(building.get_identifier()), true, ModifierEffect::format_t::INT
- );
- modifier_manager.add_modifier_effect(
- min_modifier_prefix.append(building.get_identifier()), false, ModifierEffect::format_t::INT
- );
- }
-
- return ret;
-}
-
-bool BuildingManager::generate_province_buildings(Province& province) const {
- province.reset_buildings();
- if (!building_types.is_locked()) {
- Logger::error("Cannot generate buildings until building types are locked!");
- return false;
- }
- bool ret = true;
- if (!province.get_water()) {
- for (Building const& building : buildings.get_items()) {
- ret &= province.add_building({ building });
- }
- }
- province.lock_buildings();
- return ret;
-}
diff --git a/src/openvic-simulation/economy/Building.hpp b/src/openvic-simulation/economy/Building.hpp
deleted file mode 100644
index c2eb1ef..0000000
--- a/src/openvic-simulation/economy/Building.hpp
+++ /dev/null
@@ -1,171 +0,0 @@
-#pragma once
-
-#include "openvic-simulation/Modifier.hpp"
-#include "openvic-simulation/economy/Good.hpp"
-#include "openvic-simulation/economy/ProductionType.hpp"
-#include "openvic-simulation/types/Date.hpp"
-#include "openvic-simulation/types/IdentifierRegistry.hpp"
-#include "openvic-simulation/types/fixed_point/FixedPoint.hpp"
-
-#define ARGS \
- ModifierValue&& modifier, std::string_view on_completion, fixed_point_t completion_size, level_t max_level, \
- Good::good_map_t&& goods_cost, fixed_point_t cost, Timespan build_time, bool visibility, bool on_map, \
- bool default_enabled, ProductionType const* production_type, bool pop_build_factory, bool strategic_factory, \
- bool advanced_factory, level_t fort_level, uint64_t naval_capacity, std::vector<fixed_point_t>&& colonial_points, \
- bool in_province, bool one_per_state, fixed_point_t colonial_range, fixed_point_t infrastructure, \
- bool spawn_railway_track, bool sail, bool steam, bool capital, bool port
-
-namespace OpenVic {
-
- struct BuildingManager;
- struct BuildingType;
-
- /* REQUIREMENTS:
- * MAP-11, MAP-72, MAP-73
- * MAP-12, MAP-75, MAP-76
- * MAP-13, MAP-78, MAP-79
- */
- struct Building : HasIdentifier {
- friend struct BuildingManager;
-
- using level_t = int16_t;
-
- private:
- BuildingType const& type;
- const ModifierValue modifier;
- const std::string on_completion; // probably sound played on completion
- const fixed_point_t completion_size;
- const level_t max_level;
- const Good::good_map_t goods_cost;
- const fixed_point_t cost;
- const Timespan build_time; // time
- const bool visibility;
- const bool on_map; // onmap
-
- const bool default_enabled;
- ProductionType const* production_type;
- const bool pop_build_factory;
- const bool strategic_factory;
- const bool advanced_factory;
-
- const level_t fort_level; // probably the step-per-level
-
- const uint64_t naval_capacity;
- const std::vector<fixed_point_t> colonial_points;
- const bool in_province; // province
- const bool one_per_state;
- const fixed_point_t colonial_range;
-
- const fixed_point_t infrastructure;
- const bool spawn_railway_track;
-
- const bool sail; // only in clipper shipyard
- const bool steam; // only in steamer shipyard
- const bool capital; // only in naval base
- const bool port; // only in naval base
-
- Building(std::string_view identifier, BuildingType const& type, ARGS);
-
- public:
- Building(Building&&) = default;
-
- BuildingType const& get_type() const;
- ModifierValue const& get_modifier() const;
- std::string_view get_on_completion() const;
- fixed_point_t get_completion_size() const;
- level_t get_max_level() const;
- Good::good_map_t const& get_goods_cost() const;
- fixed_point_t get_cost() const;
- Timespan get_build_time() const;
- bool has_visibility() const;
- bool is_on_map() const;
-
- bool is_default_enabled() const;
- ProductionType const* get_production_type() const;
- bool is_pop_built_factory() const;
- bool is_strategic_factory() const;
- bool is_advanced_factory() const;
-
- level_t get_fort_level() const;
-
- uint64_t get_naval_capacity() const;
- std::vector<fixed_point_t> const& get_colonial_points() const;
- bool is_in_province() const;
- bool is_one_per_state() const;
- fixed_point_t get_colonial_range() const;
-
- fixed_point_t get_infrastructure() const;
- bool spawned_railway_track() const;
- };
-
- struct BuildingType : HasIdentifier {
- friend struct BuildingManager;
-
- private:
- BuildingType(std::string_view new_identifier);
-
- public:
- BuildingType(BuildingType&&) = default;
- };
-
- enum class ExpansionState { CannotExpand, CanExpand, Preparing, Expanding };
-
- struct BuildingInstance : HasIdentifier { // used in the actual game
- friend struct BuildingManager;
- using level_t = Building::level_t;
-
- private:
- Building const& building;
-
- level_t level = 0;
- ExpansionState expansion_state = ExpansionState::CannotExpand;
- Date start, end;
- float expansion_progress;
-
- bool _can_expand() const;
-
- public:
- BuildingInstance(Building const& building);
- BuildingInstance(BuildingInstance&&) = default;
-
- Building const& get_building() const;
-
- level_t get_current_level() const;
- void set_level(level_t new_level);
-
- ExpansionState get_expansion_state() const;
- Date get_start_date() const;
- Date get_end_date() const;
- float get_expansion_progress() const;
-
- bool expand();
- void update_state(Date today);
- void tick(Date today);
- };
-
- struct Province;
-
- struct BuildingManager {
- using level_t = Building::level_t; // this is getting ridiculous
-
- private:
- IdentifierRegistry<BuildingType> building_types;
- IdentifierRegistry<Building> buildings;
-
- public:
- BuildingManager();
-
- bool add_building_type(std::string_view identifier);
- IDENTIFIER_REGISTRY_ACCESSORS(building_type)
-
- bool add_building(std::string_view identifier, BuildingType const* type, ARGS);
- IDENTIFIER_REGISTRY_ACCESSORS(building)
-
- bool load_buildings_file(
- GoodManager const& good_manager, ProductionTypeManager const& production_type_manager,
- ModifierManager& modifier_manager, ast::NodeCPtr root
- );
-
- bool generate_province_buildings(Province& province) const;
- };
-}
diff --git a/src/openvic-simulation/economy/BuildingInstance.cpp b/src/openvic-simulation/economy/BuildingInstance.cpp
new file mode 100644
index 0000000..417cdda
--- /dev/null
+++ b/src/openvic-simulation/economy/BuildingInstance.cpp
@@ -0,0 +1,52 @@
+#include "BuildingInstance.hpp"
+
+using namespace OpenVic;
+
+BuildingInstance::BuildingInstance(BuildingType const& new_building_type, level_t new_level)
+ : HasIdentifier { building_type.get_identifier() }, building_type { new_building_type }, level { new_level },
+ expansion_state { ExpansionState::CannotExpand } {}
+
+bool BuildingInstance::_can_expand() const {
+ return level < building_type.get_max_level();
+}
+
+void BuildingInstance::set_level(BuildingInstance::level_t new_level) {
+ level = new_level;
+}
+
+bool BuildingInstance::expand() {
+ if (expansion_state == ExpansionState::CanExpand) {
+ expansion_state = ExpansionState::Preparing;
+ expansion_progress = 0.0f;
+ return true;
+ }
+ return false;
+}
+
+/* REQUIREMENTS:
+ * MAP-71, MAP-74, MAP-77
+ */
+void BuildingInstance::update_state(Date today) {
+ switch (expansion_state) {
+ case ExpansionState::Preparing:
+ start_date = today;
+ end_date = start_date + building_type.get_build_time();
+ break;
+ case ExpansionState::Expanding:
+ expansion_progress = static_cast<double>(today - start_date) / static_cast<double>(end_date - start_date);
+ break;
+ default: expansion_state = _can_expand() ? ExpansionState::CanExpand : ExpansionState::CannotExpand;
+ }
+}
+
+void BuildingInstance::tick(Date today) {
+ if (expansion_state == ExpansionState::Preparing) {
+ expansion_state = ExpansionState::Expanding;
+ }
+ if (expansion_state == ExpansionState::Expanding) {
+ if (end_date <= today) {
+ level++;
+ expansion_state = ExpansionState::CannotExpand;
+ }
+ }
+}
diff --git a/src/openvic-simulation/economy/BuildingInstance.hpp b/src/openvic-simulation/economy/BuildingInstance.hpp
new file mode 100644
index 0000000..9fc9df1
--- /dev/null
+++ b/src/openvic-simulation/economy/BuildingInstance.hpp
@@ -0,0 +1,33 @@
+#pragma once
+
+#include "openvic-simulation/economy/BuildingType.hpp"
+
+namespace OpenVic {
+
+ struct BuildingInstance : HasIdentifier { // used in the actual game
+ using level_t = BuildingType::level_t;
+
+ enum class ExpansionState { CannotExpand, CanExpand, Preparing, Expanding };
+
+ private:
+ BuildingType const& PROPERTY(building_type);
+
+ level_t PROPERTY(level);
+ ExpansionState PROPERTY(expansion_state);
+ Date PROPERTY(start_date)
+ Date PROPERTY(end_date);
+ float PROPERTY(expansion_progress);
+
+ bool _can_expand() const;
+
+ public:
+ BuildingInstance(BuildingType const& new_building_type, level_t new_level = 0);
+ BuildingInstance(BuildingInstance&&) = default;
+
+ void set_level(level_t new_level);
+
+ bool expand();
+ void update_state(Date today);
+ void tick(Date today);
+ };
+}
diff --git a/src/openvic-simulation/economy/BuildingType.cpp b/src/openvic-simulation/economy/BuildingType.cpp
new file mode 100644
index 0000000..b80999a
--- /dev/null
+++ b/src/openvic-simulation/economy/BuildingType.cpp
@@ -0,0 +1,114 @@
+#include "BuildingType.hpp"
+
+using namespace OpenVic;
+using namespace OpenVic::NodeTools;
+
+BuildingType::BuildingType(
+ std::string_view identifier, ARGS
+) : HasIdentifier { identifier }, type { type }, modifier { std::move(modifier) }, on_completion { on_completion },
+ completion_size { completion_size }, max_level { max_level }, goods_cost { std::move(goods_cost) }, cost { cost },
+ build_time { build_time }, visibility { visibility }, on_map { on_map }, default_enabled { default_enabled },
+ production_type { production_type }, pop_build_factory { pop_build_factory }, strategic_factory { strategic_factory },
+ advanced_factory { advanced_factory }, fort_level { fort_level }, naval_capacity { naval_capacity },
+ colonial_points { std::move(colonial_points) }, in_province { in_province }, one_per_state { one_per_state },
+ colonial_range { colonial_range }, infrastructure { infrastructure }, spawn_railway_track { spawn_railway_track },
+ sail { sail }, steam { steam }, capital { capital }, port { port } {}
+
+BuildingManager::BuildingManager() : building_types { "building types" } {}
+
+bool BuildingManager::add_building_type(std::string_view identifier, ARGS) {
+ if (identifier.empty()) {
+ Logger::error("Invalid building identifier - empty!");
+ return false;
+ }
+
+ return building_types.add_item({
+ identifier, type, std::move(modifier), on_completion, completion_size, max_level, std::move(goods_cost),
+ cost, build_time, visibility, on_map, default_enabled, production_type, pop_build_factory, strategic_factory,
+ advanced_factory, fort_level, naval_capacity, std::move(colonial_points), in_province, one_per_state,
+ colonial_range, infrastructure, spawn_railway_track, sail, steam, capital, port
+ });
+}
+
+bool BuildingManager::load_buildings_file(
+ GoodManager const& good_manager, ProductionTypeManager const& production_type_manager, ModifierManager& modifier_manager,
+ ast::NodeCPtr root
+) {
+ const bool ret = expect_dictionary_reserve_length(
+ building_types,
+ [this, &good_manager, &production_type_manager, &modifier_manager](std::string_view key, ast::NodeCPtr value) -> bool {
+ std::string_view type;
+ ProductionType const* production_type = nullptr;
+ std::string_view on_completion;
+ fixed_point_t completion_size = 0, cost = 0, infrastructure = 0, colonial_range = 0;
+ BuildingType::level_t max_level = 0, fort_level = 0;
+ Good::good_map_t goods_cost;
+ Timespan build_time;
+ bool visibility = false, on_map = false, default_enabled = false, pop_build_factory = false;
+ bool strategic_factory = false, advanced_factory = false;
+ bool in_province = false, one_per_state = false, spawn_railway_track = false, sail = false, steam = false;
+ bool capital = false, port = false;
+ uint64_t naval_capacity = 0;
+ std::vector<fixed_point_t> colonial_points;
+ ModifierValue modifier;
+
+ bool ret = modifier_manager.expect_modifier_value_and_keys(move_variable_callback(modifier),
+ "type", ONE_EXACTLY, expect_identifier(assign_variable_callback(type)),
+ "on_completion", ZERO_OR_ONE, expect_identifier(assign_variable_callback(on_completion)),
+ "completion_size", ZERO_OR_ONE, expect_fixed_point(assign_variable_callback(completion_size)),
+ "max_level", ONE_EXACTLY, expect_uint(assign_variable_callback(max_level)),
+ "goods_cost", ONE_EXACTLY, good_manager.expect_good_decimal_map(move_variable_callback(goods_cost)),
+ "cost", ZERO_OR_MORE, expect_fixed_point(assign_variable_callback(cost)),
+ "time", ONE_EXACTLY, expect_days(assign_variable_callback(build_time)),
+ "visibility", ONE_EXACTLY, expect_bool(assign_variable_callback(visibility)),
+ "onmap", ONE_EXACTLY, expect_bool(assign_variable_callback(on_map)),
+ "default_enabled", ZERO_OR_ONE, expect_bool(assign_variable_callback(default_enabled)),
+ "production_type", ZERO_OR_ONE, production_type_manager.expect_production_type_identifier(
+ assign_variable_callback_pointer(production_type)),
+ "pop_build_factory", ZERO_OR_ONE, expect_bool(assign_variable_callback(pop_build_factory)),
+ "strategic_factory", ZERO_OR_ONE, expect_bool(assign_variable_callback(strategic_factory)),
+ "advanced_factory", ZERO_OR_ONE, expect_bool(assign_variable_callback(advanced_factory)),
+ "fort_level", ZERO_OR_ONE, expect_uint(assign_variable_callback(fort_level)),
+ "naval_capacity", ZERO_OR_ONE, expect_uint(assign_variable_callback(naval_capacity)),
+ "colonial_points", ZERO_OR_ONE, expect_list(expect_fixed_point(
+ [&colonial_points](fixed_point_t points) -> bool {
+ colonial_points.push_back(points);
+ return true;
+ }
+ )),
+ "province", ZERO_OR_ONE, expect_bool(assign_variable_callback(in_province)),
+ "one_per_state", ZERO_OR_ONE, expect_bool(assign_variable_callback(one_per_state)),
+ "colonial_range", ZERO_OR_ONE, expect_fixed_point(assign_variable_callback(colonial_range)),
+ "infrastructure", ZERO_OR_ONE, expect_fixed_point(assign_variable_callback(infrastructure)),
+ "spawn_railway_track", ZERO_OR_ONE, expect_bool(assign_variable_callback(spawn_railway_track)),
+ "sail", ZERO_OR_ONE, expect_bool(assign_variable_callback(sail)),
+ "steam", ZERO_OR_ONE, expect_bool(assign_variable_callback(steam)),
+ "capital", ZERO_OR_ONE, expect_bool(assign_variable_callback(capital)),
+ "port", ZERO_OR_ONE, expect_bool(assign_variable_callback(port))
+ )(value);
+
+ ret &= add_building_type(
+ key, type, std::move(modifier), on_completion, completion_size, max_level, std::move(goods_cost), cost,
+ build_time, visibility, on_map, default_enabled, production_type, pop_build_factory, strategic_factory,
+ advanced_factory, fort_level, naval_capacity, std::move(colonial_points), in_province, one_per_state,
+ colonial_range, infrastructure, spawn_railway_track, sail, steam, capital, port
+ );
+
+ return ret;
+ }
+ )(root);
+ lock_building_types();
+
+ for (BuildingType const& building_type : building_types.get_items()) {
+ std::string max_modifier_prefix = "max_";
+ std::string min_modifier_prefix = "min_build_";
+ modifier_manager.add_modifier_effect(
+ max_modifier_prefix.append(building_type.get_identifier()), true, ModifierEffect::format_t::INT
+ );
+ modifier_manager.add_modifier_effect(
+ min_modifier_prefix.append(building_type.get_identifier()), false, ModifierEffect::format_t::INT
+ );
+ }
+
+ return ret;
+}
diff --git a/src/openvic-simulation/economy/BuildingType.hpp b/src/openvic-simulation/economy/BuildingType.hpp
new file mode 100644
index 0000000..a49c461
--- /dev/null
+++ b/src/openvic-simulation/economy/BuildingType.hpp
@@ -0,0 +1,89 @@
+#pragma once
+
+#include "openvic-simulation/misc/Modifier.hpp"
+#include "openvic-simulation/economy/Good.hpp"
+#include "openvic-simulation/economy/ProductionType.hpp"
+#include "openvic-simulation/types/Date.hpp"
+#include "openvic-simulation/types/IdentifierRegistry.hpp"
+#include "openvic-simulation/types/fixed_point/FixedPoint.hpp"
+
+#define ARGS \
+ std::string_view type, ModifierValue&& modifier, std::string_view on_completion, fixed_point_t completion_size, \
+ level_t max_level, Good::good_map_t&& goods_cost, fixed_point_t cost, Timespan build_time, bool visibility, bool on_map, \
+ bool default_enabled, ProductionType const* production_type, bool pop_build_factory, bool strategic_factory, \
+ bool advanced_factory, level_t fort_level, uint64_t naval_capacity, std::vector<fixed_point_t>&& colonial_points, \
+ bool in_province, bool one_per_state, fixed_point_t colonial_range, fixed_point_t infrastructure, \
+ bool spawn_railway_track, bool sail, bool steam, bool capital, bool port
+
+namespace OpenVic {
+
+ struct BuildingManager;
+
+ /* REQUIREMENTS:
+ * MAP-11, MAP-72, MAP-73
+ * MAP-12, MAP-75, MAP-76
+ * MAP-13, MAP-78, MAP-79
+ */
+ struct BuildingType : HasIdentifier {
+ friend struct BuildingManager;
+
+ using level_t = int16_t;
+
+ private:
+ std::string PROPERTY(type);
+ ModifierValue PROPERTY(modifier);
+ std::string PROPERTY(on_completion); // probably sound played on completion
+ fixed_point_t PROPERTY(completion_size);
+ level_t PROPERTY(max_level);
+ Good::good_map_t PROPERTY(goods_cost);
+ fixed_point_t PROPERTY(cost);
+ Timespan PROPERTY(build_time); // time
+ bool PROPERTY(visibility);
+ bool PROPERTY(on_map); // onmap
+
+ bool PROPERTY(default_enabled);
+ ProductionType const* PROPERTY(production_type);
+ bool PROPERTY(pop_build_factory);
+ bool PROPERTY(strategic_factory);
+ bool PROPERTY(advanced_factory);
+
+ level_t PROPERTY(fort_level); // probably the step-per-level
+
+ uint64_t PROPERTY(naval_capacity);
+ std::vector<fixed_point_t> PROPERTY(colonial_points);
+ bool PROPERTY(in_province); // province
+ bool PROPERTY(one_per_state);
+ fixed_point_t PROPERTY(colonial_range);
+
+ fixed_point_t PROPERTY(infrastructure);
+ bool PROPERTY(spawn_railway_track);
+
+ bool PROPERTY(sail); // only in clipper shipyard
+ bool PROPERTY(steam); // only in steamer shipyard
+ bool PROPERTY(capital); // only in naval base
+ bool PROPERTY(port); // only in naval base
+
+ BuildingType(std::string_view identifier, ARGS);
+
+ public:
+ BuildingType(BuildingType&&) = default;
+ };
+
+ struct BuildingManager {
+ using level_t = BuildingType::level_t; // this is getting ridiculous
+
+ private:
+ IdentifierRegistry<BuildingType> building_types;
+
+ public:
+ BuildingManager();
+
+ bool add_building_type(std::string_view identifier, ARGS);
+ IDENTIFIER_REGISTRY_ACCESSORS(building_type)
+
+ bool load_buildings_file(
+ GoodManager const& good_manager, ProductionTypeManager const& production_type_manager,
+ ModifierManager& modifier_manager, ast::NodeCPtr root
+ );
+ };
+}
diff --git a/src/openvic-simulation/economy/EconomyManager.hpp b/src/openvic-simulation/economy/EconomyManager.hpp
index 7445614..d53aa7e 100644
--- a/src/openvic-simulation/economy/EconomyManager.hpp
+++ b/src/openvic-simulation/economy/EconomyManager.hpp
@@ -1,6 +1,6 @@
#pragma once
-#include "openvic-simulation/economy/Building.hpp"
+#include "openvic-simulation/economy/BuildingType.hpp"
#include "openvic-simulation/economy/Good.hpp"
#include "openvic-simulation/economy/ProductionType.hpp"
diff --git a/src/openvic-simulation/economy/Good.cpp b/src/openvic-simulation/economy/Good.cpp
index 2b1d694..4c1f7ba 100644
--- a/src/openvic-simulation/economy/Good.cpp
+++ b/src/openvic-simulation/economy/Good.cpp
@@ -64,7 +64,7 @@ bool GoodManager::add_good_category(std::string_view identifier) {
}
bool GoodManager::add_good(
- std::string_view identifier, colour_t colour, GoodCategory const* category, Good::price_t base_price,
+ std::string_view identifier, colour_t colour, GoodCategory const& category, Good::price_t base_price,
bool available_from_start, bool tradeable, bool money, bool overseas_penalty
) {
if (identifier.empty()) {
@@ -75,16 +75,12 @@ bool GoodManager::add_good(
Logger::error("Invalid good colour for ", identifier, ": ", colour_to_hex_string(colour));
return false;
}
- if (category == nullptr) {
- Logger::error("Invalid good category for ", identifier, ": null");
- return false;
- }
if (base_price <= Good::NULL_PRICE) {
Logger::error("Invalid base price for ", identifier, ": ", base_price);
return false;
}
return goods.add_item({
- identifier, colour, *category, base_price, available_from_start,
+ identifier, colour, category, base_price, available_from_start,
tradeable, money, overseas_penalty
});
}
@@ -107,10 +103,8 @@ bool GoodManager::load_goods_file(ast::NodeCPtr root) {
)(root);
lock_good_categories();
goods.reserve(goods.size() + total_expected_goods);
- ret &= expect_dictionary([this](std::string_view good_category_key, ast::NodeCPtr good_category_value) -> bool {
- GoodCategory const* good_category = get_good_category_by_identifier(good_category_key);
-
- return expect_dictionary([this, good_category](std::string_view key, ast::NodeCPtr value) -> bool {
+ ret &= expect_good_category_dictionary([this](GoodCategory const& good_category, ast::NodeCPtr good_category_value) -> bool {
+ return expect_dictionary([this, &good_category](std::string_view key, ast::NodeCPtr value) -> bool {
colour_t colour = NULL_COLOUR;
Good::price_t base_price;
bool available_from_start = true, tradeable = true;
diff --git a/src/openvic-simulation/economy/Good.hpp b/src/openvic-simulation/economy/Good.hpp
index ae2d6a9..805e6a5 100644
--- a/src/openvic-simulation/economy/Good.hpp
+++ b/src/openvic-simulation/economy/Good.hpp
@@ -33,7 +33,7 @@ namespace OpenVic {
using price_t = fixed_point_t;
static constexpr price_t NULL_PRICE = fixed_point_t::_0();
- using good_map_t = decimal_map_t<Good const*>;
+ using good_map_t = fixed_point_map_t<Good const*>;
private:
GoodCategory const& category;
@@ -73,7 +73,7 @@ namespace OpenVic {
IDENTIFIER_REGISTRY_ACCESSORS_CUSTOM_PLURAL(good_category, good_categories)
bool add_good(
- std::string_view identifier, colour_t colour, GoodCategory const* category, Good::price_t base_price,
+ std::string_view identifier, colour_t colour, GoodCategory const& category, Good::price_t base_price,
bool available_from_start, bool tradeable, bool money, bool overseas_penalty
);
IDENTIFIER_REGISTRY_ACCESSORS(good)
diff --git a/src/openvic-simulation/economy/ProductionType.cpp b/src/openvic-simulation/economy/ProductionType.cpp
index 1c65c4d..6eb7ff9 100644
--- a/src/openvic-simulation/economy/ProductionType.cpp
+++ b/src/openvic-simulation/economy/ProductionType.cpp
@@ -145,7 +145,7 @@ node_callback_t ProductionTypeManager::_expect_employed_pop_list(
return false; \
}
-bool ProductionTypeManager::add_production_type(PRODUCTION_TYPE_ARGS, GoodManager const& good_manager) {
+bool ProductionTypeManager::add_production_type(PRODUCTION_TYPE_ARGS) {
if (identifier.empty()) {
Logger::error("Invalid production type identifier - empty!");
return false;
@@ -274,7 +274,7 @@ bool ProductionTypeManager::load_production_types_file(
ret &= add_production_type(
key, owner, employees, type, workforce, std::move(input_goods), output_goods, value, std::move(bonuses),
- std::move(efficiency), coastal, farm, mine, good_manager
+ std::move(efficiency), coastal, farm, mine
);
return ret;
}
diff --git a/src/openvic-simulation/economy/ProductionType.hpp b/src/openvic-simulation/economy/ProductionType.hpp
index 802580b..13862a7 100644
--- a/src/openvic-simulation/economy/ProductionType.hpp
+++ b/src/openvic-simulation/economy/ProductionType.hpp
@@ -101,7 +101,7 @@ namespace OpenVic {
public:
ProductionTypeManager();
- bool add_production_type(PRODUCTION_TYPE_ARGS, GoodManager const& good_manager);
+ bool add_production_type(PRODUCTION_TYPE_ARGS);
IDENTIFIER_REGISTRY_ACCESSORS(production_type)
bool load_production_types_file(GoodManager const& good_manager, PopManager const& pop_manager, ast::NodeCPtr root);
diff --git a/src/openvic-simulation/history/CountryHistory.hpp b/src/openvic-simulation/history/CountryHistory.hpp
index ffb44c0..ed200bf 100644
--- a/src/openvic-simulation/history/CountryHistory.hpp
+++ b/src/openvic-simulation/history/CountryHistory.hpp
@@ -31,7 +31,7 @@ namespace OpenVic {
std::optional<Religion const*> PROPERTY(religion);
std::optional<CountryParty const*> PROPERTY(ruling_party);
std::optional<Date> PROPERTY(last_election);
- decimal_map_t<Ideology const*> PROPERTY(upper_house);
+ fixed_point_map_t<Ideology const*> PROPERTY(upper_house);
std::optional<Province const*> PROPERTY(capital);
std::optional<GovernmentType const*> PROPERTY(government_type);
std::optional<fixed_point_t> PROPERTY(plurality);
diff --git a/src/openvic-simulation/history/HistoryManager.hpp b/src/openvic-simulation/history/HistoryManager.hpp
index ec6d1c5..a7fc668 100644
--- a/src/openvic-simulation/history/HistoryManager.hpp
+++ b/src/openvic-simulation/history/HistoryManager.hpp
@@ -19,9 +19,5 @@ namespace OpenVic {
REF_GETTERS(country_manager)
REF_GETTERS(province_manager)
REF_GETTERS(diplomacy_manager)
-
- inline bool load_bookmark_file(ast::NodeCPtr root) {
- return bookmark_manager.load_bookmark_file(root);
- }
};
}
diff --git a/src/openvic-simulation/history/HistoryMap.hpp b/src/openvic-simulation/history/HistoryMap.hpp
index 64d886d..07f54f0 100644
--- a/src/openvic-simulation/history/HistoryMap.hpp
+++ b/src/openvic-simulation/history/HistoryMap.hpp
@@ -30,6 +30,11 @@ namespace OpenVic {
std::map<Date, std::unique_ptr<entry_type>> PROPERTY(entries);
bool _try_load_history_entry(GameManager const& game_manager, Args... args, Date date, ast::NodeCPtr root) {
+ const Date end_date = _get_end_date(game_manager);
+ if (date > end_date) {
+ Logger::error("History entry ", date, " defined after end date ", end_date);
+ return false;
+ }
typename decltype(entries)::iterator it = entries.find(date);
if (it == entries.end()) {
const std::pair<typename decltype(entries)::iterator, bool> result = entries.emplace(date, _make_entry(date));
@@ -64,14 +69,12 @@ namespace OpenVic {
bool is_date = false;
const Date sub_date { Date::from_string(key, &is_date, true) };
if (is_date) {
- if (sub_date <= date) {
+ if (sub_date < date) {
Logger::error("History entry ", sub_date, " defined before parent entry date ", date);
return false;
}
- const Date end_date = _get_end_date(game_manager);
- if (sub_date > end_date) {
- Logger::error("History entry ", sub_date, " defined after end date ", end_date);
- return false;
+ if (sub_date == date) {
+ Logger::warning("History entry ", sub_date, " defined with same date as parent entry");
}
if (_try_load_history_entry(game_manager, args..., sub_date, value)) {
return true;
@@ -94,7 +97,7 @@ namespace OpenVic {
return nullptr;
}
/* Returns history entries up to date as an ordered list of entries. */
- std::vector<entry_type const*> get_entries(Date end) const {
+ std::vector<entry_type const*> get_entries_up_to(Date end) const {
std::vector<entry_type const*> ret;
for (typename decltype(entries)::value_type const& entry : entries) {
if (entry.first <= end) {
diff --git a/src/openvic-simulation/history/ProvinceHistory.cpp b/src/openvic-simulation/history/ProvinceHistory.cpp
index 141d256..991dfee 100644
--- a/src/openvic-simulation/history/ProvinceHistory.cpp
+++ b/src/openvic-simulation/history/ProvinceHistory.cpp
@@ -33,10 +33,10 @@ bool ProvinceHistoryMap::_load_history_entry(
[this, &game_manager, &building_manager, &entry](
std::string_view key, ast::NodeCPtr value) -> bool {
// used for province buildings like forts or railroads
- Building const* building = building_manager.get_building_by_identifier(key);
- if (building != nullptr) {
- return expect_uint<Building::level_t>([&entry, building](Building::level_t level) -> bool {
- entry.buildings[building] = level;
+ BuildingType const* building_type = building_manager.get_building_type_by_identifier(key);
+ if (building_type != nullptr) {
+ return expect_uint<BuildingType::level_t>([&entry, building_type](BuildingType::level_t level) -> bool {
+ entry.province_buildings[building_type] = level;
return true;
})(value);
}
@@ -83,17 +83,17 @@ bool ProvinceHistoryMap::_load_history_entry(
return ret;
},
"state_building", ZERO_OR_MORE, [&building_manager, &entry](ast::NodeCPtr node) -> bool {
- Building const* building = nullptr;
+ BuildingType const* building_type = nullptr;
uint8_t level = 0;
const bool ret = expect_dictionary_keys(
"level", ONE_EXACTLY, expect_uint(assign_variable_callback(level)),
- "building", ONE_EXACTLY, building_manager.expect_building_identifier(
- assign_variable_callback_pointer(building)
+ "building", ONE_EXACTLY, building_manager.expect_building_type_identifier(
+ assign_variable_callback_pointer(building_type)
),
"upgrade", ZERO_OR_ONE, success_callback // doesn't appear to have an effect
)(node);
- entry.buildings[building] = level;
+ entry.state_buildings[building_type] = level;
return ret;
}
)(root);
diff --git a/src/openvic-simulation/history/ProvinceHistory.hpp b/src/openvic-simulation/history/ProvinceHistory.hpp
index 5a18723..e4adc08 100644
--- a/src/openvic-simulation/history/ProvinceHistory.hpp
+++ b/src/openvic-simulation/history/ProvinceHistory.hpp
@@ -5,7 +5,7 @@
#include <vector>
#include "openvic-simulation/country/Country.hpp"
-#include "openvic-simulation/economy/Building.hpp"
+#include "openvic-simulation/economy/BuildingType.hpp"
#include "openvic-simulation/economy/Good.hpp"
#include "openvic-simulation/history/Bookmark.hpp"
#include "openvic-simulation/history/HistoryMap.hpp"
@@ -18,8 +18,6 @@ namespace OpenVic {
struct ProvinceHistoryEntry : HistoryEntry {
friend struct ProvinceHistoryMap;
- using building_level_map_t = std::map<Building const*, Building::level_t>;
-
private:
Province const& PROPERTY(province);
@@ -32,8 +30,9 @@ namespace OpenVic {
std::optional<Good const*> PROPERTY(rgo);
std::optional<Province::life_rating_t> PROPERTY(life_rating);
std::optional<TerrainType const*> PROPERTY(terrain_type);
- building_level_map_t PROPERTY(buildings);
- decimal_map_t<Ideology const*> PROPERTY(party_loyalties);
+ std::map<BuildingType const*, BuildingType::level_t> PROPERTY(province_buildings);
+ std::map<BuildingType const*, BuildingType::level_t> PROPERTY(state_buildings);
+ fixed_point_map_t<Ideology const*> PROPERTY(party_loyalties);
ProvinceHistoryEntry(Province const& new_province, Date new_date);
};
diff --git a/src/openvic-simulation/interface/GUI.cpp b/src/openvic-simulation/interface/GUI.cpp
index aeec136..61b8683 100644
--- a/src/openvic-simulation/interface/GUI.cpp
+++ b/src/openvic-simulation/interface/GUI.cpp
@@ -17,7 +17,7 @@ bool Element::_fill_key_map(NodeTools::key_map_t& key_map, UIManager const& ui_m
{ "CENTER", CENTER }
};
ret &= add_key_map_entries(key_map,
- "position", ONE_EXACTLY, expect_ivec2(assign_variable_callback(position)),
+ "position", ONE_EXACTLY, expect_fvec2(assign_variable_callback(position)),
"orientation", ZERO_OR_ONE, expect_string(expect_mapped_string(orientation_map, assign_variable_callback(orientation))),
"Orientation", ZERO_OR_ONE, expect_string(expect_mapped_string(orientation_map, assign_variable_callback(orientation)))
);
@@ -68,7 +68,7 @@ bool Window::_fill_key_map(NodeTools::key_map_t& key_map, UIManager const& ui_ma
ret &= Element::_fill_key_map(key_map, ui_manager);
ret &= add_key_map_entries(key_map,
"backGround", ZERO_OR_ONE, success_callback, // TODO - load as potential panel texture (almost always empty)
- "size", ONE_EXACTLY, expect_ivec2(assign_variable_callback(size)),
+ "size", ONE_EXACTLY, expect_fvec2(assign_variable_callback(size)),
"moveable", ONE_EXACTLY, expect_int_bool(assign_variable_callback(moveable)),
"dontRender", ZERO_OR_ONE, success_callback, // always empty string?
"horizontalBorder", ZERO_OR_ONE, success_callback,
@@ -144,8 +144,8 @@ bool Text::_fill_key_map(NodeTools::key_map_t& key_map, UIManager const& ui_mana
ret &= add_key_map_entries(key_map,
"text", ZERO_OR_ONE, expect_string(assign_variable_callback_string(text), true),
"font", ONE_EXACTLY, expect_string(ui_manager.expect_font_str(assign_variable_callback_pointer(font))),
- "maxWidth", ONE_EXACTLY, expect_uint(assign_variable_callback(max_size.x)),
- "maxHeight", ONE_EXACTLY, expect_uint(assign_variable_callback(max_size.y)),
+ "maxWidth", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(max_size.x)),
+ "maxHeight", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(max_size.y)),
"borderSize", ZERO_OR_ONE, success_callback,
"fixedsize", ZERO_OR_ONE, success_callback,
@@ -161,7 +161,7 @@ OverlappingElementsBox::OverlappingElementsBox() : size {} {}
bool OverlappingElementsBox::_fill_key_map(NodeTools::key_map_t& key_map, UIManager const& ui_manager) {
bool ret = AlignedElement::_fill_key_map(key_map, ui_manager);
ret &= add_key_map_entries(key_map,
- "size", ONE_EXACTLY, expect_ivec2(assign_variable_callback(size)),
+ "size", ONE_EXACTLY, expect_fvec2(assign_variable_callback(size)),
"spacing", ONE_EXACTLY, success_callback
);
return ret;
@@ -173,7 +173,7 @@ bool ListBox::_fill_key_map(NodeTools::key_map_t& key_map, UIManager const& ui_m
bool ret = Element::_fill_key_map(key_map, ui_manager);
ret &= add_key_map_entries(key_map,
"backGround", ZERO_OR_ONE, success_callback,
- "size", ONE_EXACTLY, expect_ivec2(assign_variable_callback(size)),
+ "size", ONE_EXACTLY, expect_fvec2(assign_variable_callback(size)),
"spacing", ZERO_OR_ONE, success_callback,
"scrollbartype", ZERO_OR_ONE, success_callback, // TODO - implement modable listbox scrollbars
"borderSize", ZERO_OR_ONE, success_callback
diff --git a/src/openvic-simulation/interface/GUI.hpp b/src/openvic-simulation/interface/GUI.hpp
index 1a76ca0..f8434f6 100644
--- a/src/openvic-simulation/interface/GUI.hpp
+++ b/src/openvic-simulation/interface/GUI.hpp
@@ -17,7 +17,7 @@ namespace OpenVic::GUI {
};
private:
- ivec2_t PROPERTY(position);
+ fvec2_t PROPERTY(position);
orientation_t PROPERTY(orientation);
protected:
@@ -65,7 +65,7 @@ namespace OpenVic::GUI {
NamedInstanceRegistry<Element, UIManager const&> elements;
- ivec2_t PROPERTY(size);
+ fvec2_t PROPERTY(size);
bool PROPERTY(moveable);
bool PROPERTY(fullscreen);
// TODO - background, dontRender, horizontalBorder, verticalBorder
@@ -179,7 +179,7 @@ namespace OpenVic::GUI {
std::string PROPERTY(text);
GFX::Font const* PROPERTY(font);
- ivec2_t PROPERTY(max_size); // maxWidth, maxHeight
+ fvec2_t PROPERTY(max_size); // maxWidth, maxHeight
// TODO - borderSize, fixedsize, textureFile
@@ -198,7 +198,7 @@ namespace OpenVic::GUI {
class OverlappingElementsBox final : public AlignedElement {
friend std::unique_ptr<OverlappingElementsBox> std::make_unique<OverlappingElementsBox>();
- ivec2_t PROPERTY(size);
+ fvec2_t PROPERTY(size);
// TODO - spacing
@@ -217,7 +217,7 @@ namespace OpenVic::GUI {
class ListBox final : public Element {
friend std::unique_ptr<ListBox> std::make_unique<ListBox>();
- ivec2_t PROPERTY(size);
+ fvec2_t PROPERTY(size);
// TODO - backGround, spacing, scrollbartype, borderSize
diff --git a/src/openvic-simulation/map/Map.cpp b/src/openvic-simulation/map/Map.cpp
index 7e2213e..6df7537 100644
--- a/src/openvic-simulation/map/Map.cpp
+++ b/src/openvic-simulation/map/Map.cpp
@@ -4,6 +4,7 @@
#include <unordered_set>
#include "openvic-simulation/economy/Good.hpp"
+#include "openvic-simulation/history/ProvinceHistory.hpp"
#include "openvic-simulation/utility/BMP.hpp"
#include "openvic-simulation/utility/Logger.hpp"
@@ -24,7 +25,7 @@ Mapmode::index_t Mapmode::get_index() const {
return index;
}
-colour_t Mapmode::get_colour(Map const& map, Province const& province) const {
+Mapmode::base_stripe_t Mapmode::get_base_stripe_colours(Map const& map, Province const& province) const {
return colour_func ? colour_func(map, province) : NULL_COLOUR;
}
@@ -254,15 +255,23 @@ bool Map::generate_mapmode_colours(Mapmode::index_t index, uint8_t* target) cons
mapmode = &Mapmode::ERROR_MAPMODE;
}
// Skip past Province::NULL_INDEX
- for (size_t i = 0; i < MAPMODE_COLOUR_SIZE; ++i) {
+ for (size_t i = 0; i < sizeof(Mapmode::base_stripe_t); ++i) {
*target++ = 0;
}
for (Province const& province : provinces.get_items()) {
- const colour_t colour = mapmode->get_colour(*this, province);
- *target++ = (colour >> 16) & FULL_COLOUR;
- *target++ = (colour >> 8) & FULL_COLOUR;
- *target++ = colour & FULL_COLOUR;
- *target++ = (colour >> 24) & FULL_COLOUR;
+ const Mapmode::base_stripe_t base_stripe = mapmode->get_base_stripe_colours(*this, province);
+ const colour_t base_colour = static_cast<colour_t>(base_stripe);
+ const colour_t stripe_colour = static_cast<colour_t>(base_stripe >> (sizeof(colour_t) * 8));
+
+ *target++ = (base_colour >> 16) & COLOUR_COMPONENT; // red
+ *target++ = (base_colour >> 8) & COLOUR_COMPONENT; // green
+ *target++ = (base_colour >> 0) & COLOUR_COMPONENT; // blue
+ *target++ = (base_colour >> 24) & COLOUR_COMPONENT; // alpha
+
+ *target++ = (stripe_colour >> 16) & COLOUR_COMPONENT; // red
+ *target++ = (stripe_colour >> 8) & COLOUR_COMPONENT; // green
+ *target++ = (stripe_colour >> 0) & COLOUR_COMPONENT; // blue
+ *target++ = (stripe_colour >> 24) & COLOUR_COMPONENT; // alpha
}
return ret;
}
@@ -289,11 +298,25 @@ Pop::pop_size_t Map::get_total_map_population() const {
return total_map_population;
}
-bool Map::setup(BuildingManager const& building_manager, PopManager const& pop_manager) {
+bool Map::reset(BuildingManager const& building_manager) {
+ bool ret = true;
+ for (Province& province : provinces.get_items()) {
+ ret &= province.reset(building_manager);
+ }
+ return ret;
+}
+
+bool Map::apply_history_to_provinces(ProvinceHistoryManager const& history_manager, Date date) {
bool ret = true;
for (Province& province : provinces.get_items()) {
- province.clear_pops();
- ret &= building_manager.generate_province_buildings(province);
+ if (!province.get_water()) {
+ ProvinceHistoryMap const* history_map = history_manager.get_province_history(&province);
+ if (history_map != nullptr) {
+ for (ProvinceHistoryEntry const* entry : history_map->get_entries_up_to(date)) {
+ province.apply_history_to_province(entry);
+ }
+ }
+ }
}
return ret;
}
@@ -489,7 +512,7 @@ bool Map::load_map_images(fs::path const& province_path, fs::path const& terrain
uint8_t const* terrain_data = terrain_bmp.get_pixel_data().data();
std::vector<bool> province_checklist(provinces.size());
- std::vector<decimal_map_t<TerrainType const*>> terrain_type_pixels_list(provinces.size());
+ std::vector<fixed_point_map_t<TerrainType const*>> terrain_type_pixels_list(provinces.size());
bool ret = true;
std::unordered_set<colour_t> unrecognised_province_colours;
@@ -553,9 +576,8 @@ bool Map::load_map_images(fs::path const& province_path, fs::path const& terrain
size_t missing = 0;
for (size_t idx = 0; idx < province_checklist.size(); ++idx) {
Province* province = provinces.get_item_by_index(idx);
- province->_set_terrain_type(
- reinterpret_cast<TerrainType const*>(get_largest_item(terrain_type_pixels_list[idx]).first)
- );
+ const fixed_point_map_const_iterator_t<TerrainType const*> largest = get_largest_item(terrain_type_pixels_list[idx]);
+ province->default_terrain_type = largest != terrain_type_pixels_list[idx].end() ? largest->first : nullptr;
province->on_map = province_checklist[idx];
if (!province->on_map) {
if (detailed_errors) {
@@ -602,6 +624,6 @@ bool Map::_generate_province_adjacencies() {
bool Map::generate_and_load_province_adjacencies(std::vector<ovdl::csv::LineObject> const& additional_adjacencies) {
bool ret = _generate_province_adjacencies();
- // TODO - read additional adjacencies
+ // TODO - DEV TASK: read additional adjacencies
return ret;
}
diff --git a/src/openvic-simulation/map/Map.hpp b/src/openvic-simulation/map/Map.hpp
index d11ad8e..189713c 100644
--- a/src/openvic-simulation/map/Map.hpp
+++ b/src/openvic-simulation/map/Map.hpp
@@ -14,7 +14,10 @@ namespace OpenVic {
struct Mapmode : HasIdentifier {
friend struct Map;
- using colour_func_t = std::function<colour_t(Map const&, Province const&)>;
+ /* Bottom 32 bits are the base colour, top 32 are the stripe colour, both in ARGB format with the alpha channels
+ * controlling interpolation with the terrain colour (0 = all terrain, 255 = all corresponding RGB) */
+ using base_stripe_t = uint64_t;
+ using colour_func_t = std::function<base_stripe_t(Map const&, Province const&)>;
using index_t = size_t;
private:
@@ -29,10 +32,11 @@ namespace OpenVic {
Mapmode(Mapmode&&) = default;
index_t get_index() const;
- colour_t get_colour(Map const& map, Province const& province) const;
+ base_stripe_t get_base_stripe_colours(Map const& map, Province const& province) const;
};
struct GoodManager;
+ struct ProvinceHistoryManager;
/* REQUIREMENTS:
* MAP-4
@@ -98,10 +102,16 @@ namespace OpenVic {
bool add_mapmode(std::string_view identifier, Mapmode::colour_func_t colour_func);
IDENTIFIER_REGISTRY_ACCESSORS(mapmode)
Mapmode const* get_mapmode_by_index(size_t index) const;
- static constexpr size_t MAPMODE_COLOUR_SIZE = 4;
+
+ /* The mapmode colour image contains of a list of base colours and stripe colours. Each colour is four bytes
+ * in RGBA format, with the alpha value being used to interpolate with the terrain colour, so A = 0 is fully terrain
+ * and A = 255 is fully the RGB colour packaged with A. The base and stripe colours for each province are packed
+ * together adjacently, so each province's entry is 8 bytes long. The list contains Province::MAX_INDEX + 1 entries,
+ * that is the maximum allowed number of provinces plus one for the index-zero "null province". */
bool generate_mapmode_colours(Mapmode::index_t index, uint8_t* target) const;
- bool setup(BuildingManager const& building_manager, PopManager const& pop_manager);
+ bool reset(BuildingManager const& building_manager);
+ bool apply_history_to_provinces(ProvinceHistoryManager const& history_manager, Date date);
void update_highest_province_population();
Pop::pop_size_t get_highest_province_population() const;
diff --git a/src/openvic-simulation/map/Province.cpp b/src/openvic-simulation/map/Province.cpp
index 4b76210..c2d2da0 100644
--- a/src/openvic-simulation/map/Province.cpp
+++ b/src/openvic-simulation/map/Province.cpp
@@ -8,56 +8,16 @@ using namespace OpenVic::NodeTools;
Province::Province(
std::string_view new_identifier, colour_t new_colour, index_t new_index
) : HasIdentifierAndColour { new_identifier, new_colour, true, false }, index { new_index },
- buildings { "buildings", false } {
+ region { nullptr }, on_map { false }, has_region { false }, water { false }, default_terrain_type { nullptr },
+ terrain_type { nullptr }, life_rating { 0 }, colony_status { colony_status_t::STATE }, owner { nullptr },
+ controller { nullptr }, slave { false }, buildings { "buildings", false }, rgo { nullptr }, total_population { 0 } {
assert(index != NULL_INDEX);
}
-Province::index_t Province::get_index() const {
- return index;
-}
-
-Region* Province::get_region() const {
- return region;
-}
-
-bool Province::get_on_map() const {
- return on_map;
-}
-
-bool Province::get_has_region() const {
- return has_region;
-}
-
-bool Province::get_water() const {
- return water;
-}
-
-TerrainType const* Province::get_terrain_type() const {
- return terrain_type;
-}
-
-Province::life_rating_t Province::get_life_rating() const {
- return life_rating;
-}
-
-Province::colony_status_t Province::get_colony_status() const {
- return colony_status;
-}
-
-Country const* Province::get_owner() const {
- return owner;
-}
-
-Country const* Province::get_controller() const {
- return controller;
-}
-
-std::vector<Country const*> const& Province::get_cores() const {
- return cores;
-}
-
-bool Province::is_slave() const {
- return slave;
+std::string Province::to_string() const {
+ std::stringstream stream;
+ stream << "(#" << std::to_string(index) << ", " << get_identifier() << ", 0x" << colour_to_hex_string() << ")";
+ return stream.str();
}
bool Province::load_positions(BuildingManager const& building_manager, ast::NodeCPtr root) {
@@ -89,14 +49,6 @@ bool Province::load_positions(BuildingManager const& building_manager, ast::Node
)(root);
}
-bool Province::add_building(BuildingInstance&& building_instance) {
- return buildings.add_item(std::move(building_instance));
-}
-
-void Province::reset_buildings() {
- buildings.reset();
-}
-
bool Province::expand_building(std::string_view building_type_identifier) {
BuildingInstance* building = buildings.get_item_by_identifier(building_type_identifier);
if (building == nullptr) {
@@ -105,16 +57,6 @@ bool Province::expand_building(std::string_view building_type_identifier) {
return building->expand();
}
-Good const* Province::get_rgo() const {
- return rgo;
-}
-
-std::string Province::to_string() const {
- std::stringstream stream;
- stream << "(#" << std::to_string(index) << ", " << get_identifier() << ", 0x" << colour_to_hex_string() << ")";
- return stream.str();
-}
-
bool Province::load_pop_list(PopManager const& pop_manager, ast::NodeCPtr root) {
return expect_dictionary_reserve_length(pops,
[this, &pop_manager](std::string_view pop_type_identifier, ast::NodeCPtr pop_node) -> bool {
@@ -133,22 +75,10 @@ bool Province::add_pop(Pop&& pop) {
}
}
-void Province::clear_pops() {
- pops.clear();
-}
-
size_t Province::get_pop_count() const {
return pops.size();
}
-std::vector<Pop> const& Province::get_pops() const {
- return pops;
-}
-
-Pop::pop_size_t Province::get_total_population() const {
- return total_population;
-}
-
/* REQUIREMENTS:
* MAP-65, MAP-68, MAP-70, MAP-234
*/
@@ -185,14 +115,6 @@ Province::adjacency_t::adjacency_t(Province const* province, distance_t distance
assert(province != nullptr);
}
-Province::distance_t Province::adjacency_t::get_distance() const {
- return distance;
-}
-
-Province::flags_t Province::adjacency_t::get_flags() const {
- return flags;
-}
-
bool Province::is_adjacent_to(Province const* province) {
for (adjacency_t adj : adjacencies) {
if (adj.province == province) {
@@ -207,7 +129,6 @@ bool Province::add_adjacency(Province const* province, distance_t distance, flag
Logger::error("Tried to create null adjacency province for province ", get_identifier(), "!");
return false;
}
-
if (is_adjacent_to(province)) {
return false;
}
@@ -215,46 +136,84 @@ bool Province::add_adjacency(Province const* province, distance_t distance, flag
return true;
}
-std::vector<Province::adjacency_t> const& Province::get_adjacencies() const {
- return adjacencies;
-}
+bool Province::reset(BuildingManager const& building_manager) {
+ terrain_type = default_terrain_type;
+ life_rating = 0;
+ colony_status = colony_status_t::STATE;
+ owner = nullptr;
+ controller = nullptr;
+ cores.clear();
+ slave = false;
+ rgo = nullptr;
-void Province::_set_terrain_type(TerrainType const* type) {
- terrain_type = type;
-}
+ buildings.reset();
+ bool ret = true;
+ if (!get_water()) {
+ if (building_manager.building_types_are_locked()) {
+ for (BuildingType const& building_type : building_manager.get_building_types()) {
+ if (building_type.get_in_province()) {
+ ret &= buildings.add_item({ building_type });
+ }
+ }
+ } else {
+ Logger::error("Cannot generate buildings until building types are locked!");
+ ret = false;
+ }
+ }
+ lock_buildings();
+
+ pops.clear();
+ update_pops();
-void Province::apply_history_to_province(ProvinceHistoryMap const& history, Date date) {
- auto entries = history.get_entries(date);
-
- reset_buildings();
+ return ret;
+}
- for (ProvinceHistoryEntry const* entry : entries) {
- if (entry->get_life_rating()) life_rating = *entry->get_life_rating();
- if (entry->get_colonial()) colony_status = *entry->get_colonial();
- if (entry->get_rgo()) rgo = *entry->get_rgo();
- if (entry->get_terrain_type()) terrain_type = *entry->get_terrain_type();
- if (entry->get_owner()) owner = *entry->get_owner();
- if (entry->get_controller()) controller = *entry->get_controller();
- if (entry->get_slave()) slave = *entry->get_slave();
- for (const auto& core : entry->get_remove_cores()) {
- const auto existing_core = std::find(cores.begin(), cores.end(), core);
- if (existing_core != cores.end()) cores.erase(existing_core);
+bool Province::apply_history_to_province(ProvinceHistoryEntry const* entry) {
+ if (entry == nullptr) {
+ Logger::error("Trying to apply null province history to ", get_identifier());
+ return false;
+ }
+ if (entry->get_life_rating()) life_rating = *entry->get_life_rating();
+ if (entry->get_colonial()) colony_status = *entry->get_colonial();
+ if (entry->get_rgo()) rgo = *entry->get_rgo();
+ if (entry->get_terrain_type()) terrain_type = *entry->get_terrain_type();
+ if (entry->get_owner()) owner = *entry->get_owner();
+ if (entry->get_controller()) controller = *entry->get_controller();
+ if (entry->get_slave()) slave = *entry->get_slave();
+ for (Country const* core : entry->get_remove_cores()) {
+ const typename decltype(cores)::iterator existing_core = std::find(cores.begin(), cores.end(), core);
+ if (existing_core != cores.end()) {
+ cores.erase(existing_core);
+ } else {
+ Logger::warning(
+ "Trying to remove non-existent core ", core->get_identifier(), " from province ", get_identifier()
+ );
}
- for (const auto& core : entry->get_add_cores()) {
- const auto existing_core = std::find(cores.begin(), cores.end(), core);
- if (existing_core == cores.end()) cores.push_back(core);
+ }
+ for (Country const* core : entry->get_add_cores()) {
+ const typename decltype(cores)::iterator existing_core = std::find(cores.begin(), cores.end(), core);
+ if (existing_core == cores.end()) {
+ cores.push_back(core);
+ } else {
+ Logger::warning(
+ "Trying to add already-existing core ", core->get_identifier(), " to province ", get_identifier()
+ );
}
- // TODO: rework province buildings
- for (const auto& building : entry->get_buildings()) {
- BuildingInstance* existing_entry = buildings.get_item_by_identifier(building.first->get_identifier());
- if (existing_entry != nullptr) {
- existing_entry->set_level(building.second);
- } else {
- BuildingInstance instance = { *building.first };
- instance.set_level(building.second);
- add_building(std::move(instance));
- }
+ }
+ bool ret = true;
+ for (auto const& [building, level] : entry->get_province_buildings()) {
+ BuildingInstance* existing_entry = buildings.get_item_by_identifier(building->get_identifier());
+ if (existing_entry != nullptr) {
+ existing_entry->set_level(level);
+ } else {
+ Logger::error(
+ "Trying to set level of non-existent province building ", building->get_identifier(), " to ", level,
+ " in province ", get_identifier()
+ );
+ ret = false;
}
- // TODO: party loyalties for each POP when implemented on POP side
}
+ // TODO: load state buildings
+ // TODO: party loyalties for each POP when implemented on POP side#
+ return ret;
}
diff --git a/src/openvic-simulation/map/Province.hpp b/src/openvic-simulation/map/Province.hpp
index eda05fb..af0bed4 100644
--- a/src/openvic-simulation/map/Province.hpp
+++ b/src/openvic-simulation/map/Province.hpp
@@ -2,7 +2,7 @@
#include <cassert>
-#include "openvic-simulation/economy/Building.hpp"
+#include "openvic-simulation/economy/BuildingInstance.hpp"
#include "openvic-simulation/politics/Ideology.hpp"
#include "openvic-simulation/pop/Pop.hpp"
#include "openvic-simulation/country/Country.hpp"
@@ -13,7 +13,7 @@ namespace OpenVic {
struct Good;
struct TerrainType;
struct TerrainTypeMapping;
- struct ProvinceHistoryMap;
+ struct ProvinceHistoryEntry;
/* REQUIREMENTS:
* MAP-5, MAP-7, MAP-8, MAP-43, MAP-47
@@ -34,14 +34,10 @@ namespace OpenVic {
private:
Province const* const province;
- const distance_t distance;
- flags_t flags;
+ const distance_t PROPERTY(distance);
+ flags_t PROPERTY(flags);
adjacency_t(Province const* province, distance_t distance, flags_t flags);
-
- public:
- distance_t get_distance() const;
- flags_t get_flags() const;
};
struct province_positions_t {
@@ -64,62 +60,50 @@ namespace OpenVic {
static constexpr index_t NULL_INDEX = 0, MAX_INDEX = std::numeric_limits<index_t>::max();
private:
- const index_t index;
- Region* region = nullptr;
- bool on_map = false, has_region = false, water = false;
- life_rating_t life_rating = 0;
- colony_status_t colony_status = colony_status_t::STATE;
- IdentifierRegistry<BuildingInstance> buildings;
- // TODO - change this into a factory-like structure
- Good const* rgo = nullptr;
-
- std::vector<Pop> pops;
- Pop::pop_size_t total_population;
- decimal_map_t<PopType const*> PROPERTY(pop_type_distribution);
- decimal_map_t<Ideology const*> PROPERTY(ideology_distribution);
- decimal_map_t<Culture const*> PROPERTY(culture_distribution);
- decimal_map_t<Religion const*> PROPERTY(religion_distribution);
-
- std::vector<adjacency_t> adjacencies;
+ const index_t PROPERTY(index);
+ Region* PROPERTY(region);
+ bool PROPERTY(on_map);
+ bool PROPERTY(has_region);
+ bool PROPERTY(water);
+ /* Terrain type calculated from terrain image */
+ TerrainType const* PROPERTY(default_terrain_type);
+
+ std::vector<adjacency_t> PROPERTY(adjacencies);
province_positions_t positions;
- TerrainType const* terrain_type = nullptr;
-
- void _set_terrain_type(TerrainType const* type);
+ TerrainType const* PROPERTY(terrain_type);
+ life_rating_t PROPERTY(life_rating);
+ colony_status_t PROPERTY(colony_status);
+ Country const* PROPERTY(owner);
+ Country const* PROPERTY(controller);
+ std::vector<Country const*> PROPERTY(cores);
+ bool PROPERTY(slave);
+ // TODO - change this into a factory-like structure
+ Good const* PROPERTY(rgo);
+ IdentifierRegistry<BuildingInstance> buildings;
- Country const* owner = nullptr;
- Country const* controller = nullptr;
- std::vector<Country const*> cores;
- bool slave = false;
+ std::vector<Pop> PROPERTY(pops);
+ Pop::pop_size_t PROPERTY(total_population);
+ fixed_point_map_t<PopType const*> PROPERTY(pop_type_distribution);
+ fixed_point_map_t<Ideology const*> PROPERTY(ideology_distribution);
+ fixed_point_map_t<Culture const*> PROPERTY(culture_distribution);
+ fixed_point_map_t<Religion const*> PROPERTY(religion_distribution);
Province(std::string_view new_identifier, colour_t new_colour, index_t new_index);
public:
Province(Province&&) = default;
- index_t get_index() const;
- Region* get_region() const;
- bool get_on_map() const;
- bool get_has_region() const;
- bool get_water() const;
- TerrainType const* get_terrain_type() const;
- life_rating_t get_life_rating() const;
- colony_status_t get_colony_status() const;
+ std::string to_string() const;
+
bool load_positions(BuildingManager const& building_manager, ast::NodeCPtr root);
- bool add_building(BuildingInstance&& building_instance);
IDENTIFIER_REGISTRY_ACCESSORS(building)
- void reset_buildings();
bool expand_building(std::string_view building_type_identifier);
- Good const* get_rgo() const;
- std::string to_string() const;
bool load_pop_list(PopManager const& pop_manager, ast::NodeCPtr root);
bool add_pop(Pop&& pop);
- void clear_pops();
size_t get_pop_count() const;
- std::vector<Pop> const& get_pops() const;
- Pop::pop_size_t get_total_population() const;
void update_pops();
void update_state(Date today);
@@ -127,13 +111,8 @@ namespace OpenVic {
bool is_adjacent_to(Province const* province);
bool add_adjacency(Province const* province, distance_t distance, flags_t flags);
- std::vector<adjacency_t> const& get_adjacencies() const;
-
- Country const* get_owner() const;
- Country const* get_controller() const;
- std::vector<Country const*> const& get_cores() const;
- bool is_slave() const;
- void apply_history_to_province(ProvinceHistoryMap const& history, Date date);
+ bool reset(BuildingManager const& building_manager);
+ bool apply_history_to_province(ProvinceHistoryEntry const* entry);
};
}
diff --git a/src/openvic-simulation/map/Region.cpp b/src/openvic-simulation/map/Region.cpp
index ac232df..e33d9c9 100644
--- a/src/openvic-simulation/map/Region.cpp
+++ b/src/openvic-simulation/map/Region.cpp
@@ -65,18 +65,15 @@ ProvinceSet::provinces_t const& ProvinceSet::get_provinces() const {
return provinces;
}
+static constexpr colour_t ERROR_REGION_COLOUR = COLOUR_COMPONENT << 16;
+
Region::Region(std::string_view new_identifier, provinces_t&& new_provinces, bool new_meta)
- : HasIdentifier { new_identifier }, ProvinceSet { std::move(new_provinces) }, meta { new_meta } {
+ : HasIdentifierAndColour {
+ new_identifier, new_provinces.size() > 0 ? new_provinces.front()->get_colour() : ERROR_REGION_COLOUR, false, false
+ }, ProvinceSet { std::move(new_provinces) }, meta { new_meta } {
lock();
}
bool Region::get_meta() const {
return meta;
}
-
-colour_t Region::get_colour() const {
- if (empty()) {
- return FULL_COLOUR << 16;
- }
- return get_provinces().front()->get_colour();
-}
diff --git a/src/openvic-simulation/map/Region.hpp b/src/openvic-simulation/map/Region.hpp
index 157b643..9119b93 100644
--- a/src/openvic-simulation/map/Region.hpp
+++ b/src/openvic-simulation/map/Region.hpp
@@ -28,7 +28,7 @@ namespace OpenVic {
/* REQUIREMENTS:
* MAP-6, MAP-44, MAP-48
*/
- struct Region : HasIdentifier, ProvinceSet {
+ struct Region : HasIdentifierAndColour, ProvinceSet {
friend struct Map;
private:
@@ -44,6 +44,5 @@ namespace OpenVic {
Region(Region&&) = default;
bool get_meta() const;
- colour_t get_colour() const;
};
}
diff --git a/src/openvic-simulation/map/TerrainType.hpp b/src/openvic-simulation/map/TerrainType.hpp
index 656c938..92f78dd 100644
--- a/src/openvic-simulation/map/TerrainType.hpp
+++ b/src/openvic-simulation/map/TerrainType.hpp
@@ -1,6 +1,6 @@
#pragma once
-#include "openvic-simulation/Modifier.hpp"
+#include "openvic-simulation/misc/Modifier.hpp"
namespace OpenVic {
struct TerrainTypeManager;
diff --git a/src/openvic-simulation/military/LeaderTrait.hpp b/src/openvic-simulation/military/LeaderTrait.hpp
index 16b4201..34de44d 100644
--- a/src/openvic-simulation/military/LeaderTrait.hpp
+++ b/src/openvic-simulation/military/LeaderTrait.hpp
@@ -3,7 +3,7 @@
#include <cstdint>
#include <string_view>
-#include "openvic-simulation/Modifier.hpp"
+#include "openvic-simulation/misc/Modifier.hpp"
#include "openvic-simulation/dataloader/NodeTools.hpp"
#include "openvic-simulation/types/IdentifierRegistry.hpp"
#include "openvic-simulation/types/fixed_point/FixedPoint.hpp"
diff --git a/src/openvic-simulation/military/Wargoal.cpp b/src/openvic-simulation/military/Wargoal.cpp
index b493f22..4a00c38 100644
--- a/src/openvic-simulation/military/Wargoal.cpp
+++ b/src/openvic-simulation/military/Wargoal.cpp
@@ -117,7 +117,7 @@ bool WargoalTypeManager::load_wargoal_file(ast::NodeCPtr root) {
},
"sprite_index", ONE_EXACTLY, expect_identifier(assign_variable_callback(sprite)),
"war_name", ONE_EXACTLY, expect_identifier_or_string(assign_variable_callback(war_name)),
- "months", ONE_EXACTLY, expect_months(assign_variable_callback(available)),
+ "months", ZERO_OR_ONE, expect_months(assign_variable_callback(available)),
"truce_months", ONE_EXACTLY, expect_months(assign_variable_callback(truce)),
"is_triggered_only", ZERO_OR_ONE, expect_bool(assign_variable_callback(triggered_only)),
"is_civil_war", ZERO_OR_ONE, expect_bool(assign_variable_callback(civil_war)),
diff --git a/src/openvic-simulation/military/Wargoal.hpp b/src/openvic-simulation/military/Wargoal.hpp
index 3700347..ef8170f 100644
--- a/src/openvic-simulation/military/Wargoal.hpp
+++ b/src/openvic-simulation/military/Wargoal.hpp
@@ -1,6 +1,6 @@
#pragma once
-#include "openvic-simulation/Modifier.hpp"
+#include "openvic-simulation/misc/Modifier.hpp"
#include "openvic-simulation/types/EnumBitfield.hpp"
#include "openvic-simulation/types/IdentifierRegistry.hpp"
#include "openvic-simulation/utility/Getters.hpp"
@@ -47,7 +47,7 @@ namespace OpenVic {
WAR_SCORE_BATTLE_FACTOR,
CONSTRUCTION_SPEED
};
- using peace_modifiers_t = decimal_map_t<PEACE_MODIFIERS>;
+ using peace_modifiers_t = fixed_point_map_t<PEACE_MODIFIERS>;
private:
const std::string PROPERTY(sprite);
diff --git a/src/openvic-simulation/misc/Define.cpp b/src/openvic-simulation/misc/Define.cpp
index c866b5d..cfd96a6 100644
--- a/src/openvic-simulation/misc/Define.cpp
+++ b/src/openvic-simulation/misc/Define.cpp
@@ -37,27 +37,30 @@ bool DefineManager::add_define(std::string_view name, std::string&& value, Defin
}
Date DefineManager::get_start_date() const {
- return *start_date;
+ return start_date ? *start_date : Date {};
}
Date DefineManager::get_end_date() const {
- return *end_date;
+ return end_date ? *end_date : Date {};
}
-bool DefineManager::add_date_define(std::string_view name, Date date) {
- if (name != "start_date" && name != "end_date") {
+bool DefineManager::in_game_period(Date date) const {
+ if (start_date && end_date) {
+ return date.in_range(*start_date, *end_date);
+ } else {
return false;
}
+}
- bool ret = defines.add_item({ name, date.to_string(), Define::Type::None });
-
+bool DefineManager::add_date_define(std::string_view name, Date date) {
if (name == "start_date") {
- start_date.reset(new Date(date));
+ start_date = date;
} else if (name == "end_date") {
- end_date.reset(new Date(date));
+ end_date = date;
+ } else {
+ return false;
}
-
- return ret;
+ return defines.add_item({ name, date.to_string(), Define::Type::None });
}
bool DefineManager::load_defines_file(ast::NodeCPtr root) {
@@ -103,8 +106,6 @@ bool DefineManager::load_defines_file(ast::NodeCPtr root) {
return ret;
})(value);
} else if (key == "start_date" || key == "end_date") {
- using namespace std::placeholders;
-
return expect_identifier_or_string(expect_date_str([this, &key](Date date) -> bool {
return add_date_define(key, date);
}))(value);
diff --git a/src/openvic-simulation/misc/Define.hpp b/src/openvic-simulation/misc/Define.hpp
index be71f9d..46e4836 100644
--- a/src/openvic-simulation/misc/Define.hpp
+++ b/src/openvic-simulation/misc/Define.hpp
@@ -1,7 +1,7 @@
#pragma once
#include <concepts>
-#include <memory>
+#include <optional>
#include "openvic-simulation/types/IdentifierRegistry.hpp"
#include "openvic-simulation/types/fixed_point/FixedPoint.hpp"
@@ -32,8 +32,8 @@ namespace OpenVic {
private:
IdentifierRegistry<Define> defines;
- std::unique_ptr<Date> start_date = nullptr;
- std::unique_ptr<Date> end_date = nullptr;
+ std::optional<Date> start_date;
+ std::optional<Date> end_date;
public:
DefineManager();
@@ -44,6 +44,7 @@ namespace OpenVic {
Date get_start_date() const;
Date get_end_date() const;
+ bool in_game_period(Date date) const;
bool load_defines_file(ast::NodeCPtr root);
};
diff --git a/src/openvic-simulation/Modifier.cpp b/src/openvic-simulation/misc/Modifier.cpp
index f6e34e1..0386833 100644
--- a/src/openvic-simulation/Modifier.cpp
+++ b/src/openvic-simulation/misc/Modifier.cpp
@@ -100,7 +100,7 @@ Date ModifierInstance::get_expiry_date() const {
return expiry_date;
}
-ModifierManager::ModifierManager() : modifier_effects { "modifier effects" }, modifiers { "modifiers" } {}
+ModifierManager::ModifierManager() : modifier_effects { "modifier effects" }, event_modifiers { "event modifiers" } {}
bool ModifierManager::add_modifier_effect(std::string_view identifier, bool positive_good, ModifierEffect::format_t format) {
if (identifier.empty()) {
@@ -112,7 +112,7 @@ bool ModifierManager::add_modifier_effect(std::string_view identifier, bool posi
);
}
-bool ModifierManager::add_modifier(std::string_view identifier, ModifierValue&& values, Modifier::icon_t icon) {
+bool ModifierManager::add_event_modifier(std::string_view identifier, ModifierValue&& values, Modifier::icon_t icon) {
if (identifier.empty()) {
Logger::error("Invalid modifier effect identifier - empty!");
return false;
@@ -121,7 +121,7 @@ bool ModifierManager::add_modifier(std::string_view identifier, ModifierValue&&
Logger::error("Invalid modifier icon for ", identifier, ": ", icon);
return false;
}
- return modifiers.add_item({ identifier, std::move(values), icon });
+ return event_modifiers.add_item({ identifier, std::move(values), icon }, duplicate_warning_callback);
}
bool ModifierManager::setup_modifier_effects() {
@@ -220,6 +220,7 @@ bool ModifierManager::setup_modifier_effects() {
ret &= add_modifier_effect("local_factory_throughput", true);
ret &= add_modifier_effect("local_repair", true);
ret &= add_modifier_effect("local_rgo_output", true);
+ ret &= add_modifier_effect("local_RGO_output", true);
ret &= add_modifier_effect("local_RGO_throughput", true);
ret &= add_modifier_effect("local_ruling_party_support", true);
ret &= add_modifier_effect("local_ship_build", false);
@@ -254,6 +255,39 @@ bool ModifierManager::setup_modifier_effects() {
return ret;
}
+bool ModifierManager::load_crime_modifiers(ast::NodeCPtr root) {
+ // TODO - DEV TASK: read crime modifiers
+ return true;
+}
+
+bool ModifierManager::load_event_modifiers(ast::NodeCPtr root) {
+ // TODO - DEV TASK: read event modifiers - example framework below
+ return true;
+ /*return expect_dictionary_reserve_length(
+ event_modifiers,
+ [this](std::string_view key, ast::NodeCPtr value) -> bool {
+ ModifierValue modifier_value;
+ Modifier::icon_t icon = 0;
+ bool ret = expect_modifier_value_and_keys(
+ move_variable_callback(modifier_value),
+ "icon", ONE_EXACTLY, expect_uint(assign_variable_callback(icon))
+ )(value);
+ ret &= add_event_modifier(key, std::move(modifier_value), icon);
+ return ret;
+ }
+ )(root);*/
+}
+
+bool ModifierManager::load_static_modifiers(ast::NodeCPtr root) {
+ // TODO - DEV TASK: read static modifiers
+ return true;
+}
+
+bool ModifierManager::load_triggered_modifiers(ast::NodeCPtr root) {
+ // TODO - DEV TASK: read triggered modifiers
+ return true;
+}
+
key_value_callback_t ModifierManager::_modifier_effect_callback(
ModifierValue& modifier, key_value_callback_t default_callback, ModifierEffectValidator auto effect_validator
) const {
diff --git a/src/openvic-simulation/Modifier.hpp b/src/openvic-simulation/misc/Modifier.hpp
index fc37655..e6ea54e 100644
--- a/src/openvic-simulation/Modifier.hpp
+++ b/src/openvic-simulation/misc/Modifier.hpp
@@ -36,7 +36,7 @@ namespace OpenVic {
struct ModifierValue {
friend struct ModifierManager;
- using effect_map_t = decimal_map_t<ModifierEffect const*>;
+ using effect_map_t = fixed_point_map_t<ModifierEffect const*>;
private:
effect_map_t values;
@@ -106,7 +106,7 @@ namespace OpenVic {
*/
private:
IdentifierInstanceRegistry<ModifierEffect> modifier_effects;
- IdentifierRegistry<Modifier> modifiers;
+ IdentifierRegistry<Modifier> event_modifiers;
/* effect_validator takes in ModifierEffect const& */
NodeTools::key_value_callback_t _modifier_effect_callback(
@@ -123,11 +123,16 @@ namespace OpenVic {
);
IDENTIFIER_REGISTRY_ACCESSORS(modifier_effect)
- bool add_modifier(std::string_view identifier, ModifierValue&& values, Modifier::icon_t icon);
- IDENTIFIER_REGISTRY_ACCESSORS(modifier)
+ bool add_event_modifier(std::string_view identifier, ModifierValue&& values, Modifier::icon_t icon);
+ IDENTIFIER_REGISTRY_ACCESSORS(event_modifier)
bool setup_modifier_effects();
+ bool load_crime_modifiers(ast::NodeCPtr root);
+ bool load_event_modifiers(ast::NodeCPtr root);
+ bool load_static_modifiers(ast::NodeCPtr root);
+ bool load_triggered_modifiers(ast::NodeCPtr root);
+
NodeTools::node_callback_t expect_validated_modifier_value_and_default(
NodeTools::callback_t<ModifierValue&&> modifier_callback, NodeTools::key_value_callback_t default_callback,
ModifierEffectValidator auto effect_validator
diff --git a/src/openvic-simulation/politics/NationalFocus.hpp b/src/openvic-simulation/politics/NationalFocus.hpp
index 7c5e40a..396f8ec 100644
--- a/src/openvic-simulation/politics/NationalFocus.hpp
+++ b/src/openvic-simulation/politics/NationalFocus.hpp
@@ -2,7 +2,7 @@
#include "openvic-simulation/types/IdentifierRegistry.hpp"
#include "openvic-simulation/utility/Getters.hpp"
-#include "openvic-simulation/Modifier.hpp"
+#include "openvic-simulation/misc/Modifier.hpp"
#include "openvic-simulation/pop/Pop.hpp"
#include "openvic-simulation/politics/Ideology.hpp"
#include "openvic-simulation/economy/Good.hpp"
@@ -14,7 +14,7 @@ namespace OpenVic {
struct NationalFocusGroup : HasIdentifier {
friend struct NationalFocusManager;
-
+
private:
NationalFocusGroup(std::string_view new_identifier);
};
@@ -23,9 +23,9 @@ namespace OpenVic {
friend struct NationalFocusManager;
public:
- using pop_promotion_map_t = std::map<PopType const*, fixed_point_t>;
- using party_loyalty_map_t = std::map<Ideology const*, fixed_point_t>;
- using production_map_t = std::map<Good const*, fixed_point_t>;
+ using pop_promotion_map_t = fixed_point_map_t<PopType const*>;
+ using party_loyalty_map_t = fixed_point_map_t<Ideology const*>;
+ using production_map_t = fixed_point_map_t<Good const*>;
private:
uint8_t PROPERTY(icon);
@@ -39,8 +39,8 @@ namespace OpenVic {
std::string_view new_identifier,
uint8_t new_icon,
NationalFocusGroup const& new_group,
- ModifierValue&& new_modifiers,
- pop_promotion_map_t&& new_encouraged_promotion,
+ ModifierValue&& new_modifiers,
+ pop_promotion_map_t&& new_encouraged_promotion,
party_loyalty_map_t&& new_encouraged_loyalty,
production_map_t&& new_encouraged_production
);
@@ -64,8 +64,8 @@ namespace OpenVic {
std::string_view identifier,
uint8_t icon,
NationalFocusGroup const& group,
- ModifierValue&& modifiers,
- NationalFocus::pop_promotion_map_t&& encouraged_promotion,
+ ModifierValue&& modifiers,
+ NationalFocus::pop_promotion_map_t&& encouraged_promotion,
NationalFocus::party_loyalty_map_t&& encouraged_loyalty,
NationalFocus::production_map_t&& encouraged_production
);
diff --git a/src/openvic-simulation/politics/NationalValue.hpp b/src/openvic-simulation/politics/NationalValue.hpp
index 09ef85e..625be36 100644
--- a/src/openvic-simulation/politics/NationalValue.hpp
+++ b/src/openvic-simulation/politics/NationalValue.hpp
@@ -1,6 +1,6 @@
#pragma once
-#include "openvic-simulation/Modifier.hpp"
+#include "openvic-simulation/misc/Modifier.hpp"
#include "openvic-simulation/types/IdentifierRegistry.hpp"
namespace OpenVic {
diff --git a/src/openvic-simulation/pop/Culture.cpp b/src/openvic-simulation/pop/Culture.cpp
index 47501e0..376e2a3 100644
--- a/src/openvic-simulation/pop/Culture.cpp
+++ b/src/openvic-simulation/pop/Culture.cpp
@@ -77,7 +77,7 @@ bool CultureManager::add_culture_group(
}
bool CultureManager::add_culture(
- std::string_view identifier, colour_t colour, CultureGroup const* group, std::vector<std::string>&& first_names,
+ std::string_view identifier, colour_t colour, CultureGroup const& group, std::vector<std::string>&& first_names,
std::vector<std::string>&& last_names
) {
if (!culture_groups.is_locked()) {
@@ -88,15 +88,11 @@ bool CultureManager::add_culture(
Logger::error("Invalid culture identifier - empty!");
return false;
}
- if (group == nullptr) {
- Logger::error("Null culture group for ", identifier);
- return false;
- }
if (colour > MAX_COLOUR_RGB) {
Logger::error("Invalid culture colour for ", identifier, ": ", colour_to_hex_string(colour));
return false;
}
- return cultures.add_item({ identifier, colour, *group, std::move(first_names), std::move(last_names) });
+ return cultures.add_item({ identifier, colour, group, std::move(first_names), std::move(last_names) });
}
bool CultureManager::load_graphical_culture_type_file(ast::NodeCPtr root) {
@@ -131,7 +127,7 @@ bool CultureManager::_load_culture_group(
}
bool CultureManager::_load_culture(
- CultureGroup const* culture_group, std::string_view culture_key, ast::NodeCPtr culture_node
+ CultureGroup const& culture_group, std::string_view culture_key, ast::NodeCPtr culture_node
) {
colour_t colour = NULL_COLOUR;
@@ -191,9 +187,8 @@ bool CultureManager::load_culture_file(ast::NodeCPtr root) {
lock_culture_groups();
cultures.reserve(cultures.size() + total_expected_cultures);
- ret &= expect_dictionary([this](std::string_view culture_group_key, ast::NodeCPtr culture_group_value) -> bool {
- CultureGroup const* culture_group = get_culture_group_by_identifier(culture_group_key);
- return expect_dictionary([this, culture_group](std::string_view key, ast::NodeCPtr value) -> bool {
+ ret &= expect_culture_group_dictionary([this](CultureGroup const& culture_group, ast::NodeCPtr culture_group_value) -> bool {
+ return expect_dictionary([this, &culture_group](std::string_view key, ast::NodeCPtr value) -> bool {
static const string_set_t reserved_keys = { "leader", "unit", "union", "is_overseas" };
if (reserved_keys.contains(key)) {
return true;
diff --git a/src/openvic-simulation/pop/Culture.hpp b/src/openvic-simulation/pop/Culture.hpp
index 402af0c..2abe77d 100644
--- a/src/openvic-simulation/pop/Culture.hpp
+++ b/src/openvic-simulation/pop/Culture.hpp
@@ -71,7 +71,7 @@ namespace OpenVic {
size_t& total_expected_cultures, GraphicalCultureType const* default_unit_graphical_culture_type,
std::string_view culture_group_key, ast::NodeCPtr culture_group_node
);
- bool _load_culture(CultureGroup const* culture_group, std::string_view culture_key, ast::NodeCPtr node);
+ bool _load_culture(CultureGroup const& culture_group, std::string_view culture_key, ast::NodeCPtr node);
public:
CultureManager();
@@ -80,13 +80,13 @@ namespace OpenVic {
IDENTIFIER_REGISTRY_ACCESSORS(graphical_culture_type)
bool add_culture_group(
- std::string_view identifier, std::string_view leader, GraphicalCultureType const* new_graphical_culture_type,
+ std::string_view identifier, std::string_view leader, GraphicalCultureType const* graphical_culture_type,
bool is_overseas
);
IDENTIFIER_REGISTRY_ACCESSORS(culture_group)
bool add_culture(
- std::string_view identifier, colour_t colour, CultureGroup const* group, std::vector<std::string>&& first_names,
+ std::string_view identifier, colour_t colour, CultureGroup const& group, std::vector<std::string>&& first_names,
std::vector<std::string>&& last_names
);
IDENTIFIER_REGISTRY_ACCESSORS(culture)
diff --git a/src/openvic-simulation/pop/Pop.hpp b/src/openvic-simulation/pop/Pop.hpp
index 4abb2a9..f7f20fe 100644
--- a/src/openvic-simulation/pop/Pop.hpp
+++ b/src/openvic-simulation/pop/Pop.hpp
@@ -49,7 +49,7 @@ namespace OpenVic {
friend struct PopManager;
using sprite_t = uint8_t;
- using rebel_units_t = decimal_map_t<Unit const*>;
+ using rebel_units_t = fixed_point_map_t<Unit const*>;
private:
const enum class strata_t { POOR, MIDDLE, RICH } strata;
diff --git a/src/openvic-simulation/pop/Religion.cpp b/src/openvic-simulation/pop/Religion.cpp
index 99915c3..f52ed3e 100644
--- a/src/openvic-simulation/pop/Religion.cpp
+++ b/src/openvic-simulation/pop/Religion.cpp
@@ -37,7 +37,7 @@ bool ReligionManager::add_religion_group(std::string_view identifier) {
}
bool ReligionManager::add_religion(
- std::string_view identifier, colour_t colour, ReligionGroup const* group, Religion::icon_t icon, bool pagan
+ std::string_view identifier, colour_t colour, ReligionGroup const& group, Religion::icon_t icon, bool pagan
) {
if (!religion_groups.is_locked()) {
Logger::error("Cannot register religions until religion groups are locked!");
@@ -47,10 +47,6 @@ bool ReligionManager::add_religion(
Logger::error("Invalid religion identifier - empty!");
return false;
}
- if (group == nullptr) {
- Logger::error("Null religion group for ", identifier);
- return false;
- }
if (colour > MAX_COLOUR_RGB) {
Logger::error("Invalid religion colour for ", identifier, ": ", colour_to_hex_string(colour));
return false;
@@ -59,7 +55,7 @@ bool ReligionManager::add_religion(
Logger::error("Invalid religion icon for ", identifier, ": ", icon);
return false;
}
- return religions.add_item({ identifier, colour, *group, icon, pagan });
+ return religions.add_item({ identifier, colour, group, icon, pagan });
}
/* REQUIREMENTS:
@@ -77,10 +73,8 @@ bool ReligionManager::load_religion_file(ast::NodeCPtr root) {
)(root);
lock_religion_groups();
religions.reserve(religions.size() + total_expected_religions);
- ret &= expect_dictionary([this](std::string_view religion_group_key, ast::NodeCPtr religion_group_value) -> bool {
- ReligionGroup const* religion_group = get_religion_group_by_identifier(religion_group_key);
-
- return expect_dictionary([this, religion_group](std::string_view key, ast::NodeCPtr value) -> bool {
+ ret &= expect_religion_group_dictionary([this](ReligionGroup const& religion_group, ast::NodeCPtr religion_group_value) -> bool {
+ return expect_dictionary([this, &religion_group](std::string_view key, ast::NodeCPtr value) -> bool {
colour_t colour = NULL_COLOUR;
Religion::icon_t icon = 0;
bool pagan = false;
diff --git a/src/openvic-simulation/pop/Religion.hpp b/src/openvic-simulation/pop/Religion.hpp
index a47754d..4cc8403 100644
--- a/src/openvic-simulation/pop/Religion.hpp
+++ b/src/openvic-simulation/pop/Religion.hpp
@@ -52,7 +52,7 @@ namespace OpenVic {
IDENTIFIER_REGISTRY_ACCESSORS(religion_group)
bool add_religion(
- std::string_view identifier, colour_t colour, ReligionGroup const* group, Religion::icon_t icon, bool pagan
+ std::string_view identifier, colour_t colour, ReligionGroup const& group, Religion::icon_t icon, bool pagan
);
IDENTIFIER_REGISTRY_ACCESSORS(religion)
diff --git a/src/openvic-simulation/types/Colour.hpp b/src/openvic-simulation/types/Colour.hpp
index e516d5b..7c97b12 100644
--- a/src/openvic-simulation/types/Colour.hpp
+++ b/src/openvic-simulation/types/Colour.hpp
@@ -15,7 +15,7 @@ namespace OpenVic {
* When colour_t is used in a purely graphical context, NULL_COLOUR
* should be allowed.
*/
- static constexpr colour_t NULL_COLOUR = 0, FULL_COLOUR = 0xFF;
+ static constexpr colour_t NULL_COLOUR = 0, COLOUR_COMPONENT = 0xFF;
static constexpr colour_t MAX_COLOUR_RGB = 0xFFFFFF, MAX_COLOUR_ARGB = 0xFFFFFFFF;
constexpr colour_t float_to_colour_byte(float f, float min = 0.0f, float max = 1.0f) {
diff --git a/src/openvic-simulation/types/Date.cpp b/src/openvic-simulation/types/Date.cpp
index c5eac41..e695e45 100644
--- a/src/openvic-simulation/types/Date.cpp
+++ b/src/openvic-simulation/types/Date.cpp
@@ -204,6 +204,10 @@ Date Date::operator++(int) {
return old;
}
+bool Date::in_range(Date start, Date end) const {
+ return start <= *this && *this <= end;
+}
+
std::string Date::to_string() const {
std::stringstream ss;
ss << *this;
diff --git a/src/openvic-simulation/types/Date.hpp b/src/openvic-simulation/types/Date.hpp
index b6e693c..5aed49b 100644
--- a/src/openvic-simulation/types/Date.hpp
+++ b/src/openvic-simulation/types/Date.hpp
@@ -91,6 +91,8 @@ namespace OpenVic {
Date& operator++();
Date operator++(int);
+ bool in_range(Date start, Date end) const;
+
std::string to_string() const;
explicit operator std::string() const;
// Parsed from string of the form YYYY.MM.DD
diff --git a/src/openvic-simulation/types/IdentifierRegistry.hpp b/src/openvic-simulation/types/IdentifierRegistry.hpp
index 662815e..6c0dd3b 100644
--- a/src/openvic-simulation/types/IdentifierRegistry.hpp
+++ b/src/openvic-simulation/types/IdentifierRegistry.hpp
@@ -6,6 +6,7 @@
#include <vector>
#include "openvic-simulation/dataloader/NodeTools.hpp"
+#include "openvic-simulation/types/fixed_point/FixedPointMap.hpp"
#include "openvic-simulation/utility/Getters.hpp"
#include "openvic-simulation/utility/Logger.hpp"
@@ -77,22 +78,6 @@ namespace OpenVic {
HasIdentifierAndColour& operator=(HasIdentifierAndColour&&) = delete;
};
- template<typename T>
- using decimal_map_t = std::map<T, fixed_point_t>;
-
- template<typename T>
- constexpr typename decimal_map_t<T>::value_type get_largest_item(decimal_map_t<T> const& map) {
- constexpr auto pred = [](typename decimal_map_t<T>::value_type a, typename decimal_map_t<T>::value_type b) -> bool {
- return a.second < b.second;
- };
- const typename decimal_map_t<T>::const_iterator result = std::max_element(map.begin(), map.end(), pred);
- if (result != map.end()) {
- return *result;
- } else {
- return { nullptr, -1 };
- }
- }
-
/* Callbacks for trying to add duplicate keys via UniqueKeyRegistry::add_item */
static bool duplicate_fail_callback(std::string_view registry_name, std::string_view duplicate_identifier) {
Logger::error(
@@ -274,10 +259,10 @@ namespace OpenVic {
}
NodeTools::node_callback_t expect_item_decimal_map(
- NodeTools::callback_t<decimal_map_t<value_type const*>&&> callback
+ NodeTools::callback_t<fixed_point_map_t<value_type const*>&&> callback
) const {
return [this, callback](ast::NodeCPtr node) -> bool {
- decimal_map_t<value_type const*> map;
+ fixed_point_map_t<value_type const*> map;
bool ret = expect_item_dictionary([&map](value_type const& key, ast::NodeCPtr value) -> bool {
fixed_point_t val;
const bool ret = NodeTools::expect_fixed_point(NodeTools::assign_variable_callback(val))(value);
@@ -348,6 +333,9 @@ namespace OpenVic {
size_t get_##singular##_count() const { \
return plural.size(); \
} \
+ bool plural##_empty() const { \
+ return plural.empty(); \
+ } \
std::vector<decltype(plural)::storage_type> const& get_##plural() const { \
return plural.get_items(); \
} \
@@ -370,7 +358,7 @@ namespace OpenVic {
return plural.expect_item_dictionary(callback); \
} \
NodeTools::node_callback_t expect_##singular##_decimal_map( \
- NodeTools::callback_t<decimal_map_t<decltype(plural)::value_type const*>&&> callback \
+ NodeTools::callback_t<fixed_point_map_t<decltype(plural)::value_type const*>&&> callback \
) const { \
return plural.expect_item_decimal_map(callback); \
}
diff --git a/src/openvic-simulation/types/fixed_point/FixedPointMap.hpp b/src/openvic-simulation/types/fixed_point/FixedPointMap.hpp
new file mode 100644
index 0000000..a7d298b
--- /dev/null
+++ b/src/openvic-simulation/types/fixed_point/FixedPointMap.hpp
@@ -0,0 +1,48 @@
+#pragma once
+
+#include "openvic-simulation/types/fixed_point/FixedPoint.hpp"
+
+namespace OpenVic {
+
+ template<typename T>
+ using fixed_point_map_t = std::map<T, fixed_point_t>;
+
+ template<typename T>
+ using fixed_point_map_value_t = typename fixed_point_map_t<T>::value_type;
+
+ template<typename T>
+ using fixed_point_map_const_iterator_t = typename fixed_point_map_t<T>::const_iterator;
+
+ template<typename T>
+ constexpr fixed_point_t get_total(fixed_point_map_t<T> const& map) {
+ fixed_point_t total = 0;
+ for (auto const& [key, value] : map) {
+ total += value;
+ }
+ return total;
+ }
+
+ template<typename T>
+ constexpr fixed_point_map_const_iterator_t<T> get_largest_item(fixed_point_map_t<T> const& map) {
+ constexpr auto pred = [](fixed_point_map_value_t<T> a, fixed_point_map_value_t<T> b) -> bool {
+ return a.second < b.second;
+ };
+ return std::max_element(map.begin(), map.end(), pred);
+ }
+
+ template<typename T>
+ constexpr std::pair<fixed_point_map_const_iterator_t<T>, fixed_point_map_const_iterator_t<T>> get_largest_two_items(
+ fixed_point_map_t<T> const& map
+ ) {
+ fixed_point_map_const_iterator_t<T> largest = map.end(), second_largest = map.end();
+ for (fixed_point_map_const_iterator_t<T> it = map.begin(); it != map.end(); ++it) {
+ if (largest == map.end() || it->second > largest->second) {
+ second_largest = largest;
+ largest = it;
+ } else if (second_largest == map.end() || it->second > second_largest->second) {
+ second_largest = it;
+ }
+ }
+ return std::make_pair(std::move(largest), std::move(second_largest));
+ }
+}