mirror of
				https://github.com/vcmi/vcmi.git
				synced 2025-10-31 00:07:39 +02:00 
			
		
		
		
	Fixed at least one of the #1428 infinite turns cases.
This commit is contained in:
		| @@ -1228,9 +1228,7 @@ void VCAI::recruitCreatures(const CGDwelling * d) | ||||
| // 		if(containsSavedRes(c->cost)) | ||||
| // 			continue; | ||||
|  | ||||
| 		TResources myRes = cb->getResourceAmount(); | ||||
| 		myRes[Res::GOLD] -= GOLD_RESERVE; | ||||
| 		amin(count, myRes / VLC->creh->creatures[creID]->cost); | ||||
| 		amin(count, freeResources() / VLC->creh->creatures[creID]->cost); | ||||
| 		if(count > 0) | ||||
| 			cb->recruitCreatures(d, creID, count, i); | ||||
| 	} | ||||
| @@ -1900,6 +1898,11 @@ void VCAI::tryRealize(CGoal g) | ||||
| 			//cb->recalculatePaths(); | ||||
| 			if(!g.hero->movement) | ||||
| 				throw cannotFulfillGoalException("Cannot visit tile: hero is out of MPs!"); | ||||
| 			if(g.tile == g.hero->visitablePos()  &&  cb->getVisitableObjs(g.hero->visitablePos()).size() < 2) | ||||
| 			{ | ||||
| 				logAi->warnStream() << boost::format("Why do I want to move hero %s to tile %s? Already standing on that tile! ") % g.hero->name % g.tile; | ||||
| 				throw goalFulfilledException (g); | ||||
| 			} | ||||
| 			//if(!g.isBlockedBorderGate(g.tile)) | ||||
| 			//{ | ||||
| 				if (ai->moveHeroToTile(g.tile, g.hero.get())) | ||||
| @@ -2614,6 +2617,14 @@ void VCAI::validateObject(ObjectIdRef obj) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| TResources VCAI::freeResources() const | ||||
| { | ||||
| 	TResources myRes = cb->getResourceAmount(); | ||||
| 	myRes[Res::GOLD] -= GOLD_RESERVE; | ||||
| 	vstd::amax(myRes[Res::GOLD], 0); | ||||
| 	return myRes; | ||||
| } | ||||
|  | ||||
| AIStatus::AIStatus() | ||||
| { | ||||
| 	battle = NO_BATTLE; | ||||
| @@ -3264,7 +3275,7 @@ TSubgoal CGoal::whatToDoToAchieve() | ||||
| 					{ | ||||
| 						for (auto type : creature.second) | ||||
| 						{ | ||||
| 							if (type == objid) | ||||
| 							if (type == objid  &&  ai->freeResources().canAfford(VLC->creh->creatures[type]->cost)) | ||||
| 								dwellings.push_back(d); | ||||
| 						} | ||||
| 					} | ||||
| @@ -3273,7 +3284,7 @@ TSubgoal CGoal::whatToDoToAchieve() | ||||
| 			if (dwellings.size()) | ||||
| 			{ | ||||
| 				boost::sort(dwellings, isCloser); | ||||
| 				return CGoal(GET_OBJ).setobjid (dwellings.front()->id.getNum()); //TODO: consider needed resources | ||||
| 				return CGoal(GET_OBJ).setobjid (dwellings.front()->id.getNum()); | ||||
| 			} | ||||
| 			else | ||||
| 				return CGoal(EXPLORE); | ||||
| @@ -3435,9 +3446,12 @@ TSubgoal CGoal::whatToDoToAchieve() | ||||
| 						{ | ||||
| 							if(creLevel.first) | ||||
| 							{ | ||||
| 								auto creature = VLC->creh->creatures[creLevel.second.front()]; | ||||
| 								if(cb->getResourceAmount().canAfford(creature->cost)) | ||||
| 									return false; | ||||
| 								for(auto & creatureID : creLevel.second) | ||||
| 								{ | ||||
| 									auto creature = VLC->creh->creatures[creatureID]; | ||||
| 									if(ai->freeResources().canAfford(creature->cost)) | ||||
| 										return false; | ||||
| 								} | ||||
| 							} | ||||
| 						} | ||||
| 					} | ||||
|   | ||||
| @@ -420,6 +420,7 @@ public: | ||||
|  | ||||
| 	std::vector<HeroPtr> getUnblockedHeroes() const; | ||||
| 	HeroPtr primaryHero() const; | ||||
| 	TResources freeResources() const; //owned resources minus gold reserve | ||||
| 	TResources estimateIncome() const; | ||||
| 	bool containsSavedRes(const TResources &cost) const; | ||||
| 	void checkHeroArmy (HeroPtr h); | ||||
|   | ||||
							
								
								
									
										9
									
								
								Global.h
									
									
									
									
									
								
							
							
						
						
									
										9
									
								
								Global.h
									
									
									
									
									
								
							| @@ -629,6 +629,15 @@ namespace vstd | ||||
