diff --git a/src/openvic-simulation/InstanceManager.cpp b/src/openvic-simulation/InstanceManager.cpp index 0b94ab46..15115dd1 100644 --- a/src/openvic-simulation/InstanceManager.cpp +++ b/src/openvic-simulation/InstanceManager.cpp @@ -24,6 +24,7 @@ InstanceManager::InstanceManager( good_instance_manager }, artisanal_producer_deps { + new_definition_manager.get_define_manager().get_economy_defines(), new_definition_manager.get_modifier_manager().get_modifier_effect_cache() }, country_instance_deps { diff --git a/src/openvic-simulation/economy/production/ArtisanalProducer.cpp b/src/openvic-simulation/economy/production/ArtisanalProducer.cpp index 534767dd..6f8071a1 100644 --- a/src/openvic-simulation/economy/production/ArtisanalProducer.cpp +++ b/src/openvic-simulation/economy/production/ArtisanalProducer.cpp @@ -4,6 +4,7 @@ #include #include "openvic-simulation/country/CountryInstance.hpp" +#include "openvic-simulation/defines/EconomyDefines.hpp" #include "openvic-simulation/economy/GoodDefinition.hpp" #include "openvic-simulation/economy/GoodInstance.hpp" #include "openvic-simulation/economy/production/ProductionType.hpp" @@ -24,7 +25,8 @@ ArtisanalProducer::ArtisanalProducer( fixed_point_map_t&& new_stockpile, ProductionType const* const new_production_type, fixed_point_t new_current_production -) : modifier_effect_cache { artisanal_producer_deps.modifier_effect_cache }, +) : economy_defines { artisanal_producer_deps.economy_defines }, + modifier_effect_cache { artisanal_producer_deps.modifier_effect_cache }, stockpile { std::move(new_stockpile) }, production_type_nullable { nullptr }, current_production { new_current_production } @@ -374,9 +376,10 @@ ProductionType const* ArtisanalProducer::pick_production_type( const fixed_point_t revenue = pop.get_artisanal_revenue(); const fixed_point_t costs = costs_of_production; + const fixed_point_t base_chance_to_switch_while_profitable = economy_defines.get_goods_focus_swap_chance(); if (production_type_nullable == nullptr || (revenue <= costs)) { should_pick_new_production_type = true; - } else { + } else if (base_chance_to_switch_while_profitable > 0) { const fixed_point_t current_score = calculate_production_type_score( revenue, costs, @@ -406,8 +409,26 @@ ProductionType const* ArtisanalProducer::pick_production_type( } } - //TODO decide based on score and randomness and defines.economy.GOODS_FOCUS_SWAP_CHANCE - should_pick_new_production_type = relative_score < fixed_point_t::_0_50; + //picked so the line hits 0 at relative_score = 2/3 and the area under the curve equals 1 + //2/3 was picked as being in the top 1/3 of production types makes it very unlikely you'll profit from switching. + constexpr fixed_point_t slope = fixed_point_t{-9} / 2; + constexpr fixed_point_t offset = 3; + + const fixed_point_t change_modifier_from_relative_score = std::max(fixed_point_t::_0, slope * relative_score + offset); + const fixed_point_t switch_chance = base_chance_to_switch_while_profitable * change_modifier_from_relative_score; + if (switch_chance >= 1) { + should_pick_new_production_type = true; + } else { + constexpr fixed_point_t weights_sum = 1; + const fixed_point_t keep_current_chance = weights_sum - switch_chance; + const std::array weights { keep_current_chance, switch_chance }; + const size_t should_switch = sample_weighted_index( + random_number_generator(), + weights, + weights_sum + ); + should_pick_new_production_type = should_switch == 1; + } } if (!should_pick_new_production_type) { diff --git a/src/openvic-simulation/economy/production/ArtisanalProducer.hpp b/src/openvic-simulation/economy/production/ArtisanalProducer.hpp index e0941111..7f56e049 100644 --- a/src/openvic-simulation/economy/production/ArtisanalProducer.hpp +++ b/src/openvic-simulation/economy/production/ArtisanalProducer.hpp @@ -10,6 +10,7 @@ namespace OpenVic { struct ArtisanalProducerDeps; + struct EconomyDefines; struct GoodDefinition; struct GoodInstanceManager; struct ModifierEffectCache; @@ -21,6 +22,7 @@ namespace OpenVic { struct ArtisanalProducer { private: + EconomyDefines const& economy_defines; ModifierEffectCache const& modifier_effect_cache; fixed_point_map_t stockpile; diff --git a/src/openvic-simulation/economy/production/ArtisanalProducerDeps.hpp b/src/openvic-simulation/economy/production/ArtisanalProducerDeps.hpp index d41b6516..c3f9a169 100644 --- a/src/openvic-simulation/economy/production/ArtisanalProducerDeps.hpp +++ b/src/openvic-simulation/economy/production/ArtisanalProducerDeps.hpp @@ -1,9 +1,11 @@ #pragma once namespace OpenVic { + struct EconomyDefines; struct ModifierEffectCache; struct ArtisanalProducerDeps { + EconomyDefines const& economy_defines; ModifierEffectCache const& modifier_effect_cache; }; } \ No newline at end of file diff --git a/src/openvic-simulation/utility/WeightedSampling.hpp b/src/openvic-simulation/utility/WeightedSampling.hpp index e200a88b..f41c1fcb 100644 --- a/src/openvic-simulation/utility/WeightedSampling.hpp +++ b/src/openvic-simulation/utility/WeightedSampling.hpp @@ -9,7 +9,7 @@ namespace OpenVic { OV_ALWAYS_INLINE static size_t sample_weighted_index( const uint32_t random_value, - const std::span positive_weights, + const std::span positive_weights, const fixed_point_t weights_sum ) { if (positive_weights.empty() || weights_sum <= 0) {