diff options
Diffstat (limited to 'src')
26 files changed, 515 insertions, 351 deletions
diff --git a/src/headless/main.cpp b/src/headless/main.cpp index 3935c2d..e15005b 100644 --- a/src/headless/main.cpp +++ b/src/headless/main.cpp @@ -1,3 +1,5 @@ +#include <cstring> + #include <openvic-simulation/GameManager.hpp> #include <openvic-simulation/dataloader/Dataloader.hpp> #include <openvic-simulation/utility/Logger.hpp> @@ -19,22 +21,25 @@ static char const* get_program_name(char const* name) { return last_separator; } -static bool headless_load(Dataloader::path_vector_t const& roots) { - bool ret = true; +static void print_help(char const* program_name) { + std::cout + << "Usage: " << program_name << " [-h] [-t] [-b <path>] [path]+\n" + << " -h : Print this help message and exit the program.\n" + << " -t : Run tests after loading defines.\n" + << " -b : Use the following path as the base directory (instead of searching for one).\n" + << "Any following paths are read as mod directories, with priority starting at one above the base directory.\n" + << "(Paths with spaces need to be enclosed in \"quotes\").\n"; +} +static void setup_logger_funcs() { Logger::set_info_func([](std::string&& str) { std::cout << str; }); Logger::set_warning_func([](std::string&& str) { std::cerr << str; }); Logger::set_error_func([](std::string&& str) { std::cerr << str; }); +} - GameManager game_manager { []() { - Logger::info("State updated"); - } }; - Dataloader dataloader; +static bool headless_load(GameManager& game_manager, Dataloader const& dataloader) { + bool ret = true; - if (!dataloader.set_roots(roots)) { - Logger::error("Failed to set dataloader roots!"); - ret = false; - } if (!dataloader.load_defines(game_manager)) { Logger::error("Failed to load defines!"); ret = false; @@ -52,37 +57,92 @@ static bool headless_load(Dataloader::path_vector_t const& roots) { ret = false; } + return ret; +} + +static bool run_headless(Dataloader::path_vector_t const& roots, bool run_tests) { + bool ret = true; + + setup_logger_funcs(); + + Dataloader dataloader; + if (!dataloader.set_roots(roots)) { + Logger::error("Failed to set dataloader roots!"); + ret = false; + } + + GameManager game_manager { []() { + Logger::info("State updated"); + } }; - Testing testing = Testing(&game_manager); - std::cout << std::endl << "Testing Loaded" << std::endl << std::endl; - testing.execute_all_scripts(); - testing.report_results(); - std::cout << "Testing Executed" << std::endl << std::endl; + ret &= headless_load(game_manager, dataloader); + + if (run_tests) { + Testing testing = Testing(&game_manager); + std::cout << std::endl << "Testing Loaded" << std::endl << std::endl; + testing.execute_all_scripts(); + testing.report_results(); + std::cout << "Testing Executed" << std::endl << std::endl; + } return ret; } +/* + $ program [-h] [-t] [-b] [path]+ +*/ + int main(int argc, char const* argv[]) { - Dataloader::path_vector_t roots; - if (argc < 2) { - // TODO - non-Windows default paths - static const fs::path default_path = "C:/Program Files (x86)/Steam/steamapps/common/Victoria 2"; - - std::cout - << "Usage: " << get_program_name(argc > 0 ? argv[0] : nullptr) << " <base defines dir> [[mod defines dir]+]\n" - << "Requires defines path(s) as arguments, starting with the base defines and continuing with mods.\n" - << "(Paths with spaces need to be enclosed in \"quotes\").\n" - << "Defaulting to " << default_path << std::endl; - roots.push_back(default_path); - } else { - for (int i = 1; i < argc; ++i) { - roots.push_back(argv[i]); + char const* program_name = get_program_name(argc > 0 ? argv[0] : nullptr); + + fs::path root; + bool run_tests = false; + + int argn = 0; + while (++argn < argc) { + char const* arg = argv[argn]; + if (strcmp(arg, "-h") == 0) { + print_help(program_name); + return 0; + } else if (strcmp(arg, "-t") == 0) { + run_tests = true; + } else if (strcmp(arg, "-b") == 0) { + if (root.empty()) { + if (++argn < argc) { + root = argv[argn]; + if (!root.empty()) { + continue; + } else { + std::cerr << "Empty path after base directory command line argument \"-b\"." << std::endl; + } + } else { + std::cerr << "Missing path after base directory command line argument \"-b\"." << std::endl; + } + } else { + std::cerr << "Duplicate base directory command line argument \"-b\"." << std::endl; + } + print_help(program_name); + return -1; + } else { + break; + } + } + if (root.empty()) { + root = Dataloader::search_for_game_path(); + if (root.empty()) { + std::cerr << "Search for base directory path failed!" << std::endl; + print_help(program_name); + return -1; } } + Dataloader::path_vector_t roots = { root }; + while (argn < argc) { + roots.emplace_back(root / argv[argn++]); + } std::cout << "!!! HEADLESS SIMULATION START !!!" << std::endl; - const bool ret = headless_load(roots); + const bool ret = run_headless(roots, run_tests); std::cout << "!!! HEADLESS SIMULATION END !!!" << std::endl; diff --git a/src/openvic-simulation/Modifier.cpp b/src/openvic-simulation/Modifier.cpp index 4e5b860..1273fdd 100644 --- a/src/openvic-simulation/Modifier.cpp +++ b/src/openvic-simulation/Modifier.cpp @@ -3,13 +3,17 @@ using namespace OpenVic; using namespace OpenVic::NodeTools; -ModifierEffect::ModifierEffect(std::string_view new_identifier, bool new_positive_good) - : HasIdentifier { new_identifier }, positive_good { new_positive_good } {} +ModifierEffect::ModifierEffect(std::string_view new_identifier, bool new_positive_good, format_t new_format) + : HasIdentifier { new_identifier }, positive_good { new_positive_good }, format { new_format } {} bool ModifierEffect::get_positive_good() const { return positive_good; } +ModifierEffect::format_t ModifierEffect::get_format() const { + return format; +} + ModifierValue::ModifierValue() = default; ModifierValue::ModifierValue(effect_map_t&& new_values) : values { std::move(new_values) } {} ModifierValue::ModifierValue(ModifierValue const&) = default; @@ -94,12 +98,12 @@ Date const& ModifierInstance::get_expiry_date() const { ModifierManager::ModifierManager() : modifier_effects { "modifier effects"}, modifiers { "modifiers" } {} -bool ModifierManager::add_modifier_effect(std::string_view identifier, bool positive_good) { +bool ModifierManager::add_modifier_effect(std::string_view identifier, bool positive_good, ModifierEffect::format_t format) { if (identifier.empty()) { Logger::error("Invalid modifier effect identifier - empty!"); return false; } - return modifier_effects.add_item({ identifier, positive_good }); + return modifier_effects.add_item({ identifier, positive_good, format }); } bool ModifierManager::add_modifier(std::string_view identifier, ModifierValue&& values, Modifier::icon_t icon) { @@ -117,16 +121,40 @@ bool ModifierManager::add_modifier(std::string_view identifier, ModifierValue&& bool ModifierManager::setup_modifier_effects() { bool ret = true; + using enum ModifierEffect::format_t; + ret &= add_modifier_effect("movement_cost", false); ret &= add_modifier_effect("farm_rgo_size", true); ret &= add_modifier_effect("farm_rgo_eff", true); ret &= add_modifier_effect("mine_rgo_size", true); ret &= add_modifier_effect("mine_rgo_eff", true); - ret &= add_modifier_effect("min_build_railroad", false); - ret &= add_modifier_effect("supply_limit", true); + ret &= add_modifier_effect("supply_limit", true, RAW_DECIMAL); ret &= add_modifier_effect("combat_width", false); - ret &= add_modifier_effect("defence", true); - + ret &= add_modifier_effect("defence", true, RAW_DECIMAL); + ret &= add_modifier_effect("local_ship_build", false); + ret &= add_modifier_effect("research_points_modifier", true); + ret &= add_modifier_effect("local_rgo_output", true); + ret &= add_modifier_effect("attrition", false, RAW_DECIMAL); + ret &= add_modifier_effect("immigrant_push", false); + ret &= add_modifier_effect("population_growth", true); + ret &= add_modifier_effect("local_RGO_throughput", true); + ret &= add_modifier_effect("assimilation_rate", true); + + /* These should be added automatically for each Building loaded (or at least + * non-factories), however currently we need modifier effects locked before we + * can load buildings, so some architectural changes will be needed. + */ + ret &= add_modifier_effect("max_fort", true, ModifierEffect::format_t::INT); + ret &= add_modifier_effect("min_build_fort", true, ModifierEffect::format_t::INT); + ret &= add_modifier_effect("max_naval_base", true, ModifierEffect::format_t::INT); + ret &= add_modifier_effect("min_build_naval_base", true, ModifierEffect::format_t::INT); + ret &= add_modifier_effect("max_railroad", true, ModifierEffect::format_t::INT); + ret &= add_modifier_effect("min_build_railroad", true, ModifierEffect::format_t::INT); + ret &= add_modifier_effect("max_university", true, ModifierEffect::format_t::INT); + ret &= add_modifier_effect("min_build_university", true, ModifierEffect::format_t::INT); + ret &= add_modifier_effect("max_bank", true, ModifierEffect::format_t::INT); + ret &= add_modifier_effect("min_build_bank", true, ModifierEffect::format_t::INT); + modifier_effects.lock(); return ret; } diff --git a/src/openvic-simulation/Modifier.hpp b/src/openvic-simulation/Modifier.hpp index 2e1b03a..663d359 100644 --- a/src/openvic-simulation/Modifier.hpp +++ b/src/openvic-simulation/Modifier.hpp @@ -8,26 +8,32 @@ namespace OpenVic { struct ModifierEffect : HasIdentifier { friend struct ModifierManager; + enum class format_t { + RAW_DECIMAL, PERCENTAGE_DECIMAL, INT + }; + private: /* If true, positive values will be green and negative values will be red. * If false, the colours will be switced. */ const bool positive_good; + const format_t format; // TODO - format/precision, e.g. 80% vs 0.8 vs 0.800, 2 vs 2.0 vs 200% - ModifierEffect(std::string_view new_identifier, bool new_positive_good); + ModifierEffect(std::string_view new_identifier, bool new_positive_good, format_t new_format); public: ModifierEffect(ModifierEffect&&) = default; bool get_positive_good() const; + format_t get_format() const; }; struct ModifierValue { friend struct ModifierManager; - using effect_map_t = std::map<ModifierEffect const*, fixed_point_t>; + using effect_map_t = decimal_map_t<ModifierEffect const*>; private: effect_map_t values; @@ -95,7 +101,7 @@ namespace OpenVic { public: ModifierManager(); - bool add_modifier_effect(std::string_view identifier, bool province_good); + bool add_modifier_effect(std::string_view identifier, bool province_good, ModifierEffect::format_t format = ModifierEffect::format_t::PERCENTAGE_DECIMAL); IDENTIFIER_REGISTRY_ACCESSORS(modifier_effect) bool add_modifier(std::string_view identifier, ModifierValue&& values, Modifier::icon_t icon); @@ -110,12 +116,10 @@ namespace OpenVic { NodeTools::node_callback_t expect_modifier_value_and_key_map(NodeTools::callback_t<ModifierValue&&> modifier_callback, NodeTools::key_map_t&& key_map) const; template<typename... Args> - NodeTools::node_callback_t expect_modifier_value_and_key_map_and_default( - NodeTools::callback_t<ModifierValue&&> modifier_callback, NodeTools::key_value_callback_t default_callback, NodeTools::key_map_t&& key_map, - std::string_view key, NodeTools::dictionary_entry_t::expected_count_t expected_count, NodeTools::node_callback_t callback, - Args... args) const { - NodeTools::add_key_map_entry(key_map, key, expected_count, callback); - return expect_modifier_value_and_key_map_and_default(modifier_callback, default_callback, std::move(key_map), args...); + NodeTools::node_callback_t expect_modifier_value_and_key_map_and_default(NodeTools::callback_t<ModifierValue&&> modifier_callback, + NodeTools::key_value_callback_t default_callback, NodeTools::key_map_t&& key_map, Args... args) const { + NodeTools::add_key_map_entries(key_map, args...); + return expect_modifier_value_and_key_map_and_default(modifier_callback, default_callback, std::move(key_map)); } template<typename... Args> diff --git a/src/openvic-simulation/dataloader/Dataloader.cpp b/src/openvic-simulation/dataloader/Dataloader.cpp index b9d7496..5134054 100644 --- a/src/openvic-simulation/dataloader/Dataloader.cpp +++ b/src/openvic-simulation/dataloader/Dataloader.cpp @@ -314,7 +314,7 @@ fs::path Dataloader::search_for_game_path(fs::path hint_path) { return _cached_paths[hint_path] = _search_for_game_path(hint_path); } -bool Dataloader::set_roots(path_vector_t new_roots) { +bool Dataloader::set_roots(path_vector_t const& new_roots) { if (!roots.empty()) { Logger::error("Overriding existing dataloader roots!"); roots.clear(); @@ -700,7 +700,7 @@ static bool _load_localisation_file(Dataloader::localisation_callback_t callback return ret; } -bool Dataloader::load_localisation_files(localisation_callback_t callback, fs::path const& localisation_dir) { +bool Dataloader::load_localisation_files(localisation_callback_t callback, fs::path const& localisation_dir) const { return apply_to_files_in_dir(localisation_dir, ".csv", [callback](fs::path path) -> bool { return _load_localisation_file(callback, parse_csv(path).get_lines()); diff --git a/src/openvic-simulation/dataloader/Dataloader.hpp b/src/openvic-simulation/dataloader/Dataloader.hpp index c4cd7c7..c268a94 100644 --- a/src/openvic-simulation/dataloader/Dataloader.hpp +++ b/src/openvic-simulation/dataloader/Dataloader.hpp @@ -54,7 +54,7 @@ namespace OpenVic { static fs::path search_for_game_path(fs::path hint_path = {}); /* In reverse-load order, so base defines first and final loaded mod last */ - bool set_roots(path_vector_t new_roots); + bool set_roots(path_vector_t const& new_roots); /* REQUIREMENTS: * DAT-24 @@ -76,7 +76,7 @@ namespace OpenVic { /* Args: key, locale, localisation */ using localisation_callback_t = NodeTools::callback_t<std::string_view, locale_t, std::string_view>; - bool load_localisation_files(localisation_callback_t callback, fs::path const& localisation_dir = "localisation"); + bool load_localisation_files(localisation_callback_t callback, fs::path const& localisation_dir = "localisation") const; private: struct fshash diff --git a/src/openvic-simulation/dataloader/NodeTools.cpp b/src/openvic-simulation/dataloader/NodeTools.cpp index 391ffb6..c2edb18 100644 --- a/src/openvic-simulation/dataloader/NodeTools.cpp +++ b/src/openvic-simulation/dataloader/NodeTools.cpp @@ -360,20 +360,25 @@ node_callback_t NodeTools::expect_dictionary_key_map(key_map_t key_map) { return expect_dictionary_key_map_and_length_and_default(std::move(key_map), default_length_callback, key_value_invalid_callback); } -node_callback_t NodeTools::name_list_callback(std::vector<std::string>& list) { - return expect_list_reserve_length( - list, - expect_identifier_or_string( - [&list](std::string_view str) -> bool { - if (!str.empty()) { - list.push_back(std::string { str }); - return true; +node_callback_t NodeTools::name_list_callback(callback_t<std::vector<std::string>&&> callback) { + return [callback](ast::NodeCPtr node) -> bool { + std::vector<std::string> list; + bool ret = expect_list_reserve_length( + list, + expect_identifier_or_string( + [&list](std::string_view str) -> bool { + if (!str.empty()) { + list.push_back(std::string { str }); + return true; + } + Logger::error("Empty identifier or string"); + return false; } - Logger::error("Empty identifier or string"); - return false; - } - ) - ); + ) + )(node); + ret &= callback(std::move(list)); + return ret; + }; } callback_t<std::string_view> NodeTools::assign_variable_callback_string(std::string& var) { diff --git a/src/openvic-simulation/dataloader/NodeTools.hpp b/src/openvic-simulation/dataloader/NodeTools.hpp index 44ac271..e98a4b0 100644 --- a/src/openvic-simulation/dataloader/NodeTools.hpp +++ b/src/openvic-simulation/dataloader/NodeTools.hpp @@ -123,18 +123,24 @@ namespace OpenVic { key_value_callback_t dictionary_keys_callback(key_map_t& key_map, key_value_callback_t default_callback); bool check_key_map_counts(key_map_t& key_map); + constexpr bool add_key_map_entries(key_map_t& key_map) { return true; } + template<typename... Args> + bool add_key_map_entries(key_map_t& key_map, std::string_view key, dictionary_entry_t::expected_count_t expected_count, node_callback_t callback, Args... args) { + bool ret = add_key_map_entry(key_map, key, expected_count, callback); + ret &= add_key_map_entries(key_map, args...); + return ret; + } + node_callback_t expect_dictionary_key_map_and_length_and_default(key_map_t key_map, length_callback_t length_callback, key_value_callback_t default_callback); node_callback_t expect_dictionary_key_map_and_length(key_map_t key_map, length_callback_t length_callback); node_callback_t expect_dictionary_key_map_and_default(key_map_t key_map, key_value_callback_t default_callback); node_callback_t expect_dictionary_key_map(key_map_t key_map); template<typename... Args> - node_callback_t expect_dictionary_key_map_and_length_and_default(key_map_t key_map, length_callback_t length_callback, key_value_callback_t default_callback, - std::string_view key, dictionary_entry_t::expected_count_t expected_count, node_callback_t callback, - Args... args) { + node_callback_t expect_dictionary_key_map_and_length_and_default(key_map_t key_map, length_callback_t length_callback, key_value_callback_t default_callback, Args... args) { // TODO - pass return value back up (part of big key_map_t rewrite?) - add_key_map_entry(key_map, key, expected_count, callback); - return expect_dictionary_key_map_and_length_and_default(std::move(key_map), length_callback, default_callback, args...); + add_key_map_entries(key_map, args...); + return expect_dictionary_key_map_and_length_and_default(std::move(key_map), length_callback, default_callback); } template<typename... Args> @@ -177,7 +183,7 @@ namespace OpenVic { return expect_list_reserve_length(t, expect_assign(callback)); } - node_callback_t name_list_callback(std::vector<std::string>& list); + node_callback_t name_list_callback(callback_t<std::vector<std::string>&&> callback); template<typename T> callback_t<std::string_view> expect_mapped_string(string_map_t<T> const& map, callback_t<T> callback) { diff --git a/src/openvic-simulation/economy/Building.cpp b/src/openvic-simulation/economy/Building.cpp index 23bd04c..d132e8e 100644 --- a/src/openvic-simulation/economy/Building.cpp +++ b/src/openvic-simulation/economy/Building.cpp @@ -5,18 +5,24 @@ using namespace OpenVic; using namespace OpenVic::NodeTools; -Building::Building(std::string_view identifier, BuildingType const& type, ARGS) : HasIdentifier { identifier }, ModifierValue { std::move(modifiers) }, type { type }, - on_completion { on_completion }, completion_size { completion_size }, max_level { max_level }, goods_cost { goods_cost }, cost { cost }, build_time { build_time }, - visibility { visibility }, on_map { on_map }, default_enabled { default_enabled }, production_type { production_type }, pop_build_factory { pop_build_factory }, - strategic_factory { strategic_factory }, advanced_factory { advanced_factory }, fort_level { fort_level }, naval_capacity { naval_capacity }, - colonial_points { colonial_points }, in_province { in_province }, one_per_state { one_per_state }, colonial_range { colonial_range }, - infrastructure { infrastructure }, movement_cost { movement_cost }, local_ship_build { local_ship_build }, spawn_railway_track { spawn_railway_track }, +Building::Building(std::string_view identifier, BuildingType const& type, ARGS) + : HasIdentifier { identifier }, type { type }, modifier { std::move(modifier) }, on_completion { on_completion }, + completion_size { completion_size }, max_level { max_level }, goods_cost { std::move(goods_cost) }, cost { cost }, + build_time { build_time }, visibility { visibility }, on_map { on_map }, default_enabled { default_enabled }, + production_type { production_type }, pop_build_factory { pop_build_factory }, strategic_factory { strategic_factory }, + advanced_factory { advanced_factory }, fort_level { fort_level }, naval_capacity { naval_capacity }, + colonial_points { std::move(colonial_points) }, in_province { in_province }, one_per_state { one_per_state }, + colonial_range { colonial_range }, infrastructure { infrastructure }, spawn_railway_track { spawn_railway_track }, sail { sail }, steam { steam }, capital { capital }, port { port } {} BuildingType const& Building::get_type() const { return type; } +ModifierValue const& Building::get_modifier() const { + return modifier; +} + std::string_view Building::get_on_completion() const { return on_completion; } @@ -29,7 +35,7 @@ Building::level_t Building::get_max_level() const { return max_level; } -std::map<Good const*, fixed_point_t> const& Building::get_goods_cost() const { +Good::good_map_t const& Building::get_goods_cost() const { return goods_cost; } @@ -97,17 +103,14 @@ fixed_point_t Building::get_infrastructure() const { return infrastructure; } -fixed_point_t Building::get_movement_cost() const { - return movement_cost; -} - bool Building::spawned_railway_track() const { return spawn_railway_track; } BuildingType::BuildingType(std::string_view new_identifier) : HasIdentifier { new_identifier } {} -BuildingInstance::BuildingInstance(Building const& building) : HasIdentifier { building.get_identifier() }, building { building } {} +BuildingInstance::BuildingInstance(Building const& building) + : HasIdentifier { building.get_identifier() }, building { building } {} Building const& BuildingInstance::get_building() const { return building; @@ -181,7 +184,7 @@ bool BuildingManager::add_building_type(std::string_view identifier) { Logger::error("Invalid building type identifier - empty!"); return false; } - return building_types.add_item({ identifier }); + return building_types.add_item({ identifier }, duplicate_ignore_callback); } bool BuildingManager::add_building(std::string_view identifier, BuildingType const* type, ARGS) { @@ -195,21 +198,16 @@ bool BuildingManager::add_building(std::string_view identifier, BuildingType con } return buildings.add_item({ - identifier, *type, on_completion, completion_size, max_level, goods_cost, cost, build_time, visibility, on_map, default_enabled, - production_type, pop_build_factory, strategic_factory, advanced_factory, fort_level, naval_capacity, colonial_points, in_province, one_per_state, - colonial_range, infrastructure, movement_cost, local_ship_build, spawn_railway_track, sail, steam, capital, port, std::move(modifiers) + identifier, *type, std::move(modifier), on_completion, completion_size, max_level, std::move(goods_cost), cost, build_time, visibility, on_map, default_enabled, + production_type, pop_build_factory, strategic_factory, advanced_factory, fort_level, naval_capacity, std::move(colonial_points), in_province, one_per_state, + colonial_range, infrastructure, spawn_railway_track, sail, steam, capital, port }); } bool BuildingManager::load_buildings_file(GoodManager const& good_manager, ProductionTypeManager const& production_type_manager, ModifierManager const& modifier_manager, ast::NodeCPtr root) { bool ret = expect_dictionary_reserve_length(buildings, [this](std::string_view, ast::NodeCPtr value) -> bool { return expect_key("type", expect_identifier( - [this](std::string_view identifier) -> bool { - if (!building_types.has_identifier(identifier)) { - return building_types.add_item({ identifier }); - } - return true; - } + std::bind(&BuildingManager::add_building_type, this, std::placeholders::_1) ))(value); })(root); lock_building_types(); @@ -218,17 +216,17 @@ bool BuildingManager::load_buildings_file(GoodManager const& good_manager, Produ BuildingType const* type = nullptr; ProductionType const* production_type = nullptr; std::string_view on_completion; - fixed_point_t completion_size = 0, cost = 0, infrastructure = 0, movement_cost = 0, colonial_range = 0, local_ship_build = 0; + fixed_point_t completion_size = 0, cost = 0, infrastructure = 0, colonial_range = 0; Building::level_t max_level = 0, fort_level = 0; - std::map<Good const*, fixed_point_t> goods_cost; + Good::good_map_t goods_cost; Timespan build_time; bool visibility = false, on_map = false, default_enabled = false, pop_build_factory = false, strategic_factory = false, advanced_factory = false; bool in_province = false, one_per_state = false, spawn_railway_track = false, sail = false, steam = false, capital = false, port = false; uint64_t naval_capacity = 0; std::vector<fixed_point_t> colonial_points; - ModifierValue modifiers; + ModifierValue modifier; - bool ret = modifier_manager.expect_modifier_value_and_keys(move_variable_callback(modifiers), + bool ret = modifier_manager.expect_modifier_value_and_keys(move_variable_callback(modifier), "type", ONE_EXACTLY, expect_identifier(expect_building_type_identifier(assign_variable_callback_pointer(type))), "on_completion", ZERO_OR_ONE, expect_identifier(assign_variable_callback(on_completion)), "completion_size", ZERO_OR_ONE, expect_fixed_point(assign_variable_callback(completion_size)), @@ -239,7 +237,8 @@ bool BuildingManager::load_buildings_file(GoodManager const& good_manager, Produ "visibility", ONE_EXACTLY, expect_bool(assign_variable_callback(visibility)), "onmap", ONE_EXACTLY, expect_bool(assign_variable_callback(on_map)), "default_enabled", ZERO_OR_ONE, expect_bool(assign_variable_callback(default_enabled)), - "production_type", ZERO_OR_ONE, expect_identifier(production_type_manager.expect_production_type_identifier(assign_variable_callback_pointer(production_type))), + "production_type", ZERO_OR_ONE, expect_identifier(production_type_manager.expect_production_type_identifier( + assign_variable_callback_pointer(production_type))), "pop_build_factory", ZERO_OR_ONE, expect_bool(assign_variable_callback(pop_build_factory)), "strategic_factory", ZERO_OR_ONE, expect_bool(assign_variable_callback(strategic_factory)), "advanced_factory", ZERO_OR_ONE, expect_bool(assign_variable_callback(advanced_factory)), @@ -253,8 +252,6 @@ bool BuildingManager::load_buildings_file(GoodManager const& good_manager, Produ "one_per_state", ZERO_OR_ONE, expect_bool(assign_variable_callback(one_per_state)), "colonial_range", ZERO_OR_ONE, expect_fixed_point(assign_variable_callback(colonial_range)), "infrastructure", ZERO_OR_ONE, expect_fixed_point(assign_variable_callback(infrastructure)), - "movement_cost", ZERO_OR_ONE, expect_fixed_point(assign_variable_callback(movement_cost)), - "local_ship_build", ZERO_OR_ONE, expect_fixed_point(assign_variable_callback(local_ship_build)), "spawn_railway_track", ZERO_OR_ONE, expect_bool(assign_variable_callback(spawn_railway_track)), "sail", ZERO_OR_ONE, expect_bool(assign_variable_callback(sail)), "steam", ZERO_OR_ONE, expect_bool(assign_variable_callback(steam)), @@ -263,9 +260,10 @@ bool BuildingManager::load_buildings_file(GoodManager const& good_manager, Produ )(value); ret &= add_building( - key, type, on_completion, completion_size, max_level, goods_cost, cost, build_time, visibility, on_map, default_enabled, - production_type, pop_build_factory, strategic_factory, advanced_factory, fort_level, naval_capacity, colonial_points, in_province, - one_per_state, colonial_range, infrastructure, movement_cost, local_ship_build, spawn_railway_track, sail, steam, capital, port, std::move(modifiers) + key, type,std::move(modifier), on_completion, completion_size, max_level, std::move(goods_cost), cost, build_time, + visibility, on_map, default_enabled, production_type, pop_build_factory, strategic_factory, advanced_factory, + fort_level, naval_capacity, std::move(colonial_points), in_province, one_per_state, colonial_range, infrastructure, + spawn_railway_track, sail, steam, capital, port ); return ret; diff --git a/src/openvic-simulation/economy/Building.hpp b/src/openvic-simulation/economy/Building.hpp index 3d1e24b..cbf5bfd 100644 --- a/src/openvic-simulation/economy/Building.hpp +++ b/src/openvic-simulation/economy/Building.hpp @@ -7,12 +7,13 @@ #include "openvic-simulation/economy/ProductionType.hpp" #include "openvic-simulation/Modifier.hpp" -#define ARGS std::string_view on_completion, fixed_point_t completion_size, level_t max_level, \ - std::map<Good const*, fixed_point_t> goods_cost, fixed_point_t cost, Timespan build_time, bool visibility, bool on_map, bool default_enabled, \ - ProductionType const* production_type, bool pop_build_factory, bool strategic_factory, bool advanced_factory, level_t fort_level, \ - uint64_t naval_capacity, std::vector<fixed_point_t> colonial_points, bool in_province, bool one_per_state, fixed_point_t colonial_range, \ - fixed_point_t infrastructure, fixed_point_t movement_cost, fixed_point_t local_ship_build, bool spawn_railway_track, bool sail, bool steam, \ - bool capital, bool port, ModifierValue&& modifiers +#define ARGS \ + ModifierValue&& modifier, std::string_view on_completion, fixed_point_t completion_size, level_t max_level, \ + Good::good_map_t&& goods_cost, fixed_point_t cost, Timespan build_time, bool visibility, bool on_map, bool default_enabled, \ + ProductionType const* production_type, bool pop_build_factory, bool strategic_factory, bool advanced_factory, level_t fort_level, \ + uint64_t naval_capacity, std::vector<fixed_point_t>&& colonial_points, bool in_province, bool one_per_state, fixed_point_t colonial_range, \ + fixed_point_t infrastructure, bool spawn_railway_track, bool sail, bool steam, \ + bool capital, bool port namespace OpenVic { @@ -24,17 +25,18 @@ namespace OpenVic { * MAP-12, MAP-75, MAP-76 * MAP-13, MAP-78, MAP-79 */ - struct Building : HasIdentifier, ModifierValue { + struct Building : HasIdentifier { friend struct BuildingManager; using level_t = int16_t; private: BuildingType const& type; + ModifierValue modifier; const std::string on_completion; //probably sound played on completion const fixed_point_t completion_size; const level_t max_level; - const std::map<Good const*, fixed_point_t> goods_cost; + const Good::good_map_t goods_cost; const fixed_point_t cost; const Timespan build_time; //time const bool visibility; @@ -55,8 +57,6 @@ namespace OpenVic { const fixed_point_t colonial_range; const fixed_point_t infrastructure; - const fixed_point_t movement_cost; - const fixed_point_t local_ship_build; const bool spawn_railway_track; const bool sail; //only in clipper shipyard @@ -70,10 +70,11 @@ namespace OpenVic { Building(Building&&) = default; BuildingType const& get_type() const; + ModifierValue const& get_modifier() const; std::string_view get_on_completion() const; fixed_point_t get_completion_size() const; level_t get_max_level() const; - std::map<Good const*, fixed_point_t> const& get_goods_cost() const; + Good::good_map_t const& get_goods_cost() const; fixed_point_t get_cost() const; Timespan get_build_time() const; bool has_visibility() const; @@ -94,8 +95,6 @@ namespace OpenVic { fixed_point_t get_colonial_range() const; fixed_point_t get_infrastructure() const; - fixed_point_t get_movement_cost() const; - fixed_point_t get_local_ship_build() const; bool spawned_railway_track() const; }; diff --git a/src/openvic-simulation/economy/Good.hpp b/src/openvic-simulation/economy/Good.hpp index 1dce41f..2a850fa 100644 --- a/src/openvic-simulation/economy/Good.hpp +++ b/src/openvic-simulation/economy/Good.hpp @@ -33,6 +33,8 @@ namespace OpenVic { using price_t = fixed_point_t; static constexpr price_t NULL_PRICE = fixed_point_t::_0(); + using good_map_t = decimal_map_t<Good const*>; + private: GoodCategory const& category; const price_t base_price; diff --git a/src/openvic-simulation/economy/ProductionType.cpp b/src/openvic-simulation/economy/ProductionType.cpp index 01d45be..3a27cd6 100644 --- a/src/openvic-simulation/economy/ProductionType.cpp +++ b/src/openvic-simulation/economy/ProductionType.cpp @@ -8,29 +8,29 @@ using namespace OpenVic::NodeTools; EmployedPop::EmployedPop(PopType const* pop_type, bool artisan, effect_t effect, fixed_point_t effect_multiplier, fixed_point_t amount) : pop_type { pop_type }, artisan { artisan }, effect { effect }, effect_multiplier { effect_multiplier }, amount { amount } {} -PopType const* EmployedPop::get_pop_type() { +PopType const* EmployedPop::get_pop_type() const { return pop_type; } -bool EmployedPop::is_artisan() { +bool EmployedPop::is_artisan() const { return artisan; } -EmployedPop::effect_t EmployedPop::get_effect() { +EmployedPop::effect_t EmployedPop::get_effect() const { return effect; } -fixed_point_t EmployedPop::get_effect_multiplier() { +fixed_point_t EmployedPop::get_effect_multiplier() const { return effect_multiplier; } -fixed_point_t EmployedPop::get_amount() { +fixed_point_t EmployedPop::get_amount() const { return amount; } -ProductionType::ProductionType(PRODUCTION_TYPE_ARGS) : HasIdentifier { identifier }, owner { owner }, - employees { employees }, type { type }, workforce { workforce }, input_goods { input_goods }, output_goods { output_goods }, - value { value }, bonuses { bonuses }, efficiency { efficiency }, coastal { coastal }, farm { farm }, mine { mine } {} +ProductionType::ProductionType(PRODUCTION_TYPE_ARGS) : HasIdentifier { identifier }, owner { owner }, employees { employees }, + type { type }, workforce { workforce }, input_goods { std::move(input_goods) }, output_goods { output_goods }, + value { value }, bonuses { std::move(bonuses) }, efficiency { std::move(efficiency) }, coastal { coastal }, farm { farm }, mine { mine } {} EmployedPop const& ProductionType::get_owner() const { return owner; @@ -48,7 +48,7 @@ Pop::pop_size_t ProductionType::get_workforce() const { return workforce; } -std::map<Good const*, fixed_point_t> const& ProductionType::get_input_goods() { +Good::good_map_t const& ProductionType::get_input_goods() const { return input_goods; } @@ -60,11 +60,11 @@ fixed_point_t ProductionType::get_value() const { return value; } -std::vector<Bonus> const& ProductionType::get_bonuses() { +std::vector<Bonus> const& ProductionType::get_bonuses() const { return bonuses; } -std::map<Good const*, fixed_point_t> const& ProductionType::get_efficiency() { +Good::good_map_t const& ProductionType::get_efficiency() const { return efficiency; } @@ -83,7 +83,7 @@ bool ProductionType::is_mine() const { ProductionTypeManager::ProductionTypeManager() : production_types { "production types" } {} node_callback_t ProductionTypeManager::_expect_employed_pop(GoodManager const& good_manager, PopManager const& pop_manager, - callback_t<EmployedPop> cb) { + callback_t<EmployedPop&&> cb) { return [this, &good_manager, &pop_manager, cb](ast::NodeCPtr node) -> bool { std::string_view pop_type; @@ -113,12 +113,12 @@ node_callback_t ProductionTypeManager::_expect_employed_pop(GoodManager const& g } } - return res & cb(EmployedPop { found_pop_type, artisan, effect, effect_multiplier, amount }); + return res & cb({ found_pop_type, artisan, effect, effect_multiplier, amount }); }; } node_callback_t ProductionTypeManager::_expect_employed_pop_list(GoodManager const& good_manager, PopManager const& pop_manager, - callback_t<std::vector<EmployedPop>> cb) { + callback_t<std::vector<EmployedPop>&&> cb) { return [this, &good_manager, &pop_manager, cb](ast::NodeCPtr node) -> bool { std::vector<EmployedPop> employed_pops; @@ -128,7 +128,7 @@ node_callback_t ProductionTypeManager::_expect_employed_pop_list(GoodManager con employed_pops.push_back(owner); return res_partial; })(node); - return res & cb(employed_pops); + return res & cb(std::move(employed_pops)); }; } @@ -166,25 +166,25 @@ bool ProductionTypeManager::add_production_type(PRODUCTION_TYPE_ARGS, GoodManage } return production_types.add_item({ - identifier, owner, employees, type, workforce, input_goods, - output_goods, value, bonuses, efficiency, coastal, farm, mine + identifier, owner, employees, type, workforce, std::move(input_goods), + output_goods, value, std::move(bonuses), std::move(efficiency), coastal, farm, mine }); } #define PARSE_NODE expect_dictionary_keys_and_default( \ - key_value_success_callback, \ - "owner", ZERO_OR_ONE, _expect_employed_pop(good_manager, pop_manager, move_variable_callback(owner)), \ - "employees", ZERO_OR_ONE, _expect_employed_pop_list(good_manager, pop_manager, move_variable_callback(employees)), \ - "type", ZERO_OR_ONE, expect_identifier(expect_mapped_string(type_map, assign_variable_callback(type))), \ - "workforce", ZERO_OR_ONE, expect_uint(assign_variable_callback(workforce)), \ - "input_goods", ZERO_OR_ONE, good_manager.expect_good_decimal_map(move_variable_callback(input_goods)), \ - "output_goods", ZERO_OR_ONE, expect_identifier(good_manager.expect_good_identifier(assign_variable_callback_pointer(output_goods))), \ - "value", ZERO_OR_ONE, expect_fixed_point(assign_variable_callback(value)), \ - "efficiency", ZERO_OR_ONE, good_manager.expect_good_decimal_map(move_variable_callback(efficiency)), \ - "is_coastal", ZERO_OR_ONE, expect_bool(assign_variable_callback(coastal)), \ - "farm", ZERO_OR_ONE, expect_bool(assign_variable_callback(farm)), \ - "mine", ZERO_OR_ONE, expect_bool(assign_variable_callback(mine)) \ - ) + key_value_success_callback, \ + "owner", ZERO_OR_ONE, _expect_employed_pop(good_manager, pop_manager, move_variable_callback(owner)), \ + "employees", ZERO_OR_ONE, _expect_employed_pop_list(good_manager, pop_manager, move_variable_callback(employees)), \ + "type", ZERO_OR_ONE, expect_identifier(expect_mapped_string(type_map, assign_variable_callback(type))), \ + "workforce", ZERO_OR_ONE, expect_uint(assign_variable_callback(workforce)), \ + "input_goods", ZERO_OR_ONE, good_manager.expect_good_decimal_map(move_variable_callback(input_goods)), \ + "output_goods", ZERO_OR_ONE, expect_identifier(good_manager.expect_good_identifier(assign_variable_callback_pointer(output_goods))), \ + "value", ZERO_OR_ONE, expect_fixed_point(assign_variable_callback(value)), \ + "efficiency", ZERO_OR_ONE, good_manager.expect_good_decimal_map(move_variable_callback(efficiency)), \ + "is_coastal", ZERO_OR_ONE, expect_bool(assign_variable_callback(coastal)), \ + "farm", ZERO_OR_ONE, expect_bool(assign_variable_callback(farm)), \ + "mine", ZERO_OR_ONE, expect_bool(assign_variable_callback(mine)) \ + ) bool ProductionTypeManager::load_production_types_file(GoodManager const& good_manager, PopManager const& pop_manager, ast::NodeCPtr root) { size_t expected_types = 0; @@ -236,7 +236,7 @@ bool ProductionTypeManager::load_production_types_file(GoodManager const& good_m ProductionType::type_t type; Good const* output_goods = nullptr; Pop::pop_size_t workforce = 0; // 0 is a meaningless value -> unset - std::map<Good const*, fixed_point_t> input_goods, efficiency; + Good::good_map_t input_goods, efficiency; fixed_point_t value = 0; // 0 is a meaningless value -> unset std::vector<Bonus> bonuses; bool coastal = false, farm = false, mine = false; @@ -260,8 +260,8 @@ bool ProductionTypeManager::load_production_types_file(GoodManager const& good_m ret &= PARSE_NODE(node); ret &= add_production_type( - key, owner, employees, type, workforce, input_goods, output_goods, value, - bonuses, efficiency, coastal, farm, mine, good_manager + key, owner, employees, type, workforce, std::move(input_goods), output_goods, value, + std::move(bonuses), std::move(efficiency), coastal, farm, mine, good_manager ); return ret; } diff --git a/src/openvic-simulation/economy/ProductionType.hpp b/src/openvic-simulation/economy/ProductionType.hpp index 420e70e..2deb461 100644 --- a/src/openvic-simulation/economy/ProductionType.hpp +++ b/src/openvic-simulation/economy/ProductionType.hpp @@ -7,9 +7,8 @@ #define PRODUCTION_TYPE_ARGS \ std::string_view identifier, EmployedPop owner, std::vector<EmployedPop> employees, ProductionType::type_t type, \ - Pop::pop_size_t workforce, std::map<Good const*, fixed_point_t> input_goods, Good const* output_goods, \ - fixed_point_t value, std::vector<Bonus> bonuses, std::map<Good const*, fixed_point_t> efficiency, \ - bool coastal, bool farm, bool mine + Pop::pop_size_t workforce, Good::good_map_t&& input_goods, Good const* output_goods, fixed_point_t value, \ + std::vector<Bonus>&& bonuses, Good::good_map_t&& efficiency, bool coastal, bool farm, bool mine namespace OpenVic { struct ProductionTypeManager; @@ -17,14 +16,16 @@ namespace OpenVic { struct EmployedPop { friend struct ProductionTypeManager; - private: - PopType const* pop_type; // poptype - bool artisan; // set by the parser if the magic "artisan" poptype is passed enum struct effect_t { INPUT, OUTPUT, THROUGHPUT - } effect; + }; + + private: + PopType const* pop_type; // poptype + bool artisan; // set by the parser if the magic "artisan" poptype is passed + effect_t effect; fixed_point_t effect_multiplier; fixed_point_t amount; @@ -33,11 +34,11 @@ namespace OpenVic { public: EmployedPop() = default; - PopType const* get_pop_type(); - bool is_artisan(); - effect_t get_effect(); - fixed_point_t get_effect_multiplier(); - fixed_point_t get_amount(); + PopType const* get_pop_type() const; + bool is_artisan() const; + effect_t get_effect() const; + fixed_point_t get_effect_multiplier() const; + fixed_point_t get_amount() const; }; struct Bonus { @@ -58,12 +59,12 @@ namespace OpenVic { } type; const Pop::pop_size_t workforce; - const std::map<Good const*, fixed_point_t> input_goods; + const Good::good_map_t input_goods; Good const* output_goods; const fixed_point_t value; const std::vector<Bonus> bonuses; - const std::map<Good const*, fixed_point_t> efficiency; + const Good::good_map_t efficiency; const bool coastal; // is_coastal const bool farm; @@ -79,12 +80,12 @@ namespace OpenVic { type_t get_type() const; Pop::pop_size_t get_workforce() const; - std::map<Good const*, fixed_point_t> const& get_input_goods(); + Good::good_map_t const& get_input_goods() const; Good const* get_output_goods() const; fixed_point_t get_value() const; - std::vector<Bonus> const& get_bonuses(); + std::vector<Bonus> const& get_bonuses() const; - std::map<Good const*, fixed_point_t> const& get_efficiency(); + Good::good_map_t const& get_efficiency() const; bool is_coastal() const; bool is_farm() const; @@ -96,9 +97,9 @@ namespace OpenVic { IdentifierRegistry<ProductionType> production_types; NodeTools::node_callback_t _expect_employed_pop(GoodManager const& good_manager, PopManager const& pop_manager, - NodeTools::callback_t<EmployedPop> cb); + NodeTools::callback_t<EmployedPop&&> cb); NodeTools::node_callback_t _expect_employed_pop_list(GoodManager const& good_manager, PopManager const& pop_manager, - NodeTools::callback_t<std::vector<EmployedPop>> cb); + NodeTools::callback_t<std::vector<EmployedPop>&&> cb); public: ProductionTypeManager(); diff --git a/src/openvic-simulation/map/Map.cpp b/src/openvic-simulation/map/Map.cpp index acd882e..777579e 100644 --- a/src/openvic-simulation/map/Map.cpp +++ b/src/openvic-simulation/map/Map.cpp @@ -525,16 +525,16 @@ bool Map::load_map_images(fs::path const& province_path, fs::path const& terrain for (size_t idx = 0; idx < province_checklist.size(); ++idx) { Province* province = provinces.get_item_by_index(idx); province->_set_terrain_type(reinterpret_cast<TerrainType const*>(get_largest_item(terrain_type_pixels_list[idx]).first)); - if (!province_checklist[idx]) { + province->on_map = province_checklist[idx]; + if (!province->on_map) { if (detailed_errors) { - Logger::error("Province missing from shape image: ", province->to_string()); + Logger::warning("Province missing from shape image: ", province->to_string()); } missing++; } } if (missing > 0) { - Logger::error("Province image is missing ", missing, " province colours"); - ret = false; + Logger::warning("Province image is missing ", missing, " province colours"); } return ret; diff --git a/src/openvic-simulation/map/Province.cpp b/src/openvic-simulation/map/Province.cpp index 5b1a130..45b3987 100644 --- a/src/openvic-simulation/map/Province.cpp +++ b/src/openvic-simulation/map/Province.cpp @@ -17,6 +17,10 @@ Region* Province::get_region() const { return region; } +bool Province::get_on_map() const { + return on_map; +} + bool Province::get_has_region() const { return has_region; } diff --git a/src/openvic-simulation/map/Province.hpp b/src/openvic-simulation/map/Province.hpp index d925898..2704354 100644 --- a/src/openvic-simulation/map/Province.hpp +++ b/src/openvic-simulation/map/Province.hpp @@ -61,7 +61,7 @@ namespace OpenVic { private: const index_t index; Region* region = nullptr; - bool has_region = false, water = false; + bool on_map = false, has_region = false, water = false; life_rating_t life_rating = 0; IdentifierRegistry<BuildingInstance> buildings; // TODO - change this into a factory-like structure @@ -85,6 +85,7 @@ namespace OpenVic { index_t get_index() const; Region* get_region() const; + bool get_on_map() const; bool get_has_region() const; bool get_water() const; TerrainType const* get_terrain_type() const; diff --git a/src/openvic-simulation/map/TerrainType.cpp b/src/openvic-simulation/map/TerrainType.cpp index ce0b7e7..017b220 100644 --- a/src/openvic-simulation/map/TerrainType.cpp +++ b/src/openvic-simulation/map/TerrainType.cpp @@ -125,11 +125,8 @@ bool TerrainTypeManager::_load_terrain_type_mapping(std::string_view mapping_key "priority", ZERO_OR_ONE, expect_uint(assign_variable_callback(priority)), "has_texture", ZERO_OR_ONE, expect_bool(assign_variable_callback(has_texture)) )(mapping_value); - if (has_texture) { - if (++terrain_texture_count == terrain_texture_limit + 1) { - Logger::error("More terrain textures than limit!"); - ret = false; - } + if (has_texture && ++terrain_texture_count == terrain_texture_limit + 1) { + Logger::warning("More terrain textures than limit!"); } ret &= add_terrain_type_mapping(mapping_key, type, std::move(terrain_indicies), priority, has_texture); return true; diff --git a/src/openvic-simulation/military/Unit.cpp b/src/openvic-simulation/military/Unit.cpp index 63ece91..8b010e3 100644 --- a/src/openvic-simulation/military/Unit.cpp +++ b/src/openvic-simulation/military/Unit.cpp @@ -2,22 +2,27 @@ #include <set> -#define UNIT_ARGS icon, sprite, active, unit_type, floating_flag, priority, max_strength, \ - default_organisation, maximum_speed, weighted_value, build_time, build_cost, supply_consumption, \ - supply_cost -#define LAND_ARGS primary_culture, sprite_override, sprite_mount, sprite_mount_attach_node, \ - reconnaissance, attack, defence, discipline, support, maneuver, siege -#define NAVY_ARGS naval_icon, sail, transport, capital, move_sound, select_sound, colonial_points, build_overseas, min_port_level, \ - limit_per_port, supply_consumption_score, hull, gun_power, fire_range, evasion, torpedo_attack +#define UNIT_ARGS \ + icon, sprite, active, unit_type, floating_flag, priority, max_strength, default_organisation, maximum_speed, \ + weighted_value, move_sound, select_sound, build_time, std::move(build_cost), supply_consumption, std::move(supply_cost) + +#define LAND_ARGS \ + primary_culture, sprite_override, sprite_mount, sprite_mount_attach_node, \ + reconnaissance, attack, defence, discipline, support, maneuver, siege + +#define NAVY_ARGS \ + naval_icon, sail, transport, capital, colonial_points, build_overseas, min_port_level, \ + limit_per_port, supply_consumption_score, hull, gun_power, fire_range, evasion, torpedo_attack using namespace OpenVic; using namespace OpenVic::NodeTools; -Unit::Unit(std::string_view identifier, type_t type, UNIT_PARAMS) : HasIdentifier { identifier }, - icon { icon }, type { type }, sprite { sprite }, active { active }, unit_type { unit_type }, - floating_flag { floating_flag }, priority { priority }, max_strength { max_strength }, +Unit::Unit(std::string_view identifier, type_t type, UNIT_PARAMS) + : HasIdentifier { identifier }, icon { icon }, type { type }, sprite { sprite }, active { active }, + unit_type { unit_type }, floating_flag { floating_flag }, priority { priority }, max_strength { max_strength }, default_organisation { default_organisation }, maximum_speed { maximum_speed }, weighted_value { weighted_value }, - build_time { build_time }, build_cost { build_cost }, supply_consumption { supply_consumption }, supply_cost { supply_cost } {} + move_sound { move_sound }, select_sound { select_sound }, build_time { build_time }, build_cost { std::move(build_cost) }, + supply_consumption { supply_consumption }, supply_cost { std::move(supply_cost) } {} Unit::icon_t Unit::get_icon() const { return icon; @@ -67,7 +72,15 @@ fixed_point_t Unit::get_weighted_value() const { return weighted_value; } -std::map<Good const*, fixed_point_t> const& Unit::get_build_cost() const { +std::string_view Unit::get_move_sound() const { + return move_sound; +} + +std::string_view Unit::get_select_sound() const { + return select_sound; +} + +Good::good_map_t const& Unit::get_build_cost() const { return build_cost; } @@ -75,14 +88,15 @@ fixed_point_t Unit::get_supply_consumption() const { return supply_consumption; } -std::map<Good const*, fixed_point_t> const& Unit::get_supply_cost() const { +Good::good_map_t const& Unit::get_supply_cost() const { return supply_cost; } LandUnit::LandUnit(std::string_view identifier, UNIT_PARAMS, LAND_PARAMS) - : Unit { identifier, type_t::LAND, UNIT_ARGS }, primary_culture { primary_culture }, sprite_override { sprite_override }, - sprite_mount { sprite_mount }, sprite_mount_attach_node { sprite_mount_attach_node }, reconnaissance { reconnaissance }, - attack { attack }, defence { defence }, discipline { discipline }, support { support }, maneuver { maneuver }, siege { siege } {} + : Unit { identifier, type_t::LAND, UNIT_ARGS }, primary_culture { primary_culture }, + sprite_override { sprite_override }, sprite_mount { sprite_mount }, sprite_mount_attach_node { sprite_mount_attach_node }, + reconnaissance { reconnaissance }, attack { attack }, defence { defence }, discipline { discipline }, support { support }, + maneuver { maneuver }, siege { siege } {} bool LandUnit::get_primary_culture() const { return primary_culture; @@ -128,11 +142,12 @@ fixed_point_t LandUnit::get_siege() const { return siege; } -NavalUnit::NavalUnit(std::string_view identifier, UNIT_PARAMS, NAVY_PARAMS) : Unit { identifier, type_t::NAVAL, UNIT_ARGS }, - naval_icon { naval_icon }, sail { sail }, transport { transport }, capital { capital }, move_sound { move_sound }, - select_sound { select_sound }, colonial_points { colonial_points }, build_overseas { build_overseas }, - min_port_level { min_port_level }, limit_per_port { limit_per_port }, supply_consumption_score { supply_consumption_score }, - hull { hull }, gun_power { gun_power }, fire_range { fire_range }, evasion { evasion }, torpedo_attack { torpedo_attack } {}; +NavalUnit::NavalUnit(std::string_view identifier, UNIT_PARAMS, NAVY_PARAMS) + : Unit { identifier, type_t::NAVAL, UNIT_ARGS }, naval_icon { naval_icon }, sail { sail }, + transport { transport }, capital { capital }, colonial_points { colonial_points }, + build_overseas { build_overseas }, min_port_level { min_port_level },limit_per_port { limit_per_port }, + supply_consumption_score { supply_consumption_score }, hull { hull }, gun_power { gun_power }, + fire_range { fire_range }, evasion { evasion }, torpedo_attack { torpedo_attack } {}; NavalUnit::icon_t NavalUnit::get_naval_icon() const { return naval_icon; @@ -146,14 +161,6 @@ bool NavalUnit::is_transport() const { return transport; } -std::string_view NavalUnit::get_move_sound() const { - return move_sound; -} - -std::string_view NavalUnit::get_select_sound() const { - return select_sound; -} - fixed_point_t NavalUnit::get_colonial_points() const { return colonial_points; } @@ -235,32 +242,33 @@ bool UnitManager::add_naval_unit(std::string_view identifier, UNIT_PARAMS, NAVY_ return units.add_item(NavalUnit { identifier, UNIT_ARGS, NAVY_ARGS }); } -static bool shared_keys_callback(std::string_view key, ast::NodeCPtr) { - static const std::set<std::string, std::less<void>> reserved_keys = { - "icon", "type", "sprite", "active", "unit_type", "floating_flag", "priority", - "max_strength", "default_organisation", "maximum_speed", "weighted_value", - "build_time", "build_cost", "supply_consumption", "supply_cost" - }; - if (reserved_keys.contains(key)) return true; - Logger::error("Invalid key: ", key); - return false; -}; - bool UnitManager::load_unit_file(GoodManager const& good_manager, ast::NodeCPtr root) { return expect_dictionary([this, &good_manager](std::string_view key, ast::NodeCPtr value) -> bool { + Unit::type_t type; Unit::icon_t icon = 0; - std::string_view type, unit_type, sprite; + std::string_view unit_type, sprite, move_sound, select_sound; // TODO defaults for move_sound and select_sound bool active = true, floating_flag = false; uint32_t priority = 0; Timespan build_time; fixed_point_t maximum_speed = 0, max_strength = 0, default_organisation = 0, weighted_value = 0, supply_consumption = 0; - std::map<Good const*, fixed_point_t> build_cost, supply_cost; + Good::good_map_t build_cost, supply_cost; + using enum Unit::type_t; + static const string_map_t<Unit::type_t> type_map = { + { "land", LAND }, { "naval", NAVAL } + }; + bool ret = expect_key("type", expect_identifier(expect_mapped_string(type_map, assign_variable_callback(type))))(value); + + if (!ret) { + Logger::error("Failed to read type for unit: ", key); + return false; + } + + key_map_t key_map; //shared - bool ret = expect_dictionary_keys_and_default( - key_value_success_callback, + ret &= add_key_map_entries(key_map, "icon", ONE_EXACTLY, expect_uint(assign_variable_callback(icon)), - "type", ONE_EXACTLY, expect_identifier(assign_variable_callback(type)), + "type", ONE_EXACTLY, success_callback, "sprite", ONE_EXACTLY, expect_identifier(assign_variable_callback(sprite)), "active", ZERO_OR_ONE, expect_bool(assign_variable_callback(active)), "unit_type", ONE_EXACTLY, expect_identifier(assign_variable_callback(unit_type)), @@ -270,69 +278,77 @@ bool UnitManager::load_unit_file(GoodManager const& good_manager, ast::NodeCPtr "default_organisation", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(default_organisation)), "maximum_speed", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(maximum_speed)), "weighted_value", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(weighted_value)), + "move_sound", ZERO_OR_ONE, expect_identifier(assign_variable_callback(move_sound)), + "select_sound", ZERO_OR_ONE, expect_identifier(assign_variable_callback(select_sound)), "build_time", ONE_EXACTLY, expect_days(assign_variable_callback(build_time)), "build_cost", ONE_EXACTLY, good_manager.expect_good_decimal_map(move_variable_callback(build_cost)), "supply_consumption", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(supply_consumption)), "supply_cost", ONE_EXACTLY, good_manager.expect_good_decimal_map(move_variable_callback(supply_cost)) - )(value); - - if (type == "land") { - bool primary_culture = false; - std::string_view sprite_override, sprite_mount, sprite_mount_attach_node; - fixed_point_t reconnaissance = 0, attack = 0, defence = 0, discipline = 0, support = 0, maneuver = 0, siege = 0; - - ret &= expect_dictionary_keys_and_default( - shared_keys_callback, - "primary_culture", ZERO_OR_ONE, expect_bool(assign_variable_callback(primary_culture)), - "sprite_override", ZERO_OR_ONE, expect_identifier(assign_variable_callback(sprite_override)), - "sprite_mount", ZERO_OR_ONE, expect_identifier(assign_variable_callback(sprite_mount)), - "sprite_mount_attach_node", ZERO_OR_ONE, expect_identifier(assign_variable_callback(sprite_mount_attach_node)), - "reconnaissance", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(reconnaissance)), - "attack", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(attack)), - "defence", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(defence)), - "discipline", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(discipline)), - "support", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(support)), - "maneuver", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(maneuver)), - "siege", ZERO_OR_ONE, expect_fixed_point(assign_variable_callback(siege)) - )(value); - - ret &= add_land_unit(key, UNIT_ARGS, LAND_ARGS); - - return ret; - } else if (type == "naval") { - Unit::icon_t naval_icon = 0; - bool sail = false, transport = false, capital = false, build_overseas = false; - std::string_view move_sound, select_sound; //TODO defaults for both - uint32_t min_port_level = 0; - int32_t limit_per_port = 0; - fixed_point_t fire_range = 0, evasion = 0, supply_consumption_score = 0, hull = 0, gun_power = 0, colonial_points = 0, torpedo_attack = 0; - - ret &= expect_dictionary_keys_and_default( - shared_keys_callback, - "naval_icon", ONE_EXACTLY, expect_uint(assign_variable_callback(naval_icon)), - "sail", ZERO_OR_ONE, expect_bool(assign_variable_callback(sail)), - "transport", ZERO_OR_ONE, expect_bool(assign_variable_callback(transport)), - "capital", ZERO_OR_ONE, expect_bool(assign_variable_callback(capital)), - "move_sound", ZERO_OR_ONE, expect_identifier(assign_variable_callback(move_sound)), - "select_sound", ZERO_OR_ONE, expect_identifier(assign_variable_callback(select_sound)), - "colonial_points", ZERO_OR_ONE, expect_fixed_point(assign_variable_callback(colonial_points)), - "can_build_overseas", ZERO_OR_ONE, expect_bool(assign_variable_callback(build_overseas)), - "min_port_level", ONE_EXACTLY, expect_uint(assign_variable_callback(min_port_level)), - "limit_per_port", ONE_EXACTLY, expect_int(assign_variable_callback(limit_per_port)), - "supply_consumption_score", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(supply_consumption_score)), - "hull", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(hull)), - "gun_power", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(gun_power)), - "fire_range", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(fire_range)), - "evasion", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(evasion)), - "torpedo_attack", ZERO_OR_ONE, expect_fixed_point(assign_variable_callback(torpedo_attack)) - )(value); - - ret &= add_naval_unit(key, UNIT_ARGS, NAVY_ARGS); - - return ret; - } else { - Logger::error("Invalid type for unit ", key, ": ", type); + ); + + switch (type) { + case LAND: + { + bool primary_culture = false; + std::string_view sprite_override, sprite_mount, sprite_mount_attach_node; + fixed_point_t reconnaissance = 0, attack = 0, defence = 0, discipline = 0, support = 0, maneuver = 0, siege = 0; + + ret &= add_key_map_entries(key_map, + "primary_culture", ZERO_OR_ONE, expect_bool(assign_variable_callback(primary_culture)), + "sprite_override", ZERO_OR_ONE, expect_identifier(assign_variable_callback(sprite_override)), + "sprite_mount", ZERO_OR_ONE, expect_identifier(assign_variable_callback(sprite_mount)), + "sprite_mount_attach_node", ZERO_OR_ONE, expect_identifier(assign_variable_callback(sprite_mount_attach_node)), + "reconnaissance", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(reconnaissance)), + "attack", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(attack)), + "defence", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(defence)), + "discipline", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(discipline)), + "support", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(support)), + "maneuver", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(maneuver)), + "siege", ZERO_OR_ONE, expect_fixed_point(assign_variable_callback(siege)) + ); + + ret &= expect_dictionary_key_map(key_map)(value); + + ret &= add_land_unit(key, UNIT_ARGS, LAND_ARGS); + + return ret; + } + break; + case NAVAL: + { + Unit::icon_t naval_icon = 0; + bool sail = false, transport = false, capital = false, build_overseas = false; + uint32_t min_port_level = 0; + int32_t limit_per_port = 0; + fixed_point_t fire_range = 0, evasion = 0, supply_consumption_score = 0, hull = 0, gun_power = 0, colonial_points = 0, torpedo_attack = 0; + + ret &= add_key_map_entries(key_map, + "naval_icon", ONE_EXACTLY, expect_uint(assign_variable_callback(naval_icon)), + "sail", ZERO_OR_ONE, expect_bool(assign_variable_callback(sail)), + "transport", ZERO_OR_ONE, expect_bool(assign_variable_callback(transport)), + "capital", ZERO_OR_ONE, expect_bool(assign_variable_callback(capital)), + "colonial_points", ZERO_OR_ONE, expect_fixed_point(assign_variable_callback(colonial_points)), + "can_build_overseas", ZERO_OR_ONE, expect_bool(assign_variable_callback(build_overseas)), + "min_port_level", ONE_EXACTLY, expect_uint(assign_variable_callback(min_port_level)), + "limit_per_port", ONE_EXACTLY, expect_int(assign_variable_callback(limit_per_port)), + "supply_consumption_score", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(supply_consumption_score)), + "hull", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(hull)), + "gun_power", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(gun_power)), + "fire_range", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(fire_range)), + "evasion", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(evasion)), + "torpedo_attack", ZERO_OR_ONE, expect_fixed_point(assign_variable_callback(torpedo_attack)) + ); + + ret &= expect_dictionary_key_map(key_map)(value); + + ret &= add_naval_unit(key, UNIT_ARGS, NAVY_ARGS); + + return ret; + } + break; + default: + Logger::error("Unknown unit type for ", key, ": ", static_cast<int>(type)); return false; } })(root); -}
\ No newline at end of file +} diff --git a/src/openvic-simulation/military/Unit.hpp b/src/openvic-simulation/military/Unit.hpp index de30763..17408cf 100644 --- a/src/openvic-simulation/military/Unit.hpp +++ b/src/openvic-simulation/military/Unit.hpp @@ -9,18 +9,22 @@ #include "openvic-simulation/economy/Good.hpp" #include "openvic-simulation/types/Date.hpp" -#define UNIT_PARAMS Unit::icon_t icon, std::string_view sprite, bool active, std::string_view unit_type, \ - bool floating_flag, uint32_t priority, fixed_point_t max_strength, fixed_point_t default_organisation, \ - fixed_point_t maximum_speed, fixed_point_t weighted_value, Timespan build_time, \ - std::map<Good const*, fixed_point_t> build_cost, fixed_point_t supply_consumption, \ - std::map<Good const*, fixed_point_t> supply_cost -#define LAND_PARAMS bool primary_culture, std::string_view sprite_override, std::string_view sprite_mount, \ - std::string_view sprite_mount_attach_node, fixed_point_t reconnaissance, fixed_point_t attack, \ - fixed_point_t defence, fixed_point_t discipline, fixed_point_t support, fixed_point_t maneuver, fixed_point_t siege -#define NAVY_PARAMS Unit::icon_t naval_icon, bool sail, bool transport, bool capital, std::string_view move_sound, \ - std::string_view select_sound, fixed_point_t colonial_points, bool build_overseas, uint32_t min_port_level, \ - int32_t limit_per_port, fixed_point_t supply_consumption_score, fixed_point_t hull, fixed_point_t gun_power, \ - fixed_point_t fire_range, fixed_point_t evasion, fixed_point_t torpedo_attack +#define UNIT_PARAMS \ + Unit::icon_t icon, std::string_view sprite, bool active, std::string_view unit_type, \ + bool floating_flag, uint32_t priority, fixed_point_t max_strength, fixed_point_t default_organisation, \ + fixed_point_t maximum_speed, fixed_point_t weighted_value, std::string_view move_sound, \ + std::string_view select_sound, Timespan build_time, Good::good_map_t&& build_cost, \ + fixed_point_t supply_consumption, Good::good_map_t&& supply_cost + +#define LAND_PARAMS \ + bool primary_culture, std::string_view sprite_override, std::string_view sprite_mount, \ + std::string_view sprite_mount_attach_node, fixed_point_t reconnaissance, fixed_point_t attack, fixed_point_t defence, \ + fixed_point_t discipline, fixed_point_t support, fixed_point_t maneuver, fixed_point_t siege + +#define NAVY_PARAMS \ + Unit::icon_t naval_icon, bool sail, bool transport, bool capital, fixed_point_t colonial_points, bool build_overseas, \ + uint32_t min_port_level, int32_t limit_per_port, fixed_point_t supply_consumption_score, fixed_point_t hull, \ + fixed_point_t gun_power, fixed_point_t fire_range, fixed_point_t evasion, fixed_point_t torpedo_attack namespace OpenVic { struct Unit : HasIdentifier { @@ -44,10 +48,13 @@ namespace OpenVic { const fixed_point_t maximum_speed; const fixed_point_t weighted_value; + const std::string move_sound; + const std::string select_sound; + const Timespan build_time; - const std::map<Good const*, fixed_point_t> build_cost; + const Good::good_map_t build_cost; const fixed_point_t supply_consumption; - const std::map<Good const*, fixed_point_t> supply_cost; + const Good::good_map_t supply_cost; protected: Unit(std::string_view identifier, type_t type, UNIT_PARAMS); @@ -68,10 +75,13 @@ namespace OpenVic { fixed_point_t get_maximum_speed() const; fixed_point_t get_weighted_value() const; + std::string_view get_move_sound() const; + std::string_view get_select_sound() const; + Timespan get_build_time() const; - std::map<Good const*, fixed_point_t> const& get_build_cost() const; + Good::good_map_t const& get_build_cost() const; fixed_point_t get_supply_consumption() const; - std::map<Good const*, fixed_point_t> const& get_supply_cost() const; + Good::good_map_t const& get_supply_cost() const; }; struct LandUnit : Unit { @@ -115,8 +125,6 @@ namespace OpenVic { const bool sail; const bool transport; const bool capital; - const std::string move_sound; - const std::string select_sound; const fixed_point_t colonial_points; const bool build_overseas; const uint32_t min_port_level; @@ -138,8 +146,6 @@ namespace OpenVic { bool can_sail() const; bool is_transport() const; bool is_capital() const; - std::string_view get_move_sound() const; - std::string_view get_select_sound() const; fixed_point_t get_colonial_points() const; bool can_build_overseas() const; uint32_t get_min_port_level() const; diff --git a/src/openvic-simulation/politics/Government.cpp b/src/openvic-simulation/politics/Government.cpp index 16b3bc4..c65abc6 100644 --- a/src/openvic-simulation/politics/Government.cpp +++ b/src/openvic-simulation/politics/Government.cpp @@ -36,7 +36,7 @@ std::string_view GovernmentType::get_flag_type() const { GovernmentTypeManager::GovernmentTypeManager() : government_types { "government types" } {} -bool GovernmentTypeManager::add_government_type(std::string_view identifier, std::vector<Ideology const*> ideologies, bool elections, bool appoint_ruling_party, Timespan term_duration, std::string_view flag_type) { +bool GovernmentTypeManager::add_government_type(std::string_view identifier, std::vector<Ideology const*>&& ideologies, bool elections, bool appoint_ruling_party, Timespan term_duration, std::string_view flag_type) { if (identifier.empty()) { Logger::error("Invalid government type identifier - empty!"); return false; diff --git a/src/openvic-simulation/politics/Government.hpp b/src/openvic-simulation/politics/Government.hpp index ba8496f..8cdee48 100644 --- a/src/openvic-simulation/politics/Government.hpp +++ b/src/openvic-simulation/politics/Government.hpp @@ -34,7 +34,7 @@ namespace OpenVic { public: GovernmentTypeManager(); - bool add_government_type(std::string_view identifier, std::vector<Ideology const*> ideologies, bool elections, bool appoint_ruling_party, Timespan term_duration, std::string_view flag_type); + bool add_government_type(std::string_view identifier, std::vector<Ideology const*>&& ideologies, bool elections, bool appoint_ruling_party, Timespan term_duration, std::string_view flag_type); IDENTIFIER_REGISTRY_ACCESSORS(government_type) bool load_government_types_file(IdeologyManager const& ideology_manager, ast::NodeCPtr root); diff --git a/src/openvic-simulation/pop/Culture.cpp b/src/openvic-simulation/pop/Culture.cpp index e3ba5dd..bbfa35a 100644 --- a/src/openvic-simulation/pop/Culture.cpp +++ b/src/openvic-simulation/pop/Culture.cpp @@ -28,11 +28,11 @@ bool CultureGroup::get_is_overseas() const { } Culture::Culture(std::string_view new_identifier, colour_t new_colour, CultureGroup const& new_group, - std::vector<std::string> const& new_first_names, std::vector<std::string> const& new_last_names) + std::vector<std::string>&& new_first_names, std::vector<std::string>&& new_last_names) : HasIdentifierAndColour { new_identifier, new_colour, true, false }, group { new_group }, - first_names { new_first_names }, - last_names { new_last_names } {} + first_names { std::move(new_first_names) }, + last_names { std::move(new_last_names) } {} CultureGroup const& Culture::get_group() const { return group; @@ -79,7 +79,7 @@ bool CultureManager::add_culture_group(std::string_view identifier, std::string_ return culture_groups.add_item({ identifier, leader, *graphical_culture_type, is_overseas }); } -bool CultureManager::add_culture(std::string_view identifier, colour_t colour, CultureGroup const* group, std::vector<std::string> const& first_names, std::vector<std::string> const& last_names) { +bool CultureManager::add_culture(std::string_view identifier, colour_t colour, CultureGroup const* group, std::vector<std::string>&& first_names, std::vector<std::string>&& last_names) { if (!culture_groups.is_locked()) { Logger::error("Cannot register cultures until culture groups are locked!"); return false; @@ -96,7 +96,7 @@ bool CultureManager::add_culture(std::string_view identifier, colour_t colour, C Logger::error("Invalid culture colour for ", identifier, ": ", colour_to_hex_string(colour)); return false; } - return cultures.add_item({ identifier, colour, *group, first_names, last_names }); + return cultures.add_item({ identifier, colour, *group, std::move(first_names), std::move(last_names) }); } bool CultureManager::load_graphical_culture_type_file(ast::NodeCPtr root) { @@ -137,12 +137,12 @@ bool CultureManager::_load_culture(CultureGroup const* culture_group, bool ret = expect_dictionary_keys( "color", ONE_EXACTLY, expect_colour(assign_variable_callback(colour)), - "first_names", ONE_EXACTLY, name_list_callback(first_names), - "last_names", ONE_EXACTLY, name_list_callback(last_names), + "first_names", ONE_EXACTLY, name_list_callback(move_variable_callback(first_names)), + "last_names", ONE_EXACTLY, name_list_callback(move_variable_callback(last_names)), "radicalism", ZERO_OR_ONE, success_callback, "primary", ZERO_OR_ONE, success_callback )(culture_node); - ret &= add_culture(culture_key, colour, culture_group, first_names, last_names); + ret &= add_culture(culture_key, colour, culture_group, std::move(first_names), std::move(last_names)); return ret; } diff --git a/src/openvic-simulation/pop/Culture.hpp b/src/openvic-simulation/pop/Culture.hpp index d36a90b..688733e 100644 --- a/src/openvic-simulation/pop/Culture.hpp +++ b/src/openvic-simulation/pop/Culture.hpp @@ -45,7 +45,7 @@ namespace OpenVic { // TODO - radicalism, primary tag - Culture(std::string_view new_identifier, colour_t new_colour, CultureGroup const& new_group, std::vector<std::string> const& new_first_names, std::vector<std::string> const& new_last_names); + Culture(std::string_view new_identifier, colour_t new_colour, CultureGroup const& new_group, std::vector<std::string>&& new_first_names, std::vector<std::string>&& new_last_names); public: Culture(Culture&&) = default; @@ -74,7 +74,7 @@ namespace OpenVic { bool add_culture_group(std::string_view identifier, std::string_view leader, GraphicalCultureType const* new_graphical_culture_type, bool is_overseas); IDENTIFIER_REGISTRY_ACCESSORS(culture_group) - bool add_culture(std::string_view identifier, colour_t colour, CultureGroup const* group, std::vector<std::string> const& first_names, std::vector<std::string> const& last_names); + bool add_culture(std::string_view identifier, colour_t colour, CultureGroup const* group, std::vector<std::string>&& first_names, std::vector<std::string>&& last_names); IDENTIFIER_REGISTRY_ACCESSORS(culture) bool load_graphical_culture_type_file(ast::NodeCPtr root); diff --git a/src/openvic-simulation/types/IdentifierRegistry.cpp b/src/openvic-simulation/types/IdentifierRegistry.cpp index 8e93cb1..f92750b 100644 --- a/src/openvic-simulation/types/IdentifierRegistry.cpp +++ b/src/openvic-simulation/types/IdentifierRegistry.cpp @@ -35,11 +35,3 @@ HasIdentifierAndColour::HasIdentifierAndColour(std::string_view new_identifier, const colour_t new_colour, bool can_be_null, bool can_have_alpha) : HasIdentifier { new_identifier }, HasColour { new_colour, can_be_null, can_have_alpha } {} - -distribution_t::value_type OpenVic::get_largest_item(distribution_t const& dist) { - const distribution_t::const_iterator result = std::max_element(dist.begin(), dist.end(), - [](distribution_t::value_type a, distribution_t::value_type b) -> bool { - return a.second < b.second; - }); - return result != dist.end() ? *result : distribution_t::value_type { nullptr, -1.0f }; -} diff --git a/src/openvic-simulation/types/IdentifierRegistry.hpp b/src/openvic-simulation/types/IdentifierRegistry.hpp index 3ba7fc4..b2f52b2 100644 --- a/src/openvic-simulation/types/IdentifierRegistry.hpp +++ b/src/openvic-simulation/types/IdentifierRegistry.hpp @@ -68,9 +68,40 @@ namespace OpenVic { HasIdentifierAndColour& operator=(HasIdentifierAndColour&&) = delete; }; - using distribution_t = std::map<HasIdentifierAndColour const*, float>; + template<typename T> + using decimal_map_t = std::map<T, fixed_point_t>; + + template<typename T> + constexpr typename decimal_map_t<T>::value_type get_largest_item(decimal_map_t<T> const& map) { + constexpr auto pred = [](typename decimal_map_t<T>::value_type a, typename decimal_map_t<T>::value_type b) -> bool { + return a.second < b.second; + }; + const typename decimal_map_t<T>::const_iterator result = std::max_element( + map.begin(), map.end(), pred + ); + if (result != map.end()) { + return *result; + } else { + return { nullptr, -1 }; + } + } - distribution_t::value_type get_largest_item(distribution_t const& dist); + using distribution_t = decimal_map_t<HasIdentifierAndColour const*>; + + /* Callbacks for trying to add duplicate keys via UniqueKeyRegistry::add_item */ + static bool duplicate_fail_callback(std::string_view registry_name, std::string_view duplicate_identifier) { + Logger::error("Failure adding item to the ", registry_name, " registry - an item with the identifier \"", + duplicate_identifier, "\" already exists!"); + return false; + } + static bool duplicate_warning_callback(std::string_view registry_name, std::string_view duplicate_identifier) { + Logger::warning("Warning adding item to the ", registry_name, " registry - an item with the identifier \"", + duplicate_identifier, "\" already exists!"); + return true; + } + static bool duplicate_ignore_callback(std::string_view registry_name, std::string_view duplicate_identifier) { + return true; + } template<typename T> using get_identifier_func_t = std::string_view(T::*)(void) const; @@ -96,7 +127,7 @@ namespace OpenVic { return name; } - bool add_item(storage_type&& item, bool fail_on_duplicate = true) { + bool add_item(storage_type&& item, NodeTools::callback_t<std::string_view, std::string_view> duplicate_callback = duplicate_fail_callback) { if (locked) { Logger::error("Cannot add item to the ", name, " registry - locked!"); return false; @@ -105,15 +136,7 @@ namespace OpenVic { const std::string_view new_identifier = (new_item->*get_identifier)(); value_type const* old_item = get_item_by_identifier(new_identifier); if (old_item != nullptr) { -#define DUPLICATE_MESSAGE "Cannot add item to the ", name, " registry - an item with the identifier \"", new_identifier, "\" already exists!" - if (fail_on_duplicate) { - Logger::error(DUPLICATE_MESSAGE); - return false; - } else { - Logger::warning(DUPLICATE_MESSAGE); - return true; - } -#undef DUPLICATE_MESSAGE + return duplicate_callback(name, new_identifier); } identifier_index_map.emplace(new_identifier, items.size()); items.push_back(std::move(item)); @@ -234,9 +257,9 @@ namespace OpenVic { }); } - NodeTools::node_callback_t expect_item_decimal_map(NodeTools::callback_t<std::map<value_type const*, fixed_point_t>&&> callback) const { + NodeTools::node_callback_t expect_item_decimal_map(NodeTools::callback_t<decimal_map_t<value_type const*>&&> callback) const { return [this, callback](ast::NodeCPtr node) -> bool { - std::map<value_type const*, fixed_point_t> map; + decimal_map_t<value_type const*> map; bool ret = expect_item_dictionary([&map](value_type const& key, ast::NodeCPtr value) -> bool { fixed_point_t val; const bool ret = NodeTools::expect_fixed_point(NodeTools::assign_variable_callback(val))(value); @@ -296,7 +319,7 @@ namespace OpenVic { return plural.expect_item_identifier(callback); } \ NodeTools::node_callback_t expect_##singular##_dictionary(NodeTools::callback_t<decltype(plural)::value_type const&, ast::NodeCPtr> callback) const { \ return plural.expect_item_dictionary(callback); } \ - NodeTools::node_callback_t expect_##singular##_decimal_map(NodeTools::callback_t<std::map<decltype(plural)::value_type const*, fixed_point_t>&&> callback) const { \ + NodeTools::node_callback_t expect_##singular##_decimal_map(NodeTools::callback_t<decimal_map_t<decltype(plural)::value_type const*>&&> callback) const { \ return plural.expect_item_decimal_map(callback); } #define IDENTIFIER_REGISTRY_NON_CONST_ACCESSORS_CUSTOM_PLURAL(singular, plural) \ diff --git a/src/openvic-simulation/types/fixed_point/FixedPoint.hpp b/src/openvic-simulation/types/fixed_point/FixedPoint.hpp index 459d9c4..649d3f6 100644 --- a/src/openvic-simulation/types/fixed_point/FixedPoint.hpp +++ b/src/openvic-simulation/types/fixed_point/FixedPoint.hpp @@ -428,6 +428,28 @@ namespace OpenVic { return *this; } + constexpr fixed_point_t& operator++() { + value += ONE; + return *this; + } + + constexpr fixed_point_t operator++(int) { + const fixed_point_t old = *this; + value += ONE; + return old; + } + + constexpr fixed_point_t& operator--() { + value -= ONE; + return *this; + } + + constexpr fixed_point_t operator--(int) { + const fixed_point_t old = *this; + value -= ONE; + return old; + } + constexpr friend fixed_point_t operator*(fixed_point_t const& lhs, fixed_point_t const& rhs) { return lhs.value * rhs.value >> PRECISION; } diff --git a/src/openvic-simulation/utility/Logger.hpp b/src/openvic-simulation/utility/Logger.hpp index 55e0862..11cada5 100644 --- a/src/openvic-simulation/utility/Logger.hpp +++ b/src/openvic-simulation/utility/Logger.hpp @@ -63,21 +63,21 @@ namespace OpenVic { } }; -#define LOG_FUNC(name) \ - private: \ - static log_func_t name##_func; \ - static log_queue_t name##_queue; \ - public: \ - static void set_##name##_func(log_func_t log_func) { \ - name##_func = log_func; \ - } \ - template<typename... Ts> \ - struct name { \ - name(Ts&&... ts, source_location const& location = source_location::current()) { \ - log<Ts...>{ name##_func, name##_queue, std::forward<Ts>(ts)..., location }; \ - } \ - }; \ - template<typename... Ts> \ +#define LOG_FUNC(name) \ + private: \ + static log_func_t name##_func; \ + static log_queue_t name##_queue; \ + public: \ + static void set_##name##_func(log_func_t log_func) { \ + name##_func = log_func; \ + } \ + template<typename... Ts> \ + struct name { \ + name(Ts&&... ts, source_location const& location = source_location::current()) { \ + log<Ts...>{ name##_func, name##_queue, std::forward<Ts>(ts)..., location }; \ + } \ + }; \ + template<typename... Ts> \ name(Ts&&...) -> name<Ts...>; LOG_FUNC(info) |