aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
author Hop311 <Hop3114@gmail.com>2024-07-14 17:37:10 +0200
committer GitHub <noreply@github.com>2024-07-14 17:37:10 +0200
commite8a3b33f13ebdf3a388b4996308b4db9763dc375 (patch)
treedb365e5d71df41b7b35abdcc3d4c0d76f1653619 /src
parentb9b35ad9536cfdcd61f5208eeaad7ead4bd0418d (diff)
parente4701ebc08f57575a02bdc1777d9851a987c1cba (diff)
Merge pull request #173 from OpenVicProject/unit-colonies
Unit and leader rework (branch based templates and colony containers)
Diffstat (limited to 'src')
-rw-r--r--src/openvic-simulation/InstanceManager.cpp9
-rw-r--r--src/openvic-simulation/InstanceManager.hpp2
-rw-r--r--src/openvic-simulation/country/CountryInstance.cpp93
-rw-r--r--src/openvic-simulation/country/CountryInstance.hpp15
-rw-r--r--src/openvic-simulation/map/ProvinceInstance.cpp2
-rw-r--r--src/openvic-simulation/map/ProvinceInstance.hpp34
-rw-r--r--src/openvic-simulation/military/Deployment.cpp10
-rw-r--r--src/openvic-simulation/military/Deployment.hpp9
-rw-r--r--src/openvic-simulation/military/Leader.cpp4
-rw-r--r--src/openvic-simulation/military/Leader.hpp47
-rw-r--r--src/openvic-simulation/military/UnitInstance.cpp197
-rw-r--r--src/openvic-simulation/military/UnitInstance.hpp174
-rw-r--r--src/openvic-simulation/military/UnitInstanceGroup.cpp169
-rw-r--r--src/openvic-simulation/military/UnitInstanceGroup.hpp220
-rw-r--r--src/openvic-simulation/military/UnitType.cpp4
-rw-r--r--src/openvic-simulation/military/UnitType.hpp39
16 files changed, 643 insertions, 385 deletions
diff --git a/src/openvic-simulation/InstanceManager.cpp b/src/openvic-simulation/InstanceManager.cpp
index 7ee5fb8..c51dec7 100644
--- a/src/openvic-simulation/InstanceManager.cpp
+++ b/src/openvic-simulation/InstanceManager.cpp
@@ -36,10 +36,15 @@ void InstanceManager::update_gamestate() {
return;
}
currently_updating_gamestate = true;
+
Logger::info("Update: ", today);
+
+ // Update gamestate...
map_instance.update_gamestate(today);
+
gamestate_updated();
gamestate_needs_update = false;
+
currently_updating_gamestate = false;
}
@@ -48,8 +53,12 @@ void InstanceManager::update_gamestate() {
*/
void InstanceManager::tick() {
today++;
+
Logger::info("Tick: ", today);
+
+ // Tick...
map_instance.tick(today);
+
set_gamestate_needs_update();
}
diff --git a/src/openvic-simulation/InstanceManager.hpp b/src/openvic-simulation/InstanceManager.hpp
index 743fd71..9cf346a 100644
--- a/src/openvic-simulation/InstanceManager.hpp
+++ b/src/openvic-simulation/InstanceManager.hpp
@@ -7,7 +7,7 @@
#include "openvic-simulation/economy/GoodInstance.hpp"
#include "openvic-simulation/map/MapInstance.hpp"
#include "openvic-simulation/map/Mapmode.hpp"
-#include "openvic-simulation/military/UnitInstance.hpp"
+#include "openvic-simulation/military/UnitInstanceGroup.hpp"
#include "openvic-simulation/misc/SimulationClock.hpp"
#include "openvic-simulation/types/Date.hpp"
diff --git a/src/openvic-simulation/country/CountryInstance.cpp b/src/openvic-simulation/country/CountryInstance.cpp
index 2debd8a..a4086a7 100644
--- a/src/openvic-simulation/country/CountryInstance.cpp
+++ b/src/openvic-simulation/country/CountryInstance.cpp
@@ -2,7 +2,8 @@
#include "openvic-simulation/country/CountryDefinition.hpp"
#include "openvic-simulation/history/CountryHistory.hpp"
-#include "openvic-simulation/military/UnitInstance.hpp"
+#include "openvic-simulation/military/Deployment.hpp"
+#include "openvic-simulation/military/UnitInstanceGroup.hpp"
using namespace OpenVic;
@@ -73,6 +74,89 @@ 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);
+ return true;
+ }
+
+ 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);
+ 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:
+ 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())
+ );
+ 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;
+
+ switch (leader_to_remove->get_branch()) {
+ case LAND:
+ remove_general(static_cast<General const*>(leader_to_remove));
+ return true;
+
+ case NAVAL:
+ remove_admiral(static_cast<Admiral const*>(leader_to_remove));
+ 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;
+ }
+}
+
bool CountryInstance::apply_history_to_country(CountryHistoryEntry const* entry) {
if (entry == nullptr) {
Logger::error("Trying to apply null country history to ", get_identifier());
@@ -135,7 +219,7 @@ bool CountryInstanceManager::apply_history_to_countries(
CountryHistoryEntry const* oob_history_entry = nullptr;
for (CountryHistoryEntry const* entry : history_map->get_entries_up_to(date)) {
- country_instance.apply_history_to_country(entry);
+ ret &= country_instance.apply_history_to_country(entry);
if (entry->get_inital_oob()) {
oob_history_entry = entry;
@@ -143,10 +227,13 @@ bool CountryInstanceManager::apply_history_to_countries(
}
if (oob_history_entry != nullptr) {
- unit_instance_manager.generate_deployment(
+ ret &= unit_instance_manager.generate_deployment(
map_instance, country_instance, *oob_history_entry->get_inital_oob()
);
}
+ } else {
+ Logger::error("Country ", country_instance.get_identifier(), " has no history!");
+ ret = false;
}
}
}
diff --git a/src/openvic-simulation/country/CountryInstance.hpp b/src/openvic-simulation/country/CountryInstance.hpp
index 45924b2..3022b6a 100644
--- a/src/openvic-simulation/country/CountryInstance.hpp
+++ b/src/openvic-simulation/country/CountryInstance.hpp
@@ -2,6 +2,10 @@
#include <vector>
+#include <plf_colony.h>
+
+#include "openvic-simulation/military/Leader.hpp"
+#include "openvic-simulation/military/UnitInstanceGroup.hpp"
#include "openvic-simulation/types/Date.hpp"
#include "openvic-simulation/types/fixed_point/FixedPointMap.hpp"
#include "openvic-simulation/types/IdentifierRegistry.hpp"
@@ -42,6 +46,9 @@ namespace OpenVic {
std::vector<Reform const*> PROPERTY(reforms); // TODO: should be map of reform groups to active reforms: must set defaults & validate applied history
// TODO: Military units + OOBs; will probably need an extensible deployment class
+ plf::colony<General> PROPERTY(generals);
+ plf::colony<Admiral> PROPERTY(admirals);
+
CountryInstance(CountryDefinition const* new_country_definition);
public:
@@ -55,6 +62,14 @@ 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);
+
+ bool add_leader(LeaderBase const& new_leader);
+ bool remove_leader(LeaderBase const* leader_to_remove);
+
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 61b1527..8bb5345 100644
--- a/src/openvic-simulation/map/ProvinceInstance.cpp
+++ b/src/openvic-simulation/map/ProvinceInstance.cpp
@@ -3,7 +3,7 @@
#include "openvic-simulation/country/CountryDefinition.hpp"
#include "openvic-simulation/history/ProvinceHistory.hpp"
#include "openvic-simulation/map/ProvinceDefinition.hpp"
-#include "openvic-simulation/military/UnitInstance.hpp"
+#include "openvic-simulation/military/UnitInstanceGroup.hpp"
using namespace OpenVic;
diff --git a/src/openvic-simulation/map/ProvinceInstance.hpp b/src/openvic-simulation/map/ProvinceInstance.hpp
index ca7f149..a4f9e98 100644
--- a/src/openvic-simulation/map/ProvinceInstance.hpp
+++ b/src/openvic-simulation/map/ProvinceInstance.hpp
@@ -1,6 +1,8 @@
#pragma once
#include "openvic-simulation/economy/BuildingInstance.hpp"
+#include "openvic-simulation/military/UnitInstance.hpp"
+#include "openvic-simulation/military/UnitType.hpp"
#include "openvic-simulation/pop/Pop.hpp"
#include "openvic-simulation/types/fixed_point/FixedPointMap.hpp"
#include "openvic-simulation/types/HasIdentifier.hpp"
@@ -14,8 +16,6 @@ namespace OpenVic {
struct CountryDefinition;
struct Crime;
struct GoodDefinition;
- struct ArmyInstance;
- struct NavyInstance;
struct Ideology;
struct Culture;
struct Religion;
@@ -24,6 +24,15 @@ namespace OpenVic {
struct IdeologyManager;
struct IssueManager;
+ template<UnitType::branch_t>
+ struct UnitInstanceGroup;
+
+ template<UnitType::branch_t>
+ struct UnitInstanceGroupBranched;
+
+ using ArmyInstance = UnitInstanceGroupBranched<UnitType::branch_t::LAND>;
+ using NavyInstance = UnitInstanceGroupBranched<UnitType::branch_t::NAVAL>;
+
struct ProvinceInstance : HasIdentifierAndColour {
friend struct MapInstance;
@@ -83,6 +92,27 @@ namespace OpenVic {
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();
+ }
+ }
+ 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 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 66f656d..9c89690 100644
--- a/src/openvic-simulation/military/Deployment.cpp
+++ b/src/openvic-simulation/military/Deployment.cpp
@@ -22,13 +22,13 @@ NavyDeployment::NavyDeployment(
Deployment::Deployment(
std::string_view new_path, std::vector<ArmyDeployment>&& new_armies, std::vector<NavyDeployment>&& new_navies,
- std::vector<Leader>&& new_leaders
+ std::vector<LeaderBase>&& new_leaders
) : HasIdentifier { new_path }, armies { std::move(new_armies) }, navies { std::move(new_navies) },
leaders { std::move(new_leaders) } {}
bool DeploymentManager::add_deployment(
std::string_view path, std::vector<ArmyDeployment>&& armies, std::vector<NavyDeployment>&& navies,
- std::vector<Leader>&& leaders
+ std::vector<LeaderBase>&& leaders
) {
if (path.empty()) {
Logger::error("Attemped to load order of battle with no path! Something is very wrong!");
@@ -68,7 +68,7 @@ bool DeploymentManager::load_oob_file(
std::vector<ArmyDeployment> armies;
std::vector<NavyDeployment> navies;
- std::vector<Leader> leaders;
+ std::vector<LeaderBase> leaders;
bool ret = expect_dictionary_keys_and_default(
key_value_success_callback, // TODO: load SOI information
@@ -109,8 +109,8 @@ bool DeploymentManager::load_oob_file(
ret = false;
}
- leaders.emplace_back(
- leader_name, leader_branch, leader_date, leader_personality, leader_background, leader_prestige, picture
+ leaders.push_back(
+ { leader_name, leader_branch, leader_date, leader_personality, leader_background, leader_prestige, picture }
);
return ret;
diff --git a/src/openvic-simulation/military/Deployment.hpp b/src/openvic-simulation/military/Deployment.hpp
index 8d3f016..9a1d2ee 100644
--- a/src/openvic-simulation/military/Deployment.hpp
+++ b/src/openvic-simulation/military/Deployment.hpp
@@ -10,7 +10,6 @@
namespace OpenVic {
struct ProvinceDefinition;
- struct RegimentType;
struct RegimentDeployment {
friend struct DeploymentManager;
@@ -26,8 +25,6 @@ namespace OpenVic {
RegimentDeployment(RegimentDeployment&&) = default;
};
- struct ShipType;
-
struct ShipDeployment {
friend struct DeploymentManager;
@@ -79,11 +76,11 @@ namespace OpenVic {
private:
std::vector<ArmyDeployment> PROPERTY(armies);
std::vector<NavyDeployment> PROPERTY(navies);
- std::vector<Leader> PROPERTY(leaders);
+ std::vector<LeaderBase> PROPERTY(leaders);
Deployment(
std::string_view new_path, std::vector<ArmyDeployment>&& new_armies, std::vector<NavyDeployment>&& new_navies,
- std::vector<Leader>&& new_leaders
+ std::vector<LeaderBase>&& new_leaders
);
public:
@@ -101,7 +98,7 @@ namespace OpenVic {
public:
bool add_deployment(
std::string_view path, std::vector<ArmyDeployment>&& armies, std::vector<NavyDeployment>&& navies,
- std::vector<Leader>&& leaders
+ std::vector<LeaderBase>&& leaders
);
bool load_oob_file(
diff --git a/src/openvic-simulation/military/Leader.cpp b/src/openvic-simulation/military/Leader.cpp
index d6be36f..a86c044 100644
--- a/src/openvic-simulation/military/Leader.cpp
+++ b/src/openvic-simulation/military/Leader.cpp
@@ -2,8 +2,8 @@
using namespace OpenVic;
-Leader::Leader(
+LeaderBase::LeaderBase(
std::string_view new_name, UnitType::branch_t new_branch, Date new_date, LeaderTrait const* new_personality,
LeaderTrait const* new_background, fixed_point_t new_prestige, std::string_view new_picture
) : name { new_name }, branch { new_branch }, date { new_date }, personality { new_personality }, background { new_background },
- prestige { new_prestige }, picture { new_picture } {} \ No newline at end of file
+ prestige { new_prestige }, picture { new_picture } {}
diff --git a/src/openvic-simulation/military/Leader.hpp b/src/openvic-simulation/military/Leader.hpp
index 5995164..3f8603e 100644
--- a/src/openvic-simulation/military/Leader.hpp
+++ b/src/openvic-simulation/military/Leader.hpp
@@ -1,10 +1,20 @@
#pragma once
+#include <string>
+#include <string_view>
+
#include "openvic-simulation/military/LeaderTrait.hpp"
#include "openvic-simulation/military/UnitType.hpp"
+#include "openvic-simulation/types/Date.hpp"
+#include "openvic-simulation/types/fixed_point/FixedPoint.hpp"
+#include "openvic-simulation/utility/Utility.hpp"
namespace OpenVic {
- struct Leader {
+ struct DeploymentManager;
+
+ struct LeaderBase {
+ friend struct DeploymentManager;
+
private:
std::string PROPERTY(name);
UnitType::branch_t PROPERTY(branch); /* type in defines */
@@ -14,12 +24,39 @@ namespace OpenVic {
fixed_point_t PROPERTY(prestige);
std::string PROPERTY(picture);
- public:
- Leader(
+ private:
+ LeaderBase(
std::string_view new_name, UnitType::branch_t new_branch, Date new_date, LeaderTrait const* new_personality,
LeaderTrait const* new_background, fixed_point_t new_prestige, std::string_view new_picture
);
- Leader(Leader&&) = default;
+ protected:
+ LeaderBase(LeaderBase const&) = default;
+
+ public:
+ LeaderBase(LeaderBase&&) = default;
};
-} \ No newline at end of file
+
+ struct CountryInstance;
+
+ template<UnitType::branch_t>
+ struct UnitInstanceGroup;
+
+ template<UnitType::branch_t>
+ struct UnitInstanceGroupBranched;
+
+ template<UnitType::branch_t Branch>
+ struct LeaderBranched : LeaderBase {
+
+ friend struct CountryInstance;
+ friend bool UnitInstanceGroup<Branch>::set_leader(LeaderBranched<Branch>* new_leader);
+
+ private:
+ UnitInstanceGroupBranched<Branch>* PROPERTY(unit_instance_group);
+
+ LeaderBranched(LeaderBase const& leader_base) : LeaderBase { leader_base }, unit_instance_group { nullptr } {}
+ };
+
+ using General = LeaderBranched<UnitType::branch_t::LAND>;
+ using Admiral = LeaderBranched<UnitType::branch_t::NAVAL>;
+}
diff --git a/src/openvic-simulation/military/UnitInstance.cpp b/src/openvic-simulation/military/UnitInstance.cpp
index ac9c194..1f49205 100644
--- a/src/openvic-simulation/military/UnitInstance.cpp
+++ b/src/openvic-simulation/military/UnitInstance.cpp
@@ -1,196 +1,11 @@
#include "UnitInstance.hpp"
-#include <vector>
-
-#include "openvic-simulation/country/CountryInstance.hpp"
-#include "openvic-simulation/map/MapInstance.hpp"
-#include "openvic-simulation/map/ProvinceInstance.hpp"
-#include "openvic-simulation/military/Deployment.hpp"
-
using namespace OpenVic;
-RegimentInstance::RegimentInstance(std::string_view new_name, RegimentType const& new_regiment_type, Pop* new_pop)
- : UnitInstance { new_name, new_regiment_type }, pop { new_pop } {}
-
-ShipInstance::ShipInstance(std::string_view new_name, ShipType const& new_ship_type)
- : UnitInstance { new_name, new_ship_type } {}
-
-MovementInfo::MovementInfo() : path {}, movement_progress {} {}
-
-//TODO: pathfinding logic
-MovementInfo::MovementInfo(ProvinceInstance const* starting_province, ProvinceInstance const* target_province)
- : path { starting_province, target_province }, movement_progress { 0 } {}
-
-ArmyInstance::ArmyInstance(
- std::string_view new_name,
- std::vector<RegimentInstance*>&& new_units,
- Leader const* new_leader,
- CountryInstance* new_country
-) : UnitInstanceGroup { new_name, UnitType::branch_t::LAND, std::move(new_units), new_leader, new_country } {}
-
-void ArmyInstance::set_position(ProvinceInstance* new_position) {
- if (position != new_position) {
- if (position != nullptr) {
- position->remove_army(*this);
- }
- position = new_position;
- if (position != nullptr) {
- position->add_army(*this);
- }
- }
-}
-
-NavyInstance::NavyInstance(
- std::string_view new_name,
- std::vector<ShipInstance*>&& new_units,
- Leader const* new_leader,
- CountryInstance* new_country
-) : UnitInstanceGroup { new_name, UnitType::branch_t::NAVAL, std::move(new_units), new_leader, new_country } {}
-
-void NavyInstance::set_position(ProvinceInstance* new_position) {
- if (position != new_position) {
- if (position != nullptr) {
- position->remove_navy(*this);
- }
- position = new_position;
- if (position != nullptr) {
- position->add_navy(*this);
- }
- }
-}
-
-bool UnitInstanceManager::generate_regiment(RegimentDeployment const& regiment_deployment, RegimentInstance*& regiment) {
- // TODO - get pop from Province regiment_deployment.get_home()
- regiments.push_back({ regiment_deployment.get_name(), regiment_deployment.get_type(), nullptr });
-
- regiment = &regiments.back();
-
- return true;
-}
-
-bool UnitInstanceManager::generate_ship(ShipDeployment const& ship_deployment, ShipInstance*& ship) {
- ships.push_back({ ship_deployment.get_name(), ship_deployment.get_type() });
-
- ship = &ships.back();
-
- return true;
-}
-
-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;
- }
-
- 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;
- }
-
- bool ret = true;
-
- std::vector<RegimentInstance*> army_regiments;
-
- for (RegimentDeployment const& regiment_deployment : army_deployment.get_regiments()) {
- RegimentInstance* regiment = nullptr;
-
- ret &= generate_regiment(regiment_deployment, regiment);
-
- if (regiment != nullptr) {
- army_regiments.push_back(regiment);
- }
- }
-
- if (army_regiments.empty()) {
- Logger::error(
- "Failed to generate any regiments for army \"", army_deployment.get_name(), "\" for country \"",
- country.get_identifier(), "\""
- );
- return false;
- }
-
- armies.push_back({ army_deployment.get_name(), std::move(army_regiments), nullptr, &country });
-
- armies.back().set_position(map_instance.get_province_instance_from_const(army_deployment.get_location()));
-
- return ret;
-}
-
-bool UnitInstanceManager::generate_navy(
- MapInstance& map_instance, CountryInstance& country, NavyDeployment const& navy_deployment
-) {
- if (navy_deployment.get_ships().empty()) {
- Logger::error(
- "Trying to generate navy \"", navy_deployment.get_name(), "\" with no ships for country \"",
- country.get_identifier(), "\""
- );
- return false;
- }
-
- if (navy_deployment.get_location() == nullptr) {
- Logger::error(
- "Trying to generate navy \"", navy_deployment.get_name(), "\" with no location for country \"",
- country.get_identifier(), "\""
- );
- return false;
- }
-
- bool ret = true;
-
- std::vector<ShipInstance*> navy_ships;
-
- for (ShipDeployment const& ship_deployment : navy_deployment.get_ships()) {
- ShipInstance* ship = nullptr;
-
- ret &= generate_ship(ship_deployment, ship);
-
- if (ship != nullptr) {
- navy_ships.push_back(ship);
- }
- }
-
- if (navy_ships.empty()) {
- Logger::error(
- "Failed to generate any ships for navy \"", navy_deployment.get_name(), "\" for country \"",
- country.get_identifier(), "\""
- );
- return false;
- }
-
- navies.push_back({ navy_deployment.get_name(), std::move(navy_ships), nullptr, &country });
-
- navies.back().set_position(map_instance.get_province_instance_from_const(navy_deployment.get_location()));
-
- return ret;
-}
-
-bool UnitInstanceManager::generate_deployment(
- MapInstance& map_instance, CountryInstance& country, Deployment const* deployment
-) {
- if (deployment == nullptr) {
- Logger::error("Trying to generate null deployment for ", country.get_identifier());
- return false;
- }
-
- // TODO - Leaders (could be stored in CountryInstance?)
-
- bool ret = true;
-
- for (ArmyDeployment const& army_deployment : deployment->get_armies()) {
- ret &= generate_army(map_instance, country, army_deployment);
- }
-
- for (NavyDeployment const& navy_deployment : deployment->get_navies()) {
- ret &= generate_navy(map_instance, country, navy_deployment);
- }
+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 } {}
- return ret;
-}
+UnitInstanceBranched<UnitType::branch_t::NAVAL>::UnitInstanceBranched(
+ std::string_view new_name, ShipType const& new_ship_type
+) : UnitInstance { new_name, new_ship_type } {}
diff --git a/src/openvic-simulation/military/UnitInstance.hpp b/src/openvic-simulation/military/UnitInstance.hpp
index a1437ef..1480591 100644
--- a/src/openvic-simulation/military/UnitInstance.hpp
+++ b/src/openvic-simulation/military/UnitInstance.hpp
@@ -3,26 +3,26 @@
#include <concepts>
#include <string>
#include <string_view>
-#include <vector>
-#include "openvic-simulation/military/Leader.hpp"
#include "openvic-simulation/military/UnitType.hpp"
#include "openvic-simulation/types/fixed_point/FixedPoint.hpp"
#include "openvic-simulation/utility/Getters.hpp"
namespace OpenVic {
- template<std::derived_from<UnitType> T>
+ template<UnitType::branch_t Branch>
struct UnitInstance {
+ using _UnitType = UnitTypeBranched<Branch>;
+
private:
std::string PROPERTY(unit_name);
- T const& PROPERTY(unit_type); //can't change
+ _UnitType const& PROPERTY(unit_type);
fixed_point_t PROPERTY_RW(organisation);
fixed_point_t PROPERTY_RW(morale);
fixed_point_t PROPERTY_RW(strength);
protected:
- UnitInstance(std::string_view new_unit_name, T const& new_unit_type) :
+ 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
@@ -39,172 +39,34 @@ namespace OpenVic {
struct Pop;
- struct RegimentInstance : UnitInstance<RegimentType> {
- friend struct UnitInstanceManager;
-
- private:
- Pop* PROPERTY(pop);
-
- RegimentInstance(std::string_view new_name, RegimentType const& new_regiment_type, Pop* new_pop);
-
- public:
- RegimentInstance(RegimentInstance&&) = default;
- };
+ template<UnitType::branch_t>
+ struct UnitInstanceBranched;
- struct ShipInstance : UnitInstance<ShipType> {
+ template<>
+ struct UnitInstanceBranched<UnitType::branch_t::LAND> : UnitInstance<UnitType::branch_t::LAND> {
friend struct UnitInstanceManager;
private:
- ShipInstance(std::string_view new_name, ShipType const& new_ship_type);
-
- public:
- ShipInstance(ShipInstance&&) = default;
- };
-
- 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);
- };
-
- struct CountryInstance;
-
- template<utility::is_derived_from_specialization_of<UnitInstance> I>
- struct UnitInstanceGroup {
- private:
- std::string PROPERTY(name);
- const UnitType::branch_t PROPERTY(branch);
- std::vector<I*> PROPERTY(units);
- Leader const* PROPERTY(leader);
-
- MovementInfo PROPERTY_REF(movement_info);
+ Pop* PROPERTY(pop);
- protected:
- ProvinceInstance* PROPERTY_ACCESS(position, protected);
- CountryInstance* PROPERTY_ACCESS(country, protected);
-
- UnitInstanceGroup(
- std::string_view new_name,
- UnitType::branch_t new_branch,
- std::vector<I*>&& new_units,
- Leader const* new_leader,
- CountryInstance* new_country
- ) : name { new_name },
- branch { new_branch },
- units { std::move(new_units) },
- leader { new_leader },
- position { nullptr },
- country { new_country } {}
+ UnitInstanceBranched(std::string_view new_name, RegimentType const& new_regiment_type, Pop* new_pop);
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](I 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 (I 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;
- }
-
- virtual void set_position(ProvinceInstance* new_position) = 0;
+ UnitInstanceBranched(UnitInstanceBranched&&) = default;
};
- struct ArmyInstance : UnitInstanceGroup<RegimentInstance> {
- friend struct UnitInstanceManager;
-
- private:
- ArmyInstance(
- std::string_view new_name,
- std::vector<RegimentInstance*>&& new_units,
- Leader const* new_leader,
- CountryInstance* new_country
- );
+ using RegimentInstance = UnitInstanceBranched<UnitType::branch_t::LAND>;
- public:
- ArmyInstance(ArmyInstance&&) = default;
-
- void set_position(ProvinceInstance* new_position) override;
- };
-
- struct NavyInstance : UnitInstanceGroup<ShipInstance> {
+ template<>
+ struct UnitInstanceBranched<UnitType::branch_t::NAVAL> : UnitInstance<UnitType::branch_t::NAVAL> {
friend struct UnitInstanceManager;
private:
- std::vector<ArmyInstance const*> PROPERTY(carried_armies);
-
- NavyInstance(
- std::string_view new_name,
- std::vector<ShipInstance*>&& new_ships,
- Leader const* new_leader,
- CountryInstance* new_country
- );
+ UnitInstanceBranched(std::string_view new_name, ShipType const& new_ship_type);
public:
- NavyInstance(NavyInstance&&) = default;
-
- void set_position(ProvinceInstance* new_position) override;
+ UnitInstanceBranched(UnitInstanceBranched&&) = default;
};
- struct RegimentDeployment;
- struct ShipDeployment;
- struct MapInstance;
- struct ArmyDeployment;
- struct NavyDeployment;
- struct Deployment;
-
- struct UnitInstanceManager {
- private:
- std::deque<RegimentInstance> PROPERTY(regiments);
- std::deque<ShipInstance> PROPERTY(ships);
-
- std::deque<ArmyInstance> PROPERTY(armies);
- std::deque<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);
-
- public:
- bool generate_deployment(MapInstance& map_instance, CountryInstance& country, Deployment const* deployment);
- };
+ using ShipInstance = UnitInstanceBranched<UnitType::branch_t::NAVAL>;
}
diff --git a/src/openvic-simulation/military/UnitInstanceGroup.cpp b/src/openvic-simulation/military/UnitInstanceGroup.cpp
new file mode 100644
index 0000000..46fb992
--- /dev/null
+++ b/src/openvic-simulation/military/UnitInstanceGroup.cpp
@@ -0,0 +1,169 @@
+#include "UnitInstanceGroup.hpp"
+
+#include <vector>
+
+#include "openvic-simulation/country/CountryInstance.hpp"
+#include "openvic-simulation/map/MapInstance.hpp"
+#include "openvic-simulation/map/ProvinceInstance.hpp"
+#include "openvic-simulation/military/Deployment.hpp"
+
+using namespace OpenVic;
+
+MovementInfo::MovementInfo() : path {}, movement_progress {} {}
+
+//TODO: pathfinding logic
+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 } {}
+
+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 } {}
+
+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 });
+
+ regiment = &regiment_instance;
+
+ return true;
+}
+
+bool UnitInstanceManager::generate_ship(ShipDeployment const& ship_deployment, ShipInstance*& ship) {
+ ShipInstance& ship_instance = *ships.insert({ ship_deployment.get_name(), ship_deployment.get_type() });
+
+ ship = &ship_instance;
+
+ return true;
+}
+
+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;
+ }
+
+ 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;
+ }
+
+ bool ret = true;
+
+ std::vector<RegimentInstance*> army_regiments;
+
+ for (RegimentDeployment const& regiment_deployment : army_deployment.get_regiments()) {
+ RegimentInstance* regiment = nullptr;
+
+ ret &= generate_regiment(regiment_deployment, regiment);
+
+ if (regiment != nullptr) {
+ army_regiments.push_back(regiment);
+ }
+ }
+
+ if (army_regiments.empty()) {
+ Logger::error(
+ "Failed to generate any regiments for army \"", army_deployment.get_name(), "\" for country \"",
+ country.get_identifier(), "\""
+ );
+ return false;
+ }
+
+ ArmyInstance& army_instance = *armies.insert({ army_deployment.get_name(), std::move(army_regiments), nullptr, &country });
+
+ army_instance.set_position(map_instance.get_province_instance_from_const(army_deployment.get_location()));
+
+ return ret;
+}
+
+bool UnitInstanceManager::generate_navy(
+ MapInstance& map_instance, CountryInstance& country, NavyDeployment const& navy_deployment
+) {
+ if (navy_deployment.get_ships().empty()) {
+ Logger::error(
+ "Trying to generate navy \"", navy_deployment.get_name(), "\" with no ships for country \"",
+ country.get_identifier(), "\""
+ );
+ return false;
+ }
+
+ if (navy_deployment.get_location() == nullptr) {
+ Logger::error(
+ "Trying to generate navy \"", navy_deployment.get_name(), "\" with no location for country \"",
+ country.get_identifier(), "\""
+ );
+ return false;
+ }
+
+ bool ret = true;
+
+ std::vector<ShipInstance*> navy_ships;
+
+ for (ShipDeployment const& ship_deployment : navy_deployment.get_ships()) {
+ ShipInstance* ship = nullptr;
+
+ ret &= generate_ship(ship_deployment, ship);
+
+ if (ship != nullptr) {
+ navy_ships.push_back(ship);
+ }
+ }
+
+ if (navy_ships.empty()) {
+ Logger::error(
+ "Failed to generate any ships for navy \"", navy_deployment.get_name(), "\" for country \"",
+ country.get_identifier(), "\""
+ );
+ return false;
+ }
+
+ NavyInstance& navy_intance = *navies.insert({ navy_deployment.get_name(), std::move(navy_ships), nullptr, &country });
+
+ navy_intance.set_position(map_instance.get_province_instance_from_const(navy_deployment.get_location()));
+
+ return ret;
+}
+
+bool UnitInstanceManager::generate_deployment(
+ MapInstance& map_instance, CountryInstance& country, Deployment const* deployment
+) {
+ if (deployment == nullptr) {
+ Logger::error("Trying to generate null deployment for ", country.get_identifier());
+ return false;
+ }
+
+ bool ret = true;
+
+ for (ArmyDeployment const& army_deployment : deployment->get_armies()) {
+ ret &= generate_army(map_instance, country, army_deployment);
+ }
+
+ for (NavyDeployment const& navy_deployment : deployment->get_navies()) {
+ ret &= generate_navy(map_instance, country, navy_deployment);
+ }
+
+ for (LeaderBase const& leader : deployment->get_leaders()) {
+ ret &= country.add_leader(leader);
+ }
+
+ return ret;
+}
diff --git a/src/openvic-simulation/military/UnitInstanceGroup.hpp b/src/openvic-simulation/military/UnitInstanceGroup.hpp
new file mode 100644
index 0000000..54aac3d
--- /dev/null
+++ b/src/openvic-simulation/military/UnitInstanceGroup.hpp
@@ -0,0 +1,220 @@
+#pragma once
+
+#include <string>
+#include <string_view>
+#include <vector>
+
+#include <plf_colony.h>
+
+#include "openvic-simulation/map/ProvinceInstance.hpp"
+#include "openvic-simulation/military/UnitInstance.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;
+
+ 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>
+ struct UnitInstanceGroupBranched;
+
+ 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,
+ _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);
+ }
+
+ 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;
+ }
+ };
+
+ 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,
+ _Leader* new_leader,
+ CountryInstance* new_country
+ );
+
+ 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 const*> PROPERTY(carried_armies);
+
+ UnitInstanceGroupBranched(
+ std::string_view new_name,
+ std::vector<ShipInstance*>&& new_ships,
+ _Leader* new_leader,
+ CountryInstance* new_country
+ );
+
+ public:
+ UnitInstanceGroupBranched(UnitInstanceGroupBranched&&) = default;
+ };
+
+ using NavyInstance = UnitInstanceGroupBranched<UnitType::branch_t::NAVAL>;
+
+ struct RegimentDeployment;
+ struct ShipDeployment;
+ struct MapInstance;
+ struct ArmyDeployment;
+ struct NavyDeployment;
+ struct Deployment;
+
+ struct UnitInstanceManager {
+ private:
+ plf::colony<RegimentInstance> PROPERTY(regiments);
+ plf::colony<ShipInstance> PROPERTY(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);
+
+ public:
+ bool generate_deployment(MapInstance& map_instance, CountryInstance& country, Deployment const* deployment);
+ };
+}
diff --git a/src/openvic-simulation/military/UnitType.cpp b/src/openvic-simulation/military/UnitType.cpp
index 45ce5d9..a7769d3 100644
--- a/src/openvic-simulation/military/UnitType.cpp
+++ b/src/openvic-simulation/military/UnitType.cpp
@@ -30,7 +30,7 @@ UnitType::UnitType(
supply_cost { std::move(unit_args.supply_cost) },
terrain_modifiers { std::move(unit_args.terrain_modifiers) } {}
-RegimentType::RegimentType(
+UnitTypeBranched<LAND>::UnitTypeBranched(
std::string_view new_identifier, unit_type_args_t& unit_args, regiment_type_args_t const& regiment_type_args
) : UnitType { new_identifier, LAND, unit_args },
allowed_cultures { regiment_type_args.allowed_cultures },
@@ -45,7 +45,7 @@ RegimentType::RegimentType(
maneuver { regiment_type_args.maneuver },
siege { regiment_type_args.siege } {}
-ShipType::ShipType(
+UnitTypeBranched<NAVAL>::UnitTypeBranched(
std::string_view new_identifier, unit_type_args_t& unit_args, ship_type_args_t const& ship_type_args
) : UnitType { new_identifier, NAVAL, unit_args },
naval_icon { ship_type_args.naval_icon },
diff --git a/src/openvic-simulation/military/UnitType.hpp b/src/openvic-simulation/military/UnitType.hpp
index 9e7ecdc..095a759 100644
--- a/src/openvic-simulation/military/UnitType.hpp
+++ b/src/openvic-simulation/military/UnitType.hpp
@@ -72,7 +72,11 @@ namespace OpenVic {
UnitType(UnitType&&) = default;
};
- struct RegimentType : UnitType {
+ template<UnitType::branch_t>
+ struct UnitTypeBranched;
+
+ template<>
+ struct UnitTypeBranched<UnitType::branch_t::LAND> : UnitType {
friend struct UnitTypeManager;
enum struct allowed_cultures_t { ALL_CULTURES, ACCEPTED_CULTURES, PRIMARY_CULTURE };
@@ -102,17 +106,22 @@ namespace OpenVic {
const fixed_point_t PROPERTY(maneuver);
const fixed_point_t PROPERTY(siege);
- RegimentType(std::string_view new_identifier, unit_type_args_t& unit_args, regiment_type_args_t const& regiment_type_args);
+ UnitTypeBranched(
+ std::string_view new_identifier, unit_type_args_t& unit_args, regiment_type_args_t const& regiment_type_args
+ );
public:
- RegimentType(RegimentType&&) = default;
+ UnitTypeBranched(UnitTypeBranched&&) = default;
};
- struct ShipType : UnitType {
+ using RegimentType = UnitTypeBranched<UnitType::branch_t::LAND>;
+
+ template<>
+ struct UnitTypeBranched<UnitType::branch_t::NAVAL> : UnitType {
friend struct UnitTypeManager;
struct ship_type_args_t {
- UnitType::icon_t naval_icon = 0;
+ icon_t naval_icon = 0;
bool sail = false, transport = false, capital = false, build_overseas = false;
uint32_t min_port_level = 0;
int32_t limit_per_port = 0;
@@ -140,12 +149,14 @@ namespace OpenVic {
const fixed_point_t PROPERTY(evasion);
const fixed_point_t PROPERTY(torpedo_attack);
- ShipType(std::string_view new_identifier, unit_type_args_t& unit_args, ship_type_args_t const& ship_type_args);
+ UnitTypeBranched(std::string_view new_identifier, unit_type_args_t& unit_args, ship_type_args_t const& ship_type_args);
public:
- ShipType(ShipType&&) = default;
+ UnitTypeBranched(UnitTypeBranched&&) = default;
};
+ using ShipType = UnitTypeBranched<UnitType::branch_t::NAVAL>;
+
struct UnitTypeManager {
private:
IdentifierPointerRegistry<UnitType> IDENTIFIER_REGISTRY(unit_type);
@@ -157,15 +168,21 @@ namespace OpenVic {
void lock_all_unit_types();
bool add_regiment_type(
- std::string_view identifier, UnitType::unit_type_args_t& unit_args, RegimentType::regiment_type_args_t const& regiment_type_args
+ std::string_view identifier, UnitType::unit_type_args_t& unit_args,
+ RegimentType::regiment_type_args_t const& regiment_type_args
);
bool add_ship_type(
- std::string_view identifier, UnitType::unit_type_args_t& unit_args, ShipType::ship_type_args_t const& ship_type_args
+ std::string_view identifier, UnitType::unit_type_args_t& unit_args,
+ ShipType::ship_type_args_t const& ship_type_args
);
- static NodeTools::Callback<std::string_view> auto expect_branch_str(NodeTools::Callback<UnitType::branch_t> auto callback) {
+ static NodeTools::Callback<std::string_view> auto expect_branch_str(
+ NodeTools::Callback<UnitType::branch_t> auto callback
+ ) {
using enum UnitType::branch_t;
- static const string_map_t<UnitType::branch_t> branch_map { { "land", LAND }, { "naval", NAVAL }, { "sea", NAVAL } };
+ static const string_map_t<UnitType::branch_t> branch_map {
+ { "land", LAND }, { "naval", NAVAL }, { "sea", NAVAL }
+ };
return NodeTools::expect_mapped_string(branch_map, callback);
}
static NodeTools::NodeCallback auto expect_branch_identifier(NodeTools::Callback<UnitType::branch_t> auto callback) {