1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-01-08 00:39:47 +02:00

AI can now disband units that block slots for buying better units

When the AI cannot buy units in a city because all slots are blocked and the units in the slot are cheaper than the units it wants to buy, the AI will now get rid of the units that block that slot in order to be able to buy the better units.
This commit is contained in:
Xilmi 2024-12-12 20:06:33 +01:00
parent 6536c9a18e
commit 2ad9038709
3 changed files with 62 additions and 6 deletions

View File

@ -309,6 +309,10 @@ std::vector<creInfo> ArmyManager::getArmyAvailableToBuy(
? dynamic_cast<const CGTownInstance *>(dwelling)
: nullptr;
// Keep track of the least valuable slot in the hero's army
SlotID leastValuableSlot;
int leastValuableStackMarketValue = std::numeric_limits<int>::max();
for(int i = dwelling->creatures.size() - 1; i >= 0; i--)
{
auto ci = infoFromDC(dwelling->creatures[i]);
@ -322,13 +326,40 @@ std::vector<creInfo> ArmyManager::getArmyAvailableToBuy(
if(!ci.count) continue;
// Calculate the market value of the new stack
int newStackMarketValue = ci.creID.toCreature()->getFullRecruitCost().marketValue() * ci.count;
SlotID dst = hero->getSlotFor(ci.creID);
if(!hero->hasStackAtSlot(dst)) //need another new slot for this stack
{
if(!freeHeroSlots) //no more place for stacks
continue;
if(!freeHeroSlots) // No free slots; consider replacing
{
// Check for the least valuable existing stack
for (auto& slot : hero->Slots())
{
if(slot.second->getCreatureID() != CreatureID::NONE)
{
int currentStackMarketValue =
slot.second->getCreatureID().toCreature()->getFullRecruitCost().marketValue() * slot.second->getCount();
if(currentStackMarketValue < leastValuableStackMarketValue)
{
leastValuableStackMarketValue = currentStackMarketValue;
leastValuableSlot = slot.first;
}
}
}
// Decide whether to replace the least valuable stack
if(newStackMarketValue <= leastValuableStackMarketValue)
{
continue; // Skip if the new stack isn't worth replacing
}
}
else
{
freeHeroSlots--; //new slot will be occupied
}
}
vstd::amin(ci.count, availableRes / ci.creID.toCreature()->getFullRecruitCost()); //max count we can afford

View File

@ -58,6 +58,29 @@ void BuyArmy::accept(AIGateway * ai)
if(ci.count)
{
if (!town->getUpperArmy()->hasStackAtSlot(town->getUpperArmy()->getSlotFor(ci.creID)))
{
SlotID lowestValueSlot;
int lowestValue = std::numeric_limits<int>::max();
for (auto slot : town->getUpperArmy()->Slots())
{
if (slot.second->getCreatureID() != CreatureID::NONE)
{
int currentStackMarketValue =
slot.second->getCreatureID().toCreature()->getFullRecruitCost().marketValue() * slot.second->getCount();
if (currentStackMarketValue < lowestValue)
{
lowestValue = currentStackMarketValue;
lowestValueSlot = slot.first;
}
}
}
if (lowestValueSlot.validSlot())
{
cb->dismissCreature(town->getUpperArmy(), lowestValueSlot);
}
}
cb->recruitCreatures(town, town->getUpperArmy(), ci.creID, ci.count, ci.level);
valueBought += ci.count * ci.creID.toCreature()->getAIValue();
}

View File

@ -374,10 +374,12 @@ HeroExchangeArmy * HeroExchangeMap::tryUpgrade(
for(auto & creatureToBuy : buyArmy)
{
auto targetSlot = target->getSlotFor(creatureToBuy.creID.toCreature());
target->addToSlot(targetSlot, creatureToBuy.creID, creatureToBuy.count);
target->armyCost += creatureToBuy.creID.toCreature()->getFullRecruitCost() * creatureToBuy.count;
target->requireBuyArmy = true;
if (targetSlot.validSlot())
{
target->addToSlot(targetSlot, creatureToBuy.creID, creatureToBuy.count);
target->armyCost += creatureToBuy.creID.toCreature()->getFullRecruitCost() * creatureToBuy.count;
target->requireBuyArmy = true;
}
}
}