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

NKAI: improve neutral town priority handling, reduce priority of objects like star axis

This commit is contained in:
Andrii Danylchenko 2023-03-11 11:42:44 +02:00
parent 87638aafc0
commit 4bf570763a
9 changed files with 37 additions and 25 deletions

View File

@ -58,7 +58,7 @@ std::vector<SlotInfo> ArmyManager::getSortedSlots(const CCreatureSet * target, c
}
}
for(auto pair : creToPower)
for(auto & pair : creToPower)
resultingArmy.push_back(pair.second);
boost::sort(resultingArmy, [](const SlotInfo & left, const SlotInfo & right) -> bool
@ -112,7 +112,7 @@ std::vector<SlotInfo> ArmyManager::getBestArmy(const IBonusBearer * armyCarrier,
for(auto bonus : *bonusModifiers)
{
// army bonuses will change and object bonuses are temporary
if(bonus->source != Bonus::ARMY || bonus->source != Bonus::OBJECT)
if(bonus->source != Bonus::ARMY && bonus->source != Bonus::OBJECT)
{
newArmyInstance.addNewBonus(std::make_shared<Bonus>(*bonus));
}

View File

@ -158,7 +158,7 @@ void BuildAnalyzer::update()
updateDailyIncome();
if(ai->cb->getDate(Date::EDateType::DAY) == 1 && dailyIncome[Res::GOLD] <= 500)
if(ai->cb->getDate(Date::EDateType::DAY) == 1)
{
goldPreasure = 1;
}

View File

@ -111,6 +111,12 @@ void HeroManager::update()
int globalMainCount = std::min(((int)myHeroes.size() + 2) / 3, cb->getMapSize().x / 50 + 1);
//vstd::amin(globalMainCount, 1 + (cb->getTownsInfo().size() / 3));
if(cb->getTownsInfo().size() < 4 && globalMainCount > 2)
{
globalMainCount = 2;
}
std::sort(myHeroes.begin(), myHeroes.end(), scoreSort);
for(auto hero : myHeroes)

View File

@ -70,10 +70,7 @@ bool needToRecruitHero(const CGTownInstance * startupTown)
return false;
if(!startupTown->garrisonHero && !startupTown->visitingHero)
return false;
auto heroToCheck = startupTown->garrisonHero ? startupTown->garrisonHero.get() : startupTown->visitingHero.get();
auto paths = cb->getPathsInfo(heroToCheck);
return true;
int treasureSourcesCount = 0;
@ -83,19 +80,17 @@ bool needToRecruitHero(const CGTownInstance * startupTown)
|| obj->ID == Obj::TREASURE_CHEST
|| obj->ID == Obj::CAMPFIRE
|| obj->ID == Obj::WATER_WHEEL)
{
auto path = paths->getPathInfo(obj->visitablePos());
if((path->accessible == CGPathNode::BLOCKVIS || path->accessible == CGPathNode::VISITABLE)
&& path->reachable())
{
treasureSourcesCount++;
}
}
}
auto basicCount = cb->getTownsInfo().size() + 2;
auto boost = (int)std::floor(std::pow(treasureSourcesCount / 2.0, 2));
auto boost = std::min(
(int)std::floor(std::pow(1 + (cb->getMapSize().x / 50), 2)),
treasureSourcesCount / 2);
logAi->trace("Treasure sources found %d", treasureSourcesCount);
logAi->trace("Startup allows %d+%d heroes", basicCount, boost);
return cb->getHeroCount(ai->playerID, true) < basicCount + boost;

View File

@ -130,6 +130,9 @@ ui64 FuzzyHelper::evaluateDanger(const CGObjectInstance * obj)
return danger;
}
case Obj::PANDORAS_BOX:
return 10000; //Who knows what awaits us there
case Obj::ARTIFACT:
case Obj::RESOURCE:
{

View File

@ -236,7 +236,6 @@ void Nullkiller::makeTurn()
{
Goals::TTaskVec fastTasks = {
choseBestTask(sptr(BuyArmyBehavior()), 1),
choseBestTask(sptr(RecruitHeroBehavior()), 1),
choseBestTask(sptr(BuildingBehavior()), 1)
};
@ -251,6 +250,7 @@ void Nullkiller::makeTurn()
Goals::TTaskVec bestTasks = {
bestTask,
choseBestTask(sptr(RecruitHeroBehavior()), 1),
choseBestTask(sptr(CaptureObjectsBehavior()), 1),
choseBestTask(sptr(ClusterBehavior()), MAX_DEPTH),
choseBestTask(sptr(DefenceBehavior()), MAX_DEPTH),

View File

@ -549,7 +549,7 @@ int32_t RewardEvaluator::getGoldReward(const CGObjectInstance * target, const CG
case Obj::SEA_CHEST:
return 1500;
case Obj::PANDORAS_BOX:
return 5000;
return 2500;
case Obj::PRISON:
//Objectively saves us 2500 to hire hero
return GameConstants::HERO_GOLD_COST;

View File

@ -855,6 +855,10 @@ void AINodeStorage::setHeroes(std::map<const CGHeroInstance *, HeroRole> heroes)
for(auto & hero : heroes)
{
// do not allow our own heroes in garrison to act on map
if(hero.first->getOwner() == ai->playerID && hero.first->inTownGarrison)
continue;
uint64_t mask = FirstActorMask << actors.size();
auto actor = std::make_shared<HeroActor>(hero.first, hero.second, mask, ai);

View File

@ -86,8 +86,8 @@ InputVariable: strategicalValue
lock-range: false
term: NONE Ramp 0.200 0.000
term: LOWEST Triangle 0.000 0.010 0.250
term: LOW Triangle 0.000 0.400 0.700
term: MEDIUM Triangle 0.400 0.700 1.000
term: LOW Triangle 0.000 0.250 0.700
term: MEDIUM Triangle 0.250 0.700 1.000
term: HIGH Ramp 0.700 1.000
InputVariable: goldPreasure
description: Ratio between weekly army cost and gold income
@ -189,10 +189,10 @@ RuleBlock: gold reward
rule: if armyReward is LOW and heroRole is MAIN and danger is not NONE and armyLoss is LOW then Value is HIGH
rule: if armyReward is LOW and heroRole is MAIN and danger is NONE then Value is BITLOW with 0.5
rule: if armyReward is LOW and heroRole is MAIN and danger is NONE and mainTurnDistance is LOWEST then Value is HIGH
rule: if skillReward is LOW and heroRole is MAIN and armyLoss is LOW then Value is BITHIGH with 0.5
rule: if skillReward is MEDIUM and heroRole is MAIN and armyLoss is LOW and fear is not HIGH then Value is HIGH with 0.5
rule: if skillReward is LOW and heroRole is MAIN and armyLoss is LOW then Value is BITHIGH
rule: if skillReward is MEDIUM and heroRole is MAIN and armyLoss is LOW and fear is not HIGH then Value is BITHIGH
rule: if skillReward is HIGH and heroRole is MAIN and armyLoss is LOW and fear is not HIGH then Value is HIGH
rule: if strategicalValue is LOW and heroRole is MAIN and armyLoss is LOW then Value is BITLOW
rule: if strategicalValue is LOW and heroRole is MAIN and armyLoss is LOW then Value is BITHIGH
rule: if strategicalValue is LOWEST and heroRole is MAIN and armyLoss is LOW then Value is LOW
rule: if strategicalValue is LOW and heroRole is SCOUT and armyLoss is LOW and fear is not HIGH then Value is HIGH with 0.5
rule: if strategicalValue is MEDIUM and heroRole is SCOUT and danger is NONE and fear is not HIGH then Value is HIGH
@ -211,9 +211,13 @@ RuleBlock: gold reward
rule: if heroRole is MAIN and danger is not NONE and armyLoss is LOW then Value is BITHIGH with 0.2
rule: if heroRole is SCOUT then Value is BITLOW
rule: if goldCost is not NONE and goldReward is NONE and goldPreasure is HIGH then Value is LOWEST
rule: if turn is NOW then Value is BITHIGH with 0.2
rule: if goldPreasure is HIGH and goldReward is HIGH and armyLoss is LOW and fear is not HIGH then Value is HIGHEST
rule: if goldPreasure is HIGH and goldReward is MEDIUM and armyLoss is LOW and fear is not HIGH then Value is HIGH
rule: if goldPreasure is HIGH and goldReward is LOW and armyLoss is LOW then Value is BITHIGH
rule: if turn is NOW then Value is LOW with 0.3
rule: if turn is not NOW then Value is LOW with 0.4
rule: if goldPreasure is HIGH and goldReward is HIGH and heroRole is MAIN and danger is not NONE and armyLoss is LOW and fear is not HIGH then Value is HIGHEST
rule: if goldPreasure is HIGH and goldReward is MEDIUM and heroRole is MAIN and danger is not NONE and armyLoss is LOW and fear is not HIGH then Value is HIGH
rule: if goldPreasure is HIGH and goldReward is HIGH and heroRole is SCOUT and danger is NONE and armyLoss is LOW and fear is not HIGH then Value is HIGHEST
rule: if goldPreasure is HIGH and goldReward is MEDIUM and heroRole is SCOUT and danger is NONE and armyLoss is LOW and fear is not HIGH then Value is HIGH
rule: if goldPreasure is HIGH and goldReward is LOW and heroRole is SCOUT and armyLoss is LOW then Value is BITHIGH
rule: if goldPreasure is HIGH and goldReward is LOW and heroRole is SCOUT and scoutTurnDistance is LOW and armyLoss is LOW then Value is HIGH with 0.5
rule: if fear is MEDIUM then Value is LOW
rule: if fear is HIGH then Value is LOWEST