1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-11-25 22:42:04 +02:00

more cc renaming; BuildingID get level index and upgrades; Creatures renaming

This commit is contained in:
Mircea TheHonestCTO
2025-08-17 12:24:35 +02:00
parent bf3d5627e0
commit a4a9927e9e
15 changed files with 122 additions and 121 deletions

View File

@@ -211,8 +211,8 @@ BuildingInfo BuildAnalyzer::getBuildingOrPrerequisite(
if(toBuild.isDwelling())
{
creatureLevel = BuildingID::getLevelFromDwelling(toBuild);
creatureUpgrade = BuildingID::getUpgradedFromDwelling(toBuild);
creatureLevel = BuildingID::getLevelIndexFromDwelling(toBuild);
creatureUpgrade = BuildingID::getUpgradeNoFromDwelling(toBuild);
}
else if(toBuild == BuildingID::HORDE_1 || toBuild == BuildingID::HORDE_1_UPGR)
{

View File

@@ -119,13 +119,13 @@ std::vector<SlotInfo>::iterator ArmyManager::getBestUnitForScout(std::vector<Slo
for (const auto & unit : army)
totalPower += unit.power;
int baseMovementCost = cb->getSettings().getInteger(EGameSettings::HEROES_MOVEMENT_COST_BASE);
int baseMovementCost = cpsic->getSettings().getInteger(EGameSettings::HEROES_MOVEMENT_COST_BASE);
bool terrainHasPenalty = armyTerrain.hasValue() && armyTerrain.toEntity(LIBRARY)->moveCost != baseMovementCost;
// arbitrary threshold - don't give scout more than specified part of total AI value of our army
uint64_t maxUnitValue = totalPower / 100;
const auto & movementPointsLimits = cb->getSettings().getVector(EGameSettings::HEROES_MOVEMENT_POINTS_LAND);
const auto & movementPointsLimits = cpsic->getSettings().getVector(EGameSettings::HEROES_MOVEMENT_POINTS_LAND);
auto fastest = boost::min_element(army, [&](const SlotInfo & left, const SlotInfo & right) -> bool
{
@@ -231,9 +231,9 @@ std::vector<SlotInfo> ArmyManager::getBestArmy(const IBonusBearer * armyCarrier,
auto morale = slot.second->moraleVal();
auto multiplier = 1.0f;
const auto & badMoraleChance = cb->getSettings().getVector(EGameSettings::COMBAT_BAD_MORALE_CHANCE);
const auto & highMoraleChance = cb->getSettings().getVector(EGameSettings::COMBAT_GOOD_MORALE_CHANCE);
int moraleDiceSize = cb->getSettings().getInteger(EGameSettings::COMBAT_MORALE_DICE_SIZE);
const auto & badMoraleChance = cpsic->getSettings().getVector(EGameSettings::COMBAT_BAD_MORALE_CHANCE);
const auto & highMoraleChance = cpsic->getSettings().getVector(EGameSettings::COMBAT_GOOD_MORALE_CHANCE);
int moraleDiceSize = cpsic->getSettings().getInteger(EGameSettings::COMBAT_MORALE_DICE_SIZE);
if(morale < 0 && !badMoraleChance.empty())
{
@@ -347,7 +347,7 @@ std::vector<creInfo> ArmyManager::getArmyAvailableToBuy(
{
std::vector<creInfo> creaturesInDwellings;
int freeHeroSlots = GameConstants::ARMY_SIZE - hero->stacksCount();
bool countGrowth = (cb->getDate(Date::DAY_OF_WEEK) + turn) > 7;
bool countGrowth = (cpsic->getDate(Date::DAY_OF_WEEK) + turn) > 7;
const CGTownInstance * town = dwelling->ID == Obj::TOWN
? dynamic_cast<const CGTownInstance *>(dwelling)
@@ -478,8 +478,8 @@ void ArmyManager::update()
logAi->trace("Start analysing army");
std::vector<const CCreatureSet *> total;
auto heroes = cb->getHeroesInfo();
auto towns = cb->getTownsInfo();
auto heroes = cpsic->getHeroesInfo();
auto towns = cpsic->getTownsInfo();
std::copy(heroes.begin(), heroes.end(), std::back_inserter(total));
std::copy(towns.begin(), towns.end(), std::back_inserter(total));

View File

@@ -82,12 +82,12 @@ class StackUpgradeInfo;
class DLL_EXPORT ArmyManager : public IArmyManager
{
private:
CPlayerSpecificInfoCallback * cb; //this is enough, but we downcast from CCallback
CPlayerSpecificInfoCallback * cpsic; //this is enough, but we downcast from CCallback
const Nullkiller * aiNk;
std::map<CreatureID, SlotInfo> totalArmy;
public:
ArmyManager(CPlayerSpecificInfoCallback * CB, const Nullkiller * ai): cb(CB), aiNk(ai) {}
ArmyManager(CPlayerSpecificInfoCallback * cpsic, const Nullkiller * ai): cpsic(cpsic), aiNk(ai) {}
void update() override;
ui64 howManyReinforcementsCanBuy(const CCreatureSet * target, const CGDwelling * source) const override;

View File

@@ -19,16 +19,14 @@ namespace NK2AI
TResources BuildAnalyzer::getResourcesRequiredNow() const
{
auto resourcesAvailable = aiNk->getFreeResources();
auto result = withoutGold(armyCost) + requiredResources - resourcesAvailable;
auto result = withoutGold(armyCost) + requiredResources - aiNk->getFreeResources();
result.positive();
return result;
}
TResources BuildAnalyzer::getTotalResourcesRequired() const
{
auto resourcesAvailable = aiNk->getFreeResources();
auto result = totalDevelopmentCost + withoutGold(armyCost) - resourcesAvailable;
auto result = totalDevelopmentCost + withoutGold(armyCost) - aiNk->getFreeResources();
result.positive();
return result;
}
@@ -57,7 +55,7 @@ void BuildAnalyzer::update()
developmentInfos.push_back(TownDevelopmentInfo(town));
TownDevelopmentInfo & tdi = developmentInfos.back();
updateCreatureBuildings(tdi, aiNk->armyManager, aiNk->cc);
updateDwellings(tdi, aiNk->armyManager, aiNk->cc);
updateOtherBuildings(tdi, aiNk->armyManager, aiNk->cc);
requiredResources += tdi.requiredResources;
totalDevelopmentCost += tdi.townDevelopmentCost;
@@ -110,7 +108,7 @@ bool BuildAnalyzer::isBuilt(FactionID alignment, BuildingID bid) const
return false;
}
void TownDevelopmentInfo::addExistingDwelling(const BuildingInfo & bi)
void TownDevelopmentInfo::addBuildingBuilt(const BuildingInfo & bi)
{
armyCost += bi.armyCost;
armyStrength += bi.armyStrength;
@@ -149,43 +147,43 @@ BuildingInfo::BuildingInfo(
if(creature)
{
creatureGrows = creature->getGrowth();
creatureGrowth = creature->getGrowth();
creatureID = creature->getId();
baseCreatureID = baseCreature;
creatureCost = creature->getFullRecruitCost();
creatureUnitCost = creature->getFullRecruitCost();
creatureLevel = creature->getLevel();
if(isBuilt)
{
creatureGrows = town->creatureGrowth(creatureLevel - 1);
creatureGrowth = town->creatureGrowth(creatureLevel - 1);
}
else
{
if(id.isDwelling())
{
creatureGrows = creature->getGrowth();
creatureGrowth = creature->getGrowth();
if(town->hasBuilt(BuildingID::CASTLE))
creatureGrows *= 2;
creatureGrowth *= 2;
else if(town->hasBuilt(BuildingID::CITADEL))
creatureGrows += creatureGrows / 2;
creatureGrowth += creatureGrowth / 2;
}
else
{
creatureGrows = creature->getHorde();
creatureGrowth = creature->getHorde();
}
}
armyStrength = armyManager->evaluateStackPower(creature, creatureGrows);
armyCost = creatureCost * creatureGrows;
armyStrength = armyManager->evaluateStackPower(creature, creatureGrowth);
armyCost = creatureUnitCost * creatureGrowth;
}
}
std::string BuildingInfo::toString() const
{
return name + ", cost: " + buildCost.toString()
+ ", creature: " + std::to_string(creatureGrows) + " x " + std::to_string(creatureLevel)
+ " x " + creatureCost.toString()
+ ", creature: " + std::to_string(creatureGrowth) + " x " + std::to_string(creatureLevel)
+ " x " + creatureUnitCost.toString()
+ ", daily: " + dailyIncome.toString();
}
@@ -218,7 +216,7 @@ TResources BuildAnalyzer::calculateDailyIncome(const std::vector<const CGObjectI
return result;
}
void BuildAnalyzer::updateCreatureBuildings(TownDevelopmentInfo & developmentInfo, std::unique_ptr<ArmyManager> & armyManager, std::shared_ptr<CCallback> & cb)
void BuildAnalyzer::updateDwellings(TownDevelopmentInfo & developmentInfo, std::unique_ptr<ArmyManager> & armyManager, std::shared_ptr<CCallback> & cc)
{
for(int level = 0; level < developmentInfo.town->getTown()->creatures.size(); level++)
{
@@ -237,8 +235,8 @@ void BuildAnalyzer::updateCreatureBuildings(TownDevelopmentInfo & developmentInf
if (!developmentInfo.town->hasBuilt(buildID))
continue;
const auto & info = getBuildingOrPrerequisite(developmentInfo.town, buildID, armyManager, cb);
developmentInfo.addExistingDwelling(info);
const auto & info = getBuildingOrPrerequisite(developmentInfo.town, buildID, armyManager, cc);
developmentInfo.addBuildingBuilt(info);
break;
}
@@ -248,7 +246,7 @@ void BuildAnalyzer::updateCreatureBuildings(TownDevelopmentInfo & developmentInf
if (developmentInfo.town->hasBuilt(buildID))
continue;
const auto & info = getBuildingOrPrerequisite(developmentInfo.town, buildID, armyManager, cb);
const auto & info = getBuildingOrPrerequisite(developmentInfo.town, buildID, armyManager, cc);
if (info.isBuildable || info.isMissingResources)
developmentInfo.addBuildingToBuild(info);
}
@@ -257,7 +255,7 @@ void BuildAnalyzer::updateCreatureBuildings(TownDevelopmentInfo & developmentInf
void BuildAnalyzer::updateOtherBuildings(TownDevelopmentInfo & developmentInfo,
std::unique_ptr<ArmyManager> & armyManager,
std::shared_ptr<CCallback> & cb)
std::shared_ptr<CCallback> & cc)
{
logAi->trace("Checking other buildings");
@@ -266,7 +264,7 @@ void BuildAnalyzer::updateOtherBuildings(TownDevelopmentInfo & developmentInfo,
{BuildingID::MAGES_GUILD_3, BuildingID::MAGES_GUILD_5}
};
if(developmentInfo.built.size() >= 2 && cb->getDate(Date::DAY_OF_WEEK) > 4)
if(developmentInfo.built.size() >= 2 && cc->getDate(Date::DAY_OF_WEEK) > 4)
{
otherBuildings.push_back({BuildingID::HORDE_1});
otherBuildings.push_back({BuildingID::HORDE_2});
@@ -286,7 +284,7 @@ void BuildAnalyzer::updateOtherBuildings(TownDevelopmentInfo & developmentInfo,
{
if(!developmentInfo.town->hasBuilt(buildingID) && developmentInfo.town->getTown()->buildings.count(buildingID))
{
developmentInfo.addBuildingToBuild(getBuildingOrPrerequisite(developmentInfo.town, buildingID, armyManager, cb));
developmentInfo.addBuildingToBuild(getBuildingOrPrerequisite(developmentInfo.town, buildingID, armyManager, cc));
break;
}
}
@@ -295,40 +293,40 @@ void BuildAnalyzer::updateOtherBuildings(TownDevelopmentInfo & developmentInfo,
BuildingInfo BuildAnalyzer::getBuildingOrPrerequisite(
const CGTownInstance * town,
BuildingID toBuild,
BuildingID b,
std::unique_ptr<ArmyManager> & armyManager,
std::shared_ptr<CCallback> & cb,
std::shared_ptr<CCallback> & cc,
bool excludeDwellingDependencies)
{
BuildingID building = toBuild;
// TODO: Mircea: Remove redundant variable
BuildingID building = b;
const auto * townInfo = town->getTown();
const auto & buildPtr = townInfo->buildings.at(building);
const CCreature * creature = nullptr;
CreatureID baseCreatureID;
int creatureLevel = -1;
int creatureUpgrade = 0;
int creatureLevelIndex = -1;
int creatureUpgradeNo = 0;
if(toBuild.isDwelling())
if(b.isDwelling())
{
creatureLevel = BuildingID::getLevelFromDwelling(toBuild);
creatureUpgrade = BuildingID::getUpgradedFromDwelling(toBuild);
creatureLevelIndex = BuildingID::getLevelIndexFromDwelling(b);
creatureUpgradeNo = BuildingID::getUpgradeNoFromDwelling(b);
}
else if(toBuild == BuildingID::HORDE_1 || toBuild == BuildingID::HORDE_1_UPGR)
else if(b == BuildingID::HORDE_1 || b == BuildingID::HORDE_1_UPGR)
{
creatureLevel = townInfo->hordeLvl.at(0);
creatureLevelIndex = townInfo->hordeLvl.at(0);
}
else if(toBuild == BuildingID::HORDE_2 || toBuild == BuildingID::HORDE_2_UPGR)
else if(b == BuildingID::HORDE_2 || b == BuildingID::HORDE_2_UPGR)
{
creatureLevel = townInfo->hordeLvl.at(1);
creatureLevelIndex = townInfo->hordeLvl.at(1);
}
if(creatureLevel >= 0)
if(creatureLevelIndex >= 0)
{
auto creatures = townInfo->creatures.at(creatureLevel);
auto creatureID = creatures.size() > creatureUpgrade
? creatures.at(creatureUpgrade)
auto creatures = townInfo->creatures.at(creatureLevelIndex);
auto creatureID = creatures.size() > creatureUpgradeNo
? creatures.at(creatureUpgradeNo)
: creatures.front();
baseCreatureID = creatures.front();
@@ -340,14 +338,14 @@ BuildingInfo BuildAnalyzer::getBuildingOrPrerequisite(
//logAi->trace("checking %s buildInfo %s", info.name, info.toString());
int highestFort = 0;
for (const auto * ti : cb->getTownsInfo())
for (const auto * ti : cc->getTownsInfo())
{
highestFort = std::max(highestFort, static_cast<int>(ti->fortLevel()));
}
if(!town->hasBuilt(building))
{
auto canBuild = cb->canBuildStructure(town, building);
auto canBuild = cc->canBuildStructure(town, building);
if(canBuild == EBuildingState::ALLOWED)
{
@@ -374,25 +372,26 @@ BuildingInfo BuildAnalyzer::getBuildingOrPrerequisite(
if(vstd::contains_if(missingBuildings, otherDwelling))
{
#if NKAI_TRACE_LEVEL >= 1
logAi->trace("Can't build %d. Needs other dwelling %d", toBuild.getNum(), missingBuildings.front().getNum());
logAi->trace("Can't build %d. Needs other dwelling %d", b.getNum(), missingBuildings.front().getNum());
#endif
}
else if(missingBuildings[0] != toBuild)
else if(missingBuildings[0] != b)
{
#if NKAI_TRACE_LEVEL >= 1
logAi->trace("Can't build %d. Needs %d", toBuild.getNum(), missingBuildings[0].num);
logAi->trace("Can't build %d. Needs %d", b.getNum(), missingBuildings[0].num);
#endif
BuildingInfo prerequisite = getBuildingOrPrerequisite(town, missingBuildings[0], armyManager, cb, excludeDwellingDependencies);
BuildingInfo prerequisite = getBuildingOrPrerequisite(town, missingBuildings[0], armyManager, cc, excludeDwellingDependencies);
prerequisite.buildCostWithPrerequisites += info.buildCost;
prerequisite.creatureCost = info.creatureCost;
prerequisite.creatureGrows = info.creatureGrows;
prerequisite.creatureUnitCost = info.creatureUnitCost;
prerequisite.creatureGrowth = info.creatureGrowth;
prerequisite.creatureLevel = info.creatureLevel;
prerequisite.creatureID = info.creatureID;
prerequisite.baseCreatureID = info.baseCreatureID;
prerequisite.prerequisitesCount++;
prerequisite.armyCost = info.armyCost;
prerequisite.armyStrength = info.armyStrength;
bool haveSameOrBetterFort = false;
if (prerequisite.id == BuildingID::FORT && highestFort >= CGTownInstance::EFortLevel::FORT)
haveSameOrBetterFort = true;
@@ -423,7 +422,7 @@ BuildingInfo BuildAnalyzer::getBuildingOrPrerequisite(
else
{
#if NKAI_TRACE_LEVEL >= 1
logAi->trace("Dwelling %d exists", toBuild.getNum());
logAi->trace("Dwelling %d exists", b.getNum());
#endif
info.isBuilt = true;
}

View File

@@ -24,15 +24,15 @@ public:
BuildingID id = BuildingID::NONE;
TResources buildCost;
TResources buildCostWithPrerequisites;
int creatureGrows = 0;
uint8_t creatureLevel = 0;
TResources creatureCost;
int creatureGrowth = 0;
uint8_t creatureLevel = 0; /// @link CCreature::level
TResources creatureUnitCost;
CreatureID creatureID = CreatureID::NONE;
CreatureID baseCreatureID = CreatureID::NONE;
TResources dailyIncome;
uint8_t prerequisitesCount = 0;
uint64_t armyStrength = 0;
TResources armyCost;
TResources armyCost; // creatureCost * creatureGrows
std::string name;
bool isBuilt = false;
bool isBuildable = false;
@@ -64,8 +64,8 @@ public:
TownDevelopmentInfo(const CGTownInstance * town) : town(town) {}
TownDevelopmentInfo() : TownDevelopmentInfo(nullptr) {}
void addBuildingToBuild(const BuildingInfo & building);
void addExistingDwelling(const BuildingInfo & bi);
void addBuildingToBuild(const BuildingInfo & bi);
void addBuildingBuilt(const BuildingInfo & bi);
};
class DLL_EXPORT BuildAnalyzer
@@ -94,13 +94,13 @@ public:
static float calculateGoldPressure(TResource lockedGold, float armyCostGold, float economyDevelopmentCost, float freeGold, float dailyIncomeGold);
static TResources calculateDailyIncome(const std::vector<const CGObjectInstance *> & objects, const std::vector<const CGTownInstance *> & townInfos);
static void updateCreatureBuildings(TownDevelopmentInfo& developmentInfo, std::unique_ptr<ArmyManager>& armyManager, std::shared_ptr<CCallback>& cb);
static void updateOtherBuildings(TownDevelopmentInfo& developmentInfo, std::unique_ptr<ArmyManager>& armyManager, std::shared_ptr<CCallback>& cb);
static void updateDwellings(TownDevelopmentInfo& developmentInfo, std::unique_ptr<ArmyManager>& armyManager, std::shared_ptr<CCallback>& cc);
static void updateOtherBuildings(TownDevelopmentInfo& developmentInfo, std::unique_ptr<ArmyManager>& armyManager, std::shared_ptr<CCallback>& cc);
static BuildingInfo getBuildingOrPrerequisite(
const CGTownInstance* town,
BuildingID toBuild,
BuildingID b,
std::unique_ptr<ArmyManager> & armyManager,
std::shared_ptr<CCallback> & cb,
std::shared_ptr<CCallback> & cc,
bool excludeDwellingDependencies = true);
static int32_t approximateInGold(const TResources & res);
static TResources withoutGold(TResources other);

View File

@@ -70,7 +70,7 @@ void DangerHitMapAnalyzer::updateHitMap()
hitMapUpToDate = true;
auto start = std::chrono::high_resolution_clock::now();
auto cb = aiNk->cc.get();
auto cc = aiNk->cc.get();
auto mapSize = aiNk->cc->getMapSize();
if(hitMap.shape()[0] != mapSize.x || hitMap.shape()[1] != mapSize.y || hitMap.shape()[2] != mapSize.z)
@@ -98,7 +98,7 @@ void DangerHitMapAnalyzer::updateHitMap()
}
}
auto ourTowns = cb->getTownsInfo();
auto ourTowns = cc->getTownsInfo();
for(auto town : ourTowns)
{
@@ -158,7 +158,7 @@ void DangerHitMapAnalyzer::updateHitMap()
node.fastestDanger = newThreat;
}
auto objects = cb->getVisitableObjs(pos, false);
auto objects = cc->getVisitableObjs(pos, false);
for(auto obj : objects)
{
@@ -183,7 +183,7 @@ void DangerHitMapAnalyzer::updateHitMap()
if(newThreat.turn == 0)
{
if(cb->getPlayerRelations(obj->tempOwner, aiNk->playerID) != PlayerRelations::ENEMIES)
if(cc->getPlayerRelations(obj->tempOwner, aiNk->playerID) != PlayerRelations::ENEMIES)
enemyHeroAccessibleObjects.emplace_back(path.targetHero, obj);
}
}
@@ -203,7 +203,7 @@ void DangerHitMapAnalyzer::calculateTileOwners()
tileOwnersUpToDate = true;
auto cb = aiNk->cc.get();
auto * cc = aiNk->cc.get();
auto mapSize = aiNk->cc->getMapSize();
if(hitMap.shape()[0] != mapSize.x || hitMap.shape()[1] != mapSize.y || hitMap.shape()[2] != mapSize.z)
@@ -215,7 +215,7 @@ void DangerHitMapAnalyzer::calculateTileOwners()
auto addTownHero = [&](const CGTownInstance * town)
{
auto townHero = temporaryHeroes.emplace_back(std::make_unique<CGHeroInstance>(town->cb)).get();
auto *townHero = temporaryHeroes.emplace_back(std::make_unique<CGHeroInstance>(town->cb)).get();
GameRandomizer randomizer(*town->cb);
auto visitablePos = town->visitablePos();
@@ -229,7 +229,7 @@ void DangerHitMapAnalyzer::calculateTileOwners()
townHeroes[townHero] = HeroRole::MAIN;
};
for(auto obj : aiNk->memory->visitableObjs)
for(const auto *obj : aiNk->memory->visitableObjs)
{
if(obj && obj->ID == Obj::TOWN)
{
@@ -237,7 +237,7 @@ void DangerHitMapAnalyzer::calculateTileOwners()
}
}
for(auto town : cb->getTownsInfo())
for(const auto *town : cc->getTownsInfo())
{
addTownHero(town);
}
@@ -259,7 +259,7 @@ void DangerHitMapAnalyzer::calculateTileOwners()
if(!path.targetHero || path.getFirstBlockedAction())
continue;
auto town = heroTownMap[path.targetHero];
const auto *town = heroTownMap[path.targetHero];
if(town->getOwner() == aiNk->playerID)
{
@@ -305,7 +305,7 @@ const std::vector<HitMapInfo> & DangerHitMapAnalyzer::getTownThreats(const CGTow
PlayerColor DangerHitMapAnalyzer::getTileOwner(const int3 & tile) const
{
auto town = hitMap[tile.x][tile.y][tile.z].closestTown;
const auto *town = hitMap[tile.x][tile.y][tile.z].closestTown;
return town ? town->getOwner() : PlayerColor::NEUTRAL;
}
@@ -342,7 +342,7 @@ std::set<const CGObjectInstance *> DangerHitMapAnalyzer::getOneTurnAccessibleObj
{
std::set<const CGObjectInstance *> result;
for(auto & obj : enemyHeroAccessibleObjects)
for(const auto & obj : enemyHeroAccessibleObjects)
{
if(obj.hero == enemy)
result.insert(obj.obj);

View File

@@ -105,7 +105,7 @@ void HeroManager::update()
logAi->trace("Start analysing our heroes");
std::map<const CGHeroInstance *, float> scores;
auto myHeroes = cb->getHeroesInfo();
auto myHeroes = cc->getHeroesInfo();
for(auto & hero : myHeroes)
{
@@ -118,10 +118,10 @@ void HeroManager::update()
return scores.at(h1) > scores.at(h2);
};
int globalMainCount = std::min(((int)myHeroes.size() + 2) / 3, cb->getMapSize().x / 50 + 1);
int globalMainCount = std::min(((int)myHeroes.size() + 2) / 3, cc->getMapSize().x / 50 + 1);
//vstd::amin(globalMainCount, 1 + (cb->getTownsInfo().size() / 3));
if(cb->getTownsInfo().size() < 4 && globalMainCount > 2)
if(cc->getTownsInfo().size() < 4 && globalMainCount > 2)
{
globalMainCount = 2;
}
@@ -195,11 +195,12 @@ float HeroManager::evaluateHero(const CGHeroInstance * hero) const
bool HeroManager::heroCapReached(bool includeGarrisoned) const
{
int heroCount = cb->getHeroCount(ai->playerID, includeGarrisoned);
int heroCount = cc->getHeroCount(aiNk->playerID, includeGarrisoned);
int maxAllowed = 1 + cc->howManyTowns() * aiNk->settings->getMaxRoamingHeroes();
return heroCount >= ai->settings->getMaxRoamingHeroes()
|| heroCount >= cb->getSettings().getInteger(EGameSettings::HEROES_PER_PLAYER_ON_MAP_CAP)
|| heroCount >= cb->getSettings().getInteger(EGameSettings::HEROES_PER_PLAYER_TOTAL_CAP);
return heroCount >= maxAllowed
|| heroCount >= cc->getSettings().getInteger(EGameSettings::HEROES_PER_PLAYER_ON_MAP_CAP)
|| heroCount >= cc->getSettings().getInteger(EGameSettings::HEROES_PER_PLAYER_TOTAL_CAP);
}
float HeroManager::getFightingStrengthCached(const CGHeroInstance * hero) const
@@ -256,13 +257,13 @@ bool HeroManager::canRecruitHero(const CGTownInstance * town) const
if(!town || !townHasFreeTavern(town))
return false;
if(cb->getResourceAmount(EGameResID::GOLD) < GameConstants::HERO_GOLD_COST)
if(cc->getResourceAmount(EGameResID::GOLD) < GameConstants::HERO_GOLD_COST)
return false;
if(heroCapReached())
return false;
if(!cb->getAvailableHeroes(town).size())
if(!cc->getAvailableHeroes(town).size())
return false;
return true;
@@ -270,7 +271,7 @@ bool HeroManager::canRecruitHero(const CGTownInstance * town) const
const CGTownInstance * HeroManager::findTownWithTavern() const
{
for(const CGTownInstance * t : cb->getTownsInfo())
for(const CGTownInstance * t : cc->getTownsInfo())
if(townHasFreeTavern(t))
return t;
@@ -279,7 +280,7 @@ const CGTownInstance * HeroManager::findTownWithTavern() const
const CGHeroInstance * HeroManager::findHeroWithGrail() const
{
for(const CGHeroInstance * h : cb->getHeroesInfo())
for(const CGHeroInstance * h : cc->getHeroesInfo())
{
if(h->hasArt(ArtifactID::GRAIL))
return h;

View File

@@ -42,13 +42,13 @@ private:
static const SecondarySkillEvaluator wariorSkillsScores;
static const SecondarySkillEvaluator scountSkillsScores;
CCallback * cb; //this is enough, but we downcast from CCallback
CCallback * cc; //this is enough, but we downcast from CCallback
const Nullkiller * aiNk;
std::map<HeroPtr, HeroRole> heroRoles;
std::map<ObjectInstanceID, float> knownFightingStrength;
public:
HeroManager(CCallback * CB, const Nullkiller * ai) : cb(CB), aiNk(ai) {}
HeroManager(CCallback * cc, const Nullkiller * ai) : cc(cc), aiNk(ai) {}
const std::map<HeroPtr, HeroRole> & getHeroRoles() const;
HeroRole getHeroRole(const HeroPtr & hero) const;
int selectBestSkill(const HeroPtr & hero, const std::vector<SecondarySkill> & skills) const;

View File

@@ -31,14 +31,14 @@ void ObjectCluster::addObject(const CGObjectInstance * obj, const AIPath & path,
}
}
const CGObjectInstance * ObjectCluster::calculateCenter(const CPlayerSpecificInfoCallback * cb) const
const CGObjectInstance * ObjectCluster::calculateCenter(const CPlayerSpecificInfoCallback * cpsic) const
{
auto tile = int3(0);
float priority = 0;
for(auto & pair : objects)
{
auto newPoint = cb->getObj(pair.first)->visitablePos();
auto newPoint = cpsic->getObj(pair.first)->visitablePos();
float newPriority = std::pow(pair.second.priority, 4); // lets make high priority targets more weghtful
int3 direction = newPoint - tile;
float priorityRatio = newPriority / (priority + newPriority);
@@ -49,19 +49,19 @@ const CGObjectInstance * ObjectCluster::calculateCenter(const CPlayerSpecificInf
auto closestPair = *vstd::minElementByFun(objects, [&](const std::pair<ObjectInstanceID, ClusterObjectInfo> & pair) -> int
{
return cb->getObj(pair.first)->visitablePos().dist2dSQ(tile);
return cpsic->getObj(pair.first)->visitablePos().dist2dSQ(tile);
});
return cb->getObj(closestPair.first);
return cpsic->getObj(closestPair.first);
}
std::vector<const CGObjectInstance *> ObjectCluster::getObjects(const CPlayerSpecificInfoCallback * cb) const
std::vector<const CGObjectInstance *> ObjectCluster::getObjects(const CPlayerSpecificInfoCallback * cpsic) const
{
std::vector<const CGObjectInstance *> result;
for(auto & pair : objects)
{
result.push_back(cb->getObj(pair.first));
result.push_back(cpsic->getObj(pair.first));
}
return result;

View File

@@ -52,8 +52,8 @@ public:
{
}
std::vector<const CGObjectInstance *> getObjects(const CPlayerSpecificInfoCallback * cb) const;
const CGObjectInstance * calculateCenter(const CPlayerSpecificInfoCallback * cb) const;
std::vector<const CGObjectInstance *> getObjects(const CPlayerSpecificInfoCallback * cpsic) const;
const CGObjectInstance * calculateCenter(const CPlayerSpecificInfoCallback * cpsic) const;
};
using ClusterMap = tbb::concurrent_hash_map<ObjectInstanceID, std::shared_ptr<ObjectCluster>, ObjectInstanceIDHash>;

View File

@@ -1216,9 +1216,9 @@ public:
evaluationContext.addNonCriticalStrategicalValue(potentialUpgradeValue / 10000.0f / (float)bi.prerequisitesCount);
if(bi.id.isDwelling())
evaluationContext.armyReward += bi.armyStrength - evaluationContext.evaluator.aiNk->armyManager->evaluateStackPower(bi.baseCreatureID.toCreature(), bi.creatureGrows);
evaluationContext.armyReward += bi.armyStrength - evaluationContext.evaluator.aiNk->armyManager->evaluateStackPower(bi.baseCreatureID.toCreature(), bi.creatureGrowth);
else //This is for prerequisite-buildings
evaluationContext.armyReward += evaluationContext.evaluator.aiNk->armyManager->evaluateStackPower(bi.baseCreatureID.toCreature(), bi.creatureGrows);
evaluationContext.armyReward += evaluationContext.evaluator.aiNk->armyManager->evaluateStackPower(bi.baseCreatureID.toCreature(), bi.creatureGrowth);
if(alreadyOwn)
evaluationContext.armyReward /= bi.buildCostWithPrerequisites.marketValue();
}

View File

@@ -221,7 +221,7 @@ bool BuildingManager::getBuildingOptions(const CGTownInstance * t)
std::vector<BuildingID> extraBuildings;
for (const auto & buildingInfo : t->getTown()->buildings)
{
if (buildingInfo.first.isDwelling() && BuildingID::getUpgradedFromDwelling(buildingInfo.first) > 1)
if (buildingInfo.first.isDwelling() && BuildingID::getUpgradeNoFromDwelling(buildingInfo.first) > 1)
extraBuildings.push_back(buildingInfo.first);
}
return tryBuildAnyStructure(t, extraBuildings);

View File

@@ -170,7 +170,7 @@ void CBuildingRect::showPopupWindow(const Point & cursorPosition)
}
else
{
int level = BuildingID::getLevelFromDwelling(bid);
int level = BuildingID::getLevelIndexFromDwelling(bid);
ENGINE->windows().createAndPushWindow<CDwellingInfoBox>(parent->pos.x+parent->pos.w / 2, parent->pos.y+parent->pos.h /2, town, level);
}
}
@@ -246,7 +246,7 @@ std::string CBuildingRect::getSubtitle()//hover text for building
return town->getTown()->buildings.at(getBuilding()->bid)->getNameTranslated();
else//dwellings - recruit %creature%
{
int level = BuildingID::getLevelFromDwelling(getBuilding()->bid);
int level = BuildingID::getLevelIndexFromDwelling(getBuilding()->bid);
auto & availableCreatures = town->creatures[level].second;
if(availableCreatures.size())
{
@@ -889,7 +889,7 @@ bool CCastleBuildings::buildingTryActivateCustomUI(BuildingID buildingToTest, Bu
if (buildingToTest.isDwelling())
{
enterDwelling((BuildingID::getLevelFromDwelling(buildingToTest)));
enterDwelling((BuildingID::getLevelIndexFromDwelling(buildingToTest)));
return true;
}
else

View File

@@ -289,7 +289,7 @@ public:
class BuildingIDBase : public IdentifierBase
{
public:
//Quite useful as long as most of building mechanics hardcoded
// Quite useful as long as most of building mechanics hardcoded
// NOTE: all building with completely configurable mechanics will be removed from list
enum Type
{
@@ -369,11 +369,11 @@ public:
throw std::runtime_error("Call to getMageGuildLevel with building '" + std::to_string(getNum()) +"' that is not mages guild!");
}
static BuildingID getDwellingFromLevel(int level, int upgradeIndex)
static BuildingID getDwellingFromLevel(int levelIndex, int upgradeIndex)
{
try
{
return getDwellings().at(upgradeIndex).at(level);
return getDwellings().at(upgradeIndex).at(levelIndex);
}
catch (const std::out_of_range &)
{
@@ -381,7 +381,8 @@ public:
}
}
static int getLevelFromDwelling(BuildingID dwelling)
/// @return 0 for the first one, going up to the supported no. of dwellings - 1
static int getLevelIndexFromDwelling(BuildingID dwelling)
{
for (const auto & level : getDwellings())
{
@@ -393,7 +394,8 @@ public:
throw std::runtime_error("Call to getLevelFromDwelling with building '" + std::to_string(dwelling.num) +"' that is not dwelling!");
}
static int getUpgradedFromDwelling(BuildingID dwelling)
/// @return 0 for no upgrade, 1 for the first one, going up to the supported no. of upgrades
static int getUpgradeNoFromDwelling(BuildingID dwelling)
{
const auto & dwellings = getDwellings();
@@ -408,10 +410,9 @@ public:
static void advanceDwelling(BuildingID & dwelling)
{
int level = getLevelFromDwelling(dwelling);
int upgrade = getUpgradedFromDwelling(dwelling);
dwelling = getDwellingFromLevel(level, upgrade + 1);
int levelIndex = getLevelIndexFromDwelling(dwelling);
int upgradeNo = getUpgradeNoFromDwelling(dwelling);
dwelling = getDwellingFromLevel(levelIndex, upgradeNo + 1);
}
bool isDwelling() const

View File

@@ -2088,8 +2088,8 @@ bool CGameHandler::buildStructure(ObjectInstanceID tid, BuildingID requestedID,
{
if(buildingID.isDwelling())
{
int level = BuildingID::getLevelFromDwelling(buildingID);
int upgradeNumber = BuildingID::getUpgradedFromDwelling(buildingID);
int level = BuildingID::getLevelIndexFromDwelling(buildingID);
int upgradeNumber = BuildingID::getUpgradeNoFromDwelling(buildingID);
if(upgradeNumber >= t->getTown()->creatures.at(level).size())
{