1
0
mirror of https://github.com/vcmi/vcmi.git synced 2026-05-22 09:55:17 +02:00

BattleAI: avoid selfblocking on siege

This commit is contained in:
Andrii Danylchenko
2023-04-08 14:05:47 +03:00
parent ae5d273df9
commit 737c34b8c6
6 changed files with 48 additions and 12 deletions
+35 -10
View File
@@ -89,6 +89,7 @@ void CBattleAI::initBattleInterface(std::shared_ptr<Environment> ENV, std::share
wasUnlockingGs = CB->unlockGsWhenWaiting;
CB->waitTillRealize = true;
CB->unlockGsWhenWaiting = false;
movesSkippedByDefense = 0;
}
BattleAction CBattleAI::activeStack( const CStack * stack )
@@ -181,6 +182,7 @@ BattleAction CBattleAI::activeStack( const CStack * stack )
if(bestSpellcast.is_initialized() && bestSpellcast->value > bestAttack.damageDiff())
{
// return because spellcast value is damage dealt and score is dps reduce
movesSkippedByDefense = 0;
return BattleAction::makeCreatureSpellcast(stack, bestSpellcast->dest, bestSpellcast->spell->id);
}
@@ -196,14 +198,15 @@ BattleAction CBattleAI::activeStack( const CStack * stack )
}
else if(bestAttack.attack.shooting)
{
result = BattleAction::makeShotAttack(stack, bestAttack.attack.defender);
action = "shot";
movesSkippedByDefense = 0;
}
else
{
result = BattleAction::makeMeleeAttack(stack, bestAttack.attack.defender->getPosition(), bestAttack.from);
action = "melee";
movesSkippedByDefense = 0;
}
logAi->debug("BattleAI: %s -> %s x %d, %s, from %d curpos %d dist %d speed %d: +%lld -%lld = %lld",
@@ -217,6 +220,7 @@ BattleAction CBattleAI::activeStack( const CStack * stack )
}
else if(bestSpellcast.is_initialized())
{
movesSkippedByDefense = 0;
return BattleAction::makeCreatureSpellcast(stack, bestSpellcast->dest, bestSpellcast->spell->id);
}
@@ -235,12 +239,8 @@ BattleAction CBattleAI::activeStack( const CStack * stack )
}
}
if(score > EvaluationResult::INEFFECTIVE_SCORE)
{
return result;
}
if(!stack->hasBonusOfType(Bonus::FLYING)
if(score <= EvaluationResult::INEFFECTIVE_SCORE
&& !stack->hasBonusOfType(Bonus::FLYING)
&& stack->unitSide() == BattleSide::ATTACKER
&& cb->battleGetSiegeLevel() >= CGTownInstance::CITADEL)
{
@@ -248,10 +248,12 @@ BattleAction CBattleAI::activeStack( const CStack * stack )
if(brokenWallMoat.size())
{
movesSkippedByDefense = 0;
if(stack->doubleWide() && vstd::contains(brokenWallMoat, stack->getPosition()))
return BattleAction::makeMove(stack, stack->getPosition().cloneInDirection(BattleHex::RIGHT));
result = BattleAction::makeMove(stack, stack->getPosition().cloneInDirection(BattleHex::RIGHT));
else
return goTowardsNearest(stack, brokenWallMoat);
result = goTowardsNearest(stack, brokenWallMoat);
}
}
}
@@ -264,6 +266,15 @@ BattleAction CBattleAI::activeStack( const CStack * stack )
logAi->error("Exception occurred in %s %s",__FUNCTION__, e.what());
}
if(result.actionType == EActionType::DEFEND)
{
movesSkippedByDefense++;
}
else if(result.actionType != EActionType::WAIT)
{
movesSkippedByDefense = 0;
}
return result;
}
@@ -285,7 +296,9 @@ BattleAction CBattleAI::goTowardsNearest(const CStack * stack, std::vector<Battl
for(auto hex : hexes)
{
if(vstd::contains(avHexes, hex))
{
return BattleAction::makeMove(stack, hex);
}
if(stack->coversPos(hex))
{
@@ -396,6 +409,8 @@ BattleAction CBattleAI::useCatapult(const CStack * stack)
attack.side = side;
attack.stackNumber = stack->ID;
movesSkippedByDefense = 0;
return attack;
}
@@ -703,6 +718,7 @@ void CBattleAI::attemptCastingSpell()
spellcast.side = side;
spellcast.stackNumber = (!side) ? -1 : -2;
cb->battleMakeAction(&spellcast);
movesSkippedByDefense = 0;
}
else
{
@@ -796,12 +812,21 @@ boost::optional<BattleAction> CBattleAI::considerFleeingOrSurrendering()
}
}
bs.turnsSkippedByDefense = movesSkippedByDefense / bs.ourStacks.size();
if(!bs.canFlee || !bs.canSurrender)
{
return boost::none;
}
return cb->makeSurrenderRetreatDecision(bs);
auto result = cb->makeSurrenderRetreatDecision(bs);
if(!result && bs.canFlee && bs.turnsSkippedByDefense > 30)
{
return BattleAction::makeRetreat(bs.ourSide);
}
return result;
}