diff --git a/CMakeLists.txt b/CMakeLists.txt index a62be50..e4bdd9e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,6 +6,11 @@ set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall") file(GLOB SOURCES "*.h" "*.cpp" "*/*.h" "*/*.cpp") -include_directories(${CMAKE_SOURCE_DIR} ${CMAKE_SOURCE_DIR}/actors ${CMAKE_SOURCE_DIR}/controllers ${CMAKE_SOURCE_DIR}/entities ${CMAKE_SOURCE_DIR}/policies) +include_directories(${CMAKE_SOURCE_DIR} ${CMAKE_SOURCE_DIR}/actors + ${CMAKE_SOURCE_DIR}/controllers + ${CMAKE_SOURCE_DIR}/entities + ${CMAKE_SOURCE_DIR}/policies + ${CMAKE_SOURCE_DIR}/validators + ${CMAKE_SOURCE_DIR}/modificators) add_executable(slumber-quest ${SOURCES}) diff --git a/actors/actor.h b/actors/actor.h index 99075ed..0625978 100644 --- a/actors/actor.h +++ b/actors/actor.h @@ -3,6 +3,7 @@ #include #include +#include class Location; class Item; @@ -15,12 +16,15 @@ public: virtual void commitAction() = 0; virtual void moveToLocation(const std::shared_ptr& location) = 0; + virtual bool isLocationVisited(const std::shared_ptr& location) const = 0; virtual void giveItem(const std::shared_ptr& item) = 0; virtual void useItem(const std::shared_ptr& item) = 0; + virtual bool hasItem(const std::shared_ptr& item) const = 0; protected: std::shared_ptr _current_location; std::list> _inventory; + std::set> _visited_locations; }; #endif // ACTOR_H diff --git a/actors/player.cpp b/actors/player.cpp index da18fec..75f0921 100644 --- a/actors/player.cpp +++ b/actors/player.cpp @@ -45,20 +45,29 @@ void Player::commitAction() void Player::moveToLocation(const std::shared_ptr &location) { _current_location = location; + _visited_locations.insert(location); +} + +bool Player::isLocationVisited(const std::shared_ptr &location) const +{ + return std::find(_visited_locations.begin(), _visited_locations.end(), location) != _visited_locations.end(); } void Player::giveItem(const std::shared_ptr& item) { - item->setReceived(true); _inventory.push_back(item); } void Player::useItem(const std::shared_ptr& item) { - item->setReceived(false); _inventory.remove(item); } +bool Player::hasItem(const std::shared_ptr& item) const +{ + return std::find(_inventory.begin(), _inventory.end(), item) != _inventory.end(); +} + std::string Player::showInventory() const { if (_inventory.empty()) diff --git a/actors/player.h b/actors/player.h index 0006afe..42747e4 100644 --- a/actors/player.h +++ b/actors/player.h @@ -11,11 +11,13 @@ public: virtual void commitAction() override; virtual void moveToLocation(const std::shared_ptr& location) override; + virtual bool isLocationVisited(const std::shared_ptr& location) const override; virtual void giveItem(const std::shared_ptr& item) override; virtual void useItem(const std::shared_ptr& item) override; + virtual bool hasItem(const std::shared_ptr& item) const override; private: - std::string showInventory() const; + std::string showInventory() const; }; #endif // PLAYER_H diff --git a/controllers/controller.cpp b/controllers/controller.cpp index 42dd586..a226018 100644 --- a/controllers/controller.cpp +++ b/controllers/controller.cpp @@ -1,10 +1,12 @@ #include "controller.h" #include "policy.h" +#include "modificator.h" #include Controller::Controller(Initializer&& initializer) : _keywords(initializer.keywords), - _interaction_message(initializer.message) + _interaction_message(initializer.message), + _validator(nullptr) {} Controller::~Controller() @@ -15,32 +17,18 @@ bool Controller::validateInput(const std::string &input_word) const return std::find(_keywords.begin(), _keywords.end(), input_word) != _keywords.end(); } -void Controller::setValidationPolicies(const std::list>& policies) +void Controller::runModificators() const { - _validation_policies = policies; + for (const auto& modificator : _modificators) + modificator->run(); } -Controller::ValidationResult Controller::validatePolicies() const +void Controller::setValidator(const std::shared_ptr& validator) { - if (_validation_policies.empty()) - return {true, ""}; - - std::string interaction_output; - - bool success = true; - for (const auto& policy : _validation_policies) - { - const auto check_result = policy->check(); - interaction_output += (check_result.commentary + "\n\n"); - if (!check_result.satisfied) - { - success = false; - break; - } - } - - interaction_output.pop_back(); - interaction_output.pop_back(); - - return {success, interaction_output}; + _validator = validator; +} + +void Controller::setModificators(const std::list>& modificators) +{ + _modificators = modificators; } diff --git a/controllers/controller.h b/controllers/controller.h index fa25edd..ea939bb 100644 --- a/controllers/controller.h +++ b/controllers/controller.h @@ -7,7 +7,8 @@ class Node; class Actor; -class Policy; +class Validator; +class Modificator; class Controller { @@ -22,21 +23,18 @@ public: virtual ~Controller() = 0; virtual std::string interact(std::shared_ptr actor) = 0; - virtual bool validateInput(const std::string& input_word) const final; - virtual void setValidationPolicies(const std::list>& policies) final; + bool validateInput(const std::string& input_word) const; - struct ValidationResult - { - bool success = false; - std::string validation_output; - }; + void setValidator(const std::shared_ptr& validator); + void setModificators(const std::list>& modificators); protected: - virtual ValidationResult validatePolicies() const final; + void runModificators() const; std::list _keywords; std::string _interaction_message; - std::list> _validation_policies; + std::shared_ptr _validator; + std::list> _modificators; }; #endif // CONTROLLER_H diff --git a/controllers/itemcontroller.cpp b/controllers/itemcontroller.cpp index 2d9034a..f599f5a 100644 --- a/controllers/itemcontroller.cpp +++ b/controllers/itemcontroller.cpp @@ -1,7 +1,7 @@ #include "itemcontroller.h" #include "item.h" #include "actor.h" -#include "policy.h" +#include "validator.h" ItemController::ItemController(Initializer &&initializer) : Controller(std::move(initializer)) @@ -14,13 +14,17 @@ std::string ItemController::interact(std::shared_ptr actor) { std::string interaction_output; - const auto validation_result = validatePolicies(); - interaction_output += validation_result.validation_output; + const auto validation_result = _validator + ? _validator->validate(actor) + : Validator::ValidateResult{true, ""}; + + interaction_output += validation_result.validate_output; if (validation_result.success) { actor->giveItem(_item); interaction_output += _interaction_message; + runModificators(); } return interaction_output; diff --git a/controllers/locationcontroller.cpp b/controllers/locationcontroller.cpp index ceee1d0..6b64ee5 100644 --- a/controllers/locationcontroller.cpp +++ b/controllers/locationcontroller.cpp @@ -1,6 +1,6 @@ #include "locationcontroller.h" #include "location.h" -#include "policy.h" +#include "validator.h" #include "actor.h" LocationController::LocationController(Initializer &&initializer) : @@ -14,8 +14,11 @@ std::string LocationController::interact(std::shared_ptr actor) { std::string interaction_output; - const auto validation_result = validatePolicies(); - interaction_output += validation_result.validation_output; + const auto validation_result = _validator + ? _validator->validate(actor) + : Validator::ValidateResult{true, ""}; + + interaction_output += validation_result.validate_output; if (validation_result.success) { @@ -25,6 +28,8 @@ std::string LocationController::interact(std::shared_ptr actor) interaction_output += (_interaction_message + "\n\n" + node_interact_message); } + runModificators(); + return interaction_output; } diff --git a/entities/location.cpp b/entities/location.cpp index 573edb7..45834a8 100644 --- a/entities/location.cpp +++ b/entities/location.cpp @@ -3,13 +3,11 @@ Location::Location(Initializer &&initializer) : _interaction_message(initializer.message), - _interactive_controllers(initializer.interactive_controllers), - _is_visited(false) + _interactive_controllers(initializer.interactive_controllers) {} const std::string& Location::interact() { - _is_visited = true; return _interaction_message; } @@ -18,7 +16,22 @@ const std::list>& Location::controllers() return _interactive_controllers; } -bool Location::isVisited() const +void Location::removeControllers(const std::list> &controllers) { - return _is_visited; + for (const auto& to_remove_controller : controllers) + { + for (auto it = _interactive_controllers.begin(); it != _interactive_controllers.end(); ++it) + { + if ((*it) == to_remove_controller) + { + _interactive_controllers.erase(it); + break; + } + } + } +} + +void Location::setInteractionMessage(const std::string& message) +{ + _interaction_message = message; } diff --git a/entities/location.h b/entities/location.h index e97f26f..d22b611 100644 --- a/entities/location.h +++ b/entities/location.h @@ -19,15 +19,14 @@ public: explicit Location(Initializer &&initializer); virtual const std::string& interact(); - const std::list>& controllers(); - bool isVisited() const; + void removeControllers(const std::list>& controllers); + void setInteractionMessage(const std::string& message); private: std::string _interaction_message; std::list> _interactive_controllers; std::shared_ptr _current_user_location; - bool _is_visited; }; #endif // LOCATION_H diff --git a/modificators/modificator.cpp b/modificators/modificator.cpp new file mode 100644 index 0000000..2ddabd8 --- /dev/null +++ b/modificators/modificator.cpp @@ -0,0 +1,7 @@ +#include "modificator.h" + +Modificator::Modificator() +{} + +Modificator::~Modificator() +{} diff --git a/modificators/modificator.h b/modificators/modificator.h new file mode 100644 index 0000000..e2bd27b --- /dev/null +++ b/modificators/modificator.h @@ -0,0 +1,13 @@ +#ifndef MODIFICATOR_H +#define MODIFICATOR_H + +class Modificator +{ +public: + explicit Modificator(); + virtual ~Modificator(); + + virtual void run() const = 0; +}; + +#endif // MODIFICATOR_H diff --git a/modificators/removecontrollersmodificator.cpp b/modificators/removecontrollersmodificator.cpp new file mode 100644 index 0000000..f9ec20d --- /dev/null +++ b/modificators/removecontrollersmodificator.cpp @@ -0,0 +1,23 @@ +#include "removecontrollersmodificator.h" +#include "location.h" + +RemoveControllersModificator::RemoveControllersModificator() +{} + +RemoveControllersModificator::~RemoveControllersModificator() +{} + +void RemoveControllersModificator::run() const +{ + _location->removeControllers(_controllers_to_remove); + _location->setInteractionMessage(_new_location_message); +} + +void RemoveControllersModificator::setDependentObjects(const std::shared_ptr& location, + const std::list>& controllers, + const std::string& new_message) +{ + _location = location; + _controllers_to_remove = controllers; + _new_location_message = new_message; +} diff --git a/modificators/removecontrollersmodificator.h b/modificators/removecontrollersmodificator.h new file mode 100644 index 0000000..08f6ecb --- /dev/null +++ b/modificators/removecontrollersmodificator.h @@ -0,0 +1,31 @@ +#ifndef REMOVECONTROLLERSMODIFICATOR_H +#define REMOVECONTROLLERSMODIFICATOR_H + +#include +#include +#include + +#include "modificator.h" + +class Location; +class Controller; + +class RemoveControllersModificator : public Modificator +{ +public: + explicit RemoveControllersModificator(); + virtual ~RemoveControllersModificator() override; + + virtual void run() const override; + + void setDependentObjects(const std::shared_ptr& location, + const std::list>& controllers, + const std::string& new_message); + +private: + std::shared_ptr _location; + std::list> _controllers_to_remove; + std::string _new_location_message; +}; + +#endif // REMOVECONTROLLERSMODIFICATOR_H diff --git a/policies/itemrequiredpolicy.cpp b/policies/itemrequiredpolicy.cpp index 0e92e58..b5ee709 100644 --- a/policies/itemrequiredpolicy.cpp +++ b/policies/itemrequiredpolicy.cpp @@ -1,5 +1,6 @@ #include "itemrequiredpolicy.h" #include "item.h" +#include "actor.h" ItemRequiredPolicy::ItemRequiredPolicy(const std::string& satisfaction, const std::string& dissatisfaction) : Policy(satisfaction, dissatisfaction) @@ -8,9 +9,9 @@ ItemRequiredPolicy::ItemRequiredPolicy(const std::string& satisfaction, const st ItemRequiredPolicy::~ItemRequiredPolicy() {} -Policy::CheckResult ItemRequiredPolicy::check() const +Policy::CheckResult ItemRequiredPolicy::check(const std::shared_ptr& actor) const { - bool success = _item->isReceived(); + bool success = actor->hasItem(_item); return composeMessageFromResult(success); } diff --git a/policies/itemrequiredpolicy.h b/policies/itemrequiredpolicy.h index 3db6a53..ee7874e 100644 --- a/policies/itemrequiredpolicy.h +++ b/policies/itemrequiredpolicy.h @@ -12,7 +12,7 @@ public: explicit ItemRequiredPolicy(const std::string& satisfaction, const std::string& dissatisfaction); virtual ~ItemRequiredPolicy() override; - virtual Policy::CheckResult check() const override; + virtual Policy::CheckResult check(const std::shared_ptr& actor) const override; void setRequiredItem(const std::shared_ptr& item); diff --git a/policies/locationrequiredpolicy.cpp b/policies/locationrequiredpolicy.cpp index db30462..32c8c5e 100644 --- a/policies/locationrequiredpolicy.cpp +++ b/policies/locationrequiredpolicy.cpp @@ -1,5 +1,6 @@ #include "locationrequiredpolicy.h" #include "location.h" +#include "actor.h" LocationRequiredPolicy::LocationRequiredPolicy(const std::string& satisfaction, const std::string& dissatisfaction) : Policy(satisfaction, dissatisfaction) @@ -8,9 +9,9 @@ LocationRequiredPolicy::LocationRequiredPolicy(const std::string& satisfaction, LocationRequiredPolicy::~LocationRequiredPolicy() {} -Policy::CheckResult LocationRequiredPolicy::check() const +Policy::CheckResult LocationRequiredPolicy::check(const std::shared_ptr& actor) const { - bool success = _location->isVisited(); + bool success = actor->isLocationVisited(_location); return composeMessageFromResult(success); } diff --git a/policies/locationrequiredpolicy.h b/policies/locationrequiredpolicy.h index 3950c56..c1f6cc7 100644 --- a/policies/locationrequiredpolicy.h +++ b/policies/locationrequiredpolicy.h @@ -12,7 +12,7 @@ public: explicit LocationRequiredPolicy(const std::string& satisfaction, const std::string& dissatisfaction); virtual ~LocationRequiredPolicy() override; - virtual Policy::CheckResult check() const override; + virtual Policy::CheckResult check(const std::shared_ptr& actor) const override; void setRequiredLocation(const std::shared_ptr& location); diff --git a/policies/policy.h b/policies/policy.h index 8539149..77e6843 100644 --- a/policies/policy.h +++ b/policies/policy.h @@ -1,8 +1,11 @@ #ifndef POLICY_H #define POLICY_H +#include #include +class Actor; + class Policy { public: @@ -15,10 +18,10 @@ public: std::string commentary; }; - virtual CheckResult check() const = 0; + virtual CheckResult check(const std::shared_ptr &actor) const = 0; protected: - virtual CheckResult composeMessageFromResult(bool result) const final; + CheckResult composeMessageFromResult(bool result) const; std::string _commentary_on_satisfaction; std::string _commentary_on_dissatisfaction; diff --git a/sandboxlevelbuilder.cpp b/sandboxlevelbuilder.cpp index 7735ba9..0aae81d 100644 --- a/sandboxlevelbuilder.cpp +++ b/sandboxlevelbuilder.cpp @@ -4,6 +4,8 @@ #include "locationcontroller.h" #include "itemcontroller.h" #include "itemrequiredpolicy.h" +#include "allpoliciesvalidator.h" +#include "removecontrollersmodificator.h" #include SandboxLevelBuilder::SandboxLevelBuilder() @@ -42,7 +44,8 @@ void SandboxLevelBuilder::init() Controller::Initializer pleroman_init = {{"pleroman"}, "You talk to a pleroma user! What a happy and carefree creature. He even brew you some cofe!"}; std::shared_ptr pleroman_cont = std::make_shared(std::move(pleroman_init)); std::shared_ptr need_tenshi_policy = std::make_shared("You give him the postcard of Tenshi.", "He doesn't want to talk to you. Make him trust you!!"); - pleroman_cont->setValidationPolicies({need_tenshi_policy}); + std::shared_ptr pleroman_validator = std::make_shared(std::list>{need_tenshi_policy}); + pleroman_cont->setValidator(pleroman_validator); // START LOCATION auto&& init_msg = "You are now in a staring location. There is a door leading to a house. Typical text quest situation. To interact with something, type it as noun."; @@ -72,6 +75,10 @@ void SandboxLevelBuilder::init() std::shared_ptr tenshi = std::make_shared("Postcard of Tenshi eating corndog"); need_tenshi_policy->setRequiredItem(tenshi); + std::shared_ptr remove_tenshi_modif = std::make_shared(); + remove_tenshi_modif->setDependentObjects(table, {tenshi_cont}, "Boring table."); + tenshi_cont->setModificators({remove_tenshi_modif}); + the_first_and_only_trigger->setDependentLocation(start); door_cont->setDependentLocation(room); table_cont->setDependentLocation(table); diff --git a/validators/allpoliciesvalidator.cpp b/validators/allpoliciesvalidator.cpp new file mode 100644 index 0000000..eb48c2d --- /dev/null +++ b/validators/allpoliciesvalidator.cpp @@ -0,0 +1,29 @@ +#include "allpoliciesvalidator.h" +#include "policy.h" + +AllPoliciesValidator::AllPoliciesValidator(const std::list>& policies) : + Validator(policies) +{} + +AllPoliciesValidator::~AllPoliciesValidator() +{} + +Validator::ValidateResult AllPoliciesValidator::validate(const std::shared_ptr &actor) const +{ + Validator::ValidateResult validate_result{true, ""}; + + for (const auto& policy : _validation_policies) + { + const auto result = policy->check(actor); + validate_result.validate_output += result.commentary; + validate_result.validate_output += "\n\n"; + + if (!result.satisfied) + { + validate_result.success = false; + break; + } + } + + return validate_result; +} diff --git a/validators/allpoliciesvalidator.h b/validators/allpoliciesvalidator.h new file mode 100644 index 0000000..ea7f735 --- /dev/null +++ b/validators/allpoliciesvalidator.h @@ -0,0 +1,15 @@ +#ifndef ALLPOLICIESVALIDATOR_H +#define ALLPOLICIESVALIDATOR_H + +#include "validator.h" + +class AllPoliciesValidator : public Validator +{ +public: + explicit AllPoliciesValidator(const std::list>& policies); + virtual ~AllPoliciesValidator() override; + + virtual ValidateResult validate(const std::shared_ptr& actor) const override; +}; + +#endif // ALLPOLICIESVALIDATOR_H diff --git a/validators/anypolicyvalidator.cpp b/validators/anypolicyvalidator.cpp new file mode 100644 index 0000000..c0b20a5 --- /dev/null +++ b/validators/anypolicyvalidator.cpp @@ -0,0 +1,29 @@ +#include "anypolicyvalidator.h" +#include "policy.h" + +AnyPolicyValidator::AnyPolicyValidator(const std::list>& policies) : + Validator(policies) +{} + +AnyPolicyValidator::~AnyPolicyValidator() +{} + +Validator::ValidateResult AnyPolicyValidator::validate(const std::shared_ptr &actor) const +{ + Validator::ValidateResult validate_result{false, ""}; + + for (const auto& policy : _validation_policies) + { + const auto result = policy->check(actor); + + if (result.satisfied) + { + validate_result.validate_output += result.commentary; + validate_result.validate_output += "\n\n"; + validate_result.success = true; + break; + } + } + + return validate_result; +} diff --git a/validators/anypolicyvalidator.h b/validators/anypolicyvalidator.h new file mode 100644 index 0000000..5dba488 --- /dev/null +++ b/validators/anypolicyvalidator.h @@ -0,0 +1,15 @@ +#ifndef ANYPOLICYVALIDATOR_H +#define ANYPOLICYVALIDATOR_H + +#include "validator.h" + +class AnyPolicyValidator : public Validator +{ +public: + explicit AnyPolicyValidator(const std::list>& policies); + virtual ~AnyPolicyValidator() override; + + virtual ValidateResult validate(const std::shared_ptr& actor) const override; +}; + +#endif // ANYPOLICYVALIDATOR_H diff --git a/validators/validator.cpp b/validators/validator.cpp new file mode 100644 index 0000000..6ae70f0 --- /dev/null +++ b/validators/validator.cpp @@ -0,0 +1,8 @@ +#include "validator.h" + +Validator::Validator(const std::list>& policies) : + _validation_policies(policies) +{} + +Validator::~Validator() +{} diff --git a/validators/validator.h b/validators/validator.h new file mode 100644 index 0000000..41fd4f8 --- /dev/null +++ b/validators/validator.h @@ -0,0 +1,29 @@ +#ifndef VALIDATOR_H +#define VALIDATOR_H + +#include +#include +#include + +class Policy; +class Actor; + +class Validator +{ +public: + explicit Validator(const std::list>& policies); + virtual ~Validator() = 0; + + struct ValidateResult + { + bool success = false; + std::string validate_output; + }; + + virtual ValidateResult validate(const std::shared_ptr& actor) const = 0; + +protected: + std::list> _validation_policies; +}; + +#endif // VALIDATOR_H