1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-24 22:14:36 +02:00

AI can now use external dwellings.

AI will weekly revisit dwellings & mills.
This commit is contained in:
DjWarmonger 2012-03-05 19:11:28 +00:00
parent e7783479d2
commit bdd71b4f38
4 changed files with 85 additions and 42 deletions

View File

@ -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 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 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 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)); //tacticalAdvantage.addRule(new fl::MamdaniRule("if OurShooters is MANY and EnemyShooters is MANY then Threat is MEDIUM", engine));

View File

@ -9,6 +9,8 @@ CLogger &aiLogger = tlog6;
extern FuzzyHelper fh; extern FuzzyHelper fh;
class CGVisitableOPW;
const int ACTUAL_RESOURCE_COUNT = 7; const int ACTUAL_RESOURCE_COUNT = 7;
const double SAFE_ATTACK_CONSTANT = 1.5; const double SAFE_ATTACK_CONSTANT = 1.5;
@ -59,33 +61,6 @@ bool compareArmyStrength(const CArmedInstance *a1, const CArmedInstance *a2)
return a1->getArmyStrength() < a2->getArmyStrength(); 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), 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) }; 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; NET_EVENT_HANDLER;
LOG_ENTRY; LOG_ENTRY;
if(start && visitedObj->ID != Obj::MONSTER) if (start)
alreadyVisited.push_back(visitedObj); {
visitedObject = const_cast<CGObjectInstance *>(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*/) void VCAI::availableArtifactsChanged(const CGBlackMarket *bm /*= NULL*/)
@ -850,8 +829,14 @@ void VCAI::makeTurn()
retreiveVisitableObjs(objs, true); retreiveVisitableObjs(objs, true);
BOOST_FOREACH(const CGObjectInstance *obj, objs) BOOST_FOREACH(const CGObjectInstance *obj, objs)
{ {
if(obj->ID == Obj::CREATURE_GENERATOR1 && !vstd::contains(visitableObjs, obj)) if (isWeeklyRevisitable(obj))
visitableObjs.push_back(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()) if(cb->getSelectedHero())
@ -894,6 +879,16 @@ bool VCAI::goVisitObj(const CGObjectInstance * obj, const CGHeroInstance * h)
return moveHeroToTile(dst, h); return moveHeroToTile(dst, h);
} }
void VCAI::performObjectInteraction(const CGObjectInstance * obj, const CGHeroInstance * h)
{
switch (obj->ID)
{
case Obj::CREATURE_GENERATOR1:
recruitCreatures(dynamic_cast<const CGDwelling *>(obj));
break;
}
}
void VCAI::moveCreaturesToHero(const CGTownInstance * t) void VCAI::moveCreaturesToHero(const CGTownInstance * t)
{ {
if(t->visitingHero) 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; continue;
int count = t->creatures[i].first; int count = d->creatures[i].first;
int creID = t->creatures[i].second.back(); int creID = d->creatures[i].second.back();
// const CCreature *c = VLC->creh->creatures[creID]; // const CCreature *c = VLC->creh->creatures[creID];
// if(containsSavedRes(c->cost)) // if(containsSavedRes(c->cost))
// continue; // continue;
@ -933,7 +928,7 @@ void VCAI::recruitCreatures(const CGTownInstance * t)
myRes[Res::GOLD] -= GOLD_RESERVE; myRes[Res::GOLD] -= GOLD_RESERVE;
amin(count, myRes / VLC->creh->creatures[creID]->cost); amin(count, myRes / VLC->creh->creatures[creID]->cost);
if(count > 0) if(count > 0)
cb->recruitCreatures(t, creID, count, i); cb->recruitCreatures(d, creID, count, i);
} }
} }
@ -999,8 +994,11 @@ std::vector<const CGObjectInstance *> VCAI::getPossibleDestinations(const CGHero
validateVisitableObjs(); validateVisitableObjs();
std::vector<const CGObjectInstance *> possibleDestinations; std::vector<const CGObjectInstance *> possibleDestinations;
BOOST_FOREACH(const CGObjectInstance *obj, visitableObjs) 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); possibleDestinations.push_back(obj);
}
boost::sort(possibleDestinations, isCloser); boost::sort(possibleDestinations, isCloser);
@ -1253,6 +1251,7 @@ public:
bool VCAI::moveHeroToTile(int3 dst, const CGHeroInstance * h) bool VCAI::moveHeroToTile(int3 dst, const CGHeroInstance * h)
{ {
visitedObject = NULL;
int3 startHpos = h->visitablePos(); int3 startHpos = h->visitablePos();
bool ret = false; bool ret = false;
if(startHpos == dst) if(startHpos == dst)
@ -1301,6 +1300,8 @@ bool VCAI::moveHeroToTile(int3 dst, const CGHeroInstance * h)
} }
ret = !i; ret = !i;
} }
if (visitedObject) //we step into something interesting
performObjectInteraction (visitedObject, h);
if(h->tempOwner == playerID) //lost hero after last move if(h->tempOwner == playerID) //lost hero after last move
cb->recalculatePaths(); cb->recalculatePaths();
@ -1371,7 +1372,9 @@ void VCAI::tryRealize(CGoal g)
if(!g.hero->movement) if(!g.hero->movement)
throw cannotFulfillGoalException("Cannot visit tile: hero is out of MPs!"); throw cannotFulfillGoalException("Cannot visit tile: hero is out of MPs!");
if(!g.isBlockedBorderGate(g.tile)) if(!g.isBlockedBorderGate(g.tile))
{
ai->moveHeroToTile(g.tile, g.hero); ai->moveHeroToTile(g.tile, g.hero);
}
else else
throw cannotFulfillGoalException("There's a blocked gate!"); 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<const CGVisitableOPW *>(obj) || dynamic_cast<const CGDwelling *>(obj)) //ensures future compatibility, unlike IDs
return true;
return false;
}
int3 SectorMap::firstTileToGet(const CGHeroInstance *h, crint3 dst) int3 SectorMap::firstTileToGet(const CGHeroInstance *h, crint3 dst)

