aboutsummaryrefslogtreecommitdiff
path: root/src/openvic-simulation/country/CountryInstance.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/openvic-simulation/country/CountryInstance.cpp')
-rw-r--r--src/openvic-simulation/country/CountryInstance.cpp371
1 files changed, 344 insertions, 27 deletions
diff --git a/src/openvic-simulation/country/CountryInstance.cpp b/src/openvic-simulation/country/CountryInstance.cpp
index 4fab010..e0932eb 100644
--- a/src/openvic-simulation/country/CountryInstance.cpp
+++ b/src/openvic-simulation/country/CountryInstance.cpp
@@ -2,6 +2,7 @@
#include "openvic-simulation/country/CountryDefinition.hpp"
#include "openvic-simulation/history/CountryHistory.hpp"
+#include "openvic-simulation/map/Crime.hpp"
#include "openvic-simulation/map/MapInstance.hpp"
#include "openvic-simulation/misc/Define.hpp"
#include "openvic-simulation/politics/Ideology.hpp"
@@ -16,10 +17,12 @@ static constexpr colour_t ERROR_COLOUR = colour_t::from_integer(0xFF0000);
CountryInstance::CountryInstance(
CountryDefinition const* new_country_definition,
- decltype(technologies)::keys_t const& technology_keys,
- decltype(inventions)::keys_t const& invention_keys,
+ decltype(unlocked_building_types)::keys_t const& building_type_keys,
+ decltype(unlocked_technologies)::keys_t const& technology_keys,
+ decltype(unlocked_inventions)::keys_t const& invention_keys,
decltype(upper_house)::keys_t const& ideology_keys,
decltype(government_flag_overrides)::keys_t const& government_type_keys,
+ decltype(unlocked_crimes)::keys_t const& crime_keys,
decltype(pop_type_distribution)::keys_t const& pop_type_keys,
decltype(unlocked_regiment_types)::keys_t const& unlocked_regiment_types_keys,
decltype(unlocked_ship_types)::keys_t const& unlocked_ship_types_keys
@@ -44,13 +47,14 @@ CountryInstance::CountryInstance(
industrial_power_from_investments {},
industrial_rank { 0 },
foreign_investments {},
+ unlocked_building_types { &building_type_keys },
/* Budget */
cash_stockpile { 0 },
/* Technology */
- technologies { &technology_keys },
- inventions { &invention_keys },
+ unlocked_technologies { &technology_keys },
+ unlocked_inventions { &invention_keys },
current_research { nullptr },
invested_research_points { 0 },
expected_completion_date {},
@@ -72,6 +76,7 @@ CountryInstance::CountryInstance(
infamy { 0 },
plurality { 0 },
revanchism { 0 },
+ unlocked_crimes { &crime_keys },
/* Population */
primary_culture { nullptr },
@@ -115,7 +120,22 @@ CountryInstance::CountryInstance(
disarmed { false },
unlocked_regiment_types { &unlocked_regiment_types_keys },
allowed_regiment_cultures { RegimentType::allowed_cultures_t::NO_CULTURES },
- unlocked_ship_types { &unlocked_ship_types_keys } {
+ unlocked_ship_types { &unlocked_ship_types_keys },
+ gas_attack_unlock_level { 0 },
+ gas_defence_unlock_level { 0 },
+ unit_variant_unlock_levels {} {
+
+ for (BuildingType const& building_type : *unlocked_building_types.get_keys()) {
+ if (building_type.is_default_enabled()) {
+ unlock_building_type(building_type);
+ }
+ }
+
+ for (Crime const& crime : *unlocked_crimes.get_keys()) {
+ if (crime.is_default_active()) {
+ unlock_crime(crime);
+ }
+ }
for (RegimentType const& regiment_type : *unlocked_regiment_types.get_keys()) {
if (regiment_type.is_active()) {
@@ -301,30 +321,311 @@ template bool CountryInstance::remove_leader(LeaderBranched<UnitType::branch_t::
template bool CountryInstance::remove_leader(LeaderBranched<UnitType::branch_t::NAVAL> const*);
template<UnitType::branch_t Branch>
-void CountryInstance::unlock_unit_type(UnitTypeBranched<Branch> const& unit_type) {
- IndexedMap<UnitTypeBranched<Branch>, bool>& unlocked_unit_types = get_unlocked_unit_types<Branch>();
+bool CountryInstance::modify_unit_type_unlock(UnitTypeBranched<Branch> const& unit_type, unlock_level_t unlock_level_change) {
+ IndexedMap<UnitTypeBranched<Branch>, unlock_level_t>& unlocked_unit_types = get_unlocked_unit_types<Branch>();
- decltype(unlocked_regiment_types)::value_ref_t unlock_value = unlocked_unit_types[unit_type];
+ typename IndexedMap<UnitTypeBranched<Branch>, unlock_level_t>::value_ref_t unlock_level = unlocked_unit_types[unit_type];
- if (unlock_value) {
- Logger::warning(
- "Attempted to unlock already-unlocked unit type \"", unit_type.get_identifier(),
- "\" for country ", get_identifier()
+ // This catches subtracting below 0 or adding above the int types maximum value
+ if (unlock_level + unlock_level_change < 0) {
+ Logger::error(
+ "Attempted to change unlock level for unit type ", unit_type.get_identifier(), " in country ",
+ get_identifier(), " to invalid value: current level = ", static_cast<int64_t>(unlock_level), ", change = ",
+ static_cast<int64_t>(unlock_level_change), ", invalid new value = ",
+ static_cast<int64_t>(unlock_level + unlock_level_change)
);
- return;
+ return false;
}
- unlock_value = true;
+ unlock_level += unlock_level_change;
+
+ return true;
+}
+
+template bool CountryInstance::modify_unit_type_unlock(UnitTypeBranched<UnitType::branch_t::LAND> const&, unlock_level_t);
+template bool CountryInstance::modify_unit_type_unlock(UnitTypeBranched<UnitType::branch_t::NAVAL> const&, unlock_level_t);
+
+bool CountryInstance::modify_unit_type_unlock(UnitType const& unit_type, unlock_level_t unlock_level_change) {
+ using enum UnitType::branch_t;
- if constexpr (Branch == UnitType::branch_t::LAND) {
- allowed_regiment_cultures = RegimentType::allowed_cultures_get_most_permissive(
- allowed_regiment_cultures, unit_type.get_allowed_cultures()
+ switch (unit_type.get_branch()) {
+ case LAND:
+ return modify_unit_type_unlock(static_cast<UnitTypeBranched<LAND> const&>(unit_type), unlock_level_change);
+ case NAVAL:
+ return modify_unit_type_unlock(static_cast<UnitTypeBranched<NAVAL> const&>(unit_type), unlock_level_change);
+ default:
+ Logger::error(
+ "Attempted to change unlock level for unit type \"", unit_type.get_identifier(), "\" with invalid branch ",
+ static_cast<uint32_t>(unit_type.get_branch()), " is unlocked for country ", get_identifier()
);
+ return false;
}
}
-template void CountryInstance::unlock_unit_type(UnitTypeBranched<UnitType::branch_t::LAND> const&);
-template void CountryInstance::unlock_unit_type(UnitTypeBranched<UnitType::branch_t::NAVAL> const&);
+bool CountryInstance::unlock_unit_type(UnitType const& unit_type) {
+ return modify_unit_type_unlock(unit_type, 1);
+}
+
+bool CountryInstance::is_unit_type_unlocked(UnitType const& unit_type) const {
+ using enum UnitType::branch_t;
+
+ switch (unit_type.get_branch()) {
+ case LAND:
+ return unlocked_regiment_types[static_cast<UnitTypeBranched<LAND> const&>(unit_type)] > 0;
+ case NAVAL:
+ return unlocked_ship_types[static_cast<UnitTypeBranched<NAVAL> const&>(unit_type)] > 0;
+ default:
+ Logger::error(
+ "Attempted to check if unit type \"", unit_type.get_identifier(), "\" with invalid branch ",
+ static_cast<uint32_t>(unit_type.get_branch()), " is unlocked for country ", get_identifier()
+ );
+ return false;
+ }
+}
+
+bool CountryInstance::modify_building_type_unlock(BuildingType const& building_type, unlock_level_t unlock_level_change) {
+ decltype(unlocked_building_types)::value_ref_t unlock_level = unlocked_building_types[building_type];
+
+ // This catches subtracting below 0 or adding above the int types maximum value
+ if (unlock_level + unlock_level_change < 0) {
+ Logger::error(
+ "Attempted to change unlock level for building type ", building_type.get_identifier(), " in country ",
+ get_identifier(), " to invalid value: current level = ", static_cast<int64_t>(unlock_level), ", change = ",
+ static_cast<int64_t>(unlock_level_change), ", invalid new value = ",
+ static_cast<int64_t>(unlock_level + unlock_level_change)
+ );
+ return false;
+ }
+
+ unlock_level += unlock_level_change;
+
+ return true;
+}
+
+bool CountryInstance::unlock_building_type(BuildingType const& building_type) {
+ return modify_building_type_unlock(building_type, 1);
+}
+
+bool CountryInstance::is_building_type_unlocked(BuildingType const& building_type) const {
+ return unlocked_building_types[building_type] > 0;
+}
+
+bool CountryInstance::modify_crime_unlock(Crime const& crime, unlock_level_t unlock_level_change) {
+ decltype(unlocked_crimes)::value_ref_t unlock_level = unlocked_crimes[crime];
+
+ // This catches subtracting below 0 or adding above the int types maximum value
+ if (unlock_level + unlock_level_change < 0) {
+ Logger::error(
+ "Attempted to change unlock level for crime ", crime.get_identifier(), " in country ",
+ get_identifier(), " to invalid value: current level = ", static_cast<int64_t>(unlock_level), ", change = ",
+ static_cast<int64_t>(unlock_level_change), ", invalid new value = ",
+ static_cast<int64_t>(unlock_level + unlock_level_change)
+ );
+ return false;
+ }
+
+ unlock_level += unlock_level_change;
+
+ return true;
+}
+
+bool CountryInstance::unlock_crime(Crime const& crime) {
+ return modify_crime_unlock(crime, 1);
+}
+
+bool CountryInstance::is_crime_unlocked(Crime const& crime) const {
+ return unlocked_crimes[crime] > 0;
+}
+
+bool CountryInstance::modify_gas_attack_unlock(unlock_level_t unlock_level_change) {
+ // This catches subtracting below 0 or adding above the int types maximum value
+ if (gas_attack_unlock_level + unlock_level_change < 0) {
+ Logger::error(
+ "Attempted to change unlock level for gas attack in country ", get_identifier(),
+ " to invalid value: current level = ", static_cast<int64_t>(gas_attack_unlock_level), ", change = ",
+ static_cast<int64_t>(unlock_level_change), ", invalid new value = ",
+ static_cast<int64_t>(gas_attack_unlock_level + unlock_level_change)
+ );
+ return false;
+ }
+
+ gas_attack_unlock_level += unlock_level_change;
+
+ return true;
+}
+
+bool CountryInstance::unlock_gas_attack() {
+ return modify_gas_attack_unlock(1);
+}
+
+bool CountryInstance::is_gas_attack_unlocked() const {
+ return gas_attack_unlock_level > 0;
+}
+
+bool CountryInstance::modify_gas_defence_unlock(unlock_level_t unlock_level_change) {
+ // This catches subtracting below 0 or adding above the int types maximum value
+ if (gas_defence_unlock_level + unlock_level_change < 0) {
+ Logger::error(
+ "Attempted to change unlock level for gas defence in country ", get_identifier(),
+ " to invalid value: current level = ", static_cast<int64_t>(gas_defence_unlock_level), ", change = ",
+ static_cast<int64_t>(unlock_level_change), ", invalid new value = ",
+ static_cast<int64_t>(gas_defence_unlock_level + unlock_level_change)
+ );
+ return false;
+ }
+
+ gas_defence_unlock_level += unlock_level_change;
+
+ return true;
+}
+
+bool CountryInstance::unlock_gas_defence() {
+ return modify_gas_defence_unlock(1);
+}
+
+bool CountryInstance::is_gas_defence_unlocked() const {
+ return gas_defence_unlock_level > 0;
+}
+
+bool CountryInstance::modify_unit_variant_unlock(unit_variant_t unit_variant, unlock_level_t unlock_level_change) {
+ if (unit_variant < 1) {
+ Logger::error("Trying to modify unlock level for default unit variant 0");
+ return false;
+ }
+
+ if (unit_variant_unlock_levels.size() < unit_variant) {
+ unit_variant_unlock_levels.resize(unit_variant);
+ }
+
+ unlock_level_t& unlock_level = unit_variant_unlock_levels[unit_variant - 1];
+
+ bool ret = true;
+
+ // This catches subtracting below 0 or adding above the int types maximum value
+ if (unlock_level + unlock_level_change < 0) {
+ Logger::error(
+ "Attempted to change unlock level for unit variant ", static_cast<uint64_t>(unit_variant), " in country ",
+ get_identifier(), " to invalid value: current level = ", static_cast<int64_t>(unlock_level), ", change = ",
+ static_cast<int64_t>(unlock_level_change), ", invalid new value = ",
+ static_cast<int64_t>(unlock_level + unlock_level_change)
+ );
+ ret = false;
+ } else {
+ unlock_level += unlock_level_change;
+ }
+
+ while (!unit_variant_unlock_levels.empty() && unit_variant_unlock_levels.back() < 1) {
+ unit_variant_unlock_levels.pop_back();
+ }
+
+ return ret;
+}
+
+bool CountryInstance::unlock_unit_variant(unit_variant_t unit_variant) {
+ return modify_unit_variant_unlock(unit_variant, 1);
+}
+
+CountryInstance::unit_variant_t CountryInstance::get_max_unlocked_unit_variant() const {
+ return unit_variant_unlock_levels.size();
+}
+
+bool CountryInstance::modify_technology_unlock(Technology const& technology, unlock_level_t unlock_level_change) {
+ decltype(unlocked_technologies)::value_ref_t unlock_level = unlocked_technologies[technology];
+
+ // This catches subtracting below 0 or adding above the int types maximum value
+ if (unlock_level + unlock_level_change < 0) {
+ Logger::error(
+ "Attempted to change unlock level for technology ", technology.get_identifier(), " in country ",
+ get_identifier(), " to invalid value: current level = ", static_cast<int64_t>(unlock_level), ", change = ",
+ static_cast<int64_t>(unlock_level_change), ", invalid new value = ",
+ static_cast<int64_t>(unlock_level + unlock_level_change)
+ );
+ return false;
+ }
+
+ unlock_level += unlock_level_change;
+
+ bool ret = true;
+
+ // TODO - bool unciv_military ?
+
+ if (technology.get_unit_variant().has_value()) {
+ ret &= modify_unit_variant_unlock(*technology.get_unit_variant(), unlock_level_change);
+ }
+ for (UnitType const* unit : technology.get_activated_units()) {
+ ret &= modify_unit_type_unlock(*unit, unlock_level_change);
+ }
+ for (BuildingType const* building : technology.get_activated_buildings()) {
+ ret &= modify_building_type_unlock(*building, unlock_level_change);
+ }
+
+ return ret;
+}
+
+bool CountryInstance::set_technology_unlock_level(Technology const& technology, unlock_level_t unlock_level) {
+ const unlock_level_t unlock_level_change = unlock_level - unlocked_technologies[technology];
+ return unlock_level_change != 0 ? modify_technology_unlock(technology, unlock_level_change) : true;
+}
+
+bool CountryInstance::unlock_technology(Technology const& technology) {
+ return modify_technology_unlock(technology, 1);
+}
+
+bool CountryInstance::is_technology_unlocked(Technology const& technology) const {
+ return unlocked_technologies[technology] > 0;
+}
+
+bool CountryInstance::modify_invention_unlock(Invention const& invention, unlock_level_t unlock_level_change) {
+ decltype(unlocked_inventions)::value_ref_t unlock_level = unlocked_inventions[invention];
+
+ // This catches subtracting below 0 or adding above the int types maximum value
+ if (unlock_level + unlock_level_change < 0) {
+ Logger::error(
+ "Attempted to change unlock level for invention ", invention.get_identifier(), " in country ",
+ get_identifier(), " to invalid value: current level = ", static_cast<int64_t>(unlock_level), ", change = ",
+ static_cast<int64_t>(unlock_level_change), ", invalid new value = ",
+ static_cast<int64_t>(unlock_level + unlock_level_change)
+ );
+ return false;
+ }
+
+ unlock_level += unlock_level_change;
+
+ bool ret = true;
+
+ // TODO - handle invention.is_news()
+
+ for (UnitType const* unit : invention.get_activated_units()) {
+ ret &= modify_unit_type_unlock(*unit, unlock_level_change);
+ }
+ for (BuildingType const* building : invention.get_activated_buildings()) {
+ ret &= modify_building_type_unlock(*building, unlock_level_change);
+ }
+ for (Crime const* crime : invention.get_enabled_crimes()) {
+ ret &= modify_crime_unlock(*crime, unlock_level_change);
+ }
+ if (invention.will_unlock_gas_attack()) {
+ ret &= modify_gas_attack_unlock(unlock_level_change);
+ }
+ if (invention.will_unlock_gas_defence()) {
+ ret &= modify_gas_defence_unlock(unlock_level_change);
+ }
+
+ return ret;
+}
+
+bool CountryInstance::set_invention_unlock_level(Invention const& invention, unlock_level_t unlock_level) {
+ const unlock_level_t unlock_level_change = unlock_level - unlocked_inventions[invention];
+ return unlock_level_change != 0 ? modify_invention_unlock(invention, unlock_level_change) : true;
+}
+
+bool CountryInstance::unlock_invention(Invention const& invention) {
+ return modify_invention_unlock(invention, 1);
+}
+
+bool CountryInstance::is_invention_unlocked(Invention const& invention) const {
+ return unlocked_inventions[invention] > 0;
+}
bool CountryInstance::is_primary_culture(Culture const& culture) const {
return &culture == primary_culture;
@@ -385,8 +686,12 @@ bool CountryInstance::apply_history_to_country(
target[*key] = value;
}
};
- set_bool_map_to_indexed_map(technologies, entry.get_technologies());
- set_bool_map_to_indexed_map(inventions, entry.get_inventions());
+ for (auto const& [technology, level] : entry.get_technologies()) {
+ ret &= set_technology_unlock_level(*technology, level);
+ }
+ for (auto const& [invention, activated] : entry.get_inventions()) {
+ ret &= set_invention_unlock_level(*invention, activated ? 1 : 0);
+ }
apply_foreign_investments(entry.get_foreign_investment(), country_instance_manager);
// These need to be applied to pops
@@ -751,24 +1056,36 @@ CountryInstance const& CountryInstanceManager::get_country_instance_from_definit
bool CountryInstanceManager::generate_country_instances(
CountryDefinitionManager const& country_definition_manager,
- decltype(CountryInstance::technologies)::keys_t const& technology_keys,
- decltype(CountryInstance::inventions)::keys_t const& invention_keys,
+ decltype(CountryInstance::unlocked_building_types)::keys_t const& building_type_keys,
+ decltype(CountryInstance::unlocked_technologies)::keys_t const& technology_keys,
+ decltype(CountryInstance::unlocked_inventions)::keys_t const& invention_keys,
decltype(CountryInstance::upper_house)::keys_t const& ideology_keys,
decltype(CountryInstance::government_flag_overrides)::keys_t const& government_type_keys,
+ decltype(CountryInstance::unlocked_crimes)::keys_t const& crime_keys,
decltype(CountryInstance::pop_type_distribution)::keys_t const& pop_type_keys,
decltype(CountryInstance::unlocked_regiment_types)::keys_t const& unlocked_regiment_types_keys,
decltype(CountryInstance::unlocked_ship_types)::keys_t const& unlocked_ship_types_keys
) {
reserve_more(country_instances, country_definition_manager.get_country_definition_count());
+ bool ret = true;
+
for (CountryDefinition const& country_definition : country_definition_manager.get_country_definitions()) {
- country_instances.add_item({
- &country_definition, technology_keys, invention_keys, ideology_keys, government_type_keys, pop_type_keys,
- unlocked_regiment_types_keys, unlocked_ship_types_keys
+ ret &= country_instances.add_item({
+ &country_definition,
+ building_type_keys,
+ technology_keys,
+ invention_keys,
+ ideology_keys,
+ government_type_keys,
+ crime_keys,
+ pop_type_keys,
+ unlocked_regiment_types_keys,
+ unlocked_ship_types_keys
});
}
- return true;
+ return ret;
}
bool CountryInstanceManager::apply_history_to_countries(