diff options
Diffstat (limited to 'src/openvic-simulation/map')
-rw-r--r-- | src/openvic-simulation/map/Building.cpp | 250 | ||||
-rw-r--r-- | src/openvic-simulation/map/Building.hpp | 153 | ||||
-rw-r--r-- | src/openvic-simulation/map/Province.cpp | 21 | ||||
-rw-r--r-- | src/openvic-simulation/map/Province.hpp | 8 |
4 files changed, 334 insertions, 98 deletions
diff --git a/src/openvic-simulation/map/Building.cpp b/src/openvic-simulation/map/Building.cpp index eba2049..29ee354 100644 --- a/src/openvic-simulation/map/Building.cpp +++ b/src/openvic-simulation/map/Building.cpp @@ -1,45 +1,143 @@ #include "Building.hpp" -#include <cassert> - -#include "openvic-simulation/map/Province.hpp" -#include "openvic-simulation/utility/Logger.hpp" +#include "openvic-simulation/map/Province.hpp" //imported here so the hpp doesn't get circular imports using namespace OpenVic; +using namespace OpenVic::NodeTools; -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(); -} +Building::Building(std::string_view identifier, ARGS) : HasIdentifier { identifier }, ModifierValue { std::move(modifiers) }, type { type }, + on_completion { on_completion }, completion_size { completion_size }, max_level { max_level }, goods_cost { goods_cost }, cost { cost }, build_time { build_time }, + visibility { visibility }, on_map { on_map }, default_enabled { default_enabled }, production_type { production_type }, pop_build_factory { pop_build_factory }, + strategic_factory { strategic_factory }, advanced_factory { advanced_factory }, fort_level { fort_level }, naval_capacity { naval_capacity }, + colonial_points { colonial_points }, in_province { in_province }, one_per_state { one_per_state }, colonial_range { colonial_range }, + infrastructure { infrastructure }, movement_cost { movement_cost }, local_ship_build { local_ship_build }, spawn_railway_track { spawn_railway_track }, + sail { sail }, steam { steam }, capital { capital }, port { port } {} BuildingType const& Building::get_type() const { return type; } -Building::level_t Building::get_level() const { +std::string_view Building::get_on_completion() const { + return on_completion; +} + +fixed_point_t Building::get_completion_size() const { + return completion_size; +} + +Building::level_t Building::get_max_level() const { + return max_level; +} + +std::map<const Good*, fixed_point_t> const& Building::get_goods_cost() const { + return goods_cost; +} + +fixed_point_t Building::get_cost() const { + return cost; +} + +Timespan Building::get_build_time() const { + return build_time; +} + +bool Building::has_visibility() const { + return visibility; +} + +bool Building::is_on_map() const { + return on_map; +} + +bool Building::is_default_enabled() const { + return default_enabled; +} + +ProductionType const* Building::get_production_type() const { + return production_type; +} + +bool Building::is_pop_built_factory() const { + return pop_build_factory; +} + +bool Building::is_strategic_factory() const { + return strategic_factory; +} + +bool Building::is_advanced_factory() const { + return advanced_factory; +} + +Building::level_t Building::get_fort_level() const { + return fort_level; +} + +uint64_t Building::get_naval_capacity() const { + return naval_capacity; +} + +std::vector<uint64_t> const& Building::get_colonial_points() const { + return colonial_points; +} + +bool Building::is_in_province() const { + return in_province; +} + +bool Building::is_one_per_state() const { + return one_per_state; +} + +fixed_point_t Building::get_colonial_range() const { + return colonial_range; +} + +fixed_point_t Building::get_infrastructure() const { + return infrastructure; +} + +fixed_point_t Building::get_movement_cost() const { + return movement_cost; +} + +bool Building::spawned_railway_track() const { + return spawn_railway_track; +} + +BuildingType::BuildingType(const std::string_view new_identifier) : HasIdentifier { new_identifier } {} + +BuildingInstance::BuildingInstance(Building const& building) : HasIdentifier { building.get_identifier() }, building { building } {} + +Building const& BuildingInstance::get_building() const { + return building; +} + +bool BuildingInstance::_can_expand() const { + return level < building.get_max_level(); +} + +BuildingInstance::level_t BuildingInstance::get_current_level() const { return level; } -Building::ExpansionState Building::get_expansion_state() const { +ExpansionState BuildingInstance::get_expansion_state() const { return expansion_state; } -Date const& Building::get_start_date() const { +Date const& BuildingInstance::get_start_date() const { return start; } -Date const& Building::get_end_date() const { +Date const& BuildingInstance::get_end_date() const { return end; } -float Building::get_expansion_progress() const { +float BuildingInstance::get_expansion_progress() const { return expansion_progress; } -bool Building::expand() { +bool BuildingInstance::expand() { if (expansion_state == ExpansionState::CanExpand) { expansion_state = ExpansionState::Preparing; expansion_progress = 0.0f; @@ -51,11 +149,11 @@ bool Building::expand() { /* REQUIREMENTS: * MAP-71, MAP-74, MAP-77 */ -void Building::update_state(Date const& today) { +void BuildingInstance::update_state(Date const& today) { switch (expansion_state) { case ExpansionState::Preparing: start = today; - end = start + type.get_build_time(); + end = start + building.get_build_time(); break; case ExpansionState::Expanding: expansion_progress = static_cast<double>(today - start) / static_cast<double>(end - start); @@ -64,7 +162,7 @@ void Building::update_state(Date const& today) { } } -void Building::tick(Date const& today) { +void BuildingInstance::tick(Date const& today) { if (expansion_state == ExpansionState::Preparing) { expansion_state = ExpansionState::Expanding; } @@ -76,38 +174,96 @@ void Building::tick(Date const& today) { } } -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); -} +BuildingManager::BuildingManager() : building_types { "building types" }, buildings { "buildings" } {} -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) { +bool BuildingManager::add_building_type(const std::string_view identifier) { 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 building_types.add_item({ identifier }); +} + +bool BuildingManager::add_building(std::string_view identifier, ARGS) { + if (identifier.empty()) { + Logger::error("Invalid building identifier - empty!"); return false; } - return building_types.add_item({ identifier, max_level, build_time }); + + return buildings.add_item({ + identifier, type, on_completion, completion_size, max_level, goods_cost, cost, build_time, visibility, on_map, default_enabled, + production_type, pop_build_factory, strategic_factory, advanced_factory, fort_level, naval_capacity, colonial_points, in_province, one_per_state, + colonial_range, infrastructure, movement_cost, local_ship_build, spawn_railway_track, sail, steam, capital, port, std::move(modifiers) + }); +} + +bool BuildingManager::load_buildings_file(GoodManager const& good_manager, ProductionTypeManager const& production_type_manager, ModifierManager const& modifier_manager, ast::NodeCPtr root) { + bool ret = expect_dictionary([this, &good_manager, &production_type_manager, &modifier_manager](std::string_view key, ast::NodeCPtr value) -> bool { + std::string_view type, on_completion = "", production_type; + fixed_point_t completion_size = 0, cost = 0, infrastructure = 0, movement_cost = 0, colonial_range = 0, local_ship_build = 0; + Building::level_t max_level, fort_level = 0; + std::map<const Good*, fixed_point_t> goods_cost; + uint32_t build_days; + bool visibility, on_map, default_enabled, pop_build_factory, strategic_factory, advanced_factory, in_province, one_per_state, spawn_railway_track, sail, steam, capital, port; + default_enabled = pop_build_factory = strategic_factory = advanced_factory = in_province = one_per_state = spawn_railway_track = sail = steam = capital = port = false; + uint64_t naval_capacity = 0; + std::vector<uint64_t> colonial_points; + ModifierValue modifiers; + + bool ret = modifier_manager.expect_modifier_value_and_keys(move_variable_callback(modifiers), + "type", ONE_EXACTLY, expect_identifier(assign_variable_callback(type)), + "on_completion", ZERO_OR_ONE, expect_identifier(assign_variable_callback(on_completion)), + "completion_size", ZERO_OR_ONE, expect_fixed_point(assign_variable_callback(completion_size)), + "max_level", ONE_EXACTLY, expect_uint(assign_variable_callback(max_level)), + "goods_cost", ONE_EXACTLY, good_manager.expect_good_decimal_map(assign_variable_callback(goods_cost)), + "cost", ZERO_OR_MORE, expect_fixed_point(assign_variable_callback(cost)), + "time", ONE_EXACTLY, expect_uint(assign_variable_callback_uint("building build time", build_days)), + "visibility", ONE_EXACTLY, expect_bool(assign_variable_callback(visibility)), + "onmap", ONE_EXACTLY, expect_bool(assign_variable_callback(on_map)), + "default_enabled", ZERO_OR_ONE, expect_bool(assign_variable_callback(default_enabled)), + "production_type", ZERO_OR_ONE, expect_identifier(assign_variable_callback(production_type)), + "pop_build_factory", ZERO_OR_ONE, expect_bool(assign_variable_callback(pop_build_factory)), + "strategic_factory", ZERO_OR_ONE, expect_bool(assign_variable_callback(strategic_factory)), + "advanced_factory", ZERO_OR_ONE, expect_bool(assign_variable_callback(advanced_factory)), + "fort_level", ZERO_OR_ONE, expect_uint(assign_variable_callback_uint("building fort level", fort_level)), + "naval_capacity", ZERO_OR_ONE, expect_uint(assign_variable_callback_uint("building naval capacity", naval_capacity)), + "colonial_points", ZERO_OR_ONE, expect_list(expect_uint([&colonial_points](uint64_t points) -> bool { + return colonial_points.emplace_back(points); + })), "province", ZERO_OR_ONE, expect_bool(assign_variable_callback(in_province)), + "one_per_state", ZERO_OR_ONE, expect_bool(assign_variable_callback(one_per_state)), + "colonial_range", ZERO_OR_ONE, expect_fixed_point(assign_variable_callback(colonial_range)), + "infrastructure", ZERO_OR_ONE, expect_fixed_point(assign_variable_callback(infrastructure)), + "movement_cost", ZERO_OR_ONE, expect_fixed_point(assign_variable_callback(movement_cost)), + "local_ship_build", ZERO_OR_ONE, expect_fixed_point(assign_variable_callback(local_ship_build)), + "spawn_railway_track", ZERO_OR_ONE, expect_bool(assign_variable_callback(spawn_railway_track)), + "sail", ZERO_OR_ONE, expect_bool(assign_variable_callback(sail)), + "steam", ZERO_OR_ONE, expect_bool(assign_variable_callback(steam)), + "capital", ZERO_OR_ONE, expect_bool(assign_variable_callback(capital)), + "port", ZERO_OR_ONE, expect_bool(assign_variable_callback(port)) + )(value); + + BuildingType const* type_ref = building_types.get_item_by_identifier(type); + if (type_ref == nullptr) { + building_types.add_item({ type }); + type_ref = building_types.get_item_by_identifier(type); + } + + Timespan build_time = Timespan(build_days); + + ProductionType const* production_type_ref = production_type_manager.get_production_type_by_identifier(production_type); + + ret &= add_building( + key, *type_ref, on_completion, completion_size, max_level, goods_cost, cost, build_time, visibility, on_map, default_enabled, + production_type_ref, pop_build_factory, strategic_factory, advanced_factory, fort_level, naval_capacity, colonial_points, in_province, + one_per_state, colonial_range, infrastructure, movement_cost, local_ship_build, spawn_railway_track, sail, steam, capital, port, std::move(modifiers) + ); + + return ret; + })(root); + lock_building_types(); + lock_buildings(); + + return ret; } bool BuildingManager::generate_province_buildings(Province& province) const { @@ -118,8 +274,8 @@ bool BuildingManager::generate_province_buildings(Province& province) const { } bool ret = true; if (!province.get_water()) { - for (BuildingType const& type : building_types.get_items()) { - ret &= province.add_building({ type }); + for (Building const& building : buildings.get_items()) { + ret &= province.add_building({ building }); } } province.lock_buildings(); diff --git a/src/openvic-simulation/map/Building.hpp b/src/openvic-simulation/map/Building.hpp index d36dfd4..9b11c1c 100644 --- a/src/openvic-simulation/map/Building.hpp +++ b/src/openvic-simulation/map/Building.hpp @@ -1,9 +1,18 @@ #pragma once -#include <vector> - #include "openvic-simulation/types/Date.hpp" +#include "openvic-simulation/types/fixed_point/FixedPoint.hpp" #include "openvic-simulation/types/IdentifierRegistry.hpp" +#include "openvic-simulation/economy/Good.hpp" +#include "openvic-simulation/economy/ProductionType.hpp" +#include "openvic-simulation/Modifier.hpp" + +#define ARGS BuildingType const& type, std::string_view on_completion, fixed_point_t completion_size, level_t max_level, \ + std::map<const Good*, fixed_point_t> goods_cost, fixed_point_t cost, Timespan build_time, bool visibility, bool on_map, bool default_enabled, \ + ProductionType const* production_type, bool pop_build_factory, bool strategic_factory, bool advanced_factory, level_t fort_level, \ + uint64_t naval_capacity, std::vector<uint64_t> colonial_points, bool in_province, bool one_per_state, fixed_point_t colonial_range, \ + fixed_point_t infrastructure, fixed_point_t movement_cost, fixed_point_t local_ship_build, bool spawn_railway_track, bool sail, bool steam, \ + bool capital, bool port, ModifierValue&& modifiers namespace OpenVic { @@ -15,34 +24,120 @@ namespace OpenVic { * MAP-12, MAP-75, MAP-76 * MAP-13, MAP-78, MAP-79 */ - struct Building : HasIdentifier { + struct Building : HasIdentifier, ModifierValue { friend struct BuildingManager; - using level_t = int8_t; - - enum class ExpansionState { - CannotExpand, - CanExpand, - Preparing, - Expanding - }; + using level_t = uint8_t; private: BuildingType const& type; + const std::string_view on_completion; //probably sound played on completion + const fixed_point_t completion_size; + const level_t max_level; + const std::map<const Good*, fixed_point_t> goods_cost; + const fixed_point_t cost; + const Timespan build_time; //time + const bool visibility; + const bool on_map; //onmap + + const bool default_enabled; + ProductionType const* production_type; + const bool pop_build_factory; + const bool strategic_factory; + const bool advanced_factory; + + const level_t fort_level; //probably the step-per-level + + const uint64_t naval_capacity; + const std::vector<uint64_t> colonial_points; + const bool in_province; //province + const bool one_per_state; + const fixed_point_t colonial_range; + + const fixed_point_t infrastructure; + const fixed_point_t movement_cost; + const fixed_point_t local_ship_build; + const bool spawn_railway_track; + + const bool sail; //only in clipper shipyard + const bool steam; //only in steamer shipyard + const bool capital; //only in naval base + const bool port; //only in naval base + + Building(std::string_view identifier, ARGS); + + public: + Building(Building&&) = default; + + BuildingType const& get_type() const; + std::string_view get_on_completion() const; + fixed_point_t get_completion_size() const; + level_t get_max_level() const; + std::map<const Good*, fixed_point_t> const& get_goods_cost() const; + fixed_point_t get_cost() const; + Timespan get_build_time() const; + bool has_visibility() const; + bool is_on_map() const; + + bool is_default_enabled() const; + ProductionType const* get_production_type() const; + bool is_pop_built_factory() const; + bool is_strategic_factory() const; + bool is_advanced_factory() const; + + level_t get_fort_level() const; + + uint64_t get_naval_capacity() const; + std::vector<uint64_t> const& get_colonial_points() const; + bool is_in_province() const; + bool is_one_per_state() const; + fixed_point_t get_colonial_range() const; + + fixed_point_t get_infrastructure() const; + fixed_point_t get_movement_cost() const; + fixed_point_t get_local_ship_build() const; + bool spawned_railway_track() const; + }; + + struct BuildingType : HasIdentifier { + friend struct BuildingManager; + + private: + BuildingType(const std::string_view new_identifier); + + public: + BuildingType(BuildingType&&) = default; + }; + + enum class ExpansionState { + CannotExpand, + CanExpand, + Preparing, + Expanding + }; + + struct BuildingInstance : HasIdentifier { //used in the actual game + friend struct BuildingManager; + using level_t = Building::level_t; + + private: + Building const& building; + level_t level = 0; ExpansionState expansion_state = ExpansionState::CannotExpand; Date start, end; float expansion_progress; - Building(BuildingType const& new_type); - bool _can_expand() const; + BuildingInstance(Building const& building); + public: - Building(Building&&) = default; + BuildingInstance(BuildingInstance&&) = default; - BuildingType const& get_type() const; - level_t get_level() const; + Building const& get_building() const; + + level_t get_current_level() const; ExpansionState get_expansion_state() const; Date const& get_start_date() const; Date const& get_end_date() const; @@ -51,35 +146,29 @@ namespace OpenVic { 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 { + using level_t = Building::level_t; //this is getting ridiculous + private: IdentifierRegistry<BuildingType> building_types; + IdentifierRegistry<Building> buildings; public: BuildingManager(); - bool add_building_type(const std::string_view identifier, Building::level_t max_level, Timespan build_time); + bool add_building_type(const std::string_view identifier); IDENTIFIER_REGISTRY_ACCESSORS(BuildingType, building_type) + + bool add_building(std::string_view identifier, ARGS); + IDENTIFIER_REGISTRY_ACCESSORS(Building, building) + + bool load_buildings_file(GoodManager const& good_manager, ProductionTypeManager const& production_type_manager, ModifierManager const& modifier_manager, ast::NodeCPtr root); + bool generate_province_buildings(Province& province) const; }; } diff --git a/src/openvic-simulation/map/Province.cpp b/src/openvic-simulation/map/Province.cpp index ef574cf..21bdb85 100644 --- a/src/openvic-simulation/map/Province.cpp +++ b/src/openvic-simulation/map/Province.cpp @@ -1,20 +1,11 @@ #include "Province.hpp" -#include <cassert> -#include <cstddef> -#include <iomanip> -#include <iterator> -#include <sstream> - -#include "openvic-simulation/map/TerrainType.hpp" - 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, false }, - index { new_index }, - buildings { "buildings", false } { + index { new_index }, buildings { "buildings", false } { assert(index != NULL_INDEX); } @@ -48,8 +39,8 @@ bool Province::load_positions(BuildingManager const& building_manager, ast::Node return true; } -bool Province::add_building(Building&& building) { - return buildings.add_item(std::move(building)); +bool Province::add_building(BuildingInstance&& building_instance) { + return buildings.add_item(std::move(building_instance)); } void Province::reset_buildings() { @@ -57,7 +48,7 @@ void Province::reset_buildings() { } bool Province::expand_building(const std::string_view building_type_identifier) { - Building* building = buildings.get_item_by_identifier(building_type_identifier); + BuildingInstance* building = buildings.get_item_by_identifier(building_type_identifier); if (building == nullptr) return false; return building->expand(); } @@ -136,13 +127,13 @@ void Province::update_pops() { } void Province::update_state(Date const& today) { - for (Building& building : buildings.get_items()) + for (BuildingInstance& building : buildings.get_items()) building.update_state(today); update_pops(); } void Province::tick(Date const& today) { - for (Building& building : buildings.get_items()) + for (BuildingInstance& building : buildings.get_items()) building.tick(today); } diff --git a/src/openvic-simulation/map/Province.hpp b/src/openvic-simulation/map/Province.hpp index 6e4ac7e..349c16d 100644 --- a/src/openvic-simulation/map/Province.hpp +++ b/src/openvic-simulation/map/Province.hpp @@ -1,6 +1,6 @@ #pragma once -#include <limits> +#include <cassert> #include "openvic-simulation/map/Building.hpp" #include "openvic-simulation/pop/Pop.hpp" @@ -46,7 +46,7 @@ namespace OpenVic { Region* region = nullptr; bool has_region = false, water = false; life_rating_t life_rating = 0; - IdentifierRegistry<Building> buildings; + IdentifierRegistry<BuildingInstance> buildings; // TODO - change this into a factory-like structure Good const* rgo = nullptr; @@ -73,8 +73,8 @@ namespace OpenVic { life_rating_t get_life_rating() const; bool load_positions(BuildingManager const& building_manager, ast::NodeCPtr root); - bool add_building(Building&& building); - IDENTIFIER_REGISTRY_ACCESSORS(Building, building) + bool add_building(BuildingInstance&& building_instance); + IDENTIFIER_REGISTRY_ACCESSORS(BuildingInstance, building) void reset_buildings(); bool expand_building(const std::string_view building_type_identifier); Good const* get_rgo() const; |