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); resultingArmy.push_back(pair.second);
boost::sort(resultingArmy, [](const SlotInfo & left, const SlotInfo & right) -> bool 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) for(auto bonus : *bonusModifiers)
{ {
// army bonuses will change and object bonuses are temporary // 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)); newArmyInstance.addNewBonus(std::make_shared<Bonus>(*bonus));
} }

View File

@ -158,7 +158,7 @@ void BuildAnalyzer::update()
updateDailyIncome(); updateDailyIncome();
if(ai->cb->getDate(Date::EDateType::DAY) == 1 && dailyIncome[Res::GOLD] <= 500) if(ai->cb->getDate(Date::EDateType::DAY) == 1)
{ {
goldPreasure = 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); 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); std::sort(myHeroes.begin(), myHeroes.end(), scoreSort);
for(auto hero : myHeroes) for(auto hero : myHeroes)

View File

@ -70,10 +70,7 @@ bool needToRecruitHero(const CGTownInstance * startupTown)
return false; return false;
if(!startupTown->garrisonHero && !startupTown->visitingHero) if(!startupTown->garrisonHero && !startupTown->visitingHero)
return false; return true;
auto heroToCheck = startupTown->garrisonHero ? startupTown->garrisonHero.get() : startupTown->visitingHero.get();
auto paths = cb->getPathsInfo(heroToCheck);
int treasureSourcesCount = 0; int treasureSourcesCount = 0;
@ -84,18 +81,16 @@ bool needToRecruitHero(const CGTownInstance * startupTown)
|| obj->ID == Obj::CAMPFIRE || obj->ID == Obj::CAMPFIRE
|| obj->ID == Obj::WATER_WHEEL) || obj->ID == Obj::WATER_WHEEL)
{ {
auto path = paths->getPathInfo(obj->visitablePos()); treasureSourcesCount++;
if((path->accessible == CGPathNode::BLOCKVIS || path->accessible == CGPathNode::VISITABLE)
&& path->reachable())
{
treasureSourcesCount++;
}
} }
} }
auto basicCount = cb->getTownsInfo().size() + 2; 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); logAi->trace("Startup allows %d+%d heroes", basicCount, boost);
return cb->getHeroCount(ai->playerID, true) < basicCount + boost; return cb->getHeroCount(ai->playerID, true) < basicCount + boost;

View File

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

View File

@ -236,7 +236,6 @@ void Nullkiller::makeTurn()
{ {
Goals::TTaskVec fastTasks = { Goals::TTaskVec fastTasks = {
choseBestTask(sptr(BuyArmyBehavior()), 1), choseBestTask(sptr(BuyArmyBehavior()), 1),
choseBestTask(sptr(RecruitHeroBehavior()), 1),
choseBestTask(sptr(BuildingBehavior()), 1) choseBestTask(sptr(BuildingBehavior()), 1)
}; };
@ -251,6 +250,7 @@ void Nullkiller::makeTurn()
Goals::TTaskVec bestTasks = { Goals::TTaskVec bestTasks = {
bestTask, bestTask,
choseBestTask(sptr(RecruitHeroBehavior()), 1),
choseBestTask(sptr(CaptureObjectsBehavior()), 1), choseBestTask(sptr(CaptureObjectsBehavior()), 1),
choseBestTask(sptr(ClusterBehavior()), MAX_DEPTH), choseBestTask(sptr(ClusterBehavior()), MAX_DEPTH),
choseBestTask(sptr(DefenceBehavior()), 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: case Obj::SEA_CHEST:
return 1500; return 1500;
case Obj::PANDORAS_BOX: case Obj::PANDORAS_BOX:
return 5000; return 2500;
case Obj::PRISON: case Obj::PRISON:
//Objectively saves us 2500 to hire hero //Objectively saves us 2500 to hire hero
return GameConstants::HERO_GOLD_COST; return GameConstants::HERO_GOLD_COST;

View File

@ -855,6 +855,10 @@ void AINodeStorage::setHeroes(std::map<const CGHeroInstance *, HeroRole> heroes)
for(auto & hero : 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(); uint64_t mask = FirstActorMask << actors.size();
auto actor = std::make_shared<HeroActor>(hero.first, hero.second, mask, ai); auto actor = std::make_shared<HeroActor>(hero.first, hero.second, mask, ai);

View File

@ -86,8 +86,8 @@ InputVariable: strategicalValue
lock-range: false lock-range: false
term: NONE Ramp 0.200 0.000 term: NONE Ramp 0.200 0.000
term: LOWEST Triangle 0.000 0.010 0.250 term: LOWEST Triangle 0.000 0.010 0.250
term: LOW Triangle 0.000 0.400 0.700 term: LOW Triangle 0.000 0.250 0.700
term: MEDIUM Triangle 0.400 0.700 1.000 term: MEDIUM Triangle 0.250 0.700 1.000
term: HIGH Ramp 0.700 1.000 term: HIGH Ramp 0.700 1.000
InputVariable: goldPreasure InputVariable: goldPreasure
description: Ratio between weekly army cost and gold income 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 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 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 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 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 HIGH with 0.5 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 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 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 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 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 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 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 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 turn is NOW then Value is LOW with 0.3
rule: if goldPreasure is HIGH and goldReward is HIGH and armyLoss is LOW and fear is not HIGH then Value is HIGHEST rule: if turn is not NOW then Value is LOW with 0.4
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 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 LOW and armyLoss is LOW then Value is BITHIGH 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 MEDIUM then Value is LOW
rule: if fear is HIGH then Value is LOWEST rule: if fear is HIGH then Value is LOWEST