diff --git a/AI/Nullkiller/Analyzers/ArmyManager.cpp b/AI/Nullkiller/Analyzers/ArmyManager.cpp index d1c39980d..0a876bbe9 100644 --- a/AI/Nullkiller/Analyzers/ArmyManager.cpp +++ b/AI/Nullkiller/Analyzers/ArmyManager.cpp @@ -58,7 +58,7 @@ std::vector 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 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)); } diff --git a/AI/Nullkiller/Analyzers/BuildAnalyzer.cpp b/AI/Nullkiller/Analyzers/BuildAnalyzer.cpp index 4eed21e80..4ae59be8f 100644 --- a/AI/Nullkiller/Analyzers/BuildAnalyzer.cpp +++ b/AI/Nullkiller/Analyzers/BuildAnalyzer.cpp @@ -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; } diff --git a/AI/Nullkiller/Analyzers/HeroManager.cpp b/AI/Nullkiller/Analyzers/HeroManager.cpp index edea22385..25fb4a273 100644 --- a/AI/Nullkiller/Analyzers/HeroManager.cpp +++ b/AI/Nullkiller/Analyzers/HeroManager.cpp @@ -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) diff --git a/AI/Nullkiller/Behaviors/StartupBehavior.cpp b/AI/Nullkiller/Behaviors/StartupBehavior.cpp index 462529005..c05c31726 100644 --- a/AI/Nullkiller/Behaviors/StartupBehavior.cpp +++ b/AI/Nullkiller/Behaviors/StartupBehavior.cpp @@ -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; @@ -84,18 +81,16 @@ bool needToRecruitHero(const CGTownInstance * startupTown) || 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++; - } + 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; diff --git a/AI/Nullkiller/Engine/FuzzyHelper.cpp b/AI/Nullkiller/Engine/FuzzyHelper.cpp index 68fdcd5db..d0c5d7108 100644 --- a/AI/Nullkiller/Engine/FuzzyHelper.cpp +++ b/AI/Nullkiller/Engine/FuzzyHelper.cpp @@ -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: { diff --git a/AI/Nullkiller/Engine/Nullkiller.cpp b/AI/Nullkiller/Engine/Nullkiller.cpp index 7d2059cc7..85f7a6442 100644 --- a/AI/Nullkiller/Engine/Nullkiller.cpp +++ b/AI/Nullkiller/Engine/Nullkiller.cpp @@ -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), diff --git a/AI/Nullkiller/Engine/PriorityEvaluator.cpp b/AI/Nullkiller/Engine/PriorityEvaluator.cpp index 9374a3dc6..82d80f994 100644 --- a/AI/Nullkiller/Engine/PriorityEvaluator.cpp +++ b/AI/Nullkiller/Engine/PriorityEvaluator.cpp @@ -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; diff --git a/AI/Nullkiller/Pathfinding/AINodeStorage.cpp b/AI/Nullkiller/Pathfinding/AINodeStorage.cpp index 7709dc0ad..1880df499 100644 --- a/AI/Nullkiller/Pathfinding/AINodeStorage.cpp +++ b/AI/Nullkiller/Pathfinding/AINodeStorage.cpp @@ -855,6 +855,10 @@ void AINodeStorage::setHeroes(std::map 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(hero.first, hero.second, mask, ai); diff --git a/config/ai/object-priorities.txt b/config/ai/object-priorities.txt index be5b52efc..18f2a605d 100644 --- a/config/ai/object-priorities.txt +++ b/config/ai/object-priorities.txt @@ -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 \ No newline at end of file