diff --git a/lib/CGameInfoCallback.cpp b/lib/CGameInfoCallback.cpp index cd74085ab..c0d6b4fbf 100644 --- a/lib/CGameInfoCallback.cpp +++ b/lib/CGameInfoCallback.cpp @@ -520,10 +520,12 @@ EBuildingState::EBuildingState CGameInfoCallback::canBuildStructure( const CGTow if(vstd::contains(t->forbiddenBuildings, ID)) return EBuildingState::FORBIDDEN; //forbidden - std::function allowedTest; - std::function possiblyNotBuiltTest; + auto possiblyNotBuiltTest = [&](BuildingID id) -> bool + { + return ((id == BuildingID::CAPITOL) ? true : !t->hasBuilt(id)); + }; - allowedTest = [&](BuildingID id) -> bool + std::function allowedTest = [&](BuildingID id) -> bool { if (vstd::contains(t->forbiddenBuildings, id)) { @@ -533,12 +535,6 @@ EBuildingState::EBuildingState CGameInfoCallback::canBuildStructure( const CGTow 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)) return EBuildingState::FORBIDDEN; diff --git a/lib/LogicalExpression.h b/lib/LogicalExpression.h index e308fddd7..01acd074b 100644 --- a/lib/LogicalExpression.h +++ b/lib/LogicalExpression.h @@ -99,74 +99,22 @@ namespace LogicalExpressionDetail } }; + template + class SatisfiabilityVisitor; + template class FalsifiabilityVisitor; - /// Visitor to test whether expression's value can be true template - class SatisfiabilityVisitor : public boost::static_visitor + class PossibilityVisitor : public boost::static_visitor { typedef ExpressionBase Base; + protected: std::function satisfiabilityTest; - FalsifiabilityVisitor *falsifiabilityVisitor; - - size_t countSatisfiable(const std::vector & 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 & element) const - { - return boost::range::count_if(element, [&](const typename Base::Variant & expr) - { - return boost::apply_visitor(*falsifiabilityVisitor, expr); - }); - } - - public: - SatisfiabilityVisitor(std::function satisfiabilityTest): - satisfiabilityTest(satisfiabilityTest), - falsifiabilityVisitor(nullptr) - {} - - void setFalsifiabilityVisitor(FalsifiabilityVisitor *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 - class FalsifiabilityVisitor : public boost::static_visitor - { - typedef ExpressionBase Base; - std::function falsifiabilityTest; SatisfiabilityVisitor *satisfiabilityVisitor; + FalsifiabilityVisitor *falsifiabilityVisitor; size_t countSatisfiable(const std::vector & element) const { @@ -180,39 +128,97 @@ namespace LogicalExpressionDetail { return boost::range::count_if(element, [&](const typename Base::Variant & expr) { - return boost::apply_visitor(*this, expr); + return boost::apply_visitor(*falsifiabilityVisitor, expr); }); } public: - FalsifiabilityVisitor(std::function falsifiabilityTest): + PossibilityVisitor(std::function satisfiabilityTest, + std::function falsifiabilityTest): + satisfiabilityTest(satisfiabilityTest), falsifiabilityTest(falsifiabilityTest), - satisfiabilityVisitor(nullptr) + satisfiabilityVisitor(nullptr), + falsifiabilityVisitor(nullptr) {} - void setFalsifiabilityVisitor(SatisfiabilityVisitor *satisfiabilityVisitor) + void setSatisfiabilityVisitor(SatisfiabilityVisitor *satisfiabilityVisitor) { this->satisfiabilityVisitor = satisfiabilityVisitor; } + void setFalsifiabilityVisitor(FalsifiabilityVisitor *falsifiabilityVisitor) + { + this->falsifiabilityVisitor = falsifiabilityVisitor; + } + }; + + /// Visitor to test whether expression's value can be true + template + class SatisfiabilityVisitor : public PossibilityVisitor + { + typedef ExpressionBase Base; + + public: + SatisfiabilityVisitor(std::function satisfiabilityTest, + std::function falsifiabilityTest): + PossibilityVisitor(satisfiabilityTest, falsifiabilityTest) + { + this->setSatisfiabilityVisitor(this); + } + 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 { - return countFalsifiable(element.expressions) != 0; + return this->countSatisfiable(element.expressions) == element.expressions.size(); } 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 { - return falsifiabilityTest(element); + return this->satisfiabilityTest(element); + } + }; + + /// Visitor to test whether expression's value can be false + template + class FalsifiabilityVisitor : public PossibilityVisitor + { + typedef ExpressionBase Base; + + public: + FalsifiabilityVisitor(std::function satisfiabilityTest, + std::function falsifiabilityTest): + PossibilityVisitor(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". - bool satisfiable (std::function satisfiabilityTest, std::function falsifiabilityTest) const + bool satisfiable(std::function satisfiabilityTest, std::function falsifiabilityTest) const { - LogicalExpressionDetail::SatisfiabilityVisitor satisfiabilityVisitor(satisfiabilityTest); - LogicalExpressionDetail::FalsifiabilityVisitor falsifiabilityVisitor(falsifiabilityTest); + LogicalExpressionDetail::SatisfiabilityVisitor satisfiabilityVisitor(satisfiabilityTest, falsifiabilityTest); + LogicalExpressionDetail::FalsifiabilityVisitor falsifiabilityVisitor(satisfiabilityTest, falsifiabilityTest); satisfiabilityVisitor.setFalsifiabilityVisitor(&falsifiabilityVisitor); - falsifiabilityVisitor.setFalsifiabilityVisitor(&satisfiabilityVisitor); + falsifiabilityVisitor.setSatisfiabilityVisitor(&satisfiabilityVisitor); return boost::apply_visitor(satisfiabilityVisitor, data); }