1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-02-03 13:01:33 +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 enum HeroRole
{ {
SCOUT, SCOUT = 0,
MAIN MAIN = 1
}; };
//provisional class for AI to store a reference to an owned hero object //provisional class for AI to store a reference to an owned hero object

View File

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

View File

@ -129,10 +129,12 @@ TGoalVec CompleteQuest::missionArt() const
if(!solutions.empty()) if(!solutions.empty())
return solutions; 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; return solutions;
} }
@ -223,21 +225,18 @@ TGoalVec CompleteQuest::missionDestroyObj() const
if(!obj) if(!obj)
return CaptureObjectsBehavior(q.obj).decompose(); 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); return CaptureObjectsBehavior(obj).decompose();
//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 TGoalVec(); return TGoalVec();

View File

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

View File

@ -474,7 +474,7 @@ public:
auto army = path.heroArmy; auto army = path.heroArmy;
vstd::amax(evaluationContext.armyLossPersentage, path.getTotalArmyLoss() / (double)path.getHeroStrength()); 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.goldReward += getGoldReward(target, hero);
evaluationContext.armyReward += getArmyReward(target, hero, army, checkGold); evaluationContext.armyReward += getArmyReward(target, hero, army, checkGold);
evaluationContext.skillReward += getSkillReward(target, hero, evaluationContext.heroRole); evaluationContext.skillReward += getSkillReward(target, hero, evaluationContext.heroRole);
@ -604,17 +604,18 @@ float PriorityEvaluator::evaluate(Goals::TSubgoal task)
} }
assert(result >= 0); assert(result >= 0);
#ifdef VCMI_TRACE_PATHFINDER #ifdef AI_TRACE_LEVEL >= 1
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", 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(), task->toString(),
evaluationContext.armyLossPersentage, evaluationContext.armyLossPersentage,
(int)evaluationContext.turn,
evaluationContext.movementCostByRole[HeroRole::MAIN], evaluationContext.movementCostByRole[HeroRole::MAIN],
evaluationContext.movementCostByRole[HeroRole::SCOUT], evaluationContext.movementCostByRole[HeroRole::SCOUT],
evaluationContext.goldReward, evaluationContext.goldReward,
evaluationContext.goldCost, evaluationContext.goldCost,
evaluationContext.armyReward, evaluationContext.armyReward,
evaluationContext.danger, evaluationContext.danger,
evaluationContext.heroRole ? "scout" : "main", evaluationContext.heroRole == HeroRole::MAIN ? "main" : "scout",
evaluationContext.strategicalValue, evaluationContext.strategicalValue,
evaluationContext.closestWayRatio, evaluationContext.closestWayRatio,
result); result);

View File

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

View File

@ -10,8 +10,8 @@
#pragma once #pragma once
#define VCMI_TRACE_PATHFINDER 1 #define PATHFINDER_TRACE_LEVEL 1
#define AI_TRACE_LEVEL 1 #define AI_TRACE_LEVEL 2
#include "../../../lib/CPathfinder.h" #include "../../../lib/CPathfinder.h"
#include "../../../lib/mapObjects/CGHeroInstance.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 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 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)) if(!resources.canAfford(actor->armyCost + other->armyCost))
{ {
result = false; result = false;
#if AI_TRACE_LEVEL >= 2 #if PATHFINDER_TRACE_LEVEL >= 2
logAi->trace( logAi->trace(
"Can not afford exchange because of total cost %s but we have %s", "Can not afford exchange because of total cost %s but we have %s",
(actor->armyCost + other->armyCost).toString(), (actor->armyCost + other->armyCost).toString(),
@ -191,7 +191,7 @@ bool HeroExchangeMap::canExchange(const ChainActor * other)
if(other->creatureSet->Slots().size()) if(other->creatureSet->Slots().size())
reinforcment += ai->ah->howManyReinforcementsCanGet(actor->creatureSet, other->creatureSet); reinforcment += ai->ah->howManyReinforcementsCanGet(actor->creatureSet, other->creatureSet);
#if AI_TRACE_LEVEL >= 2 #if PATHFINDER_TRACE_LEVEL >= 2
logAi->trace( logAi->trace(
"Exchange %s->%s reinforcement: %d, %f%%", "Exchange %s->%s reinforcement: %d, %f%%",
actor->toString(), actor->toString(),

View File

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

View File

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

View File

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

View File

@ -27,7 +27,8 @@ namespace AIPathfinding
{ {
// we can not directly bypass objects, we need to interact with them first // we can not directly bypass objects, we need to interact with them first
destination.node->theNodeBefore = source.node; destination.node->theNodeBefore = source.node;
#ifdef VCMI_TRACE_PATHFINDER
#if PATHFINDER_TRACE_LEVEL >= 1
logAi->trace( logAi->trace(
"Link src node %s to destination node %s while bypassing visitable obj", "Link src node %s to destination node %s while bypassing visitable obj",
source.coord.toString(), 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); LOG_TRACE_PARAMS(logAi, "text '%s', askID '%i', soundID '%i', selection '%i', cancel '%i'", text % askID % soundID % selection % cancel);
NET_EVENT_HANDLER; NET_EVENT_HANDLER;
int sel = 0;
status.addQuery(askID, boost::str(boost::format("Blocking dialog query with %d components - %s") status.addQuery(askID, boost::str(boost::format("Blocking dialog query with %d components - %s")
% components.size() % text)); % components.size() % text));
if(selection) //select from multiple components -> take the last one (they're indexed [1-size]) auto hero = nullkiller->getActiveHero();
sel = components.size(); auto target = nullkiller->getTargetTile();
if(!selection && cancel) 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 :) //yes&no -> always answer yes, we are a brave AI :)
auto answer = 1; auto answer = 1;
auto hero = nullkiller->getActiveHero();
auto target = nullkiller->getTargetTile();
auto objects = cb->getVisitableObjs(target); auto objects = cb->getVisitableObjs(target);
if(hero.validAndSet() && target.valid() && objects.size()) if(hero.validAndSet() && target.valid() && objects.size())
@ -608,14 +605,21 @@ void VCAI::showBlockingDialog(const std::string & text, const std::vector<Compon
return; 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([=]() 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); answerQuery(askID, sel);
}); });
} }
@ -2026,6 +2030,9 @@ bool shouldVisit(HeroPtr h, const CGObjectInstance * obj)
break; break;
case Obj::TREE_OF_KNOWLEDGE: case Obj::TREE_OF_KNOWLEDGE:
{ {
if(ai->ah->getHeroRole(h) == HeroRole::SCOUT)
return false;
TResources myRes = cb->getResourceAmount(); TResources myRes = cb->getResourceAmount();
if(myRes[Res::GOLD] < 2000 || myRes[Res::GEMS] < 10) if(myRes[Res::GOLD] < 2000 || myRes[Res::GEMS] < 10)
return false; return false;