aboutsummaryrefslogtreecommitdiff
path: root/src/openvic-simulation/military/UnitInstanceGroup.hpp
blob: 78ff289703a07d5fd1af6b2b21604b88db476a0a (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
131
132
133
134
135
136
137
138
139
140
141
#pragma once

#include <string>
#include <string_view>
#include <vector>

#include <plf_colony.h>

#include "openvic-simulation/military/UnitInstance.hpp"
#include "openvic-simulation/military/UnitType.hpp"
#include "openvic-simulation/types/fixed_point/FixedPoint.hpp"
#include "openvic-simulation/utility/Getters.hpp"

namespace OpenVic {
   struct ProvinceInstance;

   struct MovementInfo {
   private:
      std::vector<ProvinceInstance const*> PROPERTY(path);
      fixed_point_t PROPERTY(movement_progress);

   public:
      MovementInfo();
      // contains/calls pathfinding logic
      MovementInfo(ProvinceInstance const* starting_province, ProvinceInstance const* target_province);
   };

   template<UnitType::branch_t>
   struct LeaderBranched;

   struct CountryInstance;

   template<UnitType::branch_t Branch>
   struct UnitInstanceGroup {
      using _UnitInstance = UnitInstanceBranched<Branch>;
      using _Leader = LeaderBranched<Branch>;

   private:
      std::string PROPERTY(name);
      std::vector<_UnitInstance*> PROPERTY(units);
      _Leader* PROPERTY(leader);

      MovementInfo PROPERTY_REF(movement_info);

   protected:
      ProvinceInstance* PROPERTY_ACCESS(position, protected);
      CountryInstance* PROPERTY_ACCESS(country, protected);

      UnitInstanceGroup(
         std::string_view new_name,
         std::vector<_UnitInstance*>&& new_units
      );

   public:
      UnitInstanceGroup(UnitInstanceGroup&&) = default;
      UnitInstanceGroup(UnitInstanceGroup const&) = delete;

      size_t get_unit_count() const;
      bool empty() const;
      size_t get_unit_category_count(UnitType::unit_category_t unit_category) const;
      UnitType const* get_display_unit_type() const;

      void set_name(std::string_view new_name);
      bool set_position(ProvinceInstance* new_position);
      bool set_country(CountryInstance* new_country);
      bool set_leader(_Leader* new_leader);
   };

   template<UnitType::branch_t>
   struct UnitInstanceGroupBranched;

   template<>
   struct UnitInstanceGroupBranched<UnitType::branch_t::LAND> : UnitInstanceGroup<UnitType::branch_t::LAND> {
      friend struct UnitInstanceManager;

   private:
      UnitInstanceGroupBranched(
         std::string_view new_name,
         std::vector<RegimentInstance*>&& new_units
      );

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

   using ArmyInstance = UnitInstanceGroupBranched<UnitType::branch_t::LAND>;

   template<>
   struct UnitInstanceGroupBranched<UnitType::branch_t::NAVAL> : UnitInstanceGroup<UnitType::branch_t::NAVAL> {
      friend struct UnitInstanceManager;

   private:
      std::vector<ArmyInstance*> PROPERTY(carried_armies);

      UnitInstanceGroupBranched(
         std::string_view new_name,
         std::vector<ShipInstance*>&& new_ships
      );

   public:
      UnitInstanceGroupBranched(UnitInstanceGroupBranched&&) = default;

      fixed_point_t get_total_consumed_supply() const;
   };

   using NavyInstance = UnitInstanceGroupBranched<UnitType::branch_t::NAVAL>;

   template<UnitType::branch_t>
   struct UnitDeployment;

   template<UnitType::branch_t>
   struct UnitDeploymentGroup;

   struct MapInstance;
   struct Deployment;

   struct UnitInstanceManager {
   private:
      plf::colony<RegimentInstance> PROPERTY(regiments);
      plf::colony<ShipInstance> PROPERTY(ships);

      UNIT_BRANCHED_GETTER(get_unit_instances, regiments, ships);

      plf::colony<ArmyInstance> PROPERTY(armies);
      plf::colony<NavyInstance> PROPERTY(navies);

      UNIT_BRANCHED_GETTER(get_unit_instance_groups, armies, navies);

      template<UnitType::branch_t Branch>
      bool generate_unit_instance(
         UnitDeployment<Branch> const& unit_deployment, UnitInstanceBranched<Branch>*& unit_instance
      );
      template<UnitType::branch_t Branch>
      bool generate_unit_instance_group(
         MapInstance& map_instance, CountryInstance& country, UnitDeploymentGroup<Branch> const& unit_deployment_group
      );

   public:
      bool generate_deployment(MapInstance& map_instance, CountryInstance& country, Deployment const* deployment);
   };
}