| 			return *pos; | ||||
| 	} | ||||
|  | ||||
| 	template <typename Container> | ||||
| 	typename Container::const_reference atOrDefault(const Container &r, size_t index, const typename Container::const_reference &defaultValue) | ||||
| 	{ | ||||
| 		if(isValidIndex(r, index)) | ||||
| 			return r[index]; | ||||
| 		 | ||||
| 		return defaultValue; | ||||
| 	} | ||||
|  | ||||
| 	using boost::math::round; | ||||
| } | ||||
| using vstd::operator-=; | ||||
|   | ||||
| @@ -1431,7 +1431,10 @@ void CBattleInterface::spellCast( const BattleSpellCast * sc ) | ||||
| 					break; | ||||
| 				default: | ||||
| 					text = CGI->generaltexth->allTexts[565]; //The %s casts %s | ||||
| 					boost::algorithm::replace_first(text, "%s", CGI->creh->creatures[sc->attackerType]->namePl); //casting stack | ||||
| 					if(auto castingCreature = vstd::atOrDefault(CGI->creh->creatures, sc->attackerType, nullptr)) | ||||
| 						boost::algorithm::replace_first(text, "%s", castingCreature->namePl); //casting stack | ||||
| 					else | ||||
| 						boost::algorithm::replace_first(text, "%s", "@Unknown caster@"); //should not happen | ||||
| 			} | ||||
| 			if (plural) | ||||
| 			{ | ||||
| @@ -1459,9 +1462,9 @@ void CBattleInterface::spellCast( const BattleSpellCast * sc ) | ||||
| 		{ | ||||
| 			boost::algorithm::replace_first(text, "%s", curInt->cb->battleGetHeroInfo(sc->side).name); | ||||
| 		} | ||||
| 		else if(sc->attackerType < CGI->creh->creatures.size()) | ||||
| 		if(auto castingCreature = vstd::atOrDefault(CGI->creh->creatures, sc->attackerType, nullptr)) | ||||
| 		{ | ||||
| 			boost::algorithm::replace_first(text, "%s", CGI->creh->creatures[sc->attackerType]->namePl); //creature caster | ||||
| 			boost::algorithm::replace_first(text, "%s", castingCreature->namePl); //creature caster | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
|   | ||||
| @@ -23,6 +23,10 @@ public: | ||||
| 	ConstTransitivePtr(T *Ptr = nullptr) | ||||
| 		: ptr(Ptr)  | ||||
| 	{} | ||||
| 	ConstTransitivePtr(std::nullptr_t) | ||||
| 		: ptr(nullptr)  | ||||
| 	{} | ||||
|  | ||||
|  | ||||
| 	const T& operator*() const | ||||
| 	{ | ||||
|   | ||||
		Reference in New Issue
	
	Block a user