Example #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;
}
Example #2
0
int3 SectorMap::findFirstVisitableTile(HeroPtr h, crint3 dst)
{
	int3 ret(-1, -1, -1);
	int3 curtile = dst;

	while (curtile != h->visitablePos())
	{
		auto topObj = cb->getTopObj(curtile);
		if (topObj && topObj->ID == Obj::HERO && topObj != h.h)
		{
			if (cb->getPlayerRelations(h->tempOwner, topObj->tempOwner) != PlayerRelations::ENEMIES)
			{
				logAi->warn("Another allied hero stands in our way");
				return ret;
			}
		}
		if (ai->myCb->getPathsInfo(h.get())->getPathInfo(curtile)->reachable())
		{
			return curtile;
		}
		else
		{
			auto i = parent.find(curtile);
			if (i != parent.end())
			{
				assert(curtile != i->second);
				curtile = i->second;
			}
			else
			{
				return ret;
				//throw cannotFulfillGoalException("Unreachable tile in sector? Should not happen!");
			}
		}
	}
	return ret;
}
Example #3
0
File: Goals.cpp Project: szpak/vcmi
TSubgoal CollectRes::whatToDoToAchieve()
{
	std::vector<const IMarket*> markets;

	std::vector<const CGObjectInstance*> visObjs;
	ai->retreiveVisitableObjs(visObjs, true);
	for(const CGObjectInstance *obj : visObjs)
	{
		if(const IMarket *m = IMarket::castFrom(obj, false))
		{
			if(obj->ID == Obj::TOWN && obj->tempOwner == ai->playerID && m->allowsTrade(EMarketMode::RESOURCE_RESOURCE))
				markets.push_back(m);
			else if(obj->ID == Obj::TRADING_POST) //TODO a moze po prostu test na pozwalanie handlu?
				markets.push_back(m);
		}
	}

	boost::sort(markets, [](const IMarket *m1, const IMarket *m2) -> bool
	{
		return m1->getMarketEfficiency() < m2->getMarketEfficiency();
	});

	markets.erase(boost::remove_if(markets, [](const IMarket *market) -> bool
	{
		return !(market->o->ID == Obj::TOWN && market->o->tempOwner == ai->playerID)
			&& !ai->isAccessible(market->o->visitablePos());
	}),markets.end());

	if(!markets.size())
	{
		for(const CGTownInstance *t : cb->getTownsInfo())
		{
			if(cb->canBuildStructure(t, BuildingID::MARKETPLACE) == EBuildingState::ALLOWED)
				return sptr (Goals::BuildThis(BuildingID::MARKETPLACE, t));
		}
	}
	else
	{
		const IMarket *m = markets.back();
		//attempt trade at back (best prices)
		int howManyCanWeBuy = 0;
		for(Res::ERes i = Res::WOOD; i <= Res::GOLD; vstd::advance(i, 1))
		{
			if(i == resID) continue;
			int toGive = -1, toReceive = -1;
			m->getOffer(i, resID, toGive, toReceive, EMarketMode::RESOURCE_RESOURCE);
			assert(toGive > 0 && toReceive > 0);
			howManyCanWeBuy += toReceive * (cb->getResourceAmount(i) / toGive);
		}

		if(howManyCanWeBuy + cb->getResourceAmount(static_cast<Res::ERes>(resID)) >= value)
		{
			auto backObj = cb->getTopObj(m->o->visitablePos()); //it'll be a hero if we have one there; otherwise marketplace
			assert(backObj);
			if (backObj->tempOwner != ai->playerID)
			{
				return sptr (Goals::GetObj(m->o->id.getNum()));
			}
			else
			{
				return sptr (Goals::GetObj(m->o->id.getNum()).setisElementar(true));
			}
		}
	}
	return sptr (setisElementar(true)); //all the conditions for trade are met
}
Example #4
0
File: Goals.cpp Project: szpak/vcmi
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;
}
Example #5
0
TSubgoal CollectRes::whatToDoToTrade()
{
	std::vector<const IMarket *> markets;

	std::vector<const CGObjectInstance *> visObjs;
	ai->retrieveVisitableObjs(visObjs, true);
	for (const CGObjectInstance * obj : visObjs)
	{
		if (const IMarket * m = IMarket::castFrom(obj, false))
		{
			if (obj->ID == Obj::TOWN && obj->tempOwner == ai->playerID && m->allowsTrade(EMarketMode::RESOURCE_RESOURCE))
				markets.push_back(m);
			else if (obj->ID == Obj::TRADING_POST)
				markets.push_back(m);
		}
	}

	boost::sort(markets, [](const IMarket * m1, const IMarket * m2) -> bool
	{
		return m1->getMarketEfficiency() < m2->getMarketEfficiency();
	});

	markets.erase(boost::remove_if(markets, [](const IMarket * market) -> bool
	{
		if (!(market->o->ID == Obj::TOWN && market->o->tempOwner == ai->playerID))
		{
			if (!ai->isAccessible(market->o->visitablePos()))
				return true;
		}
		return false;
	}), markets.end());

	if (!markets.size())
	{
		for (const CGTownInstance * t : cb->getTownsInfo())
		{
			if (cb->canBuildStructure(t, BuildingID::MARKETPLACE) == EBuildingState::ALLOWED)
				return sptr(BuildThis(BuildingID::MARKETPLACE, t).setpriority(2));
		}
	}
	else
	{
		const IMarket * m = markets.back();
		//attempt trade at back (best prices)
		int howManyCanWeBuy = 0;
		for (Res::ERes i = Res::WOOD; i <= Res::GOLD; vstd::advance(i, 1))
		{
			if (i == resID)
				continue;
			int toGive = -1, toReceive = -1;
			m->getOffer(i, resID, toGive, toReceive, EMarketMode::RESOURCE_RESOURCE);
			assert(toGive > 0 && toReceive > 0);
			howManyCanWeBuy += toReceive * (ai->ah->freeResources()[i] / toGive);
		}

		if (howManyCanWeBuy >= value)
		{
			auto backObj = cb->getTopObj(m->o->visitablePos()); //it'll be a hero if we have one there; otherwise marketplace
			assert(backObj);
			auto objid = m->o->id.getNum();
			if (backObj->tempOwner != ai->playerID) //top object not owned
			{
				return sptr(VisitObj(objid)); //just go there
			}
			else //either it's our town, or we have hero there
			{
				return sptr(Trade(resID, value, objid).setisElementar(true)); //we can do this immediately
			}
		}
	}
	return sptr(Invalid()); //cannot trade
}