mirror of
https://github.com/vcmi/vcmi.git
synced 2024-12-22 22:13:35 +02:00
BattleAI: fast targets optimization
This commit is contained in:
parent
e7394ad20c
commit
ba9998ac66
@ -507,7 +507,12 @@ void CBattleAI::attemptCastingSpell()
|
|||||||
{
|
{
|
||||||
spells::BattleCast temp(cb.get(), hero, spells::Mode::HERO, spell);
|
spells::BattleCast temp(cb.get(), hero, spells::Mode::HERO, spell);
|
||||||
|
|
||||||
for(auto & target : temp.findPotentialTargets())
|
if(!spell->isDamage() && spell->getTargetType() == spells::AimType::LOCATION)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
const bool FAST = true;
|
||||||
|
|
||||||
|
for(auto & target : temp.findPotentialTargets(FAST))
|
||||||
{
|
{
|
||||||
PossibleSpellcast ps;
|
PossibleSpellcast ps;
|
||||||
ps.dest = target;
|
ps.dest = target;
|
||||||
|
@ -600,6 +600,8 @@ void BattleExchangeEvaluator::updateReachabilityMap(HypotheticBattle & hb)
|
|||||||
if(unit->isTurret())
|
if(unit->isTurret())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
auto unitSpeed = unit->speed(turn);
|
||||||
|
|
||||||
if(turnBattle.battleCanShoot(unit))
|
if(turnBattle.battleCanShoot(unit))
|
||||||
{
|
{
|
||||||
for(BattleHex hex = BattleHex::TOP_LEFT; hex.isValid(); hex = hex + 1)
|
for(BattleHex hex = BattleHex::TOP_LEFT; hex.isValid(); hex = hex + 1)
|
||||||
@ -614,7 +616,7 @@ void BattleExchangeEvaluator::updateReachabilityMap(HypotheticBattle & hb)
|
|||||||
|
|
||||||
for(BattleHex hex = BattleHex::TOP_LEFT; hex.isValid(); hex = hex + 1)
|
for(BattleHex hex = BattleHex::TOP_LEFT; hex.isValid(); hex = hex + 1)
|
||||||
{
|
{
|
||||||
bool reachable = unitReachability.distances[hex] <= unit->speed(turn);
|
bool reachable = unitReachability.distances[hex] <= unitSpeed;
|
||||||
|
|
||||||
if(!reachable && unitReachability.accessibility[hex] == EAccessibility::ALIVE_STACK)
|
if(!reachable && unitReachability.accessibility[hex] == EAccessibility::ALIVE_STACK)
|
||||||
{
|
{
|
||||||
@ -624,7 +626,7 @@ void BattleExchangeEvaluator::updateReachabilityMap(HypotheticBattle & hb)
|
|||||||
{
|
{
|
||||||
for(BattleHex neighbor : hex.neighbouringTiles())
|
for(BattleHex neighbor : hex.neighbouringTiles())
|
||||||
{
|
{
|
||||||
reachable = unitReachability.distances[neighbor] <= unit->speed(turn);
|
reachable = unitReachability.distances[neighbor] <= unitSpeed;
|
||||||
|
|
||||||
if(reachable) break;
|
if(reachable) break;
|
||||||
}
|
}
|
||||||
|
@ -84,17 +84,6 @@ PotentialTargets::PotentialTargets(const battle::Unit * attacker, const Hypothet
|
|||||||
{
|
{
|
||||||
return lhs.damageDiff() > rhs.damageDiff();
|
return lhs.damageDiff() > rhs.damageDiff();
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!possibleAttacks.empty())
|
|
||||||
{
|
|
||||||
auto & bestAp = possibleAttacks[0];
|
|
||||||
|
|
||||||
logGlobal->debug("Battle AI best: %s -> %s at %d from %d, affects %d units: d:%lld a:%lld c:%lld s:%lld",
|
|
||||||
bestAp.attack.attacker->unitType()->getJsonKey(),
|
|
||||||
state.battleGetUnitByPos(bestAp.dest)->unitType()->getJsonKey(),
|
|
||||||
(int)bestAp.dest, (int)bestAp.from, (int)bestAp.affectedUnits.size(),
|
|
||||||
bestAp.defenderDamageReduce, bestAp.attackerDamageReduce, bestAp.collateralDamageReduce, bestAp.shootersBlockedDmg);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t PotentialTargets::bestActionValue() const
|
int64_t PotentialTargets::bestActionValue() const
|
||||||
|
@ -590,7 +590,7 @@ std::vector<AimType> BattleSpellMechanics::getTargetTypes() const
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<Destination> BattleSpellMechanics::getPossibleDestinations(size_t index, AimType aimType, const Target & current) const
|
std::vector<Destination> BattleSpellMechanics::getPossibleDestinations(size_t index, AimType aimType, const Target & current, bool fast) const
|
||||||
{
|
{
|
||||||
//TODO: BattleSpellMechanics::getPossibleDestinations
|
//TODO: BattleSpellMechanics::getPossibleDestinations
|
||||||
|
|
||||||
@ -602,7 +602,53 @@ std::vector<Destination> BattleSpellMechanics::getPossibleDestinations(size_t in
|
|||||||
switch(aimType)
|
switch(aimType)
|
||||||
{
|
{
|
||||||
case AimType::CREATURE:
|
case AimType::CREATURE:
|
||||||
|
{
|
||||||
|
auto stacks = battle()->battleGetAllStacks();
|
||||||
|
|
||||||
|
for(auto stack : stacks)
|
||||||
|
{
|
||||||
|
Target tmp = current;
|
||||||
|
tmp.emplace_back(stack->getPosition());
|
||||||
|
|
||||||
|
detail::ProblemImpl ignored;
|
||||||
|
|
||||||
|
if(canBeCastAt(tmp, ignored))
|
||||||
|
ret.emplace_back(stack->getPosition());
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case AimType::LOCATION:
|
case AimType::LOCATION:
|
||||||
|
if(fast)
|
||||||
|
{
|
||||||
|
auto stacks = battle()->battleGetAllStacks();
|
||||||
|
std::set<BattleHex> hexesToCheck;
|
||||||
|
|
||||||
|
for(auto stack : stacks)
|
||||||
|
{
|
||||||
|
hexesToCheck.insert(stack->getPosition());
|
||||||
|
|
||||||
|
for(auto adjacent : stack->getPosition().neighbouringTiles())
|
||||||
|
hexesToCheck.insert(adjacent);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(auto hex : hexesToCheck)
|
||||||
|
{
|
||||||
|
if(hex.isAvailable())
|
||||||
|
{
|
||||||
|
Target tmp = current;
|
||||||
|
tmp.emplace_back(hex);
|
||||||
|
|
||||||
|
detail::ProblemImpl ignored;
|
||||||
|
|
||||||
|
if(canBeCastAt(tmp, ignored))
|
||||||
|
ret.emplace_back(hex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
for(int i = 0; i < GameConstants::BFIELD_SIZE; i++)
|
for(int i = 0; i < GameConstants::BFIELD_SIZE; i++)
|
||||||
{
|
{
|
||||||
BattleHex dest(i);
|
BattleHex dest(i);
|
||||||
@ -617,6 +663,7 @@ std::vector<Destination> BattleSpellMechanics::getPossibleDestinations(size_t in
|
|||||||
ret.emplace_back(dest);
|
ret.emplace_back(dest);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case AimType::NO_TARGET:
|
case AimType::NO_TARGET:
|
||||||
ret.emplace_back();
|
ret.emplace_back();
|
||||||
|
@ -50,7 +50,7 @@ public:
|
|||||||
/// Returns vector of all possible destinations for specified aim type
|
/// Returns vector of all possible destinations for specified aim type
|
||||||
/// index - ???
|
/// index - ???
|
||||||
/// current - ???
|
/// current - ???
|
||||||
std::vector<Destination> getPossibleDestinations(size_t index, AimType aimType, const Target & current) const override final;
|
std::vector<Destination> getPossibleDestinations(size_t index, AimType aimType, const Target & current, bool fast) const override final;
|
||||||
|
|
||||||
/// Returns true if spell can be cast on unit
|
/// Returns true if spell can be cast on unit
|
||||||
bool isReceptive(const battle::Unit * target) const override;
|
bool isReceptive(const battle::Unit * target) const override;
|
||||||
|
@ -326,7 +326,7 @@ bool BattleCast::castIfPossible(ServerCallback * server, Target target)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<Target> BattleCast::findPotentialTargets() const
|
std::vector<Target> BattleCast::findPotentialTargets(bool fast) const
|
||||||
{
|
{
|
||||||
//TODO: for more than 2 destinations per target much more efficient algorithm is required
|
//TODO: for more than 2 destinations per target much more efficient algorithm is required
|
||||||
|
|
||||||
@ -354,7 +354,7 @@ std::vector<Target> BattleCast::findPotentialTargets() const
|
|||||||
if(previous.empty())
|
if(previous.empty())
|
||||||
{
|
{
|
||||||
Target empty;
|
Target empty;
|
||||||
destinations = m->getPossibleDestinations(index, targetTypes.at(index), empty);
|
destinations = m->getPossibleDestinations(index, targetTypes.at(index), empty, fast);
|
||||||
|
|
||||||
for(auto & destination : destinations)
|
for(auto & destination : destinations)
|
||||||
{
|
{
|
||||||
@ -367,7 +367,7 @@ std::vector<Target> BattleCast::findPotentialTargets() const
|
|||||||
{
|
{
|
||||||
for(const Target & current : previous)
|
for(const Target & current : previous)
|
||||||
{
|
{
|
||||||
destinations = m->getPossibleDestinations(index, targetTypes.at(index), current);
|
destinations = m->getPossibleDestinations(index, targetTypes.at(index), current, fast);
|
||||||
|
|
||||||
for(auto & destination : destinations)
|
for(auto & destination : destinations)
|
||||||
{
|
{
|
||||||
|
@ -139,7 +139,7 @@ public:
|
|||||||
///cast with silent check for permitted cast
|
///cast with silent check for permitted cast
|
||||||
bool castIfPossible(ServerCallback * server, Target target);
|
bool castIfPossible(ServerCallback * server, Target target);
|
||||||
|
|
||||||
std::vector<Target> findPotentialTargets() const;
|
std::vector<Target> findPotentialTargets(bool fast = false) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
///spell school level
|
///spell school level
|
||||||
@ -199,7 +199,7 @@ public:
|
|||||||
|
|
||||||
virtual std::vector<AimType> getTargetTypes() const = 0;
|
virtual std::vector<AimType> getTargetTypes() const = 0;
|
||||||
|
|
||||||
virtual std::vector<Destination> getPossibleDestinations(size_t index, AimType aimType, const Target & current) const = 0;
|
virtual std::vector<Destination> getPossibleDestinations(size_t index, AimType aimType, const Target & current, bool fast = false) const = 0;
|
||||||
|
|
||||||
virtual const Spell * getSpell() const = 0;
|
virtual const Spell * getSpell() const = 0;
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@ public:
|
|||||||
|
|
||||||
MOCK_CONST_METHOD1(isReceptive, bool(const battle::Unit * ));
|
MOCK_CONST_METHOD1(isReceptive, bool(const battle::Unit * ));
|
||||||
MOCK_CONST_METHOD0(getTargetTypes, std::vector<AimType>());
|
MOCK_CONST_METHOD0(getTargetTypes, std::vector<AimType>());
|
||||||
MOCK_CONST_METHOD3(getPossibleDestinations, std::vector<Destination>(size_t, AimType, const Target &));
|
MOCK_CONST_METHOD4(getPossibleDestinations, std::vector<Destination>(size_t, AimType, const Target &, bool));
|
||||||
|
|
||||||
MOCK_CONST_METHOD0(getSpell, const Spell *());
|
MOCK_CONST_METHOD0(getSpell, const Spell *());
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user