aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Hop311 <Hop3114@gmail.com>2024-07-19 21:35:22 +0200
committer GitHub <noreply@github.com>2024-07-19 21:35:22 +0200
commite0518bee9b4c164f40716a8033b5e207c2060c0b (patch)
tree6d2de5221d2b1945a065e0abba8198d8a052a92a
parenta673f89bb2705826b1c646365eab1775727372b7 (diff)
parentd8baf57d46539da9edba5952f73089bf9a54bdaf (diff)
Merge pull request #175 from OpenVicProject/unit-work
Unit position/country/leader handling + more use of unit branch templates
-rw-r--r--src/openvic-simulation/country/CountryInstance.cpp106
-rw-r--r--src/openvic-simulation/country/CountryInstance.hpp19
-rw-r--r--src/openvic-simulation/map/ProvinceInstance.cpp41
-rw-r--r--src/openvic-simulation/map/ProvinceInstance.hpp27
-rw-r--r--src/openvic-simulation/military/Deployment.cpp15
-rw-r--r--src/openvic-simulation/military/Deployment.hpp54
-rw-r--r--src/openvic-simulation/military/Leader.hpp4
-rw-r--r--src/openvic-simulation/military/UnitInstance.cpp16
-rw-r--r--src/openvic-simulation/military/UnitInstance.hpp11
-rw-r--r--src/openvic-simulation/military/UnitInstanceGroup.cpp254
-rw-r--r--src/openvic-simulation/military/UnitInstanceGroup.hpp151
-rw-r--r--src/openvic-simulation/military/UnitType.hpp13
12 files changed, 354 insertions, 357 deletions
diff --git a/src/openvic-simulation/country/CountryInstance.cpp b/src/openvic-simulation/country/CountryInstance.cpp
index 3e21bab..8d2955b 100644
--- a/src/openvic-simulation/country/CountryInstance.cpp
+++ b/src/openvic-simulation/country/CountryInstance.cpp
@@ -88,89 +88,63 @@ bool CountryInstance::remove_reform(Reform const* reform_to_remove) {
return true;
}
-void CountryInstance::add_general(General&& new_general) {
- generals.emplace(std::move(new_general));
-}
-
-bool CountryInstance::remove_general(General const* general_to_remove) {
- const auto it = generals.get_iterator(general_to_remove);
- if (it != generals.end()) {
- generals.erase(it);
+template<UnitType::branch_t Branch>
+bool CountryInstance::add_unit_instance_group(UnitInstanceGroup<Branch>& group) {
+ if (get_unit_instance_groups<Branch>().emplace(static_cast<UnitInstanceGroupBranched<Branch>*>(&group)).second) {
return true;
+ } else {
+ Logger::error(
+ "Trying to add already-existing ", Branch == UnitType::branch_t::LAND ? "army" : "navy", " ",
+ group.get_name(), " to country ", get_identifier()
+ );
+ return false;
}
-
- Logger::error(
- "Trying to remove non-existent general ", general_to_remove != nullptr ? general_to_remove->get_name() : "NULL",
- " from country ", get_identifier()
- );
- return false;
}
-void CountryInstance::add_admiral(Admiral&& new_admiral) {
- admirals.emplace(std::move(new_admiral));
-}
-
-bool CountryInstance::remove_admiral(Admiral const* admiral_to_remove) {
- const auto it = admirals.get_iterator(admiral_to_remove);
- if (it != admirals.end()) {
- admirals.erase(it);
+template<UnitType::branch_t Branch>
+bool CountryInstance::remove_unit_instance_group(UnitInstanceGroup<Branch>& group) {
+ if (get_unit_instance_groups<Branch>().erase(static_cast<UnitInstanceGroupBranched<Branch>*>(&group)) > 0) {
return true;
- }
-
- Logger::error(
- "Trying to remove non-existent admiral ", admiral_to_remove != nullptr ? admiral_to_remove->get_name() : "NULL",
- " from country ", get_identifier()
- );
- return false;
-}
-
-bool CountryInstance::add_leader(LeaderBase const& new_leader) {
- using enum UnitType::branch_t;
-
- switch (new_leader.get_branch()) {
- case LAND:
- add_general({ new_leader });
- return true;
-
- case NAVAL:
- add_admiral({ new_leader });
- return true;
-
- default:
+ } else {
Logger::error(
- "Trying to add leader ", new_leader.get_name(), " to country ", get_identifier(), " with invalid branch ",
- static_cast<uint32_t>(new_leader.get_branch())
+ "Trying to remove non-existent ", Branch == UnitType::branch_t::LAND ? "army" : "navy", " ",
+ group.get_name(), " from country ", get_identifier()
);
return false;
}
}
-bool CountryInstance::remove_leader(LeaderBase const* leader_to_remove) {
- if (leader_to_remove == nullptr) {
- Logger::error("Trying to remvoe null leader from country ", get_identifier());
- return false;
- }
-
- using enum UnitType::branch_t;
+template bool CountryInstance::add_unit_instance_group(UnitInstanceGroup<UnitType::branch_t::LAND>&);
+template bool CountryInstance::add_unit_instance_group(UnitInstanceGroup<UnitType::branch_t::NAVAL>&);
+template bool CountryInstance::remove_unit_instance_group(UnitInstanceGroup<UnitType::branch_t::LAND>&);
+template bool CountryInstance::remove_unit_instance_group(UnitInstanceGroup<UnitType::branch_t::NAVAL>&);
- switch (leader_to_remove->get_branch()) {
- case LAND:
- remove_general(static_cast<General const*>(leader_to_remove));
- return true;
+template<UnitType::branch_t Branch>
+void CountryInstance::add_leader(LeaderBranched<Branch>&& leader) {
+ get_leaders<Branch>().emplace(std::move(leader));
+}
- case NAVAL:
- remove_admiral(static_cast<Admiral const*>(leader_to_remove));
+template<UnitType::branch_t Branch>
+bool CountryInstance::remove_leader(LeaderBranched<Branch> const* leader) {
+ plf::colony<LeaderBranched<Branch>>& leaders = get_leaders<Branch>();
+ const auto it = leaders.get_iterator(leader);
+ if (it != leaders.end()) {
+ leaders.erase(it);
return true;
-
- default:
- Logger::error(
- "Trying to add leader ", leader_to_remove->get_name(), " to country ", get_identifier(), " with invalid branch ",
- static_cast<uint32_t>(leader_to_remove->get_branch())
- );
- return false;
}
+
+ Logger::error(
+ "Trying to remove non-existent ", Branch == UnitType::branch_t::LAND ? "general" : "admiral", " ",
+ leader != nullptr ? leader->get_name() : "NULL", " from country ", get_identifier()
+ );
+ return false;
}
+template void CountryInstance::add_leader(LeaderBranched<UnitType::branch_t::LAND>&&);
+template void CountryInstance::add_leader(LeaderBranched<UnitType::branch_t::NAVAL>&&);
+template bool CountryInstance::remove_leader(LeaderBranched<UnitType::branch_t::LAND> const*);
+template bool CountryInstance::remove_leader(LeaderBranched<UnitType::branch_t::NAVAL> const*);
+
bool CountryInstance::apply_history_to_country(CountryHistoryEntry const* entry) {
if (entry == nullptr) {
Logger::error("Trying to apply null country history to ", get_identifier());
diff --git a/src/openvic-simulation/country/CountryInstance.hpp b/src/openvic-simulation/country/CountryInstance.hpp
index 885a5fd..1eaf398 100644
--- a/src/openvic-simulation/country/CountryInstance.hpp
+++ b/src/openvic-simulation/country/CountryInstance.hpp
@@ -54,6 +54,11 @@ namespace OpenVic {
plf::colony<General> PROPERTY(generals);
plf::colony<Admiral> PROPERTY(admirals);
+ ordered_set<ArmyInstance*> PROPERTY(armies);
+ ordered_set<NavyInstance*> PROPERTY(navies);
+
+ UNIT_BRANCHED_GETTER(get_unit_instance_groups, armies, navies);
+ UNIT_BRANCHED_GETTER(get_leaders, generals, admirals);
CountryInstance(
CountryDefinition const* new_country_definition, decltype(technologies)::keys_t const& technology_keys,
@@ -70,13 +75,15 @@ namespace OpenVic {
bool add_reform(Reform const* new_reform);
bool remove_reform(Reform const* reform_to_remove);
- void add_general(General&& new_general);
- bool remove_general(General const* general_to_remove);
- void add_admiral(Admiral&& new_admiral);
- bool remove_admiral(Admiral const* admiral_to_remove);
+ template<UnitType::branch_t Branch>
+ bool add_unit_instance_group(UnitInstanceGroup<Branch>& group);
+ template<UnitType::branch_t Branch>
+ bool remove_unit_instance_group(UnitInstanceGroup<Branch>& group);
- bool add_leader(LeaderBase const& new_leader);
- bool remove_leader(LeaderBase const* leader_to_remove);
+ template<UnitType::branch_t Branch>
+ void add_leader(LeaderBranched<Branch>&& leader);
+ template<UnitType::branch_t Branch>
+ bool remove_leader(LeaderBranched<Branch> const* leader);
bool apply_history_to_country(CountryHistoryEntry const* entry);
};
diff --git a/src/openvic-simulation/map/ProvinceInstance.cpp b/src/openvic-simulation/map/ProvinceInstance.cpp
index 1792fe0..6b20cd2 100644
--- a/src/openvic-simulation/map/ProvinceInstance.cpp
+++ b/src/openvic-simulation/map/ProvinceInstance.cpp
@@ -104,41 +104,36 @@ void ProvinceInstance::tick(Date today) {
}
}
-bool ProvinceInstance::add_army(ArmyInstance& army) {
- if (armies.emplace(&army).second) {
+template<UnitType::branch_t Branch>
+bool ProvinceInstance::add_unit_instance_group(UnitInstanceGroup<Branch>& group) {
+ if (get_unit_instance_groups<Branch>().emplace(static_cast<UnitInstanceGroupBranched<Branch>*>(&group)).second) {
return true;
} else {
- Logger::error("Trying to add already-existing army ", army.get_name(), " to province ", get_identifier());
+ Logger::error(
+ "Trying to add already-existing ", Branch == UnitType::branch_t::LAND ? "army" : "navy", " ",
+ group.get_name(), " to province ", get_identifier()
+ );
return false;
}
}
-bool ProvinceInstance::remove_army(ArmyInstance& army) {
- if (armies.erase(&army) > 0) {
+template<UnitType::branch_t Branch>
+bool ProvinceInstance::remove_unit_instance_group(UnitInstanceGroup<Branch>& group) {
+ if (get_unit_instance_groups<Branch>().erase(static_cast<UnitInstanceGroupBranched<Branch>*>(&group)) > 0) {
return true;
} else {
- Logger::error("Trying to remove non-existent army ", army.get_name(), " from province ", get_identifier());
+ Logger::error(
+ "Trying to remove non-existent ", Branch == UnitType::branch_t::LAND ? "army" : "navy", " ",
+ group.get_name(), " from province ", get_identifier()
+ );
return false;
}
}
-bool ProvinceInstance::add_navy(NavyInstance& navy) {
- if (navies.emplace(&navy).second) {
- return true;
- } else {
- Logger::error("Trying to add already-existing navy ", navy.get_name(), " to province ", get_identifier());
- return false;
- }
-}
-
-bool ProvinceInstance::remove_navy(NavyInstance& navy) {
- if (navies.erase(&navy) > 0) {
- return true;
- } else {
- Logger::error("Trying to remove non-existent navy ", navy.get_name(), " from province ", get_identifier());
- return false;
- }
-}
+template bool ProvinceInstance::add_unit_instance_group(UnitInstanceGroup<UnitType::branch_t::LAND>&);
+template bool ProvinceInstance::add_unit_instance_group(UnitInstanceGroup<UnitType::branch_t::NAVAL>&);
+template bool ProvinceInstance::remove_unit_instance_group(UnitInstanceGroup<UnitType::branch_t::LAND>&);
+template bool ProvinceInstance::remove_unit_instance_group(UnitInstanceGroup<UnitType::branch_t::NAVAL>&);
bool ProvinceInstance::setup(BuildingTypeManager const& building_type_manager) {
if (buildings_are_locked()) {
diff --git a/src/openvic-simulation/map/ProvinceInstance.hpp b/src/openvic-simulation/map/ProvinceInstance.hpp
index 4398cd4..ec06e0c 100644
--- a/src/openvic-simulation/map/ProvinceInstance.hpp
+++ b/src/openvic-simulation/map/ProvinceInstance.hpp
@@ -58,6 +58,8 @@ namespace OpenVic {
ordered_set<ArmyInstance*> PROPERTY(armies);
ordered_set<NavyInstance*> PROPERTY(navies);
+ UNIT_BRANCHED_GETTER(get_unit_instance_groups, armies, navies);
+
std::vector<Pop> PROPERTY(pops);
Pop::pop_size_t PROPERTY(total_population);
IndexedMap<PopType, fixed_point_t> PROPERTY(pop_type_distribution);
@@ -89,31 +91,10 @@ namespace OpenVic {
void update_gamestate(Date today);
void tick(Date today);
- bool add_army(ArmyInstance& army);
- bool remove_army(ArmyInstance& army);
- bool add_navy(NavyInstance& navy);
- bool remove_navy(NavyInstance& navy);
-
template<UnitType::branch_t Branch>
- bool add_unit_instance_group(UnitInstanceGroup<Branch>& group) {
- if constexpr (Branch == UnitType::branch_t::LAND) {
- return add_army(static_cast<ArmyInstance&>(group));
- } else if constexpr (Branch == UnitType::branch_t::NAVAL) {
- return add_navy(static_cast<NavyInstance&>(group));
- } else {
- OpenVic::utility::unreachable();
- }
- }
+ bool add_unit_instance_group(UnitInstanceGroup<Branch>& group);
template<UnitType::branch_t Branch>
- bool remove_unit_instance_group(UnitInstanceGroup<Branch>& group) {
- if constexpr (Branch == UnitType::branch_t::LAND) {
- return remove_army(static_cast<ArmyInstance&>(group));
- } else if constexpr (Branch == UnitType::branch_t::NAVAL) {
- return remove_navy(static_cast<NavyInstance&>(group));
- } else {
- OpenVic::utility::unreachable();
- }
- }
+ bool remove_unit_instance_group(UnitInstanceGroup<Branch>& group);
bool setup(BuildingTypeManager const& building_type_manager);
bool apply_history_to_province(ProvinceHistoryEntry const* entry);
diff --git a/src/openvic-simulation/military/Deployment.cpp b/src/openvic-simulation/military/Deployment.cpp
index 9c89690..bd176be 100644
--- a/src/openvic-simulation/military/Deployment.cpp
+++ b/src/openvic-simulation/military/Deployment.cpp
@@ -5,20 +5,17 @@
using namespace OpenVic;
using namespace OpenVic::NodeTools;
-RegimentDeployment::RegimentDeployment(
+UnitDeployment<UnitType::branch_t::LAND>::UnitDeployment(
std::string_view new_name, RegimentType const& new_type, ProvinceDefinition const* new_home
) : name { new_name }, type { new_type }, home { new_home } {}
-ShipDeployment::ShipDeployment(std::string_view new_name, ShipType const& new_type)
+UnitDeployment<UnitType::branch_t::NAVAL>::UnitDeployment(std::string_view new_name, ShipType const& new_type)
: name { new_name }, type { new_type } {}
-ArmyDeployment::ArmyDeployment(
- std::string_view new_name, ProvinceDefinition const* new_location, std::vector<RegimentDeployment>&& new_regiments
-) : name { new_name }, location { new_location }, regiments { std::move(new_regiments) } {}
-
-NavyDeployment::NavyDeployment(
- std::string_view new_name, ProvinceDefinition const* new_location, std::vector<ShipDeployment>&& new_ships
-) : name { new_name }, location { new_location }, ships { std::move(new_ships) } {}
+template<UnitType::branch_t Branch>
+UnitDeploymentGroup<Branch>::UnitDeploymentGroup(
+ std::string_view new_name, ProvinceDefinition const* new_location, std::vector<_Unit>&& new_units
+) : name { new_name }, location { new_location }, units { std::move(new_units) } {}
Deployment::Deployment(
std::string_view new_path, std::vector<ArmyDeployment>&& new_armies, std::vector<NavyDeployment>&& new_navies,
diff --git a/src/openvic-simulation/military/Deployment.hpp b/src/openvic-simulation/military/Deployment.hpp
index 9a1d2ee..a53f101 100644
--- a/src/openvic-simulation/military/Deployment.hpp
+++ b/src/openvic-simulation/military/Deployment.hpp
@@ -5,13 +5,18 @@
#include <vector>
#include "openvic-simulation/military/Leader.hpp"
+#include "openvic-simulation/military/UnitType.hpp"
#include "openvic-simulation/types/HasIdentifier.hpp"
#include "openvic-simulation/utility/Getters.hpp"
namespace OpenVic {
struct ProvinceDefinition;
- struct RegimentDeployment {
+ template<UnitType::branch_t>
+ struct UnitDeployment;
+
+ template<>
+ struct UnitDeployment<UnitType::branch_t::LAND> {
friend struct DeploymentManager;
private:
@@ -19,57 +24,52 @@ namespace OpenVic {
RegimentType const& PROPERTY(type);
ProvinceDefinition const* PROPERTY(home);
- RegimentDeployment(std::string_view new_name, RegimentType const& new_type, ProvinceDefinition const* new_home);
+ UnitDeployment(std::string_view new_name, RegimentType const& new_type, ProvinceDefinition const* new_home);
public:
- RegimentDeployment(RegimentDeployment&&) = default;
+ UnitDeployment(UnitDeployment&&) = default;
};
- struct ShipDeployment {
+ using RegimentDeployment = UnitDeployment<UnitType::branch_t::LAND>;
+
+ template<>
+ struct UnitDeployment<UnitType::branch_t::NAVAL> {
friend struct DeploymentManager;
private:
std::string PROPERTY(name);
ShipType const& PROPERTY(type);
- ShipDeployment(std::string_view new_name, ShipType const& new_type);
+ UnitDeployment(std::string_view new_name, ShipType const& new_type);
public:
- ShipDeployment(ShipDeployment&&) = default;
+ UnitDeployment(UnitDeployment&&) = default;
};
- struct ArmyDeployment {
- friend struct DeploymentManager;
-
- private:
- std::string PROPERTY(name);
- ProvinceDefinition const* PROPERTY(location);
- std::vector<RegimentDeployment> PROPERTY(regiments);
+ using ShipDeployment = UnitDeployment<UnitType::branch_t::NAVAL>;
- ArmyDeployment(
- std::string_view new_name, ProvinceDefinition const* new_location, std::vector<RegimentDeployment>&& new_regiments
- );
-
- public:
- ArmyDeployment(ArmyDeployment&&) = default;
- };
-
- struct NavyDeployment {
+ template<UnitType::branch_t Branch>
+ struct UnitDeploymentGroup {
friend struct DeploymentManager;
+ using _Unit = UnitDeployment<Branch>;
+
private:
std::string PROPERTY(name);
ProvinceDefinition const* PROPERTY(location);
- std::vector<ShipDeployment> PROPERTY(ships);
+ std::vector<_Unit> PROPERTY(units);
- NavyDeployment(
- std::string_view new_name, ProvinceDefinition const* new_location, std::vector<ShipDeployment>&& new_ships
+ UnitDeploymentGroup(
+ std::string_view new_name, ProvinceDefinition const* new_location, std::vector<_Unit>&& new_units
);
public:
- NavyDeployment(NavyDeployment&&) = default;
+ UnitDeploymentGroup(UnitDeploymentGroup&&) = default;
};
+ using ArmyDeployment = UnitDeploymentGroup<UnitType::branch_t::LAND>;
+ using NavyDeployment = UnitDeploymentGroup<UnitType::branch_t::NAVAL>;
+
struct Deployment : HasIdentifier {
friend struct DeploymentManager;
@@ -85,6 +85,8 @@ namespace OpenVic {
public:
Deployment(Deployment&&) = default;
+
+ UNIT_BRANCHED_GETTER_CONST(get_unit_deployment_groups, armies, navies);
};
struct DefinitionManager;
diff --git a/src/openvic-simulation/military/Leader.hpp b/src/openvic-simulation/military/Leader.hpp
index 3f8603e..8a272e7 100644
--- a/src/openvic-simulation/military/Leader.hpp
+++ b/src/openvic-simulation/military/Leader.hpp
@@ -37,7 +37,7 @@ namespace OpenVic {
LeaderBase(LeaderBase&&) = default;
};
- struct CountryInstance;
+ struct UnitInstanceManager;
template<UnitType::branch_t>
struct UnitInstanceGroup;
@@ -48,7 +48,7 @@ namespace OpenVic {
template<UnitType::branch_t Branch>
struct LeaderBranched : LeaderBase {
- friend struct CountryInstance;
+ friend struct UnitInstanceManager;
friend bool UnitInstanceGroup<Branch>::set_leader(LeaderBranched<Branch>* new_leader);
private:
diff --git a/src/openvic-simulation/military/UnitInstance.cpp b/src/openvic-simulation/military/UnitInstance.cpp
index 1f49205..d9f12b9 100644
--- a/src/openvic-simulation/military/UnitInstance.cpp
+++ b/src/openvic-simulation/military/UnitInstance.cpp
@@ -2,6 +2,22 @@
using namespace OpenVic;
+template<UnitType::branch_t Branch>
+UnitInstance<Branch>::UnitInstance(std::string_view new_unit_name, _UnitType const& new_unit_type)
+ : unit_name { new_unit_name },
+ unit_type { new_unit_type },
+ organisation { new_unit_type.get_default_organisation() },
+ morale { 0 },
+ strength { new_unit_type.get_max_strength() } {}
+
+template<UnitType::branch_t Branch>
+void UnitInstance<Branch>::set_unit_name(std::string_view new_unit_name) {
+ unit_name = new_unit_name;
+}
+
+template struct OpenVic::UnitInstance<UnitType::branch_t::LAND>;
+template struct OpenVic::UnitInstance<UnitType::branch_t::NAVAL>;
+
UnitInstanceBranched<UnitType::branch_t::LAND>::UnitInstanceBranched(
std::string_view new_name, RegimentType const& new_regiment_type, Pop* new_pop
) : UnitInstance { new_name, new_regiment_type }, pop { new_pop } {}
diff --git a/src/openvic-simulation/military/UnitInstance.hpp b/src/openvic-simulation/military/UnitInstance.hpp
index 1480591..5ff4503 100644
--- a/src/openvic-simulation/military/UnitInstance.hpp
+++ b/src/openvic-simulation/military/UnitInstance.hpp
@@ -22,19 +22,12 @@ namespace OpenVic {
fixed_point_t PROPERTY_RW(strength);
protected:
- UnitInstance(std::string_view new_unit_name, _UnitType const& new_unit_type) :
- unit_name { new_unit_name },
- unit_type { new_unit_type },
- organisation { new_unit_type.get_default_organisation() }, //TODO: modifiers
- morale { 0 }, //TODO: modifiers
- strength { new_unit_type.get_max_strength() } {}
+ UnitInstance(std::string_view new_unit_name, _UnitType const& new_unit_type);
public:
UnitInstance(UnitInstance&&) = default;
- void set_unit_name(std::string_view new_unit_name) {
- unit_name = new_unit_name;
- }
+ void set_unit_name(std::string_view new_unit_name);
};
struct Pop;
diff --git a/src/openvic-simulation/military/UnitInstanceGroup.cpp b/src/openvic-simulation/military/UnitInstanceGroup.cpp
index 46fb992..80ca3a9 100644
--- a/src/openvic-simulation/military/UnitInstanceGroup.cpp
+++ b/src/openvic-simulation/military/UnitInstanceGroup.cpp
@@ -15,100 +15,179 @@ MovementInfo::MovementInfo() : path {}, movement_progress {} {}
MovementInfo::MovementInfo(ProvinceInstance const* starting_province, ProvinceInstance const* target_province)
: path { starting_province, target_province }, movement_progress { 0 } {}
-UnitInstanceGroupBranched<UnitType::branch_t::LAND>::UnitInstanceGroupBranched(
- std::string_view new_name,
- std::vector<RegimentInstance*>&& new_units,
- _Leader* new_leader,
- CountryInstance* new_country
-) : UnitInstanceGroup { new_name, std::move(new_units), new_leader, new_country } {}
+template<UnitType::branch_t Branch>
+UnitInstanceGroup<Branch>::UnitInstanceGroup(
+ std::string_view new_name, std::vector<_UnitInstance*>&& new_units
+) : name { new_name },
+ units { std::move(new_units) },
+ leader { nullptr },
+ position { nullptr },
+ country { nullptr } {}
+
+template<UnitType::branch_t Branch>
+size_t UnitInstanceGroup<Branch>::get_unit_count() const {
+ return units.size();
+}
-UnitInstanceGroupBranched<UnitType::branch_t::NAVAL>::UnitInstanceGroupBranched(
- std::string_view new_name,
- std::vector<ShipInstance*>&& new_units,
- _Leader* new_leader,
- CountryInstance* new_country
-) : UnitInstanceGroup { new_name, std::move(new_units), new_leader, new_country } {}
+template<UnitType::branch_t Branch>
+bool UnitInstanceGroup<Branch>::empty() const {
+ return units.empty();
+}
-bool UnitInstanceManager::generate_regiment(RegimentDeployment const& regiment_deployment, RegimentInstance*& regiment) {
- // TODO - get pop from Province regiment_deployment.get_home()
- RegimentInstance& regiment_instance =
- *regiments.insert({ regiment_deployment.get_name(), regiment_deployment.get_type(), nullptr });
+template<UnitType::branch_t Branch>
+size_t UnitInstanceGroup<Branch>::get_unit_category_count(UnitType::unit_category_t unit_category) const {
+ return std::count_if(units.begin(), units.end(), [unit_category](_UnitInstance const* unit) {
+ return unit->get_unit_type().get_unit_category() == unit_category;
+ });
+}
- regiment = &regiment_instance;
+template<UnitType::branch_t Branch>
+UnitType const* UnitInstanceGroup<Branch>::get_display_unit_type() const {
+ if (units.empty()) {
+ return nullptr;
+ }
- return true;
-}
+ fixed_point_map_t<UnitType const*> weighted_unit_types;
-bool UnitInstanceManager::generate_ship(ShipDeployment const& ship_deployment, ShipInstance*& ship) {
- ShipInstance& ship_instance = *ships.insert({ ship_deployment.get_name(), ship_deployment.get_type() });
+ for (_UnitInstance const* unit : units) {
+ UnitType const& unit_type = unit->get_unit_type();
+ weighted_unit_types[&unit_type] += unit_type.get_weighted_value();
+ }
- ship = &ship_instance;
+ return get_largest_item_tie_break(
+ weighted_unit_types,
+ [](UnitType const* lhs, UnitType const* rhs) -> bool {
+ return lhs->get_weighted_value() < rhs->get_weighted_value();
+ }
+ )->first;
+}
- return true;
+template<UnitType::branch_t Branch>
+void UnitInstanceGroup<Branch>::set_name(std::string_view new_name) {
+ name = new_name;
}
-bool UnitInstanceManager::generate_army(
- MapInstance& map_instance, CountryInstance& country, ArmyDeployment const& army_deployment
-) {
- if (army_deployment.get_regiments().empty()) {
- Logger::error(
- "Trying to generate army \"", army_deployment.get_name(), "\" with no regiments for country \"",
- country.get_identifier(), "\""
- );
- return false;
+template<UnitType::branch_t Branch>
+bool UnitInstanceGroup<Branch>::set_position(ProvinceInstance* new_position) {
+ bool ret = true;
+
+ if (position != new_position) {
+ if (position != nullptr) {
+ ret &= position->remove_unit_instance_group(*this);
+ }
+
+ position = new_position;
+
+ if (position != nullptr) {
+ ret &= position->add_unit_instance_group(*this);
+ }
}
- if (army_deployment.get_location() == nullptr) {
- Logger::error(
- "Trying to generate army \"", army_deployment.get_name(), "\" with no location for country \"",
- country.get_identifier(), "\""
- );
- return false;
+ return ret;
+}
+
+template<UnitType::branch_t Branch>
+bool UnitInstanceGroup<Branch>::set_country(CountryInstance* new_country) {
+ bool ret = true;
+
+ if (country != new_country) {
+ if (country != nullptr) {
+ ret &= country->remove_unit_instance_group(*this);
+ }
+
+ country = new_country;
+
+ if (country != nullptr) {
+ ret &= country->add_unit_instance_group(*this);
+ }
}
+ return ret;
+}
+
+template<UnitType::branch_t Branch>
+bool UnitInstanceGroup<Branch>::set_leader(_Leader* new_leader) {
bool ret = true;
- std::vector<RegimentInstance*> army_regiments;
+ if (leader != new_leader) {
+ if (leader != nullptr) {
+ if (leader->unit_instance_group == this) {
+ leader->unit_instance_group = nullptr;
+ } else {
+ Logger::error(
+ "Mismatch between leader and unit instance group: group ", name, " has leader ",
+ leader->get_name(), " but the leader has group ", leader->get_unit_instance_group() != nullptr
+ ? leader->get_unit_instance_group()->get_name() : "NULL"
+ );
+ ret = false;
+ }
+ }
- for (RegimentDeployment const& regiment_deployment : army_deployment.get_regiments()) {
- RegimentInstance* regiment = nullptr;
+ leader = new_leader;
- ret &= generate_regiment(regiment_deployment, regiment);
+ if (leader != nullptr) {
+ if (leader->unit_instance_group != nullptr) {
+ if (leader->unit_instance_group != this) {
+ ret &= leader->unit_instance_group->set_leader(nullptr);
+ } else {
+ Logger::error("Leader ", leader->get_name(), " already leads group ", name, "!");
+ ret = false;
+ }
+ }
- if (regiment != nullptr) {
- army_regiments.push_back(regiment);
+ leader->unit_instance_group = static_cast<UnitInstanceGroupBranched<Branch>*>(this);
}
}
- if (army_regiments.empty()) {
- Logger::error(
- "Failed to generate any regiments for army \"", army_deployment.get_name(), "\" for country \"",
- country.get_identifier(), "\""
- );
- return false;
- }
+ return ret;
+}
- ArmyInstance& army_instance = *armies.insert({ army_deployment.get_name(), std::move(army_regiments), nullptr, &country });
+template struct OpenVic::UnitInstanceGroup<UnitType::branch_t::LAND>;
+template struct OpenVic::UnitInstanceGroup<UnitType::branch_t::NAVAL>;
- army_instance.set_position(map_instance.get_province_instance_from_const(army_deployment.get_location()));
+UnitInstanceGroupBranched<UnitType::branch_t::LAND>::UnitInstanceGroupBranched(
+ std::string_view new_name,
+ std::vector<RegimentInstance*>&& new_units
+) : UnitInstanceGroup { new_name, std::move(new_units) } {}
- return ret;
+UnitInstanceGroupBranched<UnitType::branch_t::NAVAL>::UnitInstanceGroupBranched(
+ std::string_view new_name,
+ std::vector<ShipInstance*>&& new_units
+) : UnitInstanceGroup { new_name, std::move(new_units) } {}
+
+template<UnitType::branch_t Branch>
+bool UnitInstanceManager::generate_unit_instance(
+ UnitDeployment<Branch> const& unit_deployment, UnitInstanceBranched<Branch>*& unit_instance
+) {
+ unit_instance = &*get_unit_instances<Branch>().insert(
+ [&unit_deployment]() -> UnitInstanceBranched<Branch> {
+ if constexpr (Branch == UnitType::branch_t::LAND) {
+ // TODO - get pop from Province unit_deployment.get_home()
+ return { unit_deployment.get_name(), unit_deployment.get_type(), nullptr };
+ } else if constexpr (Branch == UnitType::branch_t::NAVAL) {
+ return { unit_deployment.get_name(), unit_deployment.get_type() };
+ }
+ }()
+ );
+
+ return true;
}
-bool UnitInstanceManager::generate_navy(
- MapInstance& map_instance, CountryInstance& country, NavyDeployment const& navy_deployment
+template<UnitType::branch_t Branch>
+bool UnitInstanceManager::generate_unit_instance_group(
+ MapInstance& map_instance, CountryInstance& country, UnitDeploymentGroup<Branch> const& unit_deployment_group
) {
- if (navy_deployment.get_ships().empty()) {
+ if (unit_deployment_group.get_units().empty()) {
Logger::error(
- "Trying to generate navy \"", navy_deployment.get_name(), "\" with no ships for country \"",
+ "Trying to generate unit group \"", unit_deployment_group.get_name(), "\" with no units for country \"",
country.get_identifier(), "\""
);
return false;
}
- if (navy_deployment.get_location() == nullptr) {
+ if (unit_deployment_group.get_location() == nullptr) {
Logger::error(
- "Trying to generate navy \"", navy_deployment.get_name(), "\" with no location for country \"",
+ "Trying to generate unit group \"", unit_deployment_group.get_name(), "\" with no location for country \"",
country.get_identifier(), "\""
);
return false;
@@ -116,29 +195,34 @@ bool UnitInstanceManager::generate_navy(
bool ret = true;
- std::vector<ShipInstance*> navy_ships;
+ std::vector<UnitInstanceBranched<Branch>*> unit_instances;
- for (ShipDeployment const& ship_deployment : navy_deployment.get_ships()) {
- ShipInstance* ship = nullptr;
+ for (UnitDeployment<Branch> const& unit_deployment : unit_deployment_group.get_units()) {
+ UnitInstanceBranched<Branch>* unit_instance = nullptr;
- ret &= generate_ship(ship_deployment, ship);
+ ret &= generate_unit_instance(unit_deployment, unit_instance);
- if (ship != nullptr) {
- navy_ships.push_back(ship);
+ if (unit_instance != nullptr) {
+ unit_instances.push_back(unit_instance);
}
}
- if (navy_ships.empty()) {
+ if (unit_instances.empty()) {
Logger::error(
- "Failed to generate any ships for navy \"", navy_deployment.get_name(), "\" for country \"",
+ "Failed to generate any units for unit group \"", unit_deployment_group.get_name(), "\" for country \"",
country.get_identifier(), "\""
);
return false;
}
- NavyInstance& navy_intance = *navies.insert({ navy_deployment.get_name(), std::move(navy_ships), nullptr, &country });
+ UnitInstanceGroupBranched<Branch>& unit_instance_group = *get_unit_instance_groups<Branch>().insert({
+ unit_deployment_group.get_name(), std::move(unit_instances)
+ });
- navy_intance.set_position(map_instance.get_province_instance_from_const(navy_deployment.get_location()));
+ ret &= unit_instance_group.set_position(
+ map_instance.get_province_instance_from_const(unit_deployment_group.get_location())
+ );
+ ret &= unit_instance_group.set_country(&country);
return ret;
}
@@ -153,16 +237,32 @@ bool UnitInstanceManager::generate_deployment(
bool ret = true;
- for (ArmyDeployment const& army_deployment : deployment->get_armies()) {
- ret &= generate_army(map_instance, country, army_deployment);
- }
+ const auto generate_group = [&]<UnitType::branch_t Branch>() -> void {
+ for (UnitDeploymentGroup<Branch> const& unit_deployment_group : deployment->get_unit_deployment_groups<Branch>()) {
+ ret &= generate_unit_instance_group(map_instance, country, unit_deployment_group);
+ }
+ };
- for (NavyDeployment const& navy_deployment : deployment->get_navies()) {
- ret &= generate_navy(map_instance, country, navy_deployment);
- }
+ using enum UnitType::branch_t;
+
+ generate_group.template operator()<LAND>();
+ generate_group.template operator()<NAVAL>();
for (LeaderBase const& leader : deployment->get_leaders()) {
- ret &= country.add_leader(leader);
+ switch (leader.get_branch()) {
+ case LAND:
+ country.add_leader<LAND>({ leader });
+ break;
+ case NAVAL:
+ country.add_leader<NAVAL>({ leader });
+ break;
+ default:
+ Logger::error(
+ "Invalid branch ", static_cast<uint64_t>(leader.get_branch()), " for leader \"", leader.get_name(),
+ "\", cannot add to country ", country.get_identifier()
+ );
+ ret = false;
+ }
}
return ret;
diff --git a/src/openvic-simulation/military/UnitInstanceGroup.hpp b/src/openvic-simulation/military/UnitInstanceGroup.hpp
index 54aac3d..4fe0cba 100644
--- a/src/openvic-simulation/military/UnitInstanceGroup.hpp
+++ b/src/openvic-simulation/military/UnitInstanceGroup.hpp
@@ -6,11 +6,10 @@
#include <plf_colony.h>
-#include "openvic-simulation/map/ProvinceInstance.hpp"
#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"
-#include "openvic-simulation/utility/Utility.hpp"
namespace OpenVic {
struct ProvinceInstance;
@@ -31,9 +30,6 @@ namespace OpenVic {
struct CountryInstance;
- template<UnitType::branch_t>
- struct UnitInstanceGroupBranched;
-
template<UnitType::branch_t Branch>
struct UnitInstanceGroup {
using _UnitInstance = UnitInstanceBranched<Branch>;
@@ -52,110 +48,27 @@ namespace OpenVic {
UnitInstanceGroup(
std::string_view new_name,
- std::vector<_UnitInstance*>&& new_units,
- _Leader* new_leader,
- CountryInstance* new_country
- ) : name { new_name },
- units { std::move(new_units) },
- leader { nullptr },
- position { nullptr },
- country { new_country } {
- set_leader(new_leader);
- }
+ std::vector<_UnitInstance*>&& new_units
+ );
public:
UnitInstanceGroup(UnitInstanceGroup&&) = default;
UnitInstanceGroup(UnitInstanceGroup const&) = delete;
- void set_name(std::string_view new_name) {
- name = new_name;
- }
-
- size_t get_unit_count() const {
- return units.size();
- }
-
- bool empty() const {
- return units.empty();
- }
-
- size_t get_unit_category_count(UnitType::unit_category_t unit_category) const {
- return std::count_if(units.begin(), units.end(), [unit_category](_UnitInstance const* unit) {
- return unit->unit_type.get_unit_category() == unit_category;
- });
- }
-
- UnitType const* get_display_unit_type() const {
- if (units.empty()) {
- return nullptr;
- }
-
- fixed_point_map_t<UnitType const*> weighted_unit_types;
-
- for (_UnitInstance const* unit : units) {
- UnitType const& unit_type = unit->get_unit_type();
- weighted_unit_types[&unit_type] += unit_type.get_weighted_value();
- }
-
- return get_largest_item_tie_break(
- weighted_unit_types,
- [](UnitType const* lhs, UnitType const* rhs) -> bool {
- return lhs->get_weighted_value() < rhs->get_weighted_value();
- }
- )->first;
- }
-
- void set_position(ProvinceInstance* new_position) {
- if (position != new_position) {
- if (position != nullptr) {
- position->remove_unit_instance_group(*this);
- }
-
- position = new_position;
-
- if (position != nullptr) {
- position->add_unit_instance_group(*this);
- }
- }
- }
-
- bool set_leader(_Leader* new_leader) {
- bool ret = true;
-
- if (leader != new_leader) {
- if (leader != nullptr) {
- if (leader->unit_instance_group == this) {
- leader->unit_instance_group = nullptr;
- } else {
- Logger::error(
- "Mismatch between leader and unit instance group: group ", name, " has leader ",
- leader->get_name(), " but the leader has group ", leader->get_unit_instance_group() != nullptr
- ? leader->get_unit_instance_group()->get_name() : "NULL"
- );
- ret = false;
- }
- }
-
- leader = new_leader;
-
- if (leader != nullptr) {
- if (leader->unit_instance_group != nullptr) {
- if (leader->unit_instance_group != this) {
- ret &= leader->unit_instance_group->set_leader(nullptr);
- } else {
- Logger::error("Leader ", leader->get_name(), " already leads group ", name, "!");
- ret = false;
- }
- }
-
- leader->unit_instance_group = static_cast<UnitInstanceGroupBranched<Branch>*>(this);
- }
- }
-
- return ret;
- }
+ 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;
@@ -163,9 +76,7 @@ namespace OpenVic {
private:
UnitInstanceGroupBranched(
std::string_view new_name,
- std::vector<RegimentInstance*>&& new_units,
- _Leader* new_leader,
- CountryInstance* new_country
+ std::vector<RegimentInstance*>&& new_units
);
public:
@@ -183,9 +94,7 @@ namespace OpenVic {
UnitInstanceGroupBranched(
std::string_view new_name,
- std::vector<ShipInstance*>&& new_ships,
- _Leader* new_leader,
- CountryInstance* new_country
+ std::vector<ShipInstance*>&& new_ships
);
public:
@@ -194,11 +103,13 @@ namespace OpenVic {
using NavyInstance = UnitInstanceGroupBranched<UnitType::branch_t::NAVAL>;
- struct RegimentDeployment;
- struct ShipDeployment;
+ template<UnitType::branch_t>
+ struct UnitDeployment;
+
+ template<UnitType::branch_t>
+ struct UnitDeploymentGroup;
+
struct MapInstance;
- struct ArmyDeployment;
- struct NavyDeployment;
struct Deployment;
struct UnitInstanceManager {
@@ -206,13 +117,21 @@ namespace OpenVic {
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);
- bool generate_regiment(RegimentDeployment const& regiment_deployment, RegimentInstance*& regiment);
- bool generate_ship(ShipDeployment const& ship_deployment, ShipInstance*& ship);
- bool generate_army(MapInstance& map_instance, CountryInstance& country, ArmyDeployment const& army_deployment);
- bool generate_navy(MapInstance& map_instance, CountryInstance& country, NavyDeployment const& navy_deployment);
+ 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);
diff --git a/src/openvic-simulation/military/UnitType.hpp b/src/openvic-simulation/military/UnitType.hpp
index 1642f22..6bd7392 100644
--- a/src/openvic-simulation/military/UnitType.hpp
+++ b/src/openvic-simulation/military/UnitType.hpp
@@ -74,6 +74,19 @@ namespace OpenVic {
UnitType(UnitType&&) = default;
};
+#define _UNIT_BRANCHED_GETTER(name, land, naval, const) \
+ template<UnitType::branch_t Branch> \
+ constexpr auto const& name() const { \
+ if constexpr (Branch == UnitType::branch_t::LAND) { \
+ return land; \
+ } else if constexpr (Branch == UnitType::branch_t::NAVAL) { \
+ return naval; \
+ } \
+ }
+
+#define UNIT_BRANCHED_GETTER(name, land, naval) _UNIT_BRANCHED_GETTER(name, land, naval, )
+#define UNIT_BRANCHED_GETTER_CONST(name, land, naval) _UNIT_BRANCHED_GETTER(name, land, naval, const)
+
template<UnitType::branch_t>
struct UnitTypeBranched;