| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158 | /** BuildingManager.cpp, part of VCMI engine** Authors: listed in file AUTHORS in main folder** License: GNU General Public License v2.0 or later* Full text of license available in license.txt file, in main folder**/#include "StdInc.h"#include "ArmyManager.h"#include "../../lib/mapObjects/MapObjects.h"void ArmyManager::init(CPlayerSpecificInfoCallback * CB){	cb = CB;}void ArmyManager::setAI(VCAI * AI){	ai = AI;}std::vector<SlotInfo> ArmyManager::getSortedSlots(const CCreatureSet * target, const CCreatureSet * source) const{	const CCreatureSet * armies[] = { target, source };	//we calculate total strength for each creature type available in armies	std::map<const CCreature *, SlotInfo> creToPower;	std::vector<SlotInfo> resultingArmy;	for(auto armyPtr : armies)	{		for(auto & i : armyPtr->Slots())		{			auto cre = dynamic_cast<const CCreature*>(i.second->getType());			auto & slotInfp = creToPower[cre];			slotInfp.creature = cre;			slotInfp.power += i.second->getPower();			slotInfp.count += i.second->getCount();		}	}	for(auto pair : creToPower)		resultingArmy.push_back(pair.second);	boost::sort(resultingArmy, [](const SlotInfo & left, const SlotInfo & right) -> bool	{		return left.power > right.power;	});	return resultingArmy;}std::vector<SlotInfo>::iterator ArmyManager::getWeakestCreature(std::vector<SlotInfo> & army) const{	auto weakest = boost::min_element(army, [](const SlotInfo & left, const SlotInfo & right) -> bool	{		if(left.creature->getLevel() != right.creature->getLevel())			return left.creature->getLevel() < right.creature->getLevel();				return left.creature->getMovementRange() > right.creature->getMovementRange();	});	return weakest;}std::vector<SlotInfo> ArmyManager::getBestArmy(const CCreatureSet * target, const CCreatureSet * source) const{	auto resultingArmy = getSortedSlots(target, source);	if(resultingArmy.size() > GameConstants::ARMY_SIZE)	{		resultingArmy.resize(GameConstants::ARMY_SIZE);	}	else if(source->needsLastStack())	{		auto weakest = getWeakestCreature(resultingArmy);		if(weakest->count == 1)		{			resultingArmy.erase(weakest);		}		else		{			weakest->power -= weakest->power / weakest->count;			weakest->count--;		}	}	return resultingArmy;}bool ArmyManager::canGetArmy(const CArmedInstance * target, const CArmedInstance * source) const{	//TODO: merge with pickBestCreatures	//if (ai->primaryHero().h == source)	if(target->tempOwner != source->tempOwner)	{		logAi->error("Why are we even considering exchange between heroes from different players?");		return false;	}	return 0 < howManyReinforcementsCanGet(target, source);}ui64 ArmyManager::howManyReinforcementsCanBuy(const CCreatureSet * h, const CGDwelling * t) const{	ui64 aivalue = 0;	TResources availableRes = cb->getResourceAmount();	int freeHeroSlots = GameConstants::ARMY_SIZE - h->stacksCount();	for(auto const & dc : t->creatures)	{		creInfo ci = infoFromDC(dc);		if(!ci.count || ci.creID == CreatureID::NONE)			continue;		vstd::amin(ci.count, availableRes / ci.cre->getFullRecruitCost()); //max count we can afford		if(ci.count && ci.creID != CreatureID::NONE) //valid creature at this level		{			//can be merged with another stack?			SlotID dst = h->getSlotFor(ci.creID);			if(!h->hasStackAtSlot(dst)) //need another new slot for this stack			{				if(!freeHeroSlots) //no more place for stacks					continue;				else					freeHeroSlots--; //new slot will be occupied			}			//we found matching occupied or free slot			aivalue += ci.count * ci.cre->getAIValue();			availableRes -= ci.cre->getFullRecruitCost() * ci.count;		}	}	return aivalue;}ui64 ArmyManager::howManyReinforcementsCanGet(const CCreatureSet * target, const CCreatureSet * source) const{	auto bestArmy = getBestArmy(target, source);	uint64_t newArmy = 0;	uint64_t oldArmy = target->getArmyStrength();	for(auto & slot : bestArmy)	{		newArmy += slot.power;	}	return newArmy > oldArmy ? newArmy - oldArmy : 0;}
 |