diff options
Diffstat (limited to 'src/openvic-simulation/military/UnitInstanceGroup.cpp')
-rw-r--r-- | src/openvic-simulation/military/UnitInstanceGroup.cpp | 254 |
1 files changed, 177 insertions, 77 deletions
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 = ®iment_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; |