diff options
author | Hop311 <hop3114@gmail.com> | 2023-09-08 18:12:22 +0200 |
---|---|---|
committer | Hop311 <hop3114@gmail.com> | 2023-09-08 18:12:22 +0200 |
commit | 7772f8871348b7b52cb0a478bb76df68d8799a07 (patch) | |
tree | fd8c4626b2cee69a9fe9250365af6b18eea63c70 /src/openvic | |
parent | 7f9a9a8241ba81be9213e6606b8be4a48f1cbaab (diff) |
More refactoring and duplicate code removal
Diffstat (limited to 'src/openvic')
40 files changed, 0 insertions, 5090 deletions
diff --git a/src/openvic/GameAdvancementHook.cpp b/src/openvic/GameAdvancementHook.cpp deleted file mode 100644 index ac16158..0000000 --- a/src/openvic/GameAdvancementHook.cpp +++ /dev/null @@ -1,76 +0,0 @@ -#include "GameAdvancementHook.hpp" - -using namespace OpenVic; - -const std::vector<std::chrono::milliseconds> GameAdvancementHook::GAME_SPEEDS = { - std::chrono::milliseconds { 4000 }, - std::chrono::milliseconds { 3000 }, - std::chrono::milliseconds { 2000 }, - std::chrono::milliseconds { 1000 }, - std::chrono::milliseconds { 100 }, - std::chrono::milliseconds { 1 } -}; - -GameAdvancementHook::GameAdvancementHook(AdvancementFunction tickFunction, - RefreshFunction updateFunction, bool startPaused, speed_t startingSpeed) - : triggerFunction { tickFunction }, - refreshFunction { updateFunction }, - isPaused { startPaused } { - lastPolledTime = std::chrono::high_resolution_clock::now(); - setSimulationSpeed(startingSpeed); -} - -void GameAdvancementHook::setSimulationSpeed(speed_t speed) { - if (speed < 0) - currentSpeed = 0; - else if (speed >= GAME_SPEEDS.size()) - currentSpeed = GAME_SPEEDS.size() - 1; - else - currentSpeed = speed; -} - -GameAdvancementHook::speed_t GameAdvancementHook::getSimulationSpeed() const { - return currentSpeed; -} - -void GameAdvancementHook::increaseSimulationSpeed() { - setSimulationSpeed(currentSpeed + 1); -} - -void GameAdvancementHook::decreaseSimulationSpeed() { - setSimulationSpeed(currentSpeed - 1); -} - -bool GameAdvancementHook::canIncreaseSimulationSpeed() const { - return currentSpeed + 1 < GAME_SPEEDS.size(); -} - -bool GameAdvancementHook::canDecreaseSimulationSpeed() const { - return currentSpeed > 0; -} - -GameAdvancementHook& GameAdvancementHook::operator++() { - increaseSimulationSpeed(); - return *this; -}; - -GameAdvancementHook& GameAdvancementHook::operator--() { - decreaseSimulationSpeed(); - return *this; -}; - -void GameAdvancementHook::conditionallyAdvanceGame() { - if (!isPaused) { - time_point_t currentTime = std::chrono::high_resolution_clock::now(); - if (std::chrono::duration_cast<std::chrono::milliseconds>(currentTime - lastPolledTime) >= GAME_SPEEDS[currentSpeed]) { - lastPolledTime = currentTime; - if (triggerFunction) triggerFunction(); - } - } - if (refreshFunction) refreshFunction(); -} - -void GameAdvancementHook::reset() { - isPaused = true; - currentSpeed = 0; -} diff --git a/src/openvic/GameAdvancementHook.hpp b/src/openvic/GameAdvancementHook.hpp deleted file mode 100644 index 59e43a4..0000000 --- a/src/openvic/GameAdvancementHook.hpp +++ /dev/null @@ -1,44 +0,0 @@ -#pragma once - -#include <chrono> -#include <functional> -#include <vector> - -namespace OpenVic { - // Conditionally advances game with provided behaviour - // Class governs game speed and pause state - class GameAdvancementHook { - public: - using AdvancementFunction = std::function<void()>; - using RefreshFunction = std::function<void()>; - using speed_t = int8_t; - - // Minimum number of miliseconds before the simulation advances - static const std::vector<std::chrono::milliseconds> GAME_SPEEDS; - - private: - using time_point_t = std::chrono::time_point<std::chrono::high_resolution_clock>; - - time_point_t lastPolledTime; - // A function pointer that advances the simulation, intended to be a capturing lambda or something similar. May need to be reworked later - AdvancementFunction triggerFunction; - RefreshFunction refreshFunction; - speed_t currentSpeed; - - public: - bool isPaused; - - GameAdvancementHook(AdvancementFunction tickFunction, RefreshFunction updateFunction, bool startPaused = true, speed_t startingSpeed = 0); - - void setSimulationSpeed(speed_t speed); - speed_t getSimulationSpeed() const; - void increaseSimulationSpeed(); - void decreaseSimulationSpeed(); - bool canIncreaseSimulationSpeed() const; - bool canDecreaseSimulationSpeed() const; - GameAdvancementHook& operator++(); - GameAdvancementHook& operator--(); - void conditionallyAdvanceGame(); - void reset(); - }; -}
\ No newline at end of file diff --git a/src/openvic/GameManager.cpp b/src/openvic/GameManager.cpp deleted file mode 100644 index 052b814..0000000 --- a/src/openvic/GameManager.cpp +++ /dev/null @@ -1,132 +0,0 @@ -#include "GameManager.hpp" - -#include "openvic/utility/Logger.hpp" - -using namespace OpenVic; - -GameManager::GameManager(state_updated_func_t state_updated_callback) - : clock { [this]() { tick(); }, [this]() { update_state(); } }, - state_updated { state_updated_callback } {} - -void GameManager::set_needs_update() { - needs_update = true; -} - -void GameManager::update_state() { - if (needs_update) { - Logger::info("Update: ", today); - map.update_state(today); - if (state_updated) state_updated(); - needs_update = false; - } -} - -/* REQUIREMENTS: - * SS-98, SS-101 - */ -void GameManager::tick() { - today++; - Logger::info("Tick: ", today); - map.tick(today); - set_needs_update(); -} - -bool GameManager::setup() { - session_start = time(nullptr); - clock.reset(); - today = { 1836 }; - good_manager.reset_to_defaults(); - bool ret = map.setup(good_manager, building_manager, pop_manager); - set_needs_update(); - return ret; -} - -Date const& GameManager::get_today() const { - return today; -} - -bool GameManager::expand_building(Province::index_t province_index, const std::string_view building_type_identifier) { - set_needs_update(); - Province* province = map.get_province_by_index(province_index); - if (province == nullptr) { - Logger::error("Invalid province index ", province_index, " while trying to expand building ", building_type_identifier); - return false; - } - return province->expand_building(building_type_identifier); -} - -bool GameManager::load_hardcoded_defines() { - bool ret = true; - - static constexpr colour_t LOW_ALPHA_VALUE = float_to_alpha_value(0.4f); - static constexpr colour_t HIGH_ALPHA_VALUE = float_to_alpha_value(0.7f); - using mapmode_t = std::pair<std::string, Mapmode::colour_func_t>; - const std::vector<mapmode_t> mapmodes { - { "mapmode_terrain", - [](Map const&, Province const& province) -> colour_t { - return LOW_ALPHA_VALUE | (province.is_water() ? 0x4287F5 : 0x0D7017); - } }, - { "mapmode_province", - [](Map const&, Province const& province) -> colour_t { - return HIGH_ALPHA_VALUE | province.get_colour(); - } }, - { "mapmode_region", - [](Map const&, Province const& province) -> colour_t { - Region const* region = province.get_region(); - if (region != nullptr) return HIGH_ALPHA_VALUE | region->get_colour(); - return NULL_COLOUR; - } }, - { "mapmode_index", - [](Map const& map, Province const& province) -> colour_t { - const colour_t f = fraction_to_colour_byte(province.get_index(), map.get_province_count() + 1); - return HIGH_ALPHA_VALUE | (f << 16) | (f << 8) | f; - } }, - { "mapmode_rgo", - [](Map const& map, Province const& province) -> colour_t { - Good const* rgo = province.get_rgo(); - if (rgo != nullptr) return HIGH_ALPHA_VALUE | rgo->get_colour(); - return NULL_COLOUR; - } }, - { "mapmode_infrastructure", - [](Map const& map, Province const& province) -> colour_t { - Building const* railroad = province.get_building_by_identifier("building_railroad"); - if (railroad != nullptr) { - colour_t val = fraction_to_colour_byte(railroad->get_level(), railroad->get_type().get_max_level() + 1, 0.5f, 1.0f); - switch (railroad->get_expansion_state()) { - case Building::ExpansionState::CannotExpand: val <<= 16; break; - case Building::ExpansionState::CanExpand: break; - default: val <<= 8; break; - } - return HIGH_ALPHA_VALUE | val; - } - return NULL_COLOUR; - } }, - { "mapmode_population", - [](Map const& map, Province const& province) -> colour_t { - return HIGH_ALPHA_VALUE | (fraction_to_colour_byte(province.get_total_population(), map.get_highest_province_population() + 1, 0.1f, 1.0f) << 8); - } }, - { "mapmode_culture", - [](Map const& map, Province const& province) -> colour_t { - HasIdentifierAndColour const* largest = get_largest_item(province.get_culture_distribution()).first; - return largest != nullptr ? HIGH_ALPHA_VALUE | largest->get_colour() : NULL_COLOUR; - } }, - { "mapmode_religion", - [](Map const& map, Province const& province) -> colour_t { - HasIdentifierAndColour const* largest = get_largest_item(province.get_religion_distribution()).first; - return largest != nullptr ? HIGH_ALPHA_VALUE | largest->get_colour() : NULL_COLOUR; - } } - }; - for (mapmode_t const& mapmode : mapmodes) - ret &= map.add_mapmode(mapmode.first, mapmode.second); - map.lock_mapmodes(); - - using building_type_t = std::tuple<std::string, Building::level_t, Timespan>; - const std::vector<building_type_t> building_types { - { "building_fort", 4, 8 }, { "building_naval_base", 6, 15 }, { "building_railroad", 5, 10 } - }; - for (building_type_t const& type : building_types) - ret &= building_manager.add_building_type(std::get<0>(type), std::get<1>(type), std::get<2>(type)); - building_manager.lock_building_types(); - - return ret; -} diff --git a/src/openvic/GameManager.hpp b/src/openvic/GameManager.hpp deleted file mode 100644 index af2ec4f..0000000 --- a/src/openvic/GameManager.hpp +++ /dev/null @@ -1,40 +0,0 @@ -#pragma once - -#include "openvic/GameAdvancementHook.hpp" -#include "openvic/economy/Good.hpp" -#include "openvic/map/Map.hpp" - -namespace OpenVic { - struct GameManager { - using state_updated_func_t = std::function<void()>; - - Map map; - BuildingManager building_manager; - GoodManager good_manager; - PopManager pop_manager; - GameAdvancementHook clock; - - private: - time_t session_start; /* SS-54, as well as allowing time-tracking */ - Date today; - state_updated_func_t state_updated; - bool needs_update; - - void set_needs_update(); - void update_state(); - void tick(); - - public: - GameManager(state_updated_func_t state_updated_callback); - - bool setup(); - - Date const& get_today() const; - bool expand_building(Province::index_t province_index, const std::string_view building_type_identifier); - - /* Hardcoded data for defining things for which parsing from files has - * not been implemented, currently mapmodes and building types. - */ - bool load_hardcoded_defines(); - }; -} diff --git a/src/openvic/dataloader/Dataloader.cpp b/src/openvic/dataloader/Dataloader.cpp deleted file mode 100644 index 55994d3..0000000 --- a/src/openvic/dataloader/Dataloader.cpp +++ /dev/null @@ -1,288 +0,0 @@ -#include "Dataloader.hpp" - -#include "openvic/GameManager.hpp" -#include "openvic/utility/Logger.hpp" - -#include <openvic-dataloader/csv/Parser.hpp> -#include <openvic-dataloader/detail/CallbackOStream.hpp> -#include <openvic-dataloader/v2script/Parser.hpp> - -using namespace OpenVic; -using namespace OpenVic::NodeTools; -using namespace ovdl; - -bool Dataloader::set_roots(std::vector<std::filesystem::path> new_roots) { - if (!roots.empty()) { - Logger::error("Overriding existing dataloader roots!"); - roots.clear(); - } - bool ret = true; - for (std::reverse_iterator<std::vector<std::filesystem::path>::const_iterator> it = new_roots.crbegin(); it != new_roots.crend(); ++it) { - if (std::find(roots.begin(), roots.end(), *it) == roots.end()) { - if (std::filesystem::is_directory(*it)) { - Logger::info("Adding dataloader root: ", *it); - roots.push_back(*it); - } else { - Logger::error("Invalid dataloader root (must be an existing directory): ", *it); - ret = false; - } - } else { - Logger::error("Duplicate dataloader root: ", *it); - ret = false; - } - } - if (roots.empty()) { - Logger::error("Dataloader has no roots after attempting to add ", new_roots.size()); - ret = false; - } - return ret; -} - -std::filesystem::path Dataloader::lookup_file(std::filesystem::path const& path) const { - for (std::filesystem::path const& root : roots) { - const std::filesystem::path composed = root / path; - if (std::filesystem::is_regular_file(composed)) { - return composed; - } - } - Logger::error("Lookup for ", path, " failed!"); - return {}; -} - -const std::filesystem::path Dataloader::TXT = ".txt"; - -static bool contains_file_with_name(std::vector<std::filesystem::path> const& paths, - std::filesystem::path const& name) { - - for (std::filesystem::path const& path : paths) { - if (path.filename() == name) return true; - } - return false; -} - -std::vector<std::filesystem::path> Dataloader::lookup_files_in_dir(std::filesystem::path const& path, - std::filesystem::path const* extension) const { - - std::vector<std::filesystem::path> ret; - for (std::filesystem::path const& root : roots) { - const std::filesystem::path composed = root / path; - std::error_code ec; - for (std::filesystem::directory_entry const& entry : std::filesystem::directory_iterator { composed, ec }) { - if (entry.is_regular_file()) { - const std::filesystem::path file = entry; - if (extension == nullptr || file.extension() == *extension) { - if (!contains_file_with_name(ret, file.filename())) { - ret.push_back(file); - } - } - } - } - } - return ret; -} - -bool Dataloader::apply_to_files_in_dir(std::filesystem::path const& path, - std::function<bool(std::filesystem::path const&)> callback, - std::filesystem::path const* extension) const { - - bool ret = true; - for (std::filesystem::path const& file : lookup_files_in_dir(path, extension)) { - ret &= callback(file); - } - return ret; -} - -template<std::derived_from<detail::BasicParser> Parser, bool(Parser::*parse_func)()> -static Parser _run_ovdl_parser(std::filesystem::path const& path) { - Parser parser; - std::string buffer; - auto error_log_stream = ovdl::detail::CallbackStream { - [](void const* s, std::streamsize n, void* user_data) -> std::streamsize { - if (s != nullptr && n > 0 && user_data != nullptr) { - static_cast<std::string*>(user_data)->append(static_cast<char const*>(s), n); - return n; - } else { - Logger::error("Invalid input to parser error log callback: ", s, " / ", n, " / ", user_data); - return 0; - } - }, &buffer - }; - parser.set_error_log_to(error_log_stream); - parser.load_from_file(path); - if (!buffer.empty()) { - Logger::error("Parser load errors:\n\n", buffer, "\n"); - buffer.clear(); - } - if (parser.has_fatal_error() || parser.has_error()) { - Logger::error("Parser errors while loading ", path); - return parser; - } - if (!(parser.*parse_func)()) { - Logger::error("Parse function returned false!"); - } - if (!buffer.empty()) { - Logger::error("Parser parse errors:\n\n", buffer, "\n"); - buffer.clear(); - } - if (parser.has_fatal_error() || parser.has_error()) { - Logger::error("Parser errors while parsing ", path); - } - return parser; -} - -static v2script::Parser _parse_defines(std::filesystem::path const& path) { - return _run_ovdl_parser<v2script::Parser, &v2script::Parser::simple_parse>(path); -} - -static csv::Windows1252Parser _parse_csv(std::filesystem::path const& path) { - return _run_ovdl_parser<csv::Windows1252Parser, &csv::Windows1252Parser::parse_csv>(path); -} - -bool Dataloader::_load_pop_types(PopManager& pop_manager, std::filesystem::path const& pop_type_directory) const { - const bool ret = apply_to_files_in_dir(pop_type_directory, - [&pop_manager](std::filesystem::path const& file) -> bool { - return pop_manager.load_pop_type_file(file, _parse_defines(file).get_file_node()); - } - ); - if (!ret) { - Logger::error("Failed to load pop types!"); - } - pop_manager.lock_pop_types(); - return ret; -} - -bool Dataloader::_load_map_dir(Map& map, std::filesystem::path const& map_directory) const { - static const std::filesystem::path defaults_filename = "default.map"; - static const std::string default_definitions = "definition.csv"; - static const std::string default_provinces = "provinces.bmp"; - static const std::string default_positions = "positions.txt"; - static const std::string default_terrain = "terrain.bmp"; - static const std::string default_rivers = "rivers.bmp"; - static const std::string default_terrain_definition = "terrain.txt"; - static const std::string default_tree_definition = "trees.txt"; - static const std::string default_continent = "continent.txt"; - static const std::string default_adjacencies = "adjacencies.csv"; - static const std::string default_region = "region.txt"; - static const std::string default_region_sea = "region_sea.txt"; - static const std::string default_province_flag_sprite = "province_flag_sprites"; - - const v2script::Parser parser = _parse_defines(lookup_file(map_directory / defaults_filename)); - - std::vector<std::string_view> water_province_identifiers; - -#define APPLY_TO_MAP_PATHS(F) \ - F(definitions) F(provinces) F(positions) F(terrain) F(rivers) \ - F(terrain_definition) F(tree_definition) F(continent) F(adjacencies) \ - F(region) F(region_sea) F(province_flag_sprite) - -#define MAP_PATH_VAR(X) std::string_view X = default_##X; - APPLY_TO_MAP_PATHS(MAP_PATH_VAR) -#undef MAP_PATH_VAR - - bool ret = expect_dictionary_keys( - "max_provinces", ONE_EXACTLY, - expect_uint( - [&map](uint64_t val) -> bool { - if (Province::NULL_INDEX < val && val <= Province::MAX_INDEX) { - return map.set_max_provinces(val); - } - Logger::error("Invalid max province count ", val, " (out of valid range ", Province::NULL_INDEX, " < max_provinces <= ", Province::MAX_INDEX, ")"); - return false; - } - ), - "sea_starts", ONE_EXACTLY, - expect_list_reserve_length( - water_province_identifiers, - expect_identifier( - [&water_province_identifiers](std::string_view identifier) -> bool { - water_province_identifiers.push_back(identifier); - return true; - } - ) - ), - -#define MAP_PATH_DICT_ENTRY(X) \ - #X, ONE_EXACTLY, expect_string(assign_variable_callback(X)), - APPLY_TO_MAP_PATHS(MAP_PATH_DICT_ENTRY) -#undef MAP_PATH_DICT_ENTRY - -#undef APPLY_TO_MAP_PATHS - - "border_heights", ZERO_OR_ONE, success_callback, - "terrain_sheet_heights", ZERO_OR_ONE, success_callback, - "tree", ZERO_OR_ONE, success_callback, - "border_cutoff", ZERO_OR_ONE, success_callback - )(parser.get_file_node()); - - if (!ret) { - Logger::error("Failed to load map default file!"); - } - - if (!map.load_province_definitions(_parse_csv(lookup_file(map_directory / definitions)).get_lines())) { - Logger::error("Failed to load province definitions file!"); - ret = false; - } - - if (!map.set_water_province_list(water_province_identifiers)) { - Logger::error("Failed to set water provinces!"); - ret = false; - } - map.lock_water_provinces(); - - return ret; -} - -bool Dataloader::load_defines(GameManager& game_manager) const { - static const std::filesystem::path good_file = "common/goods.txt"; - static const std::filesystem::path pop_type_directory = "poptypes"; - static const std::filesystem::path graphical_culture_type_file = "common/graphicalculturetype.txt"; - static const std::filesystem::path culture_file = "common/cultures.txt"; - static const std::filesystem::path religion_file = "common/religion.txt"; - static const std::filesystem::path map_directory = "map"; - - bool ret = true; - - if (!game_manager.good_manager.load_good_file(_parse_defines(lookup_file(good_file)).get_file_node())) { - Logger::error("Failed to load goods!"); - ret = false; - } - if (!_load_pop_types(game_manager.pop_manager, pop_type_directory)) { - Logger::error("Failed to load pop types!"); - ret = false; - } - if (!game_manager.pop_manager.culture_manager.load_graphical_culture_type_file(_parse_defines(lookup_file(graphical_culture_type_file)).get_file_node())) { - Logger::error("Failed to load graphical culture types!"); - ret = false; - } - if (!game_manager.pop_manager.culture_manager.load_culture_file(_parse_defines(lookup_file(culture_file)).get_file_node())) { - Logger::error("Failed to load cultures!"); - ret = false; - } - if (!game_manager.pop_manager.religion_manager.load_religion_file(_parse_defines(lookup_file(religion_file)).get_file_node())) { - Logger::error("Failed to load religions!"); - ret = false; - } - if (!_load_map_dir(game_manager.map, map_directory)) { - Logger::error("Failed to load map!"); - ret = false; - } - - return ret; -} - -bool Dataloader::load_pop_history(GameManager& game_manager, std::filesystem::path const& path) const { - return apply_to_files_in_dir(path, - [&game_manager](std::filesystem::path const& file) -> bool { - return expect_dictionary( - [&game_manager](std::string_view province_key, ast::NodeCPtr province_node) -> bool { - Province* province = game_manager.map.get_province_by_identifier(province_key); - if (province == nullptr) { - Logger::error("Invalid province id: ", province_key); - return false; - } - return province->load_pop_list(game_manager.pop_manager, province_node); - } - )(_parse_defines(file).get_file_node()); - } - ); -} diff --git a/src/openvic/dataloader/Dataloader.hpp b/src/openvic/dataloader/Dataloader.hpp deleted file mode 100644 index f723803..0000000 --- a/src/openvic/dataloader/Dataloader.hpp +++ /dev/null @@ -1,35 +0,0 @@ -#pragma once - -#include <filesystem> -#include <functional> -#include <vector> - -namespace OpenVic { - struct GameManager; - struct PopManager; - struct Map; - - class Dataloader { - std::vector<std::filesystem::path> roots; - - bool _load_pop_types(PopManager& pop_manager, std::filesystem::path const& pop_type_directory) const; - bool _load_map_dir(Map& map, std::filesystem::path const& map_directory) const; - - public: - Dataloader() = default; - - /* In reverse-load order, so base defines first and final loaded mod last */ - bool set_roots(std::vector<std::filesystem::path> new_roots); - - std::filesystem::path lookup_file(std::filesystem::path const& path) const; - static const std::filesystem::path TXT; - std::vector<std::filesystem::path> lookup_files_in_dir(std::filesystem::path const& path, - std::filesystem::path const* extension = &TXT) const; - bool apply_to_files_in_dir(std::filesystem::path const& path, - std::function<bool(std::filesystem::path const&)> callback, - std::filesystem::path const* extension = &TXT) const; - - bool load_defines(GameManager& game_manager) const; - bool load_pop_history(GameManager& game_manager, std::filesystem::path const& path) const; - }; -} diff --git a/src/openvic/dataloader/NodeTools.cpp b/src/openvic/dataloader/NodeTools.cpp deleted file mode 100644 index 499527f..0000000 --- a/src/openvic/dataloader/NodeTools.cpp +++ /dev/null @@ -1,256 +0,0 @@ -#include "NodeTools.hpp" - -#include <charconv> - -using namespace OpenVic; -using namespace OpenVic::NodeTools; - -template<typename T> -static node_callback_t _expect_type(std::function<bool(T const&)> callback) { - return [callback](ast::NodeCPtr node) -> bool { - if (node != nullptr) { - T const* cast_node = node->cast_to<T>(); - if (cast_node != nullptr) { - return callback(*cast_node); - } - Logger::error("Invalid node type ", node->get_type(), " when expecting ", T::get_type_static()); - } else { - Logger::error("Null node when expecting ", T::get_type_static()); - } - return false; - }; -} - -template<typename T = ast::AbstractStringNode> -requires(std::derived_from<T, ast::AbstractStringNode>) -static std::function<bool(T const&)> abstract_string_node_callback(std::function<bool(std::string_view)> callback) { - return [callback](T const& node) -> bool { - return callback(node._name); - }; -} - -node_callback_t NodeTools::expect_identifier(std::function<bool(std::string_view)> callback) { - return _expect_type<ast::IdentifierNode>(abstract_string_node_callback<ast::IdentifierNode>(callback)); -} - -node_callback_t NodeTools::expect_string(std::function<bool(std::string_view)> callback) { - return _expect_type<ast::StringNode>(abstract_string_node_callback<ast::StringNode>(callback)); -} - -node_callback_t NodeTools::expect_identifier_or_string(std::function<bool(std::string_view)> callback) { - return [callback](ast::NodeCPtr node) -> bool { - if (node != nullptr) { - ast::AbstractStringNode const* cast_node = node->cast_to<ast::IdentifierNode>(); - if (cast_node == nullptr) { - cast_node = node->cast_to<ast::StringNode>(); - } - if (cast_node != nullptr) { - return abstract_string_node_callback(callback)(*cast_node); - } - Logger::error("Invalid node type ", node->get_type(), " when expecting ", ast::IdentifierNode::get_type_static(), " or ", ast::StringNode::get_type_static()); - } else { - Logger::error("Null node when expecting ", ast::IdentifierNode::get_type_static(), " or ", ast::StringNode::get_type_static()); - } - return false; - }; -} - -node_callback_t NodeTools::expect_bool(std::function<bool(bool)> callback) { - return expect_identifier( - [callback](std::string_view identifier) -> bool { - if (identifier == "yes") { - return callback(true); - } else if (identifier == "no") { - return callback(false); - } - Logger::error("Invalid bool identifier text: ", identifier); - return false; - } - ); -} - -node_callback_t NodeTools::expect_int(std::function<bool(int64_t)> callback) { - return expect_identifier( - [callback](std::string_view identifier) -> bool { - bool successful = false; - const int64_t val = StringUtils::string_to_int64(identifier, &successful, 10); - if (successful) { - return callback(val); - } - Logger::error("Invalid int identifier text: ", identifier); - return false; - } - ); -} - -node_callback_t NodeTools::expect_uint(std::function<bool(uint64_t)> callback) { - return expect_identifier( - [callback](std::string_view identifier) -> bool { - bool successful = false; - const uint64_t val = StringUtils::string_to_uint64(identifier, &successful, 10); - if (successful) { - return callback(val); - } - Logger::error("Invalid uint identifier text: ", identifier); - return false; - } - ); -} - -node_callback_t NodeTools::expect_fixed_point(std::function<bool(FP)> callback) { - return expect_identifier( - [callback](std::string_view identifier) -> bool { - bool successful = false; - const FP val = FP::parse(identifier.data(), identifier.length(), &successful); - if (successful) { - return callback(val); - } - Logger::error("Invalid fixed point identifier text: ", identifier); - return false; - } - ); -} - -node_callback_t NodeTools::expect_colour(std::function<bool(colour_t)> callback) { - return [callback](ast::NodeCPtr node) -> bool { - colour_t col = NULL_COLOUR; - uint32_t components = 0; - bool ret = expect_list_of_length(3, - expect_fixed_point( - [&col, &components](FP val) -> bool { - components++; - col <<= 8; - if (val < 0 || val > 255) { - Logger::error("Invalid colour component: ", val); - return false; - } else { - if (val <= 1) val *= 255; - col |= val.to_int32_t(); - return true; - } - } - ) - )(node); - ret &= callback(col << 8 * (3 - components)); - return ret; - }; -} - -node_callback_t NodeTools::expect_date(std::function<bool(Date)> callback) { - return expect_identifier( - [callback](std::string_view identifier) -> bool { - bool successful = false; - const Date date = Date::from_string(identifier, &successful); - if (successful) { - return callback(date); - } - Logger::error("Invalid date identifier text: ", identifier); - return false; - } - ); -} - -node_callback_t NodeTools::expect_assign(key_value_callback_t callback) { - return _expect_type<ast::AssignNode>( - [callback](ast::AssignNode const& assign_node) -> bool { - return callback(assign_node._name, assign_node._initializer.get()); - } - ); -} - -node_callback_t NodeTools::expect_list_and_length(length_callback_t length_callback, node_callback_t callback) { - return _expect_type<ast::AbstractListNode>( - [length_callback, callback](ast::AbstractListNode const& list_node) -> bool { - std::vector<ast::NodeUPtr> const& list = list_node._statements; - bool ret = true; - size_t size = length_callback(list.size()); - if (size > list.size()) { - Logger::error("Trying to read more values than the list contains: ", size, " > ", list.size()); - size = list.size(); - ret = false; - } - std::for_each(list.begin(), list.begin() + size, - [callback, &ret](ast::NodeUPtr const& sub_node) -> void { - ret &= callback(sub_node.get()); - } - ); - return ret; - } - ); -} - -node_callback_t NodeTools::expect_list_of_length(size_t length, node_callback_t callback) { - return [length, callback](ast::NodeCPtr node) -> bool { - bool ret = true; - ret &= expect_list_and_length( - [length, &ret](size_t size) -> size_t { - if (size != length) { - Logger::error("List length ", size, " does not match expected length ", length); - ret = false; - if (length < size) return length; - } - return size; - }, - callback - )(node); - return ret; - }; -} - -node_callback_t NodeTools::expect_list(node_callback_t callback) { - return expect_list_and_length(default_length_callback, callback); -} - -node_callback_t NodeTools::expect_dictionary_and_length(length_callback_t length_callback, key_value_callback_t callback) { - return expect_list_and_length(length_callback, expect_assign(callback)); -} - -node_callback_t NodeTools::expect_dictionary(key_value_callback_t callback) { - return expect_dictionary_and_length(default_length_callback, callback); -} - -node_callback_t NodeTools::_expect_dictionary_keys_and_length(length_callback_t length_callback, bool allow_other_keys, key_map_t&& key_map) { - return [length_callback, allow_other_keys, key_map = std::move(key_map)](ast::NodeCPtr node) mutable -> bool { - bool ret = expect_dictionary_and_length( - length_callback, - [&key_map, allow_other_keys](std::string_view key, ast::NodeCPtr value) -> bool { - const key_map_t::iterator it = key_map.find(key); - if (it == key_map.end()) { - if (allow_other_keys) return true; - Logger::error("Invalid dictionary key: ", key); - return false; - } - dictionary_entry_t& entry = it->second; - if (++entry.count > 1 && !entry.can_repeat()) { - Logger::error("Invalid repeat of dictionary key: ", key); - return false; - } - return entry.callback(value); - } - )(node); - for (key_map_t::value_type const& key_entry : key_map) { - dictionary_entry_t const& entry = key_entry.second; - if (entry.must_appear() && entry.count < 1) { - Logger::error("Mandatory dictionary key not present: ", key_entry.first); - ret = false; - } - } - return ret; - }; -} - -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; - } - Logger::error("Empty identifier or string"); - return false; - } - ) - ); -} diff --git a/src/openvic/dataloader/NodeTools.hpp b/src/openvic/dataloader/NodeTools.hpp deleted file mode 100644 index daea8ce..0000000 --- a/src/openvic/dataloader/NodeTools.hpp +++ /dev/null @@ -1,161 +0,0 @@ -#pragma once - -#include <map> - -#include "openvic/types/Colour.hpp" -#include "openvic/types/Date.hpp" -#include "openvic/types/fixed_point/FP.hpp" - -#include <openvic-dataloader/v2script/AbstractSyntaxTree.hpp> - -namespace OpenVic { - namespace ast = ovdl::v2script::ast; - - namespace NodeTools { - - using node_callback_t = std::function<bool(ast::NodeCPtr)>; - constexpr bool success_callback(ast::NodeCPtr) { return true; } - - using key_value_callback_t = std::function<bool(std::string_view, ast::NodeCPtr)>; - - node_callback_t expect_identifier(std::function<bool(std::string_view)> callback); - node_callback_t expect_string(std::function<bool(std::string_view)> callback); - node_callback_t expect_identifier_or_string(std::function<bool(std::string_view)> callback); - node_callback_t expect_bool(std::function<bool(bool)> callback); - node_callback_t expect_int(std::function<bool(int64_t)> callback); - node_callback_t expect_uint(std::function<bool(uint64_t)> callback); - node_callback_t expect_fixed_point(std::function<bool(FP)> callback); - node_callback_t expect_colour(std::function<bool(colour_t)> callback); - node_callback_t expect_date(std::function<bool(Date)> callback); - node_callback_t expect_assign(key_value_callback_t callback); - - using length_callback_t = std::function<size_t(size_t)>; - constexpr size_t default_length_callback(size_t size) { return size; }; - - node_callback_t expect_list_and_length(length_callback_t length_callback, node_callback_t callback); - node_callback_t expect_list_of_length(size_t length, node_callback_t callback); - node_callback_t expect_list(node_callback_t callback); - - node_callback_t expect_dictionary_and_length(length_callback_t length_callback, key_value_callback_t callback); - node_callback_t expect_dictionary(key_value_callback_t callback); - - struct dictionary_entry_t { - const enum class expected_count_t : uint8_t { - _MUST_APPEAR = 0b01, - _CAN_REPEAT = 0b10, - - ZERO_OR_ONE = 0, - ONE_EXACTLY = _MUST_APPEAR, - ZERO_OR_MORE = _CAN_REPEAT, - ONE_OR_MORE = _MUST_APPEAR | _CAN_REPEAT - } expected_count; - const node_callback_t callback; - size_t count; - - dictionary_entry_t(expected_count_t new_expected_count, node_callback_t new_callback) - : expected_count { new_expected_count }, callback { new_callback }, count { 0 } {} - - constexpr bool must_appear() const { - return static_cast<uint8_t>(expected_count) & static_cast<uint8_t>(expected_count_t::_MUST_APPEAR); - } - constexpr bool can_repeat() const { - return static_cast<uint8_t>(expected_count) & static_cast<uint8_t>(expected_count_t::_CAN_REPEAT); - } - }; - using enum dictionary_entry_t::expected_count_t; - using key_map_t = std::map<std::string, dictionary_entry_t, std::less<void>>; - - constexpr struct allow_other_keys_t {} ALLOW_OTHER_KEYS; - - node_callback_t _expect_dictionary_keys_and_length(length_callback_t length_callback, bool allow_other_keys, key_map_t&& key_map); - - template<typename... Args> - node_callback_t _expect_dictionary_keys_and_length(length_callback_t length_callback, - bool allow_other_keys, key_map_t&& key_map, - const std::string_view key, dictionary_entry_t::expected_count_t expected_count, node_callback_t callback, - Args... args) { - if (key_map.find(key) == key_map.end()) { - key_map.emplace(key, dictionary_entry_t { expected_count, callback }); - } else { - Logger::error("Duplicate expected dictionary key: ", key); - } - return _expect_dictionary_keys_and_length(length_callback, allow_other_keys, std::move(key_map), args...); - } - - template<typename... Args> - node_callback_t expect_dictionary_keys_and_length(length_callback_t length_callback, - const std::string_view key, dictionary_entry_t::expected_count_t expected_count, node_callback_t callback, - Args... args) { - return _expect_dictionary_keys_and_length(length_callback, false, {}, key, expected_count, callback, args...); - } - - template<typename... Args> - node_callback_t expect_dictionary_keys_and_length(length_callback_t length_callback, - allow_other_keys_t, Args... args) { - return _expect_dictionary_keys_and_length(length_callback, true, {}, args...); - } - - template<typename... Args> - node_callback_t expect_dictionary_keys(Args... args) { - return expect_dictionary_keys_and_length(default_length_callback, args...); - } - - template<typename T> - concept Reservable = requires(T& t) { - { t.size() } -> std::same_as<size_t>; - t.reserve( size_t {} ); - }; - template<Reservable T> - node_callback_t expect_list_reserve_length(T& t, node_callback_t callback) { - return expect_list_and_length( - [&t](size_t size) -> size_t { - t.reserve(t.size() + size); - return size; - }, - callback - ); - } - template<Reservable T> - node_callback_t expect_dictionary_reserve_length(T& t, key_value_callback_t callback) { - return expect_list_reserve_length(t, expect_assign(callback)); - } - - node_callback_t name_list_callback(std::vector<std::string>& list); - - template<typename T> - std::function<bool(T)> assign_variable_callback(T& var) { - return [&var](T val) -> bool { - var = val; - return true; - }; - } - - template<typename T> - requires(std::integral<T>) - std::function<bool(uint64_t)> assign_variable_callback_uint(const std::string_view name, T& var) { - return [&var, name](uint64_t val) -> bool { - if (val <= std::numeric_limits<T>::max()) { - var = val; - return true; - } - Logger::error("Invalid ", name, ": ", val, " (valid range: [0, ", static_cast<uint64_t>(std::numeric_limits<T>::max()), "])"); - return false; - }; - } - - template<typename T> - requires(std::integral<T>) - std::function<bool(int64_t)> assign_variable_callback_int(const std::string_view name, T& var) { - return [&var, name](int64_t val) -> bool { - if (std::numeric_limits<T>::lowest() <= val && val <= std::numeric_limits<T>::max()) { - var = val; - return true; - } - Logger::error("Invalid ", name, ": ", val, " (valid range: [", - static_cast<int64_t>(std::numeric_limits<T>::lowest()), ", ", - static_cast<uint64_t>(std::numeric_limits<T>::max()), "])"); - return false; - }; - } - } -} diff --git a/src/openvic/economy/Good.cpp b/src/openvic/economy/Good.cpp deleted file mode 100644 index 8ecaae0..0000000 --- a/src/openvic/economy/Good.cpp +++ /dev/null @@ -1,176 +0,0 @@ -#include "Good.hpp" - -#include <cassert> - -using namespace OpenVic; -using namespace OpenVic::NodeTools; - -GoodCategory::GoodCategory(const std::string_view new_identifier) : HasIdentifier { new_identifier } {} - -Good::Good(const std::string_view new_identifier, colour_t new_colour, GoodCategory const& new_category, price_t new_base_price, - bool new_available_from_start, bool new_tradeable, bool new_money, bool new_overseas_penalty) - : HasIdentifierAndColour { new_identifier, new_colour, true }, - category { new_category }, - base_price { new_base_price }, - available_from_start { new_available_from_start }, - tradeable { new_tradeable }, - money { new_money }, - overseas_penalty { new_overseas_penalty } { - assert(base_price > NULL_PRICE); -} - -GoodCategory const& Good::get_category() const { - return category; -} - -Good::price_t Good::get_base_price() const { - return base_price; -} - -Good::price_t Good::get_price() const { - return price; -} - -bool Good::get_available_from_start() const { - return available_from_start; -} - -bool Good::get_available() const { - return available; -} - -bool Good::get_tradeable() const { - return tradeable; -} - -bool Good::get_money() const { - return money; -} - -bool Good::get_overseas_penalty() { - return overseas_penalty; -} - -void Good::reset_to_defaults() { - available = available_from_start; - price = base_price; -} - -GoodManager::GoodManager() : good_categories { "good categories" }, goods { "goods" } {} - -bool GoodManager::add_good_category(const std::string_view identifier) { - if (identifier.empty()) { - Logger::error("Invalid good category identifier - empty!"); - return false; - } - return good_categories.add_item({ identifier }); -} - -void GoodManager::lock_good_categories() { - good_categories.lock(); -} - -GoodCategory const* GoodManager::get_good_category_by_identifier(const std::string_view identifier) const { - return good_categories.get_item_by_identifier(identifier); -} - -size_t GoodManager::get_good_category_count() const { - return good_categories.size(); -} - -std::vector<GoodCategory> const& GoodManager::get_good_categories() const { - return good_categories.get_items(); -} - -bool GoodManager::add_good(const std::string_view identifier, colour_t colour, GoodCategory const* category, - Good::price_t base_price, bool available_from_start, bool tradeable, bool money, bool overseas_penalty) { - if (identifier.empty()) { - Logger::error("Invalid good identifier - empty!"); - return false; - } - if (colour > MAX_COLOUR_RGB) { - Logger::error("Invalid good colour for ", identifier, ": ", colour_to_hex_string(colour)); - return false; - } - if (category == nullptr) { - Logger::error("Invalid good category for ", identifier, ": null"); - return false; - } - if (base_price <= Good::NULL_PRICE) { - Logger::error("Invalid base price for ", identifier, ": ", base_price); - return false; - } - return goods.add_item({ identifier, colour, *category, base_price, available_from_start, tradeable, money, overseas_penalty }); -} - -void GoodManager::lock_goods() { - goods.lock(); -} - -Good const* GoodManager::get_good_by_index(size_t index) const { - return goods.get_item_by_index(index); -} - -Good const* GoodManager::get_good_by_identifier(const std::string_view identifier) const { - return goods.get_item_by_identifier(identifier); -} - -size_t GoodManager::get_good_count() const { - return goods.size(); -} - -std::vector<Good> const& GoodManager::get_goods() const { - return goods.get_items(); -} - -void GoodManager::reset_to_defaults() { - for (Good& good : goods.get_items()) - good.reset_to_defaults(); -} - -bool GoodManager::load_good_file(ast::NodeCPtr root) { - size_t total_expected_goods = 0; - bool ret = expect_dictionary_reserve_length( - good_categories, - [this, &total_expected_goods](std::string_view key, ast::NodeCPtr value) -> bool { - bool ret = expect_list_and_length( - [&total_expected_goods](size_t size) -> size_t { - total_expected_goods += size; - return 0; - }, - success_callback - )(value); - ret &= add_good_category(key); - return ret; - } - )(root); - lock_good_categories(); - goods.reserve(goods.size() + total_expected_goods); - ret &= expect_dictionary( - [this](std::string_view good_category_key, ast::NodeCPtr good_category_value) -> bool { - GoodCategory const* good_category = get_good_category_by_identifier(good_category_key); - - return expect_dictionary( - [this, good_category](std::string_view key, ast::NodeCPtr value) -> bool { - colour_t colour = NULL_COLOUR; - Good::price_t base_price; - bool available_from_start, tradeable = true; - bool money, overseas_penalty = false; - - bool ret = expect_dictionary_keys( - "color", ONE_EXACTLY, expect_colour(assign_variable_callback(colour)), - "cost", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(base_price)), - "available_from_start", ZERO_OR_ONE, expect_bool(assign_variable_callback(available_from_start)), - "tradeable", ZERO_OR_ONE, expect_bool(assign_variable_callback(tradeable)), - "money", ZERO_OR_ONE, expect_bool(assign_variable_callback(money)), - "overseas_penalty", ZERO_OR_ONE, expect_bool(assign_variable_callback(overseas_penalty)) - )(value); - ret &= add_good(key, colour, good_category, base_price, available_from_start, tradeable, money, overseas_penalty); - return ret; - } - )(good_category_value); - } - )(root); - lock_goods(); - return ret; -} diff --git a/src/openvic/economy/Good.hpp b/src/openvic/economy/Good.hpp deleted file mode 100644 index f04c9b2..0000000 --- a/src/openvic/economy/Good.hpp +++ /dev/null @@ -1,86 +0,0 @@ -#pragma once - -#include "openvic/types/IdentifierRegistry.hpp" -#include "openvic/dataloader/NodeTools.hpp" - -namespace OpenVic { - struct GoodManager; - - struct GoodCategory : HasIdentifier { - friend struct GoodManager; - - private: - GoodCategory(const std::string_view new_identifier); - - public: - GoodCategory(GoodCategory&&) = default; - }; - - /* REQUIREMENTS: - * - * ECON-3 , ECON-4 , ECON-5 , ECON-6 , ECON-7 , ECON-8 , ECON-9 , ECON-10, ECON-11, ECON-12, ECON-13, ECON-14, - * ECON-15, ECON-16, ECON-17, ECON-18, ECON-19, ECON-20, ECON-21, ECON-22, ECON-23, ECON-24, ECON-25, ECON-26, - * ECON-27, ECON-28, ECON-29, ECON-30, ECON-31, ECON-32, ECON-33, ECON-34, ECON-35, ECON-36, ECON-37, ECON-38, - * ECON-39, ECON-40, ECON-41, ECON-42, ECON-43, ECON-44, ECON-45, ECON-46, ECON-47, ECON-48, ECON-49, ECON-50 - * - * ECON-123, ECON-124, ECON-125, ECON-126, ECON-127, ECON-128, ECON-129, ECON-130, ECON-131, ECON-132, ECON-133, ECON-134, - * ECON-135, ECON-136, ECON-137, ECON-138, ECON-139, ECON-140, ECON-141, ECON-142, ECON-234, ECON-235, ECON-236, ECON-237, - * ECON-238, ECON-239, ECON-240, ECON-241, ECON-242, ECON-243, ECON-244, ECON-245, ECON-246, ECON-247, ECON-248, ECON-249, - * ECON-250, ECON-251, ECON-252, ECON-253, ECON-254, ECON-255, ECON-256, ECON-257, ECON-258, ECON-259, ECON-260, ECON-261 - */ - struct Good : HasIdentifierAndColour { - friend struct GoodManager; - - using price_t = FP; - static constexpr price_t NULL_PRICE = FP::_0(); - - private: - GoodCategory const& category; - const price_t base_price; - price_t price; - const bool available_from_start, tradeable, money, overseas_penalty; - bool available; - - Good(const std::string_view new_identifier, colour_t new_colour, GoodCategory const& new_category, price_t new_base_price, - bool new_available_from_start, bool new_tradeable, bool new_money, bool new_overseas_penalty); - - public: - Good(Good&&) = default; - - GoodCategory const& get_category() const; - price_t get_base_price() const; - price_t get_price() const; - bool get_available_from_start() const; - bool get_available() const; - bool get_tradeable() const; - bool get_money() const; - bool get_overseas_penalty(); - void reset_to_defaults(); - }; - - struct GoodManager { - private: - IdentifierRegistry<GoodCategory> good_categories; - IdentifierRegistry<Good> goods; - - public: - GoodManager(); - - bool add_good_category(const std::string_view identifier); - void lock_good_categories(); - GoodCategory const* get_good_category_by_identifier(const std::string_view identifier) const; - size_t get_good_category_count() const; - std::vector<GoodCategory> const& get_good_categories() const; - - bool add_good(const std::string_view identifier, colour_t colour, GoodCategory const* category, Good::price_t base_price, - bool available_from_start, bool tradeable, bool money, bool overseas_penalty); - void lock_goods(); - Good const* get_good_by_index(size_t index) const; - Good const* get_good_by_identifier(const std::string_view identifier) const; - size_t get_good_count() const; - std::vector<Good> const& get_goods() const; - - void reset_to_defaults(); - bool load_good_file(ast::NodeCPtr root); - }; -} diff --git a/src/openvic/map/Building.cpp b/src/openvic/map/Building.cpp deleted file mode 100644 index 72bccc1..0000000 --- a/src/openvic/map/Building.cpp +++ /dev/null @@ -1,135 +0,0 @@ -#include "Building.hpp" - -#include <cassert> - -#include "openvic/map/Province.hpp" -#include "openvic/utility/Logger.hpp" - -using namespace OpenVic; - -Building::Building(BuildingType const& new_type) - : HasIdentifier { new_type.get_identifier() }, - type { new_type } {} - -bool Building::_can_expand() const { - return level < type.get_max_level(); -} - -BuildingType const& Building::get_type() const { - return type; -} - -Building::level_t Building::get_level() const { - return level; -} - -Building::ExpansionState Building::get_expansion_state() const { - return expansion_state; -} - -Date const& Building::get_start_date() const { - return start; -} - -Date const& Building::get_end_date() const { - return end; -} - -float Building::get_expansion_progress() const { - return expansion_progress; -} - -bool Building::expand() { - if (expansion_state == ExpansionState::CanExpand) { - expansion_state = ExpansionState::Preparing; - expansion_progress = 0.0f; - return true; - } - return false; -} - -/* REQUIREMENTS: - * MAP-71, MAP-74, MAP-77 - */ -void Building::update_state(Date const& today) { - switch (expansion_state) { - case ExpansionState::Preparing: - start = today; - end = start + type.get_build_time(); - break; - case ExpansionState::Expanding: - expansion_progress = static_cast<double>(today - start) / static_cast<double>(end - start); - break; - default: expansion_state = _can_expand() ? ExpansionState::CanExpand : ExpansionState::CannotExpand; - } -} - -void Building::tick(Date const& today) { - if (expansion_state == ExpansionState::Preparing) { - expansion_state = ExpansionState::Expanding; - } - if (expansion_state == ExpansionState::Expanding) { - if (end <= today) { - level++; - expansion_state = ExpansionState::CannotExpand; - } - } -} - -BuildingType::BuildingType(const std::string_view new_identifier, Building::level_t new_max_level, Timespan new_build_time) - : HasIdentifier { new_identifier }, - max_level { new_max_level }, - build_time { new_build_time } { - assert(max_level >= 0); - assert(build_time >= 0); -} - -Building::level_t BuildingType::get_max_level() const { - return max_level; -} - -Timespan BuildingType::get_build_time() const { - return build_time; -} - -BuildingManager::BuildingManager() : building_types { "building types" } {} - -bool BuildingManager::add_building_type(const std::string_view identifier, Building::level_t max_level, Timespan build_time) { - if (identifier.empty()) { - Logger::error("Invalid building type identifier - empty!"); - return false; - } - if (max_level < 0) { - Logger::error("Invalid building type max level for ", identifier, ": ", max_level); - return false; - } - if (build_time < 0) { - Logger::error("Invalid building type build time for ", identifier, ": ", build_time); - return false; - } - return building_types.add_item({ identifier, max_level, build_time }); -} - -void BuildingManager::lock_building_types() { - building_types.lock(); -} - -BuildingType const* BuildingManager::get_building_type_by_identifier(const std::string_view identifier) const { - return building_types.get_item_by_identifier(identifier); -} - -bool BuildingManager::generate_province_buildings(Province& province) const { - province.reset_buildings(); - if (!building_types.is_locked()) { - Logger::error("Cannot generate buildings until building types are locked!"); - return false; - } - bool ret = true; - if (!province.is_water()) { - for (BuildingType const& type : building_types.get_items()) { - ret &= province.add_building({ type }); - } - } - province.lock_buildings(); - return ret; -} diff --git a/src/openvic/map/Building.hpp b/src/openvic/map/Building.hpp deleted file mode 100644 index d1c0348..0000000 --- a/src/openvic/map/Building.hpp +++ /dev/null @@ -1,86 +0,0 @@ -#pragma once - -#include <vector> - -#include "openvic/types/Date.hpp" -#include "openvic/types/IdentifierRegistry.hpp" - -namespace OpenVic { - - struct BuildingManager; - struct BuildingType; - - /* REQUIREMENTS: - * MAP-11, MAP-72, MAP-73 - * MAP-12, MAP-75, MAP-76 - * MAP-13, MAP-78, MAP-79 - */ - struct Building : HasIdentifier { - friend struct BuildingManager; - - using level_t = int8_t; - - enum class ExpansionState { - CannotExpand, - CanExpand, - Preparing, - Expanding - }; - - private: - BuildingType const& type; - level_t level = 0; - ExpansionState expansion_state = ExpansionState::CannotExpand; - Date start, end; - float expansion_progress; - - Building(BuildingType const& new_type); - - bool _can_expand() const; - - public: - Building(Building&&) = default; - - BuildingType const& get_type() const; - level_t get_level() const; - ExpansionState get_expansion_state() const; - Date const& get_start_date() const; - Date const& get_end_date() const; - float get_expansion_progress() const; - - bool expand(); - void update_state(Date const& today); - void tick(Date const& today); - }; - - struct BuildingType : HasIdentifier { - friend struct BuildingManager; - - private: - const Building::level_t max_level; - const Timespan build_time; - - BuildingType(const std::string_view new_identifier, Building::level_t new_max_level, Timespan new_build_time); - - public: - BuildingType(BuildingType&&) = default; - - Building::level_t get_max_level() const; - Timespan get_build_time() const; - }; - - struct Province; - - struct BuildingManager { - private: - IdentifierRegistry<BuildingType> building_types; - - public: - BuildingManager(); - - bool add_building_type(const std::string_view identifier, Building::level_t max_level, Timespan build_time); - void lock_building_types(); - BuildingType const* get_building_type_by_identifier(const std::string_view identifier) const; - bool generate_province_buildings(Province& province) const; - }; -} diff --git a/src/openvic/map/Map.cpp b/src/openvic/map/Map.cpp deleted file mode 100644 index 6375691..0000000 --- a/src/openvic/map/Map.cpp +++ /dev/null @@ -1,529 +0,0 @@ -#include "Map.hpp" - -#include <cassert> -#include <unordered_set> - -#include "openvic/economy/Good.hpp" -#include "openvic/utility/Logger.hpp" - -using namespace OpenVic; - -Mapmode::Mapmode(const std::string_view new_identifier, index_t new_index, colour_func_t new_colour_func) - : HasIdentifier { new_identifier }, - index { new_index }, - colour_func { new_colour_func } { - assert(colour_func != nullptr); -} - -const Mapmode Mapmode::ERROR_MAPMODE { "mapmode_error", 0, - [](Map const& map, Province const& province) -> colour_t { return 0xFFFF0000; } }; - -Mapmode::index_t Mapmode::get_index() const { - return index; -} - -colour_t Mapmode::get_colour(Map const& map, Province const& province) const { - return colour_func ? colour_func(map, province) : NULL_COLOUR; -} - -Map::Map() : provinces { "provinces" }, - regions { "regions" }, - mapmodes { "mapmodes" } {} - -bool Map::add_province(const std::string_view identifier, colour_t colour) { - if (provinces.size() >= max_provinces) { - Logger::error("The map's province list is full - maximum number of provinces is ", max_provinces, " (this can be at most ", Province::MAX_INDEX, ")"); - return false; - } - if (identifier.empty()) { - Logger::error("Invalid province identifier - empty!"); - return false; - } - if (colour == NULL_COLOUR || colour > MAX_COLOUR_RGB) { - Logger::error("Invalid province colour for ", identifier, ": ", colour_to_hex_string(colour)); - return false; - } - Province new_province { identifier, colour, static_cast<Province::index_t>(provinces.size() + 1) }; - const Province::index_t index = get_index_from_colour(colour); - if (index != Province::NULL_INDEX) { - Logger::error("Duplicate province colours: ", get_province_by_index(index)->to_string(), " and ", new_province.to_string()); - return false; - } - colour_index_map[new_province.get_colour()] = new_province.get_index(); - return provinces.add_item(std::move(new_province)); -} - -void Map::lock_provinces() { - provinces.lock(); -} - -bool Map::set_water_province(const std::string_view identifier) { - if (water_provinces.is_locked()) { - Logger::error("The map's water provinces have already been locked!"); - return false; - } - Province* province = get_province_by_identifier(identifier); - if (province == nullptr) { - Logger::error("Unrecognised water province identifier: ", identifier); - return false; - } - if (province->is_water()) { - Logger::error("Province ", identifier, " is already a water province!"); - return false; - } - if (!water_provinces.add_province(province)) { - Logger::error("Failed to add province ", identifier, " to water province set!"); - return false; - } - province->water = true; - return true; -} - -bool Map::set_water_province_list(std::vector<std::string_view> const& list) { - bool ret = true; - water_provinces.reserve(water_provinces.size() + list.size()); - for (std::string_view const& identifier : list) { - ret &= set_water_province(identifier); - } - return ret; -} - -void Map::lock_water_provinces() { - water_provinces.lock(); - Logger::info("Locked water provinces after registering ", water_provinces.size()); -} - -bool Map::add_region(const std::string_view identifier, std::vector<std::string_view> const& province_identifiers) { - if (identifier.empty()) { - Logger::error("Invalid region identifier - empty!"); - return false; - } - Region new_region { identifier }; - bool ret = true; - for (const std::string_view province_identifier : province_identifiers) { - Province* province = get_province_by_identifier(province_identifier); - if (province != nullptr) { - if (new_region.contains_province(province)) { - Logger::error("Duplicate province identifier ", province_identifier, " in region ", identifier); - ret = false; - } else { - size_t other_region_index = reinterpret_cast<size_t>(province->get_region()); - if (other_region_index != 0) { - other_region_index--; - if (other_region_index < regions.size()) - Logger::error("Cannot add province ", province_identifier, " to region ", identifier, " - it is already part of ", regions.get_item_by_index(other_region_index)->get_identifier()); - else - Logger::error("Cannot add province ", province_identifier, " to region ", identifier, " - it is already part of an unknown region with index ", other_region_index); - ret = false; - } else if (!new_region.add_province(province)) { - Logger::error("Failed to add province ", province_identifier, " to region ", identifier); - ret = false; - } - } - } else { - Logger::error("Invalid province identifier ", province_identifier, " for region ", identifier); - ret = false; - } - } - new_region.lock(); - if (new_region.empty()) { - Logger::error("No valid provinces in list for ", identifier); - return false; - } - - // Used to detect provinces listed in multiple regions, will - // be corrected once regions is stable (i.e. lock_regions). - Region* tmp_region_index = reinterpret_cast<Region*>(regions.size()); - for (Province* province : new_region.get_provinces()) - province->region = tmp_region_index; - ret &= regions.add_item(std::move(new_region)); - return ret; -} - -void Map::lock_regions() { - regions.lock(); - for (Region& region : regions.get_items()) - for (Province* province : region.get_provinces()) - province->region = ®ion; -} - -size_t Map::get_province_count() const { - return provinces.size(); -} - -std::vector<Province> const& Map::get_provinces() const { - return provinces.get_items(); -} - -Province* Map::get_province_by_index(Province::index_t index) { - return index != Province::NULL_INDEX ? provinces.get_item_by_index(index - 1) : nullptr; -} - -Province const* Map::get_province_by_index(Province::index_t index) const { - return index != Province::NULL_INDEX ? provinces.get_item_by_index(index - 1) : nullptr; -} - -Province* Map::get_province_by_identifier(const std::string_view identifier) { - return provinces.get_item_by_identifier(identifier); -} - -Province const* Map::get_province_by_identifier(const std::string_view identifier) const { - return provinces.get_item_by_identifier(identifier); -} - -Province::index_t Map::get_index_from_colour(colour_t colour) const { - const colour_index_map_t::const_iterator it = colour_index_map.find(colour); - if (it != colour_index_map.end()) return it->second; - return Province::NULL_INDEX; -} - -Province::index_t Map::get_province_index_at(size_t x, size_t y) const { - if (x < width && y < height) return province_shape_image[x + y * width].index; - return Province::NULL_INDEX; -} - -bool Map::set_max_provinces(Province::index_t new_max_provinces) { - if (new_max_provinces <= Province::NULL_INDEX) { - Logger::error("Trying to set max province count to an invalid value ", new_max_provinces, " (must be greater than ", Province::NULL_INDEX, ")"); - return false; - } - if (!provinces.empty() || provinces.is_locked()) { - Logger::error("Trying to set max province count to ", new_max_provinces, " after provinces have already been added and/or locked"); - return false; - } - max_provinces = new_max_provinces; - return true; -} - -Province::index_t Map::get_max_provinces() const { - return max_provinces; -} - -void Map::set_selected_province(Province::index_t index) { - if (index > get_province_count()) { - Logger::error("Trying to set selected province to an invalid index ", index, " (max index is ", get_province_count(), ")"); - selected_province = Province::NULL_INDEX; - } else { - selected_province = index; - } -} - -Province::index_t Map::get_selected_province_index() const { - return selected_province; -} - -Province const* Map::get_selected_province() const { - return get_province_by_index(get_selected_province_index()); -} - -Region* Map::get_region_by_identifier(const std::string_view identifier) { - return regions.get_item_by_identifier(identifier); -} - -Region const* Map::get_region_by_identifier(const std::string_view identifier) const { - return regions.get_item_by_identifier(identifier); -} - -size_t Map::get_region_count() const { - return regions.size(); -} - -std::vector<Region> const& Map::get_regions() const { - return regions.get_items(); -} - -static colour_t colour_at(uint8_t const* colour_data, int32_t idx) { - idx *= 3; - return (colour_data[idx] << 16) | (colour_data[idx + 1] << 8) | colour_data[idx + 2]; -} - -bool Map::generate_province_shape_image(size_t new_width, size_t new_height, uint8_t const* colour_data, - uint8_t const* terrain_data, terrain_variant_map_t const& terrain_variant_map, bool detailed_errors) { - if (!province_shape_image.empty()) { - Logger::error("Province index image has already been generated!"); - return false; - } - if (!provinces.is_locked()) { - Logger::error("Province index image cannot be generated until after provinces are locked!"); - return false; - } - if (new_width < 1 || new_height < 1) { - Logger::error("Invalid province image dimensions: ", new_width, "x", new_height); - return false; - } - if (colour_data == nullptr) { - Logger::error("Province colour data pointer is null!"); - return false; - } - if (terrain_data == nullptr) { - Logger::error("Province terrain data pointer is null!"); - return false; - } - width = new_width; - height = new_height; - province_shape_image.resize(width * height); - - std::vector<bool> province_checklist(provinces.size()); - bool ret = true; - std::unordered_set<colour_t> unrecognised_province_colours, unrecognised_terrain_colours; - - for (int32_t y = 0; y < height; ++y) { - for (int32_t x = 0; x < width; ++x) { - const int32_t idx = x + y * width; - - const colour_t terrain_colour = colour_at(terrain_data, idx); - const terrain_variant_map_t::const_iterator it = terrain_variant_map.find(terrain_colour); - if (it != terrain_variant_map.end()) province_shape_image[idx].terrain = it->second; - else { - if (unrecognised_terrain_colours.find(terrain_colour) == unrecognised_terrain_colours.end()) { - unrecognised_terrain_colours.insert(terrain_colour); - if (detailed_errors) { - Logger::error("Unrecognised terrain colour ", colour_to_hex_string(terrain_colour), - " at (", x, ", ", y, ")"); - } - } - province_shape_image[idx].terrain = 0; - } - - const colour_t province_colour = colour_at(colour_data, idx); - if (x > 0) { - const int32_t jdx = idx - 1; - if (colour_at(colour_data, jdx) == province_colour) { - province_shape_image[idx].index = province_shape_image[jdx].index; - continue; - } - } - if (y > 0) { - const int32_t jdx = idx - width; - if (colour_at(colour_data, jdx) == province_colour) { - province_shape_image[idx].index = province_shape_image[jdx].index; - continue; - } - } - 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; - continue; - } - if (unrecognised_province_colours.find(province_colour) == unrecognised_province_colours.end()) { - unrecognised_province_colours.insert(province_colour); - if (detailed_errors) { - Logger::error("Unrecognised province colour ", colour_to_hex_string(province_colour), - " at (", x, ", ", y, ")"); - } - } - province_shape_image[idx].index = Province::NULL_INDEX; - } - } - if (!unrecognised_province_colours.empty()) { - Logger::error("Province image contains ", unrecognised_province_colours.size(), " unrecognised province colours"); - ret = false; - } - if (!unrecognised_terrain_colours.empty()) { - Logger::error("Terrain image contains ", unrecognised_terrain_colours.size(), " unrecognised terrain colours"); - ret = false; - } - - size_t missing = 0; - for (size_t idx = 0; idx < province_checklist.size(); ++idx) { - if (!province_checklist[idx]) { - if (detailed_errors) { - Logger::error("Province missing from shape image: ", provinces.get_item_by_index(idx)->to_string()); - } - missing++; - } - } - if (missing > 0) { - Logger::error("Province image is missing ", missing, " province colours"); - ret = false; - } - return ret; -} - -size_t Map::get_width() const { - return width; -} - -size_t Map::get_height() const { - return height; -} - -std::vector<Map::shape_pixel_t> const& Map::get_province_shape_image() const { - return province_shape_image; -} - -bool Map::add_mapmode(const std::string_view identifier, Mapmode::colour_func_t colour_func) { - if (identifier.empty()) { - Logger::error("Invalid mapmode identifier - empty!"); - return false; - } - if (colour_func == nullptr) { - Logger::error("Mapmode colour function is null for identifier: ", identifier); - return false; - } - return mapmodes.add_item({ identifier, mapmodes.size(), colour_func }); -} - -void Map::lock_mapmodes() { - mapmodes.lock(); -} - -size_t Map::get_mapmode_count() const { - return mapmodes.size(); -} - -std::vector<Mapmode> const& Map::get_mapmodes() const { - return mapmodes.get_items(); -} - -Mapmode const* Map::get_mapmode_by_index(size_t index) const { - return mapmodes.get_item_by_index(index); -} - -Mapmode const* Map::get_mapmode_by_identifier(const std::string_view identifier) const { - return mapmodes.get_item_by_identifier(identifier); -} - -bool Map::generate_mapmode_colours(Mapmode::index_t index, uint8_t* target) const { - if (target == nullptr) { - Logger::error("Mapmode colour target pointer is null!"); - return false; - } - bool ret = true; - Mapmode const* mapmode = mapmodes.get_item_by_index(index); - if (mapmode == nullptr) { - // Not an error if mapmodes haven't yet been loaded, - // e.g. if we want to allocate the province colour - // texture before mapmodes are loaded. - if (!(mapmodes.empty() && index == 0)) { - Logger::error("Invalid mapmode index: ", index); - ret = false; - } - mapmode = &Mapmode::ERROR_MAPMODE; - } - // Skip past Province::NULL_INDEX - for (size_t i = 0; i < MAPMODE_COLOUR_SIZE; ++i) - *target++ = 0; - for (Province const& province : provinces.get_items()) { - const colour_t colour = mapmode->get_colour(*this, province); - *target++ = (colour >> 16) & FULL_COLOUR; - *target++ = (colour >> 8) & FULL_COLOUR; - *target++ = colour & FULL_COLOUR; - *target++ = (colour >> 24) & FULL_COLOUR; - } - return ret; -} - -void Map::update_highest_province_population() { - highest_province_population = 0; - for (Province const& province : provinces.get_items()) { - highest_province_population = std::max(highest_province_population, province.get_total_population()); - } -} - -Pop::pop_size_t Map::get_highest_province_population() const { - return highest_province_population; -} - -void Map::update_total_map_population() { - total_map_population = 0; - for (Province const& province : provinces.get_items()) { - total_map_population += province.get_total_population(); - } -} - -Pop::pop_size_t Map::get_total_map_population() const { - return total_map_population; -} - -bool Map::setup(GoodManager const& good_manager, BuildingManager const& building_manager, PopManager const& pop_manager) { - bool ret = true; - for (Province& province : provinces.get_items()) { - province.clear_pops(); - // Set all land provinces to have an RGO based on their index to test them - if (!province.is_water() && good_manager.get_good_count() > 0) - province.rgo = good_manager.get_good_by_index(province.get_index() % good_manager.get_good_count()); - ret &= building_manager.generate_province_buildings(province); - } - return ret; -} - -void Map::update_state(Date const& today) { - for (Province& province : provinces.get_items()) - province.update_state(today); - update_highest_province_population(); - update_total_map_population(); -} - -void Map::tick(Date const& today) { - for (Province& province : provinces.get_items()) - province.tick(today); -} - -using namespace ovdl::csv; - -static bool validate_province_definitions_header(LineObject const& header) { - static const std::vector<std::string> standard_header { "province", "red", "green", "blue" }; - for (size_t i = 0; i < standard_header.size(); ++i) { - const std::string_view val = header.get_value_for(i); - if (i == 0 && val.empty()) break; - if (val != standard_header[i]) return false; - } - return true; -} - -static bool parse_province_colour(colour_t& colour, std::array<std::string_view, 3> components) { - bool ret = true; - colour = NULL_COLOUR; - for (std::string_view& c : components) { - colour <<= 8; - if (c.ends_with('.')) c.remove_suffix(1); - bool successful = false; - uint64_t val = StringUtils::string_to_uint64(c, &successful, 10); - if (successful && val <= 255) { - colour |= val; - } else { - ret = false; - } - } - return ret; -} - -bool Map::load_province_definitions(std::vector<LineObject> const& lines) { - if (lines.empty()) { - Logger::error("No header or entries in province definition file!"); - return false; - } - { - LineObject const& header = lines.front(); - if (!validate_province_definitions_header(header)) { - Logger::error("Non-standard province definition file header - make sure this is not a province definition: ", header); - } - } - if (lines.size() <= 1) { - Logger::error("No entries in province definition file!"); - return false; - } - provinces.reserve(lines.size() - 1); - bool ret = true; - std::for_each(lines.begin() + 1, lines.end(), - [this, &ret](LineObject const& line) -> void { - const std::string_view identifier = line.get_value_for(0); - if (!identifier.empty()) { - colour_t colour; - if (!parse_province_colour(colour, { - line.get_value_for(1), - line.get_value_for(2), - line.get_value_for(3) - })) { - Logger::error("Error reading colour in province definition: ", line); - ret = false; - } - ret &= add_province(identifier, colour); - } - } - ); - lock_provinces(); - return ret; -} diff --git a/src/openvic/map/Map.hpp b/src/openvic/map/Map.hpp deleted file mode 100644 index 4684226..0000000 --- a/src/openvic/map/Map.hpp +++ /dev/null @@ -1,121 +0,0 @@ -#pragma once - -#include <functional> - -#include <openvic-dataloader/csv/LineObject.hpp> - -#include "openvic/map/Region.hpp" - -namespace OpenVic { - - struct Mapmode : HasIdentifier { - friend struct Map; - - using colour_func_t = std::function<colour_t(Map const&, Province const&)>; - using index_t = size_t; - - private: - const index_t index; - const colour_func_t colour_func; - - Mapmode(const std::string_view new_identifier, index_t new_index, colour_func_t new_colour_func); - - public: - static const Mapmode ERROR_MAPMODE; - - Mapmode(Mapmode&&) = default; - - index_t get_index() const; - colour_t get_colour(Map const& map, Province const& province) const; - }; - - struct GoodManager; - - /* REQUIREMENTS: - * MAP-4 - */ - struct Map { - using terrain_t = uint8_t; - using terrain_variant_map_t = std::map<colour_t, terrain_t>; - -#pragma pack(push, 1) - struct shape_pixel_t { - Province::index_t index; - terrain_t terrain; - }; -#pragma pack(pop) - private: - using colour_index_map_t = std::map<colour_t, Province::index_t>; - - IdentifierRegistry<Province> provinces; - IdentifierRegistry<Region> regions; - IdentifierRegistry<Mapmode> mapmodes; - ProvinceSet water_provinces; - - size_t width = 0, height = 0; - std::vector<shape_pixel_t> province_shape_image; - colour_index_map_t colour_index_map; - Province::index_t max_provinces = Province::MAX_INDEX; - Province::index_t selected_province = Province::NULL_INDEX; - - Pop::pop_size_t highest_province_population, total_map_population; - - Province::index_t get_index_from_colour(colour_t colour) const; - - public: - Map(); - - bool add_province(const std::string_view identifier, colour_t colour); - void lock_provinces(); - bool set_water_province(const std::string_view identifier); - bool set_water_province_list(std::vector<std::string_view> const& list); - void lock_water_provinces(); - bool add_region(const std::string_view identifier, std::vector<std::string_view> const& province_identifiers); - void lock_regions(); - - size_t get_province_count() const; - std::vector<Province> const& get_provinces() const; - Province* get_province_by_index(Province::index_t index); - Province const* get_province_by_index(Province::index_t index) const; - Province* get_province_by_identifier(const std::string_view identifier); - Province const* get_province_by_identifier(const std::string_view identifier) const; - Province::index_t get_province_index_at(size_t x, size_t y) const; - bool set_max_provinces(Province::index_t new_max_provinces); - Province::index_t get_max_provinces() const; - void set_selected_province(Province::index_t index); - Province::index_t get_selected_province_index() const; - Province const* get_selected_province() const; - - Region* get_region_by_identifier(const std::string_view identifier); - Region const* get_region_by_identifier(const std::string_view identifier) const; - size_t get_region_count() const; - std::vector<Region> const& get_regions() const; - - bool generate_province_shape_image(size_t new_width, size_t new_height, uint8_t const* colour_data, - uint8_t const* terrain_data, terrain_variant_map_t const& terrain_variant_map, bool detailed_errors); - size_t get_width() const; - size_t get_height() const; - std::vector<shape_pixel_t> const& get_province_shape_image() const; - - bool add_mapmode(const std::string_view identifier, Mapmode::colour_func_t colour_func); - void lock_mapmodes(); - size_t get_mapmode_count() const; - std::vector<Mapmode> const& get_mapmodes() const; - Mapmode const* get_mapmode_by_index(Mapmode::index_t index) const; - Mapmode const* get_mapmode_by_identifier(const std::string_view identifier) const; - static constexpr size_t MAPMODE_COLOUR_SIZE = 4; - bool generate_mapmode_colours(Mapmode::index_t index, uint8_t* target) const; - - bool setup(GoodManager const& good_manager, BuildingManager const& building_manager, PopManager const& pop_manager); - - void update_highest_province_population(); - Pop::pop_size_t get_highest_province_population() const; - void update_total_map_population(); - Pop::pop_size_t get_total_map_population() const; - - void update_state(Date const& today); - void tick(Date const& today); - - bool load_province_definitions(std::vector<ovdl::csv::LineObject> const& lines); - }; -} diff --git a/src/openvic/map/Province.cpp b/src/openvic/map/Province.cpp deleted file mode 100644 index cfdc263..0000000 --- a/src/openvic/map/Province.cpp +++ /dev/null @@ -1,145 +0,0 @@ -#include "Province.hpp" - -#include <cassert> -#include <iomanip> -#include <sstream> - -using namespace OpenVic; -using namespace OpenVic::NodeTools; - -Province::Province(const std::string_view new_identifier, colour_t new_colour, index_t new_index) - : HasIdentifierAndColour { new_identifier, new_colour, false }, - index { new_index }, - buildings { "buildings" } { - assert(index != NULL_INDEX); -} - -Province::index_t Province::get_index() const { - return index; -} - -Region* Province::get_region() const { - return region; -} - -bool Province::is_water() const { - return water; -} - -Province::life_rating_t Province::get_life_rating() const { - return life_rating; -} - -bool Province::add_building(Building&& building) { - return buildings.add_item(std::move(building)); -} - -void Province::lock_buildings() { - buildings.lock(false); -} - -void Province::reset_buildings() { - buildings.reset(); -} - -Building const* Province::get_building_by_identifier(const std::string_view identifier) const { - return buildings.get_item_by_identifier(identifier); -} - -size_t Province::get_building_count() const { - return buildings.size(); -} - -std::vector<Building> const& Province::get_buildings() const { - return buildings.get_items(); -} - -bool Province::expand_building(const std::string_view building_type_identifier) { - Building* building = buildings.get_item_by_identifier(building_type_identifier); - if (building == nullptr) return false; - return building->expand(); -} - -Good const* Province::get_rgo() const { - return rgo; -} - -std::string Province::to_string() const { - std::stringstream stream; - stream << "(#" << std::to_string(index) << ", " << get_identifier() << ", 0x" << colour_to_hex_string() << ")"; - return stream.str(); -} - -bool Province::load_pop_list(PopManager const& pop_manager, ast::NodeCPtr root) { - return expect_list_reserve_length( - pops, - [this, &pop_manager](ast::NodeCPtr pop_node) -> bool { - return pop_manager.load_pop_into_province(*this, pop_node); - } - )(root); -} - -bool Province::add_pop(Pop&& pop) { - if (!is_water()) { - pops.push_back(std::move(pop)); - return true; - } else { - Logger::error("Trying to add pop to water province ", get_identifier()); - return false; - } -} - -void Province::clear_pops() { - pops.clear(); -} - -size_t Province::get_pop_count() const { - return pops.size(); -} - -std::vector<Pop> const& Province::get_pops() const { - return pops; -} - -Pop::pop_size_t Province::get_total_population() const { - return total_population; -} - -distribution_t const& Province::get_pop_type_distribution() const { - return pop_types; -} - -distribution_t const& Province::get_culture_distribution() const { - return cultures; -} - -distribution_t const& Province::get_religion_distribution() const { - return religions; -} - -/* REQUIREMENTS: - * MAP-65 - */ -void Province::update_pops() { - total_population = 0; - pop_types.clear(); - cultures.clear(); - religions.clear(); - for (Pop const& pop : pops) { - total_population += pop.get_size(); - pop_types[&pop.get_type()] += pop.get_size(); - cultures[&pop.get_culture()] += pop.get_size(); - religions[&pop.get_religion()] += pop.get_size(); - } -} - -void Province::update_state(Date const& today) { - for (Building& building : buildings.get_items()) - building.update_state(today); - update_pops(); -} - -void Province::tick(Date const& today) { - for (Building& building : buildings.get_items()) - building.tick(today); -} diff --git a/src/openvic/map/Province.hpp b/src/openvic/map/Province.hpp deleted file mode 100644 index f64bca2..0000000 --- a/src/openvic/map/Province.hpp +++ /dev/null @@ -1,68 +0,0 @@ -#pragma once - -#include "openvic/map/Building.hpp" -#include "openvic/pop/Pop.hpp" - -namespace OpenVic { - struct Map; - struct Region; - struct Good; - - /* REQUIREMENTS: - * MAP-5, MAP-7, MAP-8, MAP-43, MAP-47 - */ - struct Province : HasIdentifierAndColour { - friend struct Map; - - using index_t = uint16_t; - using life_rating_t = int8_t; - - static constexpr index_t NULL_INDEX = 0, MAX_INDEX = (1 << (8 * sizeof(index_t))) - 1; - - private: - const index_t index; - Region* region = nullptr; - bool water = false; - life_rating_t life_rating = 0; - IdentifierRegistry<Building> buildings; - // TODO - change this into a factory-like structure - Good const* rgo = nullptr; - - std::vector<Pop> pops; - Pop::pop_size_t total_population; - distribution_t pop_types, cultures, religions; - - Province(const std::string_view new_identifier, colour_t new_colour, index_t new_index); - - public: - Province(Province&&) = default; - - index_t get_index() const; - Region* get_region() const; - bool is_water() const; - life_rating_t get_life_rating() const; - bool add_building(Building&& building); - void lock_buildings(); - void reset_buildings(); - Building const* get_building_by_identifier(const std::string_view identifier) const; - size_t get_building_count() const; - std::vector<Building> const& get_buildings() const; - bool expand_building(const std::string_view building_type_identifier); - Good const* get_rgo() const; - std::string to_string() const; - - bool load_pop_list(PopManager const& pop_manager, ast::NodeCPtr root); - bool add_pop(Pop&& pop); - void clear_pops(); - size_t get_pop_count() const; - std::vector<Pop> const& get_pops() const; - Pop::pop_size_t get_total_population() const; - distribution_t const& get_pop_type_distribution() const; - distribution_t const& get_culture_distribution() const; - distribution_t const& get_religion_distribution() const; - void update_pops(); - - void update_state(Date const& today); - void tick(Date const& today); - }; -} diff --git a/src/openvic/map/Region.cpp b/src/openvic/map/Region.cpp deleted file mode 100644 index 33092c5..0000000 --- a/src/openvic/map/Region.cpp +++ /dev/null @@ -1,69 +0,0 @@ -#include "Region.hpp" - -using namespace OpenVic; - -bool ProvinceSet::add_province(Province* province) { - if (locked) { - Logger::error("Cannot add province to province set - locked!"); - return false; - } - if (province == nullptr) { - Logger::error("Cannot add province to province set - null province!"); - return false; - } - if (contains_province(province)) { - Logger::error("Cannot add province ", province->get_identifier(), " to province set - already in the set!"); - return false; - } - provinces.push_back(province); - return true; -} - -void ProvinceSet::lock(bool log) { - if (locked) { - Logger::error("Failed to lock province set - already locked!"); - } else { - locked = true; - if (log) Logger::info("Locked province set with ", size(), " provinces"); - } -} - -bool ProvinceSet::is_locked() const { - return locked; -} - -void ProvinceSet::reset() { - provinces.clear(); - locked = false; -} - -bool ProvinceSet::empty() const { - return provinces.empty(); -} - -size_t ProvinceSet::size() const { - return provinces.size(); -} - -void ProvinceSet::reserve(size_t size) { - if (locked) { - Logger::error("Failed to reserve space for ", size, " items in province set - already locked!"); - } else { - provinces.reserve(size); - } -} - -bool ProvinceSet::contains_province(Province const* province) const { - return province && std::find(provinces.begin(), provinces.end(), province) != provinces.end(); -} - -std::vector<Province*> const& ProvinceSet::get_provinces() const { - return provinces; -} - -Region::Region(const std::string_view new_identifier) : HasIdentifier { new_identifier } {} - -colour_t Region::get_colour() const { - if (provinces.empty()) return FULL_COLOUR << 16; - return provinces.front()->get_colour(); -} diff --git a/src/openvic/map/Region.hpp b/src/openvic/map/Region.hpp deleted file mode 100644 index a3640ca..0000000 --- a/src/openvic/map/Region.hpp +++ /dev/null @@ -1,38 +0,0 @@ -#pragma once - -#include "openvic/map/Province.hpp" - -namespace OpenVic { - - struct ProvinceSet { - protected: - std::vector<Province*> provinces; - bool locked = false; - - public: - bool add_province(Province* province); - void lock(bool log = false); - bool is_locked() const; - void reset(); - bool empty() const; - size_t size() const; - void reserve(size_t size); - bool contains_province(Province const* province) const; - std::vector<Province*> const& get_provinces() const; - }; - - /* REQUIREMENTS: - * MAP-6, MAP-44, MAP-48 - */ - struct Region : HasIdentifier, ProvinceSet { - friend struct Map; - - private: - Region(const std::string_view new_identifier); - - public: - Region(Region&&) = default; - - colour_t get_colour() const; - }; -} diff --git a/src/openvic/pop/Culture.cpp b/src/openvic/pop/Culture.cpp deleted file mode 100644 index d86d608..0000000 --- a/src/openvic/pop/Culture.cpp +++ /dev/null @@ -1,233 +0,0 @@ -#include "Culture.hpp" - -#include "openvic/dataloader/NodeTools.hpp" - -using namespace OpenVic; -using namespace OpenVic::NodeTools; - -GraphicalCultureType::GraphicalCultureType(const std::string_view new_identifier) : HasIdentifier { new_identifier } {} - -CultureGroup::CultureGroup(const std::string_view new_identifier, const std::string_view new_leader, - GraphicalCultureType const& new_unit_graphical_culture_type, bool new_is_overseas) - : HasIdentifier { new_identifier }, leader { new_leader }, - unit_graphical_culture_type { new_unit_graphical_culture_type }, - is_overseas { new_is_overseas } {} - - -std::string const& CultureGroup::get_leader() const { - return leader; -} - -GraphicalCultureType const& CultureGroup::get_unit_graphical_culture_type() const { - return unit_graphical_culture_type; -} - -bool CultureGroup::get_is_overseas() const { - return is_overseas; -} - -Culture::Culture(const 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) - : HasIdentifierAndColour { new_identifier, new_colour, true }, - group { new_group }, - first_names { new_first_names }, - last_names { new_last_names } {} - -CultureGroup const& Culture::get_group() const { - return group; -} - -std::vector<std::string> const& Culture::get_first_names() const { - return first_names; -} - -std::vector<std::string> const& Culture::get_last_names() const { - return last_names; -} - -CultureManager::CultureManager() - : graphical_culture_types { "graphical culture types" }, - culture_groups { "culture groups" }, - cultures { "cultures" } {} - -bool CultureManager::add_graphical_culture_type(const std::string_view identifier) { - if (identifier.empty()) { - Logger::error("Invalid culture group identifier - empty!"); - return false; - } - return graphical_culture_types.add_item({ identifier }); -} - -void CultureManager::lock_graphical_culture_types() { - graphical_culture_types.lock(); -} - -GraphicalCultureType const* CultureManager::get_graphical_culture_type_by_identifier(const std::string_view identifier) const { - return graphical_culture_types.get_item_by_identifier(identifier); -} - -size_t CultureManager::get_graphical_culture_type_count() const { - return graphical_culture_types.size(); -} - -std::vector<GraphicalCultureType> const& CultureManager::get_graphical_culture_types() const { - return graphical_culture_types.get_items(); -} - -bool CultureManager::add_culture_group(const std::string_view identifier, const std::string_view leader, GraphicalCultureType const* graphical_culture_type, bool is_overseas) { - if (!graphical_culture_types.is_locked()) { - Logger::error("Cannot register culture groups until graphical culture types are locked!"); - return false; - } - if (identifier.empty()) { - Logger::error("Invalid culture group identifier - empty!"); - return false; - } - if (leader.empty()) { - Logger::error("Invalid culture group leader - empty!"); - return false; - } - if (graphical_culture_type == nullptr) { - Logger::error("Null graphical culture type for ", identifier); - return false; - } - return culture_groups.add_item({ identifier, leader, *graphical_culture_type, is_overseas }); -} - -void CultureManager::lock_culture_groups() { - culture_groups.lock(); -} - -CultureGroup const* CultureManager::get_culture_group_by_identifier(const std::string_view identifier) const { - return culture_groups.get_item_by_identifier(identifier); -} - -size_t CultureManager::get_culture_group_count() const { - return culture_groups.size(); -} - -std::vector<CultureGroup> const& CultureManager::get_culture_groups() const { - return culture_groups.get_items(); -} - -bool CultureManager::add_culture(const std::string_view identifier, colour_t colour, CultureGroup const* group, std::vector<std::string> const& first_names, std::vector<std::string> const& last_names) { - if (!culture_groups.is_locked()) { - Logger::error("Cannot register cultures until culture groups are locked!"); - return false; - } - if (identifier.empty()) { - Logger::error("Invalid culture identifier - empty!"); - return false; - } - if (group == nullptr) { - Logger::error("Null culture group for ", identifier); - return false; - } - if (colour > MAX_COLOUR_RGB) { - 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 }); -} - -void CultureManager::lock_cultures() { - cultures.lock(); -} - -Culture const* CultureManager::get_culture_by_identifier(const std::string_view identifier) const { - return cultures.get_item_by_identifier(identifier); -} - -size_t CultureManager::get_culture_count() const { - return cultures.size(); -} - -std::vector<Culture> const& CultureManager::get_cultures() const { - return cultures.get_items(); -} - -bool CultureManager::load_graphical_culture_type_file(ast::NodeCPtr root) { - const bool ret = expect_list_reserve_length( - graphical_culture_types, - expect_identifier( - std::bind(&CultureManager::add_graphical_culture_type, this, std::placeholders::_1) - ) - )(root); - lock_graphical_culture_types(); - return ret; -} - -bool CultureManager::load_culture_file(ast::NodeCPtr root) { - if (!graphical_culture_types.is_locked()) { - Logger::error("Cannot load culture groups until graphical culture types are locked!"); - return false; - } - - static const std::string default_unit_graphical_culture_type_identifier = "Generic"; - GraphicalCultureType const* const default_unit_graphical_culture_type = get_graphical_culture_type_by_identifier(default_unit_graphical_culture_type_identifier); - if (default_unit_graphical_culture_type == nullptr) { - Logger::error("Failed to find default unit graphical culture type: ", default_unit_graphical_culture_type_identifier); - } - - size_t total_expected_cultures = 0; - bool ret = expect_dictionary_reserve_length( - culture_groups, - [this, default_unit_graphical_culture_type, &total_expected_cultures](std::string_view key, ast::NodeCPtr value) -> bool { - std::string_view leader; - GraphicalCultureType const* unit_graphical_culture_type = default_unit_graphical_culture_type; - bool is_overseas = true; - - bool ret = expect_dictionary_keys_and_length( - [&total_expected_cultures](size_t size) -> size_t { - total_expected_cultures += size; - return size; - }, - ALLOW_OTHER_KEYS, - "leader", ONE_EXACTLY, expect_identifier(assign_variable_callback(leader)), - "unit", ZERO_OR_ONE, - expect_identifier( - [this, &unit_graphical_culture_type](std::string_view identifier) -> bool { - unit_graphical_culture_type = get_graphical_culture_type_by_identifier(identifier); - if (unit_graphical_culture_type != nullptr) return true; - Logger::error("Invalid unit graphical culture type: ", identifier); - return false; - } - ), - "union", ZERO_OR_ONE, success_callback, - "is_overseas", ZERO_OR_ONE, expect_bool(assign_variable_callback(is_overseas)) - )(value); - ret &= add_culture_group(key, leader, unit_graphical_culture_type, is_overseas); - return ret; - } - )(root); - lock_culture_groups(); - cultures.reserve(cultures.size() + total_expected_cultures); - - ret &= expect_dictionary( - [this](std::string_view culture_group_key, ast::NodeCPtr culture_group_value) -> bool { - - CultureGroup const* culture_group = get_culture_group_by_identifier(culture_group_key); - - return expect_dictionary( - [this, culture_group](std::string_view key, ast::NodeCPtr value) -> bool { - if (key == "leader" || key == "unit" || key == "union" || key == "is_overseas") return true; - - colour_t colour = NULL_COLOUR; - std::vector<std::string> first_names, last_names; - - 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), - "radicalism", ZERO_OR_ONE, success_callback, - "primary", ZERO_OR_ONE, success_callback - )(value); - ret &= add_culture(key, colour, culture_group, first_names, last_names); - return ret; - } - )(culture_group_value); - } - )(root); - lock_cultures(); - return ret; -} diff --git a/src/openvic/pop/Culture.hpp b/src/openvic/pop/Culture.hpp deleted file mode 100644 index cc6c2a6..0000000 --- a/src/openvic/pop/Culture.hpp +++ /dev/null @@ -1,89 +0,0 @@ -#pragma once - -#include "openvic/dataloader/NodeTools.hpp" -#include "openvic/types/IdentifierRegistry.hpp" - -namespace OpenVic { - - struct CultureManager; - - struct GraphicalCultureType : HasIdentifier { - friend struct CultureManager; - - private: - GraphicalCultureType(const std::string_view new_identifier); - - public: - GraphicalCultureType(GraphicalCultureType&&) = default; - }; - - struct CultureGroup : HasIdentifier { - friend struct CultureManager; - - private: - const std::string leader; - GraphicalCultureType const& unit_graphical_culture_type; - const bool is_overseas; - - // TODO - union tag - - CultureGroup(const std::string_view new_identifier, const std::string_view new_leader, GraphicalCultureType const& new_unit_graphical_culture_type, bool new_is_overseas); - - public: - CultureGroup(CultureGroup&&) = default; - - std::string const& get_leader() const; - GraphicalCultureType const& get_unit_graphical_culture_type() const; - bool get_is_overseas() const; - }; - - struct Culture : HasIdentifierAndColour { - friend struct CultureManager; - - private: - CultureGroup const& group; - const std::vector<std::string> first_names, last_names; - - // TODO - radicalism, primary tag - - Culture(const 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); - - public: - Culture(Culture&&) = default; - - CultureGroup const& get_group() const; - std::vector<std::string> const& get_first_names() const; - std::vector<std::string> const& get_last_names() const; - }; - - struct CultureManager { - private: - IdentifierRegistry<GraphicalCultureType> graphical_culture_types; - IdentifierRegistry<CultureGroup> culture_groups; - IdentifierRegistry<Culture> cultures; - - public: - CultureManager(); - - bool add_graphical_culture_type(const std::string_view identifier); - void lock_graphical_culture_types(); - GraphicalCultureType const* get_graphical_culture_type_by_identifier(const std::string_view identifier) const; - size_t get_graphical_culture_type_count() const; - std::vector<GraphicalCultureType> const& get_graphical_culture_types() const; - - bool add_culture_group(const std::string_view identifier, const std::string_view leader, GraphicalCultureType const* new_graphical_culture_type, bool is_overseas); - void lock_culture_groups(); - CultureGroup const* get_culture_group_by_identifier(const std::string_view identifier) const; - size_t get_culture_group_count() const; - std::vector<CultureGroup> const& get_culture_groups() const; - - bool add_culture(const std::string_view identifier, colour_t colour, CultureGroup const* group, std::vector<std::string> const& first_names, std::vector<std::string> const& last_names); - void lock_cultures(); - Culture const* get_culture_by_identifier(const std::string_view identifier) const; - size_t get_culture_count() const; - std::vector<Culture> const& get_cultures() const; - - bool load_graphical_culture_type_file(ast::NodeCPtr root); - bool load_culture_file(ast::NodeCPtr root); - }; -} diff --git a/src/openvic/pop/Pop.cpp b/src/openvic/pop/Pop.cpp deleted file mode 100644 index fbe8708..0000000 --- a/src/openvic/pop/Pop.cpp +++ /dev/null @@ -1,195 +0,0 @@ -#include "Pop.hpp" - -#include <cassert> - -#include "openvic/dataloader/NodeTools.hpp" -#include "openvic/map/Province.hpp" -#include "openvic/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 } { - assert(size > 0); -} - -PopType const& Pop::get_type() const { - return type; -} - -Culture const& Pop::get_culture() const { - return culture; -} - -Religion const& Pop::get_religion() const { - return religion; -} - -Pop::pop_size_t Pop::get_size() const { - return size; -} - -Pop::pop_size_t Pop::get_num_promoted() const { - return num_promoted; -} - -Pop::pop_size_t Pop::get_num_demoted() const { - return num_demoted; -} - -Pop::pop_size_t Pop::get_num_migrated() const { - return num_migrated; -} - -Pop::pop_size_t Pop::get_pop_daily_change() const { - return Pop::get_num_promoted() - (Pop::get_num_demoted() + Pop::get_num_migrated()); -} - -PopType::PopType(const std::string_view new_identifier, colour_t new_colour, - strata_t new_strata, sprite_t new_sprite, - 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_is_slave) - : HasIdentifierAndColour { new_identifier, new_colour, true }, - strata { new_strata }, - sprite { new_sprite }, - max_size { new_max_size }, - merge_max_size { new_merge_max_size }, - state_capital_only { new_state_capital_only }, - demote_migrant { new_demote_migrant }, - is_artisan { new_is_artisan }, - is_slave { new_is_slave } { - assert(sprite > 0); - assert(max_size > 0); - assert(merge_max_size > 0); -} - -PopType::sprite_t PopType::get_sprite() const { - return sprite; -} - -PopType::strata_t PopType::get_strata() const { - return strata; -} - -Pop::pop_size_t PopType::get_max_size() const { - return max_size; -} - -Pop::pop_size_t PopType::get_merge_max_size() const { - return merge_max_size; -} - -bool PopType::get_state_capital_only() const { - return state_capital_only; -} - -bool PopType::get_demote_migrant() const { - return demote_migrant; -} - -bool PopType::get_is_artisan() const { - return is_artisan; -} - -bool PopType::get_is_slave() const { - return is_slave; -} - -PopManager::PopManager() : pop_types { "pop types" } {} - -bool PopManager::add_pop_type(const std::string_view identifier, colour_t colour, PopType::strata_t strata, PopType::sprite_t sprite, - Pop::pop_size_t max_size, Pop::pop_size_t merge_max_size, bool state_capital_only, bool demote_migrant, bool is_artisan, bool is_slave) { - if (identifier.empty()) { - Logger::error("Invalid pop type identifier - empty!"); - return false; - } - if (colour > MAX_COLOUR_RGB) { - Logger::error("Invalid pop type colour for ", identifier, ": ", colour_to_hex_string(colour)); - return false; - } - if (sprite <= 0) { - Logger::error("Invalid pop type sprite index for ", identifier, ": ", sprite); - return false; - } - if (max_size <= 0) { - Logger::error("Invalid pop type max size for ", identifier, ": ", max_size); - return false; - } - if (merge_max_size <= 0) { - Logger::error("Invalid pop type merge max size for ", identifier, ": ", merge_max_size); - return false; - } - return pop_types.add_item({ identifier, colour, strata, sprite, max_size, merge_max_size, state_capital_only, demote_migrant, is_artisan, is_slave }); -} - -void PopManager::lock_pop_types() { - pop_types.lock(); -} - -PopType const* PopManager::get_pop_type_by_identifier(const std::string_view identifier) const { - return pop_types.get_item_by_identifier(identifier); -} - -size_t PopManager::get_pop_type_count() const { - return pop_types.size(); -} - -std::vector<PopType> const& PopManager::get_pop_types() const { - return pop_types.get_items(); -} - -bool PopManager::load_pop_type_file(std::filesystem::path const& path, ast::NodeCPtr root) { - - // TODO - pop type loading - - if (pop_types.empty()) - return add_pop_type("test_pop_type", 0xFF0000, PopType::strata_t::POOR, 1, 1, 1, false, false, false, false); - return true; -} - -bool PopManager::load_pop_into_province(Province& province, ast::NodeCPtr root) const { - static PopType const* type = get_pop_type_by_identifier("test_pop_type"); - Culture const* culture = nullptr; - Religion const* religion = nullptr; - Pop::pop_size_t size = 0; - - bool ret = expect_assign( - [this, &culture, &religion, &size](std::string_view, ast::NodeCPtr pop_node) -> bool { - return expect_dictionary_keys( - "culture", ONE_EXACTLY, - expect_identifier( - [&culture, this](std::string_view identifier) -> bool { - culture = culture_manager.get_culture_by_identifier(identifier); - if (culture != nullptr) return true; - Logger::error("Invalid pop culture: ", identifier); - return false; - } - ), - "religion", ONE_EXACTLY, - expect_identifier( - [&religion, this](std::string_view identifier) -> bool { - religion = religion_manager.get_religion_by_identifier(identifier); - if (religion != nullptr) return true; - Logger::error("Invalid pop religion: ", identifier); - return false; - } - ), - "size", ONE_EXACTLY, expect_uint(assign_variable_callback_uint("pop size", size)), - "militancy", ZERO_OR_ONE, success_callback, - "rebel_type", ZERO_OR_ONE, success_callback - )(pop_node); - } - )(root); - - if (type != nullptr && culture != nullptr && religion != nullptr && size > 0) { - ret &= province.add_pop({ *type, *culture, *religion, size }); - } else { - Logger::error("Some pop arguments are invalid: type = ", type, ", culture = ", culture, ", religion = ", religion, ", size = ", size); - ret = false; - } - return ret; -} diff --git a/src/openvic/pop/Pop.hpp b/src/openvic/pop/Pop.hpp deleted file mode 100644 index f4694f0..0000000 --- a/src/openvic/pop/Pop.hpp +++ /dev/null @@ -1,104 +0,0 @@ -#pragma once - -#include <filesystem> - -#include "openvic/pop/Culture.hpp" -#include "openvic/pop/Religion.hpp" - -namespace OpenVic { - - struct PopManager; - struct PopType; - - /* REQUIREMENTS: - * POP-18, POP-19, POP-20, POP-21 - */ - struct Pop { - friend struct PopManager; - - using pop_size_t = int64_t; - - private: - PopType const& type; - Culture const& culture; - Religion const& religion; - pop_size_t size, num_promoted, num_demoted, num_migrated; - - Pop(PopType const& new_type, Culture const& new_culture, Religion const& new_religion, pop_size_t new_size); - - public: - Pop(Pop const&) = delete; - Pop(Pop&&) = default; - Pop& operator=(Pop const&) = delete; - Pop& operator=(Pop&&) = delete; - - PopType const& get_type() const; - Culture const& get_culture() const; - Religion const& get_religion() const; - pop_size_t get_size() const; - pop_size_t get_num_promoted() const; - pop_size_t get_num_demoted() const; - pop_size_t get_num_migrated() const; - pop_size_t get_pop_daily_change() const; - }; - - /* REQUIREMENTS: - * POP-26 - */ - struct PopType : HasIdentifierAndColour { - friend struct PopManager; - - using sprite_t = uint8_t; - - private: - const enum class strata_t { - POOR, - MIDDLE, - RICH - } strata; - const sprite_t sprite; - const Pop::pop_size_t max_size, merge_max_size; - const bool state_capital_only, demote_migrant, is_artisan, is_slave; - - // TODO - rebel composition, life/everyday/luxury needs, country and province migration targets, promote_to targets, ideologies and issues - - PopType(const std::string_view new_identifier, colour_t new_colour, strata_t new_strata, sprite_t new_sprite, 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_is_slave); - - public: - PopType(PopType&&) = default; - - strata_t get_strata() const; - sprite_t get_sprite() const; - Pop::pop_size_t get_max_size() const; - Pop::pop_size_t get_merge_max_size() const; - bool get_state_capital_only() const; - bool get_demote_migrant() const; - bool get_is_artisan() const; - bool get_is_slave() const; - }; - - struct Province; - - struct PopManager { - private: - IdentifierRegistry<PopType> pop_types; - - public: - CultureManager culture_manager; - ReligionManager religion_manager; - - PopManager(); - - bool add_pop_type(const std::string_view identifier, colour_t new_colour, PopType::strata_t strata, PopType::sprite_t sprite, - Pop::pop_size_t max_size, Pop::pop_size_t merge_max_size, bool state_capital_only, bool demote_migrant, - bool is_artisan, bool is_slave); - void lock_pop_types(); - PopType const* get_pop_type_by_identifier(const std::string_view identifier) const; - size_t get_pop_type_count() const; - std::vector<PopType> const& get_pop_types() const; - - bool load_pop_type_file(std::filesystem::path const& path, ast::NodeCPtr root); - bool load_pop_into_province(Province& province, ast::NodeCPtr root) const; - }; -} diff --git a/src/openvic/pop/Religion.cpp b/src/openvic/pop/Religion.cpp deleted file mode 100644 index f7c657a..0000000 --- a/src/openvic/pop/Religion.cpp +++ /dev/null @@ -1,142 +0,0 @@ -#include "Religion.hpp" - -#include <cassert> - -using namespace OpenVic; -using namespace OpenVic::NodeTools; - -ReligionGroup::ReligionGroup(const std::string_view new_identifier) : HasIdentifier { new_identifier } {} - -Religion::Religion(const std::string_view new_identifier, colour_t new_colour, - ReligionGroup const& new_group, icon_t new_icon, bool new_pagan) - : HasIdentifierAndColour { new_identifier, new_colour, true }, - group { new_group }, - icon { new_icon }, - pagan { new_pagan } { - assert(icon > 0); -} - -ReligionGroup const& Religion::get_group() const { - return group; -} - -Religion::icon_t Religion::get_icon() const { - return icon; -} - -bool Religion::get_pagan() const { - return pagan; -} - -ReligionManager::ReligionManager() - : religion_groups { "religion groups" }, - religions { "religions" } {} - -bool ReligionManager::add_religion_group(const std::string_view identifier) { - if (identifier.empty()) { - Logger::error("Invalid religion group identifier - empty!"); - return false; - } - return religion_groups.add_item({ identifier }); -} - -void ReligionManager::lock_religion_groups() { - religion_groups.lock(); -} - -ReligionGroup const* ReligionManager::get_religion_group_by_identifier(const std::string_view identifier) const { - return religion_groups.get_item_by_identifier(identifier); -} - -size_t ReligionManager::get_religion_group_count() const { - return religion_groups.size(); -} - -std::vector<ReligionGroup> const& ReligionManager::get_religion_groups() const { - return religion_groups.get_items(); -} - -bool ReligionManager::add_religion(const std::string_view identifier, colour_t colour, ReligionGroup const* group, Religion::icon_t icon, bool pagan) { - if (!religion_groups.is_locked()) { - Logger::error("Cannot register religions until religion groups are locked!"); - return false; - } - if (identifier.empty()) { - Logger::error("Invalid religion identifier - empty!"); - return false; - } - if (group == nullptr) { - Logger::error("Null religion group for ", identifier); - return false; - } - if (colour > MAX_COLOUR_RGB) { - Logger::error("Invalid religion colour for ", identifier, ": ", colour_to_hex_string(colour)); - return false; - } - if (icon <= 0) { - Logger::error("Invalid religion icon for ", identifier, ": ", icon); - return false; - } - return religions.add_item({ identifier, colour, *group, icon, pagan }); -} - -void ReligionManager::lock_religions() { - religions.lock(); -} - -Religion const* ReligionManager::get_religion_by_identifier(const std::string_view identifier) const { - return religions.get_item_by_identifier(identifier); -} - -size_t ReligionManager::get_religion_count() const { - return religions.size(); -} - -std::vector<Religion> const& ReligionManager::get_religions() const { - return religions.get_items(); -} - -bool ReligionManager::load_religion_file(ast::NodeCPtr root) { - - size_t total_expected_religions = 0; - bool ret = expect_dictionary_reserve_length( - religion_groups, - [this, &total_expected_religions](std::string_view key, ast::NodeCPtr value) -> bool { - bool ret = expect_list_and_length( - [&total_expected_religions](size_t size) -> size_t { - total_expected_religions += size; - return 0; - }, - success_callback - )(value); - ret &= add_religion_group(key); - return ret; - } - )(root); - lock_religion_groups(); - religions.reserve(religions.size() + total_expected_religions); - ret &= expect_dictionary( - [this](std::string_view religion_group_key, ast::NodeCPtr religion_group_value) -> bool { - - ReligionGroup const* religion_group = get_religion_group_by_identifier(religion_group_key); - - return expect_dictionary( - [this, religion_group](std::string_view key, ast::NodeCPtr value) -> bool { - colour_t colour = NULL_COLOUR; - Religion::icon_t icon = 0; - bool pagan = false; - - bool ret = expect_dictionary_keys( - "icon", ONE_EXACTLY, expect_uint(assign_variable_callback_uint("religion icon", icon)), - "color", ONE_EXACTLY, expect_colour(assign_variable_callback(colour)), - "pagan", ZERO_OR_ONE, expect_bool(assign_variable_callback(pagan)) - )(value); - ret &= add_religion(key, colour, religion_group, icon, pagan); - return ret; - } - )(religion_group_value); - } - )(root); - lock_religions(); - return ret; -} diff --git a/src/openvic/pop/Religion.hpp b/src/openvic/pop/Religion.hpp deleted file mode 100644 index f04b035..0000000 --- a/src/openvic/pop/Religion.hpp +++ /dev/null @@ -1,62 +0,0 @@ -#pragma once - -#include "openvic/types/IdentifierRegistry.hpp" -#include "openvic/dataloader/NodeTools.hpp" - -namespace OpenVic { - - struct ReligionManager; - - struct ReligionGroup : HasIdentifier { - friend struct ReligionManager; - - private: - ReligionGroup(const std::string_view new_identifier); - - public: - ReligionGroup(ReligionGroup&&) = default; - }; - - struct Religion : HasIdentifierAndColour { - friend struct ReligionManager; - - using icon_t = uint8_t; - - private: - ReligionGroup const& group; - const icon_t icon; - const bool pagan; - - Religion(const std::string_view new_identifier, colour_t new_colour, ReligionGroup const& new_group, icon_t new_icon, bool new_pagan); - - public: - Religion(Religion&&) = default; - - ReligionGroup const& get_group() const; - icon_t get_icon() const; - bool get_pagan() const; - }; - - struct ReligionManager { - private: - IdentifierRegistry<ReligionGroup> religion_groups; - IdentifierRegistry<Religion> religions; - - public: - ReligionManager(); - - bool add_religion_group(const std::string_view identifier); - void lock_religion_groups(); - ReligionGroup const* get_religion_group_by_identifier(const std::string_view identifier) const; - size_t get_religion_group_count() const; - std::vector<ReligionGroup> const& get_religion_groups() const; - - bool add_religion(const std::string_view identifier, colour_t colour, ReligionGroup const* group, Religion::icon_t icon, bool pagan); - void lock_religions(); - Religion const* get_religion_by_identifier(const std::string_view identifier) const; - size_t get_religion_count() const; - std::vector<Religion> const& get_religions() const; - - bool load_religion_file(ast::NodeCPtr root); - }; -} diff --git a/src/openvic/types/Colour.hpp b/src/openvic/types/Colour.hpp deleted file mode 100644 index 01f3852..0000000 --- a/src/openvic/types/Colour.hpp +++ /dev/null @@ -1,36 +0,0 @@ -#pragma once - -#include <algorithm> -#include <cstdint> -#include <iomanip> -#include <sstream> -#include <string> - -namespace OpenVic { - // Represents a 24-bit RGB integer OR a 32-bit ARGB integer - using colour_t = uint32_t; - /* When colour_t is used as an identifier, NULL_COLOUR is disallowed - * and should be reserved as an error value. - * When colour_t is used in a purely graphical context, NULL_COLOUR - * should be allowed. - */ - static constexpr colour_t NULL_COLOUR = 0, FULL_COLOUR = 0xFF, MAX_COLOUR_RGB = 0xFFFFFF; - constexpr colour_t float_to_colour_byte(float f, float min = 0.0f, float max = 1.0f) { - return static_cast<colour_t>(std::clamp(min + f * (max - min), min, max) * 255.0f); - } - constexpr colour_t fraction_to_colour_byte(int n, int d, float min = 0.0f, float max = 1.0f) { - return float_to_colour_byte(static_cast<float>(n) / static_cast<float>(d), min, max); - } - constexpr colour_t float_to_alpha_value(float a) { - return float_to_colour_byte(a) << 24; - } - constexpr float colour_byte_to_float(colour_t colour) { - return std::clamp(static_cast<float>(colour) / 255.0f, 0.0f, 1.0f); - } - - inline std::string colour_to_hex_string(colour_t colour) { - std::ostringstream stream; - stream << std::hex << std::setfill('0') << std::setw(6) << colour; - return stream.str(); - } -} diff --git a/src/openvic/types/Date.cpp b/src/openvic/types/Date.cpp deleted file mode 100644 index 1f13808..0000000 --- a/src/openvic/types/Date.cpp +++ /dev/null @@ -1,262 +0,0 @@ -#include "Date.hpp" - -#include <algorithm> -#include <cassert> -#include <cctype> -#include <charconv> - -#include "openvic/utility/Logger.hpp" -#include "openvic/utility/StringUtils.hpp" - -using namespace OpenVic; - -Timespan::Timespan(day_t value) : days { value } {} - -bool Timespan::operator<(Timespan other) const { return days < other.days; }; -bool Timespan::operator>(Timespan other) const { return days > other.days; }; -bool Timespan::operator<=(Timespan other) const { return days <= other.days; }; -bool Timespan::operator>=(Timespan other) const { return days >= other.days; }; -bool Timespan::operator==(Timespan other) const { return days == other.days; }; -bool Timespan::operator!=(Timespan other) const { return days != other.days; }; - -Timespan Timespan::operator+(Timespan other) const { return days + other.days; } - -Timespan Timespan::operator-(Timespan other) const { return days - other.days; } - -Timespan Timespan::operator*(day_t factor) const { return days * factor; } - -Timespan Timespan::operator/(day_t factor) const { return days / factor; } - -Timespan& Timespan::operator+=(Timespan other) { - days += other.days; - return *this; -} - -Timespan& Timespan::operator-=(Timespan other) { - days -= other.days; - return *this; -} - -Timespan& Timespan::operator++() { - days++; - return *this; -} - -Timespan Timespan::operator++(int) { - Timespan old = *this; - ++(*this); - return old; -} - -Timespan::operator day_t() const { - return days; -} - -Timespan::operator double() const { - return days; -} - -std::string Timespan::to_string() const { - return std::to_string(days); -} - -Timespan::operator std::string() const { - return to_string(); -} - -std::ostream& OpenVic::operator<<(std::ostream& out, Timespan const& timespan) { - return out << timespan.to_string(); -} - -Timespan Date::_dateToTimespan(year_t year, month_t month, day_t day) { - month = std::clamp<month_t>(month, 1, MONTHS_IN_YEAR); - day = std::clamp<day_t>(day, 1, DAYS_IN_MONTH[month - 1]); - return year * DAYS_IN_YEAR + DAYS_UP_TO_MONTH[month - 1] + day - 1; -} - -Timespan::day_t const* Date::DAYS_UP_TO_MONTH = generate_days_up_to_month(); - -Timespan::day_t const* Date::generate_days_up_to_month() { - static Timespan::day_t days_up_to_month[MONTHS_IN_YEAR]; - Timespan::day_t days = 0; - for (int month = 0; month < MONTHS_IN_YEAR; - days_up_to_month[month] = days, days += DAYS_IN_MONTH[month++]); - assert(days == DAYS_IN_YEAR); - return days_up_to_month; -} - -Date::month_t const* Date::MONTH_FROM_DAY_IN_YEAR = generate_month_from_day_in_year(); - -Date::month_t const* Date::generate_month_from_day_in_year() { - static month_t month_from_day_in_year[DAYS_IN_YEAR]; - Timespan::day_t days_left = 0; - for (int day = 0, month = 0; day < DAYS_IN_YEAR; - days_left = (days_left > 0 ? days_left : DAYS_IN_MONTH[month++]) - 1, - month_from_day_in_year[day++] = month); - assert(days_left == 0); - assert(month_from_day_in_year[DAYS_IN_YEAR - 1] == MONTHS_IN_YEAR); - return month_from_day_in_year; -} - -Date::Date(Timespan total_days) : timespan { total_days } { - if (timespan < 0) { - Logger::error("Invalid timespan for date: ", timespan, " (cannot be negative)"); - timespan = 0; - } -} - -Date::Date(year_t year, month_t month, day_t day) : timespan { _dateToTimespan(year, month, day) } {} - -Date::year_t Date::getYear() const { - return static_cast<Timespan::day_t>(timespan) / DAYS_IN_YEAR; -} - -Date::month_t Date::getMonth() const { - return MONTH_FROM_DAY_IN_YEAR[static_cast<Timespan::day_t>(timespan) % DAYS_IN_YEAR]; -} - -Date::day_t Date::getDay() const { - return (static_cast<Timespan::day_t>(timespan) % DAYS_IN_YEAR) - DAYS_UP_TO_MONTH[getMonth() - 1] + 1; -} - -bool Date::operator<(Date other) const { return timespan < other.timespan; }; -bool Date::operator>(Date other) const { return timespan > other.timespan; }; -bool Date::operator<=(Date other) const { return timespan <= other.timespan; }; -bool Date::operator>=(Date other) const { return timespan >= other.timespan; }; -bool Date::operator==(Date other) const { return timespan == other.timespan; }; -bool Date::operator!=(Date other) const { return timespan != other.timespan; }; - -Date Date::operator+(Timespan other) const { return timespan + other; } - -Timespan Date::operator-(Date other) const { return timespan - other.timespan; } - -Date& Date::operator+=(Timespan other) { - timespan += other; - return *this; -} - -Date& Date::operator-=(Timespan other) { - timespan -= other; - return *this; -} - -Date& Date::operator++() { - timespan++; - return *this; -} - -Date Date::operator++(int) { - Date old = *this; - ++(*this); - return old; -} - -std::string Date::to_string() const { - std::stringstream ss; - ss << *this; - return ss.str(); -} - -Date::operator std::string() const { - return to_string(); -} - -std::ostream& OpenVic::operator<<(std::ostream& out, Date const& date) { - return out << static_cast<int>(date.getYear()) << Date::SEPARATOR_CHARACTER << static_cast<int>(date.getMonth()) << Date::SEPARATOR_CHARACTER << static_cast<int>(date.getDay()); -} - -// Parsed from string of the form YYYY.MM.DD -Date Date::from_string(char const* const str, char const* const end, bool* successful) { - if (successful != nullptr) *successful = true; - - year_t year = 0; - month_t month = 1; - day_t day = 1; - - if (str == nullptr || end <= str) { - Logger::error("Invalid string start/end pointers: ", static_cast<void const*>(str), " - ", static_cast<void const*>(end)); - if (successful != nullptr) *successful = false; - return { year, month, day }; - } - - char const* year_end = str; - while (std::isdigit(*year_end) && ++year_end < end); - - if (year_end <= str) { - Logger::error("Failed to find year digits in date: ", std::string_view { str, static_cast<size_t>(end - str) }); - if (successful != nullptr) *successful = false; - return { year, month, day }; - } - - bool sub_successful = false; - uint64_t val = StringUtils::string_to_uint64(str, year_end, &sub_successful, 10); - if (!sub_successful || val >= 1 << (8 * sizeof(year_t))) { - Logger::error("Failed to read year: ", std::string_view { str, static_cast<size_t>(end - str) }); - if (successful != nullptr) *successful = false; - return { year, month, day }; - } - year = val; - if (year_end < end) { - if (*year_end == SEPARATOR_CHARACTER) { - char const* const month_start = year_end + 1; - char const* month_end = month_start; - if (month_start < end) { - while (std::isdigit(*month_end) && ++month_end < end); - } - if (month_start >= month_end) { - Logger::error("Failed to find month digits in date: ", std::string_view { str, static_cast<size_t>(end - str) }); - if (successful != nullptr) *successful = false; - } else { - sub_successful = false; - val = StringUtils::string_to_uint64(month_start, month_end, &sub_successful, 10); - if (!sub_successful || val < 1 || val > MONTHS_IN_YEAR) { - Logger::error("Failed to read month: ", std::string_view { str, static_cast<size_t>(end - str) }); - if (successful != nullptr) *successful = false; - } else { - month = val; - if (month_end < end) { - if (*month_end == SEPARATOR_CHARACTER) { - char const* const day_start = month_end + 1; - char const* day_end = day_start; - if (day_start < end) { - while (std::isdigit(*day_end) && ++day_end < end); - } - if (day_start >= day_end) { - Logger::error("Failed to find day digits in date: ", std::string_view { str, static_cast<size_t>(end - str) }); - if (successful != nullptr) *successful = false; - } else { - sub_successful = false; - val = StringUtils::string_to_uint64(day_start, day_end, &sub_successful); - if (!sub_successful || val < 1 || val > DAYS_IN_MONTH[month - 1]) { - Logger::error("Failed to read day: ", std::string_view { str, static_cast<size_t>(end - str) }); - if (successful != nullptr) *successful = false; - } else { - day = val; - if (day_end < end) { - Logger::error("Unexpected string \"", std::string_view { day_end, static_cast<size_t>(end - day_end) }, "\" at the end of date ", std::string_view { str, static_cast<size_t>(end - str) }); - if (successful != nullptr) *successful = false; - } - } - } - } else { - Logger::error("Unexpected character \"", *month_end, "\" in month of date ", std::string_view { str, static_cast<size_t>(end - str) }); - if (successful != nullptr) *successful = false; - } - } - } - } - } else { - Logger::error("Unexpected character \"", *year_end, "\" in year of date ", std::string_view { str, static_cast<size_t>(end - str) }); - if (successful != nullptr) *successful = false; - } - } - return { year, month, day }; -}; - -Date Date::from_string(char const* str, size_t length, bool* successful) { - return from_string(str, str + length, successful); -} - -Date Date::from_string(const std::string_view str, bool* successful) { - return from_string(str.data(), str.length(), successful); -} diff --git a/src/openvic/types/Date.hpp b/src/openvic/types/Date.hpp deleted file mode 100644 index 601f9dc..0000000 --- a/src/openvic/types/Date.hpp +++ /dev/null @@ -1,96 +0,0 @@ -#pragma once - -#include <cstdint> -#include <ostream> -#include <string> - -namespace OpenVic { - // A relative period between points in time, measured in days - struct Timespan { - using day_t = int64_t; - - private: - day_t days; - - public: - Timespan(day_t value = 0); - - bool operator<(Timespan other) const; - bool operator>(Timespan other) const; - bool operator<=(Timespan other) const; - bool operator>=(Timespan other) const; - bool operator==(Timespan other) const; - bool operator!=(Timespan other) const; - - Timespan operator+(Timespan other) const; - Timespan operator-(Timespan other) const; - Timespan operator*(day_t factor) const; - Timespan operator/(day_t factor) const; - Timespan& operator+=(Timespan other); - Timespan& operator-=(Timespan other); - Timespan& operator++(); - Timespan operator++(int); - - explicit operator day_t() const; - explicit operator double() const; - std::string to_string() const; - explicit operator std::string() const; - }; - std::ostream& operator<<(std::ostream& out, Timespan const& timespan); - - // Represents an in-game date - // Note: Current implementation does not account for leap-years, or dates before Year 0 - struct Date { - using year_t = uint16_t; - using month_t = uint8_t; - using day_t = uint8_t; - - static constexpr Timespan::day_t MONTHS_IN_YEAR = 12; - static constexpr Timespan::day_t DAYS_IN_YEAR = 365; - static constexpr Timespan::day_t DAYS_IN_MONTH[MONTHS_IN_YEAR] { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; - static Timespan::day_t const* DAYS_UP_TO_MONTH; - static month_t const* MONTH_FROM_DAY_IN_YEAR; - - static constexpr char SEPARATOR_CHARACTER = '.'; - - private: - // Number of days since Jan 1st, Year 0 - Timespan timespan; - - static Timespan _dateToTimespan(year_t year, month_t month, day_t day); - static Timespan::day_t const* generate_days_up_to_month(); - static month_t const* generate_month_from_day_in_year(); - - public: - // The Timespan is considered to be the number of days since Jan 1st, Year 0 - Date(Timespan total_days); - // Year month day specification - Date(year_t year = 0, month_t month = 1, day_t day = 1); - - year_t getYear() const; - month_t getMonth() const; - day_t getDay() const; - - bool operator<(Date other) const; - bool operator>(Date other) const; - bool operator<=(Date other) const; - bool operator>=(Date other) const; - bool operator==(Date other) const; - bool operator!=(Date other) const; - - Date operator+(Timespan other) const; - Timespan operator-(Date other) const; - Date& operator+=(Timespan other); - Date& operator-=(Timespan other); - Date& operator++(); - Date operator++(int); - - std::string to_string() const; - explicit operator std::string() const; - // Parsed from string of the form YYYY.MM.DD - static Date from_string(char const* str, char const* end, bool* successful = nullptr); - static Date from_string(char const* str, size_t length, bool* successful = nullptr); - static Date from_string(const std::string_view str, bool* successful = nullptr); - }; - std::ostream& operator<<(std::ostream& out, Date const& date); -} diff --git a/src/openvic/types/IdentifierRegistry.cpp b/src/openvic/types/IdentifierRegistry.cpp deleted file mode 100644 index 6d5221b..0000000 --- a/src/openvic/types/IdentifierRegistry.cpp +++ /dev/null @@ -1,37 +0,0 @@ -#include "IdentifierRegistry.hpp" - -#include <cassert> - -using namespace OpenVic; - -HasIdentifier::HasIdentifier(const std::string_view new_identifier) - : identifier { new_identifier } { - assert(!identifier.empty()); -} - -std::string const& HasIdentifier::get_identifier() const { - return identifier; -} - -HasColour::HasColour(colour_t const new_colour, bool can_be_null) : colour(new_colour) { - assert((can_be_null || colour != NULL_COLOUR) && colour <= MAX_COLOUR_RGB); -} - -colour_t HasColour::get_colour() const { return colour; } - -std::string HasColour::colour_to_hex_string() const { - return OpenVic::colour_to_hex_string(colour); -} - -HasIdentifierAndColour::HasIdentifierAndColour(const std::string_view new_identifier, - const colour_t new_colour, bool can_be_null) - : HasIdentifier { new_identifier }, - HasColour { new_colour, can_be_null } {} - -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/types/IdentifierRegistry.hpp b/src/openvic/types/IdentifierRegistry.hpp deleted file mode 100644 index 502b74b..0000000 --- a/src/openvic/types/IdentifierRegistry.hpp +++ /dev/null @@ -1,152 +0,0 @@ -#pragma once - -#include <map> -#include <vector> - -#include "openvic/types/Colour.hpp" -#include "openvic/utility/Logger.hpp" - -namespace OpenVic { - /* - * Base class for objects with a non-empty string identifier, - * uniquely named instances of which can be entered into an - * IdentifierRegistry instance. - */ - class HasIdentifier { - const std::string identifier; - - protected: - HasIdentifier(const std::string_view new_identifier); - - public: - HasIdentifier(HasIdentifier const&) = delete; - HasIdentifier(HasIdentifier&&) = default; - HasIdentifier& operator=(HasIdentifier const&) = delete; - HasIdentifier& operator=(HasIdentifier&&) = delete; - - std::string const& get_identifier() const; - }; - - /* - * Base class for objects with associated colour information. - */ - class HasColour { - const colour_t colour; - - protected: - HasColour(const colour_t new_colour, bool can_be_null); - - public: - HasColour(HasColour const&) = delete; - HasColour(HasColour&&) = default; - HasColour& operator=(HasColour const&) = delete; - HasColour& operator=(HasColour&&) = delete; - - colour_t get_colour() const; - std::string colour_to_hex_string() const; - }; - - /* - * Base class for objects with a unique string identifier - * and associated colour information. - */ - class HasIdentifierAndColour : public HasIdentifier, public HasColour { - protected: - HasIdentifierAndColour(const std::string_view new_identifier, const colour_t new_colour, bool can_be_null); - - public: - HasIdentifierAndColour(HasIdentifierAndColour const&) = delete; - HasIdentifierAndColour(HasIdentifierAndColour&&) = default; - HasIdentifierAndColour& operator=(HasIdentifierAndColour const&) = delete; - HasIdentifierAndColour& operator=(HasIdentifierAndColour&&) = delete; - }; - - using distribution_t = std::map<HasIdentifierAndColour const*, float>; - - distribution_t::value_type get_largest_item(distribution_t const& dist); - - /* - * Template for a list of objects with unique string identifiers that can - * be locked to prevent any further additions. The template argument T is - * the type of object that the registry will store, and the second part ensures - * that HasIdentifier is a base class of T. - */ - template<typename T> - requires(std::derived_from<T, HasIdentifier>) - class IdentifierRegistry { - using identifier_index_map_t = std::map<std::string, size_t, std::less<void>>; - - const std::string name; - std::vector<T> items; - bool locked = false; - identifier_index_map_t identifier_index_map; - - public: - IdentifierRegistry(const std::string_view new_name) : name { new_name } {} - bool add_item(T&& item) { - if (locked) { - Logger::error("Cannot add item to the ", name, " registry - locked!"); - return false; - } - T const* old_item = get_item_by_identifier(item.get_identifier()); - if (old_item != nullptr) { - Logger::error("Cannot add item to the ", name, " registry - an item with the identifier \"", item.get_identifier(), "\" already exists!"); - return false; - } - identifier_index_map[item.get_identifier()] = items.size(); - items.push_back(std::move(item)); - return true; - } - void lock(bool log = true) { - if (locked) { - Logger::error("Failed to lock ", name, " registry - already locked!"); - } else { - locked = true; - if (log) Logger::info("Locked ", name, " registry after registering ", size(), " items"); - } - } - bool is_locked() const { - return locked; - } - void reset() { - identifier_index_map.clear(); - items.clear(); - locked = false; - } - size_t size() const { - return items.size(); - } - bool empty() const { - return items.empty(); - } - void reserve(size_t size) { - if (locked) { - Logger::error("Failed to reserve space for ", size, " items in ", name, " registry - already locked!"); - } else { - items.reserve(size); - } - } - T* get_item_by_identifier(const std::string_view identifier) { - const identifier_index_map_t::const_iterator it = identifier_index_map.find(identifier); - if (it != identifier_index_map.end()) return &items[it->second]; - return nullptr; - } - T const* get_item_by_identifier(const std::string_view identifier) const { - const identifier_index_map_t::const_iterator it = identifier_index_map.find(identifier); - if (it != identifier_index_map.end()) return &items[it->second]; - return nullptr; - } - T* get_item_by_index(size_t index) { - return index < items.size() ? &items[index] : nullptr; - } - T const* get_item_by_index(size_t index) const { - return index < items.size() ? &items[index] : nullptr; - } - std::vector<T>& get_items() { - return items; - } - std::vector<T> const& get_items() const { - return items; - } - }; -} diff --git a/src/openvic/types/fixed_point/FP.hpp b/src/openvic/types/fixed_point/FP.hpp deleted file mode 100644 index 42ddf79..0000000 --- a/src/openvic/types/fixed_point/FP.hpp +++ /dev/null @@ -1,581 +0,0 @@ -#pragma once - -#include <cerrno> -#include <cmath> -#include <cstdint> -#include <cstdlib> -#include <limits> -#include <string_view> - -#include "openvic/utility/Logger.hpp" -#include "openvic/utility/NumberUtils.hpp" -#include "openvic/utility/StringUtils.hpp" - -#include "FPLUT.hpp" - -namespace OpenVic { - struct FP { - static constexpr size_t SIZE = 8; - - constexpr FP() : value { 0 } {} - constexpr FP(int64_t new_value) : value { new_value } {} - constexpr FP(int32_t new_value) : value { static_cast<int64_t>(new_value) << FPLUT::PRECISION } {} - - // Trivial destructor - ~FP() = default; - - static constexpr FP max() { - return std::numeric_limits<int64_t>::max(); - } - - static constexpr FP min() { - return std::numeric_limits<int64_t>::min(); - } - - static constexpr FP usable_max() { - return static_cast<int64_t>(2147483648LL); - } - - static constexpr FP usable_min() { - return -usable_max(); - } - - static constexpr FP _0() { - return 0; - } - - static constexpr FP _1() { - return 1; - } - - static constexpr FP _2() { - return 2; - } - - static constexpr FP _3() { - return 3; - } - - static constexpr FP _4() { - return 4; - } - - static constexpr FP _5() { - return 5; - } - - static constexpr FP _6() { - return 6; - } - - static constexpr FP _7() { - return 7; - } - - static constexpr FP _8() { - return 8; - } - - static constexpr FP _9() { - return 9; - } - - static constexpr FP _10() { - return 10; - } - - static constexpr FP _50() { - return 50; - } - - static constexpr FP _100() { - return 100; - } - - static constexpr FP _200() { - return 200; - } - - static constexpr FP _0_01() { - return _1() / _100(); - } - - static constexpr FP _0_02() { - return _0_01() * 2; - } - - static constexpr FP _0_03() { - return _0_01() * 3; - } - - static constexpr FP _0_04() { - return _0_01() * 4; - } - - static constexpr FP _0_05() { - return _0_01() * 5; - } - - static constexpr FP _0_10() { - return _1() / 10; - } - - static constexpr FP _0_20() { - return _0_10() * 2; - } - - static constexpr FP _0_25() { - return _1() / 4; - } - - static constexpr FP _0_33() { - return _1() / 3; - } - - static constexpr FP _0_50() { - return _1() / 2; - } - - static constexpr FP _0_75() { - return _1() - _0_25(); - } - - static constexpr FP _0_95() { - return _1() - _0_05(); - } - - static constexpr FP _0_99() { - return _1() - _0_01(); - } - - static constexpr FP _1_01() { - return _1() + _0_01(); - } - - static constexpr FP _1_10() { - return _1() + _0_10(); - } - - static constexpr FP _1_50() { - return _1() + _0_50(); - } - - static constexpr FP minus_one() { - return -1; - } - - static constexpr FP pi() { - return static_cast<int64_t>(205887LL); - } - - static constexpr FP pi2() { - return pi() * 2; - } - - static constexpr FP pi_quarter() { - return pi() / 4; - } - - static constexpr FP pi_half() { - return pi() / 2; - } - - static constexpr FP one_div_pi2() { - return 1 / pi2(); - } - - static constexpr FP deg2rad() { - return static_cast<int64_t>(1143LL); - } - - static constexpr FP rad2deg() { - return static_cast<int64_t>(3754936LL); - } - - static constexpr FP e() { - return static_cast<int64_t>(178145LL); - } - - constexpr bool is_negative() const { - return value < 0; - } - - constexpr FP abs() const { - return !is_negative() ? value : -value; - } - - // Doesn't account for sign, so -n.abc -> 1 - 0.abc - constexpr FP get_frac() const { - return value & (FPLUT::ONE - 1); - } - - constexpr int64_t to_int64_t() const { - return value >> FPLUT::PRECISION; - } - - constexpr void set_raw_value(int64_t value) { - this->value = value; - } - - constexpr int64_t get_raw_value() const { - return value; - } - - constexpr int32_t to_int32_t() const { - return static_cast<int32_t>(to_int64_t()); - } - - constexpr float to_float() const { - return value / static_cast<float>(FPLUT::ONE); - } - - constexpr float to_float_rounded() const { - return static_cast<float>(NumberUtils::round_to_int64((value / static_cast<float>(FPLUT::ONE)) * 100000.0f)) / 100000.0f; - } - - constexpr double to_double() const { - return value / static_cast<double>(FPLUT::ONE); - } - - constexpr float to_double_rounded() const { - return NumberUtils::round_to_int64((value / static_cast<double>(FPLUT::ONE)) * 100000.0) / 100000.0; - } - - std::string to_string() const { - FP val = abs(); - std::string str = std::to_string(val.to_int64_t()) + "."; - if (is_negative()) str = "-" + str; - val = val.get_frac(); - do { - val *= 10; - str.push_back('0' + static_cast<char>(val.to_int64_t())); - val = val.get_frac(); - } while (val > 0); - return str; - } - - // Deterministic - static constexpr FP parse_raw(int64_t value) { - return value; - } - - // Deterministic - static constexpr FP parse(int64_t value) { - return value << FPLUT::PRECISION; - } - - // Deterministic - static constexpr FP parse(char const* str, char const* const end, bool* successful = nullptr) { - if (successful != nullptr) *successful = false; - - if (str == nullptr || str >= end) { - return _0(); - } - - bool negative = false; - - if (*str == '-') { - negative = true; - ++str; - if (str == end) return _0(); - } - - char const* dot_pointer = str; - while (*dot_pointer != '.' && ++dot_pointer != end); - - if (dot_pointer == str && dot_pointer + 1 == end) { - // Invalid: ".", "+." or "-." - return _0(); - } - - FP result = _0(); - if (successful != nullptr) *successful = true; - - if (dot_pointer != str) { - // Non-empty integer part - bool int_successful = false; - result += parse_integer(str, dot_pointer, &int_successful); - if (!int_successful && successful != nullptr) *successful = false; - } - - if (dot_pointer + 1 < end) { - // Non-empty fractional part - bool frac_successful = false; - result += parse_fraction(dot_pointer + 1, end, &frac_successful); - if (!frac_successful && successful != nullptr) *successful = false; - } - - return negative ? -result : result; - } - - static constexpr FP parse(char const* str, size_t length, bool* successful = nullptr) { - return parse(str, str + length, successful); - } - - static FP parse(const std::string_view str, bool* successful = nullptr) { - return parse(str.data(), str.length(), successful); - } - - // Not Deterministic - static constexpr FP parse_unsafe(float value) { - return static_cast<int64_t>(value * FPLUT::ONE + 0.5f * (value < 0 ? -1 : 1)); - } - - // Not Deterministic - static FP parse_unsafe(char const* value) { - char* endpointer; - double double_value = std::strtod(value, &endpointer); - - if (*endpointer != '\0') { - Logger::error("Unsafe fixed point parse failed to parse the end of a string: \"", endpointer, "\""); - } - - int64_t integer_value = static_cast<long>(double_value * FPLUT::ONE + 0.5 * (double_value < 0 ? -1 : 1)); - - return integer_value; - } - - constexpr operator int32_t() const { - return to_int32_t(); - } - - constexpr operator int64_t() const { - return to_int64_t(); - } - - constexpr operator float() const { - return to_float(); - } - - constexpr operator double() const { - return to_double(); - } - - operator std::string() const { - return to_string(); - } - - friend std::ostream& operator<<(std::ostream& stream, FP const& obj) { - return stream << obj.to_string(); - } - - constexpr friend FP operator-(FP const& obj) { - return -obj.value; - } - - constexpr friend FP operator+(FP const& obj) { - return +obj.value; - } - - constexpr friend FP operator+(FP const& lhs, FP const& rhs) { - return lhs.value + rhs.value; - } - - constexpr friend FP operator+(FP const& lhs, int32_t const& rhs) { - return lhs.value + (static_cast<int64_t>(rhs) << FPLUT::PRECISION); - } - - constexpr friend FP operator+(int32_t const& lhs, FP const& rhs) { - return (static_cast<int64_t>(lhs) << FPLUT::PRECISION) + rhs.value; - } - - constexpr FP operator+=(FP const& obj) { - value += obj.value; - return *this; - } - - constexpr FP operator+=(int32_t const& obj) { - value += (static_cast<int64_t>(obj) << FPLUT::PRECISION); - return *this; - } - - constexpr friend FP operator-(FP const& lhs, FP const& rhs) { - return lhs.value - rhs.value; - } - - constexpr friend FP operator-(FP const& lhs, int32_t const& rhs) { - return lhs.value - (static_cast<int64_t>(rhs) << FPLUT::PRECISION); - } - - constexpr friend FP operator-(int32_t const& lhs, FP const& rhs) { - return (static_cast<int64_t>(lhs) << FPLUT::PRECISION) - rhs.value; - } - - constexpr FP operator-=(FP const& obj) { - value -= obj.value; - return *this; - } - - constexpr FP operator-=(int32_t const& obj) { - value -= (static_cast<int64_t>(obj) << FPLUT::PRECISION); - return *this; - } - - constexpr friend FP operator*(FP const& lhs, FP const& rhs) { - return lhs.value * rhs.value >> FPLUT::PRECISION; - } - - constexpr friend FP operator*(FP const& lhs, int32_t const& rhs) { - return lhs.value * rhs; - } - - constexpr friend FP operator*(int32_t const& lhs, FP const& rhs) { - return lhs * rhs.value; - } - - constexpr FP operator*=(FP const& obj) { - value *= obj.value >> FPLUT::PRECISION; - return *this; - } - - constexpr FP operator*=(int32_t const& obj) { - value *= obj; - return *this; - } - - constexpr friend FP operator/(FP const& lhs, FP const& rhs) { - return (lhs.value << FPLUT::PRECISION) / rhs.value; - } - - constexpr friend FP operator/(FP const& lhs, int32_t const& rhs) { - return lhs.value / rhs; - } - - constexpr friend FP operator/(int32_t const& lhs, FP const& rhs) { - return (static_cast<int64_t>(lhs) << (2 * FPLUT::PRECISION)) / rhs.value; - } - - constexpr FP operator/=(FP const& obj) { - value = (value << FPLUT::PRECISION) / obj.value; - return *this; - } - - constexpr FP operator/=(int32_t const& obj) { - value /= obj; - return *this; - } - - constexpr friend FP operator%(FP const& lhs, FP const& rhs) { - return lhs.value % rhs.value; - } - - constexpr friend FP operator%(FP const& lhs, int32_t const& rhs) { - return lhs.value % (static_cast<int64_t>(rhs) << FPLUT::PRECISION); - } - - constexpr friend FP operator%(int32_t const& lhs, FP const& rhs) { - return (static_cast<int64_t>(lhs) << FPLUT::PRECISION) % rhs.value; - } - - constexpr FP operator%=(FP const& obj) { - value %= obj.value; - return *this; - } - - constexpr FP operator%=(int32_t const& obj) { - value %= (static_cast<int64_t>(obj) << FPLUT::PRECISION); - return *this; - } - - constexpr friend bool operator<(FP const& lhs, FP const& rhs) { - return lhs.value < rhs.value; - } - - constexpr friend bool operator<(FP const& lhs, int32_t const& rhs) { - return lhs.value < static_cast<int64_t>(rhs) << FPLUT::PRECISION; - } - - constexpr friend bool operator<(int32_t const& lhs, FP const& rhs) { - return static_cast<int64_t>(lhs) << FPLUT::PRECISION < rhs.value; - } - - constexpr friend bool operator<=(FP const& lhs, FP const& rhs) { - return lhs.value <= rhs.value; - } - - constexpr friend bool operator<=(FP const& lhs, int32_t const& rhs) { - return lhs.value <= static_cast<int64_t>(rhs) << FPLUT::PRECISION; - } - - constexpr friend bool operator<=(int32_t const& lhs, FP const& rhs) { - return static_cast<int64_t>(lhs) << FPLUT::PRECISION <= rhs.value; - } - - constexpr friend bool operator>(FP const& lhs, FP const& rhs) { - return lhs.value > rhs.value; - } - - constexpr friend bool operator>(FP const& lhs, int32_t const& rhs) { - return lhs.value > static_cast<int64_t>(rhs) << FPLUT::PRECISION; - } - - constexpr friend bool operator>(int32_t const& lhs, FP const& rhs) { - return static_cast<int64_t>(lhs) << FPLUT::PRECISION > rhs.value; - } - - constexpr friend bool operator>=(FP const& lhs, FP const& rhs) { - return lhs.value >= rhs.value; - } - - constexpr friend bool operator>=(FP const& lhs, int32_t const& rhs) { - return lhs.value >= static_cast<int64_t>(rhs) << FPLUT::PRECISION; - } - - constexpr friend bool operator>=(int32_t const& lhs, FP const& rhs) { - return static_cast<int64_t>(lhs) << FPLUT::PRECISION >= rhs.value; - } - - constexpr friend bool operator==(FP const& lhs, FP const& rhs) { - return lhs.value == rhs.value; - } - - constexpr friend bool operator==(FP const& lhs, int32_t const& rhs) { - return lhs.value == static_cast<int64_t>(rhs) << FPLUT::PRECISION; - } - - constexpr friend bool operator==(int32_t const& lhs, FP const& rhs) { - return static_cast<int64_t>(lhs) << FPLUT::PRECISION == rhs.value; - } - - constexpr friend bool operator!=(FP const& lhs, FP const& rhs) { - return lhs.value != rhs.value; - } - - constexpr friend bool operator!=(FP const& lhs, int32_t const& rhs) { - return lhs.value != static_cast<int64_t>(rhs) << FPLUT::PRECISION; - } - - constexpr friend bool operator!=(int32_t const& lhs, FP const& rhs) { - return static_cast<int64_t>(lhs) << FPLUT::PRECISION != rhs.value; - } - - private: - int64_t value; - - static constexpr FP parse_integer(char const* str, char const* const end, bool* successful) { - int64_t parsed_value = StringUtils::string_to_int64(str, end, successful, 10); - return parse(parsed_value); - } - - static constexpr FP parse_fraction(char const* str, char const* end, bool* successful) { - char const* const read_end = str + FPLUT::PRECISION; - if (read_end < end) end = read_end; - uint64_t parsed_value = StringUtils::string_to_uint64(str, end, successful, 10); - while (end++ < read_end) { - parsed_value *= 10; - } - uint64_t decimal = NumberUtils::pow(static_cast<uint64_t>(10), FPLUT::PRECISION); - int64_t ret = 0; - for (int i = FPLUT::PRECISION - 1; i >= 0; --i) { - decimal >>= 1; - if (parsed_value > decimal) { - parsed_value -= decimal; - ret |= 1 << i; - } - } - return ret; - } - }; - - static_assert(sizeof(FP) == FP::SIZE, "FP is not 8 bytes"); -} diff --git a/src/openvic/types/fixed_point/FPLUT.hpp b/src/openvic/types/fixed_point/FPLUT.hpp deleted file mode 100644 index f9b21ab..0000000 --- a/src/openvic/types/fixed_point/FPLUT.hpp +++ /dev/null @@ -1,33 +0,0 @@ -#pragma once - -#include <array> -#include <cmath> -#include <cstddef> -#include <cstdint> -#include <numbers> -#include <utility> - -#include "FPLUT_sin_512.hpp" - -namespace OpenVic::FPLUT { - constexpr int32_t PRECISION = 16; - constexpr int64_t ONE = 1 << PRECISION; - - // The LUT index is between 0 and 2^16, the index table goes until 512, if we shift by 7 our index will be between 0 and 511 - constexpr int32_t SHIFT = 16 - 9; - - constexpr int64_t sin(int64_t value) { - int sign = 1; - if (value < 0) { - value = -value; - sign = -1; - } - - int index = value >> SHIFT; - int64_t a = SIN_LUT[index]; - int64_t b = SIN_LUT[index + 1]; - int64_t fraction = (value - (index << SHIFT)) << 9; - int64_t result = a + (((b - a) * fraction) >> PRECISION); - return result * sign; - } -} diff --git a/src/openvic/types/fixed_point/FPLUT_sin_512.hpp b/src/openvic/types/fixed_point/FPLUT_sin_512.hpp deleted file mode 100644 index 1af0380..0000000 --- a/src/openvic/types/fixed_point/FPLUT_sin_512.hpp +++ /dev/null @@ -1,58 +0,0 @@ -#pragma once - -#include <cstdint> - -static constexpr int32_t SIN_LUT[] = { - 0, 804, 1608, 2412, 3216, 4019, 4821, 5623, 6424, 7224, - 8022, 8820, 9616, 10411, 11204, 11996, 12785, 13573, 14359, 15143, - 15924, 16703, 17479, 18253, 19024, 19792, 20557, 21320, 22078, 22834, - 23586, 24335, 25080, 25821, 26558, 27291, 28020, 28745, 29466, 30182, - 30893, 31600, 32303, 33000, 33692, 34380, 35062, 35738, 36410, 37076, - 37736, 38391, 39040, 39683, 40320, 40951, 41576, 42194, 42806, 43412, - 44011, 44604, 45190, 45769, 46341, 46906, 47464, 48015, 48559, 49095, - 49624, 50146, 50660, 51166, 51665, 52156, 52639, 53114, 53581, 54040, - 54491, 54934, 55368, 55794, 56212, 56621, 57022, 57414, 57798, 58172, - 58538, 58896, 59244, 59583, 59914, 60235, 60547, 60851, 61145, 61429, - 61705, 61971, 62228, 62476, 62714, 62943, 63162, 63372, 63572, 63763, - 63944, 64115, 64277, 64429, 64571, 64704, 64827, 64940, 65043, 65137, - 65220, 65294, 65358, 65413, 65457, 65492, 65516, 65531, 65536, 65531, - 65516, 65492, 65457, 65413, 65358, 65294, 65220, 65137, 65043, 64940, - 64827, 64704, 64571, 64429, 64277, 64115, 63944, 63763, 63572, 63372, - 63162, 62943, 62714, 62476, 62228, 61971, 61705, 61429, 61145, 60851, - 60547, 60235, 59914, 59583, 59244, 58896, 58538, 58172, 57798, 57414, - 57022, 56621, 56212, 55794, 55368, 54934, 54491, 54040, 53581, 53114, - 52639, 52156, 51665, 51166, 50660, 50146, 49624, 49095, 48559, 48015, - 47464, 46906, 46341, 45769, 45190, 44604, 44011, 43412, 42806, 42194, - 41576, 40951, 40320, 39683, 39040, 38391, 37736, 37076, 36410, 35738, - 35062, 34380, 33692, 33000, 32303, 31600, 30893, 30182, 29466, 28745, - 28020, 27291, 26558, 25821, 25080, 24335, 23586, 22834, 22078, 21320, - 20557, 19792, 19024, 18253, 17479, 16703, 15924, 15143, 14359, 13573, - 12785, 11996, 11204, 10411, 9616, 8820, 8022, 7224, 6424, 5623, - 4821, 4019, 3216, 2412, 1608, 804, 0, -804, -1608, -2412, - -3216, -4019, -4821, -5623, -6424, -7224, -8022, -8820, -9616, -10411, - -11204, -11996, -12785, -13573, -14359, -15143, -15924, -16703, -17479, -18253, - -19024, -19792, -20557, -21320, -22078, -22834, -23586, -24335, -25080, -25821, - -26558, -27291, -28020, -28745, -29466, -30182, -30893, -31600, -32303, -33000, - -33692, -34380, -35062, -35738, -36410, -37076, -37736, -38391, -39040, -39683, - -40320, -40951, -41576, -42194, -42806, -43412, -44011, -44604, -45190, -45769, - -46341, -46906, -47464, -48015, -48559, -49095, -49624, -50146, -50660, -51166, - -51665, -52156, -52639, -53114, -53581, -54040, -54491, -54934, -55368, -55794, - -56212, -56621, -57022, -57414, -57798, -58172, -58538, -58896, -59244, -59583, - -59914, -60235, -60547, -60851, -61145, -61429, -61705, -61971, -62228, -62476, - -62714, -62943, -63162, -63372, -63572, -63763, -63944, -64115, -64277, -64429, - -64571, -64704, -64827, -64940, -65043, -65137, -65220, -65294, -65358, -65413, - -65457, -65492, -65516, -65531, -65536, -65531, -65516, -65492, -65457, -65413, - -65358, -65294, -65220, -65137, -65043, -64940, -64827, -64704, -64571, -64429, - -64277, -64115, -63944, -63763, -63572, -63372, -63162, -62943, -62714, -62476, - -62228, -61971, -61705, -61429, -61145, -60851, -60547, -60235, -59914, -59583, - -59244, -58896, -58538, -58172, -57798, -57414, -57022, -56621, -56212, -55794, - -55368, -54934, -54491, -54040, -53581, -53114, -52639, -52156, -51665, -51166, - -50660, -50146, -49624, -49095, -48559, -48015, -47464, -46906, -46341, -45769, - -45190, -44604, -44011, -43412, -42806, -42194, -41576, -40951, -40320, -39683, - -39040, -38391, -37736, -37076, -36410, -35738, -35062, -34380, -33692, -33000, - -32303, -31600, -30893, -30182, -29466, -28745, -28020, -27291, -26558, -25821, - -25080, -24335, -23586, -22834, -22078, -21320, -20557, -19792, -19024, -18253, - -17479, -16703, -15924, -15143, -14359, -13573, -12785, -11996, -11204, -10411, - -9616, -8820, -8022, -7224, -6424, -5623, -4821, -4019, -3216, -2412, - -1608, -804, 0 -}; diff --git a/src/openvic/types/fixed_point/FPMath.hpp b/src/openvic/types/fixed_point/FPMath.hpp deleted file mode 100644 index 965d63c..0000000 --- a/src/openvic/types/fixed_point/FPMath.hpp +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once - -#include "FP.hpp" - -namespace OpenVic::FPMath { - constexpr FP sin(FP number) { - number %= FP::pi2(); - number *= FP::one_div_pi2(); - return FPLUT::sin(number.get_raw_value()); - } -} diff --git a/src/openvic/types/fixed_point/lut_generator/lut_generator.py b/src/openvic/types/fixed_point/lut_generator/lut_generator.py deleted file mode 100644 index 5c5ba8b..0000000 --- a/src/openvic/types/fixed_point/lut_generator/lut_generator.py +++ /dev/null @@ -1,39 +0,0 @@ -#!/usr/bin/env python -import math - -PRECISION = 16 -ONE = 1 << PRECISION -SIN_VALUE_COUNT = 512 - -SinLut = [] - -for i in range(SIN_VALUE_COUNT): - angle = 2 * math.pi * i / SIN_VALUE_COUNT - - sin_value = math.sin(angle) - moved_sin = sin_value * ONE - rounded_sin = int(moved_sin + 0.5) if moved_sin > 0 else int(moved_sin - 0.5) - SinLut.append(rounded_sin) - -SinLut.append(SinLut[0]) - -output = [ -"""#pragma once - -#include <cstdint> - -static constexpr int32_t SIN_LUT[] = {""" -] - -lines = [SinLut[i:i+10] for i in range(0, len(SinLut), 10)] - -for line in lines: - output.append("\t" + ", ".join(str(value) for value in line) + ",") - -output[-1] = output[-1][:-1] # Remove the last comma -output.append("};\n") - -cpp_code = "\n".join(output) - -with open(f"FPLUT_sin_{SIN_VALUE_COUNT}.hpp", "w", newline="\n") as file: - file.write(cpp_code) diff --git a/src/openvic/utility/BMP.cpp b/src/openvic/utility/BMP.cpp deleted file mode 100644 index 0ea0f30..0000000 --- a/src/openvic/utility/BMP.cpp +++ /dev/null @@ -1,163 +0,0 @@ -#include "BMP.hpp" - -#include <cstring> -#include <set> - -#include "openvic/utility/Logger.hpp" - -using namespace OpenVic; - -BMP::~BMP() { - close(); -} - -bool BMP::open(char const* filepath) { - reset(); - errno = 0; - file = fopen(filepath, "rb"); - if (file == nullptr || errno != 0) { - Logger::error("Failed to open BMP file \"", filepath, "\" (errno = ", errno, ")"); - file = nullptr; - return false; - } - return true; -} - -bool BMP::read_header() { - if (header_validated) { - Logger::error("BMP header already validated!"); - return false; - } - if (file == nullptr) { - Logger::error("Cannot read BMP header before opening a file"); - return false; - } - if (fseek(file, 0, SEEK_SET) != 0) { - Logger::error("Failed to move to the beginning of the BMP file!"); - return false; - } - if (fread(&header, sizeof(header), 1, file) != 1) { - Logger::error("Failed to read BMP header!"); - return false; - } - - header_validated = true; - - // Validate constants - static constexpr uint16_t BMP_SIGNATURE = 0x4d42; - if (header.signature != BMP_SIGNATURE) { - Logger::error("Invalid BMP signature: ", header.signature, " (must be ", BMP_SIGNATURE, ")"); - header_validated = false; - } - static constexpr uint32_t DIB_HEADER_SIZE = 40; - if (header.dib_header_size != DIB_HEADER_SIZE) { - Logger::error("Invalid BMP DIB header size: ", header.dib_header_size, " (must be ", DIB_HEADER_SIZE, ")"); - header_validated = false; - } - static constexpr uint16_t NUM_PLANES = 1; - if (header.num_planes != NUM_PLANES) { - Logger::error("Invalid BMP plane count: ", header.num_planes, " (must be ", NUM_PLANES, ")"); - header_validated = false; - } - static constexpr uint16_t COMPRESSION = 0; // Only support uncompressed BMPs - if (header.compression != COMPRESSION) { - Logger::error("Invalid BMP compression method: ", header.compression, " (must be ", COMPRESSION, ")"); - header_validated = false; - } - - // Validate sizes and dimensions - // TODO - image_size_bytes can be 0 for non-compressed BMPs - if (header.file_size != header.offset + header.image_size_bytes) { - Logger::error("Invalid BMP memory sizes: file size = ", header.file_size, " != ", header.offset + header.image_size_bytes, - " = ", header.offset, " + ", header.image_size_bytes, " = image data offset + image data size"); - header_validated = false; - } - // TODO - support negative widths (i.e. horizontal flip) - if (header.width_px <= 0) { - Logger::error("Invalid BMP width: ", header.width_px, " (must be positive)"); - header_validated = false; - } - // TODO - support negative heights (i.e. vertical flip) - if (header.height_px <= 0) { - Logger::error("Invalid BMP height: ", header.height_px, " (must be positive)"); - header_validated = false; - } - // TODO - validate x_resolution_ppm - // TODO - validate y_resolution_ppm - - // Validate colours -#define VALID_BITS_PER_PIXEL 1, 2, 4, 8, 16, 24, 32 -#define STR(x) #x - static const std::set<uint16_t> BITS_PER_PIXEL { VALID_BITS_PER_PIXEL }; - if (!BITS_PER_PIXEL.contains(header.bits_per_pixel)) { - Logger::error("Invalid BMP bits per pixel: ", header.bits_per_pixel, " (must be one of " STR(VALID_BITS_PER_PIXEL) ")"); - header_validated = false; - } -#undef VALID_BITS_PER_PIXEL -#undef STR - static constexpr uint16_t PALETTE_BITS_PER_PIXEL_LIMIT = 8; - if (header.num_colours != 0 && header.bits_per_pixel > PALETTE_BITS_PER_PIXEL_LIMIT) { - Logger::error("Invalid BMP palette size: ", header.num_colours, " (should be 0 as bits per pixel is ", header.bits_per_pixel, " > 8)"); - header_validated = false; - } - // TODO - validate important_colours - - palette_size = header.bits_per_pixel > PALETTE_BITS_PER_PIXEL_LIMIT ? 0 - // Use header.num_colours if it's greater than 0 and at most 1 << header.bits_per_pixel - : 0 < header.num_colours && header.num_colours - 1 >> header.bits_per_pixel == 0 ? header.num_colours - : 1 << header.bits_per_pixel; - - const uint32_t expected_offset = palette_size * PALETTE_COLOUR_SIZE + sizeof(header); - if (header.offset != expected_offset) { - Logger::error("Invalid BMP image data offset: ", header.offset, " (should be ", expected_offset, ")"); - header_validated = false; - } - - return header_validated; -} - -bool BMP::read_palette() { - if (file == nullptr) { - Logger::error("Cannot read BMP palette before opening a file"); - return false; - } - if (!header_validated) { - Logger::error("Cannot read palette before BMP header is validated!"); - return false; - } - if (palette_size == 0) { - Logger::error("Cannot read BMP palette - header indicates this file doesn't have one"); - return false; - } - if (fseek(file, sizeof(header), SEEK_SET) != 0) { - Logger::error("Failed to move to the palette in the BMP file!"); - return false; - } - palette.resize(palette_size); - if (fread(palette.data(), palette_size * PALETTE_COLOUR_SIZE, 1, file) != 1) { - Logger::error("Failed to read BMP header!"); - palette.clear(); - return false; - } - return true; -} - -void BMP::close() { - if (file != nullptr) { - if (fclose(file) != 0) - Logger::error("Failed to close BMP!"); - file = nullptr; - } -} - -void BMP::reset() { - close(); - memset(&header, 0, sizeof(header)); - header_validated = false; - palette_size = 0; - palette.clear(); -} - -std::vector<colour_t> const& BMP::get_palette() const { - return palette; -} diff --git a/src/openvic/utility/BMP.hpp b/src/openvic/utility/BMP.hpp deleted file mode 100644 index 7ed36a5..0000000 --- a/src/openvic/utility/BMP.hpp +++ /dev/null @@ -1,51 +0,0 @@ -#pragma once - -#include <cstdio> -#include <vector> - -#include "openvic/types/Colour.hpp" - -namespace OpenVic { - class BMP { -#pragma pack(push) -#pragma pack(1) - struct header_t { - uint16_t signature; // Signature: 0x4d42 (or 'B' 'M') - uint32_t file_size; // File size in bytes - uint16_t reserved1; // Not used - uint16_t reserved2; // Not used - uint32_t offset; // Offset to image data in bytes from beginning of file - uint32_t dib_header_size; // DIB header size in bytes - int32_t width_px; // Width of the image - int32_t height_px; // Height of image - uint16_t num_planes; // Number of colour planes - uint16_t bits_per_pixel; // Bits per pixel - uint32_t compression; // Compression type - uint32_t image_size_bytes; // Image size in bytes - int32_t x_resolution_ppm; // Pixels per meter - int32_t y_resolution_ppm; // Pixels per meter - uint32_t num_colours; // Number of colours - uint32_t important_colours; // Important colours - } header; -#pragma pack(pop) - - FILE* file = nullptr; - bool header_validated = false; - uint32_t palette_size = 0; - std::vector<colour_t> palette; - - public: - static constexpr uint32_t PALETTE_COLOUR_SIZE = sizeof(colour_t); - - BMP() = default; - ~BMP(); - - bool open(char const* filepath); - bool read_header(); - bool read_palette(); - void close(); - void reset(); - - std::vector<colour_t> const& get_palette() const; - }; -} diff --git a/src/openvic/utility/Logger.cpp b/src/openvic/utility/Logger.cpp deleted file mode 100644 index bf9a67c..0000000 --- a/src/openvic/utility/Logger.cpp +++ /dev/null @@ -1,20 +0,0 @@ -#include "Logger.hpp" - -#include <iostream> - -using namespace OpenVic; - -Logger::log_func_t Logger::info_func {}; -Logger::log_queue_t Logger::info_queue {}; -Logger::log_func_t Logger::error_func {}; -Logger::log_queue_t Logger::error_queue {}; - -char const* Logger::get_filename(char const* filepath) { - if (filepath == nullptr) return nullptr; - char const* last_slash = filepath; - while (*filepath != '\0') { - if (*filepath == '\\' || *filepath == '/') last_slash = filepath + 1; - filepath++; - } - return last_slash; -} diff --git a/src/openvic/utility/Logger.hpp b/src/openvic/utility/Logger.hpp deleted file mode 100644 index 417aba7..0000000 --- a/src/openvic/utility/Logger.hpp +++ /dev/null @@ -1,87 +0,0 @@ -#pragma once - -#include <functional> -#include <queue> -#include <sstream> -#ifdef __cpp_lib_source_location -#include <source_location> -#endif - -namespace OpenVic { - -#ifndef __cpp_lib_source_location -#include <string> - // Implementation of std::source_location for compilers that do not support it - // Note: uses non-standard extensions that are supported by Clang, GCC, and MSVC - // https://clang.llvm.org/docs/LanguageExtensions.html#source-location-builtins - // https://stackoverflow.com/a/67970107 - class source_location { - std::string _file; - int _line; - std::string _function; - - public: - source_location(std::string f, int l, std::string n) : _file(f), _line(l), _function(n) {} - static source_location current(std::string f = __builtin_FILE(), int l = __builtin_LINE(), std::string n = __builtin_FUNCTION()) { - return source_location(f, l, n); - } - - inline char const* file_name() const { return _file.c_str(); } - inline int line() const { return _line; } - inline char const* function_name() const { return _function.c_str(); } - }; -#endif - - class Logger { - using log_func_t = std::function<void(std::string&&)>; - using log_queue_t = std::queue<std::string>; - -#ifdef __cpp_lib_source_location - using source_location = std::source_location; -#else - using source_location = OpenVic::source_location; -#endif - - static char const* get_filename(char const* filepath); - - template<typename... Ts> - struct log { - log(log_func_t log_func, log_queue_t& log_queue, Ts&&... ts, source_location const& location) { - std::stringstream stream; - stream << "\n" << get_filename(location.file_name()) << "(" - << location.line() << ") `" << location.function_name() << "`: "; - ((stream << std::forward<Ts>(ts)), ...); - stream << std::endl; - log_queue.push(stream.str()); - if (log_func) { - do { - log_func(std::move(log_queue.front())); - log_queue.pop(); - } while (!log_queue.empty()); - } - } - }; - -#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) - LOG_FUNC(error) - -#undef LOG_FUNC - }; -} diff --git a/src/openvic/utility/NumberUtils.hpp b/src/openvic/utility/NumberUtils.hpp deleted file mode 100644 index 6211772..0000000 --- a/src/openvic/utility/NumberUtils.hpp +++ /dev/null @@ -1,27 +0,0 @@ -#include <cstdint> - -namespace OpenVic::NumberUtils { - constexpr int64_t round_to_int64(float num) { - return (num > 0.0f) ? (num + 0.5f) : (num - 0.5f); - } - - constexpr int64_t round_to_int64(double num) { - return (num > 0.0) ? (num + 0.5) : (num - 0.5); - } - - constexpr uint64_t pow(uint64_t base, size_t exponent) { - uint64_t ret = 1; - while (exponent-- > 0) { - ret *= base; - } - return ret; - } - - constexpr int64_t pow(int64_t base, size_t exponent) { - int64_t ret = 1; - while (exponent-- > 0) { - ret *= base; - } - return ret; - } -} diff --git a/src/openvic/utility/StringUtils.hpp b/src/openvic/utility/StringUtils.hpp deleted file mode 100644 index 5d6001c..0000000 --- a/src/openvic/utility/StringUtils.hpp +++ /dev/null @@ -1,127 +0,0 @@ -#include <cstdint> -#include <limits> -#include <string_view> - -namespace OpenVic::StringUtils { - /* The constexpr function 'string_to_uint64' will convert a string into a uint64_t integer value. - * The function takes four parameters: the input string (as a pair of pointers marking the start and - * end of the string), a bool pointer for reporting success, and the base for numerical conversion. - * The base parameter defaults to 10 (decimal), but it can be any value between 2 and 36. If the base - * given is 0, it will be set to 16 if the string starts with "0x" or "0X", otherwise 8 if the string - * still starts with "0", otherwise 10. The success bool pointer parameter is used to report whether - * or not conversion was successful. It can be nullptr if this information is not needed. - */ - constexpr uint64_t string_to_uint64(char const* str, const char* const end, bool* successful = nullptr, int base = 10) { - if (successful != nullptr) *successful = false; - - // Base value should be between 2 and 36. If it's not, return 0 as an invalid case. - if (str == nullptr || end <= str || base < 0 || base == 1 || base > 36) - return 0; - - // The result of the conversion will be stored in this variable. - uint64_t result = 0; - - // If base is zero, base is determined by the string prefix. - if (base == 0) { - if (*str == '0') { - if (str + 1 != end && (str[1] == 'x' || str[1] == 'X')) { - base = 16; // Hexadecimal. - str += 2; // Skip '0x' or '0X' - if (str == end) return 0; - } else { - base = 8; // Octal. - } - } else { - base = 10; // Decimal. - } - } else if (base == 16) { - // If base is 16 and string starts with '0x' or '0X', skip these characters. - if (*str == '0' && str + 1 != end && (str[1] == 'x' || str[1] == 'X')) { - str += 2; - if (str == end) return 0; - } - } - - // Convert the number in the string. - for (; str != end; ++str) { - int digit; - if (*str >= '0' && *str <= '9') { - digit = *str - '0'; // Calculate digit value for '0'-'9'. - } else if (*str >= 'a' && *str <= 'z') { - digit = *str - 'a' + 10; // Calculate digit value for 'a'-'z'. - } else if (*str >= 'A' && *str <= 'Z') { - digit = *str - 'A' + 10; // Calculate digit value for 'A'-'Z'. - } else { - break; // Stop conversion if current character is not a digit. - } - - if (digit >= base) { - break; // Stop conversion if current digit is greater than or equal to the base. - } - - // Check for overflow on multiplication - if (result > std::numeric_limits<uint64_t>::max() / base) { - return std::numeric_limits<uint64_t>::max(); - } - - result *= base; - - // Check for overflow on addition - if (result > std::numeric_limits<uint64_t>::max() - digit) { - return std::numeric_limits<uint64_t>::max(); - } - - result += digit; - } - - // If successful is not null and the entire string was parsed, - // set *successful to true (if not it is already false). - if (successful != nullptr && str == end) *successful = true; - - return result; - } - - constexpr uint64_t string_to_uint64(char const* str, size_t length, bool* successful = nullptr, int base = 10) { - return string_to_uint64(str, str + length, successful, base); - } - - inline uint64_t string_to_uint64(const std::string_view str, bool* successful = nullptr, int base = 10) { - return string_to_uint64(str.data(), str.length(), successful, base); - } - - constexpr int64_t string_to_int64(char const* str, const char* const end, bool* successful = nullptr, int base = 10) { - if (successful != nullptr) *successful = false; - - if (str == nullptr || end <= str) return 0; - - // This flag will be set if the number is negative. - bool is_negative = false; - - // Check if there is a sign character. - if (*str == '+' || *str == '-') { - if (*str == '-') - is_negative = true; - ++str; - if (str == end) return 0; - } - - const uint64_t result = string_to_uint64(str, end, successful, base); - if (!is_negative) { - if (result >= std::numeric_limits<int64_t>::max()) - return std::numeric_limits<int64_t>::max(); - return result; - } else { - if (result > std::numeric_limits<int64_t>::max()) - return std::numeric_limits<int64_t>::min(); - return -result; - } - } - - constexpr int64_t string_to_int64(char const* str, size_t length, bool* successful = nullptr, int base = 10) { - return string_to_int64(str, str + length, successful, base); - } - - inline int64_t string_to_int64(const std::string_view str, bool* successful = nullptr, int base = 10) { - return string_to_int64(str.data(), str.length(), successful, base); - } -} |