浏览代码

Improvements for AI speed (#1760)

AI heroes will be excluded from exploration if:
- There is no clear way to next exploration point or
- There is no possible exploration point at all
AI heroes will be erased from the list above if:
- FoW changes
- New object is added
- To prevent lock, primary hero will be erased at the start of each turn
DjWarmonger 11 年之前
父节点
当前提交
441e4b2cb2
共有 3 个文件被更改,包括 45 次插入7 次删除
  1. 13 4
      AI/VCAI/Goals.cpp
  2. 23 0
      AI/VCAI/VCAI.cpp
  3. 9 3
      AI/VCAI/VCAI.h

+ 13 - 4
AI/VCAI/Goals.cpp

@@ -567,6 +567,9 @@ TGoalVec Explore::getAllPossibleSubgoals()
 			if (ai->getGoal(h)->goalType == Goals::EXPLORE) //do not reassign hero who is already explorer
 				return true;
 
+			if (!ai->isAbleToExplore(h))
+				return true;
+
 			return !h->movement; //saves time, immobile heroes are useless anyway
 		});
 	}
@@ -603,11 +606,17 @@ TGoalVec Explore::getAllPossibleSubgoals()
 		{
 			ret.push_back (sptr (Goals::VisitTile(t).sethero(h)));
 		}
-		else if (hero.h == h || (!hero && h == ai->primaryHero().h)) //check this only ONCE, high cost
+		else
 		{
-			t = ai->explorationDesperate(h);
-			if (t.valid()) //don't waste time if we are completely blocked
-				ret.push_back (sptr(Goals::ClearWayTo(t, h).setisAbstract(true)));
+			ai->markHeroUnableToExplore (h); //there is no freely accessible tile, do not poll this hero anymore
+			//possible issues when gathering army to break
+
+			if (hero.h == h || (!hero && h == ai->primaryHero().h)) //check this only ONCE, high cost
+			{
+				t = ai->explorationDesperate(h);
+				if (t.valid()) //don't waste time if we are completely blocked
+					ret.push_back (sptr(Goals::ClearWayTo(t, h).setisAbstract(true)));
+			}
 		}
 	}
 	//we either don't have hero yet or none of heroes can explore

+ 23 - 0
AI/VCAI/VCAI.cpp

@@ -282,6 +282,8 @@ void VCAI::tileRevealed(const std::unordered_set<int3, ShashInt3> &pos)
 	for(int3 tile : pos)
 		for(const CGObjectInstance *obj : myCb->getVisitableObjs(tile))
 			addVisitableObj(obj);
+
+	clearHeroesUnableToExplore();
 }
 
 void VCAI::heroExchangeStarted(ObjectInstanceID hero1, ObjectInstanceID hero2, QueryID query)
@@ -361,6 +363,8 @@ void VCAI::newObject(const CGObjectInstance * obj)
 	NET_EVENT_HANDLER;
 	if(obj->isVisitable())
 		addVisitableObj(obj);
+
+	clearHeroesUnableToExplore();
 }
 
 void VCAI::objectRemoved(const CGObjectInstance *obj)
@@ -661,6 +665,8 @@ void VCAI::makeTurn()
 	if(cb->getSelectedHero())
 		cb->recalculatePaths();
 
+	markHeroAbleToExplore (primaryHero());
+
 	makeTurnInternal();
 	makingTurn.reset();
 
@@ -1469,6 +1475,23 @@ void VCAI::unreserveObject(HeroPtr h, const CGObjectInstance *obj)
 	erase_if_present(reservedHeroesMap[h], obj);
 }
 
+void VCAI::markHeroUnableToExplore (HeroPtr h)
+{
+	heroesUnableToExplore.insert(h);
+}
+void VCAI::markHeroAbleToExplore (HeroPtr h)
+{
+	erase_if_present(heroesUnableToExplore, h);
+}
+bool VCAI::isAbleToExplore (HeroPtr h)
+{
+	return !vstd::contains (heroesUnableToExplore, h);
+}
+void VCAI::clearHeroesUnableToExplore()
+{
+	heroesUnableToExplore.clear();
+}
+
 void VCAI::validateVisitableObjs()
 {
 	std::vector<const CGObjectInstance *> hlp;

+ 9 - 3
AI/VCAI/VCAI.h

@@ -149,6 +149,7 @@ public:
 
 	std::map<HeroPtr, Goals::TSubgoal> lockedHeroes; //TODO: allow non-elementar objectives
 	std::map<HeroPtr, std::set<const CGObjectInstance *> > reservedHeroesMap; //objects reserved by specific heroes
+	std::set<HeroPtr> heroesUnableToExplore; //these heroes will not be polled for exploration in current state of game
 
 	//sets are faster to search, also do not contain duplicates
 	std::set<const CGObjectInstance *> visitableObjs;
@@ -282,8 +283,13 @@ public:
 	void addVisitableObj(const CGObjectInstance *obj);
 	void markObjectVisited (const CGObjectInstance *obj);
 	void reserveObject (HeroPtr h, const CGObjectInstance *obj); //TODO: reserve all objects that heroes attempt to visit
-	void unreserveObject (HeroPtr h, const CGObjectInstance *obj); 
-	//void removeVisitableObj(const CGObjectInstance *obj);
+	void unreserveObject (HeroPtr h, const CGObjectInstance *obj);
+
+	void markHeroUnableToExplore (HeroPtr h);
+	void markHeroAbleToExplore (HeroPtr h);
+	bool isAbleToExplore (HeroPtr h);
+	void clearHeroesUnableToExplore();
+
 	void validateObject(const CGObjectInstance *obj); //checks if object is still visible and if not, removes references to it
 	void validateObject(ObjectIdRef obj); //checks if object is still visible and if not, removes references to it
 	void validateVisitableObjs();
@@ -344,7 +350,7 @@ public:
 		h & knownSubterraneanGates & townVisitsThisWeek & lockedHeroes & reservedHeroesMap; //FIXME: cannot instantiate abstract class
 		h & visitableObjs & alreadyVisited & reservedObjs;
 		h & saving & status & battlename;
-
+		h & heroesUnableToExplore;
 
 		//myCB is restored after load by init call
 	}