1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-11-06 09:09:40 +02:00

Merge remote-tracking branch 'upstream/develop' into battle-dialog

This commit is contained in:
nordsoft
2023-04-11 02:22:42 +04:00
186 changed files with 1814 additions and 1257 deletions

View File

@@ -101,7 +101,7 @@ BattleAction CBattleAI::activeStack( const CStack * stack )
try
{
if(stack->type->idNumber == CreatureID::CATAPULT)
if(stack->type->getId() == CreatureID::CATAPULT)
return useCatapult(stack);
if(stack->hasBonusOfType(Bonus::SIEGE_WEAPON) && stack->hasBonusOfType(Bonus::HEALER))
{
@@ -271,7 +271,7 @@ BattleAction CBattleAI::activeStack( const CStack * stack )
BattleAction CBattleAI::goTowardsNearest(const CStack * stack, std::vector<BattleHex> hexes) const
{
auto reachability = cb->getReachability(stack);
auto avHexes = cb->battleGetAvailableHexes(reachability, stack);
auto avHexes = cb->battleGetAvailableHexes(reachability, stack, true);
if(!avHexes.size() || !hexes.size()) //we are blocked or dest is blocked
{

View File

@@ -271,7 +271,7 @@ std::vector<const battle::Unit *> BattleExchangeEvaluator::getAdjacentUnits(cons
auto hexes = stack->getSurroundingHexes();
for(auto hex : hexes)
{
auto neighbor = cb->battleGetStackByPos(hex);
auto neighbor = cb->battleGetUnitByPos(hex);
if(neighbor && neighbor->unitSide() == stack->unitSide() && !vstd::contains(checkedStacks, neighbor))
{

View File

@@ -15,7 +15,7 @@ PotentialTargets::PotentialTargets(const battle::Unit * attacker, const Hypothet
{
auto attackerInfo = state.battleGetUnitByID(attacker->unitId());
auto reachability = state.getReachability(attackerInfo);
auto avHexes = state.battleGetAvailableHexes(reachability, attackerInfo);
auto avHexes = state.battleGetAvailableHexes(reachability, attackerInfo, true);
//FIXME: this should part of battleGetAvailableHexes
bool forceTarget = false;

View File

@@ -435,7 +435,7 @@ int64_t HypotheticBattle::getActualDamage(const DamageRange & damage, int32_t at
int64_t HypotheticBattle::getTreeVersion() const
{
return getBattleNode()->getTreeVersion() + bonusTreeVersion;
return getBonusBearer()->getTreeVersion() + bonusTreeVersion;
}
#if SCRIPTING_ENABLED

View File

@@ -1053,7 +1053,7 @@ void AIGateway::recruitCreatures(const CGDwelling * d, const CArmedInstance * re
int count = d->creatures[i].first;
CreatureID creID = d->creatures[i].second.back();
vstd::amin(count, cb->getResourceAmount() / VLC->creh->objects[creID]->cost);
vstd::amin(count, cb->getResourceAmount() / creID.toCreature()->getFullRecruitCost());
if(count > 0)
cb->recruitCreatures(d, recruiter, creID, count, i);
}
@@ -1068,7 +1068,7 @@ bool AIGateway::canRecruitAnyHero(const CGTownInstance * t) const
if(!t || !townHasFreeTavern(t))
return false;
if(cb->getResourceAmount(Res::GOLD) < GameConstants::HERO_GOLD_COST) //TODO: use ResourceManager
if(cb->getResourceAmount(EGameResID::GOLD) < GameConstants::HERO_GOLD_COST) //TODO: use ResourceManager
return false;
if(cb->getHeroesInfo().size() >= ALLOWED_ROAMING_HEROES)
return false;
@@ -1396,7 +1396,7 @@ void AIGateway::tryRealize(Goals::DigAtTile & g)
void AIGateway::tryRealize(Goals::Trade & g) //trade
{
if(cb->getResourceAmount((Res::ERes)g.resID) >= g.value) //goal is already fulfilled. Why we need this check, anyway?
if(cb->getResourceAmount(GameResID(g.resID)) >= g.value) //goal is already fulfilled. Why we need this check, anyway?
throw goalFulfilledException(sptr(g));
int accquiredResources = 0;
@@ -1405,10 +1405,10 @@ void AIGateway::tryRealize(Goals::Trade & g) //trade
if(const IMarket * m = IMarket::castFrom(obj, false))
{
auto freeRes = cb->getResourceAmount(); //trade only resources which are not reserved
for(auto it = Res::ResourceSet::nziterator(freeRes); it.valid(); it++)
for(auto it = ResourceSet::nziterator(freeRes); it.valid(); it++)
{
auto res = it->resType;
if(res == g.resID) //sell any other resource
if(res.getNum() == g.resID) //sell any other resource
continue;
int toGive, toGet;
@@ -1421,7 +1421,7 @@ void AIGateway::tryRealize(Goals::Trade & g) //trade
accquiredResources = static_cast<int>(toGet * (it->resVal / toGive));
logAi->debug("Traded %d of %s for %d of %s at %s", toGive, res, accquiredResources, g.resID, obj->getObjectName());
}
if (cb->getResourceAmount((Res::ERes)g.resID) >= g.value)
if (cb->getResourceAmount(GameResID(g.resID)))
throw goalFulfilledException(sptr(g)); //we traded all we needed
}

View File

@@ -20,6 +20,8 @@
#include "../../lib/GameSettings.h"
#include <vcmi/CreatureService.h>
namespace NKAI
{
@@ -278,8 +280,8 @@ creInfo infoFromDC(const dwellingContent & dc)
ci.creID = dc.second.size() ? dc.second.back() : CreatureID(-1); //should never be accessed
if (ci.creID != -1)
{
ci.cre = VLC->creh->objects[ci.creID].get();
ci.level = ci.cre->level; //this is cretaure tier, while tryRealize expects dwelling level. Ignore.
ci.cre = VLC->creatures()->getById(ci.creID);
ci.level = ci.cre->getLevel(); //this is creature tier, while tryRealize expects dwelling level. Ignore.
}
else
{
@@ -398,7 +400,7 @@ bool shouldVisit(const Nullkiller * ai, const CGHeroInstance * h, const CGObject
{
if(level.first
&& h->getSlotFor(CreatureID(c)) != SlotID()
&& ai->cb->getResourceAmount().canAfford(c.toCreature()->cost))
&& ai->cb->getResourceAmount().canAfford(c.toCreature()->getFullRecruitCost()))
{
return true;
}
@@ -411,7 +413,7 @@ bool shouldVisit(const Nullkiller * ai, const CGHeroInstance * h, const CGObject
{
for(auto slot : h->Slots())
{
if(slot.second->type->upgrades.size())
if(slot.second->type->hasUpgrades())
return true; //TODO: check price?
}
return false;
@@ -438,7 +440,7 @@ bool shouldVisit(const Nullkiller * ai, const CGHeroInstance * h, const CGObject
return false;
TResources myRes = ai->getFreeResources();
if(myRes[Res::GOLD] < 2000 || myRes[Res::GEMS] < 10)
if(myRes[EGameResID::GOLD] < 2000 || myRes[EGameResID::GEMS] < 10)
return false;
break;
}

View File

@@ -161,7 +161,7 @@ struct creInfo
{
int count;
CreatureID creID;
CCreature * cre;
const Creature * cre;
int level;
};
creInfo infoFromDC(const dwellingContent & dc);

View File

@@ -28,8 +28,8 @@ public:
StackUpgradeInfo(CreatureID initial, CreatureID upgraded, int count)
:initialCreature(initial), upgradedCreature(upgraded), count(count)
{
cost = (upgradedCreature.toCreature()->cost - initialCreature.toCreature()->cost) * count;
upgradeValue = (upgradedCreature.toCreature()->AIValue - initialCreature.toCreature()->AIValue) * count;
cost = (upgradedCreature.toCreature()->getFullRecruitCost() - initialCreature.toCreature()->getFullRecruitCost()) * count;
upgradeValue = (upgradedCreature.toCreature()->getAIValue() - initialCreature.toCreature()->getAIValue()) * count;
}
};
@@ -50,9 +50,10 @@ std::vector<SlotInfo> ArmyManager::getSortedSlots(const CCreatureSet * target, c
{
for(auto & i : armyPtr->Slots())
{
auto & slotInfp = creToPower[i.second->type];
auto cre = dynamic_cast<const CCreature*>(i.second->type);
auto & slotInfp = creToPower[cre];
slotInfp.creature = i.second->type;
slotInfp.creature = cre;
slotInfp.power += i.second->getPower();
slotInfp.count += i.second->count;
}
@@ -73,8 +74,8 @@ std::vector<SlotInfo>::iterator ArmyManager::getWeakestCreature(std::vector<Slot
{
auto weakest = boost::min_element(army, [](const SlotInfo & left, const SlotInfo & right) -> bool
{
if(left.creature->level != right.creature->level)
return left.creature->level < right.creature->level;
if(left.creature->getLevel() != right.creature->getLevel())
return left.creature->getLevel() < right.creature->getLevel();
return left.creature->Speed() > right.creature->Speed();
});
@@ -99,7 +100,7 @@ std::vector<SlotInfo> ArmyManager::getBestArmy(const IBonusBearer * armyCarrier,
for(auto & slot : sortedSlots)
{
alignmentMap[slot.creature->faction] += slot.power;
alignmentMap[slot.creature->getFactionIndex()] += slot.power;
}
std::set<TFaction> allowedFactions;
@@ -133,13 +134,13 @@ std::vector<SlotInfo> ArmyManager::getBestArmy(const IBonusBearer * armyCarrier,
for(auto & slot : sortedSlots)
{
if(vstd::contains(allowedFactions, slot.creature->faction))
if(vstd::contains(allowedFactions, slot.creature->getFactionIndex()))
{
auto slotID = newArmyInstance.getSlotFor(slot.creature);
if(slotID.validSlot())
{
newArmyInstance.setCreature(slotID, slot.creature->idNumber, slot.count);
newArmyInstance.setCreature(slotID, slot.creature->getId(), slot.count);
newArmy.push_back(slot);
}
}
@@ -217,7 +218,7 @@ std::shared_ptr<CCreatureSet> ArmyManager::getArmyAvailableToBuyAsCCreatureSet(
if(!ci.count || ci.creID == -1)
continue;
vstd::amin(ci.count, availableRes / ci.cre->cost); //max count we can afford
vstd::amin(ci.count, availableRes / ci.cre->getFullRecruitCost()); //max count we can afford
if(!ci.count)
continue;
@@ -228,7 +229,7 @@ std::shared_ptr<CCreatureSet> ArmyManager::getArmyAvailableToBuyAsCCreatureSet(
break;
army->setCreature(dst, ci.creID, ci.count);
availableRes -= ci.cre->cost * ci.count;
availableRes -= ci.cre->getFullRecruitCost() * ci.count;
}
return army;
@@ -244,7 +245,7 @@ ui64 ArmyManager::howManyReinforcementsCanBuy(
for(const creInfo & ci : army)
{
aivalue += ci.count * ci.cre->AIValue;
aivalue += ci.count * ci.cre->getAIValue();
}
return aivalue;
@@ -279,14 +280,14 @@ std::vector<creInfo> ArmyManager::getArmyAvailableToBuy(
freeHeroSlots--; //new slot will be occupied
}
vstd::amin(ci.count, availableRes / ci.cre->cost); //max count we can afford
vstd::amin(ci.count, availableRes / ci.cre->getFullRecruitCost()); //max count we can afford
if(!ci.count)
continue;
ci.level = i; //this is important for Dungeon Summoning Portal
creaturesInDwellings.push_back(ci);
availableRes -= ci.cre->cost * ci.count;
availableRes -= ci.cre->getFullRecruitCost() * ci.count;
}
return creaturesInDwellings;
@@ -308,7 +309,7 @@ ui64 ArmyManager::howManyReinforcementsCanGet(const IBonusBearer * armyCarrier,
uint64_t ArmyManager::evaluateStackPower(const CCreature * creature, int count) const
{
return creature->AIValue * count;
return creature->getAIValue() * count;
}
SlotInfo ArmyManager::getTotalCreaturesAvailable(CreatureID creatureID) const
@@ -378,12 +379,12 @@ std::vector<StackUpgradeInfo> ArmyManager::getHillFortUpgrades(const CCreatureSe
CreatureID strongestUpgrade = *vstd::minElementByFun(possibleUpgrades, [](CreatureID cre) -> uint64_t
{
return cre.toCreature()->AIValue;
return cre.toCreature()->getAIValue();
});
StackUpgradeInfo upgrade = StackUpgradeInfo(initial, strongestUpgrade, creature.second->count);
if(initial.toCreature()->level == 1)
if(initial.toCreature()->getLevel() == 1)
upgrade.cost = TResources();
upgrades.push_back(upgrade);
@@ -417,7 +418,7 @@ std::vector<StackUpgradeInfo> ArmyManager::getDwellingUpgrades(const CCreatureSe
CreatureID strongestUpgrade = *vstd::minElementByFun(possibleUpgrades, [](CreatureID cre) -> uint64_t
{
return cre.toCreature()->AIValue;
return cre.toCreature()->getAIValue();
});
StackUpgradeInfo upgrade = StackUpgradeInfo(initial, strongestUpgrade, creature.second->count);
@@ -488,7 +489,7 @@ ArmyUpgradeInfo ArmyManager::calculateCreaturesUpgrade(
upgradedArmy.power = evaluateStackPower(upgradedArmy.creature, upgradedArmy.count);
auto slotToReplace = std::find_if(result.resultingArmy.begin(), result.resultingArmy.end(), [&](const SlotInfo & slot) -> bool {
return slot.count == upgradedArmy.count && slot.creature->idNumber == upgrade.initialCreature;
return slot.count == upgradedArmy.count && slot.creature->getId() == upgrade.initialCreature;
});
resourcesLeft -= upgrade.cost;

View File

@@ -93,9 +93,9 @@ void BuildAnalyzer::updateOtherBuildings(TownDevelopmentInfo & developmentInfo)
int32_t convertToGold(const TResources & res)
{
return res[Res::GOLD]
+ 75 * (res[Res::WOOD] + res[Res::ORE])
+ 125 * (res[Res::GEMS] + res[Res::CRYSTAL] + res[Res::MERCURY] + res[Res::SULFUR]);
return res[EGameResID::GOLD]
+ 75 * (res[EGameResID::WOOD] + res[EGameResID::ORE])
+ 125 * (res[EGameResID::GEMS] + res[EGameResID::CRYSTAL] + res[EGameResID::MERCURY] + res[EGameResID::SULFUR]);
}
TResources BuildAnalyzer::getResourcesRequiredNow() const
@@ -164,8 +164,8 @@ void BuildAnalyzer::update()
}
else
{
goldPreasure = ai->getLockedResources()[Res::GOLD] / 10000.0f
+ (float)armyCost[Res::GOLD] / (1 + ai->getFreeGold() + (float)dailyIncome[Res::GOLD] * 7.0f);
goldPreasure = ai->getLockedResources()[EGameResID::GOLD] / 10000.0f
+ (float)armyCost[EGameResID::GOLD] / (1 + ai->getFreeGold() + (float)dailyIncome[EGameResID::GOLD] * 7.0f);
}
logAi->trace("Gold preasure: %f", goldPreasure);
@@ -280,7 +280,7 @@ void BuildAnalyzer::updateDailyIncome()
if(mine)
{
dailyIncome[mine->producedResource] += mine->producedQuantity;
dailyIncome[mine->producedResource.getNum()] += mine->producedQuantity;
}
}
@@ -355,10 +355,10 @@ BuildingInfo::BuildingInfo(
if(creature)
{
creatureGrows = creature->growth;
creatureID = creature->idNumber;
creatureCost = creature->cost;
creatureLevel = creature->level;
creatureGrows = creature->getGrowth();
creatureID = creature->getId();
creatureCost = creature->getFullRecruitCost();
creatureLevel = creature->getLevel();
baseCreatureID = baseCreature;
if(exists)
@@ -367,7 +367,7 @@ BuildingInfo::BuildingInfo(
}
else
{
creatureGrows = creature->growth;
creatureGrows = creature->getGrowth();
if(town->hasBuilt(BuildingID::CASTLE))
creatureGrows *= 2;

View File

@@ -58,7 +58,7 @@ Goals::TGoalVec BuildingBehavior::decompose() const
{
for(auto & buildingInfo : developmentInfo.toBuild)
{
if(goldPreasure < MAX_GOLD_PEASURE || buildingInfo.dailyIncome[Res::GOLD] > 0)
if(goldPreasure < MAX_GOLD_PEASURE || buildingInfo.dailyIncome[EGameResID::GOLD] > 0)
{
if(buildingInfo.notEnoughRes)
{

View File

@@ -162,7 +162,7 @@ void DefenceBehavior::evaluateDefence(Goals::TGoalVec & tasks, const CGTownInsta
if(!town->visitingHero
&& town->hasBuilt(BuildingID::TAVERN)
&& cb->getResourceAmount(Res::GOLD) > GameConstants::HERO_GOLD_COST)
&& cb->getResourceAmount(EGameResID::GOLD) > GameConstants::HERO_GOLD_COST)
{
auto heroesInTavern = cb->getAvailableHeroes(town);

View File

@@ -69,7 +69,7 @@ Goals::TGoalVec RecruitHeroBehavior::decompose() const
}
if(cb->getHeroesInfo().size() < cb->getTownsInfo().size() + 1
|| (ai->nullkiller->getFreeResources()[Res::GOLD] > 10000
|| (ai->nullkiller->getFreeResources()[EGameResID::GOLD] > 10000
&& ai->nullkiller->buildAnalyzer->getGoldPreasure() < MAX_GOLD_PEASURE))
{
tasks.push_back(Goals::sptr(Goals::RecruitHero(town).setpriority(3)));

View File

@@ -76,7 +76,7 @@ bool needToRecruitHero(const CGTownInstance * startupTown)
for(auto obj : ai->nullkiller->objectClusterizer->getNearbyObjects())
{
if((obj->ID == Obj::RESOURCE && obj->subID == Res::GOLD)
if((obj->ID == Obj::RESOURCE && obj->subID == GameResID(EGameResID::GOLD))
|| obj->ID == Obj::TREASURE_CHEST
|| obj->ID == Obj::CAMPFIRE
|| obj->ID == Obj::WATER_WHEEL)

View File

@@ -65,13 +65,13 @@ armyStructure evaluateArmyStructure(const CArmedInstance * army)
for(auto s : army->Slots())
{
bool walker = true;
const CCreature * creature = s.second->type;
if(creature->hasBonus(selectorSHOOTER, keySHOOTER))
auto bearer = s.second->getType()->getBonusBearer();
if(bearer->hasBonus(selectorSHOOTER, keySHOOTER))
{
shootersStrength += s.second->getPower();
walker = false;
}
if(creature->hasBonus(selectorFLYING, keyFLYING))
if(bearer->hasBonus(selectorFLYING, keyFLYING))
{
flyersStrength += s.second->getPower();
walker = false;
@@ -79,7 +79,7 @@ armyStructure evaluateArmyStructure(const CArmedInstance * army)
if(walker)
walkersStrength += s.second->getPower();
vstd::amax(maxSpeed, creature->valOfBonuses(selectorSTACKS_SPEED, keySTACKS_SPEED));
vstd::amax(maxSpeed, bearer->valOfBonuses(selectorSTACKS_SPEED, keySTACKS_SPEED));
}
armyStructure as;
as.walkers = static_cast<float>(walkersStrength / totalStrength);

View File

@@ -85,7 +85,7 @@ public:
void unlockHero(const CGHeroInstance * hero) { lockedHeroes.erase(hero); }
bool arePathHeroesLocked(const AIPath & path) const;
TResources getFreeResources() const;
int32_t getFreeGold() const { return getFreeResources()[Res::GOLD]; }
int32_t getFreeGold() const { return getFreeResources()[EGameResID::GOLD]; }
void lockResources(const TResources & res);
const TResources & getLockedResources() const { return lockedResources; }

View File

@@ -148,14 +148,15 @@ uint64_t getCreatureBankArmyReward(const CGObjectInstance * target, const CGHero
for (auto c : creatures)
{
//Only if hero has slot for this creature in the army
if (hero->getSlotFor(c.data.type).validSlot())
auto ccre = dynamic_cast<const CCreature*>(c.data.type);
if (hero->getSlotFor(ccre).validSlot())
{
result += (c.data.type->AIValue * c.data.count) * c.chance;
result += (c.data.type->getAIValue() * c.data.count) * c.chance;
}
else
{
//we will need to discard the weakest stack
result += (c.data.type->AIValue * c.data.count - weakestStackPower) * c.chance;
result += (c.data.type->getAIValue() * c.data.count - weakestStackPower) * c.chance;
}
}
result /= 100; //divide by total chance
@@ -173,11 +174,11 @@ uint64_t getDwellingScore(CCallback * cb, const CGObjectInstance * target, bool
if(creLevel.first && creLevel.second.size())
{
auto creature = creLevel.second.back().toCreature();
auto creaturesAreFree = creature->level == 1;
if(!creaturesAreFree && checkGold && !cb->getResourceAmount().canAfford(creature->cost * creLevel.first))
auto creaturesAreFree = creature->getLevel() == 1;
if(!creaturesAreFree && checkGold && !cb->getResourceAmount().canAfford(creature->getFullRecruitCost() * creLevel.first))
continue;
score += creature->AIValue * creLevel.first;
score += creature->getAIValue() * creLevel.first;
}
}
@@ -194,9 +195,9 @@ int getDwellingArmyCost(const CGObjectInstance * target)
if(creLevel.first && creLevel.second.size())
{
auto creature = creLevel.second.back().toCreature();
auto creaturesAreFree = creature->level == 1;
auto creaturesAreFree = creature->getLevel() == 1;
if(!creaturesAreFree)
cost += creature->cost[Res::GOLD] * creLevel.first;
cost += creature->getRecruitCost(EGameResID::GOLD) * creLevel.first;
}
}
@@ -300,7 +301,7 @@ int RewardEvaluator::getGoldCost(const CGObjectInstance * target, const CGHeroIn
switch(target->ID)
{
case Obj::HILL_FORT:
return ai->armyManager->calculateCreaturesUpgrade(army, target, ai->cb->getResourceAmount()).upgradeCost[Res::GOLD];
return ai->armyManager->calculateCreaturesUpgrade(army, target, ai->cb->getResourceAmount()).upgradeCost[EGameResID::GOLD];
case Obj::SCHOOL_OF_MAGIC:
case Obj::SCHOOL_OF_WAR:
return 1000;
@@ -375,12 +376,12 @@ float RewardEvaluator::getStrategicalValue(const CGObjectInstance * target) cons
switch(target->ID)
{
case Obj::MINE:
return target->subID == Res::GOLD
return target->subID == GameResID(EGameResID::GOLD)
? 0.5f
: 0.4f * getTotalResourceRequirementStrength(target->subID) + 0.1f * getResourceRequirementStrength(target->subID);
case Obj::RESOURCE:
return target->subID == Res::GOLD
return target->subID == GameResID(EGameResID::GOLD)
? 0
: 0.2f * getTotalResourceRequirementStrength(target->subID) + 0.4f * getResourceRequirementStrength(target->subID);
@@ -391,7 +392,7 @@ float RewardEvaluator::getStrategicalValue(const CGObjectInstance * target) cons
for (TResources::nziterator it (resourceReward); it.valid(); it++)
{
//Evaluate resources used for construction. Gold is evaluated separately.
if (it->resType != Res::GOLD)
if (it->resType != EGameResID::GOLD)
{
sum += 0.1f * getResourceRequirementStrength(it->resType);
}
@@ -502,7 +503,7 @@ int32_t getArmyCost(const CArmedInstance * army)
for(auto stack : army->Slots())
{
value += stack.second->getCreatureID().toCreature()->cost[Res::GOLD] * stack.second->count;
value += stack.second->getCreatureID().toCreature()->getRecruitCost(EGameResID::GOLD) * stack.second->count;
}
return value;
@@ -517,7 +518,7 @@ int32_t RewardEvaluator::getGoldReward(const CGObjectInstance * target, const CG
const int dailyIncomeMultiplier = 5;
const float enemyArmyEliminationGoldRewardRatio = 0.2f;
const int32_t heroEliminationBonus = GameConstants::HERO_GOLD_COST / 2;
auto isGold = target->subID == Res::GOLD; // TODO: other resorces could be sold but need to evaluate market power
auto isGold = target->subID == GameResID(EGameResID::GOLD); // TODO: other resorces could be sold but need to evaluate market power
switch(target->ID)
{
@@ -540,7 +541,7 @@ int32_t RewardEvaluator::getGoldReward(const CGObjectInstance * target, const CG
case Obj::WAGON:
return 100;
case Obj::CREATURE_BANK:
return getCreatureBankResources(target, hero)[Res::GOLD];
return getCreatureBankResources(target, hero)[EGameResID::GOLD];
case Obj::CRYPT:
case Obj::DERELICT_SHIP:
return 3000;
@@ -627,7 +628,7 @@ private:
continue;
auto creature = creatureInfo.second.back().toCreature();
result += creature->AIValue * town->getGrowthInfo(creature->getLevel() - 1).totalGrowth();
result += creature->getAIValue() * town->getGrowthInfo(creature->getLevel() - 1).totalGrowth();
}
return result;
@@ -644,7 +645,7 @@ public:
auto & treat = defendTown.getTreat();
auto armyIncome = townArmyIncome(town);
auto dailyIncome = town->dailyIncome()[Res::GOLD];
auto dailyIncome = town->dailyIncome()[EGameResID::GOLD];
auto strategicalValue = std::sqrt(armyIncome / 20000.0f) + dailyIncome / 3000.0f;
@@ -804,10 +805,10 @@ public:
Goals::BuildThis & buildThis = dynamic_cast<Goals::BuildThis &>(*task);
auto & bi = buildThis.buildingInfo;
evaluationContext.goldReward += 7 * bi.dailyIncome[Res::GOLD] / 2; // 7 day income but half we already have
evaluationContext.goldReward += 7 * bi.dailyIncome[EGameResID::GOLD] / 2; // 7 day income but half we already have
evaluationContext.heroRole = HeroRole::MAIN;
evaluationContext.movementCostByRole[evaluationContext.heroRole] += bi.prerequisitesCount;
evaluationContext.goldCost += bi.buildCostWithPrerequisits[Res::GOLD];
evaluationContext.goldCost += bi.buildCostWithPrerequisits[EGameResID::GOLD];
if(bi.creatureID != CreatureID::NONE)
{
@@ -921,7 +922,7 @@ float PriorityEvaluator::evaluate(Goals::TSubgoal task)
closestHeroRatioVariable->setValue(evaluationContext.closestWayRatio);
strategicalValueVariable->setValue(evaluationContext.strategicalValue);
goldPreasureVariable->setValue(ai->buildAnalyzer->getGoldPreasure());
goldCostVariable->setValue(evaluationContext.goldCost / ((float)ai->getFreeResources()[Res::GOLD] + (float)ai->buildAnalyzer->getDailyIncome()[Res::GOLD] + 1.0f));
goldCostVariable->setValue(evaluationContext.goldCost / ((float)ai->getFreeResources()[EGameResID::GOLD] + (float)ai->buildAnalyzer->getDailyIncome()[EGameResID::GOLD] + 1.0f));
turnVariable->setValue(evaluationContext.turn);
fearVariable->setValue(evaluationContext.enemyHeroDangerRatio);

View File

@@ -60,7 +60,7 @@ std::string AbstractGoal::toString() const //TODO: virtualize
desc = "GATHER TROOPS";
break;
case GET_ART_TYPE:
desc = "GET ARTIFACT OF TYPE " + VLC->arth->objects[aid]->getNameTranslated();
desc = "GET ARTIFACT OF TYPE " + VLC->artifacts()->getByIndex(aid)->getNameTranslated();
break;
case DIG_AT_TILE:
desc = "DIG AT TILE " + tile.toString();

View File

@@ -57,12 +57,12 @@ void BuyArmy::accept(AIGateway * ai)
if(objid != -1 && ci.creID != objid)
continue;
vstd::amin(ci.count, res / ci.cre->cost);
vstd::amin(ci.count, res / ci.cre->getFullRecruitCost());
if(ci.count)
{
cb->recruitCreatures(town, town->getUpperArmy(), ci.creID, ci.count, ci.level);
valueBought += ci.count * ci.cre->AIValue;
valueBought += ci.count * ci.cre->getAIValue();
}
}

View File

@@ -214,7 +214,7 @@ TGoalVec CompleteQuest::missionResources() const
for(int i = 0; i < q.quest->m7resources.size(); ++i)
{
if(q.quest->m7resources[i])
solutions.push_back(sptr(CollectRes(i, q.quest->m7resources[i])));
solutions.push_back(sptr(CollectRes(static_cast<EGameResID>(i), q.quest->m7resources[i])));
}
}
}

View File

@@ -162,7 +162,7 @@ TGoalVec GatherArmy::getAllPossibleSubgoals()
for(auto & creatureID : creLevel.second)
{
auto creature = VLC->creh->creatures[creatureID];
if(ai->ah->freeResources().canAfford(creature->cost))
if(ai->ah->freeResources().canAfford(creature->getFullRecruitCost()))
objs.push_back(obj); //TODO: reserve resources?
}
}

View File

@@ -27,10 +27,10 @@ namespace Goals
: CGoal(Goals::TRADE)
{
}
Trade(int rid, int val, int Objid)
Trade(GameResID rid, int val, int Objid)
: CGoal(Goals::TRADE)
{
resID = rid;
resID = rid.getNum();
value = val;
objid = Objid;
}

View File

@@ -23,7 +23,7 @@ using namespace Goals;
ArmyUpgrade::ArmyUpgrade(const AIPath & upgradePath, const CGObjectInstance * upgrader, const ArmyUpgradeInfo & upgrade)
: CGoal(Goals::ARMY_UPGRADE), upgrader(upgrader), upgradeValue(upgrade.upgradeValue),
initialValue(upgradePath.heroArmy->getArmyStrength()), goldCost(upgrade.upgradeCost[Res::GOLD])
initialValue(upgradePath.heroArmy->getArmyStrength()), goldCost(upgrade.upgradeCost[EGameResID::GOLD])
{
sethero(upgradePath.targetHero);
}

View File

@@ -350,7 +350,7 @@ HeroExchangeArmy * HeroExchangeMap::tryUpgrade(
{
auto targetSlot = target->getFreeSlot();
target->addToSlot(targetSlot, slotInfo.creature->idNumber, TQuantity(slotInfo.count));
target->addToSlot(targetSlot, slotInfo.creature->getId(), TQuantity(slotInfo.count));
}
resources -= upgradeInfo.upgradeCost;
@@ -372,10 +372,10 @@ HeroExchangeArmy * HeroExchangeMap::tryUpgrade(
for(auto & creatureToBuy : buyArmy)
{
auto targetSlot = target->getSlotFor(creatureToBuy.cre);
auto targetSlot = target->getSlotFor(dynamic_cast<const CCreature*>(creatureToBuy.cre));
target->addToSlot(targetSlot, creatureToBuy.creID, creatureToBuy.count);
target->armyCost += creatureToBuy.cre->cost * creatureToBuy.count;
target->armyCost += creatureToBuy.cre->getFullRecruitCost() * creatureToBuy.count;
target->requireBuyArmy = true;
}
}
@@ -399,7 +399,7 @@ HeroExchangeArmy * HeroExchangeMap::pickBestCreatures(const CCreatureSet * army1
{
auto targetSlot = target->getFreeSlot();
target->addToSlot(targetSlot, slotInfo.creature->idNumber, TQuantity(slotInfo.count));
target->addToSlot(targetSlot, slotInfo.creature->getId(), TQuantity(slotInfo.count));
}
return target;
@@ -420,7 +420,7 @@ DwellingActor::DwellingActor(const CGDwelling * dwelling, uint64_t chainMask, bo
{
for(auto & slot : creatureSet->Slots())
{
armyCost += slot.second->getCreatureID().toCreature()->cost * slot.second->count;
armyCost += slot.second->getCreatureID().toCreature()->getFullRecruitCost() * slot.second->count;
}
}
@@ -454,7 +454,7 @@ CCreatureSet * DwellingActor::getDwellingCreatures(const CGDwelling * dwelling,
auto creature = creatureInfo.second.back().toCreature();
dwellingCreatures->addToSlot(
dwellingCreatures->getSlotFor(creature),
creature->idNumber,
creature->getId(),
TQuantity(creatureInfo.first));
}

View File

@@ -80,7 +80,7 @@ static bool willSecondHexBlockMoreEnemyShooters(const BattleHex &h1, const Battl
for(int i = 0; i < 2; i++)
{
for (auto & neighbour : (i ? h2 : h1).neighbouringTiles())
if(const CStack * s = cbc->battleGetStackByPos(neighbour))
if(const auto * s = cbc->battleGetUnitByPos(neighbour))
if(s->isShooter())
shooters[i]++;
}
@@ -95,7 +95,7 @@ BattleAction CStupidAI::activeStack( const CStack * stack )
ReachabilityInfo dists = cb->getReachability(stack);
std::vector<EnemyInfo> enemiesShootable, enemiesReachable, enemiesUnreachable;
if(stack->type->idNumber == CreatureID::CATAPULT)
if(stack->type->getId() == CreatureID::CATAPULT)
{
BattleAction attack;
static const std::vector<int> wallHexes = {50, 183, 182, 130, 78, 29, 12, 95};
@@ -120,7 +120,7 @@ BattleAction CStupidAI::activeStack( const CStack * stack )
}
else
{
std::vector<BattleHex> avHexes = cb->battleGetAvailableHexes(stack);
std::vector<BattleHex> avHexes = cb->battleGetAvailableHexes(stack, true);
for (BattleHex hex : avHexes)
{
@@ -238,7 +238,7 @@ void CStupidAI::print(const std::string &text) const
BattleAction CStupidAI::goTowards(const CStack * stack, std::vector<BattleHex> hexes) const
{
auto reachability = cb->getReachability(stack);
auto avHexes = cb->battleGetAvailableHexes(reachability, stack);
auto avHexes = cb->battleGetAvailableHexes(reachability, stack, false);
if(!avHexes.size() || !hexes.size()) //we are blocked or dest is blocked
{

View File

@@ -230,8 +230,8 @@ creInfo infoFromDC(const dwellingContent & dc)
ci.creID = dc.second.size() ? dc.second.back() : CreatureID(-1); //should never be accessed
if (ci.creID != -1)
{
ci.cre = VLC->creh->objects[ci.creID];
ci.level = ci.cre->level; //this is cretaure tier, while tryRealize expects dwelling level. Ignore.
ci.cre = VLC->creatures()->getById(ci.creID);
ci.level = ci.cre->getLevel(); //this is creature tier, while tryRealize expects dwelling level. Ignore.
}
else
{

View File

@@ -152,7 +152,7 @@ struct creInfo
{
int count;
CreatureID creID;
CCreature * cre;
const Creature * cre;
int level;
};
creInfo infoFromDC(const dwellingContent & dc);

View File

@@ -36,9 +36,10 @@ std::vector<SlotInfo> ArmyManager::getSortedSlots(const CCreatureSet * target, c
{
for(auto & i : armyPtr->Slots())
{
auto & slotInfp = creToPower[i.second->type];
auto cre = dynamic_cast<const CCreature*>(i.second->type);
auto & slotInfp = creToPower[cre];
slotInfp.creature = i.second->type;
slotInfp.creature = cre;
slotInfp.power += i.second->getPower();
slotInfp.count += i.second->count;
}
@@ -59,8 +60,8 @@ std::vector<SlotInfo>::iterator ArmyManager::getWeakestCreature(std::vector<Slot
{
auto weakest = boost::min_element(army, [](const SlotInfo & left, const SlotInfo & right) -> bool
{
if(left.creature->level != right.creature->level)
return left.creature->level < right.creature->level;
if(left.creature->getLevel() != right.creature->getLevel())
return left.creature->getLevel() < right.creature->getLevel();
return left.creature->Speed() > right.creature->Speed();
});
@@ -120,7 +121,7 @@ ui64 ArmyManager::howManyReinforcementsCanBuy(const CCreatureSet * h, const CGDw
if(!ci.count || ci.creID == -1)
continue;
vstd::amin(ci.count, availableRes / ci.cre->cost); //max count we can afford
vstd::amin(ci.count, availableRes / ci.cre->getFullRecruitCost()); //max count we can afford
if(ci.count && ci.creID != -1) //valid creature at this level
{
@@ -135,8 +136,8 @@ ui64 ArmyManager::howManyReinforcementsCanBuy(const CCreatureSet * h, const CGDw
}
//we found matching occupied or free slot
aivalue += ci.count * ci.cre->AIValue;
availableRes -= ci.cre->cost * ci.count;
aivalue += ci.count * ci.cre->getAIValue();
availableRes -= ci.cre->getFullRecruitCost() * ci.count;
}
}

View File

@@ -64,13 +64,13 @@ armyStructure evaluateArmyStructure(const CArmedInstance * army)
for(auto s : army->Slots())
{
bool walker = true;
const CCreature * creature = s.second->type;
if(creature->hasBonus(selectorSHOOTER, keySHOOTER))
auto bearer = s.second->getType()->getBonusBearer();
if(bearer->hasBonus(selectorSHOOTER, keySHOOTER))
{
shootersStrength += s.second->getPower();
walker = false;
}
if(creature->hasBonus(selectorFLYING, keyFLYING))
if(bearer->hasBonus(selectorFLYING, keyFLYING))
{
flyersStrength += s.second->getPower();
walker = false;
@@ -78,7 +78,7 @@ armyStructure evaluateArmyStructure(const CArmedInstance * army)
if(walker)
walkersStrength += s.second->getPower();
vstd::amax(maxSpeed, creature->valOfBonuses(selectorSTACKS_SPEED, keySTACKS_SPEED));
vstd::amax(maxSpeed, bearer->valOfBonuses(selectorSTACKS_SPEED, keySTACKS_SPEED));
}
armyStructure as;
as.walkers = static_cast<float>(walkersStrength / totalStrength);

View File

@@ -35,7 +35,7 @@ TSubgoal BuyArmy::whatToDoToAchieve()
{
//TODO: calculate the actual cost of units instead
TResources price;
price[Res::GOLD] = static_cast<int>(value * 0.4f); //some approximate value
price[EGameResID::GOLD] = static_cast<int>(value * 0.4f); //some approximate value
return ai->ah->whatToDo(price, iAmElementar()); //buy right now or gather resources
}

View File

@@ -46,7 +46,7 @@ TGoalVec CollectRes::getAllPossibleSubgoals()
switch (obj->ID.num)
{
case Obj::TREASURE_CHEST:
return resID == Res::GOLD;
return resID == GameResID(EGameResID::GOLD);
break;
case Obj::RESOURCE:
return obj->subID == resID;
@@ -59,24 +59,24 @@ TGoalVec CollectRes::getAllPossibleSubgoals()
return true; //contains all resources
break;
case Obj::WINDMILL:
switch (resID)
switch (GameResID(resID).toEnum())
{
case Res::GOLD:
case Res::WOOD:
case EGameResID::GOLD:
case EGameResID::WOOD:
return false;
}
break;
case Obj::WATER_WHEEL:
if (resID != Res::GOLD)
if (resID != GameResID(EGameResID::GOLD))
return false;
break;
case Obj::MYSTICAL_GARDEN:
if ((resID != Res::GOLD) && (resID != Res::GEMS))
if ((resID != GameResID(EGameResID::GOLD)) && (resID != GameResID(EGameResID::GEMS)))
return false;
break;
case Obj::LEAN_TO:
case Obj::WAGON:
if (resID != Res::GOLD)
if (resID != GameResID(EGameResID::GOLD))
return false;
break;
default:
@@ -170,12 +170,12 @@ TSubgoal CollectRes::whatToDoToTrade()
const IMarket * m = markets.back();
//attempt trade at back (best prices)
int howManyCanWeBuy = 0;
for (Res::ERes i = Res::WOOD; i <= Res::GOLD; vstd::advance(i, 1))
for (auto i = EGameResID::WOOD; i <= EGameResID::GOLD; vstd::advance(i, 1))
{
if (i == resID)
if (GameResID(i) == resID)
continue;
int toGive = -1, toReceive = -1;
m->getOffer(i, resID, toGive, toReceive, EMarketMode::RESOURCE_RESOURCE);
m->getOffer(GameResID(i), resID, toGive, toReceive, EMarketMode::RESOURCE_RESOURCE);
assert(toGive > 0 && toReceive > 0);
howManyCanWeBuy += toReceive * (ai->ah->freeResources()[i] / toGive);
}
@@ -191,7 +191,7 @@ TSubgoal CollectRes::whatToDoToTrade()
}
else //either it's our town, or we have hero there
{
return sptr(Trade(resID, value, objid).setisElementar(true)); //we can do this immediately
return sptr(Trade(static_cast<EGameResID>(resID), value, objid).setisElementar(true)); //we can do this immediately
}
}
}

View File

@@ -24,10 +24,10 @@ namespace Goals
: CGoal(Goals::COLLECT_RES)
{
}
CollectRes(int rid, int val)
CollectRes(GameResID rid, int val)
: CGoal(Goals::COLLECT_RES)
{
resID = rid;
resID = rid.getNum();
value = val;
priority = 2;
}

View File

@@ -172,7 +172,7 @@ TGoalVec CompleteQuest::missionArmy() const
for(auto creature : q.quest->m6creatures)
{
solutions.push_back(sptr(GatherTroops(creature.type->idNumber, creature.count)));
solutions.push_back(sptr(GatherTroops(creature.type->getId(), creature.count)));
}
return solutions;
@@ -235,7 +235,7 @@ TGoalVec CompleteQuest::missionResources() const
for(int i = 0; i < q.quest->m7resources.size(); ++i)
{
if(q.quest->m7resources[i])
solutions.push_back(sptr(CollectRes(i, q.quest->m7resources[i])));
solutions.push_back(sptr(CollectRes(static_cast<EGameResID>(i), q.quest->m7resources[i])));
}
}
}

View File

@@ -159,7 +159,7 @@ TGoalVec GatherArmy::getAllPossibleSubgoals()
for(auto & creatureID : creLevel.second)
{
auto creature = VLC->creh->objects[creatureID];
if(ai->ah->freeResources().canAfford(creature->cost))
if(ai->ah->freeResources().canAfford(creature->getFullRecruitCost()))
objs.push_back(obj); //TODO: reserve resources?
}
}

View File

@@ -93,21 +93,21 @@ TGoalVec GatherTroops::getAllPossibleSubgoals()
continue;
}
auto creature = VLC->creh->objects[objid];
if(t->subID == creature->faction) //TODO: how to force AI to build unupgraded creatures? :O
auto creature = VLC->creatures()->getByIndex(objid);
if(t->subID == creature->getFactionIndex()) //TODO: how to force AI to build unupgraded creatures? :O
{
auto creatures = vstd::tryAt(t->town->creatures, creature->level - 1);
auto creatures = vstd::tryAt(t->town->creatures, creature->getLevel() - 1);
if(!creatures)
continue;
int upgradeNumber = vstd::find_pos(*creatures, creature->idNumber);
int upgradeNumber = vstd::find_pos(*creatures, creature->getId());
if(upgradeNumber < 0)
continue;
BuildingID bid(BuildingID::DWELL_FIRST + creature->level - 1 + upgradeNumber * GameConstants::CREATURES_PER_TOWN);
if(t->hasBuilt(bid) && ai->ah->freeResources().canAfford(creature->cost)) //this assumes only creatures with dwellings are assigned to faction
BuildingID bid(BuildingID::DWELL_FIRST + creature->getLevel() - 1 + upgradeNumber * GameConstants::CREATURES_PER_TOWN);
if(t->hasBuilt(bid) && ai->ah->freeResources().canAfford(creature->getFullRecruitCost())) //this assumes only creatures with dwellings are assigned to faction
{
solutions.push_back(sptr(BuyArmy(t, creature->AIValue * this->value).setobjid(objid)));
solutions.push_back(sptr(BuyArmy(t, creature->getAIValue() * this->value).setobjid(objid)));
}
/*else //disable random building requests for now - this code needs to know a lot of town/resource context to do more good than harm
{
@@ -129,7 +129,7 @@ TGoalVec GatherTroops::getAllPossibleSubgoals()
{
for(auto type : creature.second)
{
if(type == objid && ai->ah->freeResources().canAfford(VLC->creh->objects[type]->cost))
if(type == objid && ai->ah->freeResources().canAfford(VLC->creatures()->getById(type)->getFullRecruitCost()))
vstd::concatenate(solutions, ai->ah->howToVisitObj(obj));
}
}

View File

@@ -33,6 +33,6 @@ TSubgoal RecruitHero::whatToDoToAchieve()
return sptr(BuildThis(BuildingID::TAVERN).setpriority(2));
TResources res;
res[Res::GOLD] = GameConstants::HERO_GOLD_COST;
res[EGameResID::GOLD] = GameConstants::HERO_GOLD_COST;
return ai->ah->whatToDo(res, iAmElementar()); //either buy immediately, or collect res
}

View File

@@ -24,10 +24,10 @@ namespace Goals
: CGoal(Goals::TRADE)
{
}
Trade(int rid, int val, int Objid)
Trade(GameResID rid, int val, int Objid)
: CGoal(Goals::TRADE)
{
resID = rid;
resID = rid.getNum();
value = val;
objid = Objid;
priority = 3; //trading is instant, but picking resources is free

View File

@@ -154,7 +154,7 @@ TSubgoal Win::whatToDoToAchieve()
case EventCondition::HAVE_RESOURCES:
//TODO mines? piles? marketplace?
//save?
return sptr(CollectRes(static_cast<Res::ERes>(goal.objectType), goal.value));
return sptr(CollectRes(static_cast<EGameResID>(goal.objectType), goal.value));
case EventCondition::HAVE_CREATURES:
return sptr(GatherTroops(goal.objectType, goal.value));
case EventCondition::TRANSPORT:

View File

@@ -73,8 +73,8 @@ boost::optional<int> MapObjectsEvaluator::getObjectValue(const CGObjectInstance
{
for(auto & creatureID : creLevel.second)
{
auto creature = VLC->creh->objects[creatureID];
aiValue += (creature->AIValue * creature->growth);
auto creature = VLC->creatures()->getById(creatureID);
aiValue += (creature->getAIValue() * creature->getGrowth());
}
}
return aiValue;

View File

@@ -58,15 +58,15 @@ TResources ResourceManager::estimateIncome() const
{
if (obj->ID == Obj::MINE)
{
switch (obj->subID)
auto mine = dynamic_cast<const CGMine*>(obj);
switch (mine->producedResource.toEnum())
{
case Res::WOOD:
case Res::ORE:
case EGameResID::WOOD:
case EGameResID::ORE:
ret[obj->subID] += WOOD_ORE_MINE_PRODUCTION;
break;
case Res::GOLD:
case 7: //abandoned mine -> also gold
ret[Res::GOLD] += GOLD_MINE_PRODUCTION;
case EGameResID::GOLD:
ret[EGameResID::GOLD] += GOLD_MINE_PRODUCTION;
break;
default:
ret[obj->subID] += RESOURCE_MINE_PRODUCTION;
@@ -90,11 +90,11 @@ Goals::TSubgoal ResourceManager::collectResourcesForOurGoal(ResourceObjective &o
{
auto allResources = cb->getResourceAmount();
auto income = estimateIncome();
Res::ERes resourceType = Res::INVALID;
GameResID resourceType = EGameResID::INVALID;
TResource amountToCollect = 0;
typedef std::pair<Res::ERes, TResource> resPair;
std::map<Res::ERes, TResource> missingResources;
using resPair = std::pair<GameResID, TResource>;
std::map<GameResID, TResource> missingResources;
//TODO: unit test for complex resource sets
@@ -102,10 +102,10 @@ Goals::TSubgoal ResourceManager::collectResourcesForOurGoal(ResourceObjective &o
for (auto it = queue.ordered_begin(); it != queue.ordered_end(); it++)
{
//choose specific resources we need for this goal (not 0)
for (auto r = Res::ResourceSet::nziterator(o.resources); r.valid(); r++)
for (auto r = ResourceSet::nziterator(o.resources); r.valid(); r++)
missingResources[r->resType] += it->resources[r->resType]; //goal it costs r units of resType
}
for (auto it = Res::ResourceSet::nziterator(o.resources); it.valid(); it++)
for (auto it = ResourceSet::nziterator(o.resources); it.valid(); it++)
{
missingResources[it->resType] -= allResources[it->resType]; //missing = (what we need) - (what we have)
vstd::amax(missingResources[it->resType], 0); // if we have more resources than reserved, we don't need them
@@ -129,11 +129,11 @@ Goals::TSubgoal ResourceManager::collectResourcesForOurGoal(ResourceObjective &o
break;
}
}
if (resourceType == Res::INVALID) //no needed resources has 0 income,
if (resourceType == EGameResID::INVALID) //no needed resources has 0 income,
{
//find the one which takes longest to collect
typedef std::pair<Res::ERes, float> timePair;
std::map<Res::ERes, float> daysToEarn;
using timePair = std::pair<GameResID, float>;
std::map<GameResID, float> daysToEarn;
for (auto it : missingResources)
daysToEarn[it.first] = (float)missingResources[it.first] / income[it.first];
auto incomeComparer = [](const timePair & lhs, const timePair & rhs) -> bool
@@ -345,7 +345,7 @@ TResources ResourceManager::freeResources() const
TResource ResourceManager::freeGold() const
{
return freeResources()[Res::GOLD];
return freeResources()[EGameResID::GOLD];
}
TResources ResourceManager::allResources() const
@@ -355,5 +355,5 @@ TResources ResourceManager::allResources() const
TResource ResourceManager::allGold() const
{
return cb->getResourceAmount()[Res::GOLD];
return cb->getResourceAmount()[EGameResID::GOLD];
}

View File

@@ -1235,7 +1235,7 @@ void VCAI::recruitCreatures(const CGDwelling * d, const CArmedInstance * recruit
int count = d->creatures[i].first;
CreatureID creID = d->creatures[i].second.back();
vstd::amin(count, ah->freeResources() / VLC->creh->objects[creID]->cost);
vstd::amin(count, ah->freeResources() / VLC->creatures()->getById(creID)->getFullRecruitCost());
if(count > 0)
cb->recruitCreatures(d, recruiter, creID, count, i);
}
@@ -1314,7 +1314,7 @@ bool VCAI::canRecruitAnyHero(const CGTownInstance * t) const
t = findTownWithTavern();
if(!t)
return false;
if(cb->getResourceAmount(Res::GOLD) < GameConstants::HERO_GOLD_COST) //TODO: use ResourceManager
if(cb->getResourceAmount(EGameResID::GOLD) < GameConstants::HERO_GOLD_COST) //TODO: use ResourceManager
return false;
if(cb->getHeroesInfo().size() >= ALLOWED_ROAMING_HEROES)
return false;
@@ -1434,7 +1434,7 @@ void VCAI::wander(HeroPtr h)
}
break;
}
else if(cb->getResourceAmount(Res::GOLD) >= GameConstants::HERO_GOLD_COST)
else if(cb->getResourceAmount(EGameResID::GOLD) >= GameConstants::HERO_GOLD_COST)
{
std::vector<const CGTownInstance *> towns = cb->getTownsInfo();
vstd::erase_if(towns, [&](const CGTownInstance * t) -> bool
@@ -2123,10 +2123,10 @@ void VCAI::tryRealize(Goals::Trade & g) //trade
if(const IMarket * m = IMarket::castFrom(obj, false))
{
auto freeRes = ah->freeResources(); //trade only resources which are not reserved
for(auto it = Res::ResourceSet::nziterator(freeRes); it.valid(); it++)
for(auto it = ResourceSet::nziterator(freeRes); it.valid(); it++)
{
auto res = it->resType;
if(res == g.resID) //sell any other resource
if(res.getNum() == g.resID) //sell any other resource
continue;
int toGive, toGet;
@@ -2180,7 +2180,7 @@ void VCAI::tryRealize(Goals::BuyArmy & g)
|| t->getUpperArmy()->getSlotFor(ci.creID) == SlotID())
continue;
vstd::amin(ci.count, res / ci.cre->cost); //max count we can afford
vstd::amin(ci.count, res / ci.cre->getFullRecruitCost()); //max count we can afford
if(!ci.count)
continue;
@@ -2196,15 +2196,15 @@ void VCAI::tryRealize(Goals::BuyArmy & g)
*boost::max_element(creaturesInDwellings, [](const creInfo & lhs, const creInfo & rhs)
{
//max value of creatures we can buy with our res
int value1 = lhs.cre->AIValue * lhs.count,
value2 = rhs.cre->AIValue * rhs.count;
int value1 = lhs.cre->getAIValue() * lhs.count,
value2 = rhs.cre->getAIValue() * rhs.count;
return value1 < value2;
});
cb->recruitCreatures(t, t->getUpperArmy(), ci.creID, ci.count, ci.level);
valueBought += ci.count * ci.cre->AIValue;
valueBought += ci.count * ci.cre->getAIValue();
}
throw goalFulfilledException(sptr(g)); //we bought as many creatures as we wanted
@@ -2826,7 +2826,7 @@ bool shouldVisit(HeroPtr h, const CGObjectInstance * obj)
{
for(auto slot : h->Slots())
{
if(slot.second->type->upgrades.size())
if(slot.second->type->hasUpgrades())
return true; //TODO: check price?
}
return false;
@@ -2850,7 +2850,7 @@ bool shouldVisit(HeroPtr h, const CGObjectInstance * obj)
case Obj::TREE_OF_KNOWLEDGE:
{
TResources myRes = ai->ah->freeResources();
if(myRes[Res::GOLD] < 2000 || myRes[Res::GEMS] < 10)
if(myRes[EGameResID::GOLD] < 2000 || myRes[EGameResID::GEMS] < 10)
return false;
break;
}