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:
@@ -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
|
||||
{
|
||||
|
||||
@@ -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))
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -161,7 +161,7 @@ struct creInfo
|
||||
{
|
||||
int count;
|
||||
CreatureID creID;
|
||||
CCreature * cre;
|
||||
const Creature * cre;
|
||||
int level;
|
||||
};
|
||||
creInfo infoFromDC(const dwellingContent & dc);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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)));
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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; }
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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])));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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?
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -152,7 +152,7 @@ struct creInfo
|
||||
{
|
||||
int count;
|
||||
CreatureID creID;
|
||||
CCreature * cre;
|
||||
const Creature * cre;
|
||||
int level;
|
||||
};
|
||||
creInfo infoFromDC(const dwellingContent & dc);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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])));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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?
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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];
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user