View File

@ -37,7 +37,7 @@ public:
enum EGoals enum EGoals
{ {
INVALID = -1, INVALID = -1,
WIN, DO_NOT_LOSE, CONQUER, BUILD, EXPLORE, WIN, DO_NOT_LOSE, CONQUER, BUILD, EXPLORE, //GATHER_ARMY,// BOOST_HERO,
RECRUIT_HERO, RECRUIT_HERO,
BUILD_STRUCTURE, //if hero set, then in visited town BUILD_STRUCTURE, //if hero set, then in visited town
COLLECT_RES, COLLECT_RES,
@ -172,6 +172,8 @@ public:
CGoal currentGoal; CGoal currentGoal;
CGObjectInstance * visitedObject; //remember currently viisted object
boost::thread *makingTurn; boost::thread *makingTurn;
void tryRealize(CGoal g); void tryRealize(CGoal g);
@ -251,9 +253,11 @@ public:
void recruitHero(const CGTownInstance * t); void recruitHero(const CGTownInstance * t);
std::vector<const CGObjectInstance *> getPossibleDestinations(const CGHeroInstance *h); std::vector<const CGObjectInstance *> getPossibleDestinations(const CGHeroInstance *h);
void buildStructure(const CGTownInstance * t); 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); void moveCreaturesToHero(const CGTownInstance * t);
bool goVisitObj(const CGObjectInstance * obj, const CGHeroInstance * h); bool goVisitObj(const CGObjectInstance * obj, const CGHeroInstance * h);
void performObjectInteraction(const CGObjectInstance * obj, const CGHeroInstance * h);
bool moveHeroToTile(int3 dst, const CGHeroInstance * h); bool moveHeroToTile(int3 dst, const CGHeroInstance * h);
void waitTillFree(); void waitTillFree();
@ -284,4 +288,6 @@ template<int id>
bool objWithID(const CGObjectInstance *obj) bool objWithID(const CGObjectInstance *obj)
{ {
return obj->ID == id; return obj->ID == id;
} }
bool isWeeklyRevisitable (const CGObjectInstance * obj);

View File

@ -169,6 +169,33 @@ namespace EBattleStackState
enum EBattleStackState{ALIVE = 180, SUMMONED, CLONED, HAD_MORALE, WAITING, MOVED, DEFENDING, FEAR}; 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 declarations
typedef si64 expType; typedef si64 expType;
typedef ui32 TSpell; typedef ui32 TSpell;