Implement validators and modificators for controllers

This commit is contained in:
NaiJi ✨ 2021-05-16 02:44:19 +03:00
parent 159b7e4673
commit 5030b71e3f
26 changed files with 300 additions and 62 deletions

View File

@ -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})

View File

@ -3,6 +3,7 @@
#include <memory>
#include <list>
#include <set>
class Location;
class Item;
@ -15,12 +16,15 @@ public:
virtual void commitAction() = 0;
virtual void moveToLocation(const std::shared_ptr<Location>& location) = 0;
virtual bool isLocationVisited(const std::shared_ptr<Location>& location) const = 0;
virtual void giveItem(const std::shared_ptr<Item>& item) = 0;
virtual void useItem(const std::shared_ptr<Item>& item) = 0;
virtual bool hasItem(const std::shared_ptr<Item>& item) const = 0;
protected:
std::shared_ptr<Location> _current_location;
std::list<std::shared_ptr<Item>> _inventory;
std::set<std::shared_ptr<Location>> _visited_locations;
};
#endif // ACTOR_H

View File

@ -45,20 +45,29 @@ void Player::commitAction()
void Player::moveToLocation(const std::shared_ptr<Location> &location)
{
_current_location = location;
_visited_locations.insert(location);
}
bool Player::isLocationVisited(const std::shared_ptr<Location> &location) const
{
return std::find(_visited_locations.begin(), _visited_locations.end(), location) != _visited_locations.end();
}
void Player::giveItem(const std::shared_ptr<Item>& item)
{
item->setReceived(true);
_inventory.push_back(item);
}
void Player::useItem(const std::shared_ptr<Item>& item)
{
item->setReceived(false);
_inventory.remove(item);
}
bool Player::hasItem(const std::shared_ptr<Item>& item) const
{
return std::find(_inventory.begin(), _inventory.end(), item) != _inventory.end();
}
std::string Player::showInventory() const
{
if (_inventory.empty())

View File

@ -11,8 +11,10 @@ public:
virtual void commitAction() override;
virtual void moveToLocation(const std::shared_ptr<Location>& location) override;
virtual bool isLocationVisited(const std::shared_ptr<Location>& location) const override;
virtual void giveItem(const std::shared_ptr<Item>& item) override;
virtual void useItem(const std::shared_ptr<Item>& item) override;
virtual bool hasItem(const std::shared_ptr<Item>& item) const override;
private:
std::string showInventory() const;

View File

@ -1,10 +1,12 @@
#include "controller.h"
#include "policy.h"
#include "modificator.h"
#include <algorithm>
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<std::shared_ptr<Policy>>& 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>& 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<std::shared_ptr<Modificator>>& modificators)
{
_modificators = modificators;
}

View File

@ -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> actor) = 0;
virtual bool validateInput(const std::string& input_word) const final;
virtual void setValidationPolicies(const std::list<std::shared_ptr<Policy>>& 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>& validator);
void setModificators(const std::list<std::shared_ptr<Modificator>>& modificators);
protected:
virtual ValidationResult validatePolicies() const final;
void runModificators() const;
std::list<std::string> _keywords;
std::string _interaction_message;
std::list<std::shared_ptr<Policy>> _validation_policies;
std::shared_ptr<Validator> _validator;
std::list<std::shared_ptr<Modificator>> _modificators;
};
#endif // CONTROLLER_H

View File

@ -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> 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;

View File

@ -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> 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> actor)
interaction_output += (_interaction_message + "\n\n" + node_interact_message);
}
runModificators();
return interaction_output;
}

View File

@ -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<std::shared_ptr<Controller>>& Location::controllers()
return _interactive_controllers;
}
bool Location::isVisited() const
void Location::removeControllers(const std::list<std::shared_ptr<Controller>> &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;
}

View File

@ -19,15 +19,14 @@ public:
explicit Location(Initializer &&initializer);
virtual const std::string& interact();
const std::list<std::shared_ptr<Controller>>& controllers();
bool isVisited() const;
void removeControllers(const std::list<std::shared_ptr<Controller>>& controllers);
void setInteractionMessage(const std::string& message);
private:
std::string _interaction_message;
std::list<std::shared_ptr<Controller>> _interactive_controllers;
std::shared_ptr<Location> _current_user_location;
bool _is_visited;
};
#endif // LOCATION_H

View File

@ -0,0 +1,7 @@
#include "modificator.h"
Modificator::Modificator()
{}
Modificator::~Modificator()
{}

View File

@ -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

View File

@ -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>& location,
const std::list<std::shared_ptr<Controller>>& controllers,
const std::string& new_message)
{
_location = location;
_controllers_to_remove = controllers;
_new_location_message = new_message;
}

View File

