aboutsummaryrefslogtreecommitdiff
path: root/src/openvic-simulation/politics/Rule.hpp
blob: 518c555168d65ce6f69b2cb28fe46d58741e5383 (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
#pragma once

#include "openvic-simulation/types/IdentifierRegistry.hpp"
#include "openvic-simulation/types/OrderedContainers.hpp"

namespace OpenVic {
   struct RuleManager;
   struct BuildingTypeManager;

   /* The index of the Rule within its group, used to determine precedence in mutually exclusive rule groups. */
   struct Rule : HasIdentifier, HasIndex<> {
      friend struct RuleManager;

      enum class rule_group_t : uint8_t {
         ECONOMY, CITIZENSHIP, SLAVERY, UPPER_HOUSE, VOTING
      };

      static constexpr bool is_mutually_exclusive_group(rule_group_t group) {
         using enum rule_group_t;
         return group == CITIZENSHIP || group == UPPER_HOUSE || group == VOTING;
      }

      /* Mutually exclusive groups must be default disabled! */
      static constexpr bool is_default_enabled(rule_group_t group) {
         using enum rule_group_t;
         return !is_mutually_exclusive_group(group) && group != SLAVERY;
      }

   private:
      const rule_group_t PROPERTY(group);

      Rule(std::string_view new_identifier, rule_group_t new_group, index_t new_index);

   public:
      Rule(Rule&&) = default;
   };

   struct RuleSet {
      friend struct RuleManager;

      using rule_map_t = ordered_map<Rule const*, bool>;
      using rule_group_map_t = ordered_map<Rule::rule_group_t, rule_map_t>;

   private:
      rule_group_map_t rule_groups;

   public:
      RuleSet() = default;
      RuleSet(rule_group_map_t&& new_rule_groups);
      RuleSet(RuleSet const&) = default;
      RuleSet(RuleSet&&) = default;

      RuleSet& operator=(RuleSet const&) = default;
      RuleSet& operator=(RuleSet&&) = default;

      /* Removes conflicting and disabled mutually exclusive rules. If log is true, a warning will be emitted for each
       * removed disabled rule and an error will be emitted for each removed conflicting rule. Returns true if no conflicts
       * are found (regardless of whether disabled rules are removed or not), false otherwise. */
      bool trim_and_resolve_conflicts(bool log);
      size_t get_rule_group_count() const;
      size_t get_rule_count() const;

      rule_map_t const& get_rule_group(Rule::rule_group_t group, bool* successful = nullptr) const;
      bool get_rule(Rule const* rule, bool* successful = nullptr) const;
      bool has_rule(Rule const* rule) const;

      /* Sets the rule to the specified value. Returns false if there was an existing rule, regardless of its value. */
      bool set_rule(Rule const* rule, bool value);

      RuleSet& operator|=(RuleSet const& right);
      RuleSet operator|(RuleSet const& right) const;

      friend std::ostream& operator<<(std::ostream& stream, RuleSet const& value);
   };

   struct RuleManager {
   private:
      IdentifierRegistry<Rule> IDENTIFIER_REGISTRY(rule);
      ordered_map<Rule::rule_group_t, size_t> rule_group_sizes;

   public:
      bool add_rule(std::string_view identifier, Rule::rule_group_t group);

      bool setup_rules(BuildingTypeManager const& building_type_manager);

      NodeTools::node_callback_t expect_rule_set(NodeTools::callback_t<RuleSet&&> ruleset_callback) const;
   };
}