浏览代码

Fixed #1131 - AI will use subterranean gate for exploration

DjWarmonger 13 年之前
父节点
当前提交
b3acde24d5
共有 1 个文件被更改,包括 47 次插入6 次删除
  1. 47 6
      AI/VCAI/VCAI.cpp

+ 47 - 6
AI/VCAI/VCAI.cpp

@@ -2720,7 +2720,7 @@ int3 whereToExplore(HeroPtr h)
 			}
 
 			if(profits.empty())
-				throw cannotFulfillGoalException("Cannot explore - no possible ways found!");
+				return int3 (-1,-1,-1);
 
 			auto bestDest = profits.end();
 			bestDest--;
@@ -2927,14 +2927,28 @@ TSubgoal CGoal::whatToDoToAchieve()
 
 		}
 		throw cannotFulfillGoalException("Cannot reach given tile!");
-		//return CGoal(EXPLORE); // TODO improve
 	case EXPLORE:
 		{
 			auto objs = ai->visitableObjs; //try to use buildings that uncover map
-			erase_if(objs, [&](const CGObjectInstance *obj)
+			erase_if(objs, [&](const CGObjectInstance *obj) -> bool
 			{
-				return (obj->ID != Obj::REDWOOD_OBSERVATORY && obj->ID != Obj::PILLAR_OF_FIRE && obj->ID != Obj::CARTOGRAPHER)
-					|| vstd::contains(ai->alreadyVisited, obj); //TODO: check if object radius is uncovered? worth it?
+				if (vstd::contains(ai->alreadyVisited, obj))
+					return true;
+				switch (obj->ID)
+				{
+					case Obj::REDWOOD_OBSERVATORY:
+					case Obj::PILLAR_OF_FIRE:
+					case Obj::CARTOGRAPHER:
+					case Obj::SUBTERRANEAN_GATE: //TODO: check ai->knownSubterraneanGates
+					//case Obj::MONOLITH1:
+					//case obj::MONOLITH2:
+					//case obj::MONOLITH3:
+					//case Obj::WHIRLPOOL:
+						return false; //do not erase
+						break;
+					default:
+						return true;
+				}
 			});
 			if (objs.size())
 			{
@@ -2943,6 +2957,7 @@ TSubgoal CGoal::whatToDoToAchieve()
 					BOOST_FOREACH (auto obj, objs)
 					{
 						auto pos = obj->visitablePos();
+						//FIXME: this confition fails if everything but guarded subterranen gate was explored. in this case we should gather army for hero
 						if (isSafeToVisit(hero, pos) && ai->isAccessibleForHero(pos, hero))
 							return CGoal(VISIT_TILE).settile(pos).sethero(hero);
 					}
@@ -2960,7 +2975,33 @@ TSubgoal CGoal::whatToDoToAchieve()
 
 			if (hero)
 			{
-				return CGoal(VISIT_TILE).settile(whereToExplore(hero)).sethero(hero);
+				int3 t = whereToExplore(hero);
+				if (t.z == -1) //no safe tile to explore - we need to break!
+				{
+					erase_if (objs, [&](const CGObjectInstance *obj) -> bool
+					{
+						switch (obj->ID)
+						{
+							case Obj::CARTOGRAPHER:
+							case Obj::SUBTERRANEAN_GATE:
+							//case Obj::MONOLITH1:
+							//case obj::MONOLITH2:
+							//case obj::MONOLITH3:
+							//case Obj::WHIRLPOOL:
+								return false; //do not erase
+								break;
+							default:
+								return true;
+						}
+					});
+					if (objs.size())
+					{
+						return CGoal (VISIT_TILE).settile(objs.front()->visitablePos()).sethero(hero).setisAbstract(true);
+					}
+					else
+						throw cannotFulfillGoalException("Cannot explore - no possible ways found!");
+				}
+				return CGoal(VISIT_TILE).settile(t).sethero(hero);
 			}
 
 			auto hs = cb->getHeroesInfo();