diff --git a/src/openvic-simulation/country/CountryDefinition.cpp b/src/openvic-simulation/country/CountryDefinition.cpp index 30c39bbf..f8562e4e 100644 --- a/src/openvic-simulation/country/CountryDefinition.cpp +++ b/src/openvic-simulation/country/CountryDefinition.cpp @@ -64,9 +64,9 @@ bool CountryDefinitionManager::add_country( static constexpr colour_t default_colour = colour_t::fill_as(colour_t::max_value); return country_definitions.emplace_item( - identifier, - identifier, colour, get_country_definition_count(), *graphical_culture, std::move(parties), std::move(unit_names), - dynamic_tag, std::move(alternative_colours), + identifier, // + identifier, colour, CountryDefinition::index_t { get_country_definition_count() }, *graphical_culture, + std::move(parties), std::move(unit_names), dynamic_tag, std::move(alternative_colours), /* Default to country colour for the chest and grey for the others. Update later if necessary. */ colour, default_colour, default_colour ); diff --git a/src/openvic-simulation/country/CountryDefinition.hpp b/src/openvic-simulation/country/CountryDefinition.hpp index 3b732aad..9d745dc0 100644 --- a/src/openvic-simulation/country/CountryDefinition.hpp +++ b/src/openvic-simulation/country/CountryDefinition.hpp @@ -9,6 +9,7 @@ #include "openvic-simulation/types/HasIndex.hpp" #include "openvic-simulation/types/IdentifierRegistry.hpp" #include "openvic-simulation/types/OrderedContainers.hpp" +#include "openvic-simulation/types/TypedIndices.hpp" namespace OpenVic { struct CountryDefinitionManager; @@ -20,7 +21,7 @@ namespace OpenVic { struct UnitType; /* Generic information about a TAG */ - struct CountryDefinition : HasIdentifierAndColour, HasIndex { + struct CountryDefinition : HasIdentifierAndColour, HasIndex { friend struct CountryDefinitionManager; using unit_names_map_t = ordered_map; diff --git a/src/openvic-simulation/country/CountryInstance.cpp b/src/openvic-simulation/country/CountryInstance.cpp index c5da10b6..faf882ee 100644 --- a/src/openvic-simulation/country/CountryInstance.cpp +++ b/src/openvic-simulation/country/CountryInstance.cpp @@ -6,6 +6,8 @@ #include #include +#include + #include "openvic-simulation/country/SharedCountryValues.hpp" #include "openvic-simulation/country/CountryDefinition.hpp" #include "openvic-simulation/defines/CountryDefines.hpp" @@ -2065,7 +2067,7 @@ void CountryInstance::manage_national_stockpile( fixed_point_t weights_sum = 0; for (auto [good_instance, good_data] : goods_data) { - const size_t index = good_instance.index; + const size_t index = type_safe::get(good_instance.index); if (good_data.is_automated || !good_data.is_selling) { const fixed_point_t quantity_to_allocate_for = good_data.is_automated ? good_data.government_needs - good_data.stockpile_amount diff --git a/src/openvic-simulation/country/CountryInstance.hpp b/src/openvic-simulation/country/CountryInstance.hpp index ed10fbc5..13ddda28 100644 --- a/src/openvic-simulation/country/CountryInstance.hpp +++ b/src/openvic-simulation/country/CountryInstance.hpp @@ -18,6 +18,7 @@ #include "openvic-simulation/types/IndexedFlatMap.hpp" #include "openvic-simulation/types/OrderedContainers.hpp" #include "openvic-simulation/types/TechnologyUnlockLevel.hpp" +#include "openvic-simulation/types/TypedIndices.hpp" #include "openvic-simulation/types/UnitBranchType.hpp" #include "openvic-simulation/types/UnitVariant.hpp" #include "openvic-simulation/types/ValueHistory.hpp" @@ -78,7 +79,7 @@ namespace OpenVic { /* Representation of a country's mutable attributes, with a CountryDefinition that is unique at any single time * but can be swapped with other CountryInstance's CountryDefinition when switching tags. */ - struct CountryInstance : FlagStrings, HasIndex, PopsAggregate { + struct CountryInstance : FlagStrings, HasIndex, PopsAggregate { friend struct CountryInstanceManager; /* diff --git a/src/openvic-simulation/dataloader/Dataloader.cpp b/src/openvic-simulation/dataloader/Dataloader.cpp index 3b103d76..9607260a 100644 --- a/src/openvic-simulation/dataloader/Dataloader.cpp +++ b/src/openvic-simulation/dataloader/Dataloader.cpp @@ -784,7 +784,7 @@ bool Dataloader::_load_map_dir(DefinitionManager& definition_manager) const { bool ret = expect_dictionary_keys( "max_provinces", ONE_EXACTLY, - expect_uint(std::bind_front(&MapDefinition::set_max_provinces, &map_definition)), + expect_index(std::bind_front(&MapDefinition::set_max_provinces, &map_definition)), "sea_starts", ONE_EXACTLY, expect_list_reserve_length( water_province_identifiers, expect_identifier(vector_callback(water_province_identifiers)) diff --git a/src/openvic-simulation/dataloader/NodeTools.hpp b/src/openvic-simulation/dataloader/NodeTools.hpp index 0eb6a486..5886e8fa 100644 --- a/src/openvic-simulation/dataloader/NodeTools.hpp +++ b/src/openvic-simulation/dataloader/NodeTools.hpp @@ -1,5 +1,6 @@ #pragma once +#include #include #include #include @@ -13,6 +14,8 @@ #include +#include + #include "openvic-simulation/types/Colour.hpp" #include "openvic-simulation/types/Date.hpp" #include "openvic-simulation/types/IndexedFlatMap.hpp" @@ -195,6 +198,28 @@ using namespace std::string_view_literals; return expect_uint(callback, base); } + template T> + requires std::unsigned_integral> + NodeCallback auto expect_index(callback_t& callback, int base = 10) { + using underlying_type = type_safe::underlying_type; + + return expect_uint64([callback](uint64_t val) mutable -> bool { + if (val <= static_cast(std::numeric_limits::max())) { + return callback(T(val)); + } + spdlog::error_s( + "Invalid uint: {} (valid range: [0, {}])", + val, static_cast(std::numeric_limits::max()) + ); + return false; + }, base); + } + template T> + requires std::unsigned_integral> + NodeCallback auto expect_index(callback_t&& callback, int base = 10) { + return expect_index(callback, base); + } + callback_t expect_fixed_point_str(callback_t callback); node_callback_t expect_fixed_point(callback_t callback); /* Expect a list of 3 base 10 values, each either in the range [0, 1] or (1, 255], representing RGB components. */ diff --git a/src/openvic-simulation/economy/BuildingType.cpp b/src/openvic-simulation/economy/BuildingType.cpp index 08caa684..5b0ff0a8 100644 --- a/src/openvic-simulation/economy/BuildingType.cpp +++ b/src/openvic-simulation/economy/BuildingType.cpp @@ -12,7 +12,7 @@ BuildingType::BuildingType( index_t new_index, std::string_view identifier, building_type_args_t& building_type_args -) : HasIndex { new_index }, +) : HasIndex { new_index }, Modifier { identifier, std::move(building_type_args.modifier), modifier_type_t::BUILDING }, type { building_type_args.type }, on_completion { building_type_args.on_completion }, @@ -52,7 +52,7 @@ bool BuildingTypeManager::add_building_type( const bool ret = building_types.emplace_item( identifier, - get_building_type_count(), identifier, building_type_args + BuildingType::index_t { get_building_type_count() }, identifier, building_type_args ); if (ret) { diff --git a/src/openvic-simulation/economy/BuildingType.hpp b/src/openvic-simulation/economy/BuildingType.hpp index f8b0d205..a64ebe62 100644 --- a/src/openvic-simulation/economy/BuildingType.hpp +++ b/src/openvic-simulation/economy/BuildingType.hpp @@ -6,6 +6,7 @@ #include "openvic-simulation/types/HasIndex.hpp" #include "openvic-simulation/types/IdentifierRegistry.hpp" #include "openvic-simulation/types/fixed_point/FixedPoint.hpp" +#include "openvic-simulation/types/TypedIndices.hpp" #include "openvic-simulation/utility/Containers.hpp" namespace OpenVic { @@ -19,7 +20,7 @@ namespace OpenVic { * MAP-12, MAP-75, MAP-76 * MAP-13, MAP-78, MAP-79 */ - struct BuildingType : HasIndex, Modifier { + struct BuildingType : HasIndex, Modifier { using naval_capacity_t = uint64_t; struct building_type_args_t { diff --git a/src/openvic-simulation/economy/GoodDefinition.cpp b/src/openvic-simulation/economy/GoodDefinition.cpp index 2c84d529..79db6e34 100644 --- a/src/openvic-simulation/economy/GoodDefinition.cpp +++ b/src/openvic-simulation/economy/GoodDefinition.cpp @@ -63,7 +63,7 @@ bool GoodDefinitionManager::add_good_definition( if (good_definitions.emplace_item( identifier, - identifier, colour, get_good_definition_count(), category, base_price, is_available_from_start, + identifier, colour, GoodDefinition::index_t { get_good_definition_count() }, category, base_price, is_available_from_start, is_tradeable, is_money, has_overseas_penalty )) { category.good_definitions.push_back(&get_back_good_definition()); diff --git a/src/openvic-simulation/economy/GoodDefinition.hpp b/src/openvic-simulation/economy/GoodDefinition.hpp index dcf1dac8..5510d237 100644 --- a/src/openvic-simulation/economy/GoodDefinition.hpp +++ b/src/openvic-simulation/economy/GoodDefinition.hpp @@ -3,6 +3,7 @@ #include "openvic-simulation/types/HasIdentifier.hpp" #include "openvic-simulation/types/HasIndex.hpp" #include "openvic-simulation/types/IdentifierRegistry.hpp" +#include "openvic-simulation/types/TypedIndices.hpp" #include "openvic-simulation/utility/Containers.hpp" namespace OpenVic { @@ -31,7 +32,7 @@ namespace OpenVic { * ECON-238, ECON-239, ECON-240, ECON-241, ECON-242, ECON-243, ECON-244, ECON-245, ECON-246, ECON-247, ECON-248, ECON-249, * ECON-250, ECON-251, ECON-252, ECON-253, ECON-254, ECON-255, ECON-256, ECON-257, ECON-258, ECON-259, ECON-260, ECON-261 */ - struct GoodDefinition : HasIdentifierAndColour, HasIndex { + struct GoodDefinition : HasIdentifierAndColour, HasIndex { public: GoodCategory const& category; diff --git a/src/openvic-simulation/economy/GoodInstance.cpp b/src/openvic-simulation/economy/GoodInstance.cpp index 5811027a..34ab86a3 100644 --- a/src/openvic-simulation/economy/GoodInstance.cpp +++ b/src/openvic-simulation/economy/GoodInstance.cpp @@ -10,7 +10,7 @@ GoodInstance::GoodInstance( GoodDefinition const* new_good_definition, GameRulesManager const* new_game_rules_manager ) : HasIdentifierAndColour { *new_good_definition }, - HasIndex { new_good_definition->index }, + HasIndex { new_good_definition->index }, GoodMarket { *new_game_rules_manager, *new_good_definition } {} diff --git a/src/openvic-simulation/economy/GoodInstance.hpp b/src/openvic-simulation/economy/GoodInstance.hpp index ba69c365..fc39b01a 100644 --- a/src/openvic-simulation/economy/GoodInstance.hpp +++ b/src/openvic-simulation/economy/GoodInstance.hpp @@ -3,13 +3,14 @@ #include "openvic-simulation/economy/trading/GoodMarket.hpp" #include "openvic-simulation/types/HasIndex.hpp" #include "openvic-simulation/types/HasIdentifier.hpp" +#include "openvic-simulation/types/TypedIndices.hpp" namespace OpenVic { struct GoodDefinition; struct GoodDefinitionManager; struct GoodInstanceManager; - struct GoodInstance : HasIdentifierAndColour, HasIndex, GoodMarket { + struct GoodInstance : HasIdentifierAndColour, HasIndex, GoodMarket { friend struct GoodInstanceManager; public: diff --git a/src/openvic-simulation/economy/production/ArtisanalProducer.cpp b/src/openvic-simulation/economy/production/ArtisanalProducer.cpp index cf8aa304..14b5f966 100644 --- a/src/openvic-simulation/economy/production/ArtisanalProducer.cpp +++ b/src/openvic-simulation/economy/production/ArtisanalProducer.cpp @@ -3,6 +3,8 @@ #include +#include + #include "openvic-simulation/country/CountryInstance.hpp" #include "openvic-simulation/defines/EconomyDefines.hpp" #include "openvic-simulation/economy/GoodDefinition.hpp" @@ -267,7 +269,7 @@ void ArtisanalProducer::artisan_tick_handler::allocate_money_for_inputs( ); max_quantity_to_buy_per_good[&input_good] = max_quantity_to_buy; pop.allocate_cash_for_artisanal_spending(money_to_spend); - const size_t index_in_all_goods = input_good.index; + const size_t index_in_all_goods = type_safe::get(input_good.index); pop_max_quantity_to_buy_per_good[index_in_all_goods] += max_quantity_to_buy; pop_money_to_spend_per_good[index_in_all_goods] += money_to_spend; debug_cash_left -= money_to_spend; diff --git a/src/openvic-simulation/history/Bookmark.cpp b/src/openvic-simulation/history/Bookmark.cpp index d60b98c2..d2fb7c6b 100644 --- a/src/openvic-simulation/history/Bookmark.cpp +++ b/src/openvic-simulation/history/Bookmark.cpp @@ -2,6 +2,8 @@ #include +#include + #include "openvic-simulation/dataloader/NodeTools.hpp" #include "openvic-simulation/types/Date.hpp" #include "openvic-simulation/types/IdentifierRegistry.hpp" @@ -16,7 +18,7 @@ Bookmark::Bookmark( std::string_view new_description, Date new_date, fvec2_t new_initial_camera_position -) : HasIdentifier { std::to_string(new_index) }, +) : HasIdentifier { std::to_string(type_safe::get(new_index)) }, HasIndex { new_index }, name { new_name }, description { new_description }, @@ -28,7 +30,7 @@ bool BookmarkManager::add_bookmark( ) { return bookmarks.emplace_item( name, - bookmarks.size(), name, description, date, initial_camera_position + Bookmark::index_t { bookmarks.size() }, name, description, date, initial_camera_position ); } diff --git a/src/openvic-simulation/history/Bookmark.hpp b/src/openvic-simulation/history/Bookmark.hpp index 3682e722..4584d628 100644 --- a/src/openvic-simulation/history/Bookmark.hpp +++ b/src/openvic-simulation/history/Bookmark.hpp @@ -7,9 +7,10 @@ #include "openvic-simulation/types/HasIdentifier.hpp" #include "openvic-simulation/types/HasIndex.hpp" #include "openvic-simulation/types/IdentifierRegistry.hpp" +#include "openvic-simulation/types/TypedIndices.hpp" namespace OpenVic { - struct Bookmark : HasIdentifier, HasIndex { + struct Bookmark : HasIdentifier, HasIndex { private: memory::string PROPERTY(name); diff --git a/src/openvic-simulation/history/ProvinceHistory.cpp b/src/openvic-simulation/history/ProvinceHistory.cpp index ffd0cad6..f788cf32 100644 --- a/src/openvic-simulation/history/ProvinceHistory.cpp +++ b/src/openvic-simulation/history/ProvinceHistory.cpp @@ -1,5 +1,7 @@ #include "ProvinceHistory.hpp" +#include + #include "openvic-simulation/dataloader/NodeTools.hpp" #include "openvic-simulation/DefinitionManager.hpp" #include "openvic-simulation/economy/GoodDefinition.hpp" @@ -192,7 +194,7 @@ void ProvinceHistoryManager::lock_province_histories(MapDefinition const& map_de memory::vector province_checklist(provinces.size()); for (auto [province, history_map] : mutable_iterator(province_histories)) { - province_checklist[province->index] = true; + province_checklist[type_safe::get(province->index)] = true; history_map.sort_entries(); } diff --git a/src/openvic-simulation/map/Crime.cpp b/src/openvic-simulation/map/Crime.cpp index bdfa180b..fa18bb18 100644 --- a/src/openvic-simulation/map/Crime.cpp +++ b/src/openvic-simulation/map/Crime.cpp @@ -13,7 +13,7 @@ Crime::Crime( icon_t new_icon, ConditionScript&& new_trigger, bool new_default_active -) : HasIndex { new_index }, +) : HasIndex { new_index }, TriggeredModifier { new_identifier, std::move(new_values), modifier_type_t::CRIME, new_icon, std::move(new_trigger) }, default_active { new_default_active } {} @@ -29,7 +29,7 @@ bool CrimeManager::add_crime_modifier( return crime_modifiers.emplace_item( identifier, duplicate_warning_callback, - get_crime_modifier_count(), identifier, std::move(values), icon, std::move(trigger), default_active + Crime::index_t { get_crime_modifier_count() }, identifier, std::move(values), icon, std::move(trigger), default_active ); } diff --git a/src/openvic-simulation/map/Crime.hpp b/src/openvic-simulation/map/Crime.hpp index 0404e672..3a4a4548 100644 --- a/src/openvic-simulation/map/Crime.hpp +++ b/src/openvic-simulation/map/Crime.hpp @@ -2,11 +2,12 @@ #include "openvic-simulation/modifier/Modifier.hpp" #include "openvic-simulation/types/HasIndex.hpp" +#include "openvic-simulation/types/TypedIndices.hpp" namespace OpenVic { struct CrimeManager; - struct Crime final : HasIndex, TriggeredModifier { + struct Crime final : HasIndex, TriggeredModifier { friend struct CrimeManager; private: diff --git a/src/openvic-simulation/map/MapDefinition.cpp b/src/openvic-simulation/map/MapDefinition.cpp index 34585dc4..55b282e9 100644 --- a/src/openvic-simulation/map/MapDefinition.cpp +++ b/src/openvic-simulation/map/MapDefinition.cpp @@ -14,6 +14,8 @@ #include #include +#include + #include "openvic-simulation/dataloader/NodeTools.hpp" #include "openvic-simulation/map/ProvinceDefinition.hpp" #include "openvic-simulation/modifier/ModifierManager.hpp" @@ -35,19 +37,19 @@ MapDefinition::MapDefinition() {} ProvinceDefinition* MapDefinition::get_province_definition_from_number( decltype(std::declval().get_province_number())province_number ) { - return province_definitions.get_item_by_index(ProvinceDefinition::get_index_from_province_number(province_number)); + return province_definitions.get_item_by_index(type_safe::get(ProvinceDefinition::get_index_from_province_number(province_number))); } ProvinceDefinition const* MapDefinition::get_province_definition_from_number( decltype(std::declval().get_province_number())province_number ) const { - return province_definitions.get_item_by_index(ProvinceDefinition::get_index_from_province_number(province_number)); + return province_definitions.get_item_by_index(type_safe::get(ProvinceDefinition::get_index_from_province_number(province_number))); } RiverSegment::RiverSegment(uint8_t new_size, memory::vector&& new_points) : size { new_size }, points { std::move(new_points) } {} bool MapDefinition::add_province_definition(std::string_view identifier, colour_t colour) { - if (province_definitions.size() >= max_provinces) { + if (province_definitions.size() >= type_safe::get(max_provinces)) { spdlog::error_s( "The map's province list is full - maximum number of provinces is {} (this can be at most {})", max_provinces, ProvinceDefinition::MAX_INDEX @@ -73,20 +75,20 @@ bool MapDefinition::add_province_definition(std::string_view identifier, colour_ if (province_number != ProvinceDefinition::NULL_INDEX) { spdlog::error_s( "Duplicate province colours: {} and {}", - get_province_definition_from_number(province_number)->to_string(), identifier + get_province_definition_from_number(type_safe::get(province_number))->to_string(), identifier ); return false; } if (!province_definitions.emplace_item( identifier, - identifier, colour, get_province_definition_count() + identifier, colour, ProvinceDefinition::index_t(get_province_definition_count()) )) { return false; } ProvinceDefinition const& new_province = province_definitions.back(); - colour_index_map[new_province.get_colour()] = new_province.get_province_number(); + colour_index_map[new_province.get_colour()] = ProvinceDefinition::index_t(new_province.get_province_number()); return true; } @@ -482,11 +484,11 @@ ProvinceDefinition::index_t MapDefinition::get_province_number_at(ivec2_t pos) c } ProvinceDefinition* MapDefinition::get_province_definition_at(ivec2_t pos) { - return get_province_definition_from_number(get_province_number_at(pos)); + return get_province_definition_from_number(type_safe::get(get_province_number_at(pos))); } ProvinceDefinition const* MapDefinition::get_province_definition_at(ivec2_t pos) const { - return get_province_definition_from_number(get_province_number_at(pos)); + return get_province_definition_from_number(type_safe::get(get_province_number_at(pos))); } bool MapDefinition::set_max_provinces(ProvinceDefinition::index_t new_max_provinces) { @@ -504,8 +506,8 @@ bool MapDefinition::set_max_provinces(ProvinceDefinition::index_t new_max_provin return false; } max_provinces = new_max_provinces; - path_map_land.reserve_space(max_provinces); - path_map_sea.reserve_space(max_provinces); + path_map_land.reserve_space(type_safe::get(max_provinces)); + path_map_sea.reserve_space(type_safe::get(max_provinces)); return true; } @@ -892,15 +894,15 @@ bool MapDefinition::load_map_images(fs::path const& province_path, fs::path cons if (province_number != ProvinceDefinition::NULL_INDEX) { const ProvinceDefinition::index_t array_index = province_number - 1; - pixels_per_province[array_index]++; - pixel_position_sum_per_province[array_index] += static_cast(pos); + pixels_per_province[type_safe::get(array_index)]++; + pixel_position_sum_per_province[type_safe::get(array_index)] += static_cast(pos); } const TerrainTypeMapping::index_t terrain = terrain_data[pixel_index]; TerrainTypeMapping const* mapping = terrain_type_manager.get_terrain_type_mapping_for(terrain); if (mapping != nullptr) { if (province_number != ProvinceDefinition::NULL_INDEX) { - terrain_type_pixels_list[province_number - 1][&mapping->type]++; + terrain_type_pixels_list[type_safe::get(province_number - 1)][&mapping->type]++; } if (mapping->has_texture && terrain < terrain_type_manager.get_terrain_texture_limit()) { province_shape_image[pixel_index].terrain = terrain + 1; diff --git a/src/openvic-simulation/map/Mapmode.cpp b/src/openvic-simulation/map/Mapmode.cpp index c217dc11..200d55b5 100644 --- a/src/openvic-simulation/map/Mapmode.cpp +++ b/src/openvic-simulation/map/Mapmode.cpp @@ -1,5 +1,9 @@ #include "Mapmode.hpp" +#include + +#include + #include "openvic-simulation/country/CountryInstance.hpp" #include "openvic-simulation/economy/BuildingType.hpp" #include "openvic-simulation/economy/GoodDefinition.hpp" // IWYU pragma: keep @@ -28,7 +32,7 @@ Mapmode::Mapmode( parchment_mapmode_allowed { new_parchment_mapmode_allowed } {} const Mapmode Mapmode::ERROR_MAPMODE { - "mapmode_error", -1, []( + "mapmode_error", index_t { std::numeric_limits::max() }, []( MapInstance const& map_instance, ProvinceInstance const& province, CountryInstance const* player_country, ProvinceInstance const* selected_province ) -> base_stripe_t { @@ -59,7 +63,7 @@ bool MapmodeManager::add_mapmode( } return mapmodes.emplace_item( identifier, - identifier, get_mapmode_count(), colour_func, localisation_key, parchment_mapmode_allowed + identifier, Mapmode::index_t { get_mapmode_count() }, colour_func, localisation_key, parchment_mapmode_allowed ); } @@ -84,7 +88,7 @@ bool MapmodeManager::generate_mapmode_colours( Mapmode::base_stripe_t* target_stripes = reinterpret_cast(target); - target_stripes[ProvinceDefinition::NULL_INDEX] = colour_argb_t::null(); + target_stripes[type_safe::get(ProvinceDefinition::NULL_INDEX)] = colour_argb_t::null(); for (ProvinceInstance const& province : map_instance.get_province_instances()) { target_stripes[province.province_definition.get_province_number()] = mapmode->get_base_stripe_colours( diff --git a/src/openvic-simulation/map/Mapmode.hpp b/src/openvic-simulation/map/Mapmode.hpp index df1fb35f..530248d6 100644 --- a/src/openvic-simulation/map/Mapmode.hpp +++ b/src/openvic-simulation/map/Mapmode.hpp @@ -4,6 +4,7 @@ #include "openvic-simulation/types/HasIdentifier.hpp" #include "openvic-simulation/types/HasIndex.hpp" #include "openvic-simulation/types/IdentifierRegistry.hpp" +#include "openvic-simulation/types/TypedIndices.hpp" #include @@ -14,7 +15,7 @@ namespace OpenVic { struct ProvinceInstance; struct CountryInstance; - struct Mapmode : HasIdentifier, HasIndex { + struct Mapmode : HasIdentifier, HasIndex { /* Bottom 32 bits are the base colour, top 32 are the stripe colour, both in ARGB format with the alpha channels * controlling interpolation with the terrain colour (0 = all terrain, 255 = all corresponding RGB) */ struct base_stripe_t { diff --git a/src/openvic-simulation/map/ProvinceDefinition.hpp b/src/openvic-simulation/map/ProvinceDefinition.hpp index 2126e1e5..848a61e3 100644 --- a/src/openvic-simulation/map/ProvinceDefinition.hpp +++ b/src/openvic-simulation/map/ProvinceDefinition.hpp @@ -1,6 +1,7 @@ #pragma once #include +#include #include "openvic-simulation/dataloader/NodeTools.hpp" #include "openvic-simulation/types/fixed_point/FixedPoint.hpp" @@ -8,6 +9,7 @@ #include "openvic-simulation/types/HasIdentifier.hpp" #include "openvic-simulation/types/HasIndex.hpp" #include "openvic-simulation/types/OrderedContainers.hpp" +#include "openvic-simulation/types/TypedIndices.hpp" #include "openvic-simulation/types/Vector.hpp" #include "openvic-simulation/utility/Containers.hpp" @@ -26,7 +28,7 @@ namespace OpenVic { * MAP-5, MAP-7, MAP-8, MAP-43, MAP-47 * POP-22 */ - struct ProvinceDefinition : HasIdentifierAndColour, HasIndex { + struct ProvinceDefinition : HasIdentifierAndColour, HasIndex { friend struct MapDefinition; using distance_t = fixed_point_t; // should this go inside adjacency_t? @@ -82,7 +84,7 @@ namespace OpenVic { fixed_point_map_t building_rotation; }; - static constexpr index_t NULL_INDEX = 0, MAX_INDEX = std::numeric_limits::max(); + static constexpr index_t NULL_INDEX { 0 }, MAX_INDEX = std::numeric_limits::max(); private: /* Immutable attributes (unchanged after initial game load) */ @@ -112,11 +114,11 @@ namespace OpenVic { return region != nullptr; } - constexpr index_t get_province_number() const { - return index+1; + constexpr std::size_t get_province_number() const { + return index.value_ + 1; } - static constexpr index_t get_index_from_province_number(const index_t province_number) { - return province_number - 1; + static constexpr index_t get_index_from_province_number(const std::size_t province_number) { + return index_t(province_number - 1); } /* The positions' y coordinates need to be inverted. */ diff --git a/src/openvic-simulation/map/ProvinceInstance.hpp b/src/openvic-simulation/map/ProvinceInstance.hpp index 7ed30ffb..943e3485 100644 --- a/src/openvic-simulation/map/ProvinceInstance.hpp +++ b/src/openvic-simulation/map/ProvinceInstance.hpp @@ -14,6 +14,7 @@ #include "openvic-simulation/types/HasIndex.hpp" #include "openvic-simulation/types/OrderedContainers.hpp" #include "openvic-simulation/types/ProvinceLifeRating.hpp" +#include "openvic-simulation/types/TypedIndices.hpp" #include "openvic-simulation/types/UnitBranchType.hpp" #include "openvic-simulation/utility/Containers.hpp" #include "openvic-simulation/utility/ForwardableSpan.hpp" @@ -48,7 +49,7 @@ namespace OpenVic { //HasIndex index_t must match ProvinceDefinition's index_t struct ProvinceInstance : HasIdentifierAndColour, - HasIndex, + HasIndex, FlagStrings, PopsAggregate { friend struct MapInstance; diff --git a/src/openvic-simulation/map/TerrainType.cpp b/src/openvic-simulation/map/TerrainType.cpp index 118e4f09..3d134f1b 100644 --- a/src/openvic-simulation/map/TerrainType.cpp +++ b/src/openvic-simulation/map/TerrainType.cpp @@ -20,7 +20,7 @@ TerrainType::TerrainType( fixed_point_t new_defence_bonus, fixed_point_t new_combat_width_percentage_change, bool new_is_water -) : HasIndex { new_index }, +) : HasIndex { new_index }, Modifier { new_identifier, std::move(new_modifier), modifier_type_t::TERRAIN }, HasColour { new_colour, false }, movement_cost { new_movement_cost }, @@ -95,7 +95,7 @@ bool TerrainTypeManager::add_terrain_type( return terrain_types.emplace_item( identifier, - get_terrain_type_count(), identifier, + TerrainType::index_t { get_terrain_type_count() }, identifier, colour, std::move(values), movement_cost, defence_bonus, combat_width_percentage_change, is_water ); } diff --git a/src/openvic-simulation/map/TerrainType.hpp b/src/openvic-simulation/map/TerrainType.hpp index 4d78afb6..0857f0a0 100644 --- a/src/openvic-simulation/map/TerrainType.hpp +++ b/src/openvic-simulation/map/TerrainType.hpp @@ -4,12 +4,13 @@ #include "openvic-simulation/types/HasIdentifier.hpp" #include "openvic-simulation/types/HasIndex.hpp" #include "openvic-simulation/types/OrderedContainers.hpp" +#include "openvic-simulation/types/TypedIndices.hpp" #include "openvic-simulation/utility/Containers.hpp" namespace OpenVic { // Using HasColour rather than HasIdentifierAndColour to avoid needing virtual inheritance // (extending Modifier is more useful than extending HasIdentifierAndColour). - struct TerrainType : HasIndex, Modifier, public HasColour { + struct TerrainType : HasIndex, Modifier, public HasColour { private: ModifierValue PROPERTY(modifier); fixed_point_t PROPERTY(movement_cost); diff --git a/src/openvic-simulation/military/UnitType.cpp b/src/openvic-simulation/military/UnitType.cpp index 60d64027..e07fa392 100644 --- a/src/openvic-simulation/military/UnitType.cpp +++ b/src/openvic-simulation/military/UnitType.cpp @@ -48,7 +48,7 @@ UnitTypeBranched::UnitTypeBranched( index_t new_index, 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 }, - HasIndex> { new_index }, + HasIndex { new_index }, allowed_cultures { regiment_type_args.allowed_cultures }, sprite_override { regiment_type_args.sprite_override }, sprite_mount { regiment_type_args.sprite_mount }, @@ -65,7 +65,7 @@ UnitTypeBranched::UnitTypeBranched( index_t new_index, 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 }, - HasIndex> { new_index }, + HasIndex { new_index }, naval_icon { ship_type_args.naval_icon }, sail { ship_type_args.sail }, transport { ship_type_args.transport }, @@ -133,7 +133,7 @@ bool UnitTypeManager::add_regiment_type( bool ret = regiment_types.emplace_item( identifier, - get_regiment_type_count(), identifier, + RegimentType::index_t { get_regiment_type_count() }, identifier, unit_args, std::move(regiment_type_args) ); if (ret) { @@ -166,7 +166,7 @@ bool UnitTypeManager::add_ship_type( bool ret = ship_types.emplace_item( identifier, - get_ship_type_count(), identifier, + ShipType::index_t { get_ship_type_count() }, identifier, unit_args, ship_type_args ); if (ret) { diff --git a/src/openvic-simulation/military/UnitType.hpp b/src/openvic-simulation/military/UnitType.hpp index 689b02ff..12175818 100644 --- a/src/openvic-simulation/military/UnitType.hpp +++ b/src/openvic-simulation/military/UnitType.hpp @@ -13,6 +13,7 @@ #include "openvic-simulation/types/HasIndex.hpp" #include "openvic-simulation/types/IdentifierRegistry.hpp" #include "openvic-simulation/types/fixed_point/FixedPoint.hpp" +#include "openvic-simulation/types/TypedIndices.hpp" #include "openvic-simulation/types/UnitBranchType.hpp" namespace OpenVic { @@ -82,7 +83,7 @@ namespace OpenVic { }; template<> - struct UnitTypeBranched : UnitType, HasIndex> { + struct UnitTypeBranched : UnitType, HasIndex { static constexpr regiment_allowed_cultures_t allowed_cultures_get_most_permissive( regiment_allowed_cultures_t lhs, regiment_allowed_cultures_t rhs ) { @@ -124,7 +125,7 @@ namespace OpenVic { }; template<> - struct UnitTypeBranched : UnitType, HasIndex> { + struct UnitTypeBranched : UnitType, HasIndex { struct ship_type_args_t { icon_t naval_icon = 0; bool sail = false, transport = false, capital = false, build_overseas = false; diff --git a/src/openvic-simulation/misc/GameAction.cpp b/src/openvic-simulation/misc/GameAction.cpp index f4e06230..2ae12c0f 100644 --- a/src/openvic-simulation/misc/GameAction.cpp +++ b/src/openvic-simulation/misc/GameAction.cpp @@ -137,7 +137,7 @@ bool GameActionManager::game_action_callback_set_speed(game_action_argument_t co } bool GameActionManager::game_action_callback_set_ai(game_action_argument_t const& argument) const { - std::pair const* country_ai = std::get_if>(&argument); + std::pair const* country_ai = std::get_if>(&argument); if (OV_unlikely(country_ai == nullptr)) { spdlog::error_s("GAME_ACTION_SET_AI called with invalid argument: {}", game_action_argument_to_string(argument)); return false; @@ -180,8 +180,8 @@ bool GameActionManager::game_action_callback_expand_province_building(game_actio // Budget bool GameActionManager::game_action_callback_set_strata_tax(game_action_argument_t const& argument) const { - std::tuple const* country_strata_value = - std::get_if>(&argument); + std::tuple const* country_strata_value = + std::get_if>(&argument); if (OV_unlikely(country_strata_value == nullptr)) { spdlog::error_s("GAME_ACTION_SET_STRATA_TAX called with invalid argument: {}", game_action_argument_to_string(argument)); return false; @@ -208,7 +208,7 @@ bool GameActionManager::game_action_callback_set_strata_tax(game_action_argument } bool GameActionManager::game_action_callback_set_army_spending(game_action_argument_t const& argument) const { - std::pair const* country_value = std::get_if>(&argument); + std::pair const* country_value = std::get_if>(&argument); if (OV_unlikely(country_value == nullptr)) { spdlog::error_s( "GAME_ACTION_SET_ARMY_SPENDING called with invalid argument: {}", game_action_argument_to_string(argument) @@ -229,7 +229,7 @@ bool GameActionManager::game_action_callback_set_army_spending(game_action_argum } bool GameActionManager::game_action_callback_set_navy_spending(game_action_argument_t const& argument) const { - std::pair const* country_value = std::get_if>(&argument); + std::pair const* country_value = std::get_if>(&argument); if (OV_unlikely(country_value == nullptr)) { spdlog::error_s( "GAME_ACTION_SET_NAVY_SPENDING called with invalid argument: {}", game_action_argument_to_string(argument) @@ -250,7 +250,7 @@ bool GameActionManager::game_action_callback_set_navy_spending(game_action_argum } bool GameActionManager::game_action_callback_set_construction_spending(game_action_argument_t const& argument) const { - std::pair const* country_value = std::get_if>(&argument); + std::pair const* country_value = std::get_if>(&argument); if (OV_unlikely(country_value == nullptr)) { spdlog::error_s( "GAME_ACTION_SET_CONSTRUCTION_SPENDING called with invalid argument: {}", game_action_argument_to_string(argument) @@ -271,7 +271,7 @@ bool GameActionManager::game_action_callback_set_construction_spending(game_acti } bool GameActionManager::game_action_callback_set_education_spending(game_action_argument_t const& argument) const { - std::pair const* country_value = std::get_if>(&argument); + std::pair const* country_value = std::get_if>(&argument); if (OV_unlikely(country_value == nullptr)) { spdlog::error_s( "GAME_ACTION_SET_EDUCATION_SPENDING called with invalid argument: {}", game_action_argument_to_string(argument) @@ -292,7 +292,7 @@ bool GameActionManager::game_action_callback_set_education_spending(game_action_ } bool GameActionManager::game_action_callback_set_administration_spending(game_action_argument_t const& argument) const { - std::pair const* country_value = std::get_if>(&argument); + std::pair const* country_value = std::get_if>(&argument); if (OV_unlikely(country_value == nullptr)) { spdlog::error_s( "GAME_ACTION_SET_ADMINISTRATION_SPENDING called with invalid argument: {}", game_action_argument_to_string(argument) @@ -313,7 +313,7 @@ bool GameActionManager::game_action_callback_set_administration_spending(game_ac } bool GameActionManager::game_action_callback_set_social_spending(game_action_argument_t const& argument) const { - std::pair const* country_value = std::get_if>(&argument); + std::pair const* country_value = std::get_if>(&argument); if (OV_unlikely(country_value == nullptr)) { spdlog::error_s( "GAME_ACTION_SET_SOCIAL_SPENDING called with invalid argument: {}", game_action_argument_to_string(argument) @@ -334,7 +334,7 @@ bool GameActionManager::game_action_callback_set_social_spending(game_action_arg } bool GameActionManager::game_action_callback_set_military_spending(game_action_argument_t const& argument) const { - std::pair const* country_value = std::get_if>(&argument); + std::pair const* country_value = std::get_if>(&argument); if (OV_unlikely(country_value == nullptr)) { spdlog::error_s( "GAME_ACTION_SET_MILITARY_SPENDING called with invalid argument: {}", game_action_argument_to_string(argument) @@ -355,7 +355,7 @@ bool GameActionManager::game_action_callback_set_military_spending(game_action_a } bool GameActionManager::game_action_callback_set_tariff_rate(game_action_argument_t const& argument) const { - std::pair const* country_value = std::get_if>(&argument); + std::pair const* country_value = std::get_if>(&argument); if (OV_unlikely(country_value == nullptr)) { spdlog::error_s("GAME_ACTION_SET_TARIFF_RATE called with invalid argument: {}", game_action_argument_to_string(argument)); return false; @@ -375,7 +375,7 @@ bool GameActionManager::game_action_callback_set_tariff_rate(game_action_argumen // Technology bool GameActionManager::game_action_callback_start_research(game_action_argument_t const& argument) const { - std::pair const* country_tech = std::get_if>(&argument); + std::pair const* country_tech = std::get_if>(&argument); if (OV_unlikely(country_tech == nullptr)) { spdlog::error_s("GAME_ACTION_START_RESEARCH called with invalid argument: {}", game_action_argument_to_string(argument)); return false; @@ -412,8 +412,8 @@ bool GameActionManager::game_action_callback_start_research(game_action_argument // Trade bool GameActionManager::game_action_callback_set_good_automated(game_action_argument_t const& argument) const { - std::tuple const* country_good_automated = - std::get_if>(&argument); + std::tuple const* country_good_automated = + std::get_if>(&argument); if (OV_unlikely(country_good_automated == nullptr)) { spdlog::error_s( "GAME_ACTION_SET_GOOD_AUTOMATED called with invalid argument: {}", game_action_argument_to_string(argument) @@ -449,8 +449,8 @@ bool GameActionManager::game_action_callback_set_good_automated(game_action_argu } bool GameActionManager::game_action_callback_set_good_trade_order(game_action_argument_t const& argument) const { - std::tuple const* country_good_sell_amount = - std::get_if>(&argument); + std::tuple const* country_good_sell_amount = + std::get_if>(&argument); if (OV_unlikely(country_good_sell_amount == nullptr)) { spdlog::error_s( "GAME_ACTION_SET_GOOD_TRADE_ORDER called with invalid argument: {}", game_action_argument_to_string(argument) @@ -512,7 +512,7 @@ bool GameActionManager::game_action_callback_set_good_trade_order(game_action_ar // Military bool GameActionManager::game_action_callback_create_leader(game_action_argument_t const& argument) const { - std::pair const* country_branch = std::get_if>(&argument); + std::pair const* country_branch = std::get_if>(&argument); if (OV_unlikely(country_branch == nullptr)) { spdlog::error_s("GAME_ACTION_CREATE_LEADER called with invalid argument: {}", game_action_argument_to_string(argument)); return false; @@ -563,7 +563,7 @@ bool GameActionManager::game_action_callback_set_use_leader(game_action_argument } bool GameActionManager::game_action_callback_set_auto_create_leaders(game_action_argument_t const& argument) const { - std::pair const* country_value = std::get_if>(&argument); + std::pair const* country_value = std::get_if>(&argument); if (OV_unlikely(country_value == nullptr)) { spdlog::error_s( "GAME_ACTION_SET_AUTO_CREATE_LEADERS called with invalid argument: {}", game_action_argument_to_string(argument) @@ -587,7 +587,7 @@ bool GameActionManager::game_action_callback_set_auto_create_leaders(game_action } bool GameActionManager::game_action_callback_set_auto_assign_leaders(game_action_argument_t const& argument) const { - std::pair const* country_value = std::get_if>(&argument); + std::pair const* country_value = std::get_if>(&argument); if (OV_unlikely(country_value == nullptr)) { spdlog::error_s( "GAME_ACTION_SET_AUTO_ASSIGN_LEADERS called with invalid argument: {}", game_action_argument_to_string(argument) @@ -611,7 +611,7 @@ bool GameActionManager::game_action_callback_set_auto_assign_leaders(game_action } bool GameActionManager::game_action_callback_set_mobilise(game_action_argument_t const& argument) const { - std::pair const* country_mobilise = std::get_if>(&argument); + std::pair const* country_mobilise = std::get_if>(&argument); if (OV_unlikely(country_mobilise == nullptr)) { spdlog::error_s("GAME_ACTION_SET_MOBILISE called with invalid argument: {}", game_action_argument_to_string(argument)); return false; diff --git a/src/openvic-simulation/misc/GameAction.hpp b/src/openvic-simulation/misc/GameAction.hpp index d605ef21..cc3035d8 100644 --- a/src/openvic-simulation/misc/GameAction.hpp +++ b/src/openvic-simulation/misc/GameAction.hpp @@ -6,6 +6,7 @@ #include #include +#include "openvic-simulation/types/TypedIndices.hpp" #include "openvic-simulation/types/fixed_point/FixedPoint.hpp" namespace OpenVic { @@ -74,9 +75,17 @@ namespace OpenVic { }; using game_action_argument_t = std::variant< - std::monostate, bool, int64_t, std::pair, std::pair, - std::pair, std::tuple, - std::tuple, std::tuple + std::monostate, + bool, + int64_t, + std::pair, + std::pair, + std::pair, + std::tuple, + std::pair, + std::pair, + std::tuple, + std::tuple >; memory::string game_action_argument_to_string(game_action_argument_t const& argument); diff --git a/src/openvic-simulation/politics/Government.cpp b/src/openvic-simulation/politics/Government.cpp index 2a6a1fe1..5ab8c424 100644 --- a/src/openvic-simulation/politics/Government.cpp +++ b/src/openvic-simulation/politics/Government.cpp @@ -13,7 +13,7 @@ GovernmentType::GovernmentType( bool new_appoint_ruling_party, Timespan new_term_duration, std::string_view new_flag_type_identifier -) : HasIndex { new_index }, +) : HasIndex { new_index }, HasIdentifier { new_identifier }, ideologies { std::move(new_ideologies) }, elections { new_elections }, @@ -47,7 +47,7 @@ bool GovernmentTypeManager::add_government_type( const bool ret = government_types.emplace_item( identifier, - get_government_type_count(), identifier, std::move(ideologies), elections, appoint_ruling_party, term_duration, flag_type + GovernmentType::index_t { get_government_type_count() }, identifier, std::move(ideologies), elections, appoint_ruling_party, term_duration, flag_type ); /* flag_type can be empty here for default/non-ideological flag */ diff --git a/src/openvic-simulation/politics/Government.hpp b/src/openvic-simulation/politics/Government.hpp index 394db78a..78f9c3e6 100644 --- a/src/openvic-simulation/politics/Government.hpp +++ b/src/openvic-simulation/politics/Government.hpp @@ -4,13 +4,14 @@ #include "openvic-simulation/types/HasIdentifier.hpp" #include "openvic-simulation/types/HasIndex.hpp" #include "openvic-simulation/types/IdentifierRegistry.hpp" +#include "openvic-simulation/types/TypedIndices.hpp" #include "openvic-simulation/utility/Containers.hpp" namespace OpenVic { struct Ideology; struct IdeologyManager; - struct GovernmentType : HasIndex, HasIdentifier { + struct GovernmentType : HasIndex, HasIdentifier { private: memory::vector PROPERTY(ideologies); const bool PROPERTY_CUSTOM_PREFIX(elections, holds); diff --git a/src/openvic-simulation/politics/Ideology.cpp b/src/openvic-simulation/politics/Ideology.cpp index 2171d905..f892d316 100644 --- a/src/openvic-simulation/politics/Ideology.cpp +++ b/src/openvic-simulation/politics/Ideology.cpp @@ -83,7 +83,7 @@ bool IdeologyManager::add_ideology( return false; } - const Ideology::index_t new_index = ideologies.size(); + const Ideology::index_t new_index = Ideology::index_t { ideologies.size() }; return ideologies.emplace_item( identifier, identifier, diff --git a/src/openvic-simulation/politics/Ideology.hpp b/src/openvic-simulation/politics/Ideology.hpp index 9e54b555..239469da 100644 --- a/src/openvic-simulation/politics/Ideology.hpp +++ b/src/openvic-simulation/politics/Ideology.hpp @@ -4,6 +4,7 @@ #include "openvic-simulation/types/HasIdentifier.hpp" #include "openvic-simulation/types/HasIndex.hpp" #include "openvic-simulation/types/IdentifierRegistry.hpp" +#include "openvic-simulation/types/TypedIndices.hpp" namespace OpenVic { struct IdeologyManager; @@ -14,7 +15,7 @@ namespace OpenVic { IdeologyGroup(IdeologyGroup&&) = default; }; - struct Ideology : HasIdentifierAndColour, HasIndex { + struct Ideology : HasIdentifierAndColour, HasIndex { friend struct IdeologyManager; static constexpr colour_t NO_IDEOLOGY_COLOUR = colour_t::fill_as(colour_t::max_value); diff --git a/src/openvic-simulation/politics/IssueManager.cpp b/src/openvic-simulation/politics/IssueManager.cpp index a7b9c372..bcea5318 100644 --- a/src/openvic-simulation/politics/IssueManager.cpp +++ b/src/openvic-simulation/politics/IssueManager.cpp @@ -14,7 +14,7 @@ bool IssueManager::add_party_policy_group(std::string_view identifier) { return party_policy_groups.emplace_item( identifier, - identifier, get_party_policy_group_count() + identifier, PartyPolicyGroup::index_t { get_party_policy_group_count() } ); } @@ -29,7 +29,7 @@ bool IssueManager::add_party_policy( if (!party_policies.emplace_item( identifier, - get_party_policy_count(), identifier, + PartyPolicy::index_t { get_party_policy_count() }, identifier, new_colour, std::move(values), party_policy_group, std::move(rules), jingoism )) { return false; @@ -61,7 +61,7 @@ bool IssueManager::add_reform_group( if (!reform_groups.emplace_item( identifier, - identifier, get_reform_group_count(), reform_type, ordered, administrative + identifier, ReformGroup::index_t { get_reform_group_count() }, reform_type, ordered, administrative )) { return false; } @@ -112,7 +112,7 @@ bool IssueManager::add_reform( if (!reforms.emplace_item( identifier, - get_reform_count(), identifier, + Reform::index_t { get_reform_count() }, identifier, new_colour, std::move(values), reform_group, ordinal, administrative_multiplier, std::move(rules), technology_cost, std::move(allow), std::move(on_execute_trigger), std::move(on_execute_effect) )) { diff --git a/src/openvic-simulation/politics/PartyPolicy.hpp b/src/openvic-simulation/politics/PartyPolicy.hpp index b110f5a2..e45dfeaf 100644 --- a/src/openvic-simulation/politics/PartyPolicy.hpp +++ b/src/openvic-simulation/politics/PartyPolicy.hpp @@ -2,19 +2,20 @@ #include "openvic-simulation/politics/BaseIssue.hpp" #include "openvic-simulation/types/HasIndex.hpp" +#include "openvic-simulation/types/TypedIndices.hpp" namespace OpenVic { struct PartyPolicy; // PartyPolicy group (i.e. trade_policy) - struct PartyPolicyGroup : HasIndex, BaseIssueGroup { + struct PartyPolicyGroup : HasIndex, BaseIssueGroup { friend struct IssueManager; public: PartyPolicyGroup( std::string_view new_identifier, index_t new_index - ) : HasIndex { new_index }, BaseIssueGroup { new_identifier } {} + ) : HasIndex { new_index }, BaseIssueGroup { new_identifier } {} PartyPolicyGroup(PartyPolicyGroup&&) = default; std::span get_party_policies() const { @@ -23,7 +24,7 @@ namespace OpenVic { }; // PartyPolicy (i.e. protectionism) - struct PartyPolicy : HasIndex, BaseIssue { + struct PartyPolicy : HasIndex, BaseIssue { public: PartyPolicy( index_t new_index, @@ -33,7 +34,7 @@ namespace OpenVic { PartyPolicyGroup const& new_issue_group, RuleSet&& new_rules, bool new_is_jingoism - ) : HasIndex { new_index }, + ) : HasIndex { new_index }, BaseIssue { new_identifier, new_colour, diff --git a/src/openvic-simulation/politics/Rebel.cpp b/src/openvic-simulation/politics/Rebel.cpp index 75cbb331..902a0395 100644 --- a/src/openvic-simulation/politics/Rebel.cpp +++ b/src/openvic-simulation/politics/Rebel.cpp @@ -19,7 +19,7 @@ RebelType::RebelType( ConditionalWeightFactorMul&& new_spawn_chance, ConditionalWeightFactorMul&& new_movement_evaluation, ConditionScript&& new_siege_won_trigger, EffectScript&& new_siege_won_effect, ConditionScript&& new_demands_enforced_trigger, EffectScript&& new_demands_enforced_effect -) : HasIndex { new_index }, +) : HasIndex { new_index }, HasIdentifier { new_identifier }, icon { icon }, area { area }, break_alliance_on_win { break_alliance_on_win }, desired_governments { std::move(desired_governments) }, defection { defection }, independence { independence }, @@ -62,7 +62,7 @@ bool RebelManager::add_rebel_type( return rebel_types.emplace_item( new_identifier, - get_rebel_type_count(), new_identifier, + RebelType::index_t { get_rebel_type_count() }, new_identifier, icon, area, break_alliance_on_win, std::move(desired_governments), defection, independence, defect_delay, ideology, allow_all_cultures, allow_all_culture_groups, allow_all_religions, allow_all_ideologies, resilient, reinforcing, general, smart, unit_transfer, occupation_mult, std::move(will_rise), std::move(spawn_chance), diff --git a/src/openvic-simulation/politics/Rebel.hpp b/src/openvic-simulation/politics/Rebel.hpp index cf0b42c5..8a87565e 100644 --- a/src/openvic-simulation/politics/Rebel.hpp +++ b/src/openvic-simulation/politics/Rebel.hpp @@ -8,6 +8,7 @@ #include "openvic-simulation/types/HasIndex.hpp" #include "openvic-simulation/types/IdentifierRegistry.hpp" #include "openvic-simulation/types/OrderedContainers.hpp" +#include "openvic-simulation/types/TypedIndices.hpp" namespace OpenVic { struct GovernmentType; @@ -17,7 +18,7 @@ namespace OpenVic { struct ModifierManager; struct RebelManager; - struct RebelType : HasIndex, HasIdentifier { + struct RebelType : HasIndex, HasIdentifier { friend struct RebelManager; using government_map_t = ordered_map; diff --git a/src/openvic-simulation/politics/Reform.cpp b/src/openvic-simulation/politics/Reform.cpp index c0917c88..6644e081 100644 --- a/src/openvic-simulation/politics/Reform.cpp +++ b/src/openvic-simulation/politics/Reform.cpp @@ -12,7 +12,7 @@ ReformGroup::ReformGroup( bool new_is_ordered, bool new_is_administrative ) : BaseIssueGroup { new_identifier }, - HasIndex { new_index }, + HasIndex { new_index }, reform_type { new_reform_type }, is_ordered { new_is_ordered }, is_administrative { new_is_administrative } {} @@ -26,7 +26,7 @@ Reform::Reform( new_identifier, new_colour, std::move(new_values), new_reform_group, std::move(new_rules), false, modifier_type_t::REFORM }, - HasIndex { new_index }, + HasIndex { new_index }, ordinal { new_ordinal }, administrative_multiplier { new_administrative_multiplier }, technology_cost { new_technology_cost }, diff --git a/src/openvic-simulation/politics/Reform.hpp b/src/openvic-simulation/politics/Reform.hpp index a10693f8..f4792b34 100644 --- a/src/openvic-simulation/politics/Reform.hpp +++ b/src/openvic-simulation/politics/Reform.hpp @@ -5,6 +5,7 @@ #include "openvic-simulation/scripts/EffectScript.hpp" #include "openvic-simulation/types/HasIdentifier.hpp" #include "openvic-simulation/types/HasIndex.hpp" +#include "openvic-simulation/types/TypedIndices.hpp" namespace OpenVic { struct ReformGroup; @@ -26,7 +27,7 @@ namespace OpenVic { struct Reform; // Reform group (i.e. slavery) - struct ReformGroup : HasIndex, BaseIssueGroup { + struct ReformGroup : HasIndex, BaseIssueGroup { public: ReformType const& reform_type; @@ -52,7 +53,7 @@ namespace OpenVic { }; // Reform (i.e. yes_slavery) - struct Reform : HasIndex, BaseIssue { + struct Reform : HasIndex, BaseIssue { friend struct IssueManager; using tech_cost_t = uint32_t; diff --git a/src/openvic-simulation/politics/Rule.cpp b/src/openvic-simulation/politics/Rule.cpp index d3e49dcf..288f7f52 100644 --- a/src/openvic-simulation/politics/Rule.cpp +++ b/src/openvic-simulation/politics/Rule.cpp @@ -147,7 +147,7 @@ bool RuleManager::add_rule(std::string_view identifier, Rule::rule_group_t group } return rules.emplace_item( identifier, - identifier, group, rule_group_sizes[group]++, localisation_key + identifier, group, Rule::index_t { rule_group_sizes[group]++ }, localisation_key ); } diff --git a/src/openvic-simulation/politics/Rule.hpp b/src/openvic-simulation/politics/Rule.hpp index 63608c47..bc5f0ab7 100644 --- a/src/openvic-simulation/politics/Rule.hpp +++ b/src/openvic-simulation/politics/Rule.hpp @@ -4,13 +4,14 @@ #include "openvic-simulation/types/HasIndex.hpp" #include "openvic-simulation/types/IdentifierRegistry.hpp" #include "openvic-simulation/types/OrderedContainers.hpp" +#include "openvic-simulation/types/TypedIndices.hpp" namespace OpenVic { struct RuleManager; struct BuildingTypeManager; /* The index of the Rule within its group, used to determine precedence in mutually exclusive rule groups. */ - struct Rule : HasIdentifier, HasIndex { + struct Rule : HasIdentifier, HasIndex { enum class rule_group_t : uint8_t { ECONOMY, CITIZENSHIP, SLAVERY, UPPER_HOUSE, VOTING }; diff --git a/src/openvic-simulation/population/Pop.cpp b/src/openvic-simulation/population/Pop.cpp index 90a2981e..65c1b011 100644 --- a/src/openvic-simulation/population/Pop.cpp +++ b/src/openvic-simulation/population/Pop.cpp @@ -7,6 +7,8 @@ #include #include +#include + #include "openvic-simulation/country/CountryParty.hpp" #include "openvic-simulation/country/CountryDefinition.hpp" #include "openvic-simulation/country/CountryInstance.hpp" @@ -38,6 +40,7 @@ #include "openvic-simulation/utility/Logger.hpp" #include "openvic-simulation/utility/Typedefs.hpp" + using namespace OpenVic; PopBase::PopBase( @@ -453,7 +456,7 @@ void Pop::allocate_for_needs( GoodDefinition const& good_definition = *good_definition_ptr; const ptrdiff_t i = it - scaled_needs.begin(); const fixed_point_t money_to_spend = money_to_spend_per_good_draft[i]; - money_to_spend_per_good[good_definition.index] += money_to_spend; + money_to_spend_per_good[type_safe::get(good_definition.index)] += money_to_spend; cash_left_to_spend -= money_to_spend; } @@ -577,7 +580,7 @@ void Pop::pop_tick_without_cleanup( if (OV_likely(max_quantity_to_buy > 0)) { \ need_category##_needs_price_inverse_sum += market_instance.get_good_instance(good_definition).get_price_inverse(); \ need_category##_needs[good_definition_ptr] += max_quantity_to_buy; \ - max_quantity_to_buy_per_good[good_definition.index] += max_quantity_to_buy; \ + max_quantity_to_buy_per_good[type_safe::get(good_definition.index)] += max_quantity_to_buy; \ } \ } \ } diff --git a/src/openvic-simulation/population/PopManager.cpp b/src/openvic-simulation/population/PopManager.cpp index ba462e6a..d82100f9 100644 --- a/src/openvic-simulation/population/PopManager.cpp +++ b/src/openvic-simulation/population/PopManager.cpp @@ -63,7 +63,7 @@ bool PopManager::add_strata(std::string_view identifier) { } return stratas.emplace_item( identifier, - identifier, get_strata_count() + identifier, Strata::index_t { get_strata_count() } ); } @@ -154,7 +154,7 @@ bool PopManager::add_pop_type( identifier, identifier, colour, - get_pop_type_count(), + PopType::index_t { get_pop_type_count() }, *strata, sprite, std::move(life_needs), diff --git a/src/openvic-simulation/population/PopType.hpp b/src/openvic-simulation/population/PopType.hpp index 3b8cf1f1..50d0b61d 100644 --- a/src/openvic-simulation/population/PopType.hpp +++ b/src/openvic-simulation/population/PopType.hpp @@ -8,6 +8,7 @@ #include "openvic-simulation/types/IndexedFlatMap.hpp" #include "openvic-simulation/types/PopSize.hpp" #include "openvic-simulation/types/PopSprite.hpp" +#include "openvic-simulation/types/TypedIndices.hpp" #include "openvic-simulation/utility/Containers.hpp" namespace OpenVic { @@ -18,7 +19,7 @@ namespace OpenVic { struct PopType; struct UnitType; - struct Strata : HasIdentifier, HasIndex { + struct Strata : HasIdentifier, HasIndex { friend struct PopManager; private: @@ -32,7 +33,7 @@ namespace OpenVic { /* REQUIREMENTS: * POP-15, POP-16, POP-17, POP-26 */ - struct PopType : HasIdentifierAndColour, HasIndex { + struct PopType : HasIdentifierAndColour, HasIndex { friend struct PopManager; /* This is a bitfield - PopTypes can have up to one of each income source for each need category. */ diff --git a/src/openvic-simulation/research/Invention.cpp b/src/openvic-simulation/research/Invention.cpp index 4ceddf6c..c11036b3 100644 --- a/src/openvic-simulation/research/Invention.cpp +++ b/src/openvic-simulation/research/Invention.cpp @@ -20,7 +20,7 @@ Invention::Invention( bool new_unlock_gas_defence, ConditionScript&& new_limit, ConditionalWeightBase&& new_chance -) : HasIndex { new_index }, +) : HasIndex { new_index }, Modifier { new_identifier, std::move(new_values), modifier_type_t::INVENTION }, news { new_news }, activated_units { std::move(new_activated_units) }, @@ -52,7 +52,7 @@ bool InventionManager::add_invention( return inventions.emplace_item( identifier, - get_invention_count(), identifier, + Invention::index_t { get_invention_count() }, identifier, std::move(values), news, std::move(activated_units), std::move(activated_buildings), std::move(enabled_crimes), unlock_gas_attack, unlock_gas_defence, std::move(limit), std::move(chance) ); diff --git a/src/openvic-simulation/research/Invention.hpp b/src/openvic-simulation/research/Invention.hpp index e85b0c64..d03a84aa 100644 --- a/src/openvic-simulation/research/Invention.hpp +++ b/src/openvic-simulation/research/Invention.hpp @@ -5,6 +5,7 @@ #include "openvic-simulation/types/HasIndex.hpp" #include "openvic-simulation/types/IdentifierRegistry.hpp" #include "openvic-simulation/types/OrderedContainers.hpp" +#include "openvic-simulation/types/TypedIndices.hpp" namespace OpenVic { @@ -16,7 +17,7 @@ namespace OpenVic { struct UnitType; struct UnitTypeManager; - struct Invention : HasIndex, Modifier { + struct Invention : HasIndex, Modifier { friend struct InventionManager; //TODO implement limit and chance diff --git a/src/openvic-simulation/research/Technology.cpp b/src/openvic-simulation/research/Technology.cpp index 094a4f66..03465761 100644 --- a/src/openvic-simulation/research/Technology.cpp +++ b/src/openvic-simulation/research/Technology.cpp @@ -53,7 +53,7 @@ bool TechnologyManager::add_technology_folder(std::string_view identifier) { return technology_folders.emplace_item( identifier, - identifier, get_technology_folder_count() + identifier, TechnologyFolder::index_t { get_technology_folder_count() } ); } @@ -99,7 +99,7 @@ bool TechnologyManager::add_technology( if (!technologies.emplace_item( identifier, identifier, - get_technology_count(), + Technology::index_t { get_technology_count() }, *area, year, cost, diff --git a/src/openvic-simulation/research/Technology.hpp b/src/openvic-simulation/research/Technology.hpp index ad688d64..cb09d783 100644 --- a/src/openvic-simulation/research/Technology.hpp +++ b/src/openvic-simulation/research/Technology.hpp @@ -8,6 +8,7 @@ #include "openvic-simulation/types/HasIdentifier.hpp" #include "openvic-simulation/types/HasIndex.hpp" #include "openvic-simulation/types/OrderedContainers.hpp" +#include "openvic-simulation/types/TypedIndices.hpp" #include "openvic-simulation/types/UnitVariant.hpp" #include "openvic-simulation/utility/Containers.hpp" @@ -19,7 +20,7 @@ namespace OpenVic { struct TechnologyManager; struct UnitTypeManager; - struct TechnologyFolder : HasIdentifier, HasIndex { + struct TechnologyFolder : HasIdentifier, HasIndex { friend struct TechnologyManager; private: @@ -44,7 +45,7 @@ namespace OpenVic { TechnologyArea(TechnologyArea&&) = default; }; - struct Technology : Modifier, HasIndex { + struct Technology : Modifier, HasIndex { friend struct TechnologyManager; using area_index_t = uint8_t; diff --git a/src/openvic-simulation/types/HasIndex.hpp b/src/openvic-simulation/types/HasIndex.hpp index d2defe40..ec3d741f 100644 --- a/src/openvic-simulation/types/HasIndex.hpp +++ b/src/openvic-simulation/types/HasIndex.hpp @@ -1,10 +1,11 @@ #pragma once -#include -#include +#include + +#include "openvic-simulation/utility/Concepts.hpp" namespace OpenVic { - template + template IndexT> class HasIndex { public: using index_t = IndexT; diff --git a/src/openvic-simulation/types/IndexedFlatMap.hpp b/src/openvic-simulation/types/IndexedFlatMap.hpp index 28994c87..46fc48ed 100644 --- a/src/openvic-simulation/types/IndexedFlatMap.hpp +++ b/src/openvic-simulation/types/IndexedFlatMap.hpp @@ -6,6 +6,8 @@ #include #include +#include + #include #include "openvic-simulation/types/FixedVector.hpp" @@ -67,7 +69,7 @@ namespace OpenVic { */ constexpr size_t get_internal_index_from_key(KeyType const& key) const { static_assert(has_index); - const size_t index = key.index; + const size_t index = type_safe::get(key.index); if (index < min_index || index > max_index) { spdlog::error_s( "DEVELOPER: OpenVic::IndexedFlatMap<{},{}> attempted to access key with index {} which is outside the map's defined range [{}, {}].", @@ -99,9 +101,12 @@ namespace OpenVic { return false; } - const size_t min_index = new_keys.front().index; - const size_t max_index = new_keys.back().index; - const size_t expected_capacity = max_index - min_index + 1; + using index_type = decltype(std::declval().index); + using underlying_type = type_safe::underlying_type; + + const underlying_type min_index = type_safe::get(new_keys.front().index); + const underlying_type max_index = type_safe::get(new_keys.back().index); + const underlying_type expected_capacity = max_index - min_index + 1; if (new_keys.size() != expected_capacity) { spdlog::error_s( @@ -115,18 +120,19 @@ namespace OpenVic { return false; } - for (size_t i = 0; i < new_keys.size(); ++i) { - if (new_keys[i].index != min_index + i) { + for (underlying_type i = 0; i < new_keys.size(); ++i) { + const auto expected_index = index_type { underlying_type(min_index + i) }; + if (new_keys[i].index != expected_index) { spdlog::error_s( "DEVELOPER: OpenVic::IndexedFlatMap<{},{}> must be constructed with a continuous span of keys with incremental indices. " "Expected index {} but got {} at position {}.", utility::type_name(), utility::type_name(), - min_index + i, + expected_index, new_keys[i].index, i ); - assert(new_keys[i].index == min_index + i); + assert(new_keys[i].index == expected_index); return false; } } @@ -354,8 +360,8 @@ namespace OpenVic { keys_span_type new_keys, GeneratorTemplateType value_generator ) : keys(new_keys), - min_index { new_keys.front().index }, - max_index { new_keys.back().index }, + min_index { type_safe::get(new_keys.front().index) }, + max_index { type_safe::get(new_keys.back().index) }, values(new_keys.size()) { static_assert(has_index); if (!validate_new_keys(new_keys)) { @@ -386,8 +392,8 @@ namespace OpenVic { requires (std::is_move_constructible_v || std::is_copy_constructible_v) && (std::default_initializable || std::constructible_from) : keys(new_keys), - min_index { new_keys.front().index }, - max_index { new_keys.back().index }, + min_index { type_safe::get(new_keys.front().index) }, + max_index { type_safe::get(new_keys.back().index) }, values() { static_assert(has_index); if (!validate_new_keys(new_keys)) { @@ -419,8 +425,8 @@ namespace OpenVic { requires (!std::is_move_constructible_v) && (!std::is_copy_constructible_v) && (std::default_initializable || std::constructible_from) : keys(new_keys), - min_index { new_keys.front().index }, - max_index { new_keys.back().index }, + min_index { type_safe::get(new_keys.front().index) }, + max_index { type_safe::get(new_keys.back().index) }, values(new_keys.size()) { static_assert(has_index); if (!validate_new_keys(new_keys)) { @@ -470,6 +476,11 @@ namespace OpenVic { return values[get_internal_index_from_key(key)]; } + template + requires requires { type_safe::get(std::declval()); } + constexpr ValueType& at_index(I const& index) { + return at_index(type_safe::get(index)); + } constexpr ValueType& at_index(const size_t index) { if (index < min_index || index > max_index) { spdlog::error_s( @@ -485,6 +496,11 @@ namespace OpenVic { return values[index - min_index]; } + template + requires requires { type_safe::get(std::declval()); } + constexpr ValueType const& at_index(I const& index) const { + return at_index(type_safe::get(index)); + } constexpr ValueType const& at_index(const size_t index) const { if (index < min_index || index > max_index) { spdlog::error_s( @@ -505,6 +521,11 @@ namespace OpenVic { return contains_index(key.index); } + template + requires requires { type_safe::get(std::declval()); } + constexpr bool contains_index(I const& external_index) const { + return contains_index(type_safe::get(external_index)); + } constexpr bool contains_index(const size_t external_index) const { return external_index >= min_index && external_index <= max_index; } diff --git a/src/openvic-simulation/types/TypedIndices.hpp b/src/openvic-simulation/types/TypedIndices.hpp new file mode 100644 index 00000000..a3835f42 --- /dev/null +++ b/src/openvic-simulation/types/TypedIndices.hpp @@ -0,0 +1,67 @@ +#pragma once + +#include +#include + +#include +#include + +#include + +#define TYPED_INDEX_CUSTOM(name, base_type) \ + namespace OpenVic { \ + struct name : type_safe::strong_typedef, \ + type_safe::strong_typedef_op::equality_comparison, \ + type_safe::strong_typedef_op::relational_comparison { \ + using strong_typedef::strong_typedef; \ + }; \ + } \ + template<> \ + struct fmt::formatter : fmt::formatter { \ + fmt::format_context::iterator format(OpenVic::name const& value, fmt::format_context& ctx) const { \ + return fmt::formatter::format(type_safe::get(value), ctx); \ + } \ + }; +#define TYPED_INDEX(name) TYPED_INDEX_CUSTOM(name, std::size_t) + +TYPED_INDEX(bookmark_index_t) +TYPED_INDEX(building_type_index_t) +TYPED_INDEX(country_index_t) +TYPED_INDEX(crime_index_t) +TYPED_INDEX(good_index_t) +TYPED_INDEX(government_type_index_t) +TYPED_INDEX(ideology_index_t) +TYPED_INDEX(invention_index_t) +TYPED_INDEX(map_mode_index_t) +TYPED_INDEX(party_policy_index_t) +TYPED_INDEX(party_policy_group_index_t) +TYPED_INDEX(pop_type_index_t) +TYPED_INDEX(rebel_type_index_t) +TYPED_INDEX(reform_index_t) +TYPED_INDEX(reform_group_index_t) +TYPED_INDEX(regiment_type_index_t) +TYPED_INDEX(rule_index_t) +TYPED_INDEX(ship_type_index_t) +TYPED_INDEX(strata_index_t) +TYPED_INDEX(technology_index_t) +TYPED_INDEX(technology_folder_index_t) +TYPED_INDEX(terrain_type_index_t) + +namespace OpenVic { + struct province_index_t : type_safe::strong_typedef, + type_safe::strong_typedef_op::equality_comparison, + type_safe::strong_typedef_op::relational_comparison, + type_safe::strong_typedef_op::mixed_addition, + type_safe::strong_typedef_op::mixed_subtraction { + using strong_typedef::strong_typedef; + }; +} +template<> +struct fmt::formatter : fmt::formatter { + fmt::format_context::iterator format(OpenVic::province_index_t const& value, fmt::format_context& ctx) const { + return fmt::formatter::format(type_safe::get(value), ctx); + } +}; + +#undef TYPED_INDEX +#undef TYPED_INDEX_CUSTOM diff --git a/src/openvic-simulation/utility/Concepts.hpp b/src/openvic-simulation/utility/Concepts.hpp index 57740755..dddacb68 100644 --- a/src/openvic-simulation/utility/Concepts.hpp +++ b/src/openvic-simulation/utility/Concepts.hpp @@ -5,6 +5,8 @@ #include #include +#include + namespace OpenVic { template class Z> struct is_specialization_of : std::false_type {}; @@ -106,8 +108,10 @@ namespace OpenVic { }; template - concept has_index = requires(T const& key) { - { key.index } -> std::convertible_to; + concept has_index = requires { + static_cast( + static_cast().index)>>(std::declval().index) + ); }; template