1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-01-26 03:52:01 +02:00

Nullkiller: fix priorities after refactoring

This commit is contained in:
Andrii Danylchenko 2021-05-16 14:39:47 +03:00 committed by Andrii Danylchenko
parent 1349eff201
commit cebb5b296b
14 changed files with 77 additions and 68 deletions

View File

@ -36,9 +36,9 @@ extern const int GOLD_RESERVE;
enum HeroRole
{
SCOUT,
SCOUT = 0,
MAIN
MAIN = 1
};
//provisional class for AI to store a reference to an owned hero object

View File

@ -363,12 +363,12 @@ ArmyUpgradeInfo ArmyManager::calculateCreateresUpgrade(
{
SlotInfo upgradedArmy;
upgradedArmy.creature = upgrade.upgradedCreature;
upgradedArmy.creature = upgrade.upgradedCreature.toCreature();
upgradedArmy.count = upgrade.count;
upgradedArmy.power = evaluateStackPower(upgradedArmy.creature, upgradedArmy.count);
auto slotToReplace = std::find_if(result.resultingArmy.begin(), result.resultingArmy.end(), [&](const SlotInfo & slot) -> bool {
return slot.count == upgradedArmy.count && slot.creature == upgrade.initialCreature;
return slot.count == upgradedArmy.count && slot.creature->idNumber == upgrade.initialCreature;
});
resourcesLeft -= upgrade.cost;

View File

@ -129,10 +129,12 @@ TGoalVec CompleteQuest::missionArt() const
if(!solutions.empty())
return solutions;
/*for(auto art : q.quest->m5arts)
CaptureObjectsBehavior findArts;
for(auto art : q.quest->m5arts)
{
solutions.push_back(sptr(GetArtOfType(art))); //TODO: transport?
}*/
solutions.push_back(sptr(CaptureObjectsBehavior().ofType(Obj::ARTIFACT, art)));
}
return solutions;
}
@ -223,21 +225,18 @@ TGoalVec CompleteQuest::missionDestroyObj() const
if(!obj)
return CaptureObjectsBehavior(q.obj).decompose();
if(obj->ID == Obj::HERO)
auto relations = cb->getPlayerRelations(ai->playerID, obj->tempOwner);
//if(relations == PlayerRelations::SAME_PLAYER)
//{
// auto heroToProtect = cb->getHero(obj->id);
// //solutions.push_back(sptr(GatherArmy().sethero(heroToProtect)));
//}
//else
if(relations == PlayerRelations::ENEMIES)
{
auto relations = cb->getPlayerRelations(ai->playerID, obj->tempOwner);
//if(relations == PlayerRelations::SAME_PLAYER)
//{
// auto heroToProtect = cb->getHero(obj->id);
// //solutions.push_back(sptr(GatherArmy().sethero(heroToProtect)));
//}
//else
if(relations == PlayerRelations::ENEMIES)
{
return CaptureObjectsBehavior(obj).decompose();
}
return CaptureObjectsBehavior(obj).decompose();
}
return TGoalVec();

View File

