mirror of
https://github.com/vcmi/vcmi.git
synced 2024-12-24 22:14:36 +02:00
BattleAI: avoid selfblocking on siege
This commit is contained in:
parent
ae5d273df9
commit
737c34b8c6
@ -212,11 +212,13 @@ AttackPossibility AttackPossibility::evaluate(const BattleAttackInfo & attackInf
|
||||
// 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:%lld a:%lld c:%lld s:%lld",
|
||||
#if BATTLE_TRACE_LEVEL>=1
|
||||
logAi->trace("BattleAI best AP: %s -> %s at %d from %d, affects %d units: d:%lld a:%lld c:%lld s:%lld",
|
||||
attackInfo.attacker->unitType()->getJsonKey(),
|
||||
attackInfo.defender->unitType()->getJsonKey(),
|
||||
(int)bestAp.dest, (int)bestAp.from, (int)bestAp.affectedUnits.size(),
|
||||
bestAp.defenderDamageReduce, bestAp.attackerDamageReduce, bestAp.collateralDamageReduce, bestAp.shootersBlockedDmg);
|
||||
#endif
|
||||
|
||||
//TODO other damage related to attack (eg. fire shield and other abilities)
|
||||
return bestAp;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -60,6 +60,7 @@ class CBattleAI : public CBattleGameInterface
|
||||
|
||||
//Previous setting of cb
|
||||
bool wasWaitingForRealize, wasUnlockingGs;
|
||||
int movesSkippedByDefense;
|
||||
|
||||
public:
|
||||
CBattleAI();
|
||||
|
@ -355,6 +355,13 @@ int64_t BattleExchangeEvaluator::calculateExchange(
|
||||
logAi->trace("Battle exchange at %lld", ap.attack.shooting ? ap.dest : ap.from);
|
||||
#endif
|
||||
|
||||
if(cb->battleGetMySide() == BattlePerspective::LEFT_SIDE
|
||||
&& cb->battleGetGateState() == EGateState::BLOCKED
|
||||
&& ap.attack.defender->coversPos(ESiegeHex::GATE_BRIDGE))
|
||||
{
|
||||
return EvaluationResult::INEFFECTIVE_SCORE;
|
||||
}
|
||||
|
||||
std::vector<const battle::Unit *> ourStacks;
|
||||
std::vector<const battle::Unit *> enemyStacks;
|
||||
|
||||
|
@ -42,7 +42,7 @@ struct EvaluationResult
|
||||
bool defend;
|
||||
|
||||
EvaluationResult(const AttackPossibility & ap)
|
||||
:wait(false), score(0), bestAttack(ap), defend(false)
|
||||
:wait(false), score(INEFFECTIVE_SCORE), bestAttack(ap), defend(false)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
@ -29,6 +29,7 @@ public:
|
||||
std::vector<const battle::Unit *> enemyStacks;
|
||||
const CGHeroInstance * ourHero;
|
||||
const CGHeroInstance * enemyHero;
|
||||
int turnsSkippedByDefense;
|
||||
|
||||
BattleStateInfoForRetreat();
|
||||
uint64_t getOurStrength() const;
|
||||
|
Loading…
Reference in New Issue
Block a user