From eac76ba7c8dc714535c67b8febef3168b1670caf Mon Sep 17 00:00:00 2001 From: hop311 Date: Wed, 18 Sep 2024 23:37:35 +0100 Subject: Add ModifierSum and improve ModifierValue --- src/openvic-simulation/misc/Modifier.cpp | 95 +++++++++++++++++++++++++++++++- src/openvic-simulation/misc/Modifier.hpp | 38 ++++++++++++- 2 files changed, 127 insertions(+), 6 deletions(-) diff --git a/src/openvic-simulation/misc/Modifier.cpp b/src/openvic-simulation/misc/Modifier.cpp index e201fdd..333bb20 100644 --- a/src/openvic-simulation/misc/Modifier.cpp +++ b/src/openvic-simulation/misc/Modifier.cpp @@ -49,7 +49,7 @@ bool ModifierValue::empty() const { return values.empty(); } -fixed_point_t ModifierValue::get_effect(ModifierEffect const* effect, bool* successful) { +fixed_point_t ModifierValue::get_effect(ModifierEffect const* effect, bool* successful) const { const effect_map_t::const_iterator it = values.find(effect); if (it != values.end()) { if (successful != nullptr) { @@ -67,6 +67,14 @@ bool ModifierValue::has_effect(ModifierEffect const* effect) const { return values.contains(effect); } +void ModifierValue::set_effect(ModifierEffect const* effect, fixed_point_t value) { + if (effect != nullptr) { + values[effect] = value; + } else { + Logger::error("Tried to set null modifier effect on ModifierValue!"); + } +} + ModifierValue& ModifierValue::operator+=(ModifierValue const& right) { for (effect_map_t::value_type const& value : right.values) { values[value.first] += value.second; @@ -99,6 +107,32 @@ ModifierValue ModifierValue::operator-(ModifierValue const& right) const { return ret -= right; } +ModifierValue& ModifierValue::operator*=(fixed_point_t const& right) { + for (auto value : mutable_iterator(values)) { + value.second *= right; + } + return *this; +} + +ModifierValue ModifierValue::operator*(fixed_point_t const& right) const { + ModifierValue ret = *this; + return ret *= right; +} + +fixed_point_t& ModifierValue::operator[](ModifierEffect const* effect) { + return values[effect]; +} + +void ModifierValue::multiply_add(ModifierValue const& other, fixed_point_t multiplier) { + if (multiplier == fixed_point_t::_1()) { + *this += other; + } else if (multiplier != fixed_point_t::_0()) { + for (effect_map_t::value_type const& value : other.values) { + values[value.first] += value.second * multiplier; + } + } +} + Modifier::Modifier(std::string_view new_identifier, ModifierValue&& new_values, icon_t new_icon) : HasIdentifier { new_identifier }, ModifierValue { std::move(new_values) }, icon { new_icon } {} @@ -110,8 +144,63 @@ bool TriggeredModifier::parse_scripts(DefinitionManager const& definition_manage return trigger.parse_script(false, definition_manager); } -ModifierInstance::ModifierInstance(Modifier const& modifier, Date expiry_date) - : modifier { modifier }, expiry_date { expiry_date } {} +ModifierInstance::ModifierInstance(Modifier const& new_modifier, Date new_expiry_date) + : modifier { &new_modifier }, expiry_date { new_expiry_date } {} + +void ModifierSum::clear() { + modifiers.clear(); + value_sum.clear(); +} + +bool ModifierSum::empty() { + return modifiers.empty(); +} + +fixed_point_t ModifierSum::get_effect(ModifierEffect const* effect, bool* successful) const { + return value_sum.get_effect(effect, successful); +} + +bool ModifierSum::has_effect(ModifierEffect const* effect) const { + return value_sum.has_effect(effect); +} + +void ModifierSum::add_modifier(Modifier const& modifier, fixed_point_t multiplier) { + modifiers[&modifier] += multiplier; + value_sum.multiply_add(modifier, multiplier); +} + +void ModifierSum::add_modifier_sum(ModifierSum const& modifier_sum) { + modifiers += modifier_sum.modifiers; + value_sum += modifier_sum.value_sum; +} + +ModifierSum& ModifierSum::operator+=(Modifier const& modifier) { + add_modifier(modifier); + return *this; +} + +ModifierSum& ModifierSum::operator+=(ModifierSum const& modifier_sum) { + add_modifier_sum(modifier_sum); + return *this; +} + +// TODO - include value_sum[effect] in result? Early return if lookup in value_sum fails? +std::vector> ModifierSum::get_contributing_modifiers( + ModifierEffect const* effect +) const { + std::vector> ret; + + for (auto const& [modifier, multiplier] : modifiers) { + bool successful = false; + const fixed_point_t value = modifier->get_effect(effect, &successful); + + if (successful) { + ret.emplace_back(modifier, value * multiplier); + } + } + + return ret; +} bool ModifierManager::add_modifier_effect( std::string_view identifier, bool positive_good, ModifierEffect::format_t format, std::string_view localisation_key diff --git a/src/openvic-simulation/misc/Modifier.hpp b/src/openvic-simulation/misc/Modifier.hpp index f3cc0f6..c36585f 100644 --- a/src/openvic-simulation/misc/Modifier.hpp +++ b/src/openvic-simulation/misc/Modifier.hpp @@ -57,14 +57,21 @@ namespace OpenVic { void clear(); bool empty() const; - fixed_point_t get_effect(ModifierEffect const* effect, bool* successful = nullptr); + fixed_point_t get_effect(ModifierEffect const* effect, bool* successful = nullptr) const; bool has_effect(ModifierEffect const* effect) const; + void set_effect(ModifierEffect const* effect, fixed_point_t value); ModifierValue& operator+=(ModifierValue const& right); ModifierValue operator+(ModifierValue const& right) const; ModifierValue operator-() const; ModifierValue& operator-=(ModifierValue const& right); ModifierValue operator-(ModifierValue const& right) const; + ModifierValue& operator*=(fixed_point_t const& right); + ModifierValue operator*(fixed_point_t const& right) const; + + fixed_point_t& operator[](ModifierEffect const* effect); + + void multiply_add(ModifierValue const& other, fixed_point_t multiplier); friend std::ostream& operator<<(std::ostream& stream, ModifierValue const& value); }; @@ -105,10 +112,35 @@ namespace OpenVic { struct ModifierInstance { private: - Modifier const& PROPERTY(modifier); + Modifier const* PROPERTY(modifier); // We can assume this is never null Date PROPERTY(expiry_date); - ModifierInstance(Modifier const& modifier, Date expiry_date); + public: + ModifierInstance(Modifier const& new_modifier, Date new_expiry_date); + }; + + struct ModifierSum { + private: + fixed_point_map_t PROPERTY(modifiers); + ModifierValue PROPERTY(value_sum); + + public: + ModifierSum() = default; + ModifierSum(ModifierSum&&) = default; + + void clear(); + bool empty(); + + fixed_point_t get_effect(ModifierEffect const* effect, bool* successful = nullptr) const; + bool has_effect(ModifierEffect const* effect) const; + + void add_modifier(Modifier const& modifier, fixed_point_t multiplier = fixed_point_t::_1()); + void add_modifier_sum(ModifierSum const& modifier_sum); + + ModifierSum& operator+=(Modifier const& modifier); + ModifierSum& operator+=(ModifierSum const& modifier_sum); + + std::vector> get_contributing_modifiers(ModifierEffect const* effect) const; }; template -- cgit v1.2.3-56-ga3b1