Пример #1
0
TGoalVec ClearWayTo::getAllPossibleSubgoals()
{
	TGoalVec ret;
	for (auto h : cb->getHeroesInfo())
	{
		if ((hero && hero->visitablePos() == tile && hero == *h) || //we can't free the way ourselves
			h->visitablePos() == tile) //we are already on that tile! what does it mean?
			continue;

		SectorMap sm(h);

		int3 tileToHit = sm.firstTileToGet(hero ? hero : h, tile);
		//if our hero is trapped, make sure we request clearing the way from OUR perspective
		if (!tileToHit.valid())
			continue;

		if (isBlockedBorderGate(tileToHit))
		{	//FIXME: this way we'll not visit gate and activate quest :?
			ret.push_back  (sptr (Goals::FindObj (Obj::KEYMASTER, cb->getTile(tileToHit)->visitableObjects.back()->subID)));
		}

		auto topObj = cb->getTopObj(tileToHit);
		if(topObj)
		{
			if (topObj->ID == Obj::HERO && cb->getPlayerRelations(h->tempOwner, topObj->tempOwner) != PlayerRelations::ENEMIES)
				if (topObj != hero.get(true)) //the hero we wnat to free
					logAi->errorStream() << boost::format("%s stands in the way of %s") % topObj->getHoverText()  % h->getHoverText();
			if (topObj->ID == Obj::QUEST_GUARD || topObj->ID == Obj::BORDERGUARD)
			{
				if (shouldVisit(h, topObj))
				{
					//do NOT use VISIT_TILE, as tile with quets guard can't be visited
					ret.push_back (sptr (Goals::GetObj(topObj->id.getNum()).sethero(h)));
				}
				else
				{
					//TODO: we should be able to return apriopriate quest here (VCAI::striveToQuest)
					logAi->debugStream() << "Quest guard blocks the way to " + tile();
				}
			}
		}
		else
			ret.push_back (sptr (Goals::VisitTile(tileToHit).sethero(h)));
	}
	if (ai->canRecruitAnyHero())
		ret.push_back (sptr (Goals::RecruitHero()));

	if (ret.empty())
	{
		logAi->warnStream() << "There is no known way to clear the way to tile " + tile();
		throw goalFulfilledException (sptr(*this)); //make sure asigned hero gets unlocked
	}

	return ret;
}
Пример #2
0
ui64 evaluateDanger(crint3 tile, const CGHeroInstance *visitor)
{
	const TerrainTile *t = cb->getTile(tile, false);
	if(!t) //we can know about guard but can't check its tile (the edge of fow)
		return 190000000; //MUCH

	ui64 objectDanger = 0, guardDanger = 0;

	auto visitableObjects = cb->getVisitableObjs(tile);
	// in some scenarios hero happens to be "under" the object (eg town). Then we consider ONLY the hero.
	if(vstd::contains_if(visitableObjects, objWithID<Obj::HERO>))
		vstd::erase_if(visitableObjects, [](const CGObjectInstance * obj)
		{
			return !objWithID<Obj::HERO>(obj);
		});

	if(const CGObjectInstance * dangerousObject = vstd::backOrNull(visitableObjects))
	{
		objectDanger = evaluateDanger(dangerousObject); //unguarded objects can also be dangerous or unhandled
		if (objectDanger)
		{
			//TODO: don't downcast objects AI shouldn't know about!
			auto armedObj = dynamic_cast<const CArmedInstance*>(dangerousObject);
			if (armedObj)
			{
				float tacticalAdvantage = fh->getTacticalAdvantage(visitor, armedObj);
				objectDanger *= tacticalAdvantage; //this line tends to go infinite for allied towns (?)
			}
		}
		if (dangerousObject->ID == Obj::SUBTERRANEAN_GATE)
		{ //check guard on the other side of the gate
			auto it = ai->knownSubterraneanGates.find(dangerousObject);
			if (it != ai->knownSubterraneanGates.end())
			{
				auto guards = cb->getGuardingCreatures(it->second->visitablePos());
				for (auto cre : guards)
				{
					vstd::amax (guardDanger, evaluateDanger(cre) *
						fh->getTacticalAdvantage(visitor, dynamic_cast<const CArmedInstance*>(cre)));
				}
			}
		}
	}

	auto guards = cb->getGuardingCreatures(tile);
	for (auto cre : guards)
	{
		vstd::amax (guardDanger, evaluateDanger(cre) * fh->getTacticalAdvantage(visitor, dynamic_cast<const CArmedInstance*>(cre))); //we are interested in strongest monster around
	}


	//TODO mozna odwiedzic blockvis nie ruszajac straznika
	return std::max(objectDanger, guardDanger);
}
Пример #3
0
ui64 evaluateDanger(crint3 tile)
{
	const TerrainTile *t = cb->getTile(tile, false);
	if(!t) //we can know about guard but can't check its tile (the edge of fow)
		return 190000000; //MUCH

	ui64 objectDanger = 0, guardDanger = 0;

	auto visObjs = cb->getVisitableObjs(tile);
	if(visObjs.size())
		objectDanger = evaluateDanger(visObjs.back());

	int3 guardPos = cb->guardingCreaturePosition(tile);
	if(guardPos.x >= 0 && guardPos != tile)
		guardDanger = evaluateDanger(guardPos);

	//TODO mozna odwiedzic blockvis nie ruszajac straznika
	return std::max(objectDanger, guardDanger);
}
Пример #4
0
bool boundaryBetweenTwoPoints (int3 pos1, int3 pos2) //determines if two points are separated by known barrier
{
	int xMin = std::min (pos1.x, pos2.x);
	int xMax = std::max (pos1.x, pos2.x);
	int yMin = std::min (pos1.y, pos2.y);
	int yMax = std::max (pos1.y, pos2.y);

	for (int x = xMin; x <= xMax; ++x)
	{
		for (int y = yMin; y <= yMax; ++y)
		{
			int3 tile = int3(x, y, pos1.z); //use only on same level, ofc
			if (abs(pos1.dist2d(tile) - pos2.dist2d(tile)) < 1.5)
			{
				if (!(cb->isVisible(tile) && cb->getTile(tile)->blocked)) //if there's invisible or unblocked tile inbetween, it's good 
					return false;
			}
		}
	}
	return true; //if all are visible and blocked, we're at dead end
}
Пример #5
0
TGoalVec ClearWayTo::getAllPossibleSubgoals()
{
	TGoalVec ret;

	std::vector<const CGHeroInstance *> heroes;

	if (hero)
		heroes.push_back(hero.h);
	else
	{
		heroes = cb->getHeroesInfo();
	}

	for (auto h : heroes)
	{
		//TODO: handle clearing way to allied heroes that are blocked
		//if ((hero && hero->visitablePos() == tile && hero == *h) || //we can't free the way ourselves
		//	h->visitablePos() == tile) //we are already on that tile! what does it mean?
		//	continue;

		//if our hero is trapped, make sure we request clearing the way from OUR perspective

		SectorMap sm(h);

		int3 tileToHit = sm.firstTileToGet(h, tile);
		if (!tileToHit.valid())
			continue;

		if (isBlockedBorderGate(tileToHit))
		{	//FIXME: this way we'll not visit gate and activate quest :?
			ret.push_back  (sptr (Goals::FindObj (Obj::KEYMASTER, cb->getTile(tileToHit)->visitableObjects.back()->subID)));
		}

		auto topObj = cb->getTopObj(tileToHit);
		if (topObj)
		{
			if (vstd::contains(ai->reservedObjs, topObj) && !vstd::contains(ai->reservedHeroesMap[h], topObj))
			{
				throw goalFulfilledException (sptr(Goals::ClearWayTo(tile, h)));
				continue; //do not capure object reserved by other hero
			}

			if (topObj->ID == Obj::HERO && cb->getPlayerRelations(h->tempOwner, topObj->tempOwner) != PlayerRelations::ENEMIES)
				if (topObj != hero.get(true)) //the hero we want to free
					logAi->errorStream() << boost::format("%s stands in the way of %s") % topObj->getHoverText()  % h->getHoverText();
			if (topObj->ID == Obj::QUEST_GUARD || topObj->ID == Obj::BORDERGUARD)
			{
				if (shouldVisit(h, topObj))
				{
					//do NOT use VISIT_TILE, as tile with quets guard can't be visited
					ret.push_back (sptr (Goals::GetObj(topObj->id.getNum()).sethero(h)));
					continue; //do not try to visit tile or gather army
				}
				else
				{
					//TODO: we should be able to return apriopriate quest here (VCAI::striveToQuest)
					logAi->debugStream() << "Quest guard blocks the way to " + tile();
				}
			}
		}

		if (isSafeToVisit(h, tileToHit)) //this makes sense only if tile is guarded, but there i no quest object
		{
			ret.push_back (sptr (Goals::VisitTile(tileToHit).sethero(h)));
		}
		else
		{
			ret.push_back (sptr (Goals::GatherArmy(evaluateDanger(tileToHit, h)*SAFE_ATTACK_CONSTANT).
				sethero(h).setisAbstract(true)));
		}
	}
	if (ai->canRecruitAnyHero())
		ret.push_back (sptr (Goals::RecruitHero()));

	if (ret.empty())
	{
		logAi->warnStream() << "There is no known way to clear the way to tile " + tile();
		throw goalFulfilledException (sptr(Goals::ClearWayTo(tile))); //make sure asigned hero gets unlocked
	}

	return ret;
}
Пример #6
0
bool isBlockedBorderGate(int3 tileToHit)
{
    return cb->getTile(tileToHit)->topVisitableId() == Obj::BORDER_GATE
		&& cb->getPathInfo(tileToHit)->accessible != CGPathNode::ACCESSIBLE;
}
Пример #7
0
bool isBlockedBorderGate(int3 tileToHit)
{
    return cb->getTile(tileToHit)->topVisitableId() == Obj::BORDER_GATE &&
	       (dynamic_cast <const CGKeys *>(cb->getTile(tileToHit)->visitableObjects.back()))->wasMyColorVisited (ai->playerID);
}