aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.vscode/launch.json20
-rw-r--r--build_scons_and_execute_windows.bat4
-rw-r--r--delete_obj_files_windows.bat1
m---------deps/openvic-dataloader0
-rw-r--r--src/openvic-simulation/dataloader/Dataloader.cpp99
-rw-r--r--src/openvic-simulation/dataloader/Dataloader.hpp9
-rw-r--r--src/openvic-simulation/economy/Good.cpp32
-rw-r--r--src/openvic-simulation/economy/Good.hpp2
-rw-r--r--src/openvic-simulation/history/Bookmark.cpp10
-rw-r--r--src/openvic-simulation/history/Bookmark.hpp2
-rw-r--r--src/openvic-simulation/history/CountryHistory.cpp82
-rw-r--r--src/openvic-simulation/history/CountryHistory.hpp6
-rw-r--r--src/openvic-simulation/history/HistoryMap.cpp4
-rw-r--r--src/openvic-simulation/history/HistoryMap.hpp48
-rw-r--r--src/openvic-simulation/history/ProvinceHistory.cpp71
-rw-r--r--src/openvic-simulation/history/ProvinceHistory.hpp11
-rw-r--r--src/openvic-simulation/interface/UI.hpp2
-rw-r--r--src/openvic-simulation/map/Map.cpp86
-rw-r--r--src/openvic-simulation/map/Province.cpp35
-rw-r--r--src/openvic-simulation/map/Province.hpp13
-rw-r--r--src/openvic-simulation/military/Unit.cpp77
-rw-r--r--src/openvic-simulation/military/Unit.hpp2
-rw-r--r--src/openvic-simulation/misc/Decision.cpp4
-rw-r--r--src/openvic-simulation/misc/Modifier.cpp24
-rw-r--r--src/openvic-simulation/misc/Modifier.hpp2
-rw-r--r--src/openvic-simulation/politics/Government.cpp6
-rw-r--r--src/openvic-simulation/politics/Government.hpp2
-rw-r--r--src/openvic-simulation/politics/Rebel.cpp9
-rw-r--r--src/openvic-simulation/politics/Rebel.hpp2
-rw-r--r--src/openvic-simulation/pop/Pop.cpp105
-rw-r--r--src/openvic-simulation/pop/Pop.hpp42
-rw-r--r--src/openvic-simulation/research/Technology.cpp19
-rw-r--r--src/openvic-simulation/research/Technology.hpp2
-rw-r--r--src/openvic-simulation/types/fixed_point/FixedPoint.hpp4
34 files changed, 560 insertions, 277 deletions
diff --git a/.vscode/launch.json b/.vscode/launch.json
deleted file mode 100644
index da3dff4..0000000
--- a/.vscode/launch.json
+++ /dev/null
@@ -1,20 +0,0 @@
-{
- // Use IntelliSense to learn about possible attributes.
- // Hover to view descriptions of existing attributes.
- // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
- "version": "0.2.0",
- "configurations": [
- {
- "name": "(Windows) Launch",
- "type": "cppvsdbg",
- "request": "launch",
- "program": "${workspaceFolder}/bin/openvic-simulation.headless.windows.template_debug.dev.x86_64.exe",
- "args": [],
- "stopAtEntry": false,
- "cwd": "${fileDirname}",
- "environment": [],
- "console": "integratedTerminal"
- }
-
- ]
-} \ No newline at end of file
diff --git a/build_scons_and_execute_windows.bat b/build_scons_and_execute_windows.bat
deleted file mode 100644
index e48c2a2..0000000
--- a/build_scons_and_execute_windows.bat
+++ /dev/null
@@ -1,4 +0,0 @@
-scons
-cd bin
-openvic-simulation.headless.windows.template_debug.x86_64.exe
-cd ../ \ No newline at end of file
diff --git a/delete_obj_files_windows.bat b/delete_obj_files_windows.bat
deleted file mode 100644
index bf32282..0000000
--- a/delete_obj_files_windows.bat
+++ /dev/null
@@ -1 +0,0 @@
-del /S *.obj \ No newline at end of file
diff --git a/deps/openvic-dataloader b/deps/openvic-dataloader
-Subproject ce1f1e5fe32ed0856bd2b6df5136dad3f6bc991
+Subproject ebf9972d080e2120a9aa9bd15af8150dc2d5a3b
diff --git a/src/openvic-simulation/dataloader/Dataloader.cpp b/src/openvic-simulation/dataloader/Dataloader.cpp
index 8065367..97b5592 100644
--- a/src/openvic-simulation/dataloader/Dataloader.cpp
+++ b/src/openvic-simulation/dataloader/Dataloader.cpp
@@ -25,6 +25,15 @@ using StringUtils::append_string_views;
#define FILESYSTEM_NEEDS_FORWARD_SLASHES
#endif
+static fs::path ensure_forward_slash_path(std::string_view path) {
+#if defined(FILESYSTEM_NEEDS_FORWARD_SLASHES)
+ /* Back-slashes need to be converted into forward-slashes */
+ return StringUtils::make_forward_slash_path(StringUtils::remove_leading_slashes(path));
+#else
+ return path;
+#endif
+}
+
static constexpr bool path_equals_case_insensitive(std::string_view lhs, std::string_view rhs) {
constexpr auto ichar_equals = [](unsigned char l, unsigned char r) {
return std::tolower(l) == std::tolower(r);
@@ -60,13 +69,7 @@ bool Dataloader::set_roots(path_vector_t const& new_roots) {
}
fs::path Dataloader::lookup_file(std::string_view path, bool print_error) const {
-#if defined(FILESYSTEM_NEEDS_FORWARD_SLASHES)
- /* Back-slashes need to be converted into forward-slashes */
- const std::string forward_slash_path { StringUtils::make_forward_slash_path(StringUtils::remove_leading_slashes(path)) };
- path = forward_slash_path;
-#endif
-
- const fs::path filepath { path };
+ const fs::path filepath { ensure_forward_slash_path(path) };
#if defined(FILESYSTEM_CASE_INSENSITIVE)
/* Case-insensitive filesystem */
@@ -120,12 +123,7 @@ requires requires (_UniqueKey const& unique_key, std::string_view path) {
Dataloader::path_vector_t Dataloader::_lookup_files_in_dir(
std::string_view path, fs::path const& extension, _UniqueKey const& unique_key
) const {
-#if defined(FILESYSTEM_NEEDS_FORWARD_SLASHES)
- /* Back-slashes need to be converted into forward-slashes */
- const std::string forward_slash_path { StringUtils::make_forward_slash_path(StringUtils::remove_leading_slashes(path)) };
- path = forward_slash_path;
-#endif
- const fs::path dirpath { path };
+ const fs::path dirpath { ensure_forward_slash_path(path) };
path_vector_t ret;
struct file_entry_t {
fs::path file;
@@ -134,9 +132,8 @@ Dataloader::path_vector_t Dataloader::_lookup_files_in_dir(
string_map_t<file_entry_t> found_files;
for (fs::path const& root : roots) {
const size_t root_len = root.string().size();
- const fs::path composed = root / dirpath;
std::error_code ec;
- for (fs::directory_entry const& entry : _DirIterator { composed, ec }) {
+ for (fs::directory_entry const& entry : _DirIterator { root / dirpath, ec }) {
if (entry.is_regular_file()) {
fs::path file = entry;
if ((extension.empty() || file.extension() == extension)) {
@@ -199,6 +196,20 @@ bool Dataloader::apply_to_files(path_vector_t const& files, callback_t<fs::path
return ret;
}
+string_set_t Dataloader::lookup_dirs_in_dir(std::string_view path) const {
+ const fs::path dirpath { ensure_forward_slash_path(path) };
+ string_set_t ret;
+ for (fs::path const& root : roots) {
+ std::error_code ec;
+ for (fs::directory_entry const& entry : fs::directory_iterator { root / dirpath, ec }) {
+ if (entry.is_directory()) {
+ ret.emplace(entry.path().filename().string());
+ }
+ }
+ }
+ return ret;
+}
+
template<std::derived_from<detail::BasicParser> Parser, bool (*parse_func)(Parser&)>
static Parser _run_ovdl_parser(fs::path const& path) {
Parser parser;
@@ -292,19 +303,25 @@ bool Dataloader::_load_interface_files(UIManager& ui_manager) const {
return ret;
}
-bool Dataloader::_load_pop_types(
- PopManager& pop_manager, UnitManager const& unit_manager, GoodManager const& good_manager
-) const {
+bool Dataloader::_load_pop_types(GameManager& game_manager) const {
+ PopManager& pop_manager = game_manager.get_pop_manager();
+ UnitManager const& unit_manager = game_manager.get_military_manager().get_unit_manager();
+ GoodManager const& good_manager = game_manager.get_economy_manager().get_good_manager();
+
static constexpr std::string_view pop_type_directory = "poptypes";
- const bool ret = apply_to_files(
- lookup_files_in_dir(pop_type_directory, ".txt"),
+ const path_vector_t pop_type_files = lookup_files_in_dir(pop_type_directory, ".txt");
+ pop_manager.reserve_pop_types(pop_type_files.size());
+ bool ret = apply_to_files(
+ pop_type_files,
[&pop_manager, &unit_manager, &good_manager](fs::path const& file) -> bool {
return pop_manager.load_pop_type_file(
file.stem().string(), unit_manager, good_manager, parse_defines(file).get_file_node()
);
}
);
+ pop_manager.lock_stratas();
pop_manager.lock_pop_types();
+ ret &= pop_manager.generate_modifiers(game_manager.get_modifier_manager());
return ret;
}
@@ -498,6 +515,30 @@ bool Dataloader::_load_history(GameManager& game_manager, bool unused_history_fi
);
}
);
+
+ /* Pop History */
+ static constexpr std::string_view pop_history_directory = "history/pops/";
+ const string_set_t pop_history_dirs = lookup_dirs_in_dir(pop_history_directory);
+ const Date last_bookmark_date = game_manager.get_history_manager().get_bookmark_manager().get_last_bookmark_date();
+ for (std::string const& dir : pop_history_dirs) {
+ bool successful = false;
+ const Date date = Date::from_string(dir, &successful);
+ if (successful && date <= last_bookmark_date) {
+ bool non_integer_size = false;
+ ret &= apply_to_files(
+ lookup_files_in_dir(StringUtils::append_string_views(pop_history_directory, dir), ".txt"),
+ [this, &game_manager, date, &non_integer_size](fs::path const& file) -> bool {
+ return game_manager.get_history_manager().get_province_manager().load_pop_history_file(
+ game_manager, date, parse_defines(file).get_file_node(), &non_integer_size
+ );
+ }
+ );
+ if (non_integer_size) {
+ Logger::warning("Non-integer pop sizes in pop history files for ", date);
+ }
+ }
+ }
+
game_manager.get_history_manager().get_province_manager().lock_province_histories(game_manager.get_map(), false);
static constexpr std::string_view diplomacy_history_directory = "history/diplomacy";
@@ -692,10 +733,7 @@ bool Dataloader::load_defines(GameManager& game_manager) const {
Logger::error("Failed to load units!");
ret = false;
}
- if (!_load_pop_types(
- game_manager.get_pop_manager(), game_manager.get_military_manager().get_unit_manager(),
- game_manager.get_economy_manager().get_good_manager()
- )) {
+ if (!_load_pop_types(game_manager)) {
Logger::error("Failed to load pop types!");
ret = false;
}
@@ -844,19 +882,6 @@ bool Dataloader::load_defines(GameManager& game_manager) const {
return ret;
}
-bool Dataloader::load_pop_history(GameManager& game_manager, std::string_view path) const {
- return apply_to_files(
- lookup_files_in_dir(path, ".txt"),
- [&game_manager](fs::path const& file) -> bool {
- return game_manager.get_map().expect_province_dictionary(
- [&game_manager](Province& province, ast::NodeCPtr value) -> bool {
- return province.load_pop_list(game_manager.get_pop_manager(), value);
- }
- )(parse_defines(file).get_file_node());
- }
- );
-}
-
static bool _load_localisation_file(Dataloader::localisation_callback_t callback, std::vector<csv::LineObject> const& lines) {
bool ret = true;
for (csv::LineObject const& line : lines) {
diff --git a/src/openvic-simulation/dataloader/Dataloader.hpp b/src/openvic-simulation/dataloader/Dataloader.hpp
index 78021b3..107c93a 100644
--- a/src/openvic-simulation/dataloader/Dataloader.hpp
+++ b/src/openvic-simulation/dataloader/Dataloader.hpp
@@ -11,10 +11,6 @@ namespace OpenVic {
struct GameManager;
class UIManager;
- struct PopManager;
- struct UnitManager;
- struct GoodManager;
- struct EventManager;
class Dataloader {
public:
@@ -24,7 +20,7 @@ namespace OpenVic {
path_vector_t roots;
bool _load_interface_files(UIManager& ui_manager) const;
- bool _load_pop_types(PopManager& pop_manager, UnitManager const& unit_manager, GoodManager const& good_manager) const;
+ bool _load_pop_types(GameManager& game_manager) const;
bool _load_units(GameManager& game_manager) const;
bool _load_goods(GameManager& game_manager) const;
bool _load_rebel_types(GameManager& game_manager) const;
@@ -94,8 +90,9 @@ namespace OpenVic {
) const;
bool apply_to_files(path_vector_t const& files, NodeTools::callback_t<fs::path const&> callback) const;
+ string_set_t lookup_dirs_in_dir(std::string_view path) const;
+
bool load_defines(GameManager& game_manager) const;
- bool load_pop_history(GameManager& game_manager, std::string_view path) const;
enum locale_t : size_t {
English, French, German, Polish, Spanish, Italian, Swedish,
diff --git a/src/openvic-simulation/economy/Good.cpp b/src/openvic-simulation/economy/Good.cpp
index 5500483..44b896b 100644
--- a/src/openvic-simulation/economy/Good.cpp
+++ b/src/openvic-simulation/economy/Good.cpp
@@ -94,22 +94,22 @@ bool GoodManager::load_goods_file(ast::NodeCPtr root) {
return ret;
}
-#define GOOD_MODIFIER(name) \
- modifier_manager.register_complex_modifier(name); \
- for (Good const& good : this->get_goods()) { \
- ret &= modifier_manager.add_modifier_effect( \
- StringUtils::append_string_views(name, "_", good.get_identifier()), \
- true \
- ); \
- }
-
-bool GoodManager::generate_modifiers(ModifierManager& modifier_manager) {
+bool GoodManager::generate_modifiers(ModifierManager& modifier_manager) const {
bool ret = true;
- GOOD_MODIFIER("factory_goods_output");
- GOOD_MODIFIER("factory_goods_throughput");
- GOOD_MODIFIER("rgo_goods_output");
- GOOD_MODIFIER("rgo_size");
+
+ const auto good_modifier = [this, &modifier_manager, &ret](std::string_view name) -> void {
+ ret &= modifier_manager.register_complex_modifier(name);
+ for (Good const& good : get_goods()) {
+ ret &= modifier_manager.add_modifier_effect(
+ StringUtils::append_string_views(name, "_", good.get_identifier()), true
+ );
+ }
+ };
+
+ good_modifier("factory_goods_output");
+ good_modifier("factory_goods_throughput");
+ good_modifier("rgo_goods_output");
+ good_modifier("rgo_size");
+
return ret;
}
-
-#undef GOOD_MODIFIER \ No newline at end of file
diff --git a/src/openvic-simulation/economy/Good.hpp b/src/openvic-simulation/economy/Good.hpp
index c595768..d9d4251 100644
--- a/src/openvic-simulation/economy/Good.hpp
+++ b/src/openvic-simulation/economy/Good.hpp
@@ -76,6 +76,6 @@ namespace OpenVic {
void reset_to_defaults();
bool load_goods_file(ast::NodeCPtr root);
- bool generate_modifiers(ModifierManager& modifier_manager);
+ bool generate_modifiers(ModifierManager& modifier_manager) const;
};
}
diff --git a/src/openvic-simulation/history/Bookmark.cpp b/src/openvic-simulation/history/Bookmark.cpp
index 2927950..b758867 100644
--- a/src/openvic-simulation/history/Bookmark.cpp
+++ b/src/openvic-simulation/history/Bookmark.cpp
@@ -48,3 +48,13 @@ bool BookmarkManager::load_bookmark_file(ast::NodeCPtr root) {
return ret;
}
+
+Date BookmarkManager::get_last_bookmark_date() const {
+ Date ret {};
+ for (Bookmark const& bookmark : get_bookmarks()) {
+ if (bookmark.get_date() > ret) {
+ ret = bookmark.get_date();
+ }
+ }
+ return ret;
+}
diff --git a/src/openvic-simulation/history/Bookmark.hpp b/src/openvic-simulation/history/Bookmark.hpp
index 7401105..6f30586 100644
--- a/src/openvic-simulation/history/Bookmark.hpp
+++ b/src/openvic-simulation/history/Bookmark.hpp
@@ -38,5 +38,7 @@ namespace OpenVic {
uint32_t initial_camera_y
);
bool load_bookmark_file(ast::NodeCPtr root);
+
+ Date get_last_bookmark_date() const;
};
}
diff --git a/src/openvic-simulation/history/CountryHistory.cpp b/src/openvic-simulation/history/CountryHistory.cpp
index 9ee7d65..00c88b8 100644
--- a/src/openvic-simulation/history/CountryHistory.cpp
+++ b/src/openvic-simulation/history/CountryHistory.cpp
@@ -25,9 +25,10 @@ bool CountryHistoryMap::_load_history_entry(
CountryManager const& country_manager = game_manager.get_country_manager();
TechnologyManager const& technology_manager = game_manager.get_research_manager().get_technology_manager();
InventionManager const& invention_manager = game_manager.get_research_manager().get_invention_manager();
+ DecisionManager const& decision_manager = game_manager.get_decision_manager();
return expect_dictionary_keys_and_default(
- [this, &game_manager, &dataloader, &deployment_manager, &issue_manager,
+ [this, &game_manager, &dataloader, &deployment_manager, &issue_manager,
&technology_manager, &invention_manager, &country_manager, &entry](std::string_view key, ast::NodeCPtr value) -> bool {
ReformGroup const* reform_group = issue_manager.get_reform_group_by_identifier(key);
if (reform_group != nullptr) {
@@ -66,14 +67,11 @@ bool CountryHistoryMap::_load_history_entry(
return entry.inventions.emplace(invention, flag).second;
} else return false;
}
-
+
return _load_history_sub_entry_callback(
game_manager, dataloader, deployment_manager, entry.get_date(), value, key, value
);
},
- /* we have to use a lambda, assign_variable_callback_pointer
- * apparently doesn't play nice with const & non-const accessors */
- // TODO - fix this issue (cause by provinces having non-const accessors)
"capital", ZERO_OR_ONE,
game_manager.get_map().expect_province_identifier(assign_variable_callback_pointer(entry.capital)),
"primary_culture", ZERO_OR_ONE,
@@ -122,24 +120,74 @@ bool CountryHistoryMap::_load_history_entry(
"consciousness", ZERO_OR_ONE, expect_fixed_point(assign_variable_callback(entry.consciousness)),
"nonstate_consciousness", ZERO_OR_ONE, expect_fixed_point(assign_variable_callback(entry.nonstate_consciousness)),
"is_releasable_vassal", ZERO_OR_ONE, expect_bool(assign_variable_callback(entry.releasable_vassal)),
- "decision", ZERO_OR_ONE, success_callback, //TODO: decisions
+ "decision", ZERO_OR_MORE, decision_manager.expect_decision_identifier(set_callback_pointer(entry.decisions)),
"govt_flag", ZERO_OR_ONE, [&entry, &politics_manager](ast::NodeCPtr value) -> bool {
+ GovernmentTypeManager const& government_type_manager = politics_manager.get_government_type_manager();
GovernmentType const* government_type = nullptr;
- std::string_view flag;
- bool ret = expect_dictionary_keys(
- "government", ONE_EXACTLY, politics_manager.get_government_type_manager()
- .expect_government_type_identifier(assign_variable_callback_pointer(government_type)),
- "flag", ONE_EXACTLY, expect_identifier_or_string(assign_variable_callback(flag))
+ bool flag_expected = false;
+ bool ret = expect_dictionary(
+ [&entry, &government_type_manager, &government_type, &flag_expected](std::string_view id,
+ ast::NodeCPtr node) -> bool {
+ if (id == "government") {
+ bool ret = true;
+ if (flag_expected) {
+ Logger::error(
+ "Government key found when expect flag type override for ", government_type,
+ " in history of ", entry.get_country().get_identifier()
+ );
+ ret = false;
+ }
+ flag_expected = true;
+ government_type = nullptr;
+ ret &= government_type_manager.expect_government_type_identifier(
+ assign_variable_callback_pointer(government_type)
+ )(node);
+ return ret;
+ } else if (id == "flag") {
+ if (flag_expected) {
+ flag_expected = false;
+ GovernmentType const* flag_override_government_type = nullptr;
+ bool ret = government_type_manager.expect_government_type_identifier(
+ assign_variable_callback_pointer(flag_override_government_type)
+ )(node);
+ /* If the first government type is null, the "government" section will have already output
+ * an error, so no need to output another one here. */
+ if (government_type != nullptr && flag_override_government_type != nullptr) {
+ ret &= entry.government_flag_overrides.emplace(
+ government_type, flag_override_government_type
+ ).second;
+ }
+ return ret;
+ } else {
+ Logger::error(
+ "Flag key found when expecting government type for flag type override in history of ",
+ entry.get_country().get_identifier()
+ );
+ return false;
+ }
+ } else {
+ Logger::error(
+ "Invalid key ", id, " in government flag overrides in history of ",
+ entry.get_country().get_identifier()
+ );
+ return false;
+ }
+ }
)(value);
- if (government_type != nullptr) {
- return ret & entry.government_flags.emplace(government_type, flag).second;
- } else return false;
+ if (flag_expected) {
+ Logger::error(
+ "Missing flag type override for government type ", government_type, " in history of ",
+ entry.get_country().get_identifier()
+ );
+ ret = false;
+ }
+ return ret;
},
- "colonial_points", ZERO_OR_ONE, expect_fixed_point(assign_variable_callback(entry.colonial_points)),
- "set_country_flag", ZERO_OR_ONE, expect_identifier_or_string([&entry](std::string_view flag) -> bool {
+ "colonial_points", ZERO_OR_ONE, expect_fixed_point(assign_variable_callback(entry.colonial_points)),
+ "set_country_flag", ZERO_OR_MORE, expect_identifier_or_string([&entry](std::string_view flag) -> bool {
return entry.country_flags.emplace(flag).second;
}),
- "set_global_flag", ZERO_OR_ONE, expect_identifier_or_string([&entry](std::string_view flag) -> bool {
+ "set_global_flag", ZERO_OR_MORE, expect_identifier_or_string([&entry](std::string_view flag) -> bool {
return entry.global_flags.emplace(flag).second;
})
)(root);
diff --git a/src/openvic-simulation/history/CountryHistory.hpp b/src/openvic-simulation/history/CountryHistory.hpp
index af7d502..106b1c3 100644
--- a/src/openvic-simulation/history/CountryHistory.hpp
+++ b/src/openvic-simulation/history/CountryHistory.hpp
@@ -3,6 +3,7 @@
#include <map>
#include <optional>
+#include "openvic-simulation/misc/Decision.hpp"
#include "openvic-simulation/country/Country.hpp"
#include "openvic-simulation/history/Bookmark.hpp"
#include "openvic-simulation/history/HistoryMap.hpp"
@@ -54,9 +55,8 @@ namespace OpenVic {
std::optional<fixed_point_t> PROPERTY(colonial_points);
string_set_t PROPERTY(country_flags);
string_set_t PROPERTY(global_flags);
- std::map<GovernmentType const*, std::string> PROPERTY(government_flags);
-
- //TODO: decisions
+ std::map<GovernmentType const*, GovernmentType const*> PROPERTY(government_flag_overrides);
+ std::set<Decision const*> decisions;
CountryHistoryEntry(Country const& new_country, Date new_date);
};
diff --git a/src/openvic-simulation/history/HistoryMap.cpp b/src/openvic-simulation/history/HistoryMap.cpp
index b669208..7b5353f 100644
--- a/src/openvic-simulation/history/HistoryMap.cpp
+++ b/src/openvic-simulation/history/HistoryMap.cpp
@@ -6,10 +6,10 @@ using namespace OpenVic;
HistoryEntry::HistoryEntry(Date new_date) : date { new_date } {}
-Date OpenVic::_get_start_date(GameManager const& game_manager) {
+Date _HistoryMapHelperFuncs::_get_start_date(GameManager const& game_manager) {
return game_manager.get_define_manager().get_start_date();
}
-Date OpenVic::_get_end_date(GameManager const& game_manager) {
+Date _HistoryMapHelperFuncs::_get_end_date(GameManager const& game_manager) {
return game_manager.get_define_manager().get_end_date();
}
diff --git a/src/openvic-simulation/history/HistoryMap.hpp b/src/openvic-simulation/history/HistoryMap.hpp
index 07f54f0..576f00e 100644
--- a/src/openvic-simulation/history/HistoryMap.hpp
+++ b/src/openvic-simulation/history/HistoryMap.hpp
@@ -18,9 +18,11 @@ namespace OpenVic {
struct GameManager;
- /* Helper functions to avoid cyclic dependency issues */
- Date _get_start_date(GameManager const& game_manager);
- Date _get_end_date(GameManager const& game_manager);
+ namespace _HistoryMapHelperFuncs {
+ /* Helper functions to avoid cyclic dependency issues */
+ Date _get_start_date(GameManager const& game_manager);
+ Date _get_end_date(GameManager const& game_manager);
+ }
template<std::derived_from<HistoryEntry> _Entry, typename... Args>
struct HistoryMap {
@@ -30,22 +32,12 @@ namespace OpenVic {
std::map<Date, std::unique_ptr<entry_type>> PROPERTY(entries);
bool _try_load_history_entry(GameManager const& game_manager, Args... args, Date date, ast::NodeCPtr root) {
- const Date end_date = _get_end_date(game_manager);
- if (date > end_date) {
- Logger::error("History entry ", date, " defined after end date ", end_date);
+ entry_type *const entry = _get_or_make_entry(game_manager, date);
+ if (entry != nullptr) {
+ return _load_history_entry(game_manager, args..., *entry, root);
+ } else {
return false;
}
- typename decltype(entries)::iterator it = entries.find(date);
- if (it == entries.end()) {
- const std::pair<typename decltype(entries)::iterator, bool> result = entries.emplace(date, _make_entry(date));
- if (result.second) {
- it = result.first;
- } else {
- Logger::error("Failed to create history entry at date ", date);
- return false;
- }
- }
- return _load_history_entry(game_manager, args..., *it->second, root);
}
protected:
@@ -58,7 +50,7 @@ namespace OpenVic {
) = 0;
bool _load_history_file(GameManager const& game_manager, Args... args, ast::NodeCPtr root) {
- return _try_load_history_entry(game_manager, args..., _get_start_date(game_manager), root);
+ return _try_load_history_entry(game_manager, args..., _HistoryMapHelperFuncs::_get_start_date(game_manager), root);
}
bool _load_history_sub_entry_callback(
@@ -87,6 +79,26 @@ namespace OpenVic {
return default_callback(key, value);
}
+ /* Returns history entry at specific date, if date doesn't have an entry creates one, if that fails returns nullptr. */
+ entry_type* _get_or_make_entry(GameManager const& game_manager, Date date) {
+ const Date end_date = _HistoryMapHelperFuncs::_get_end_date(game_manager);
+ if (date > end_date) {
+ Logger::error("History entry ", date, " defined after end date ", end_date);
+ return nullptr;
+ }
+ typename decltype(entries)::iterator it = entries.find(date);
+ if (it == entries.end()) {
+ const std::pair<typename decltype(entries)::iterator, bool> result = entries.emplace(date, _make_entry(date));
+ if (result.second) {
+ it = result.first;
+ } else {
+ Logger::error("Failed to create history entry at date ", date);
+ return nullptr;
+ }
+ }
+ return it->second.get();
+ }
+
public:
/* Returns history entry at specific date, if date doesn't have an entry returns nullptr. */
entry_type const* get_entry(Date date) const {
diff --git a/src/openvic-simulation/history/ProvinceHistory.cpp b/src/openvic-simulation/history/ProvinceHistory.cpp
index d9d3ef6..4e92300 100644
--- a/src/openvic-simulation/history/ProvinceHistory.cpp
+++ b/src/openvic-simulation/history/ProvinceHistory.cpp
@@ -135,6 +135,21 @@ ProvinceHistoryMap const* ProvinceHistoryManager::get_province_history(Province
}
}
+ProvinceHistoryMap* ProvinceHistoryManager::_get_or_make_province_history(Province const& province) {
+ decltype(province_histories)::iterator it = province_histories.find(&province);
+ if (it == province_histories.end()) {
+ const std::pair<decltype(province_histories)::iterator, bool> result =
+ province_histories.emplace(&province, ProvinceHistoryMap { province });
+ if (result.second) {
+ it = result.first;
+ } else {
+ Logger::error("Failed to create province history map for province ", province.get_identifier());
+ return nullptr;
+ }
+ }
+ return &it->second;
+}
+
bool ProvinceHistoryManager::load_province_history_file(
GameManager const& game_manager, Province const& province, ast::NodeCPtr root
) {
@@ -146,18 +161,52 @@ bool ProvinceHistoryManager::load_province_history_file(
return false;
}
- decltype(province_histories)::iterator it = province_histories.find(&province);
- if (it == province_histories.end()) {
- const std::pair<decltype(province_histories)::iterator, bool> result =
- province_histories.emplace(&province, ProvinceHistoryMap { province });
- if (result.second) {
- it = result.first;
- } else {
- Logger::error("Failed to create province history map for province ", province.get_identifier());
- return false;
+ ProvinceHistoryMap* province_history = _get_or_make_province_history(province);
+ if (province_history != nullptr) {
+ return province_history->_load_history_file(game_manager, root);
+ } else {
+ return false;
+ }
+}
+
+bool ProvinceHistoryEntry::_load_province_pop_history(
+ GameManager const& game_manager, ast::NodeCPtr root, bool *non_integer_size
+) {
+ PopManager const& pop_manager = game_manager.get_pop_manager();
+ RebelManager const& rebel_manager = game_manager.get_politics_manager().get_rebel_manager();
+ return pop_manager.expect_pop_type_dictionary(
+ [this, &pop_manager, &rebel_manager, non_integer_size](PopType const& pop_type, ast::NodeCPtr pop_node) -> bool {
+ return pop_manager.load_pop_into_vector(rebel_manager, pops, pop_type, pop_node, non_integer_size);
}
+ )(root);
+}
+
+bool ProvinceHistoryMap::_load_province_pop_history(
+ GameManager const& game_manager, Date date, ast::NodeCPtr root, bool *non_integer_size
+) {
+ ProvinceHistoryEntry* entry = _get_or_make_entry(game_manager, date);
+ if (entry != nullptr) {
+ return entry->_load_province_pop_history(game_manager, root, non_integer_size);
+ } else {
+ return false;
}
- ProvinceHistoryMap& province_history = it->second;
+}
- return province_history._load_history_file(game_manager, root);
+bool ProvinceHistoryManager::load_pop_history_file(
+ GameManager const& game_manager, Date date, ast::NodeCPtr root, bool *non_integer_size
+) {
+ if (locked) {
+ Logger::error("Attempted to load pop history file after province history registry was locked!");
+ return false;
+ }
+ return game_manager.get_map().expect_province_dictionary(
+ [this, &game_manager, date, non_integer_size](Province const& province, ast::NodeCPtr node) -> bool {
+ ProvinceHistoryMap* province_history = _get_or_make_province_history(province);
+ if (province_history != nullptr) {
+ return province_history->_load_province_pop_history(game_manager, date, node, non_integer_size);
+ } else {
+ return false;
+ }
+ }
+ )(root);
}
diff --git a/src/openvic-simulation/history/ProvinceHistory.hpp b/src/openvic-simulation/history/ProvinceHistory.hpp
index e4adc08..c3c8e67 100644
--- a/src/openvic-simulation/history/ProvinceHistory.hpp
+++ b/src/openvic-simulation/history/ProvinceHistory.hpp
@@ -33,8 +33,11 @@ namespace OpenVic {
std::map<BuildingType const*, BuildingType::level_t> PROPERTY(province_buildings);
std::map<BuildingType const*, BuildingType::level_t> PROPERTY(state_buildings);
fixed_point_map_t<Ideology const*> PROPERTY(party_loyalties);
+ std::vector<Pop> PROPERTY(pops);
ProvinceHistoryEntry(Province const& new_province, Date new_date);
+
+ bool _load_province_pop_history(GameManager const& game_manager, ast::NodeCPtr root, bool *non_integer_size);
};
struct ProvinceHistoryManager;
@@ -50,6 +53,11 @@ namespace OpenVic {
std::unique_ptr<ProvinceHistoryEntry> _make_entry(Date date) const override;
bool _load_history_entry(GameManager const& game_manager, ProvinceHistoryEntry& entry, ast::NodeCPtr root) override;
+
+ private:
+ bool _load_province_pop_history(
+ GameManager const& game_manager, Date date, ast::NodeCPtr root, bool *non_integer_size
+ );
};
struct ProvinceHistoryManager {
@@ -57,6 +65,8 @@ namespace OpenVic {
std::map<Province const*, ProvinceHistoryMap> PROPERTY(province_histories);
bool locked = false;
+ ProvinceHistoryMap* _get_or_make_province_history(Province const& province);
+
public:
ProvinceHistoryManager() = default;
@@ -66,5 +76,6 @@ namespace OpenVic {
ProvinceHistoryMap const* get_province_history(Province const* province) const;
bool load_province_history_file(GameManager const& game_manager, Province const& province, ast::NodeCPtr root);
+ bool load_pop_history_file(GameManager const& game_manager, Date date, ast::NodeCPtr root, bool *non_integer_size);
};
} // namespace OpenVic
diff --git a/src/openvic-simulation/interface/UI.hpp b/src/openvic-simulation/interface/UI.hpp
index 12eadb5..ce9336c 100644
--- a/src/openvic-simulation/interface/UI.hpp
+++ b/src/openvic-simulation/interface/UI.hpp
@@ -4,7 +4,7 @@
namespace OpenVic {
- class UIManager {
+ class UIManager {
NamedInstanceRegistry<GFX::Sprite> IDENTIFIER_REGISTRY(sprite);
NamedInstanceRegistry<GUI::Scene, UIManager const&> IDENTIFIER_REGISTRY(scene);
IdentifierRegistry<GFX::Font> IDENTIFIER_REGISTRY(font);
diff --git a/src/openvic-simulation/map/Map.cpp b/src/openvic-simulation/map/Map.cpp
index 18f72cf..1e68cc6 100644
--- a/src/openvic-simulation/map/Map.cpp
+++ b/src/openvic-simulation/map/Map.cpp
@@ -294,8 +294,15 @@ bool Map::apply_history_to_provinces(ProvinceHistoryManager const& history_manag
if (!province.get_water()) {
ProvinceHistoryMap const* history_map = history_manager.get_province_history(&province);
if (history_map != nullptr) {
+ ProvinceHistoryEntry const* pop_history_entry = nullptr;
for (ProvinceHistoryEntry const* entry : history_map->get_entries_up_to(date)) {
province.apply_history_to_province(entry);
+ if (!entry->get_pops().empty()) {
+ pop_history_entry = entry;
+ }
+ }
+ if (pop_history_entry != nullptr) {
+ province.add_pop_vec(pop_history_entry->get_pops());
}
}
}
@@ -493,34 +500,41 @@ bool Map::load_map_images(fs::path const& province_path, fs::path const& terrain
std::vector<fixed_point_map_t<TerrainType const*>> terrain_type_pixels_list(provinces.size());
bool ret = true;
std::unordered_set<colour_t> unrecognised_province_colours;
+
+ std::vector<fixed_point_t> pixels_per_province(provinces.size());
+ std::vector<fixed_point_t> x_sum_per_province(provinces.size());
+ std::vector<fixed_point_t> y_sum_per_province(provinces.size());
for (size_t y = 0; y < height; ++y) {
for (size_t x = 0; x < width; ++x) {
- const size_t idx = x + y * width;
+ const size_t pixel_index = x + y * width;
+ const colour_t province_colour = colour_at(province_data, pixel_index);
- const colour_t province_colour = colour_at(province_data, idx);
if (x > 0) {
- const size_t jdx = idx - 1;
+ const size_t jdx = pixel_index - 1;
if (colour_at(province_data, jdx) == province_colour) {
- province_shape_image[idx].index = province_shape_image[jdx].index;
+ province_shape_image[pixel_index].index = province_shape_image[jdx].index;
goto set_terrain;
}
}
+
if (y > 0) {
- const size_t jdx = idx - width;
+ const size_t jdx = pixel_index - width;
if (colour_at(province_data, jdx) == province_colour) {
- province_shape_image[idx].index = province_shape_image[jdx].index;
+ province_shape_image[pixel_index].index = province_shape_image[jdx].index;
goto set_terrain;
}
}
+
{
- const Province::index_t index = get_index_from_colour(province_colour);
- if (index != Province::NULL_INDEX) {
- province_checklist[index - 1] = true;
- province_shape_image[idx].index = index;
+ const Province::index_t province_index = get_index_from_colour(province_colour);
+ if (province_index != Province::NULL_INDEX) {
+ province_checklist[province_index - 1] = true;
+ province_shape_image[pixel_index].index = province_index;
goto set_terrain;
}
}
+
if (!unrecognised_province_colours.contains(province_colour)) {
unrecognised_province_colours.insert(province_colour);
if (detailed_errors) {
@@ -529,20 +543,30 @@ bool Map::load_map_images(fs::path const& province_path, fs::path const& terrain
);
}
}
- province_shape_image[idx].index = Province::NULL_INDEX;
+
+ province_shape_image[pixel_index].index = Province::NULL_INDEX;
set_terrain:
- const TerrainTypeMapping::index_t terrain = terrain_data[idx];
+ const Province::index_t province_index = province_shape_image[pixel_index].index;
+ if (province_index != Province::NULL_INDEX) {
+ const uint16_t array_index = province_index - 1;
+ pixels_per_province[array_index]++;
+ x_sum_per_province[array_index] += x;
+ y_sum_per_province[array_index] += y;
+ }
+
+ 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_shape_image[idx].index != Province::NULL_INDEX) {
- terrain_type_pixels_list[province_shape_image[idx].index - 1][&mapping->get_type()]++;
+
+ if (province_index != Province::NULL_INDEX) {
+ terrain_type_pixels_list[province_index - 1][&mapping->get_type()]++;
}
- province_shape_image[idx].terrain =
+ province_shape_image[pixel_index].terrain =
mapping->get_has_texture() && terrain < terrain_type_manager.get_terrain_texture_limit() ? terrain + 1 : 0;
} else {
- province_shape_image[idx].terrain = 0;
+ province_shape_image[pixel_index].terrain = 0;
}
}
}
@@ -552,11 +576,22 @@ bool Map::load_map_images(fs::path const& province_path, fs::path const& terrain
}
size_t missing = 0;
- for (size_t idx = 0; idx < province_checklist.size(); ++idx) {
- Province* province = provinces.get_item_by_index(idx);
- const fixed_point_map_const_iterator_t<TerrainType const*> largest = get_largest_item(terrain_type_pixels_list[idx]);
- province->default_terrain_type = largest != terrain_type_pixels_list[idx].end() ? largest->first : nullptr;
- province->on_map = province_checklist[idx];
+ for (size_t array_index = 0; array_index < province_checklist.size(); ++array_index) {
+ Province* province = provinces.get_item_by_index(array_index);
+ const fixed_point_t pixel_count = pixels_per_province[array_index];
+ if(pixel_count > 0) {
+ const fixed_point_t x = x_sum_per_province[array_index] / pixel_count;
+ const fixed_point_t y = y_sum_per_province[array_index] / pixel_count;
+ const fvec2_t center { x, y };
+ province->positions.center = center;
+ }
+ else {
+ Logger::warning("Province ",province->index," has no pixels");
+ }
+
+ const fixed_point_map_const_iterator_t<TerrainType const*> largest = get_largest_item(terrain_type_pixels_list[array_index]);
+ province->default_terrain_type = largest != terrain_type_pixels_list[array_index].end() ? largest->first : nullptr;
+ province->on_map = province_checklist[array_index];
if (!province->on_map) {
if (detailed_errors) {
Logger::warning("Province missing from shape image: ", province->to_string());
@@ -577,10 +612,12 @@ bool Map::load_map_images(fs::path const& province_path, fs::path const& terrain
bool Map::_generate_province_adjacencies() {
bool changed = false;
- auto generate_adjacency = [&](Province* cur, size_t x, size_t y) -> bool {
+ auto generate_adjacency = [&](Province* current, size_t x, size_t y) -> bool {
Province* neighbour = get_province_by_index(province_shape_image[x + y * width].index);
- if (neighbour != nullptr && cur != neighbour) {
- return cur->add_adjacency(neighbour, 0, 0) | neighbour->add_adjacency(cur, 0, 0);
+ if (neighbour != nullptr && current != neighbour) {
+ const Province::distance_t distance = current->calculate_distance_to(neighbour);
+ const Province::flags_t flags = 0;
+ return current->add_adjacency(neighbour, distance, flags) | neighbour->add_adjacency(current, distance, flags);
}
return false;
};
@@ -588,6 +625,7 @@ bool Map::_generate_province_adjacencies() {
for (size_t y = 0; y < height; ++y) {
for (size_t x = 0; x < width; ++x) {
Province* cur = get_province_by_index(province_shape_image[x + y * width].index);
+
if (cur != nullptr) {
changed |= generate_adjacency(cur, (x + 1) % width, y);
if (y + 1 < height) {
diff --git a/src/openvic-simulation/map/Province.cpp b/src/openvic-simulation/map/Province.cpp
index 363be6c..717ef35 100644
--- a/src/openvic-simulation/map/Province.cpp
+++ b/src/openvic-simulation/map/Province.cpp
@@ -58,14 +58,6 @@ bool Province::expand_building(std::string_view building_type_identifier) {
return building->expand();
}
-bool Province::load_pop_list(PopManager const& pop_manager, ast::NodeCPtr root) {
- return expect_dictionary_reserve_length(pops,
- [this, &pop_manager](std::string_view pop_type_identifier, ast::NodeCPtr pop_node) -> bool {
- return pop_manager.load_pop_into_province(*this, pop_type_identifier, pop_node);
- }
- )(root);
-}
-
bool Province::add_pop(Pop&& pop) {
if (!get_water()) {
pops.push_back(std::move(pop));
@@ -76,6 +68,19 @@ bool Province::add_pop(Pop&& pop) {
}
}
+bool Province::add_pop_vec(std::vector<Pop> const& pop_vec) {
+ if (!get_water()) {
+ pops.reserve(pops.size() + pop_vec.size());
+ for (Pop const& pop : pop_vec) {
+ pops.push_back(pop);
+ }
+ return true;
+ } else {
+ Logger::error("Trying to add pop vector to water province ", get_identifier());
+ return false;
+ }
+}
+
size_t Province::get_pop_count() const {
return pops.size();
}
@@ -116,7 +121,7 @@ Province::adjacency_t::adjacency_t(Province const* province, distance_t distance
assert(province != nullptr);
}
-bool Province::is_adjacent_to(Province const* province) {
+bool Province::is_adjacent_to(Province const* province) const {
for (adjacency_t adj : adjacencies) {
if (adj.province == province) {
return true;
@@ -137,6 +142,18 @@ bool Province::add_adjacency(Province const* province, distance_t distance, flag
return true;
}
+fvec2_t Province::get_unit_position() const {
+ return positions.unit.value_or(positions.center);
+}
+
+Province::distance_t Province::calculate_distance_to(Province const* province) const {
+ const fvec2_t my_unit_position = get_unit_position();
+ const fvec2_t other_unit_position = province->get_unit_position();
+ const fvec2_t distance_vector = other_unit_position - my_unit_position;
+ const fixed_point_t distance = distance_vector.length_squared();
+ return static_cast<Province::distance_t>(distance);
+}
+
bool Province::reset(BuildingTypeManager const& building_type_manager) {
terrain_type = default_terrain_type;
life_rating = 0;
diff --git a/src/openvic-simulation/map/Province.hpp b/src/openvic-simulation/map/Province.hpp
index 0b98588..2f8068e 100644
--- a/src/openvic-simulation/map/Province.hpp
+++ b/src/openvic-simulation/map/Province.hpp
@@ -26,7 +26,7 @@ namespace OpenVic {
using index_t = uint16_t;
using life_rating_t = int8_t;
- using distance_t = uint16_t;
+ using distance_t = fixed_point_t;
using flags_t = uint16_t;
enum struct colony_status_t : uint8_t { STATE, PROTECTORATE, COLONY };
@@ -43,10 +43,11 @@ namespace OpenVic {
};
struct province_positions_t {
+ fvec2_t center;
fvec2_t text;
fixed_point_t text_rotation;
fixed_point_t text_scale;
- fvec2_t unit;
+ std::optional<fvec2_t> unit;
fvec2_t city;
fvec2_t factory;
fvec2_t building_construction;
@@ -89,6 +90,8 @@ namespace OpenVic {
fixed_point_map_t<Culture const*> PROPERTY(culture_distribution);
fixed_point_map_t<Religion const*> PROPERTY(religion_distribution);
+ fvec2_t get_unit_position() const;
+
Province(std::string_view new_identifier, colour_t new_colour, index_t new_index);
public:
@@ -100,17 +103,19 @@ namespace OpenVic {
bool expand_building(std::string_view building_type_identifier);
- bool load_pop_list(PopManager const& pop_manager, ast::NodeCPtr root);
bool add_pop(Pop&& pop);
+ bool add_pop_vec(std::vector<Pop> const& pop_vec);
size_t get_pop_count() const;
void update_pops();
void update_state(Date today);
void tick(Date today);
- bool is_adjacent_to(Province const* province);
+ bool is_adjacent_to(Province const* province) const;
bool add_adjacency(Province const* province, distance_t distance, flags_t flags);
+ distance_t calculate_distance_to(Province const* province) const;
+
bool reset(BuildingTypeManager const& building_type_manager);
bool apply_history_to_province(ProvinceHistoryEntry const* entry);
};
diff --git a/src/openvic-simulation/military/Unit.cpp b/src/openvic-simulation/military/Unit.cpp
index 01c6f84..98fe392 100644
--- a/src/openvic-simulation/military/Unit.cpp
+++ b/src/openvic-simulation/military/Unit.cpp
@@ -188,52 +188,53 @@ bool UnitManager::load_unit_file(GoodManager const& good_manager, ast::NodeCPtr
})(root);
}
-#define STAT_MODIFIER(name, positive_good, format) \
- ret &= modifier_manager.add_modifier_effect(StringUtils::append_string_views(identifier, "_", name), positive_good, ModifierEffect::format_t::format)
+bool UnitManager::generate_modifiers(ModifierManager& modifier_manager) const {
+ bool ret = true;
+
+ const auto generate_stat_modifiers = [&modifier_manager, &ret](std::string_view identifier, Unit::type_t type) -> void {
+
+ const auto stat_modifier = [&modifier_manager, &ret, &identifier](std::string_view suffix, bool positive_good,
+ ModifierEffect::format_t format) -> void {
+ ret &= modifier_manager.add_modifier_effect(
+ StringUtils::append_string_views(identifier, suffix), positive_good, format
+ );
+ };
-bool UnitManager::generate_modifiers(ModifierManager& modifier_manager) {
- std::function<bool(std::string_view, Unit::type_t)> generate_stat_modifiers = [this, &modifier_manager](std::string_view identifier, Unit::type_t type) -> bool {
- modifier_manager.register_complex_modifier(identifier);
- bool ret = true;
+ using enum ModifierEffect::format_t;
- STAT_MODIFIER("default_organisation", true, RAW_DECIMAL);
- STAT_MODIFIER("maximum_speed", true, RAW_DECIMAL);
- STAT_MODIFIER("build_time", false, INT);
- STAT_MODIFIER("supply_consumption", false, PROPORTION_DECIMAL);
+ ret &= modifier_manager.register_complex_modifier(identifier);
+
+ stat_modifier("_default_organisation", true, RAW_DECIMAL);
+ stat_modifier("_maximum_speed", true, RAW_DECIMAL);
+ stat_modifier("_build_time", false, INT);
+ stat_modifier("_supply_consumption", false, PROPORTION_DECIMAL);
switch (type) {
- case Unit::type_t::LAND: {
- STAT_MODIFIER("reconnaissance", true, RAW_DECIMAL);
- STAT_MODIFIER("attack", true, RAW_DECIMAL);
- STAT_MODIFIER("defence", true, RAW_DECIMAL);
- STAT_MODIFIER("discipline", true, PROPORTION_DECIMAL);
- STAT_MODIFIER("support", true, PROPORTION_DECIMAL);
- STAT_MODIFIER("maneuver", true, INT);
- STAT_MODIFIER("siege", true, RAW_DECIMAL);
+ case Unit::type_t::LAND:
+ stat_modifier("_reconnaissance", true, RAW_DECIMAL);
+ stat_modifier("_attack", true, RAW_DECIMAL);
+ stat_modifier("_defence", true, RAW_DECIMAL);
+ stat_modifier("_discipline", true, PROPORTION_DECIMAL);
+ stat_modifier("_support", true, PROPORTION_DECIMAL);
+ stat_modifier("_maneuver", true, INT);
+ stat_modifier("_siege", true, RAW_DECIMAL);
break;
- }
- case Unit::type_t::NAVAL: {
- STAT_MODIFIER("colonial_points", true, INT);
- STAT_MODIFIER("supply_consumption_score", false, INT);
- STAT_MODIFIER("hull", true, RAW_DECIMAL);
- STAT_MODIFIER("gun_power", true, RAW_DECIMAL);
- STAT_MODIFIER("fire_range", true, RAW_DECIMAL);
- STAT_MODIFIER("evasion", true, PROPORTION_DECIMAL);
- STAT_MODIFIER("torpedo_attack", true, RAW_DECIMAL);
+ case Unit::type_t::NAVAL:
+ stat_modifier("_colonial_points", true, INT);
+ stat_modifier("_supply_consumption_score", false, INT);
+ stat_modifier("_hull", true, RAW_DECIMAL);
+ stat_modifier("_gun_power", true, RAW_DECIMAL);
+ stat_modifier("_fire_range", true, RAW_DECIMAL);
+ stat_modifier("_evasion", true, PROPORTION_DECIMAL);
+ stat_modifier("_torpedo_attack", true, RAW_DECIMAL);
break;
}
- }
-
- return ret;
};
- bool ret = true;
- ret &= generate_stat_modifiers("army_base", Unit::type_t::LAND);
- ret &= generate_stat_modifiers("navy_base", Unit::type_t::NAVAL);
- for (Unit const& unit : this->get_units())
- ret &= generate_stat_modifiers(unit.get_identifier(), unit.get_type());
-
+ generate_stat_modifiers("army_base", Unit::type_t::LAND);
+ generate_stat_modifiers("navy_base", Unit::type_t::NAVAL);
+ for (Unit const& unit : get_units()) {
+ generate_stat_modifiers(unit.get_identifier(), unit.get_type());
+ }
return ret;
}
-
-#undef STAT_MODIFIER \ No newline at end of file
diff --git a/src/openvic-simulation/military/Unit.hpp b/src/openvic-simulation/military/Unit.hpp
index 6e3a6e4..a44f4e5 100644
--- a/src/openvic-simulation/military/Unit.hpp
+++ b/src/openvic-simulation/military/Unit.hpp
@@ -122,6 +122,6 @@ namespace OpenVic {
static NodeTools::callback_t<std::string_view> expect_type_str(NodeTools::Callback<Unit::type_t> auto callback);
bool load_unit_file(GoodManager const& good_manager, ast::NodeCPtr root);
- bool generate_modifiers(ModifierManager& modifier_manager);
+ bool generate_modifiers(ModifierManager& modifier_manager) const;
};
}
diff --git a/src/openvic-simulation/misc/Decision.cpp b/src/openvic-simulation/misc/Decision.cpp
index 9200688..f1f2b6c 100644
--- a/src/openvic-simulation/misc/Decision.cpp
+++ b/src/openvic-simulation/misc/Decision.cpp
@@ -34,7 +34,7 @@ bool DecisionManager::add_decision(
}
}
- return decisions.add_item({
+ return decisions.add_item({
identifier,
alert,
news,
@@ -42,7 +42,7 @@ bool DecisionManager::add_decision(
news_desc_long,
news_desc_medium,
news_desc_short,
- picture
+ picture
}, duplicate_warning_callback);
}
diff --git a/src/openvic-simulation/misc/Modifier.cpp b/src/openvic-simulation/misc/Modifier.cpp
index ac052c2..40698e5 100644
--- a/src/openvic-simulation/misc/Modifier.cpp
+++ b/src/openvic-simulation/misc/Modifier.cpp
@@ -132,11 +132,6 @@ bool ModifierManager::setup_modifier_effects() {
ret &= add_modifier_effect("max_tariff", true);
ret &= add_modifier_effect("max_tax", true);
ret &= add_modifier_effect("max_war_exhaustion", true, PERCENTAGE_DECIMAL);
- ret &= add_modifier_effect("middle_income_modifier", true);
- ret &= add_modifier_effect("middle_life_needs", true);
- ret &= add_modifier_effect("middle_everyday_needs", true);
- ret &= add_modifier_effect("middle_luxury_needs", true);
- ret &= add_modifier_effect("middle_vote", true);
ret &= add_modifier_effect("min_military_spending", true);
ret &= add_modifier_effect("min_social_spending", true);
ret &= add_modifier_effect("min_tariff", true);
@@ -150,11 +145,6 @@ bool ModifierManager::setup_modifier_effects() {
ret &= add_modifier_effect("non_accepted_pop_militancy_modifier", false, RAW_DECIMAL);
ret &= add_modifier_effect("org_regain", true);
ret &= add_modifier_effect("political_reform_desire", false);
- ret &= add_modifier_effect("poor_income_modifier", true);
- ret &= add_modifier_effect("poor_life_needs", true);
- ret &= add_modifier_effect("poor_everyday_needs", true);
- ret &= add_modifier_effect("poor_luxury_needs", true);
- ret &= add_modifier_effect("poor_vote", true);
ret &= add_modifier_effect("prestige", true, RAW_DECIMAL);
ret &= add_modifier_effect("research_points", true, RAW_DECIMAL);
ret &= add_modifier_effect("research_points_modifier", true);
@@ -163,11 +153,6 @@ bool ModifierManager::setup_modifier_effects() {
ret &= add_modifier_effect("RGO_output", true);
ret &= add_modifier_effect("rgo_throughput", true);
ret &= add_modifier_effect("RGO_throughput", true);
- ret &= add_modifier_effect("rich_income_modifier", true);
- ret &= add_modifier_effect("rich_life_needs", true);
- ret &= add_modifier_effect("rich_everyday_needs", true);
- ret &= add_modifier_effect("rich_luxury_needs", true);
- ret &= add_modifier_effect("rich_vote", true);
ret &= add_modifier_effect("ruling_party_support", true);
ret &= add_modifier_effect("social_reform_desire", false);
ret &= add_modifier_effect("supply_consumption", false);
@@ -249,8 +234,13 @@ bool ModifierManager::setup_modifier_effects() {
return ret;
}
-void ModifierManager::register_complex_modifier(std::string_view identifier) {
- complex_modifiers.emplace(identifier);
+bool ModifierManager::register_complex_modifier(std::string_view identifier) {
+ if (complex_modifiers.emplace(identifier).second) {
+ return true;
+ } else {
+ Logger::error("Duplicate complex modifier: ", identifier);
+ return false;
+ }
}
bool ModifierManager::add_event_modifier(std::string_view identifier, ModifierValue&& values, Modifier::icon_t icon) {
diff --git a/src/openvic-simulation/misc/Modifier.hpp b/src/openvic-simulation/misc/Modifier.hpp
index a176d6c..f3a2499 100644
--- a/src/openvic-simulation/misc/Modifier.hpp
+++ b/src/openvic-simulation/misc/Modifier.hpp
@@ -129,7 +129,7 @@ namespace OpenVic {
ModifierEffect::format_t format = ModifierEffect::format_t::PROPORTION_DECIMAL
);
- void register_complex_modifier(std::string_view identifier);
+ bool register_complex_modifier(std::string_view identifier);
bool setup_modifier_effects();
diff --git a/src/openvic-simulation/politics/Government.cpp b/src/openvic-simulation/politics/Government.cpp
index a226518..fc93cc3 100644
--- a/src/openvic-simulation/politics/Government.cpp
+++ b/src/openvic-simulation/politics/Government.cpp
@@ -111,3 +111,9 @@ bool GovernmentTypeManager::load_government_types_file(IdeologyManager const& id
return ret;
}
+
+bool GovernmentTypeManager::is_valid_flag_type(std::string_view type) const {
+ return std::any_of(flag_types.begin(), flag_types.end(), [type](std::string const& flag_type) -> bool {
+ return flag_type == type;
+ });
+}
diff --git a/src/openvic-simulation/politics/Government.hpp b/src/openvic-simulation/politics/Government.hpp
index 4682bbf..34a9194 100644
--- a/src/openvic-simulation/politics/Government.hpp
+++ b/src/openvic-simulation/politics/Government.hpp
@@ -38,5 +38,7 @@ namespace OpenVic {
);
bool load_government_types_file(IdeologyManager const& ideology_manager, ast::NodeCPtr root);
+
+ bool is_valid_flag_type(std::string_view type) const;
};
} // namespace OpenVic
diff --git a/src/openvic-simulation/politics/Rebel.cpp b/src/openvic-simulation/politics/Rebel.cpp
index a00b4a8..6850e83 100644
--- a/src/openvic-simulation/politics/Rebel.cpp
+++ b/src/openvic-simulation/politics/Rebel.cpp
@@ -142,16 +142,17 @@ bool RebelManager::load_rebels_file(
return ret;
}
-bool RebelManager::generate_modifiers(ModifierManager& modifier_manager) {
+bool RebelManager::generate_modifiers(ModifierManager& modifier_manager) const {
bool ret = true;
- modifier_manager.register_complex_modifier("rebel_org_gain");
+ ret &= modifier_manager.register_complex_modifier("rebel_org_gain");
ret &= modifier_manager.add_modifier_effect("rebel_org_gain_all", false);
for (RebelType const& rebel_type : get_rebel_types()) {
- std::string modifier_name = StringUtils::append_string_views("rebel_org_gain_", rebel_type.get_identifier());
- ret &= modifier_manager.add_modifier_effect(modifier_name, false);
+ ret &= modifier_manager.add_modifier_effect(
+ StringUtils::append_string_views("rebel_org_gain_", rebel_type.get_identifier()), false
+ );
}
return ret;
} \ No newline at end of file
diff --git a/src/openvic-simulation/politics/Rebel.hpp b/src/openvic-simulation/politics/Rebel.hpp
index c0fc9ff..29ae3ae 100644
--- a/src/openvic-simulation/politics/Rebel.hpp
+++ b/src/openvic-simulation/politics/Rebel.hpp
@@ -77,6 +77,6 @@ namespace OpenVic {
);
bool load_rebels_file(IdeologyManager const& ideology_manager, GovernmentTypeManager const& government_type_manager, ast::NodeCPtr root);
- bool generate_modifiers(ModifierManager& modifier_manager);
+ bool generate_modifiers(ModifierManager& modifier_manager) const;
};
} \ No newline at end of file
diff --git a/src/openvic-simulation/pop/Pop.cpp b/src/openvic-simulation/pop/Pop.cpp
index cf54c2b..39deeaa 100644
--- a/src/openvic-simulation/pop/Pop.cpp
+++ b/src/openvic-simulation/pop/Pop.cpp
@@ -4,14 +4,18 @@
#include "openvic-simulation/dataloader/NodeTools.hpp"
#include "openvic-simulation/map/Province.hpp"
+#include "openvic-simulation/politics/Rebel.hpp"
#include "openvic-simulation/utility/Logger.hpp"
using namespace OpenVic;
using namespace OpenVic::NodeTools;
Pop::Pop(
- PopType const& new_type, Culture const& new_culture, Religion const& new_religion, pop_size_t new_size
-) : type { new_type }, culture { new_culture }, religion { new_religion }, size { new_size } {
+ PopType const& new_type, Culture const& new_culture, Religion const& new_religion, pop_size_t new_size,
+ fixed_point_t new_militancy, fixed_point_t new_consciousness, RebelType const* new_rebel_type
+) : type { new_type }, culture { new_culture }, religion { new_religion }, size { new_size }, num_promoted { 0 },
+ num_demoted { 0 }, num_migrated { 0 }, militancy { new_militancy }, consciousness { new_consciousness },
+ rebel_type { new_rebel_type } {
assert(size > 0);
}
@@ -19,8 +23,10 @@ Pop::pop_size_t Pop::get_pop_daily_change() const {
return Pop::get_num_promoted() - (Pop::get_num_demoted() + Pop::get_num_migrated());
}
+Strata::Strata(std::string_view new_identifier) : HasIdentifier { new_identifier } {}
+
PopType::PopType(
- std::string_view new_identifier, colour_t new_colour, strata_t new_strata, sprite_t new_sprite,
+ std::string_view new_identifier, colour_t new_colour, Strata const& new_strata, sprite_t new_sprite,
Good::good_map_t&& new_life_needs, Good::good_map_t&& new_everyday_needs, Good::good_map_t&& new_luxury_needs,
rebel_units_t&& new_rebel_units, Pop::pop_size_t new_max_size, Pop::pop_size_t new_merge_max_size,
bool new_state_capital_only, bool new_demote_migrant, bool new_is_artisan, bool new_allowed_to_vote, bool new_is_slave,
@@ -42,8 +48,16 @@ PopType::PopType(
PopManager::PopManager() : slave_sprite { 0 }, administrative_sprite { 0 } {}
+bool PopManager::add_strata(std::string_view identifier) {
+ if (identifier.empty()) {
+ Logger::error("Invalid strata identifier - empty!");
+ return false;
+ }
+ return stratas.add_item({ identifier });
+}
+
bool PopManager::add_pop_type(
- std::string_view identifier, colour_t colour, PopType::strata_t strata, PopType::sprite_t sprite,
+ std::string_view identifier, colour_t colour, Strata const* strata, PopType::sprite_t sprite,
Good::good_map_t&& life_needs, Good::good_map_t&& everyday_needs, Good::good_map_t&& luxury_needs,
PopType::rebel_units_t&& rebel_units, Pop::pop_size_t max_size, Pop::pop_size_t merge_max_size, bool state_capital_only,
bool demote_migrant, bool is_artisan, bool allowed_to_vote, bool is_slave, bool can_be_recruited,
@@ -58,6 +72,10 @@ bool PopManager::add_pop_type(
Logger::error("Invalid pop type colour for ", identifier, ": ", colour_to_hex_string(colour));
return false;
}
+ if (strata == nullptr) {
+ Logger::error("Invalid pop type strata for ", identifier, " - null!");
+ return false;
+ }
if (sprite <= 0) {
Logger::error("Invalid pop type sprite index for ", identifier, ": ", sprite);
return false;
@@ -71,7 +89,7 @@ bool PopManager::add_pop_type(
return false;
}
const bool ret = pop_types.add_item({
- identifier, colour, strata, sprite, std::move(life_needs), std::move(everyday_needs),
+ identifier, colour, *strata, sprite, std::move(life_needs), std::move(everyday_needs),
std::move(luxury_needs), std::move(rebel_units), max_size, merge_max_size, state_capital_only,
demote_migrant, is_artisan, allowed_to_vote, is_slave, can_be_recruited, can_reduce_consciousness,
administrative_efficiency, can_build, factory, can_work_factory, unemployment
@@ -87,20 +105,19 @@ bool PopManager::add_pop_type(
return ret;
}
+void PopManager::reserve_pop_types(size_t count) {
+ stratas.reserve(stratas.size() + count);
+ pop_types.reserve(pop_types.size() + count);
+}
+
/* REQUIREMENTS:
* POP-3, POP-4, POP-5, POP-6, POP-7, POP-8, POP-9, POP-10, POP-11, POP-12, POP-13, POP-14
*/
bool PopManager::load_pop_type_file(
std::string_view filestem, UnitManager const& unit_manager, GoodManager const& good_manager, ast::NodeCPtr root
) {
- static const string_map_t<PopType::strata_t> strata_map = {
- { "poor", PopType::strata_t::POOR },
- { "middle", PopType::strata_t::MIDDLE },
- { "rich", PopType::strata_t::RICH }
- };
-
colour_t colour = NULL_COLOUR;
- PopType::strata_t strata = PopType::strata_t::POOR;
+ Strata const* strata = nullptr;
PopType::sprite_t sprite = 0;
Good::good_map_t life_needs, everyday_needs, luxury_needs;
PopType::rebel_units_t rebel_units;
@@ -114,7 +131,19 @@ bool PopManager::load_pop_type_file(
"is_artisan", ZERO_OR_ONE, expect_bool(assign_variable_callback(is_artisan)),
"max_size", ZERO_OR_ONE, expect_uint(assign_variable_callback(max_size)),
"merge_max_size", ZERO_OR_ONE, expect_uint(assign_variable_callback(merge_max_size)),
- "strata", ONE_EXACTLY, expect_identifier(expect_mapped_string(strata_map, assign_variable_callback(strata))),
+ "strata", ONE_EXACTLY, expect_identifier(
+ [this, &strata](std::string_view identifier) -> bool {
+ strata = get_strata_by_identifier(identifier);
+ if (strata != nullptr) {
+ return true;
+ }
+ if (add_strata(identifier)) {
+ strata = &get_stratas().back();
+ return true;
+ }
+ return false;
+ }
+ ),
"state_capital_only", ZERO_OR_ONE, expect_bool(assign_variable_callback(state_capital_only)),
"research_points", ZERO_OR_ONE, success_callback, // TODO - research points generation
"research_optimum", ZERO_OR_ONE, success_callback, // TODO - bonus research points generation
@@ -157,27 +186,55 @@ bool PopManager::load_pop_type_file(
return ret;
}
-bool PopManager::load_pop_into_province(Province& province, std::string_view pop_type_identifier, ast::NodeCPtr pop_node)
- const {
- PopType const* type = get_pop_type_by_identifier(pop_type_identifier);
+bool PopManager::load_pop_into_vector(
+ RebelManager const& rebel_manager, std::vector<Pop>& vec, PopType const& type, ast::NodeCPtr pop_node,
+ bool *non_integer_size
+) const {
Culture const* culture = nullptr;
Religion const* religion = nullptr;
- Pop::pop_size_t size = 0;
+ fixed_point_t size = 0; /* Some genius filled later start dates with non-integer sized pops */
+ fixed_point_t militancy = 0, consciousness = 0;
+ RebelType const* rebel_type = nullptr;
+
bool ret = expect_dictionary_keys(
"culture", ONE_EXACTLY, culture_manager.expect_culture_identifier(assign_variable_callback_pointer(culture)),
"religion", ONE_EXACTLY, religion_manager.expect_religion_identifier(assign_variable_callback_pointer(religion)),
- "size", ONE_EXACTLY, expect_uint(assign_variable_callback(size)),
- "militancy", ZERO_OR_ONE, success_callback,
- "rebel_type", ZERO_OR_ONE, success_callback
+ "size", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(size)),
+ "militancy", ZERO_OR_ONE, expect_fixed_point(assign_variable_callback(militancy)),
+ "consciousness", ZERO_OR_ONE, expect_fixed_point(assign_variable_callback(consciousness)),
+ "rebel_type", ZERO_OR_ONE, rebel_manager.expect_rebel_type_identifier(assign_variable_callback_pointer(rebel_type))
)(pop_node);
- if (type != nullptr && culture != nullptr && religion != nullptr && size > 0) {
- ret &= province.add_pop({ *type, *culture, *religion, size });
+ if (non_integer_size != nullptr && !size.is_integer()) {
+ *non_integer_size = true;
+ }
+
+ if (culture != nullptr && religion != nullptr && size >= 1) {
+ vec.emplace_back(Pop { type, *culture, *religion, size.to_int64_t(), militancy, consciousness, rebel_type });
} else {
Logger::warning(
- "Some pop arguments are invalid: province = ", province, ", type = ", type, ", culture = ", culture,
- ", religion = ", religion, ", size = ", size
+ "Some pop arguments are invalid: culture = ", culture, ", religion = ", religion, ", size = ", size
);
}
return ret;
}
+
+bool PopManager::generate_modifiers(ModifierManager& modifier_manager) const {
+ bool ret = true;
+ for (Strata const& strata : get_stratas()) {
+ const auto strata_modifier = [&modifier_manager, &ret, &strata](std::string_view suffix, bool positive_good) -> void {
+ ret &= modifier_manager.add_modifier_effect(
+ StringUtils::append_string_views(strata.get_identifier(), suffix), positive_good
+ );
+ };
+
+ strata_modifier("_income_modifier", true);
+ strata_modifier("_savings_modifier", true);
+ strata_modifier("_vote", true);
+
+ strata_modifier("_life_needs", false);
+ strata_modifier("_everyday_needs", false);
+ strata_modifier("_luxury_needs", false);
+ }
+ return ret;
+}
diff --git a/src/openvic-simulation/pop/Pop.hpp b/src/openvic-simulation/pop/Pop.hpp
index 736b77d..0c84aae 100644
--- a/src/openvic-simulation/pop/Pop.hpp
+++ b/src/openvic-simulation/pop/Pop.hpp
@@ -9,6 +9,8 @@ namespace OpenVic {
struct PopManager;
struct PopType;
+ struct RebelType;
+ struct RebelManager;
/* REQUIREMENTS:
* POP-18, POP-19, POP-20, POP-21, POP-34, POP-35, POP-36, POP-37
@@ -27,10 +29,17 @@ namespace OpenVic {
pop_size_t PROPERTY(num_demoted);
pop_size_t PROPERTY(num_migrated);
- Pop(PopType const& new_type, Culture const& new_culture, Religion const& new_religion, pop_size_t new_size);
+ fixed_point_t PROPERTY(militancy);
+ fixed_point_t PROPERTY(consciousness);
+ RebelType const* PROPERTY(rebel_type);
+
+ Pop(
+ PopType const& new_type, Culture const& new_culture, Religion const& new_religion, pop_size_t new_size,
+ fixed_point_t new_militancy, fixed_point_t new_consciousness, RebelType const* new_rebel_type
+ );
public:
- Pop(Pop const&) = delete;
+ Pop(Pop const&) = default;
Pop(Pop&&) = default;
Pop& operator=(Pop const&) = delete;
Pop& operator=(Pop&&) = delete;
@@ -38,6 +47,16 @@ namespace OpenVic {
pop_size_t get_pop_daily_change() const;
};
+ struct Strata : HasIdentifier {
+ friend struct PopManager;
+
+ private:
+ Strata(std::string_view new_identifier);
+
+ public:
+ Strata(Strata&&) = default;
+ };
+
/* REQUIREMENTS:
* POP-15, POP-16, POP-17, POP-26
*/
@@ -48,7 +67,7 @@ namespace OpenVic {
using rebel_units_t = fixed_point_map_t<Unit const*>;
private:
- const enum class strata_t { POOR, MIDDLE, RICH } PROPERTY(strata);
+ Strata const& PROPERTY(strata);
const sprite_t PROPERTY(sprite);
const Good::good_map_t PROPERTY(life_needs);
const Good::good_map_t PROPERTY(everyday_needs);
@@ -72,7 +91,7 @@ namespace OpenVic {
// TODO - country and province migration targets, promote_to targets, ideologies and issues
PopType(
- std::string_view new_identifier, colour_t new_colour, strata_t new_strata, sprite_t new_sprite,
+ std::string_view new_identifier, colour_t new_colour, Strata const& new_strata, sprite_t new_sprite,
Good::good_map_t&& new_life_needs, Good::good_map_t&& new_everyday_needs, Good::good_map_t&& new_luxury_needs,
rebel_units_t&& new_rebel_units, Pop::pop_size_t new_max_size, Pop::pop_size_t new_merge_max_size,
bool new_state_capital_only, bool new_demote_migrant, bool new_is_artisan, bool new_allowed_to_vote,
@@ -89,6 +108,8 @@ namespace OpenVic {
struct PopManager {
private:
+ /* Using strata/stratas instead of stratum/strata to avoid confusion. */
+ IdentifierRegistry<Strata> IDENTIFIER_REGISTRY(strata);
IdentifierRegistry<PopType> IDENTIFIER_REGISTRY(pop_type);
PopType::sprite_t PROPERTY(slave_sprite);
PopType::sprite_t PROPERTY(administrative_sprite);
@@ -99,8 +120,10 @@ namespace OpenVic {
public:
PopManager();
+ bool add_strata(std::string_view identifier);
+
bool add_pop_type(
- std::string_view identifier, colour_t new_colour, PopType::strata_t strata, PopType::sprite_t sprite,
+ std::string_view identifier, colour_t new_colour, Strata const* strata, PopType::sprite_t sprite,
Good::good_map_t&& life_needs, Good::good_map_t&& everyday_needs, Good::good_map_t&& luxury_needs,
PopType::rebel_units_t&& rebel_units, Pop::pop_size_t max_size, Pop::pop_size_t merge_max_size,
bool state_capital_only, bool demote_migrant, bool is_artisan, bool allowed_to_vote, bool is_slave,
@@ -108,9 +131,16 @@ namespace OpenVic {
bool can_work_factory, bool unemployment
);
+ void reserve_pop_types(size_t count);
+
bool load_pop_type_file(
std::string_view filestem, UnitManager const& unit_manager, GoodManager const& good_manager, ast::NodeCPtr root
);
- bool load_pop_into_province(Province& province, std::string_view pop_type_identifier, ast::NodeCPtr pop_node) const;
+ bool load_pop_into_vector(
+ RebelManager const& rebel_manager, std::vector<Pop>& vec, PopType const& type, ast::NodeCPtr pop_node,
+ bool *non_integer_size
+ ) const;
+
+ bool generate_modifiers(ModifierManager& modifier_manager) const;
};
}
diff --git a/src/openvic-simulation/research/Technology.cpp b/src/openvic-simulation/research/Technology.cpp
index 3ba3624..7851707 100644
--- a/src/openvic-simulation/research/Technology.cpp
+++ b/src/openvic-simulation/research/Technology.cpp
@@ -143,19 +143,22 @@ bool TechnologyManager::load_technologies_file(
})(root);
}
-#define TECH_MODIFIER(NAME, POS) ret &= modifier_manager.add_modifier_effect(NAME, POS)
-#define UNCIV_TECH_MODIFIER(NAME) TECH_MODIFIER(NAME, false); TECH_MODIFIER(StringUtils::append_string_views("self_", NAME), false);
-bool TechnologyManager::generate_modifiers(ModifierManager& modifier_manager) {
+bool TechnologyManager::generate_modifiers(ModifierManager& modifier_manager) const {
bool ret = true;
- UNCIV_TECH_MODIFIER("unciv_military_modifier");
- UNCIV_TECH_MODIFIER("unciv_economic_modifier");
+ const auto unciv_tech_modifier = [&modifier_manager, &ret](std::string_view name) -> void {
+ ret &= modifier_manager.add_modifier_effect(name, false);
+ ret &= modifier_manager.add_modifier_effect(StringUtils::append_string_views("self_", name), false);
+ };
+
+ unciv_tech_modifier("unciv_military_modifier");
+ unciv_tech_modifier("unciv_economic_modifier");
for (TechnologyFolder const& folder : get_technology_folders()) {
- TECH_MODIFIER(StringUtils::append_string_views(folder.get_identifier(), "_research_bonus"), true);
+ ret &= modifier_manager.add_modifier_effect(
+ StringUtils::append_string_views(folder.get_identifier(), "_research_bonus"), true
+ );
}
return ret;
}
-#undef UNCIV_TECH_MODIFIER
-#undef TECH_MODIFIER \ No newline at end of file
diff --git a/src/openvic-simulation/research/Technology.hpp b/src/openvic-simulation/research/Technology.hpp
index 8489e9b..1035a8e 100644
--- a/src/openvic-simulation/research/Technology.hpp
+++ b/src/openvic-simulation/research/Technology.hpp
@@ -87,6 +87,6 @@ namespace OpenVic {
ModifierManager const& modifier_manager, UnitManager const& unit_manager,
BuildingTypeManager const& building_type_manager, ast::NodeCPtr root
); // technologies/*.txt
- bool generate_modifiers(ModifierManager& modifier_manager);
+ bool generate_modifiers(ModifierManager& modifier_manager) const;
};
} \ No newline at end of file
diff --git a/src/openvic-simulation/types/fixed_point/FixedPoint.hpp b/src/openvic-simulation/types/fixed_point/FixedPoint.hpp
index ba6790f..75abefb 100644
--- a/src/openvic-simulation/types/fixed_point/FixedPoint.hpp
+++ b/src/openvic-simulation/types/fixed_point/FixedPoint.hpp
@@ -214,6 +214,10 @@ namespace OpenVic {
return value & (ONE - 1);
}
+ constexpr bool is_integer() const {
+ return get_frac() == 0;
+ }
+
constexpr int64_t to_int64_t() const {
return value >> PRECISION;
}