1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-08-13 19:54:17 +02:00

Extract PossibilityVisitor

This commit is contained in:
Piotr Wójcik
2016-09-12 22:28:11 +02:00
parent 40003460ca
commit e1a1bc89c0
2 changed files with 81 additions and 79 deletions

View File

@@ -520,10 +520,12 @@ EBuildingState::EBuildingState CGameInfoCallback::canBuildStructure( const CGTow
if(vstd::contains(t->forbiddenBuildings, ID)) if(vstd::contains(t->forbiddenBuildings, ID))
return EBuildingState::FORBIDDEN; //forbidden return EBuildingState::FORBIDDEN; //forbidden
std::function<bool(BuildingID id)> allowedTest; auto possiblyNotBuiltTest = [&](BuildingID id) -> bool
std::function<bool(BuildingID id)> possiblyNotBuiltTest; {
return ((id == BuildingID::CAPITOL) ? true : !t->hasBuilt(id));
};
allowedTest = [&](BuildingID id) -> bool std::function<bool(BuildingID id)> allowedTest = [&](BuildingID id) -> bool
{ {
if (vstd::contains(t->forbiddenBuildings, id)) if (vstd::contains(t->forbiddenBuildings, id))
{ {
@@ -533,12 +535,6 @@ EBuildingState::EBuildingState CGameInfoCallback::canBuildStructure( const CGTow
return t->genBuildingRequirements(id, true).satisfiable(allowedTest, possiblyNotBuiltTest); return t->genBuildingRequirements(id, true).satisfiable(allowedTest, possiblyNotBuiltTest);
}; };
possiblyNotBuiltTest = [&](BuildingID id) -> bool
{
//TODO consider destroing
return !t->hasBuilt(id);
};
if (!t->genBuildingRequirements(ID, true).satisfiable(allowedTest, possiblyNotBuiltTest)) if (!t->genBuildingRequirements(ID, true).satisfiable(allowedTest, possiblyNotBuiltTest))
return EBuildingState::FORBIDDEN; return EBuildingState::FORBIDDEN;

View File

@@ -99,74 +99,22 @@ namespace LogicalExpressionDetail
} }
}; };
template <typename ContainedClass>
class SatisfiabilityVisitor;
template <typename ContainedClass> template <typename ContainedClass>
class FalsifiabilityVisitor; class FalsifiabilityVisitor;
/// Visitor to test whether expression's value can be true
template <typename ContainedClass> template <typename ContainedClass>
class SatisfiabilityVisitor : public boost::static_visitor<bool> class PossibilityVisitor : public boost::static_visitor<bool>
{ {
typedef ExpressionBase<ContainedClass> Base; typedef ExpressionBase<ContainedClass> Base;
protected:
std::function<bool(const typename Base::Value &)> satisfiabilityTest; std::function<bool(const typename Base::Value &)> satisfiabilityTest;
FalsifiabilityVisitor<ContainedClass> *falsifiabilityVisitor;
size_t countSatisfiable(const std::vector<typename Base::Variant> & element) const
{
return boost::range::count_if(element, [&](const typename Base::Variant & expr)
{
return boost::apply_visitor(*this, expr);
});
}
size_t countFalsifiable(const std::vector<typename Base::Variant> & element) const
{
return boost::range::count_if(element, [&](const typename Base::Variant & expr)
{
return boost::apply_visitor(*falsifiabilityVisitor, expr);
});
}
public:
SatisfiabilityVisitor(std::function<bool (const typename Base::Value &)> satisfiabilityTest):
satisfiabilityTest(satisfiabilityTest),
falsifiabilityVisitor(nullptr)
{}
void setFalsifiabilityVisitor(FalsifiabilityVisitor<ContainedClass> *falsifiabilityVisitor)
{
this->falsifiabilityVisitor = falsifiabilityVisitor;
}
bool operator()(const typename Base::OperatorAny & element) const
{
return countSatisfiable(element.expressions) != 0;
}
bool operator()(const typename Base::OperatorAll & element) const
{
return countSatisfiable(element.expressions) == element.expressions.size();
}
bool operator()(const typename Base::OperatorNone & element) const
{
return countFalsifiable(element.expressions) == element.expressions.size();
}
bool operator()(const typename Base::Value & element) const
{
return satisfiabilityTest(element);
}
};
/// Visitor to test whether expression's value can be false
template <typename ContainedClass>
class FalsifiabilityVisitor : public boost::static_visitor<bool>
{
typedef ExpressionBase<ContainedClass> Base;
std::function<bool(const typename Base::Value &)> falsifiabilityTest; std::function<bool(const typename Base::Value &)> falsifiabilityTest;
SatisfiabilityVisitor<ContainedClass> *satisfiabilityVisitor; SatisfiabilityVisitor<ContainedClass> *satisfiabilityVisitor;
FalsifiabilityVisitor<ContainedClass> *falsifiabilityVisitor;
size_t countSatisfiable(const std::vector<typename Base::Variant> & element) const size_t countSatisfiable(const std::vector<typename Base::Variant> & element) const
{ {
@@ -180,39 +128,97 @@ namespace LogicalExpressionDetail
{ {
return boost::range::count_if(element, [&](const typename Base::Variant & expr) return boost::range::count_if(element, [&](const typename Base::Variant & expr)
{ {
return boost::apply_visitor(*this, expr); return boost::apply_visitor(*falsifiabilityVisitor, expr);
}); });
} }
public: public:
FalsifiabilityVisitor(std::function<bool (const typename Base::Value &)> falsifiabilityTest): PossibilityVisitor(std::function<bool (const typename Base::Value &)> satisfiabilityTest,
std::function<bool (const typename Base::Value &)> falsifiabilityTest):
satisfiabilityTest(satisfiabilityTest),
falsifiabilityTest(falsifiabilityTest), falsifiabilityTest(falsifiabilityTest),
satisfiabilityVisitor(nullptr) satisfiabilityVisitor(nullptr),
falsifiabilityVisitor(nullptr)
{} {}
void setFalsifiabilityVisitor(SatisfiabilityVisitor<ContainedClass> *satisfiabilityVisitor) void setSatisfiabilityVisitor(SatisfiabilityVisitor<ContainedClass> *satisfiabilityVisitor)
{ {
this->satisfiabilityVisitor = satisfiabilityVisitor; this->satisfiabilityVisitor = satisfiabilityVisitor;
} }
void setFalsifiabilityVisitor(FalsifiabilityVisitor<ContainedClass> *falsifiabilityVisitor)
{
this->falsifiabilityVisitor = falsifiabilityVisitor;
}
};
/// Visitor to test whether expression's value can be true
template <typename ContainedClass>
class SatisfiabilityVisitor : public PossibilityVisitor<ContainedClass>
{
typedef ExpressionBase<ContainedClass> Base;
public:
SatisfiabilityVisitor(std::function<bool (const typename Base::Value &)> satisfiabilityTest,
std::function<bool (const typename Base::Value &)> falsifiabilityTest):
PossibilityVisitor<ContainedClass>(satisfiabilityTest, falsifiabilityTest)
{
this->setSatisfiabilityVisitor(this);
}
bool operator()(const typename Base::OperatorAny & element) const bool operator()(const typename Base::OperatorAny & element) const
{ {
return countFalsifiable(element.expressions) == element.expressions.size(); return this->countSatisfiable(element.expressions) != 0;
} }
bool operator()(const typename Base::OperatorAll & element) const bool operator()(const typename Base::OperatorAll & element) const
{ {
return countFalsifiable(element.expressions) != 0; return this->countSatisfiable(element.expressions) == element.expressions.size();
} }
bool operator()(const typename Base::OperatorNone & element) const bool operator()(const typename Base::OperatorNone & element) const
{ {
return countSatisfiable(element.expressions) != 0; return this->countFalsifiable(element.expressions) == element.expressions.size();
} }
bool operator()(const typename Base::Value & element) const bool operator()(const typename Base::Value & element) const
{ {
return falsifiabilityTest(element); return this->satisfiabilityTest(element);
}
};
/// Visitor to test whether expression's value can be false
template <typename ContainedClass>
class FalsifiabilityVisitor : public PossibilityVisitor<ContainedClass>
{
typedef ExpressionBase<ContainedClass> Base;
public:
FalsifiabilityVisitor(std::function<bool (const typename Base::Value &)> satisfiabilityTest,
std::function<bool (const typename Base::Value &)> falsifiabilityTest):
PossibilityVisitor<ContainedClass>(satisfiabilityTest, falsifiabilityTest)
{
this->setFalsifiabilityVisitor(this);
}
bool operator()(const typename Base::OperatorAny & element) const
{
return this->countFalsifiable(element.expressions) == element.expressions.size();
}
bool operator()(const typename Base::OperatorAll & element) const
{
return this->countFalsifiable(element.expressions) != 0;
}
bool operator()(const typename Base::OperatorNone & element) const
{
return this->countSatisfiable(element.expressions) != 0;
}
bool operator()(const typename Base::Value & element) const
{
return this->falsifiabilityTest(element);
} }
}; };
@@ -554,13 +560,13 @@ public:
} }
/// calculates if expression can evaluate to "true". /// calculates if expression can evaluate to "true".
bool satisfiable (std::function<bool(const Value &)> satisfiabilityTest, std::function<bool(const Value &)> falsifiabilityTest) const bool satisfiable(std::function<bool(const Value &)> satisfiabilityTest, std::function<bool(const Value &)> falsifiabilityTest) const
{ {
LogicalExpressionDetail::SatisfiabilityVisitor<Value> satisfiabilityVisitor(satisfiabilityTest); LogicalExpressionDetail::SatisfiabilityVisitor<Value> satisfiabilityVisitor(satisfiabilityTest, falsifiabilityTest);
LogicalExpressionDetail::FalsifiabilityVisitor<Value> falsifiabilityVisitor(falsifiabilityTest); LogicalExpressionDetail::FalsifiabilityVisitor<Value> falsifiabilityVisitor(satisfiabilityTest, falsifiabilityTest);
satisfiabilityVisitor.setFalsifiabilityVisitor(&falsifiabilityVisitor); satisfiabilityVisitor.setFalsifiabilityVisitor(&falsifiabilityVisitor);
falsifiabilityVisitor.setFalsifiabilityVisitor(&satisfiabilityVisitor); falsifiabilityVisitor.setSatisfiabilityVisitor(&satisfiabilityVisitor);
return boost::apply_visitor(satisfiabilityVisitor, data); return boost::apply_visitor(satisfiabilityVisitor, data);
} }