Explorar o código

Extract PossibilityVisitor

Piotr Wójcik %!s(int64=9) %!d(string=hai) anos
pai
achega
e1a1bc89c0
Modificáronse 2 ficheiros con 54 adicións e 52 borrados
  1. 5 9
      lib/CGameInfoCallback.cpp
  2. 49 43
      lib/LogicalExpression.h

+ 5 - 9
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<bool(BuildingID id)> allowedTest;
-	std::function<bool(BuildingID id)> possiblyNotBuiltTest;
+	auto possiblyNotBuiltTest = [&](BuildingID id) -> bool
+	{
+		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))
 		{
@@ -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;
 

+ 49 - 43
lib/LogicalExpression.h

@@ -99,23 +99,28 @@ namespace LogicalExpressionDetail
 		}
 	};
 
+	template <typename ContainedClass>
+	class SatisfiabilityVisitor;
+
 	template <typename ContainedClass>
 	class FalsifiabilityVisitor;
 
-	/// Visitor to test whether expression's value can be true
 	template <typename ContainedClass>
-	class SatisfiabilityVisitor : public boost::static_visitor<bool>
+	class PossibilityVisitor : public boost::static_visitor<bool>
 	{
 		typedef ExpressionBase<ContainedClass> Base;
 
+	protected:
 		std::function<bool(const typename Base::Value &)> satisfiabilityTest;
+		std::function<bool(const typename Base::Value &)> falsifiabilityTest;
+		SatisfiabilityVisitor<ContainedClass> *satisfiabilityVisitor;
 		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);
+				return boost::apply_visitor(*satisfiabilityVisitor, expr);
 			});
 		}
 
@@ -128,91 +133,92 @@ namespace LogicalExpressionDetail
 		}
 
 	public:
-		SatisfiabilityVisitor(std::function<bool (const typename Base::Value &)> satisfiabilityTest):
+		PossibilityVisitor(std::function<bool (const typename Base::Value &)> satisfiabilityTest,
+		                   std::function<bool (const typename Base::Value &)> falsifiabilityTest):
 			satisfiabilityTest(satisfiabilityTest),
+			falsifiabilityTest(falsifiabilityTest),
+			satisfiabilityVisitor(nullptr),
 			falsifiabilityVisitor(nullptr)
 		{}
 
+		void setSatisfiabilityVisitor(SatisfiabilityVisitor<ContainedClass> *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
 		{
-			return countSatisfiable(element.expressions) != 0;
+			return this->countSatisfiable(element.expressions) != 0;
 		}
 
 		bool operator()(const typename Base::OperatorAll & element) const
 		{
-			return countSatisfiable(element.expressions) == element.expressions.size();
+			return this->countSatisfiable(element.expressions) == element.expressions.size();
 		}
 
 		bool operator()(const typename Base::OperatorNone & element) const
 		{
-			return countFalsifiable(element.expressions) == element.expressions.size();
+			return this->countFalsifiable(element.expressions) == element.expressions.size();
 		}
 
 		bool operator()(const typename Base::Value & element) const
 		{
-			return satisfiabilityTest(element);
+			return this->satisfiabilityTest(element);
 		}
 	};
 
 	/// Visitor to test whether expression's value can be false
 	template <typename ContainedClass>
-	class FalsifiabilityVisitor : public boost::static_visitor<bool>
+	class FalsifiabilityVisitor : public PossibilityVisitor<ContainedClass>
 	{
 		typedef ExpressionBase<ContainedClass> Base;
 
-		std::function<bool(const typename Base::Value &)> falsifiabilityTest;
-		SatisfiabilityVisitor<ContainedClass> *satisfiabilityVisitor;
-
-		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(*satisfiabilityVisitor, 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(*this, expr);
-			});
-		}
-
 	public:
-		FalsifiabilityVisitor(std::function<bool (const typename Base::Value &)> falsifiabilityTest):
-			falsifiabilityTest(falsifiabilityTest),
-			satisfiabilityVisitor(nullptr)
-		{}
-
-		void setFalsifiabilityVisitor(SatisfiabilityVisitor<ContainedClass> *satisfiabilityVisitor)
+		FalsifiabilityVisitor(std::function<bool (const typename Base::Value &)> satisfiabilityTest,
+		                      std::function<bool (const typename Base::Value &)> falsifiabilityTest):
+			PossibilityVisitor<ContainedClass>(satisfiabilityTest, falsifiabilityTest)
 		{
-			this->satisfiabilityVisitor = satisfiabilityVisitor;
+			this->setFalsifiabilityVisitor(this);
 		}
 
 		bool operator()(const typename Base::OperatorAny & element) const
 		{
-			return countFalsifiable(element.expressions) == element.expressions.size();
+			return this->countFalsifiable(element.expressions) == element.expressions.size();
 		}
 
 		bool operator()(const typename Base::OperatorAll & element) const
 		{
-			return countFalsifiable(element.expressions) != 0;
+			return this->countFalsifiable(element.expressions) != 0;
 		}
 
 		bool operator()(const typename Base::OperatorNone & element) const
 		{
-			return countSatisfiable(element.expressions) != 0;
+			return this->countSatisfiable(element.expressions) != 0;
 		}
 
 		bool operator()(const typename Base::Value & element) const
 		{
-			return falsifiabilityTest(element);
+			return this->falsifiabilityTest(element);
 		}
 	};
 
@@ -554,13 +560,13 @@ public:
 	}
 
 	/// 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::FalsifiabilityVisitor<Value> falsifiabilityVisitor(falsifiabilityTest);
+		LogicalExpressionDetail::SatisfiabilityVisitor<Value> satisfiabilityVisitor(satisfiabilityTest, falsifiabilityTest);
+		LogicalExpressionDetail::FalsifiabilityVisitor<Value> falsifiabilityVisitor(satisfiabilityTest, falsifiabilityTest);
 
 		satisfiabilityVisitor.setFalsifiabilityVisitor(&falsifiabilityVisitor);
-		falsifiabilityVisitor.setFalsifiabilityVisitor(&satisfiabilityVisitor);
+		falsifiabilityVisitor.setSatisfiabilityVisitor(&satisfiabilityVisitor);
 
 		return boost::apply_visitor(satisfiabilityVisitor, data);
 	}