From e6bb39d3a4ddd36e9ac5516de1673028b51ece47 Mon Sep 17 00:00:00 2001 From: DjWarmonger Date: Sat, 23 Nov 2013 12:30:10 +0000 Subject: [PATCH] More work on VCAI Goals, still derived functions are not called :/ --- AI/VCAI/Goals.h | 8 +++++- AI/VCAI/VCAI.cpp | 58 ++++++++++++++++++++------------------ AI/VCAI/VCAI.h | 2 +- lib/CObjectHandler.cpp | 64 +++++++++++++++++++++--------------------- 4 files changed, 70 insertions(+), 62 deletions(-) diff --git a/AI/VCAI/Goals.h b/AI/VCAI/Goals.h index b4534a14d..dca629560 100644 --- a/AI/VCAI/Goals.h +++ b/AI/VCAI/Goals.h @@ -128,8 +128,10 @@ public: tile = int3(-1, -1, -1); town = nullptr; } + //virtual TSubgoal whatToDoToAchieve() override; + OSETTER(bool, isElementar) - OSETTER(bool, isAbstract) //FIXME: find out why this setter does not compile? + OSETTER(bool, isAbstract) OSETTER(bool, priority) OSETTER(int, value) OSETTER(int, resID) @@ -143,6 +145,10 @@ public: { return make_shared> (setisElementar(true)); } + template void serialize(Handler &h, const int version) + { + h & static_cast(*this); + } }; //There seems to be some ambiguity on these two, template function keeps form consitent diff --git a/AI/VCAI/VCAI.cpp b/AI/VCAI/VCAI.cpp index a2dc3ddb4..e69c6e6a8 100644 --- a/AI/VCAI/VCAI.cpp +++ b/AI/VCAI/VCAI.cpp @@ -1,5 +1,6 @@ #include "StdInc.h" #include "VCAI.h" +#include "Goals.h" #include "../../lib/UnlockGuard.h" #include "../../lib/CObjectHandler.h" #include "../../lib/CConfigHandler.h" @@ -713,12 +714,12 @@ void VCAI::makeTurnInternal() logAi->errorStream() << "Error: there is wrong object on list for hero " << hero.first->name; continue; } - striveToGoal (Goals::VisitTile(obj->visitablePos()).sethero(hero.first)); + striveToGoal (sptr(Goals::VisitTile(obj->visitablePos()).sethero(hero.first))); } } //now try to win - striveToGoal(Goals::Win()); + striveToGoal(sptr(Goals::Win())); //finally, continue our abstract long-term goals @@ -740,7 +741,7 @@ void VCAI::makeTurnInternal() if (it->first && it->first->tempOwner == playerID && vstd::contains(lockedHeroes, it->first)) //make sure hero still has his goal { cb->setSelection(*it->first); - striveToGoal (it->second); + striveToGoal (make_shared(it->second)); } safeCopy.erase(it); } @@ -751,7 +752,7 @@ void VCAI::makeTurnInternal() striveToQuest (quest); } - striveToGoal(Goals::Build()); //TODO: smarter building management + striveToGoal(sptr(Goals::Build())); //TODO: smarter building management } catch(boost::thread_interrupted &e) { @@ -1156,7 +1157,7 @@ void VCAI::wander(HeroPtr h) const CGTownInstance *t = townsNotReachable.back(); logAi->debugStream() << boost::format("%s can't reach any town, we'll try to make our way to %s at %s") % h->name % t->name % t->visitablePos(); int3 pos1 = h->pos; - striveToGoal(Goals::VisitTile(t->visitablePos()).sethero(h)); + striveToGoal(sptr(Goals::VisitTile(t->visitablePos()).sethero(h))); if (pos1 == h->pos && h == primaryHero()) //hero can't move { if(cb->getResourceAmount(Res::GOLD) >= HERO_GOLD_COST && cb->getHeroesInfo().size() < ALLOWED_ROAMING_HEROES && cb->getAvailableHeroes(t).size()) @@ -1687,18 +1688,19 @@ bool VCAI::fulfillsGoal (Goals::AbstractGoal &goal, const Goals::AbstractGoal &m return fulfillsGoal (goal, const_cast(mainGoal)); } -void VCAI::striveToGoal(const Goals::AbstractGoal &ultimateGoal) +void VCAI::striveToGoal(Goals::TSubgoal ultimateGoal) { - if (ultimateGoal.invalid()) + if (ultimateGoal->invalid()) return; - std::shared_ptr abstractGoal = make_shared(Goals::Invalid()); + Goals::TSubgoal abstractGoal = sptr(Goals::Invalid()); while(1) { - std::shared_ptr goal = make_shared(ultimateGoal); //FIXME: preserve subclass of goal - logAi->debugStream() << boost::format("Striving to goal of type %s") % ultimateGoal.name(); - int maxGoals = 100; //preventing deadlock for mutually dependent goals, FIXME: do not try to realize goal when loop didn't suceed + Goals::TSubgoal goal = ultimateGoal; //FIXME: preserve subclass of goal + logAi->debugStream() << boost::format("Striving to goal of type %s") % ultimateGoal->name(); + int maxGoals = 100; //preventing deadlock for mutually dependent goals + //FIXME: do not try to realize goal when loop didn't suceed while(!goal->isElementar && !goal->isAbstract && maxGoals) { logAi->debugStream() << boost::format("Considering goal %s") % goal->name(); @@ -1757,12 +1759,12 @@ void VCAI::striveToGoal(const Goals::AbstractGoal &ultimateGoal) catch(goalFulfilledException &e) { completeGoal (*goal); - if (fulfillsGoal (*goal, ultimateGoal) || maxGoals > 98) //completed goal was main goal //TODO: find better condition + if (fulfillsGoal (*goal, *ultimateGoal.get()) || maxGoals > 98) //completed goal was main goal //TODO: find better condition return; } catch(std::exception &e) { - logAi->debugStream() << boost::format("Failed to realize subgoal of type %s (greater goal type was %s), I will stop.") % goal->name() % ultimateGoal.name(); + logAi->debugStream() << boost::format("Failed to realize subgoal of type %s (greater goal type was %s), I will stop.") % goal->name() % ultimateGoal->name(); logAi->debugStream() << boost::format("The error message was: %s") % e.what(); break; } @@ -1816,7 +1818,7 @@ void VCAI::striveToGoal(const Goals::AbstractGoal &ultimateGoal) } catch(std::exception &e) { - logAi->debugStream() << boost::format("Failed to realize subgoal of type %s (greater goal type was %s), I will stop.") % goal->name() % ultimateGoal.name(); + logAi->debugStream() << boost::format("Failed to realize subgoal of type %s (greater goal type was %s), I will stop.") % goal->name() % ultimateGoal->name(); logAi->debugStream() << boost::format("The error message was: %s") % e.what(); break; } @@ -1841,13 +1843,13 @@ void VCAI::striveToQuest (const QuestInfo &q) { if (q.quest->checkQuest(hero)) { - striveToGoal (Goals::GetObj(q.obj->id.getNum()).sethero(hero)); + striveToGoal (sptr(Goals::GetObj(q.obj->id.getNum()).sethero(hero))); return; } } for (auto art : q.quest->m5arts) { - striveToGoal (Goals::GetArtOfType(art)); //TODO: transport? + striveToGoal (sptr(Goals::GetArtOfType(art))); //TODO: transport? } break; } @@ -1858,11 +1860,11 @@ void VCAI::striveToQuest (const QuestInfo &q) { if (q.quest->checkQuest(hero)) { - striveToGoal (Goals::GetObj(q.obj->id.getNum()).sethero(hero)); + striveToGoal (sptr(Goals::GetObj(q.obj->id.getNum()).sethero(hero))); return; } } - striveToGoal (Goals::FindObj(Obj::PRISON)); //rule of a thumb - quest heroes usually are locked in prisons + striveToGoal (sptr(Goals::FindObj(Obj::PRISON))); //rule of a thumb - quest heroes usually are locked in prisons //BNLOG ("Don't know how to recruit hero with id %d\n", q.quest->m13489val); break; } @@ -1872,13 +1874,13 @@ void VCAI::striveToQuest (const QuestInfo &q) { if (q.quest->checkQuest(hero)) //veyr bad info - stacks can be split between multiple heroes :( { - striveToGoal (Goals::GetObj(q.obj->id.getNum()).sethero(hero)); + striveToGoal (sptr(Goals::GetObj(q.obj->id.getNum()).sethero(hero))); return; } } for (auto creature : q.quest->m6creatures) { - striveToGoal (Goals::GatherTroops(creature.type->idNumber, creature.count)); + striveToGoal (sptr(Goals::GatherTroops(creature.type->idNumber, creature.count))); } //TODO: exchange armies... oh my //BNLOG ("Don't know how to recruit %d of %s\n", (int)(creature.count) % creature.type->namePl); @@ -1890,19 +1892,19 @@ void VCAI::striveToQuest (const QuestInfo &q) { if (q.quest->checkQuest(heroes.front())) //it doesn't matter which hero it is { - striveToGoal (Goals::VisitTile(q.tile)); + striveToGoal (sptr(Goals::VisitTile(q.tile))); } else { for (int i = 0; i < q.quest->m7resources.size(); ++i) { if (q.quest->m7resources[i]) - striveToGoal (Goals::CollectRes(i, q.quest->m7resources[i])); + striveToGoal (sptr(Goals::CollectRes(i, q.quest->m7resources[i]))); } } } else - striveToGoal (Goals::RecruitHero()); //FIXME: checkQuest requires any hero belonging to player :( + striveToGoal (sptr(Goals::RecruitHero())); //FIXME: checkQuest requires any hero belonging to player :( break; } case CQuest::MISSION_KILL_HERO: @@ -1910,9 +1912,9 @@ void VCAI::striveToQuest (const QuestInfo &q) { auto obj = cb->getObjByQuestIdentifier(q.quest->m13489val); if (obj) - striveToGoal (Goals::GetObj(obj->id.getNum())); + striveToGoal (sptr(Goals::GetObj(obj->id.getNum()))); else - striveToGoal (Goals::VisitTile(q.tile)); //visit seer hut + striveToGoal (sptr(Goals::VisitTile(q.tile))); //visit seer hut break; } case CQuest::MISSION_PRIMARY_STAT: @@ -1922,7 +1924,7 @@ void VCAI::striveToQuest (const QuestInfo &q) { if (q.quest->checkQuest(hero)) { - striveToGoal (Goals::GetObj(q.obj->id.getNum()).sethero(hero)); + striveToGoal (sptr(Goals::GetObj(q.obj->id.getNum()).sethero(hero))); return; } } @@ -1939,7 +1941,7 @@ void VCAI::striveToQuest (const QuestInfo &q) { if (q.quest->checkQuest(hero)) { - striveToGoal (Goals::VisitTile(q.tile).sethero(hero)); //TODO: causes infinite loop :/ + striveToGoal (sptr(Goals::VisitTile(q.tile).sethero(hero))); //TODO: causes infinite loop :/ return; } } @@ -1954,7 +1956,7 @@ void VCAI::striveToQuest (const QuestInfo &q) } case CQuest::MISSION_KEYMASTER: { - striveToGoal (Goals::FindObj(Obj::KEYMASTER, q.obj->subID)); + striveToGoal (sptr(Goals::FindObj(Obj::KEYMASTER, q.obj->subID))); break; } } diff --git a/AI/VCAI/VCAI.h b/AI/VCAI/VCAI.h index 12c6c6c6c..de7954ce7 100644 --- a/AI/VCAI/VCAI.h +++ b/AI/VCAI/VCAI.h @@ -231,7 +231,7 @@ public: void performTypicalActions(); void buildArmyIn(const CGTownInstance * t); - void striveToGoal(const Goals::AbstractGoal & ultimateGoal); + void striveToGoal(Goals::TSubgoal ultimateGoal); void endTurn(); void wander(HeroPtr h); void setGoal(HeroPtr h, const Goals::AbstractGoal &goal); diff --git a/lib/CObjectHandler.cpp b/lib/CObjectHandler.cpp index ffee95835..8dca5e285 100644 --- a/lib/CObjectHandler.cpp +++ b/lib/CObjectHandler.cpp @@ -2112,13 +2112,13 @@ int CGTownInstance::creatureDwellingLevel(int dwelling) const if (!hasBuilt(BuildingID(BuildingID::DWELL_FIRST+dwelling+i*GameConstants::CREATURES_PER_TOWN))) return i-1; } -} -int CGTownInstance::getHordeLevel(const int & HID) const//HID - 0 or 1; returns creature level or -1 if that horde structure is not present -{ - return town->hordeLvl.at(HID); -} -int CGTownInstance::creatureGrowth(const int & level) const -{ +} +int CGTownInstance::getHordeLevel(const int & HID) const//HID - 0 or 1; returns creature level or -1 if that horde structure is not present +{ + return town->hordeLvl.at(HID); +} +int CGTownInstance::creatureGrowth(const int & level) const +{ return getGrowthInfo(level).totalGrowth(); } @@ -2139,17 +2139,17 @@ GrowthInfo CGTownInstance::getGrowthInfo(int level) const if (hasBuilt(BuildingID::CASTLE)) ret.entries.push_back(GrowthInfo::Entry(subID, BuildingID::CASTLE, castleBonus = base)); - else if (hasBuilt(BuildingID::CITADEL)) - ret.entries.push_back(GrowthInfo::Entry(subID, BuildingID::CITADEL, castleBonus = base / 2)); - - if(town->hordeLvl.at(0) == level)//horde 1 - if(hasBuilt(BuildingID::HORDE_1)) - ret.entries.push_back(GrowthInfo::Entry(subID, BuildingID::HORDE_1, creature->hordeGrowth)); - - if(town->hordeLvl.at(1) == level)//horde 2 - if(hasBuilt(BuildingID::HORDE_2)) - ret.entries.push_back(GrowthInfo::Entry(subID, BuildingID::HORDE_2, creature->hordeGrowth)); - + else if (hasBuilt(BuildingID::CITADEL)) + ret.entries.push_back(GrowthInfo::Entry(subID, BuildingID::CITADEL, castleBonus = base / 2)); + + if(town->hordeLvl.at(0) == level)//horde 1 + if(hasBuilt(BuildingID::HORDE_1)) + ret.entries.push_back(GrowthInfo::Entry(subID, BuildingID::HORDE_1, creature->hordeGrowth)); + + if(town->hordeLvl.at(1) == level)//horde 2 + if(hasBuilt(BuildingID::HORDE_2)) + ret.entries.push_back(GrowthInfo::Entry(subID, BuildingID::HORDE_2, creature->hordeGrowth)); + int dwellingBonus = 0; if(const PlayerState *p = cb->getPlayer(tempOwner, false)) { @@ -2617,13 +2617,13 @@ bool CGTownInstance::addBonusIfBuilt(BuildingID building, Bonus::BonusType type, bool CGTownInstance::addBonusIfBuilt(BuildingID building, Bonus::BonusType type, int val, TPropagatorPtr & prop, int subtype /*= -1*/) { - if(hasBuilt(building)) - { - std::ostringstream descr; - descr << town->buildings.at(building)->Name() << " "; - if(val > 0) - descr << "+"; - else if(val < 0) + if(hasBuilt(building)) + { + std::ostringstream descr; + descr << town->buildings.at(building)->Name() << " "; + if(val > 0) + descr << "+"; + else if(val < 0) descr << "-"; descr << val; @@ -2692,13 +2692,13 @@ bool CGTownInstance::armedGarrison() const int CGTownInstance::getTownLevel() const { - // count all buildings that are not upgrades - return boost::range::count_if(builtBuildings, [&](const BuildingID & build) - { - return town->buildings.at(build) && town->buildings.at(build)->upgrade == -1; - }); -} - + // count all buildings that are not upgrades + return boost::range::count_if(builtBuildings, [&](const BuildingID & build) + { + return town->buildings.at(build) && town->buildings.at(build)->upgrade == -1; + }); +} + CBonusSystemNode * CGTownInstance::whatShouldBeAttached() { return &townAndVis;