浏览代码

Fixed two recursive infinite loops in case of alternate buildings.
* introduced in https://github.com/vcmi/vcmi/pull/211

AlexVinS 9 年之前
父节点
当前提交
f760e22707
共有 2 个文件被更改,包括 11 次插入10 次删除
  1. 1 6
      lib/CGameInfoCallback.cpp
  2. 10 4
      lib/mapObjects/CGTownInstance.cpp

+ 1 - 6
lib/CGameInfoCallback.cpp

@@ -539,12 +539,7 @@ EBuildingState::EBuildingState CGameInfoCallback::canBuildStructure( const CGTow
 
 
 	std::function<bool(BuildingID id)> allowedTest = [&](BuildingID id) -> bool
 	std::function<bool(BuildingID id)> allowedTest = [&](BuildingID id) -> bool
 	{
 	{
-		if (vstd::contains(t->forbiddenBuildings, id))
-		{
-			return false;
-		}
-
-		return t->genBuildingRequirements(id, true).satisfiable(allowedTest, possiblyNotBuiltTest);
+		return !vstd::contains(t->forbiddenBuildings, id);
 	};
 	};
 
 
 	if (!t->genBuildingRequirements(ID, true).satisfiable(allowedTest, possiblyNotBuiltTest))
 	if (!t->genBuildingRequirements(ID, true).satisfiable(allowedTest, possiblyNotBuiltTest))

+ 10 - 4
lib/mapObjects/CGTownInstance.cpp

@@ -1128,7 +1128,8 @@ CBuilding::TRequired CGTownInstance::genBuildingRequirements(BuildingID buildID,
 {
 {
 	const CBuilding * building = town->buildings.at(buildID);
 	const CBuilding * building = town->buildings.at(buildID);
 
 
-	deep = false;//FIXME: deep test crashes with alternate buildings
+	//TODO: find better solution to prevent infinite loops
+	std::set<BuildingID> processed;
 
 
 	std::function<CBuilding::TRequired::Variant(const BuildingID &)> dependTest =
 	std::function<CBuilding::TRequired::Variant(const BuildingID &)> dependTest =
 	[&](const BuildingID & id) -> CBuilding::TRequired::Variant
 	[&](const BuildingID & id) -> CBuilding::TRequired::Variant
@@ -1144,10 +1145,14 @@ CBuilding::TRequired CGTownInstance::genBuildingRequirements(BuildingID buildID,
 				return id;
 				return id;
 		}
 		}
 
 
-		if (build->upgrade != BuildingID::NONE)
-			requirements.expressions.push_back(dependTest(build->upgrade));
+		if(!vstd::contains(processed, id))
+		{
+			processed.insert(id);
+			if (build->upgrade != BuildingID::NONE)
+				requirements.expressions.push_back(dependTest(build->upgrade));
 
 
-		requirements.expressions.push_back(build->requirements.morph(dependTest));
+			requirements.expressions.push_back(build->requirements.morph(dependTest));
+		}
 		return requirements;
 		return requirements;
 	};
 	};
 
 
@@ -1157,6 +1162,7 @@ CBuilding::TRequired CGTownInstance::genBuildingRequirements(BuildingID buildID,
 		const CBuilding * upgr = town->buildings.at(building->upgrade);
 		const CBuilding * upgr = town->buildings.at(building->upgrade);
 
 
 		requirements.expressions.push_back(dependTest(upgr->bid));
 		requirements.expressions.push_back(dependTest(upgr->bid));
+		processed.clear();
 	}
 	}
 	requirements.expressions.push_back(building->requirements.morph(dependTest));
 	requirements.expressions.push_back(building->requirements.morph(dependTest));