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:
parent
e7783479d2
commit
bdd71b4f38
@ -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));
|
||||||
|
|
||||||
|
@ -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)
|
||||||
|
@ -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);
|
@ -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;
|
||||||
|
Loading…
Reference in New Issue
Block a user