mirror of
https://github.com/vcmi/vcmi.git
synced 2024-12-24 22:14:36 +02:00
commit
6f5710e809
@ -430,9 +430,16 @@ bool shouldVisit(const Nullkiller * ai, const CGHeroInstance * h, const CGObject
|
||||
return false;
|
||||
}
|
||||
|
||||
if(obj->wasVisited(h)) //it must pointer to hero instance, heroPtr calls function wasVisited(ui8 player);
|
||||
if(obj->wasVisited(h))
|
||||
return false;
|
||||
|
||||
auto rewardable = dynamic_cast<const Rewardable::Interface *>(obj);
|
||||
|
||||
if(rewardable && rewardable->getAvailableRewards(h, Rewardable::EEventType::EVENT_FIRST_VISIT).empty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -79,6 +79,15 @@ bool needToRecruitHero(const Nullkiller * ai, const CGTownInstance * startupTown
|
||||
bool isGoldPile = dynamic_cast<const CGResource *>(obj)
|
||||
&& dynamic_cast<const CGResource *>(obj)->resourceID() == EGameResID::GOLD;
|
||||
|
||||
auto rewardable = dynamic_cast<const Rewardable::Interface *>(obj);
|
||||
|
||||
if(rewardable)
|
||||
{
|
||||
for(auto & info : rewardable->configuration.info)
|
||||
if(info.reward.resources[EGameResID::GOLD] > 0)
|
||||
isGoldPile = true;
|
||||
}
|
||||
|
||||
if(isGoldPile
|
||||
|| obj->ID == Obj::TREASURE_CHEST
|
||||
|| obj->ID == Obj::CAMPFIRE
|
||||
|
@ -137,16 +137,19 @@ TResources getCreatureBankResources(const CGObjectInstance * target, const CGHer
|
||||
return sum > 1 ? result / sum : result;
|
||||
}
|
||||
|
||||
uint64_t getResourcesGoldReward(const TResources & res)
|
||||
int32_t getResourcesGoldReward(const TResources & res)
|
||||
{
|
||||
int nonGoldResources = res[EGameResID::GEMS]
|
||||
+ res[EGameResID::SULFUR]
|
||||
+ res[EGameResID::WOOD]
|
||||
+ res[EGameResID::ORE]
|
||||
+ res[EGameResID::CRYSTAL]
|
||||
+ res[EGameResID::MERCURY];
|
||||
int32_t result = 0;
|
||||
|
||||
return res[EGameResID::GOLD] + 100 * nonGoldResources;
|
||||
for(EGameResID r = EGameResID(0); r < EGameResID::COUNT; r.advance(1))
|
||||
{
|
||||
if(res[r] > 0)
|
||||
{
|
||||
result += r == EGameResID::GOLD ? res[r] : res[r] * 100;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
uint64_t getCreatureBankArmyReward(const CGObjectInstance * target, const CGHeroInstance * hero)
|
||||
@ -250,9 +253,9 @@ int getDwellingArmyCost(const CGObjectInstance * target)
|
||||
return cost;
|
||||
}
|
||||
|
||||
static uint64_t evaluateArtifactArmyValue(const CArtifactInstance * art)
|
||||
static uint64_t evaluateArtifactArmyValue(const CArtifact * art)
|
||||
{
|
||||
if(art->artType->getId() == ArtifactID::SPELL_SCROLL)
|
||||
if(art->getId() == ArtifactID::SPELL_SCROLL)
|
||||
return 1500;
|
||||
|
||||
auto statsValue =
|
||||
@ -267,7 +270,7 @@ static uint64_t evaluateArtifactArmyValue(const CArtifactInstance * art)
|
||||
|
||||
auto classValue = 0;
|
||||
|
||||
switch(art->artType->aClass)
|
||||
switch(art->aClass)
|
||||
{
|
||||
case CArtifact::EartClass::ART_MINOR:
|
||||
classValue = 1000;
|
||||
@ -315,7 +318,7 @@ uint64_t RewardEvaluator::getArmyReward(
|
||||
case Obj::WARRIORS_TOMB:
|
||||
return 1000;
|
||||
case Obj::ARTIFACT:
|
||||
return evaluateArtifactArmyValue(dynamic_cast<const CGArtifact *>(target)->storedArtifact);
|
||||
return evaluateArtifactArmyValue(dynamic_cast<const CGArtifact *>(target)->storedArtifact->artType);
|
||||
case Obj::DRAGON_UTOPIA:
|
||||
return 10000;
|
||||
case Obj::HERO:
|
||||
@ -328,8 +331,46 @@ uint64_t RewardEvaluator::getArmyReward(
|
||||
case Obj::MAGIC_SPRING:
|
||||
return getManaRecoveryArmyReward(hero);
|
||||
default:
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
|
||||
auto rewardable = dynamic_cast<const Rewardable::Interface *>(target);
|
||||
|
||||
if(rewardable)
|
||||
{
|
||||
auto totalValue = 0;
|
||||
|
||||
for(int index : rewardable->getAvailableRewards(hero, Rewardable::EEventType::EVENT_FIRST_VISIT))
|
||||
{
|
||||
auto & info = rewardable->configuration.info[index];
|
||||
|
||||
auto rewardValue = 0;
|
||||
|
||||
if(!info.reward.artifacts.empty())
|
||||
{
|
||||
for(auto artID : info.reward.artifacts)
|
||||
{
|
||||
const CArtifact * art = dynamic_cast<const CArtifact *>(VLC->artifacts()->getById(artID));
|
||||
|
||||
rewardValue += evaluateArtifactArmyValue(art);
|
||||
}
|
||||
}
|
||||
|
||||
if(!info.reward.creatures.empty())
|
||||
{
|
||||
for(auto stackInfo : info.reward.creatures)
|
||||
{
|
||||
rewardValue += stackInfo.getType()->getAIValue() * stackInfo.getCount();
|
||||
}
|
||||
}
|
||||
|
||||
totalValue += rewardValue > 0 ? rewardValue / (info.reward.artifacts.size() + info.reward.creatures.size()) : 0;
|
||||
}
|
||||
|
||||
return totalValue;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint64_t RewardEvaluator::getArmyGrowth(
|
||||
@ -473,7 +514,24 @@ uint64_t RewardEvaluator::getManaRecoveryArmyReward(const CGHeroInstance * hero)
|
||||
return ai->heroManager->getMagicStrength(hero) * 10000 * (1.0f - std::sqrt(static_cast<float>(hero->mana) / hero->manaLimit()));
|
||||
}
|
||||
|
||||
float RewardEvaluator::getStrategicalValue(const CGObjectInstance * target) const
|
||||
float RewardEvaluator::getResourceRequirementStrength(const TResources & res) const
|
||||
{
|
||||
float sum = 0.0f;
|
||||
|
||||
for(TResources::nziterator it(res); it.valid(); it++)
|
||||
{
|
||||
//Evaluate resources used for construction. Gold is evaluated separately.
|
||||
if(it->resType != EGameResID::GOLD)
|
||||
{
|
||||
sum += 0.1f * it->resVal * getResourceRequirementStrength(it->resType)
|
||||
+ 0.05f * it->resVal * getTotalResourceRequirementStrength(it->resType);
|
||||
}
|
||||
}
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
||||
float RewardEvaluator::getStrategicalValue(const CGObjectInstance * target, const CGHeroInstance * hero) const
|
||||
{
|
||||
if(!target)
|
||||
return 0;
|
||||
@ -491,24 +549,17 @@ float RewardEvaluator::getStrategicalValue(const CGObjectInstance * target) cons
|
||||
case Obj::RESOURCE:
|
||||
{
|
||||
auto resource = dynamic_cast<const CGResource *>(target);
|
||||
return resource->resourceID() == EGameResID::GOLD
|
||||
? 0
|
||||
: 0.2f * getTotalResourceRequirementStrength(resource->resourceID()) + 0.4f * getResourceRequirementStrength(resource->resourceID());
|
||||
TResources res;
|
||||
res[resource->resourceID()] = resource->amount;
|
||||
|
||||
return getResourceRequirementStrength(res);
|
||||
}
|
||||
|
||||
case Obj::CREATURE_BANK:
|
||||
{
|
||||
auto resourceReward = getCreatureBankResources(target, nullptr);
|
||||
float sum = 0.0f;
|
||||
for (TResources::nziterator it (resourceReward); it.valid(); it++)
|
||||
{
|
||||
//Evaluate resources used for construction. Gold is evaluated separately.
|
||||
if (it->resType != EGameResID::GOLD)
|
||||
{
|
||||
sum += 0.1f * it->resVal * getResourceRequirementStrength(it->resType);
|
||||
}
|
||||
}
|
||||
return sum;
|
||||
|
||||
return getResourceRequirementStrength(resourceReward);
|
||||
}
|
||||
|
||||
case Obj::TOWN:
|
||||
@ -547,8 +598,24 @@ float RewardEvaluator::getStrategicalValue(const CGObjectInstance * target) cons
|
||||
return 0.6f;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
|
||||
auto rewardable = dynamic_cast<const Rewardable::Interface *>(target);
|
||||
|
||||
if(rewardable && hero)
|
||||
{
|
||||
auto resourceReward = 0.0f;
|
||||
|
||||
for(int index : rewardable->getAvailableRewards(hero, Rewardable::EEventType::EVENT_FIRST_VISIT))
|
||||
{
|
||||
resourceReward += getResourceRequirementStrength(rewardable->configuration.info[index].reward.resources);
|
||||
}
|
||||
|
||||
return resourceReward;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
float RewardEvaluator::evaluateWitchHutSkillScore(const CGObjectInstance * hut, const CGHeroInstance * hero, HeroRole role) const
|
||||
@ -593,11 +660,11 @@ float RewardEvaluator::getSkillReward(const CGObjectInstance * target, const CGH
|
||||
case Obj::ARENA:
|
||||
return 2;
|
||||
case Obj::SHRINE_OF_MAGIC_INCANTATION:
|
||||
return 0.2f;
|
||||
return 0.25f;
|
||||
case Obj::SHRINE_OF_MAGIC_GESTURE:
|
||||
return 0.3f;
|
||||
return 1.0f;
|
||||
case Obj::SHRINE_OF_MAGIC_THOUGHT:
|
||||
return 0.5f;
|
||||
return 2.0f;
|
||||
case Obj::LIBRARY_OF_ENLIGHTENMENT:
|
||||
return 8;
|
||||
case Obj::WITCH_HUT:
|
||||
@ -606,14 +673,56 @@ float RewardEvaluator::getSkillReward(const CGObjectInstance * target, const CGH
|
||||
//Can contains experience, spells, or skills (only on custom maps)
|
||||
return 2.5f;
|
||||
case Obj::PYRAMID:
|
||||
return 3.0f;
|
||||
return 6.0f;
|
||||
case Obj::HERO:
|
||||
return ai->cb->getPlayerRelations(target->tempOwner, ai->playerID) == PlayerRelations::ENEMIES
|
||||
? enemyHeroEliminationSkillRewardRatio * dynamic_cast<const CGHeroInstance *>(target)->level
|
||||
: 0;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
|
||||
auto rewardable = dynamic_cast<const Rewardable::Interface *>(target);
|
||||
|
||||
if(rewardable)
|
||||
{
|
||||
auto totalValue = 0.0f;
|
||||
|
||||
for(int index : rewardable->getAvailableRewards(hero, Rewardable::EEventType::EVENT_FIRST_VISIT))
|
||||
{
|
||||
auto & info = rewardable->configuration.info[index];
|
||||
|
||||
auto rewardValue = 0.0f;
|
||||
|
||||
if(!info.reward.spells.empty())
|
||||
{
|
||||
for(auto spellID : info.reward.spells)
|
||||
{
|
||||
const spells::Spell * spell = VLC->spells()->getById(spellID);
|
||||
|
||||
if(hero->canLearnSpell(spell) && !hero->spellbookContainsSpell(spellID))
|
||||
{
|
||||
rewardValue += std::sqrt(spell->getLevel()) / 4.0f;
|
||||
}
|
||||
}
|
||||
|
||||
totalValue += rewardValue / info.reward.spells.size();
|
||||
}
|
||||
|
||||
if(!info.reward.primary.empty())
|
||||
{
|
||||
for(auto value : info.reward.primary)
|
||||
{
|
||||
totalValue += value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return totalValue;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const HitMapInfo & RewardEvaluator::getEnemyHeroDanger(const int3 & tile, uint8_t turn) const
|
||||
@ -697,8 +806,26 @@ int32_t RewardEvaluator::getGoldReward(const CGObjectInstance * target, const CG
|
||||
? heroEliminationBonus + enemyArmyEliminationGoldRewardRatio * getArmyCost(dynamic_cast<const CGHeroInstance *>(target))
|
||||
: 0;
|
||||
default:
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
|
||||
auto rewardable = dynamic_cast<const Rewardable::Interface *>(target);
|
||||
|
||||
if(rewardable)
|
||||
{
|
||||
auto goldReward = 0;
|
||||
|
||||
for(int index : rewardable->getAvailableRewards(hero, Rewardable::EEventType::EVENT_FIRST_VISIT))
|
||||
{
|
||||
auto & info = rewardable->configuration.info[index];
|
||||
|
||||
goldReward += getResourcesGoldReward(info.reward.resources);
|
||||
}
|
||||
|
||||
return goldReward;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
class HeroExchangeEvaluator : public IEvaluationContextBuilder
|
||||
|
@ -39,7 +39,8 @@ public:
|
||||
int getGoldCost(const CGObjectInstance * target, const CGHeroInstance * hero, const CCreatureSet * army) const;
|
||||
float getEnemyHeroStrategicalValue(const CGHeroInstance * enemy) const;
|
||||
float getResourceRequirementStrength(int resType) const;
|
||||
float getStrategicalValue(const CGObjectInstance * target) const;
|
||||
float getResourceRequirementStrength(const TResources & res) const;
|
||||
float getStrategicalValue(const CGObjectInstance * target, const CGHeroInstance * hero = nullptr) const;
|
||||
float getTotalResourceRequirementStrength(int resType) const;
|
||||
float evaluateWitchHutSkillScore(const CGObjectInstance * hut, const CGHeroInstance * hero, HeroRole role) const;
|
||||
float getSkillReward(const CGObjectInstance * target, const CGHeroInstance * hero, HeroRole role) const;
|
||||
|
@ -29,9 +29,6 @@ private:
|
||||
|
||||
protected:
|
||||
|
||||
/// filters list of visit info and returns rewards that can be granted to current hero
|
||||
std::vector<ui32> getAvailableRewards(const CGHeroInstance * hero, Rewardable::EEventType event) const;
|
||||
|
||||
/// function that must be called if hero got level-up during grantReward call
|
||||
virtual void grantRewardAfterLevelup(IGameCallback * cb, const Rewardable::VisitInfo & reward, const CArmedInstance * army, const CGHeroInstance * hero) const;
|
||||
|
||||
@ -39,6 +36,9 @@ protected:
|
||||
virtual void grantRewardBeforeLevelup(IGameCallback * cb, const Rewardable::VisitInfo & reward, const CGHeroInstance * hero) const;
|
||||
|
||||
public:
|
||||
|
||||
/// filters list of visit info and returns rewards that can be granted to current hero
|
||||
std::vector<ui32> getAvailableRewards(const CGHeroInstance * hero, Rewardable::EEventType event) const;
|
||||
|
||||
Rewardable::Configuration configuration;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user