diff options
Diffstat (limited to 'src/openvic-simulation/map/Building.cpp')
-rw-r--r-- | src/openvic-simulation/map/Building.cpp | 127 |
1 files changed, 127 insertions, 0 deletions
diff --git a/src/openvic-simulation/map/Building.cpp b/src/openvic-simulation/map/Building.cpp new file mode 100644 index 0000000..6e5cf18 --- /dev/null +++ b/src/openvic-simulation/map/Building.cpp @@ -0,0 +1,127 @@ +#include "Building.hpp" + +#include <cassert> + +#include "openvic-simulation/map/Province.hpp" +#include "openvic-simulation/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 }); +} + +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; +} |