Browse Source

BattleAI refactoring

Andrii Danylchenko 1 year ago
parent
commit
26609d7a4f
2 changed files with 54 additions and 54 deletions
  1. 53 54
      AI/BattleAI/BattleEvaluator.cpp
  2. 1 0
      AI/BattleAI/BattleEvaluator.h

+ 53 - 54
AI/BattleAI/BattleEvaluator.cpp

@@ -249,6 +249,31 @@ uint64_t timeElapsed(std::chrono::time_point<std::chrono::high_resolution_clock>
 	return std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
 	return std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
 }
 }
 
 
+BattleAction BattleEvaluator::moveOrAttack(const CStack * stack, BattleHex hex, const PotentialTargets & targets)
+{
+	auto additionalScore = 0;
+	std::optional<AttackPossibility> attackOnTheWay;
+
+	for(auto & target : targets.possibleAttacks)
+	{
+		if(!target.attack.shooting && target.from == hex && target.attackValue() > additionalScore)
+		{
+			additionalScore = target.attackValue();
+			attackOnTheWay = target;
+		}
+	}
+
+	if(attackOnTheWay)
+	{
+		activeActionMade = true;
+		return BattleAction::makeMeleeAttack(stack, attackOnTheWay->attack.defender->getPosition(), attackOnTheWay->from);
+	}
+	else
+	{
+		return BattleAction::makeMove(stack, hex);
+	}
+}
+
 BattleAction BattleEvaluator::goTowardsNearest(const CStack * stack, std::vector<BattleHex> hexes, const PotentialTargets & targets)
 BattleAction BattleEvaluator::goTowardsNearest(const CStack * stack, std::vector<BattleHex> hexes, const PotentialTargets & targets)
 {
 {
 	auto reachability = cb->getBattle(battleID)->getReachability(stack);
 	auto reachability = cb->getBattle(battleID)->getReachability(stack);
@@ -261,69 +286,38 @@ BattleAction BattleEvaluator::goTowardsNearest(const CStack * stack, std::vector
 
 
 	std::vector<BattleHex> targetHexes = hexes;
 	std::vector<BattleHex> targetHexes = hexes;
 
 
-	for(int i = 0; i < 5; i++)
-	{
-		std::sort(targetHexes.begin(), targetHexes.end(), [&](BattleHex h1, BattleHex h2) -> bool
-			{
-				return reachability.distances[h1] < reachability.distances[h2];
-			});
+	vstd::erase_if(targetHexes, [](const BattleHex & hex) { return !hex.isValid(); });
 
 
-		for(auto hex : targetHexes)
+	std::sort(targetHexes.begin(), targetHexes.end(), [&](BattleHex h1, BattleHex h2) -> bool
 		{
 		{
-			if(vstd::contains(avHexes, hex))
-			{
-				auto additionalScore = 0;
-				std::optional<AttackPossibility> attackOnTheWay;
+			return reachability.distances[h1] < reachability.distances[h2];
+		});
 
 
-				for(auto & target : targets.possibleAttacks)
-				{
-					if(!target.attack.shooting && target.from == hex && target.attackValue() > additionalScore)
-					{
-						additionalScore = target.attackValue();
-						attackOnTheWay = target;
-					}
-				}
+	BattleHex bestNeighbor = targetHexes.front();
 
 
-				if(attackOnTheWay)
-				{
-					activeActionMade = true;
-					return BattleAction::makeMeleeAttack(stack, attackOnTheWay->attack.defender->getPosition(), attackOnTheWay->from);
-				}
-				else
-				{
-					return BattleAction::makeMove(stack, hex);
-				}
-			}
+	if(reachability.distances[bestNeighbor] > GameConstants::BFIELD_SIZE)
+	{
+		logAi->trace("No richable hexes.");
+		return BattleAction::makeDefend(stack);
+	}
 
 
-			if(stack->coversPos(hex))
-			{
-				logAi->warn("Warning: already standing on neighbouring tile!");
-				//We shouldn't even be here...
-				return BattleAction::makeDefend(stack);
-			}
+	// this turn
+	for(auto hex : targetHexes)
+	{
+		if(vstd::contains(avHexes, hex))
+		{
+			return moveOrAttack(stack, hex, targets);
 		}
 		}
 
 
-		if(reachability.distances[targetHexes.front()] <= GameConstants::BFIELD_SIZE)
+		if(stack->coversPos(hex))
 		{
 		{
-			break;
+			logAi->warn("Warning: already standing on neighbouring hex!");
+			//We shouldn't even be here...
+			return BattleAction::makeDefend(stack);
 		}
 		}
-
-		std::vector<BattleHex> copy = targetHexes;
-
-		for(auto hex : copy)
-			vstd::concatenate(targetHexes, hex.allNeighbouringTiles());
-
-		vstd::erase_if(targetHexes, [](const BattleHex & hex) {return !hex.isValid();});
-		vstd::removeDuplicates(targetHexes);
-	}
-
-	BattleHex bestNeighbor = targetHexes.front();
-
-	if(reachability.distances[bestNeighbor] > GameConstants::BFIELD_SIZE)
-	{
-		return BattleAction::makeDefend(stack);
 	}
 	}
 
 
+	// not this turn
 	scoreEvaluator.updateReachabilityMap(hb);
 	scoreEvaluator.updateReachabilityMap(hb);
 
 
 	if(stack->hasBonusOfType(BonusType::FLYING))
 	if(stack->hasBonusOfType(BonusType::FLYING))
@@ -363,7 +357,7 @@ BattleAction BattleEvaluator::goTowardsNearest(const CStack * stack, std::vector
 			return scoreEvaluator.checkPositionBlocksOurStacks(*hb, stack, hex) ? BLOCKED_STACK_PENALTY + distance : distance;
 			return scoreEvaluator.checkPositionBlocksOurStacks(*hb, stack, hex) ? BLOCKED_STACK_PENALTY + distance : distance;
 		});
 		});
 
 
