Explorar o código

Battle AI: fix casting Implosion when it kills target stack, fix casting summon elementals

Andrii Danylchenko hai 1 ano
pai
achega
ed36b1a882
Modificáronse 1 ficheiros con 29 adicións e 6 borrados
  1. 29 6
      AI/BattleAI/BattleEvaluator.cpp

+ 29 - 6
AI/BattleAI/BattleEvaluator.cpp

@@ -630,7 +630,15 @@ bool BattleEvaluator::attemptCastingSpell(const CStack * activeStack)
 				auto & ps = possibleCasts[i];
 
 #if BATTLE_TRACE_LEVEL >= 1
-				logAi->trace("Evaluating %s", ps.spell->getNameTranslated());
+				if(ps.dest.empty())
+					logAi->trace("Evaluating %s", ps.spell->getNameTranslated());
+				else
+				{
+					auto psFirst = ps.dest.front();
+					auto strWhere = psFirst.unitValue ? psFirst.unitValue->getDescription() : std::to_string(psFirst.hexValue.hex);
+
+					logAi->trace("Evaluating %s at %s", ps.spell->getNameTranslated(), strWhere);
+				}
 #endif
 
 				auto state = std::make_shared<HypotheticBattle>(env.get(), cb->getBattle(battleID));
@@ -667,7 +675,7 @@ bool BattleEvaluator::attemptCastingSpell(const CStack * activeStack)
 
 					innerEvaluator.updateReachabilityMap(state);
 
-					auto moveTarget = scoreEvaluator.findMoveTowardsUnreachable(activeStack, innerTargets, innerCache, state);
+					auto moveTarget = innerEvaluator.findMoveTowardsUnreachable(activeStack, innerTargets, innerCache, state);
 
 					if(!innerTargets.possibleAttacks.empty())
 					{
@@ -682,12 +690,22 @@ bool BattleEvaluator::attemptCastingSpell(const CStack * activeStack)
 				}
 				else
 				{
-					ps.value = scoreEvaluator.evaluateExchange(*cachedAttack.ap, cachedAttack.turn, *targets, innerCache, state);
+					auto updatedAttacker = state->getForUpdate(cachedAttack.ap->attack.attacker->unitId());
+					auto updatedDefender = state->getForUpdate(cachedAttack.ap->attack.defender->unitId());
+					auto updatedBai = BattleAttackInfo(
+						updatedAttacker.get(),
+						updatedDefender.get(),
+						cachedAttack.ap->attack.chargeDistance,
+						cachedAttack.ap->attack.shooting);
+
+					auto updatedAttack = AttackPossibility::evaluate(updatedBai, cachedAttack.ap->from, innerCache, state);
+
+					ps.value = scoreEvaluator.evaluateExchange(updatedAttack, cachedAttack.turn, *targets, innerCache, state);
 				}
 
 				for(const auto & unit : allUnits)
 				{
-					if(!unit->isValidTarget())
+					if(!unit->isValidTarget(true))
 						continue;
 
 					auto newHealth = unit->getAvailableHealth();
@@ -710,13 +728,18 @@ bool BattleEvaluator::attemptCastingSpell(const CStack * activeStack)
 
 						if(ourUnit * goodEffect == 1)
 						{
-							if(ourUnit && goodEffect && (unit->isClone() || unit->isGhost()))
+							auto isMagical = state->getForUpdate(unit->unitId())->summoned
+								|| unit->isClone()
+								|| unit->isGhost();
+
+							if(ourUnit && goodEffect && isMagical)
 								continue;
 
 							ps.value += dpsReduce * scoreEvaluator.getPositiveEffectMultiplier();
 						}
 						else
-							ps.value -= dpsReduce * scoreEvaluator.getNegativeEffectMultiplier();
+							// discourage AI making collateral damage with spells
+							ps.value -= 4 * dpsReduce * scoreEvaluator.getNegativeEffectMultiplier();
 
 #if BATTLE_TRACE_LEVEL >= 1
 						logAi->trace(