aboutsummaryrefslogtreecommitdiff
path: root/src/openvic-simulation/economy/GoodDefinition.cpp
blob: fcaae114e8a6446e255294a5ec29cec3bb12b955 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
#include "GoodDefinition.hpp"

#include "openvic-simulation/modifier/Modifier.hpp"

using namespace OpenVic;
using namespace OpenVic::NodeTools;

GoodCategory::GoodCategory(std::string_view new_identifier) : HasIdentifier { new_identifier } {}

GoodDefinition::GoodDefinition(
   std::string_view new_identifier,
   colour_t new_colour,
   index_t new_index,
   GoodCategory const& new_category,
   fixed_point_t new_base_price,
   bool new_available_from_start,
   bool new_tradeable,
   bool new_money,
   bool new_overseas_penalty
) : HasIdentifierAndColour { new_identifier, new_colour, false },
   HasIndex { new_index },
   category { new_category },
   base_price { new_base_price },
   available_from_start { new_available_from_start },
   tradeable { new_tradeable },
   money { new_money },
   overseas_penalty { new_overseas_penalty } {}

bool GoodDefinitionManager::add_good_category(std::string_view identifier) {
   if (identifier.empty()) {
      Logger::error("Invalid good category identifier - empty!");
      return false;
   }
   return good_categories.add_item({ identifier });
}

bool GoodDefinitionManager::add_good_definition(
   std::string_view identifier, colour_t colour, GoodCategory const& category, fixed_point_t base_price,
   bool available_from_start, bool tradeable, bool money, bool overseas_penalty
) {
   if (identifier.empty()) {
      Logger::error("Invalid good identifier - empty!");
      return false;
   }
   if (base_price <= 0) {
      Logger::error("Invalid base price for ", identifier, ": ", base_price);
      return false;
   }
   return good_definitions.add_item({
      identifier, colour, get_good_definition_count(), category, base_price, available_from_start,
      tradeable, money, overseas_penalty
   });
}

bool GoodDefinitionManager::load_goods_file(ast::NodeCPtr root) {
   size_t total_expected_goods = 0;
   bool ret = expect_dictionary_reserve_length(
      good_categories,
      [this, &total_expected_goods](std::string_view key, ast::NodeCPtr value) -> bool {
         bool ret = expect_length(add_variable_callback(total_expected_goods))(value);
         ret &= add_good_category(key);
         return ret;
      }
   )(root);
   lock_good_categories();
   reserve_more_good_definitions(total_expected_goods);
   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 = colour_t::null();
         fixed_point_t base_price;
         bool available_from_start = true, tradeable = true;
         bool money = false, overseas_penalty = false;

         bool ret = expect_dictionary_keys(
            "color", ONE_EXACTLY, expect_colour(assign_variable_callback(colour)),
            "cost", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(base_price)),
            "available_from_start", ZERO_OR_ONE, expect_bool(assign_variable_callback(available_from_start)),
            "tradeable", ZERO_OR_ONE, expect_bool(assign_variable_callback(tradeable)),
            "money", ZERO_OR_ONE, expect_bool(assign_variable_callback(money)),
            "overseas_penalty", ZERO_OR_ONE, expect_bool(assign_variable_callback(overseas_penalty))
         )(value);
         ret &= add_good_definition(
            key, colour, good_category, base_price, available_from_start, tradeable, money, overseas_penalty
         );
         return ret;
      })(good_category_value);
   })(root);
   lock_good_definitions();
   return ret;
}

bool GoodDefinitionManager::generate_modifiers(ModifierManager& modifier_manager) const {
   using enum ModifierEffect::format_t;
   using enum ModifierEffect::target_t;

   bool ret = true;

   const auto good_modifier = [this, &modifier_manager, &ret](
      std::string_view name, bool is_positive_good, auto make_localisation_suffix
   ) -> void {
      ret &= modifier_manager.register_complex_modifier(name);

      for (GoodDefinition const& good : get_good_definitions()) {
         ret &= modifier_manager.add_modifier_effect(
            ModifierManager::get_flat_identifier(name, good.get_identifier()), is_positive_good, PROPORTION_DECIMAL,
            COUNTRY, make_localisation_suffix(good.get_identifier())
         );
      }
   };

   const auto make_production_localisation_suffix = [](std::string_view localisation_suffix) -> auto {
      return [localisation_suffix](std::string_view good_identifier) -> std::string {
         return StringUtils::append_string_views("$", good_identifier,  "$ $", localisation_suffix, "$");
      };
   };

   good_modifier("artisan_goods_input", false, make_production_localisation_suffix("TECH_INPUT"));
   good_modifier("artisan_goods_output", true, make_production_localisation_suffix("TECH_OUTPUT"));
   good_modifier("artisan_goods_throughput", true, make_production_localisation_suffix("TECH_THROUGHPUT"));
   good_modifier("factory_goods_input", false, make_production_localisation_suffix("TECH_INPUT"));
   good_modifier("factory_goods_output", true, make_production_localisation_suffix("TECH_OUTPUT"));
   good_modifier("factory_goods_throughput", true, make_production_localisation_suffix("TECH_THROUGHPUT"));
   good_modifier("rgo_goods_output", true, make_production_localisation_suffix("TECH_OUTPUT"));
   good_modifier("rgo_goods_throughput", true, make_production_localisation_suffix("TECH_THROUGHPUT"));
   good_modifier("rgo_size", true, [](std::string_view good_identifier) -> std::string {
      return StringUtils::append_string_views(good_identifier, "_RGO_SIZE");
   });

   return ret;
}