-		return BattleAction::makeMove(stack, *nearestAvailableHex);
+		return moveOrAttack(stack, *nearestAvailableHex, targets);
 	}
 	}
 	else
 	else
 	{
 	{
@@ -377,11 +371,16 @@ BattleAction BattleEvaluator::goTowardsNearest(const CStack * stack, std::vector
 
 
 			if(vstd::contains(avHexes, currentDest)
 			if(vstd::contains(avHexes, currentDest)
 				&& !scoreEvaluator.checkPositionBlocksOurStacks(*hb, stack, currentDest))
 				&& !scoreEvaluator.checkPositionBlocksOurStacks(*hb, stack, currentDest))
-				return BattleAction::makeMove(stack, currentDest);
+			{
+				return moveOrAttack(stack, currentDest, targets);
+			}
 
 
 			currentDest = reachability.predecessors[currentDest];
 			currentDest = reachability.predecessors[currentDest];
 		}
 		}
 	}
 	}
+	
+	logAi->error("We should either detect that hexes are unreachable or make a move!");
+	return BattleAction::makeDefend(stack);
 }
 }
 
 
 bool BattleEvaluator::canCastSpell()
 bool BattleEvaluator::canCastSpell()

+ 1 - 0
AI/BattleAI/BattleEvaluator.h

@@ -47,6 +47,7 @@ public:
 	std::vector<BattleHex> getBrokenWallMoatHexes() const;
 	std::vector<BattleHex> getBrokenWallMoatHexes() const;
 	void evaluateCreatureSpellcast(const CStack * stack, PossibleSpellcast & ps); //for offensive damaging spells only
 	void evaluateCreatureSpellcast(const CStack * stack, PossibleSpellcast & ps); //for offensive damaging spells only
 	void print(const std::string & text) const;
 	void print(const std::string & text) const;
+	BattleAction moveOrAttack(const CStack * stack, BattleHex hex, const PotentialTargets & targets);
 
 
 	BattleEvaluator(
 	BattleEvaluator(
 		std::shared_ptr<Environment> env,
 		std::shared_ptr<Environment> env,