1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-01-12 02:28:11 +02:00

[BattleAI] Battle magic fixes

* should fix https://bugs.vcmi.eu/view.php?id=2901
This commit is contained in:
AlexVinS 2018-03-01 22:18:01 +03:00
parent e48797f7e8
commit 386805c4e0

View File

@ -359,7 +359,7 @@ void CBattleAI::attemptCastingSpell()
if(enemyHadTurnOut) if(enemyHadTurnOut)
*enemyHadTurnOut = enemyHadTurn; *enemyHadTurnOut = enemyHadTurn;
return ourTurnSpan > minTurnSpan; return ourTurnSpan >= minTurnSpan;
}; };
RNGStub rngStub; RNGStub rngStub;
@ -369,12 +369,26 @@ void CBattleAI::attemptCastingSpell()
TStacks all = cb->battleGetAllStacks(false); TStacks all = cb->battleGetAllStacks(false);
size_t ourRemainingTurns = 0;
for(auto unit : all) for(auto unit : all)
{ {
healthOfStack[unit->unitId()] = unit->getAvailableHealth(); healthOfStack[unit->unitId()] = unit->getAvailableHealth();
valueOfStack[unit->unitId()] = 0; valueOfStack[unit->unitId()] = 0;
if(cb->battleGetOwner(unit) == playerID && unit->canMove() && !unit->moved())
ourRemainingTurns++;
} }
LOGFL("I have %d turns left in this round", ourRemainingTurns);
const bool castNow = ourRemainingTurns <= 1;
if(castNow)
print("I should try to cast a spell now");
else
print("I could wait better moment to cast a spell");
auto amount = all.size(); auto amount = all.size();
std::vector<battle::Units> turnOrder; std::vector<battle::Units> turnOrder;
@ -401,8 +415,6 @@ void CBattleAI::attemptCastingSpell()
auto evaluateSpellcast = [&] (PossibleSpellcast * ps) auto evaluateSpellcast = [&] (PossibleSpellcast * ps)
{ {
int64_t totalGain = 0;
HypotheticBattle state(cb); HypotheticBattle state(cb);
spells::BattleCast cast(&state, hero, spells::Mode::HERO, ps->spell); spells::BattleCast cast(&state, hero, spells::Mode::HERO, ps->spell);
@ -415,10 +427,13 @@ void CBattleAI::attemptCastingSpell()
for(auto unit : all) for(auto unit : all)
{ {
newHealthOfStack[unit->unitId()] = unit->getAvailableHealth(); auto unitId = unit->unitId();
newValueOfStack[unit->unitId()] = 0; auto localUnit = state.battleGetUnitByID(unitId);
if(state.battleGetOwner(unit) == playerID && unit->alive() && unit->willMove()) newHealthOfStack[unitId] = localUnit->getAvailableHealth();
newValueOfStack[unitId] = 0;
if(state.battleGetOwner(localUnit) == playerID && localUnit->alive() && localUnit->willMove())
ourUnits++; ourUnits++;
} }
@ -427,22 +442,32 @@ void CBattleAI::attemptCastingSpell()
std::vector<battle::Units> newTurnOrder; std::vector<battle::Units> newTurnOrder;
state.battleGetTurnOrder(newTurnOrder, amount, 2); state.battleGetTurnOrder(newTurnOrder, amount, 2);
if(evaluateQueue(newValueOfStack, newTurnOrder, &state, minTurnSpan, nullptr)) const bool turnSpanOK = evaluateQueue(newValueOfStack, newTurnOrder, &state, minTurnSpan, nullptr);
if(turnSpanOK || castNow)
{ {
int64_t totalGain = 0;
for(auto unit : all) for(auto unit : all)
{ {
auto newValue = getValOr(newValueOfStack, unit->unitId(), 0); auto unitId = unit->unitId();
auto oldValue = getValOr(valueOfStack, unit->unitId(), 0); auto localUnit = state.battleGetUnitByID(unitId);
auto healthDiff = newHealthOfStack[unit->unitId()] - healthOfStack[unit->unitId()]; auto newValue = getValOr(newValueOfStack, unitId, 0);
auto oldValue = getValOr(valueOfStack, unitId, 0);
if(unit->unitOwner() != playerID) auto healthDiff = newHealthOfStack[unitId] - healthOfStack[unitId];
if(localUnit->unitOwner() != playerID)
healthDiff = -healthDiff; healthDiff = -healthDiff;
auto gain = newValue - oldValue + healthDiff; if(healthDiff < 0)
{
ps->value = -1;
return; //do not damage own units at all
}
if(gain != 0) totalGain += (newValue - oldValue + healthDiff);
totalGain += gain;
} }
ps->value = totalGain; ps->value = totalGain;
@ -456,11 +481,8 @@ void CBattleAI::attemptCastingSpell()
std::vector<std::function<void()>> tasks; std::vector<std::function<void()>> tasks;
for(PossibleSpellcast & psc : possibleCasts) for(PossibleSpellcast & psc : possibleCasts)
{
tasks.push_back(std::bind(evaluateSpellcast, &psc)); tasks.push_back(std::bind(evaluateSpellcast, &psc));
}
uint32_t threadCount = boost::thread::hardware_concurrency(); uint32_t threadCount = boost::thread::hardware_concurrency();
if(threadCount == 0) if(threadCount == 0)
@ -476,7 +498,7 @@ void CBattleAI::attemptCastingSpell()
LOGFL("Evaluation took %d ms", timer.getDiff()); LOGFL("Evaluation took %d ms", timer.getDiff());
auto pscValue = [] (const PossibleSpellcast &ps) -> int64_t auto pscValue = [](const PossibleSpellcast &ps) -> int64_t
{ {
return ps.value; return ps.value;
}; };