Explorar o código

[BattleAI] Battle magic fixes
* should fix https://bugs.vcmi.eu/view.php?id=2901

AlexVinS %!s(int64=7) %!d(string=hai) anos
pai
achega
386805c4e0
Modificáronse 1 ficheiros con 40 adicións e 18 borrados
  1. 40 18
      AI/BattleAI/BattleAI.cpp

+ 40 - 18
AI/BattleAI/BattleAI.cpp

@@ -359,7 +359,7 @@ void CBattleAI::attemptCastingSpell()
 		if(enemyHadTurnOut)
 			*enemyHadTurnOut = enemyHadTurn;
 
-		return ourTurnSpan > minTurnSpan;
+		return ourTurnSpan >= minTurnSpan;
 	};
 
 	RNGStub rngStub;
@@ -369,12 +369,26 @@ void CBattleAI::attemptCastingSpell()
 
 	TStacks all = cb->battleGetAllStacks(false);
 
+	size_t ourRemainingTurns = 0;
+
 	for(auto unit : all)
 	{
 		healthOfStack[unit->unitId()] = unit->getAvailableHealth();
 		valueOfStack[unit->unitId()] = 0;
+
+		if(cb->battleGetOwner(unit) == playerID && unit->canMove() && !unit->moved())
+			ourRemainingTurns++;
 	}
 
+	LOGFL("I have %d turns left in this round", ourRemainingTurns);
+
+	const bool castNow = ourRemainingTurns <= 1;
+
+	if(castNow)
+		print("I should try to cast a spell now");
+	else
+		print("I could wait better moment to cast a spell");
+
 	auto amount = all.size();
 
 	std::vector<battle::Units> turnOrder;
@@ -401,8 +415,6 @@ void CBattleAI::attemptCastingSpell()
 
 	auto evaluateSpellcast = [&] (PossibleSpellcast * ps)
 	{
-		int64_t totalGain = 0;
-
 		HypotheticBattle state(cb);
 
 		spells::BattleCast cast(&state, hero, spells::Mode::HERO, ps->spell);
@@ -415,10 +427,13 @@ void CBattleAI::attemptCastingSpell()
 
 		for(auto unit : all)
 		{
-			newHealthOfStack[unit->unitId()] = unit->getAvailableHealth();
-			newValueOfStack[unit->unitId()] = 0;
+			auto unitId = unit->unitId();
+			auto localUnit = state.battleGetUnitByID(unitId);
+
+			newHealthOfStack[unitId] = localUnit->getAvailableHealth();
+			newValueOfStack[unitId] = 0;
 
-			if(state.battleGetOwner(unit) == playerID && unit->alive() && unit->willMove())
+			if(state.battleGetOwner(localUnit) == playerID && localUnit->alive() && localUnit->willMove())
 				ourUnits++;
 		}
 
@@ -427,22 +442,32 @@ void CBattleAI::attemptCastingSpell()
 		std::vector<battle::Units> newTurnOrder;
 		state.battleGetTurnOrder(newTurnOrder, amount, 2);
 
-		if(evaluateQueue(newValueOfStack, newTurnOrder, &state, minTurnSpan, nullptr))
+		const bool turnSpanOK = evaluateQueue(newValueOfStack, newTurnOrder, &state, minTurnSpan, nullptr);
+
+		if(turnSpanOK || castNow)
 		{
+			int64_t totalGain = 0;
+
 			for(auto unit : all)
 			{
-				auto newValue = getValOr(newValueOfStack, unit->unitId(), 0);
-				auto oldValue = getValOr(valueOfStack, unit->unitId(), 0);
+				auto unitId = unit->unitId();
+				auto localUnit = state.battleGetUnitByID(unitId);
 
-				auto healthDiff = newHealthOfStack[unit->unitId()] - healthOfStack[unit->unitId()];
+				auto newValue = getValOr(newValueOfStack, unitId, 0);
+				auto oldValue = getValOr(valueOfStack, unitId, 0);
 
-				if(unit->unitOwner() != playerID)
+				auto healthDiff = newHealthOfStack[unitId] - healthOfStack[unitId];
+
+				if(localUnit->unitOwner() != playerID)
 					healthDiff = -healthDiff;
 
-				auto gain = newValue - oldValue + healthDiff;
+				if(healthDiff < 0)
+				{
+					ps->value = -1;
+					return; //do not damage own units at all
+				}
 
-				if(gain != 0)
-					totalGain += gain;
+				totalGain += (newValue - oldValue + healthDiff);
 			}
 
 			ps->value = totalGain;
@@ -456,11 +481,8 @@ void CBattleAI::attemptCastingSpell()
 	std::vector<std::function<void()>> tasks;
 
 	for(PossibleSpellcast & psc : possibleCasts)
-	{
 		tasks.push_back(std::bind(evaluateSpellcast, &psc));
 
-	}
-
 	uint32_t threadCount = boost::thread::hardware_concurrency();
 
 	if(threadCount == 0)
@@ -476,7 +498,7 @@ void CBattleAI::attemptCastingSpell()
 
 	LOGFL("Evaluation took %d ms", timer.getDiff());
 
-	auto pscValue = [] (const PossibleSpellcast &ps) -> int64_t
+	auto pscValue = [](const PossibleSpellcast &ps) -> int64_t
 	{
 		return ps.value;
 	};