diff --git a/AI/Nullkiller/Engine/Nullkiller.cpp b/AI/Nullkiller/Engine/Nullkiller.cpp index 39054c75d..4a10d8b6c 100644 --- a/AI/Nullkiller/Engine/Nullkiller.cpp +++ b/AI/Nullkiller/Engine/Nullkiller.cpp @@ -387,7 +387,7 @@ void Nullkiller::makeTurn() if(bestTask->priority > 0) { #if NKAI_TRACE_LEVEL >= 1 - logAi->info("Pass %d: Performing task %s with prio: %d", i, bestTask->toString(), bestTask->priority); + logAi->info("Pass %d: Performing prio 0 task %s with prio: %d", i, bestTask->toString(), bestTask->priority); #endif if(!executeTask(bestTask)) return; diff --git a/AI/Nullkiller/Engine/PriorityEvaluator.cpp b/AI/Nullkiller/Engine/PriorityEvaluator.cpp index f2882e124..e6ad50e97 100644 --- a/AI/Nullkiller/Engine/PriorityEvaluator.cpp +++ b/AI/Nullkiller/Engine/PriorityEvaluator.cpp @@ -63,7 +63,8 @@ EvaluationContext::EvaluationContext(const Nullkiller* ai) involvesSailing(false), isTradeBuilding(false), isExchange(false), - isExplore(false) + isArmyUpgrade(false), + explorePriority(0) { } @@ -493,7 +494,7 @@ uint64_t RewardEvaluator::townArmyGrowth(const CGTownInstance * town) const return result; } -uint64_t RewardEvaluator::getManaRecoveryArmyReward(const CGHeroInstance * hero) const +float RewardEvaluator::getManaRecoveryArmyReward(const CGHeroInstance * hero) const { return ai->heroManager->getMagicStrength(hero) * 10000 * (1.0f - std::sqrt(static_cast(hero->mana) / hero->manaLimit())); } @@ -868,6 +869,7 @@ public: evaluationContext.armyReward += upgradeValue; evaluationContext.addNonCriticalStrategicalValue(upgradeValue / (float)armyUpgrade.hero->getArmyStrength()); + evaluationContext.isArmyUpgrade = true; } }; @@ -882,7 +884,24 @@ public: int tilesDiscovered = task->value; evaluationContext.addNonCriticalStrategicalValue(0.03f * tilesDiscovered); - evaluationContext.isExplore = true; + for (auto obj : evaluationContext.evaluator.ai->cb->getVisitableObjs(task->tile)) + { + switch (obj->ID.num) + { + case Obj::MONOLITH_ONE_WAY_ENTRANCE: + case Obj::MONOLITH_TWO_WAY: + case Obj::SUBTERRANEAN_GATE: + case Obj::WHIRLPOOL: + evaluationContext.explorePriority = 1; + break; + case Obj::REDWOOD_OBSERVATORY: + case Obj::PILLAR_OF_FIRE: + evaluationContext.explorePriority = 2; + break; + } + } + if (evaluationContext.explorePriority == 0) + evaluationContext.explorePriority = 3; } }; @@ -1320,7 +1339,7 @@ float PriorityEvaluator::evaluate(Goals::TSubgoal task, int priorityTier) float score = 0; float maxWillingToLose = ai->cb->getTownsInfo().empty() ? 1 : 0.25; #if NKAI_TRACE_LEVEL >= 2 - logAi->trace("BEFORE: priorityTier %d, Evaluated %s, loss: %f, turn: %d, turns main: %f, scout: %f, gold: %f, cost: %d, army gain: %f, army growth: %f skill: %f danger: %d, threatTurns: %d, threat: %d, role: %s, strategical value: %f, conquest value: %f cwr: %f, fear: %f, isDefend: %d", + logAi->trace("BEFORE: priorityTier %d, Evaluated %s, loss: %f, turn: %d, turns main: %f, scout: %f, gold: %f, cost: %d, army gain: %f, army growth: %f skill: %f danger: %d, threatTurns: %d, threat: %d, role: %s, strategical value: %f, conquest value: %f cwr: %f, fear: %f, explorePriority: %d isDefend: %d", priorityTier, task->toString(), evaluationContext.armyLossPersentage, @@ -1340,6 +1359,7 @@ float PriorityEvaluator::evaluate(Goals::TSubgoal task, int priorityTier) evaluationContext.conquestValue, evaluationContext.closestWayRatio, evaluationContext.enemyHeroDangerRatio, + evaluationContext.explorePriority, evaluationContext.isDefend); #endif @@ -1369,7 +1389,7 @@ float PriorityEvaluator::evaluate(Goals::TSubgoal task, int priorityTier) } case PriorityTier::KILL: //Take towns / kill heroes that are further away { - if (evaluationContext.conquestValue > 0) + if (evaluationContext.conquestValue > 0 || evaluationContext.explorePriority == 1) score = 1000; if (vstd::isAlmostZero(score) || (evaluationContext.enemyHeroDangerRatio > 1 && (evaluationContext.turn > 0 || evaluationContext.isExchange) && !ai->cb->getTownsInfo().empty())) return 0; @@ -1388,6 +1408,10 @@ float PriorityEvaluator::evaluate(Goals::TSubgoal task, int priorityTier) return 0; if (evaluationContext.isDefend && (evaluationContext.enemyHeroDangerRatio < 1 || evaluationContext.threatTurns > 0 || evaluationContext.turn > 0)) return 0; + if (evaluationContext.explorePriority == 3) + return 0; + if (evaluationContext.isArmyUpgrade) + return 0; score += evaluationContext.strategicalValue * 1000; score += evaluationContext.goldReward; score += evaluationContext.skillReward * evaluationContext.armyInvolvement * (1 - evaluationContext.armyLossPersentage) * 0.05; @@ -1397,8 +1421,6 @@ float PriorityEvaluator::evaluate(Goals::TSubgoal task, int priorityTier) score -= evaluationContext.armyInvolvement * evaluationContext.armyLossPersentage; if (score > 0) { - if(!evaluationContext.isExplore) - score = 1000; score *= evaluationContext.closestWayRatio; if (evaluationContext.enemyHeroDangerRatio > 1) score /= evaluationContext.enemyHeroDangerRatio; @@ -1408,11 +1430,23 @@ float PriorityEvaluator::evaluate(Goals::TSubgoal task, int priorityTier) } break; } + case PriorityTier::LOW_PRIO_EXPLORE: + { + if (evaluationContext.enemyHeroDangerRatio > 1) + return 0; + if (evaluationContext.explorePriority != 3) + return 0; + score = 1000; + score *= evaluationContext.closestWayRatio; + if (evaluationContext.movementCost > 0) + score /= evaluationContext.movementCost; + break; + } case PriorityTier::DEFEND: //Defend whatever if nothing else is to do { if (evaluationContext.enemyHeroDangerRatio > 1 && evaluationContext.isExchange) return 0; - if (evaluationContext.isDefend) + if (evaluationContext.isDefend || evaluationContext.isArmyUpgrade) score = 1000; score *= evaluationContext.closestWayRatio; score /= (evaluationContext.turn + 1); diff --git a/AI/Nullkiller/Engine/PriorityEvaluator.h b/AI/Nullkiller/Engine/PriorityEvaluator.h index c04e2477d..4978bd28f 100644 --- a/AI/Nullkiller/Engine/PriorityEvaluator.h +++ b/AI/Nullkiller/Engine/PriorityEvaluator.h @@ -49,7 +49,7 @@ public: uint64_t getUpgradeArmyReward(const CGTownInstance * town, const BuildingInfo & bi) const; const HitMapInfo & getEnemyHeroDanger(const int3 & tile, uint8_t turn) const; uint64_t townArmyGrowth(const CGTownInstance * town) const; - uint64_t getManaRecoveryArmyReward(const CGHeroInstance * hero) const; + float getManaRecoveryArmyReward(const CGHeroInstance * hero) const; }; struct DLL_EXPORT EvaluationContext @@ -80,7 +80,8 @@ struct DLL_EXPORT EvaluationContext bool involvesSailing; bool isTradeBuilding; bool isExchange; - bool isExplore; + bool isArmyUpgrade; + int explorePriority; EvaluationContext(const Nullkiller * ai); @@ -112,6 +113,7 @@ public: INSTADEFEND, KILL, HUNTER_GATHER, + LOW_PRIO_EXPLORE, DEFEND };