1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-12-24 00:36:29 +02:00

Fuzzy rework, added more defence and gather army routines

This commit is contained in:
Andrii Danylchenko
2023-06-04 16:02:02 +03:00
parent b1ca663eb6
commit b19ac01bf9
28 changed files with 710 additions and 195 deletions

View File

@@ -19,12 +19,12 @@ HitMapInfo HitMapInfo::NoTreat;
void DangerHitMapAnalyzer::updateHitMap()
{
if(upToDate)
if(hitMapUpToDate)
return;
logAi->trace("Update danger hitmap");
upToDate = true;
hitMapUpToDate = true;
auto start = std::chrono::high_resolution_clock::now();
auto cb = ai->cb.get();
@@ -71,8 +71,10 @@ void DangerHitMapAnalyzer::updateHitMap()
auto turn = path.turn();
auto & node = hitMap[pos.x][pos.y][pos.z];
if(tileDanger / (turn / 3 + 1) > node.maximumDanger.danger / (node.maximumDanger.turn / 3 + 1)
|| (tileDanger == node.maximumDanger.danger && node.maximumDanger.turn > turn))
auto newMaxDanger = tileDanger / std::sqrt(turn / 3.0f + 1);
auto currentMaxDanger = node.maximumDanger.danger / std::sqrt(node.maximumDanger.turn / 3.0f + 1);
if(newMaxDanger > currentMaxDanger)
{
node.maximumDanger.danger = tileDanger;
node.maximumDanger.turn = turn;
@@ -104,6 +106,94 @@ void DangerHitMapAnalyzer::updateHitMap()
logAi->trace("Danger hit map updated in %ld", timeElapsed(start));
}
void DangerHitMapAnalyzer::calculateTileOwners()
{
if(tileOwnersUpToDate) return;
tileOwnersUpToDate = true;
auto cb = ai->cb.get();
auto mapSize = ai->cb->getMapSize();
tileOwners.resize(boost::extents[mapSize.x][mapSize.y][mapSize.z]);
std::map<const CGHeroInstance *, HeroRole> townHeroes;
std::map<const CGHeroInstance *, const CGTownInstance *> heroTownMap;
PathfinderSettings pathfinderSettings;
pathfinderSettings.mainTurnDistanceLimit = 3;
auto addTownHero = [&](const CGTownInstance * town)
{
auto townHero = new CGHeroInstance();
CRandomGenerator rng;
townHero->pos = town->pos;
townHero->setOwner(ai->playerID); // lets avoid having multiple colors
townHero->initHero(rng, static_cast<HeroTypeID>(0));
townHero->initObj(rng);
heroTownMap[townHero] = town;
townHeroes[townHero] = HeroRole::MAIN;
};
for(auto obj : ai->memory->visitableObjs)
{
if(obj && obj->ID == Obj::TOWN)
{
addTownHero(dynamic_cast<const CGTownInstance *>(obj));
}
}
for(auto town : cb->getTownsInfo())
{
addTownHero(town);
}
ai->pathfinder->updatePaths(townHeroes, PathfinderSettings());
pforeachTilePos(mapSize, [&](const int3 & pos)
{
float ourDistance = std::numeric_limits<float>::max();
float enemyDistance = std::numeric_limits<float>::max();
const CGTownInstance * enemyTown = nullptr;
for(AIPath & path : ai->pathfinder->getPathInfo(pos))
{
if(!path.targetHero || path.getFirstBlockedAction())
continue;
auto town = heroTownMap[path.targetHero];
if(town->getOwner() == ai->playerID)
{
vstd::amin(ourDistance, path.movementCost());
}
else
{
if(enemyDistance > path.movementCost())
{
enemyDistance = path.movementCost();
enemyTown = town;
}
}
}
if(ourDistance == enemyDistance)
{
tileOwners[pos.x][pos.y][pos.z] = PlayerColor::NEUTRAL;
}
else if(!enemyTown || ourDistance < enemyDistance)
{
tileOwners[pos.x][pos.y][pos.z] = ai->playerID;
}
else
{
tileOwners[pos.x][pos.y][pos.z] = enemyTown->getOwner();
}
});
}
uint64_t DangerHitMapAnalyzer::enemyCanKillOurHeroesAlongThePath(const AIPath & path) const
{
int3 tile = path.targetTile();
@@ -144,7 +234,7 @@ const std::set<const CGObjectInstance *> & DangerHitMapAnalyzer::getOneTurnAcces
void DangerHitMapAnalyzer::reset()
{
upToDate = false;
hitMapUpToDate = false;
}
}