@ -0,0 +1,31 @@
#ifndef REMOVECONTROLLERSMODIFICATOR_H
#define REMOVECONTROLLERSMODIFICATOR_H
#include <string>
#include <memory>
#include <list>
#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>& location,
const std::list<std::shared_ptr<Controller>>& controllers,
const std::string& new_message);
private:
std::shared_ptr<Location> _location;
std::list<std::shared_ptr<Controller>> _controllers_to_remove;
std::string _new_location_message;
};
#endif // REMOVECONTROLLERSMODIFICATOR_H

View File

@ -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>& actor) const
{
bool success = _item->isReceived();
bool success = actor->hasItem(_item);
return composeMessageFromResult(success);
}

View File

@ -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>& actor) const override;
void setRequiredItem(const std::shared_ptr<Item>& item);

View File

@ -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>& actor) const
{
bool success = _location->isVisited();
bool success = actor->isLocationVisited(_location);
return composeMessageFromResult(success);
}

View File

@ -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>& actor) const override;
void setRequiredLocation(const std::shared_ptr<Location>& location);

View File

@ -1,8 +1,11 @@
#ifndef POLICY_H
#define POLICY_H
#include <memory>
#include <string>
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> &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;

View File

@ -4,6 +4,8 @@
#include "locationcontroller.h"
#include "itemcontroller.h"
#include "itemrequiredpolicy.h"
#include "allpoliciesvalidator.h"
#include "removecontrollersmodificator.h"
#include <iostream>
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<LocationController> pleroman_cont = std::make_shared<LocationController>(std::move(pleroman_init));
std::shared_ptr<ItemRequiredPolicy> need_tenshi_policy = std::make_shared<ItemRequiredPolicy>("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<AllPoliciesValidator> pleroman_validator = std::make_shared<AllPoliciesValidator>(std::list<std::shared_ptr<Policy>>{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<Item> tenshi = std::make_shared<Item>("Postcard of Tenshi eating corndog");
need_tenshi_policy->setRequiredItem(tenshi);
std::shared_ptr<RemoveControllersModificator> remove_tenshi_modif = std::make_shared<RemoveControllersModificator>();
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);

View File

@ -0,0 +1,29 @@
#include "allpoliciesvalidator.h"
#include "policy.h"
AllPoliciesValidator::AllPoliciesValidator(const std::list<std::shared_ptr<Policy>>& policies) :
Validator(policies)
{}
AllPoliciesValidator::~AllPoliciesValidator()
{}
Validator::ValidateResult AllPoliciesValidator::validate(const std::shared_ptr<Actor> &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;
}

View File

@ -0,0 +1,15 @@
#ifndef ALLPOLICIESVALIDATOR_H
#define ALLPOLICIESVALIDATOR_H
#include "validator.h"
class AllPoliciesValidator : public Validator
{
public:
explicit AllPoliciesValidator(const std::list<std::shared_ptr<Policy>>& policies);
virtual ~AllPoliciesValidator() override;
virtual ValidateResult validate(const std::shared_ptr<Actor>& actor) const override;
};
#endif // ALLPOLICIESVALIDATOR_H

View File

@ -0,0 +1,29 @@
#include "anypolicyvalidator.h"
#include "policy.h"
AnyPolicyValidator::AnyPolicyValidator(const std::list<std::shared_ptr<Policy>>& policies) :
Validator(policies)
{}
AnyPolicyValidator::~AnyPolicyValidator()
{}
Validator::ValidateResult AnyPolicyValidator::validate(const std::shared_ptr<Actor> &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;
}

View File

@ -0,0 +1,15 @@
#ifndef ANYPOLICYVALIDATOR_H
#define ANYPOLICYVALIDATOR_H
#include "validator.h"
class AnyPolicyValidator : public Validator
{
public:
explicit AnyPolicyValidator(const std::list<std::shared_ptr<Policy>>& policies);
virtual ~AnyPolicyValidator() override;
virtual ValidateResult validate(const std::shared_ptr<Actor>& actor) const override;
};
#endif // ANYPOLICYVALIDATOR_H

8
validators/validator.cpp Normal file
View File

@ -0,0 +1,8 @@
#include "validator.h"
Validator::Validator(const std::list<std::shared_ptr<Policy>>& policies) :
_validation_policies(policies)
{}
Validator::~Validator()
{}

29
validators/validator.h Normal file
View File

@ -0,0 +1,29 @@
#ifndef VALIDATOR_H
#define VALIDATOR_H
#include <list>
#include <memory>
#include <string>
class Policy;
class Actor;
class Validator
{
public:
explicit Validator(const std::list<std::shared_ptr<Policy>>& policies);
virtual ~Validator() = 0;
struct ValidateResult
{
bool success = false;
std::string validate_output;
};
virtual ValidateResult validate(const std::shared_ptr<Actor>& actor) const = 0;
protected:
std::list<std::shared_ptr<Policy>> _validation_policies;
};
#endif // VALIDATOR_H