aboutsummaryrefslogtreecommitdiff
path: root/src/openvic-simulation/military
diff options
context:
space:
mode:
author hop311 <hop3114@gmail.com>2024-04-15 00:29:28 +0200
committer hop311 <hop3114@gmail.com>2024-04-15 00:38:46 +0200
commit5799836bee29024ce8a2d0fc45e06664c0110751 (patch)
tree54a0ad26ef3cec9a56644479611e8abaad62b1f7 /src/openvic-simulation/military
parent109d31f147512c8d51f35f9773cd3c6bb1b8b994 (diff)
Generate starting unit instancesunits
Diffstat (limited to 'src/openvic-simulation/military')
-rw-r--r--src/openvic-simulation/military/Deployment.cpp63
-rw-r--r--src/openvic-simulation/military/Deployment.hpp40
-rw-r--r--src/openvic-simulation/military/Leader.hpp2
-rw-r--r--src/openvic-simulation/military/MilitaryManager.hpp4
-rw-r--r--src/openvic-simulation/military/UnitInstance.cpp170
-rw-r--r--src/openvic-simulation/military/UnitInstance.hpp116
6 files changed, 350 insertions, 45 deletions
diff --git a/src/openvic-simulation/military/Deployment.cpp b/src/openvic-simulation/military/Deployment.cpp
index 903df3a..1f8b820 100644
--- a/src/openvic-simulation/military/Deployment.cpp
+++ b/src/openvic-simulation/military/Deployment.cpp
@@ -5,16 +5,19 @@
using namespace OpenVic;
using namespace OpenVic::NodeTools;
-RegimentDeployment::RegimentDeployment(std::string_view new_name, RegimentType const* new_type, Province const* new_home)
+RegimentDeployment::RegimentDeployment(std::string_view new_name, RegimentType const& new_type, Province const* new_home)
: name { new_name }, type { new_type }, home { new_home } {}
-ShipDeployment::ShipDeployment(std::string_view new_name, ShipType const* new_type) : name { new_name }, type { new_type } {}
+ShipDeployment::ShipDeployment(std::string_view new_name, ShipType const& new_type)
+ : name { new_name }, type { new_type } {}
-ArmyDeployment::ArmyDeployment(std::string_view new_name, Province const* new_location, std::vector<RegimentDeployment>&& new_regiments)
- : name { new_name }, location { new_location }, regiments { std::move(new_regiments) } {}
+ArmyDeployment::ArmyDeployment(
+ std::string_view new_name, Province 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, Province const* new_location, std::vector<ShipDeployment>&& new_ships)
- : name { new_name }, location { new_location }, ships { std::move(new_ships) } {}
+NavyDeployment::NavyDeployment(
+ std::string_view new_name, Province const* new_location, std::vector<ShipDeployment>&& new_ships
+) : name { new_name }, location { new_location }, ships { std::move(new_ships) } {}
Deployment::Deployment(
std::string_view new_path, std::vector<ArmyDeployment>&& new_armies, std::vector<NavyDeployment>&& new_navies,
@@ -23,16 +26,15 @@ Deployment::Deployment(
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::string_view path, std::vector<ArmyDeployment>&& armies, std::vector<NavyDeployment>&& navies,
+ std::vector<Leader>&& leaders
) {
if (path.empty()) {
Logger::error("Attemped to load order of battle with no path! Something is very wrong!");
return false;
}
- return deployments.add_item(
- std::make_unique<Deployment>(std::move(path), std::move(armies), std::move(navies), std::move(leaders))
- );
+ return deployments.add_item({ path, std::move(armies), std::move(navies), std::move(leaders) });
}
bool DeploymentManager::load_oob_file(
@@ -43,12 +45,16 @@ bool DeploymentManager::load_oob_file(
if (deployment != nullptr) {
return true;
}
+
if (missing_oob_files.contains(history_path)) {
return !fail_on_missing;
}
+
static constexpr std::string_view oob_directory = "history/units/";
+
const fs::path lookedup_path =
dataloader.lookup_file(StringUtils::append_string_views(oob_directory, history_path), false);
+
if (lookedup_path.empty()) {
missing_oob_files.emplace(history_path);
if (fail_on_missing) {
@@ -58,9 +64,11 @@ bool DeploymentManager::load_oob_file(
return true;
}
}
+
std::vector<ArmyDeployment> armies;
std::vector<NavyDeployment> navies;
std::vector<Leader> leaders;
+
bool ret = expect_dictionary_keys_and_default(
key_value_success_callback, // TODO: load SOI information
"leader", ZERO_OR_MORE, [&leaders, &game_manager](ast::NodeCPtr node) -> bool {
@@ -95,6 +103,7 @@ bool DeploymentManager::load_oob_file(
);
ret = false;
}
+
if (leader_background != nullptr && !leader_background->is_background_trait()) {
Logger::error(
"Leader ", leader_name, " has background ", leader_background->get_identifier(),
@@ -102,9 +111,11 @@ bool DeploymentManager::load_oob_file(
);
ret = false;
}
+
leaders.emplace_back(
leader_name, leader_branch, leader_date, leader_personality, leader_background, leader_prestige, picture
);
+
return ret;
},
"army", ZERO_OR_MORE, [&armies, &game_manager](ast::NodeCPtr node) -> bool {
@@ -120,6 +131,7 @@ bool DeploymentManager::load_oob_file(
std::string_view regiment_name {};
RegimentType const* regiment_type = nullptr;
Province const* regiment_home = nullptr;
+
const bool ret = expect_dictionary_keys(
"name", ONE_EXACTLY, expect_string(assign_variable_callback(regiment_name)),
"type", ONE_EXACTLY, game_manager.get_military_manager().get_unit_type_manager()
@@ -127,16 +139,26 @@ bool DeploymentManager::load_oob_file(
"home", ZERO_OR_ONE, game_manager.get_map()
.expect_province_identifier(assign_variable_callback_pointer(regiment_home))
)(node);
+
if (regiment_home == nullptr) {
Logger::warning("RegimentDeployment ", regiment_name, " has no home province!");
}
- army_regiments.emplace_back(regiment_name, regiment_type, regiment_home);
+
+ if (regiment_type == nullptr) {
+ Logger::error("RegimentDeployment ", regiment_name, " has no type!");
+ return false;
+ }
+
+ army_regiments.push_back({regiment_name, *regiment_type, regiment_home});
+
return ret;
},
/* Another paradox gem, tested in game and they don't lead the army or even show up */
"leader", ZERO_OR_MORE, success_callback
)(node);
- armies.emplace_back(army_name, army_location, std::move(army_regiments));
+
+ armies.push_back({ army_name, army_location, std::move(army_regiments) });
+
return ret;
},
"navy", ZERO_OR_MORE, [&navies, &game_manager](ast::NodeCPtr node) -> bool {
@@ -151,26 +173,39 @@ bool DeploymentManager::load_oob_file(
"ship", ONE_OR_MORE, [&game_manager, &navy_ships](ast::NodeCPtr node) -> bool {
std::string_view ship_name {};
ShipType const* ship_type = nullptr;
+
const bool ret = expect_dictionary_keys(
"name", ONE_EXACTLY, expect_string(assign_variable_callback(ship_name)),
"type", ONE_EXACTLY, game_manager.get_military_manager().get_unit_type_manager()
.expect_ship_type_identifier(assign_variable_callback_pointer(ship_type))
)(node);
- navy_ships.emplace_back(ship_name, ship_type);
+
+ if (ship_type == nullptr) {
+ Logger::error("ShipDeployment ", ship_name, " has no type!");
+ return false;
+ }
+
+ navy_ships.push_back({ ship_name, *ship_type });
+
return ret;
},
/* Another paradox gem, tested in game and they don't lead the army or even show up */
"leader", ZERO_OR_MORE, success_callback
)(node);
- navies.emplace_back(navy_name, navy_location, std::move(navy_ships));
+
+ navies.push_back({ navy_name, navy_location, std::move(navy_ships) });
+
return ret;
}
)(Dataloader::parse_defines(lookedup_path).get_file_node());
+
ret &= add_deployment(history_path, std::move(armies), std::move(navies), std::move(leaders));
+
deployment = get_deployment_by_identifier(history_path);
if (deployment == nullptr) {
ret = false;
}
+
return ret;
}
diff --git a/src/openvic-simulation/military/Deployment.hpp b/src/openvic-simulation/military/Deployment.hpp
index 742914d..8966397 100644
--- a/src/openvic-simulation/military/Deployment.hpp
+++ b/src/openvic-simulation/military/Deployment.hpp
@@ -11,48 +11,64 @@
namespace OpenVic {
struct RegimentDeployment {
+ friend struct DeploymentManager;
+
private:
std::string PROPERTY(name);
- RegimentType const* PROPERTY(type);
+ RegimentType const& PROPERTY(type);
Province const* PROPERTY(home);
+ RegimentDeployment(std::string_view new_name, RegimentType const& new_type, Province const* new_home);
+
public:
- RegimentDeployment(std::string_view new_name, RegimentType const* new_type, Province const* new_home);
+ RegimentDeployment(RegimentDeployment&&) = default;
};
struct ShipDeployment {
+ friend struct DeploymentManager;
+
private:
std::string PROPERTY(name);
- ShipType const* PROPERTY(type);
+ ShipType const& PROPERTY(type);
+
+ ShipDeployment(std::string_view new_name, ShipType const& new_type);
public:
- ShipDeployment(std::string_view new_name, ShipType const* new_type);
+ ShipDeployment(ShipDeployment&&) = default;
};
struct ArmyDeployment {
+ friend struct DeploymentManager;
+
private:
std::string PROPERTY(name);
Province const* PROPERTY(location);
std::vector<RegimentDeployment> PROPERTY(regiments);
+ ArmyDeployment(
+ std::string_view new_name, Province const* new_location, std::vector<RegimentDeployment>&& new_regiments
+ );
+
public:
- ArmyDeployment(std::string_view new_name, Province const* new_location, std::vector<RegimentDeployment>&& new_regiments);
+ ArmyDeployment(ArmyDeployment&&) = default;
};
struct NavyDeployment {
+ friend struct DeploymentManager;
+
private:
std::string PROPERTY(name);
Province const* PROPERTY(location);
std::vector<ShipDeployment> PROPERTY(ships);
- public:
NavyDeployment(std::string_view new_name, Province const* new_location, std::vector<ShipDeployment>&& new_ships);
+
+ public:
+ NavyDeployment(NavyDeployment&&) = default;
};
struct Deployment : HasIdentifier {
- friend std::unique_ptr<Deployment> std::make_unique<Deployment>(
- std::string_view&&, std::vector<OpenVic::ArmyDeployment>&&, std::vector<OpenVic::NavyDeployment>&&, std::vector<OpenVic::Leader>&&
- );
+ friend struct DeploymentManager;
private:
std::vector<ArmyDeployment> PROPERTY(armies);
@@ -70,18 +86,20 @@ namespace OpenVic {
struct DeploymentManager {
private:
- IdentifierInstanceRegistry<Deployment> IDENTIFIER_REGISTRY(deployment);
+ IdentifierRegistry<Deployment> IDENTIFIER_REGISTRY(deployment);
string_set_t missing_oob_files;
public:
bool add_deployment(
- std::string_view path, std::vector<ArmyDeployment>&& armies, std::vector<NavyDeployment>&& navies, std::vector<Leader>&& leaders
+ std::string_view path, std::vector<ArmyDeployment>&& armies, std::vector<NavyDeployment>&& navies,
+ std::vector<Leader>&& leaders
);
bool load_oob_file(
GameManager const& game_manager, Dataloader const& dataloader, std::string_view history_path,
Deployment const*& deployment, bool fail_on_missing
);
+
size_t get_missing_oob_file_count() const;
};
} // namespace OpenVic
diff --git a/src/openvic-simulation/military/Leader.hpp b/src/openvic-simulation/military/Leader.hpp
index 180fd39..5995164 100644
--- a/src/openvic-simulation/military/Leader.hpp
+++ b/src/openvic-simulation/military/Leader.hpp
@@ -19,5 +19,7 @@ namespace OpenVic {
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;
};
} \ No newline at end of file
diff --git a/src/openvic-simulation/military/MilitaryManager.hpp b/src/openvic-simulation/military/MilitaryManager.hpp
index 343d789..c2fd058 100644
--- a/src/openvic-simulation/military/MilitaryManager.hpp
+++ b/src/openvic-simulation/military/MilitaryManager.hpp
@@ -2,6 +2,7 @@
#include "openvic-simulation/military/Deployment.hpp"
#include "openvic-simulation/military/LeaderTrait.hpp"
+#include "openvic-simulation/military/UnitInstance.hpp"
#include "openvic-simulation/military/UnitType.hpp"
#include "openvic-simulation/military/Wargoal.hpp"
@@ -12,5 +13,8 @@ namespace OpenVic {
LeaderTraitManager PROPERTY_REF(leader_trait_manager);
DeploymentManager PROPERTY_REF(deployment_manager);
WargoalTypeManager PROPERTY_REF(wargoal_type_manager);
+
+ // TODO - separate this mutable game data manager from const defines data managers.
+ UnitInstanceManager PROPERTY_REF(unit_instance_manager);
};
}
diff --git a/src/openvic-simulation/military/UnitInstance.cpp b/src/openvic-simulation/military/UnitInstance.cpp
index 7927b0f..fcb9e3b 100644
--- a/src/openvic-simulation/military/UnitInstance.cpp
+++ b/src/openvic-simulation/military/UnitInstance.cpp
@@ -1,10 +1,14 @@
#include "UnitInstance.hpp"
+
#include <vector>
+
+#include "openvic-simulation/country/CountryInstance.hpp"
+#include "openvic-simulation/map/Map.hpp"
#include "openvic-simulation/military/UnitType.hpp"
using namespace OpenVic;
-RegimentInstance::RegimentInstance(std::string_view new_name, RegimentType const& new_regiment_type, Pop& new_pop)
+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)
@@ -14,18 +18,172 @@ MovementInfo::MovementInfo() : path {}, movement_progress {} {}
//TODO: pathfinding logic
MovementInfo::MovementInfo(Province const* starting_province, Province const* target_province)
- : path { std::vector { starting_province, target_province } }, movement_progress { 0 } {}
+ : path { starting_province, target_province }, movement_progress { 0 } {}
ArmyInstance::ArmyInstance(
std::string_view new_name,
std::vector<RegimentInstance*>&& new_units,
Leader const* new_leader,
- Province const* new_position
-) : UnitInstanceGroup { new_name, UnitType::branch_t::LAND, std::move(new_units), new_leader, new_position } {}
+ CountryInstance* new_country
+) : UnitInstanceGroup { new_name, UnitType::branch_t::LAND, std::move(new_units), new_leader, new_country } {}
+
+void ArmyInstance::set_position(Province* 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,
- Province const* new_position
-) : UnitInstanceGroup { new_name, UnitType::branch_t::NAVAL, std::move(new_units), new_leader, new_position } {} \ No newline at end of file
+ CountryInstance* new_country
+) : UnitInstanceGroup { new_name, UnitType::branch_t::NAVAL, std::move(new_units), new_leader, new_country } {}
+
+void NavyInstance::set_position(Province* 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(Map& map, 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.remove_province_const(army_deployment.get_location()));
+
+ return ret;
+}
+
+bool UnitInstanceManager::generate_navy(Map& map, 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.remove_province_const(navy_deployment.get_location()));
+
+ return ret;
+}
+
+bool UnitInstanceManager::generate_deployment(Map& map, 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, country, army_deployment);
+ }
+
+ for (NavyDeployment const& navy_deployment : deployment->get_navies()) {
+ ret &= generate_navy(map, country, navy_deployment);
+ }
+
+ return ret;
+}
diff --git a/src/openvic-simulation/military/UnitInstance.hpp b/src/openvic-simulation/military/UnitInstance.hpp
index dcca18a..e3d541a 100644
--- a/src/openvic-simulation/military/UnitInstance.hpp
+++ b/src/openvic-simulation/military/UnitInstance.hpp
@@ -3,7 +3,9 @@
#include <concepts>
#include <string_view>
#include <vector>
+
#include "openvic-simulation/map/Province.hpp"
+#include "openvic-simulation/military/Deployment.hpp"
#include "openvic-simulation/military/Leader.hpp"
#include "openvic-simulation/military/UnitType.hpp"
#include "openvic-simulation/types/fixed_point/FixedPoint.hpp"
@@ -11,7 +13,7 @@
namespace OpenVic {
template<std::derived_from<UnitType> T>
struct UnitInstance {
- protected:
+ private:
std::string PROPERTY(unit_name);
T const& PROPERTY(unit_type); //can't change
@@ -26,23 +28,35 @@ namespace OpenVic {
organisation { new_unit_type.get_default_organisation() }, //TODO: modifiers
morale { 0 }, //TODO: modifiers
strength { new_unit_type.get_max_strength() } {}
+
public:
+ UnitInstance(UnitInstance&&) = default;
+
void set_unit_name(std::string_view new_unit_name) {
unit_name = new_unit_name;
}
};
struct RegimentInstance : UnitInstance<RegimentType> {
+ friend struct UnitInstanceManager;
+
private:
- Pop& PROPERTY(pop);
+ Pop* PROPERTY(pop);
+
+ RegimentInstance(std::string_view new_name, RegimentType const& new_regiment_type, Pop* new_pop);
public:
- RegimentInstance(std::string_view new_name, RegimentType const& new_regiment_type, Pop& new_pop);
+ RegimentInstance(RegimentInstance&&) = default;
};
struct ShipInstance : UnitInstance<ShipType> {
- public:
+ friend struct UnitInstanceManager;
+
+ private:
ShipInstance(std::string_view new_name, ShipType const& new_ship_type);
+
+ public:
+ ShipInstance(ShipInstance&&) = default;
};
struct MovementInfo {
@@ -55,56 +69,130 @@ namespace OpenVic {
MovementInfo(Province const* starting_province, Province const* target_province); // contains/calls pathfinding logic
};
+ 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_RW(leader);
- Province const* PROPERTY_RW(position);
+ Leader const* PROPERTY(leader);
MovementInfo PROPERTY_REF(movement_info);
protected:
+ Province* 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,
- Province const* new_position
+ CountryInstance* new_country
) : name { new_name },
branch { new_branch },
units { std::move(new_units) },
leader { new_leader },
- position { new_position } {}
-
+ position { nullptr },
+ country { new_country } {}
+
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(Province* new_position) = 0;
};
struct ArmyInstance : UnitInstanceGroup<RegimentInstance> {
- public:
+ friend struct UnitInstanceManager;
+
+ private:
ArmyInstance(
std::string_view new_name,
std::vector<RegimentInstance*>&& new_units,
Leader const* new_leader,
- Province const* new_position
+ CountryInstance* new_country
);
+
+ public:
+ ArmyInstance(ArmyInstance&&) = default;
+
+ void set_position(Province* new_position) override;
};
struct NavyInstance : UnitInstanceGroup<ShipInstance> {
+ friend struct UnitInstanceManager;
+
private:
std::vector<ArmyInstance const*> PROPERTY(carried_armies);
- public:
NavyInstance(
std::string_view new_name,
std::vector<ShipInstance*>&& new_ships,
Leader const* new_leader,
- Province const* new_position
+ CountryInstance* new_country
);
+
+ public:
+ NavyInstance(NavyInstance&&) = default;
+
+ void set_position(Province* new_position) override;
+ };
+
+ 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(Map& map, CountryInstance& country, ArmyDeployment const& army_deployment);
+ bool generate_navy(Map& map, CountryInstance& country, NavyDeployment const& navy_deployment);
+
+ public:
+ bool generate_deployment(Map& map, CountryInstance& country, Deployment const* deployment);
};
-} \ No newline at end of file
+}