Browse Source

Formatting

Victor Luchits 5 years ago
parent
commit
59c39527c5
3 changed files with 191 additions and 187 deletions
  1. 185 183
      AI/BattleAI/AttackPossibility.cpp
  2. 4 3
      AI/BattleAI/BattleAI.cpp
  3. 2 1
      AI/BattleAI/PotentialTargets.cpp

+ 185 - 183
AI/BattleAI/AttackPossibility.cpp

@@ -1,188 +1,190 @@
-/*
- * AttackPossibility.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 "AttackPossibility.h"
-#include "../../lib/CStack.h"//todo: remove
-
-AttackPossibility::AttackPossibility(BattleHex from, BattleHex dest, const BattleAttackInfo & attack)
-	: from(from), dest(dest), attack(attack)
-{
-}
-
-int64_t AttackPossibility::damageDiff() const
-{
-	return damageDealt - damageReceived - collateralDamage + shootersBlockedDmg;
-}
-
-int64_t AttackPossibility::attackValue() const
-{
-	return damageDiff();
-}
-
-int64_t AttackPossibility::evaluateBlockedShootersDmg(const BattleAttackInfo & attackInfo, BattleHex hex, const HypotheticBattle * state)
-{
-	int64_t res = 0;
-
-	if(attackInfo.shooting)
-		return 0;
-
-	auto attacker = attackInfo.attacker;
-	auto hexes = attacker->getSurroundingHexes(hex);
-	for(BattleHex tile : hexes)
-	{
-		auto st = state->battleGetUnitByPos(tile, true);
-		if(!st || !state->battleMatchOwner(st, attacker))
-			continue;
-		if(!state->battleCanShoot(st))
-			continue;
-
-		BattleAttackInfo rangeAttackInfo(st, attacker, true);
-		rangeAttackInfo.defenderPos = hex;
-
-		BattleAttackInfo meleeAttackInfo(st, attacker, false);
-		meleeAttackInfo.defenderPos = hex;
-
-		auto rangeDmg = getCbc()->battleEstimateDamage(rangeAttackInfo);
-		auto meleeDmg = getCbc()->battleEstimateDamage(meleeAttackInfo);
-
-		int64_t gain = (rangeDmg.first + rangeDmg.second - meleeDmg.first - meleeDmg.second) / 2 + 1;
-		res += gain;
-	}
-
-	return res;
-}
-
-AttackPossibility AttackPossibility::evaluate(const BattleAttackInfo & attackInfo, BattleHex hex, const HypotheticBattle * state)
-{
-	auto attacker = attackInfo.attacker;
-	auto defender = attackInfo.defender;
-	const std::string cachingStringBlocksRetaliation = "type_BLOCKS_RETALIATION";
-	static const auto selectorBlocksRetaliation = Selector::type(Bonus::BLOCKS_RETALIATION);
-	const bool counterAttacksBlocked = attacker->hasBonus(selectorBlocksRetaliation, cachingStringBlocksRetaliation);
+/*
+ * AttackPossibility.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 "AttackPossibility.h"
+#include "../../lib/CStack.h"//todo: remove
+
+AttackPossibility::AttackPossibility(BattleHex from, BattleHex dest, const BattleAttackInfo & attack)
+	: from(from), dest(dest), attack(attack)
+{
+}
+
+int64_t AttackPossibility::damageDiff() const
+{
+	return damageDealt - damageReceived - collateralDamage + shootersBlockedDmg;
+}
+
+int64_t AttackPossibility::attackValue() const
+{
+	return damageDiff();
+}
+
+int64_t AttackPossibility::evaluateBlockedShootersDmg(const BattleAttackInfo & attackInfo, BattleHex hex, const HypotheticBattle * state)
+{
+	int64_t res = 0;
+
+	if(attackInfo.shooting)
+		return 0;
+
+	auto attacker = attackInfo.attacker;
+	auto hexes = attacker->getSurroundingHexes(hex);
+	for(BattleHex tile : hexes)
+	{
+		auto st = state->battleGetUnitByPos(tile, true);
+		if(!st || !state->battleMatchOwner(st, attacker))
+			continue;
+		if(!state->battleCanShoot(st))
+			continue;
+
+		BattleAttackInfo rangeAttackInfo(st, attacker, true);
+		rangeAttackInfo.defenderPos = hex;
+
+		BattleAttackInfo meleeAttackInfo(st, attacker, false);
+		meleeAttackInfo.defenderPos = hex;
+
+		auto rangeDmg = getCbc()->battleEstimateDamage(rangeAttackInfo);
+		auto meleeDmg = getCbc()->battleEstimateDamage(meleeAttackInfo);
+
+		int64_t gain = (rangeDmg.first + rangeDmg.second - meleeDmg.first - meleeDmg.second) / 2 + 1;
+		res += gain;
+	}
+
+	return res;
+}
+
+AttackPossibility AttackPossibility::evaluate(const BattleAttackInfo & attackInfo, BattleHex hex, const HypotheticBattle * state)
+{
+	auto attacker = attackInfo.attacker;
+	auto defender = attackInfo.defender;
+	const std::string cachingStringBlocksRetaliation = "type_BLOCKS_RETALIATION";
+	static const auto selectorBlocksRetaliation = Selector::type(Bonus::BLOCKS_RETALIATION);
+	const bool counterAttacksBlocked = attacker->hasBonus(selectorBlocksRetaliation, cachingStringBlocksRetaliation);
 	const bool mindControlled = [&](const battle::Unit *attacker) -> bool
 	{
-		auto actualSide = getCbc()->playerToSide(getCbc()->battleGetOwner(attacker));
-		if (actualSide && actualSide.get() != attacker->unitSide())
+		auto actualSide = getCbc()->playerToSide(getCbc()->battleGetOwner(attacker));
+		if (actualSide && actualSide.get() != attacker->unitSide())
 			return true;
 		return false;
 	} (attacker);
-
-	AttackPossibility bestAp(hex, BattleHex::INVALID, attackInfo);
-
-	std::vector<BattleHex> defenderHex;
-	if(attackInfo.shooting) {
-		defenderHex = defender->getHexes();
-	} else {
-		defenderHex = CStack::meleeAttackHexes(attacker, defender, hex);
-	}
-
-	for(BattleHex defHex : defenderHex) {
-		if(defHex == hex) {
-			// should be impossible but check anyway
-			continue;
-		}
-
-		AttackPossibility ap(hex, defHex, attackInfo);
-		ap.attackerState = attacker->acquireState();
-		ap.shootersBlockedDmg = bestAp.shootersBlockedDmg;
-
-		const int totalAttacks = ap.attackerState->getTotalAttacks(attackInfo.shooting);
-
-		if (!attackInfo.shooting)
-			ap.attackerState->setPosition(hex);
-
-		std::vector<const battle::Unit*> units;
-
-		if (attackInfo.shooting)
-			units = state->getAttackedBattleUnits(attacker, defHex, true, BattleHex::INVALID);
-		else
-			units = state->getAttackedBattleUnits(attacker, defHex, false, hex);
-
-		// ensure the defender is also affected
-		bool addDefender = true;
-		for(auto unit : units) {
-			if (unit->unitId() == defender->unitId()) {
-				addDefender = false;
-				break;
-			}
-		}
-		if(addDefender) {
-			units.push_back(defender);
-		}
-
-		for(auto u : units) {
-			if(!ap.attackerState->alive()) {
-				break;
-			}
-
-			assert(u->unitId() != attacker->unitId());
-
-			auto defenderState = u->acquireState();
-			ap.affectedUnits.push_back(defenderState);
-
-			for(int i = 0; i < totalAttacks; i++) {
-				si64 damageDealt, damageReceived;
-
-				TDmgRange retaliation(0, 0);
-				auto attackDmg = getCbc()->battleEstimateDamage(ap.attack, &retaliation);
-
-				vstd::amin(attackDmg.first, defenderState->getAvailableHealth());
-				vstd::amin(attackDmg.second, defenderState->getAvailableHealth());
-
-				vstd::amin(retaliation.first, ap.attackerState->getAvailableHealth());
-				vstd::amin(retaliation.second, ap.attackerState->getAvailableHealth());
-
-				damageDealt = (attackDmg.first + attackDmg.second) / 2;
-				ap.attackerState->afterAttack(attackInfo.shooting, false);
-
-				//FIXME: use ranged retaliation
-				damageReceived = 0;
-				if (!attackInfo.shooting && defenderState->ableToRetaliate() && !counterAttacksBlocked)
-				{
-					damageReceived = (retaliation.first + retaliation.second) / 2;
-					defenderState->afterAttack(attackInfo.shooting, true);
-				}
-
-				bool isEnemy = state->battleMatchOwner(attacker, u) && !mindControlled;
-				if(isEnemy)
-					ap.damageDealt += damageDealt;
-				else // friendly fire
-					ap.collateralDamage += damageDealt;
-
-				if(u->unitId() == defender->unitId() || 
-					(!attackInfo.shooting && CStack::isMeleeAttackPossible(u, attacker, hex))) { //FIXME: handle RANGED_RETALIATION ?
-					ap.damageReceived += damageReceived;
-				}
-
-				ap.attackerState->damage(damageReceived);
-				defenderState->damage(damageDealt);
-
-				if (!ap.attackerState->alive() || !defenderState->alive())
-					break;
-			}
-		}
-
-		if(!bestAp.dest.isValid() || ap.attackValue() > bestAp.attackValue()) {
-			bestAp = ap;
-		}
-	}
-
-	// check how much damage we gain from blocking enemy shooters on this hex
-	bestAp.shootersBlockedDmg = evaluateBlockedShootersDmg(attackInfo, hex, state);
-
-	logAi->debug("BattleAI best AP: %s -> %s at %d from %d, affects %d units: %d %d %d %s",
-		VLC->creh->creatures.at(attackInfo.attacker->acquireState()->creatureId())->identifier.c_str(),
-		VLC->creh->creatures.at(attackInfo.defender->acquireState()->creatureId())->identifier.c_str(),
-		(int)bestAp.dest, (int)bestAp.from, (int)bestAp.affectedUnits.size(),
-		(int)bestAp.damageDealt, (int)bestAp.damageReceived, (int)bestAp.collateralDamage, (int)bestAp.shootersBlockedDmg);
-
-	//TODO other damage related to attack (eg. fire shield and other abilities)
-	return bestAp;
-}
+
+	AttackPossibility bestAp(hex, BattleHex::INVALID, attackInfo);
+
+	std::vector<BattleHex> defenderHex;
+	if(attackInfo.shooting)
+		defenderHex = defender->getHexes();
+	else
+		defenderHex = CStack::meleeAttackHexes(attacker, defender, hex);
+
+	for(BattleHex defHex : defenderHex)
+	{
+		if(defHex == hex) {
+			// should be impossible but check anyway
+			continue;
+		}
+
+		AttackPossibility ap(hex, defHex, attackInfo);
+		ap.attackerState = attacker->acquireState();
+		ap.shootersBlockedDmg = bestAp.shootersBlockedDmg;
+
+		const int totalAttacks = ap.attackerState->getTotalAttacks(attackInfo.shooting);
+
+		if (!attackInfo.shooting)
+			ap.attackerState->setPosition(hex);
+
+		std::vector<const battle::Unit*> units;
+
+		if (attackInfo.shooting)
+			units = state->getAttackedBattleUnits(attacker, defHex, true, BattleHex::INVALID);
+		else
+			units = state->getAttackedBattleUnits(attacker, defHex, false, hex);
+
+		// ensure the defender is also affected
+		bool addDefender = true;
+		for(auto unit : units) {
+			if (unit->unitId() == defender->unitId()) {
+				addDefender = false;
+				break;
+			}
+		}
+		if(addDefender) {
+			units.push_back(defender);
+		}
+
+		for(auto u : units) {
+			if(!ap.attackerState->alive()) {
+				break;
+			}
+
+			assert(u->unitId() != attacker->unitId());
+
+			auto defenderState = u->acquireState();
+			ap.affectedUnits.push_back(defenderState);
+
+			for(int i = 0; i < totalAttacks; i++) {
+				si64 damageDealt, damageReceived;
+
+				TDmgRange retaliation(0, 0);
+				auto attackDmg = getCbc()->battleEstimateDamage(ap.attack, &retaliation);
+
+				vstd::amin(attackDmg.first, defenderState->getAvailableHealth());
+				vstd::amin(attackDmg.second, defenderState->getAvailableHealth());
+
+				vstd::amin(retaliation.first, ap.attackerState->getAvailableHealth());
+				vstd::amin(retaliation.second, ap.attackerState->getAvailableHealth());
+
+				damageDealt = (attackDmg.first + attackDmg.second) / 2;
+				ap.attackerState->afterAttack(attackInfo.shooting, false);
+
+				//FIXME: use ranged retaliation
+				damageReceived = 0;
+				if (!attackInfo.shooting && defenderState->ableToRetaliate() && !counterAttacksBlocked)
+				{
+					damageReceived = (retaliation.first + retaliation.second) / 2;
+					defenderState->afterAttack(attackInfo.shooting, true);
+				}
+
+				bool isEnemy = state->battleMatchOwner(attacker, u) && !mindControlled;
+				if(isEnemy)
+					ap.damageDealt += damageDealt;
+				else // friendly fire
+					ap.collateralDamage += damageDealt;
+
+				if(u->unitId() == defender->unitId() || 
+					(!attackInfo.shooting && CStack::isMeleeAttackPossible(u, attacker, hex)))
+				{
+					//FIXME: handle RANGED_RETALIATION ?
+					ap.damageReceived += damageReceived;
+				}
+
+				ap.attackerState->damage(damageReceived);
+				defenderState->damage(damageDealt);
+
+				if (!ap.attackerState->alive() || !defenderState->alive())
+					break;
+			}
+		}
+
+		if(!bestAp.dest.isValid() || ap.attackValue() > bestAp.attackValue()) {
+			bestAp = ap;
+		}
+	}
+
+	// check how much damage we gain from blocking enemy shooters on this hex
+	bestAp.shootersBlockedDmg = evaluateBlockedShootersDmg(attackInfo, hex, state);
+
+	logAi->debug("BattleAI best AP: %s -> %s at %d from %d, affects %d units: %d %d %d %s",
+		VLC->creh->creatures.at(attackInfo.attacker->acquireState()->creatureId())->identifier.c_str(),
+		VLC->creh->creatures.at(attackInfo.defender->acquireState()->creatureId())->identifier.c_str(),
+		(int)bestAp.dest, (int)bestAp.from, (int)bestAp.affectedUnits.size(),
+		(int)bestAp.damageDealt, (int)bestAp.damageReceived, (int)bestAp.collateralDamage, (int)bestAp.shootersBlockedDmg);
+
+	//TODO other damage related to attack (eg. fire shield and other abilities)
+	return bestAp;
+}

+ 4 - 3
AI/BattleAI/BattleAI.cpp

@@ -164,11 +164,12 @@ BattleAction CBattleAI::activeStack( const CStack * stack )
 				return BattleAction::makeCreatureSpellcast(stack, bestSpellcast->dest, bestSpellcast->spell->id);
 			else if(bestAttack.attack.shooting)
 				return BattleAction::makeShotAttack(stack, bestAttack.attack.defender);
-			else {
+			else
+			{
 				auto &target = bestAttack;
 				logAi->debug("BattleAI: %s -> %s %d from, %d curpos %d dist %d speed %d: %d %d %d",
-					VLC->creh->creatures.at(target.attackerState->creatureId())->identifier.c_str(),
-					VLC->creh->creatures.at(target.affectedUnits[0]->creatureId())->identifier.c_str(),
+					VLC->creh->creatures.at(target.attackerState->creatureId())->identifier,
+					VLC->creh->creatures.at(target.affectedUnits[0]->creatureId())->identifier,
 					(int)target.affectedUnits.size(), (int)target.from, (int)bestAttack.attack.attacker->getPosition().hex,
 					(int)bestAttack.attack.chargedFields, (int)bestAttack.attack.attacker->Speed(0, true),
 					(int)target.damageDealt, (int)target.damageReceived, (int)target.attackValue()

+ 2 - 1
AI/BattleAI/PotentialTargets.cpp

@@ -69,7 +69,8 @@ PotentialTargets::PotentialTargets(const battle::Unit * attacker, const Hypothet
 		}
 		else
 		{
-			for(BattleHex hex : avHexes) {
+			for(BattleHex hex : avHexes)
+			{
 				if(!CStack::isMeleeAttackPossible(attackerInfo, defender, hex))
 					continue;