mirror of
				https://github.com/vcmi/vcmi.git
				synced 2025-10-31 00:07:39 +02:00 
			
		
		
		
	Rewritten VCAI::pickBestCreatures. Should fix the compilation error ( http://forum.vcmi.eu/viewtopic.php?p=6605#6605 ).
This commit is contained in:
		| @@ -863,6 +863,10 @@ void VCAI::makeTurnInternal() | ||||
| 	blockedHeroes.clear(); | ||||
| 	saving = 0; | ||||
|  | ||||
| 	//it looks messy here, but it's better to have armed heroes before attempting realizing goals | ||||
| 	BOOST_FOREACH(const CGTownInstance *t, cb->getTownsInfo()) | ||||
| 		moveCreaturesToHero(t); | ||||
|  | ||||
| 	try | ||||
| 	{ | ||||
| 		striveToGoal(CGoal(WIN)); | ||||
| @@ -901,7 +905,7 @@ void VCAI::performObjectInteraction(const CGObjectInstance * obj, const CGHeroIn | ||||
|  | ||||
| void VCAI::moveCreaturesToHero(const CGTownInstance * t) | ||||
| { | ||||
| 	if(t->visitingHero) | ||||
| 	if(t->visitingHero && t->armedGarrison()) | ||||
| 	{ | ||||
| 		pickBestCreatures (t->visitingHero, t); | ||||
| 	} | ||||
| @@ -909,56 +913,37 @@ void VCAI::moveCreaturesToHero(const CGTownInstance * t) | ||||
|  | ||||
| void VCAI::pickBestCreatures(const CArmedInstance * army, const CArmedInstance * source) | ||||
| { | ||||
| 	if (army->stacksCount() == GameConstants::ARMY_SIZE) //try merging our army first | ||||
| 	{ | ||||
| 		for (int i = 0; i < GameConstants::ARMY_SIZE; ++i) | ||||
| 		{ | ||||
| 			if (const CStackInstance *s = army->getStackPtr(i)) | ||||
| 			{ | ||||
| 				for (int j = 0; j < GameConstants::ARMY_SIZE; ++j) | ||||
| 				{ | ||||
| 					if (i != j && army->mergableStacks(std::pair<TSlot, TSlot>(i, j))) | ||||
| 					{ | ||||
| 						cb->mergeStacks (army, army, j, i); | ||||
| 						break; | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	//TODO - what if source is a hero (the last stack problem) -> it'd good to create a single stack of weakest cre | ||||
| 	const CArmedInstance *armies[] = {army, source}; | ||||
| 	//we calculate total strength for each creature type available in armies | ||||
| 	std::map<const CCreature*, int> creToPower; | ||||
| 	BOOST_FOREACH(auto armyPtr, armies) | ||||
| 		BOOST_FOREACH(auto &i, armyPtr->Slots()) | ||||
| 			creToPower[i.second->type] += i.second->getPower();  | ||||
| 	//TODO - consider more than just power (ie morale penalty, hero specialty in certain stacks, etc) | ||||
|  | ||||
| 	for (int i = 0; i < GameConstants::ARMY_SIZE; ++i) | ||||
| 	std::vector<const CCreature *> bestArmy; //types that'll be in final dst army | ||||
| 	for (int i = 0; i < GameConstants::ARMY_SIZE; i++) //pick the creatures from which we can get most power, as many as dest can fit | ||||
| 	{ | ||||
| 		if(const CStackInstance *s = source->getStackPtr(i)) | ||||
| 		{ | ||||
| 			//find d | ||||
| 			int dstSlot = army->getSlotFor(s->type); | ||||
| 			if(dstSlot >= 0) | ||||
| 		typedef const std::pair<const CCreature*, int> &CrePowerPair; | ||||
| 		auto creIt = boost::max_element(creToPower, [](CrePowerPair lhs, CrePowerPair rhs) | ||||
| 			{ | ||||
| 				if (army->hasStackAtSlot(dstSlot)) | ||||
| 					cb->mergeStacks(source, army, i, dstSlot); | ||||
| 				else  | ||||
| 					cb->swapCreatures(source, army, i, dstSlot); | ||||
| 			} | ||||
| 			else //exchange poorest stack with stronger one | ||||
| 			{ | ||||
| 				TSlot weakestStack = 0; | ||||
| 				for (int j = 1; j < GameConstants::ARMY_SIZE; ++j) | ||||
| 				{ | ||||
| 					const CStackInstance *p = army->getStackPtr(j); | ||||
| 					const CStackInstance *w = army->getStackPtr(weakestStack); | ||||
| 					if (p && w) | ||||
| 					{ | ||||
| 						if (p->getPower() < w->getPower()) | ||||
| 							weakestStack = j; | ||||
| 					} | ||||
| 				} | ||||
| 				if (const CStackInstance *w = army->getStackPtr(weakestStack)) | ||||
| 					if (w->getPower() < s->getPower()) | ||||
| 						cb->swapCreatures(source, army, i, weakestStack); | ||||
| 			} | ||||
| 		} | ||||
| 				return lhs.second < rhs.second; | ||||
| 			}); | ||||
| 		bestArmy.push_back(creIt->first); | ||||
| 		creToPower.erase(creIt); | ||||
| 		if(creToPower.empty()) | ||||
| 			break; | ||||
| 	} | ||||
| 	 | ||||
| 	//foreach best type -> iterate over slots in both armies and if it's the appropriate type, send it to the slot where it belongs | ||||
| 	for (int i = 0; i < bestArmy.size(); i++) //i-th strongest creature type will go to i-th slot | ||||
| 		BOOST_FOREACH(auto armyPtr, armies)  | ||||
| 			for (int j = 0; j < GameConstants::ARMY_SIZE; j++) | ||||
| 				if(armyPtr->getCreature(j) == bestArmy[i]  &&  (i != j || armyPtr != army)) //it's a searched creature not in dst slot | ||||
| 						cb->mergeOrSwapStacks(armyPtr, army, j, i); | ||||
|  | ||||
| 	//TODO - having now strongest possible army, we may want to think about arranging stacks | ||||
| } | ||||
|  | ||||
| void VCAI::recruitCreatures(const CGDwelling * d) | ||||
|   | ||||
| @@ -403,6 +403,14 @@ void CCallback::validatePaths() | ||||
| 	} | ||||
| } | ||||
|  | ||||
| int CCallback::mergeOrSwapStacks(const CArmedInstance *s1, const CArmedInstance *s2, int p1, int p2) | ||||
| { | ||||
| 	if(s1->getCreature(p1) == s2->getCreature(p2)) | ||||
| 		return mergeStacks(s1, s2, p1, p2); | ||||
| 	else | ||||
| 		return swapCreatures(s1, s2, p1, p2); | ||||
| } | ||||
|  | ||||
| CBattleCallback::CBattleCallback(CGameState *GS, int Player, CClient *C ) | ||||
| { | ||||
| 	gs = GS; | ||||
|   | ||||
| @@ -60,6 +60,7 @@ public: | ||||
| 	virtual void selectionMade(int selection, int asker) =0; | ||||
| 	virtual int swapCreatures(const CArmedInstance *s1, const CArmedInstance *s2, int p1, int p2)=0;//swaps creatures between two possibly different garrisons // TODO: AI-unsafe code - fix it! | ||||
| 	virtual int mergeStacks(const CArmedInstance *s1, const CArmedInstance *s2, int p1, int p2)=0;//joins first stack to the second (creatures must be same type) | ||||
| 	virtual int mergeOrSwapStacks(const CArmedInstance *s1, const CArmedInstance *s2, int p1, int p2) =0; //first goes to the second | ||||
| 	virtual int splitStack(const CArmedInstance *s1, const CArmedInstance *s2, int p1, int p2, int val)=0;//split creatures from the first stack | ||||
| 	//virtual bool swapArtifacts(const CGHeroInstance * hero1, ui16 pos1, const CGHeroInstance * hero2, ui16 pos2)=0; //swaps artifacts between two given heroes | ||||
| 	virtual bool swapArtifacts(const IArtifactSetBase * src, ui16 pos1, const IArtifactSetBase * dest, ui16 pos2)=0; | ||||
| @@ -121,6 +122,7 @@ public: | ||||
| 	bool teleportHero(const CGHeroInstance *who, const CGTownInstance *where); | ||||
| 	void selectionMade(int selection, int asker); | ||||
| 	int swapCreatures(const CArmedInstance *s1, const CArmedInstance *s2, int p1, int p2); | ||||
| 	int mergeOrSwapStacks(const CArmedInstance *s1, const CArmedInstance *s2, int p1, int p2); //first goes to the second | ||||
| 	int mergeStacks(const CArmedInstance *s1, const CArmedInstance *s2, int p1, int p2); //first goes to the second | ||||
| 	int splitStack(const CArmedInstance *s1, const CArmedInstance *s2, int p1, int p2, int val); | ||||
| 	bool dismissHero(const CGHeroInstance * hero); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user