@ -35,14 +35,9 @@ Goals::TGoalVec DefenceBehavior::decompose() const
{
Goals::TGoalVec tasks;
auto heroes = cb->getHeroesInfo();
if(heroes.size())
for(auto town : cb->getTownsInfo())
{
for(auto town : cb->getTownsInfo())
{
evaluateDefence(tasks, town);
}
evaluateDefence(tasks, town);
}
return tasks;

View File

@ -474,7 +474,7 @@ public:
auto army = path.heroArmy;
vstd::amax(evaluationContext.armyLossPersentage, path.getTotalArmyLoss() / (double)path.getHeroStrength());
vstd::amax(evaluationContext.heroRole, ai->ah->getHeroRole(heroPtr));
evaluationContext.heroRole = ai->ah->getHeroRole(heroPtr);
evaluationContext.goldReward += getGoldReward(target, hero);
evaluationContext.armyReward += getArmyReward(target, hero, army, checkGold);
evaluationContext.skillReward += getSkillReward(target, hero, evaluationContext.heroRole);
@ -604,17 +604,18 @@ float PriorityEvaluator::evaluate(Goals::TSubgoal task)
}
assert(result >= 0);
#ifdef VCMI_TRACE_PATHFINDER
logAi->trace("Evaluated %s, loss: %f, turns main: %f, scout: %f, gold: %d, cost: %d, army gain: %d, danger: %d, role: %s, strategical value: %f, cwr: %f, result %f",
#ifdef AI_TRACE_LEVEL >= 1
logAi->trace("Evaluated %s, loss: %f, turn: %d, turns main: %f, scout: %f, gold: %d, cost: %d, army gain: %d, danger: %d, role: %s, strategical value: %f, cwr: %f, result %f",
task->toString(),
evaluationContext.armyLossPersentage,
(int)evaluationContext.turn,
evaluationContext.movementCostByRole[HeroRole::MAIN],
evaluationContext.movementCostByRole[HeroRole::SCOUT],
evaluationContext.goldReward,
evaluationContext.goldCost,
evaluationContext.armyReward,
evaluationContext.danger,
evaluationContext.heroRole ? "scout" : "main",
evaluationContext.heroRole == HeroRole::MAIN ? "main" : "scout",
evaluationContext.strategicalValue,
evaluationContext.closestWayRatio,
result);

View File

@ -214,7 +214,7 @@ void AINodeStorage::commit(
destination->theNodeBefore = source->theNodeBefore;
destination->chainOther = nullptr;
#if AI_TRACE_LEVEL >= 2
#if PATHFINDER_TRACE_LEVEL >= 2
logAi->trace(
"Commited %s -> %s, cost: %f, turn: %s, mp: %d, hero: %s, mask: %x, army: %lld",
source->coord.toString(),
@ -422,7 +422,7 @@ void AINodeStorage::calculateHeroChain(
|| (node->action == CGPathNode::ENodeAction::UNKNOWN && node->actor->hero)
|| (node->actor->chainMask & srcNode->actor->chainMask) != 0)
{
#if AI_TRACE_LEVEL >= 2
#if PATHFINDER_TRACE_LEVEL >= 2
logAi->trace(
"Skip exchange %s[%x] -> %s[%x] at %s because of %s",
node->actor->toString(),
@ -439,7 +439,7 @@ void AINodeStorage::calculateHeroChain(
continue;
}
#if AI_TRACE_LEVEL >= 2
#if PATHFINDER_TRACE_LEVEL >= 2
logAi->trace(
"Thy exchange %s[%x] -> %s[%x] at %s",
node->actor->toString(),
@ -464,7 +464,7 @@ void AINodeStorage::calculateHeroChain(
&& (other->armyLoss == 0 || other->armyLoss < other->actor->armyValue)
&& carrier->actor->canExchange(other->actor))
{
#if AI_TRACE_LEVEL >= 2
#if PATHFINDER_TRACE_LEVEL >= 2
logAi->trace(
"Exchange allowed %s[%x] -> %s[%x] at %s",
other->actor->toString(),
@ -481,7 +481,7 @@ void AINodeStorage::calculateHeroChain(
if(hasLessMp && hasLessExperience)
{
#if AI_TRACE_LEVEL >= 2
#if PATHFINDER_TRACE_LEVEL >= 2
logAi->trace("Exchange at %s is ineficient. Blocked.", carrier->coord.toString());
#endif
return;
@ -505,7 +505,7 @@ void AINodeStorage::addHeroChain(const std::vector<ExchangeCandidate> & result)
if(!chainNodeOptional)
{
#if AI_TRACE_LEVEL >= 2
#if PATHFINDER_TRACE_LEVEL >= 2
logAi->trace("Exchange at %s can not allocate node. Blocked.", carrier->coord.toString());
#endif
continue;
@ -515,7 +515,7 @@ void AINodeStorage::addHeroChain(const std::vector<ExchangeCandidate> & result)
if(exchangeNode->action != CGPathNode::ENodeAction::UNKNOWN)
{
#if AI_TRACE_LEVEL >= 2
#if PATHFINDER_TRACE_LEVEL >= 2
logAi->trace("Exchange at %s node is already in use. Blocked.", carrier->coord.toString());
#endif
continue;
@ -523,7 +523,7 @@ void AINodeStorage::addHeroChain(const std::vector<ExchangeCandidate> & result)
if(exchangeNode->turns != 0xFF && exchangeNode->cost < chainInfo.cost)
{
#if AI_TRACE_LEVEL >= 2
#if PATHFINDER_TRACE_LEVEL >= 2
logAi->trace(
"Exchange at %s is is not effective enough. %f < %f",
exchangeNode->coord.toString(),
@ -544,7 +544,7 @@ void AINodeStorage::addHeroChain(const std::vector<ExchangeCandidate> & result)
exchangeNode->chainOther = other;
exchangeNode->armyLoss = chainInfo.armyLoss;
#if AI_TRACE_LEVEL >= 2
#if PATHFINDER_TRACE_LEVEL >= 2
logAi->trace(
"Chain accepted at %s %s -> %s, mask %x, cost %f, turn: %s, mp: %d, army %i",
exchangeNode->coord.toString(),
@ -858,7 +858,7 @@ void AINodeStorage::calculateTownPortalTeleportations(std::vector<CGPathNode *>
if(nodeOptional)
{
#if AI_TRACE_LEVEL >= 1
#if PATHFINDER_TRACE_LEVEL >= 1
logAi->trace("Adding town portal node at %s", targetTown->name);
#endif
initialNodes.push_back(nodeOptional.get());
@ -897,7 +897,7 @@ bool AINodeStorage::hasBetterChain(
{
if(node.cost < candidateNode->cost)
{
#if AI_TRACE_LEVEL >= 2
#if PATHFINDER_TRACE_LEVEL >= 2
logAi->trace(
"Block ineficient battle move %s->%s, hero: %s[%X], army %lld, mp diff: %i",
source->coord.toString(),
@ -921,7 +921,7 @@ bool AINodeStorage::hasBetterChain(
if(nodeArmyValue > candidateArmyValue
&& node.cost <= candidateNode->cost)
{
#if AI_TRACE_LEVEL >= 2
#if PATHFINDER_TRACE_LEVEL >= 2
logAi->trace(
"Block ineficient move because of stronger army %s->%s, hero: %s[%X], army %lld, mp diff: %i",
source->coord.toString(),

View File

@ -10,8 +10,8 @@
#pragma once
#define VCMI_TRACE_PATHFINDER 1
#define AI_TRACE_LEVEL 1
#define PATHFINDER_TRACE_LEVEL 1
#define AI_TRACE_LEVEL 2
#include "../../../lib/CPathfinder.h"
#include "../../../lib/mapObjects/CGHeroInstance.h"

View File

@ -36,7 +36,8 @@ namespace AIPathfinding
return dynamic_cast<const IQuestObject *>(questInfo.obj)->checkQuest(node->actor->hero);
}
return questInfo.quest->checkQuest(node->actor->hero);
return questInfo.quest->progress == CQuest::NOT_ACTIVE
|| questInfo.quest->checkQuest(node->actor->hero);
}
Goals::TSubgoal QuestAction::decompose(const CGHeroInstance * hero) const

View File

@ -172,7 +172,7 @@ bool HeroExchangeMap::canExchange(const ChainActor * other)
if(!resources.canAfford(actor->armyCost + other->armyCost))
{
result = false;
#if AI_TRACE_LEVEL >= 2
#if PATHFINDER_TRACE_LEVEL >= 2
logAi->trace(
"Can not afford exchange because of total cost %s but we have %s",
(actor->armyCost + other->armyCost).toString(),
@ -191,7 +191,7 @@ bool HeroExchangeMap::canExchange(const ChainActor * other)
if(other->creatureSet->Slots().size())
reinforcment += ai->ah->howManyReinforcementsCanGet(actor->creatureSet, other->creatureSet);
#if AI_TRACE_LEVEL >= 2
#if PATHFINDER_TRACE_LEVEL >= 2
logAi->trace(
"Exchange %s->%s reinforcement: %d, %f%%",
actor->toString(),

View File

@ -37,7 +37,7 @@ namespace AIPathfinding
if(virtualBoat && tryEmbarkVirtualBoat(destination, source, virtualBoat))
{
#ifdef VCMI_TRACE_PATHFINDER
#if PATHFINDER_TRACE_LEVEL >= 1
logAi->trace("Embarking to virtual boat while moving %s -> %s!", source.coord.toString(), destination.coord.toString());
#endif
}
@ -138,7 +138,7 @@ namespace AIPathfinding
}
else
{
#ifdef VCMI_TRACE_PATHFINDER
#if PATHFINDER_TRACE_LEVEL >= 1
logAi->trace(
"Special transition node already allocated. Blocked moving %s -> %s",
source.coord.toString(),

View File

@ -102,6 +102,11 @@ namespace AIPathfinding
auto questObj = dynamic_cast<const IQuestObject *>(destination.nodeObject);
auto nodeHero = pathfinderHelper->hero;
if(destination.nodeObject->ID == Obj::QUEST_GUARD && questObj->quest->missionType == CQuest::MISSION_NONE)
{
return false;
}
if(!destination.nodeObject->wasVisited(nodeHero->tempOwner)
|| !questObj->checkQuest(nodeHero))
{
@ -154,7 +159,7 @@ namespace AIPathfinding
if(guardsAlreadyBypassed && srcNode->actor->allowBattle)
{
#ifdef VCMI_TRACE_PATHFINDER
#if PATHFINDER_TRACE_LEVEL >= 1
logAi->trace(
"Bypass guard at destination while moving %s -> %s",
source.coord.toString(),
@ -182,7 +187,7 @@ namespace AIPathfinding
if(!battleNodeOptional)
{
#ifdef VCMI_TRACE_PATHFINDER
#if PATHFINDER_TRACE_LEVEL >= 1
logAi->trace(
"Can not allocate battle node while moving %s -> %s",
source.coord.toString(),
@ -195,7 +200,7 @@ namespace AIPathfinding
if(battleNode->locked)
{
#ifdef VCMI_TRACE_PATHFINDER
#if PATHFINDER_TRACE_LEVEL >= 1
logAi->trace(
"Block bypass guard at destination while moving %s -> %s",
source.coord.toString(),
@ -222,7 +227,7 @@ namespace AIPathfinding
battleNode->specialAction = std::make_shared<BattleAction>(destination.coord);
#ifdef VCMI_TRACE_PATHFINDER
#if PATHFINDER_TRACE_LEVEL >= 1
logAi->trace(
"Begin bypass guard at destination with danger %s while moving %s -> %s",
std::to_string(danger),

View File

@ -37,7 +37,7 @@ namespace AIPathfinding
if(blocker == BlockingReason::SOURCE_GUARDED && nodeStorage->getAINode(source.node)->actor->allowBattle)
{
#ifdef VCMI_TRACE_PATHFINDER
#if PATHFINDER_TRACE_LEVEL >= 1
logAi->trace(
"Bypass src guard while moving from %s to %s",
source.coord.toString(),

View File

@ -27,7 +27,8 @@ namespace AIPathfinding
{
// we can not directly bypass objects, we need to interact with them first
destination.node->theNodeBefore = source.node;
#ifdef VCMI_TRACE_PATHFINDER
#if PATHFINDER_TRACE_LEVEL >= 1
logAi->trace(
"Link src node %s to destination node %s while bypassing visitable obj",
source.coord.toString(),

View File

@ -569,12 +569,11 @@ void VCAI::showBlockingDialog(const std::string & text, const std::vector<Compon
{
LOG_TRACE_PARAMS(logAi, "text '%s', askID '%i', soundID '%i', selection '%i', cancel '%i'", text % askID % soundID % selection % cancel);
NET_EVENT_HANDLER;
int sel = 0;
status.addQuery(askID, boost::str(boost::format("Blocking dialog query with %d components - %s")
% components.size() % text));
if(selection) //select from multiple components -> take the last one (they're indexed [1-size])
sel = components.size();
auto hero = nullkiller->getActiveHero();
auto target = nullkiller->getTargetTile();
if(!selection && cancel)
{
@ -582,8 +581,6 @@ void VCAI::showBlockingDialog(const std::string & text, const std::vector<Compon
{
//yes&no -> always answer yes, we are a brave AI :)
auto answer = 1;
auto hero = nullkiller->getActiveHero();
auto target = nullkiller->getTargetTile();
auto objects = cb->getVisitableObjs(target);
if(hero.validAndSet() && target.valid() && objects.size())
@ -608,14 +605,21 @@ void VCAI::showBlockingDialog(const std::string & text, const std::vector<Compon
return;
}
// TODO: Find better way to understand it is Chest of Treasures
if(components.size() == 2 && components.front().id == Component::RESOURCE)
{
sel = 1; // for now lets pick gold from a chest.
}
requestActionASAP([=]()
{
int sel = 0;
if(selection) //select from multiple components -> take the last one (they're indexed [1-size])
sel = components.size();
// TODO: Find better way to understand it is Chest of Treasures
if(components.size() == 2
&& components.front().id == Component::RESOURCE
&& ah->getHeroRole(hero) != HeroRole::MAIN)
{
sel = 1; // for now lets pick gold from a chest.
}
answerQuery(askID, sel);
});
}
@ -2026,6 +2030,9 @@ bool shouldVisit(HeroPtr h, const CGObjectInstance * obj)
break;
case Obj::TREE_OF_KNOWLEDGE:
{
if(ai->ah->getHeroRole(h) == HeroRole::SCOUT)
return false;
TResources myRes = cb->getResourceAmount();
if(myRes[Res::GOLD] < 2000 || myRes[Res::GEMS] < 10)
return false;