From bdd71b4f3841574a8afeabc2ce397a741892fb7f Mon Sep 17 00:00:00 2001 From: DjWarmonger Date: Mon, 5 Mar 2012 19:11:28 +0000 Subject: [PATCH] AI can now use external dwellings. AI will weekly revisit dwellings & mills. --- AI/VCAI/Fuzzy.cpp | 2 +- AI/VCAI/VCAI.cpp | 86 +++++++++++++++++++++++++-------------------- AI/VCAI/VCAI.h | 12 +++++-- lib/GameConstants.h | 27 ++++++++++++++ 4 files changed, 85 insertions(+), 42 deletions(-) diff --git a/AI/VCAI/Fuzzy.cpp b/AI/VCAI/Fuzzy.cpp index 1b212777c..6f6321512 100644 --- a/AI/VCAI/Fuzzy.cpp +++ b/AI/VCAI/Fuzzy.cpp @@ -190,7 +190,7 @@ void FuzzyHelper::initTacticalAdvantage() tacticalAdvantage.addRule(new fl::MamdaniRule("if OurShooters is MANY and EnemySpeed is LOW then Threat is very LOW", engine)); tacticalAdvantage.addRule(new fl::MamdaniRule("if OurSpeed is LOW and OurShooters is FEW and EnemyShooters is MANY then Threat is very HIGH", engine)); - tacticalAdvantage.addRule(new fl::MamdaniRule("if (OurShooters is MANY or OurFlyers is MANY) and EnemyShooters is MANY then Threat is LOW", engine)); + tacticalAdvantage.addRule(new fl::MamdaniRule("if (OurShooters is MANY and OurFlyers is MANY) and EnemyShooters is MANY then Threat is LOW", engine)); tacticalAdvantage.addRule(new fl::MamdaniRule("if OurShooters is MANY and EnemySpeed is HIGH then Threat is somewhat HIGH", engine)); //tacticalAdvantage.addRule(new fl::MamdaniRule("if OurShooters is MANY and EnemyShooters is MANY then Threat is MEDIUM", engine)); diff --git a/AI/VCAI/VCAI.cpp b/AI/VCAI/VCAI.cpp index 6dbb56c26..f8395b7bc 100644 --- a/AI/VCAI/VCAI.cpp +++ b/AI/VCAI/VCAI.cpp @@ -9,6 +9,8 @@ CLogger &aiLogger = tlog6; extern FuzzyHelper fh; +class CGVisitableOPW; + const int ACTUAL_RESOURCE_COUNT = 7; const double SAFE_ATTACK_CONSTANT = 1.5; @@ -59,33 +61,6 @@ bool compareArmyStrength(const CArmedInstance *a1, const CArmedInstance *a2) return a1->getArmyStrength() < a2->getArmyStrength(); } -//TODO integrate with that constants file -namespace Obj -{ - enum - { - BOAT = 8, - CREATURE_BANK = 16, - CREATURE_GENERATOR1 = 17, - DERELICT_SHIP = 24, - DRAGON_UTOPIA = 25, - GARRISON = 33, - MONOLITH1 = 43, - MONOLITH2 = 44, - MONOLITH3 = 45, - MINE = 53, - MONSTER = 54, - OBELISK = 57, - PYRAMID = 63, - CRYPT = 84, - SHIPWRECK = 85, - TRADING_POST = 99, - SUBTERRANEAN_GATE = 103, - WHIRLPOOL = 111, - BORDER_GATE = 212, - GARRISON2 = 219, - }; -} static const int3 dirs[] = { int3(0,1,0),int3(0,-1,0),int3(-1,0,0),int3(+1,0,0), int3(1,1,0),int3(-1,1,0),int3(1,-1,0),int3(-1,-1,0) }; @@ -540,8 +515,12 @@ void VCAI::heroVisit(const CGHeroInstance *visitor, const CGObjectInstance *visi { NET_EVENT_HANDLER; LOG_ENTRY; - if(start && visitedObj->ID != Obj::MONSTER) - alreadyVisited.push_back(visitedObj); + if (start) + { + visitedObject = const_cast(visitedObj); // remember teh object and wait for return + if(visitedObj->ID != Obj::MONSTER) //TODO: poll bank if it was cleared + alreadyVisited.push_back(visitedObj); + } } void VCAI::availableArtifactsChanged(const CGBlackMarket *bm /*= NULL*/) @@ -850,8 +829,14 @@ void VCAI::makeTurn() retreiveVisitableObjs(objs, true); BOOST_FOREACH(const CGObjectInstance *obj, objs) { - if(obj->ID == Obj::CREATURE_GENERATOR1 && !vstd::contains(visitableObjs, obj)) - visitableObjs.push_back(obj); + if (isWeeklyRevisitable(obj)) + { + if (!vstd::contains(visitableObjs, obj)) + visitableObjs.push_back(obj); + auto o = std::find (alreadyVisited.begin(), alreadyVisited.end(), obj); + if (o != alreadyVisited.end()) + alreadyVisited.erase(o); + } } } if(cb->getSelectedHero()) @@ -894,6 +879,16 @@ bool VCAI::goVisitObj(const CGObjectInstance * obj, const CGHeroInstance * h) return moveHeroToTile(dst, h); } +void VCAI::performObjectInteraction(const CGObjectInstance * obj, const CGHeroInstance * h) +{ + switch (obj->ID) + { + case Obj::CREATURE_GENERATOR1: + recruitCreatures(dynamic_cast(obj)); + break; + } +} + void VCAI::moveCreaturesToHero(const CGTownInstance * t) { if(t->visitingHero) @@ -916,15 +911,15 @@ void VCAI::moveCreaturesToHero(const CGTownInstance * t) } } -void VCAI::recruitCreatures(const CGTownInstance * t) +void VCAI::recruitCreatures(const CGDwelling * d) { - for(int i = 0; i < t->creatures.size(); i++) + for(int i = 0; i < d->creatures.size(); i++) { - if(!t->creatures[i].second.size()) + if(!d->creatures[i].second.size()) continue; - int count = t->creatures[i].first; - int creID = t->creatures[i].second.back(); + int count = d->creatures[i].first; + int creID = d->creatures[i].second.back(); // const CCreature *c = VLC->creh->creatures[creID]; // if(containsSavedRes(c->cost)) // continue; @@ -933,7 +928,7 @@ void VCAI::recruitCreatures(const CGTownInstance * t) myRes[Res::GOLD] -= GOLD_RESERVE; amin(count, myRes / VLC->creh->creatures[creID]->cost); if(count > 0) - cb->recruitCreatures(t, creID, count, i); + cb->recruitCreatures(d, creID, count, i); } } @@ -999,8 +994,11 @@ std::vector VCAI::getPossibleDestinations(const CGHero validateVisitableObjs(); std::vector possibleDestinations; BOOST_FOREACH(const CGObjectInstance *obj, visitableObjs) - if(cb->getPathInfo(obj->visitablePos())->reachable() && obj->tempOwner != playerID) + { + if(cb->getPathInfo(obj->visitablePos())->reachable() && + (obj->tempOwner != playerID || isWeeklyRevisitable(obj))) //flag or get weekly resources / creatures possibleDestinations.push_back(obj); + } boost::sort(possibleDestinations, isCloser); @@ -1253,6 +1251,7 @@ public: bool VCAI::moveHeroToTile(int3 dst, const CGHeroInstance * h) { + visitedObject = NULL; int3 startHpos = h->visitablePos(); bool ret = false; if(startHpos == dst) @@ -1301,6 +1300,8 @@ bool VCAI::moveHeroToTile(int3 dst, const CGHeroInstance * h) } ret = !i; } + if (visitedObject) //we step into something interesting + performObjectInteraction (visitedObject, h); if(h->tempOwner == playerID) //lost hero after last move cb->recalculatePaths(); @@ -1371,7 +1372,9 @@ void VCAI::tryRealize(CGoal g) if(!g.hero->movement) throw cannotFulfillGoalException("Cannot visit tile: hero is out of MPs!"); if(!g.isBlockedBorderGate(g.tile)) + { ai->moveHeroToTile(g.tile, g.hero); + } else throw cannotFulfillGoalException("There's a blocked gate!"); } @@ -2337,6 +2340,13 @@ void SectorMap::write(crstring fname) } } +bool isWeeklyRevisitable (const CGObjectInstance * obj) +{ //TODO: allow polling of remaining creatures in dwelling + if (dynamic_cast(obj) || dynamic_cast(obj)) //ensures future compatibility, unlike IDs + return true; + return false; +} + int3 SectorMap::firstTileToGet(const CGHeroInstance *h, crint3 dst) diff --git a/AI/VCAI/VCAI.h b/AI/VCAI/VCAI.h index 941c23331..5885f709f 100644 --- a/AI/VCAI/VCAI.h +++ b/AI/VCAI/VCAI.h @@ -37,7 +37,7 @@ public: enum EGoals { INVALID = -1, - WIN, DO_NOT_LOSE, CONQUER, BUILD, EXPLORE, + WIN, DO_NOT_LOSE, CONQUER, BUILD, EXPLORE, //GATHER_ARMY,// BOOST_HERO, RECRUIT_HERO, BUILD_STRUCTURE, //if hero set, then in visited town COLLECT_RES, @@ -172,6 +172,8 @@ public: CGoal currentGoal; + CGObjectInstance * visitedObject; //remember currently viisted object + boost::thread *makingTurn; void tryRealize(CGoal g); @@ -251,9 +253,11 @@ public: void recruitHero(const CGTownInstance * t); std::vector getPossibleDestinations(const CGHeroInstance *h); void buildStructure(const CGTownInstance * t); - void recruitCreatures(const CGTownInstance * t); + //void recruitCreatures(const CGTownInstance * t); + void recruitCreatures(const CGDwelling * d); void moveCreaturesToHero(const CGTownInstance * t); bool goVisitObj(const CGObjectInstance * obj, const CGHeroInstance * h); + void performObjectInteraction(const CGObjectInstance * obj, const CGHeroInstance * h); bool moveHeroToTile(int3 dst, const CGHeroInstance * h); void waitTillFree(); @@ -284,4 +288,6 @@ template bool objWithID(const CGObjectInstance *obj) { return obj->ID == id; -} \ No newline at end of file +} + +bool isWeeklyRevisitable (const CGObjectInstance * obj); \ No newline at end of file diff --git a/lib/GameConstants.h b/lib/GameConstants.h index 72d5d6530..16f4bc3a6 100644 --- a/lib/GameConstants.h +++ b/lib/GameConstants.h @@ -169,6 +169,33 @@ namespace EBattleStackState enum EBattleStackState{ALIVE = 180, SUMMONED, CLONED, HAD_MORALE, WAITING, MOVED, DEFENDING, FEAR}; } +namespace Obj +{ + enum + { + BOAT = 8, + CREATURE_BANK = 16, + CREATURE_GENERATOR1 = 17, + DERELICT_SHIP = 24, + DRAGON_UTOPIA = 25, + GARRISON = 33, + MONOLITH1 = 43, + MONOLITH2 = 44, + MONOLITH3 = 45, + MINE = 53, + MONSTER = 54, + OBELISK = 57, + PYRAMID = 63, + CRYPT = 84, + SHIPWRECK = 85, + TRADING_POST = 99, + SUBTERRANEAN_GATE = 103, + WHIRLPOOL = 111, + BORDER_GATE = 212, + GARRISON2 = 219, + }; +} + // Typedef declarations typedef si64 expType; typedef ui32 TSpell;