mirror of
https://github.com/vcmi/vcmi.git
synced 2025-07-05 00:49:09 +02:00
Complete solution for artifact equip & exchange.
This commit is contained in:
102
AI/VCAI/VCAI.cpp
102
AI/VCAI/VCAI.cpp
@ -989,62 +989,96 @@ void VCAI::pickBestCreatures(const CArmedInstance * army, const CArmedInstance *
|
|||||||
|
|
||||||
void VCAI::pickBestArtifacts(const CGHeroInstance * h, const CGHeroInstance * other)
|
void VCAI::pickBestArtifacts(const CGHeroInstance * h, const CGHeroInstance * other)
|
||||||
{
|
{
|
||||||
std::vector<ArtifactLocation> allArtifacts;
|
auto equipBest = [](const CGHeroInstance * h, const CGHeroInstance * otherh, bool giveStuffToFirstHero) -> void
|
||||||
|
{
|
||||||
|
bool changeMade = false;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
changeMade = false;
|
||||||
|
|
||||||
|
//we collect gear always in same order
|
||||||
|
std::vector<ArtifactLocation> allArtifacts;
|
||||||
|
if (giveStuffToFirstHero)
|
||||||
|
{
|
||||||
for (auto p : h->artifactsWorn)
|
for (auto p : h->artifactsWorn)
|
||||||
{
|
{
|
||||||
if (p.second.artifact)
|
if (p.second.artifact)
|
||||||
allArtifacts.push_back(ArtifactLocation(h, p.first));
|
allArtifacts.push_back(ArtifactLocation(h, p.first));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
for (auto slot : h->artifactsInBackpack)
|
for (auto slot : h->artifactsInBackpack)
|
||||||
allArtifacts.push_back(ArtifactLocation(h, h->getArtPos(slot.artifact)));
|
allArtifacts.push_back(ArtifactLocation(h, h->getArtPos(slot.artifact)));
|
||||||
|
|
||||||
if (other)
|
if (otherh)
|
||||||
{
|
{
|
||||||
for (auto p : other->artifactsWorn)
|
for (auto p : otherh->artifactsWorn)
|
||||||
{
|
{
|
||||||
if (p.second.artifact)
|
if (p.second.artifact)
|
||||||
allArtifacts.push_back(ArtifactLocation(other, p.first));
|
allArtifacts.push_back(ArtifactLocation(otherh, p.first));
|
||||||
}
|
}
|
||||||
for (auto slot : other->artifactsInBackpack)
|
for (auto slot : otherh->artifactsInBackpack)
|
||||||
allArtifacts.push_back(ArtifactLocation(other, other->getArtPos(slot.artifact)));
|
allArtifacts.push_back(ArtifactLocation(otherh, otherh->getArtPos(slot.artifact)));
|
||||||
}
|
}
|
||||||
|
//we give stuff to one hero or another, depending on giveStuffToFirstHero
|
||||||
|
|
||||||
|
const CGHeroInstance * target = nullptr;
|
||||||
|
if (giveStuffToFirstHero)
|
||||||
|
target = h;
|
||||||
|
else
|
||||||
|
target = otherh;
|
||||||
|
|
||||||
for (auto location : allArtifacts)
|
for (auto location : allArtifacts)
|
||||||
{
|
{
|
||||||
auto artifact = location.getSlot()->artifact;
|
if (location.relatedObj() == target && location.slot < ArtifactPosition::AFTER_LAST)
|
||||||
auto otherSlot = h->getSlot(artifact->firstAvailableSlot(h));
|
continue; //don't reequip artifact we already wear
|
||||||
if (otherSlot && otherSlot->artifact)
|
|
||||||
if (compareArtifacts (artifact, otherSlot->artifact)) //if that artifact is better than what we have, pick it
|
auto s = location.getSlot();
|
||||||
cb->swapArtifacts (location, ArtifactLocation(h, h->getArtPos(otherSlot->artifact)));
|
if (!s)
|
||||||
|
continue;
|
||||||
|
auto artifact = s->artifact;
|
||||||
|
if (!artifact)
|
||||||
|
continue;
|
||||||
|
//FIXME: why are the above possible to be null?
|
||||||
|
|
||||||
|
bool emptySlotFound = false;
|
||||||
|
for (auto slot : artifact->artType->possibleSlots.at(target->bearerType()))
|
||||||
|
{
|
||||||
|
if (target->isPositionFree(slot))
|
||||||
|
{
|
||||||
|
cb->swapArtifacts(location, ArtifactLocation(target, slot)); //just put into empty slot
|
||||||
|
emptySlotFound = true;
|
||||||
|
changeMade = true;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
if (!emptySlotFound) //try to put that atifact in already occupied slot
|
||||||
|
{
|
||||||
|
for (auto slot : artifact->artType->possibleSlots.at(target->bearerType()))
|
||||||
|
{
|
||||||
|
auto otherSlot = target->getSlot(slot);
|
||||||
|
if (otherSlot && otherSlot->artifact) //we need to exchange artifact for better one
|
||||||
|
{
|
||||||
|
if (compareArtifacts(artifact, otherSlot->artifact)) //if that artifact is better than what we have, pick it
|
||||||
|
{
|
||||||
|
cb->swapArtifacts(location, ArtifactLocation(target, target->getArtPos(otherSlot->artifact)));
|
||||||
|
break;
|
||||||
|
changeMade = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (changeMade)
|
||||||
|
break; //start evaluating artifacts from scratch
|
||||||
|
}
|
||||||
|
} while (changeMade);
|
||||||
|
};
|
||||||
|
|
||||||
|
equipBest (h, other, true);
|
||||||
|
|
||||||
if (other)
|
if (other)
|
||||||
{
|
{
|
||||||
//do not touch artifacts worn by first (main) hero
|
equipBest(h, other, false);
|
||||||
//slots may have moved significantly, just start from scratch
|
|
||||||
allArtifacts.clear();
|
|
||||||
|
|
||||||
for (auto slot : h->artifactsInBackpack)
|
|
||||||
allArtifacts.push_back(ArtifactLocation(h, h->getArtPos(slot.artifact)));
|
|
||||||
|
|
||||||
for (auto p : other->artifactsWorn)
|
|
||||||
{
|
|
||||||
if (p.second.artifact)
|
|
||||||
allArtifacts.push_back(ArtifactLocation(other, p.first));
|
|
||||||
}
|
|
||||||
for (auto slot : other->artifactsInBackpack)
|
|
||||||
allArtifacts.push_back(ArtifactLocation(other, other->getArtPos(slot.artifact)));
|
|
||||||
|
|
||||||
for (auto location : allArtifacts)
|
|
||||||
{
|
|
||||||
auto artifact = location.getSlot()->artifact;
|
|
||||||
auto otherSlot = other->getSlot(artifact->firstAvailableSlot(other));
|
|
||||||
if (otherSlot && otherSlot->artifact)
|
|
||||||
if (compareArtifacts(artifact, otherSlot->artifact)) //if that artifact is better than what we have, pick it
|
|
||||||
cb->swapArtifacts(location, ArtifactLocation(other, other->getArtPos(otherSlot->artifact)));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user