1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-11-26 08:41:13 +02:00

Some more.

This commit is contained in:
DjWarmonger 2013-10-19 11:37:22 +00:00
parent 7b4964b882
commit c77fa499e7
4 changed files with 92 additions and 77 deletions

View File

@ -67,7 +67,7 @@ std::string Goals::CGoal::name() const //TODO: virtualize
}
}
#define I_AM_ELEMENTAR return Goals::CGoal(*this).setisElementar(true) //FIXME: we loose some information about clas here?
#define I_AM_ELEMENTAR return (*this).setisElementar(true)
TSubgoal Win::whatToDoToAchieve()
{
@ -83,11 +83,11 @@ TSubgoal Win::whatToDoToAchieve()
switch(cond)
{
case EVictoryConditionType::ARTIFACT:
return CGoal(GET_ART_TYPE).setaid(vc.objectId);
return Goals::GetArtOfType().setaid(vc.objectId);
case EVictoryConditionType::BEATHERO:
return CGoal(GET_OBJ).setobjid(vc.obj->id.getNum());
return Goals::GetObj(vc.obj->id.getNum());
case EVictoryConditionType::BEATMONSTER:
return CGoal(GET_OBJ).setobjid(vc.obj->id.getNum());
return Goals::GetObj(vc.obj->id.getNum());
case EVictoryConditionType::BUILDCITY:
//TODO build castle/capitol
break;
@ -99,7 +99,7 @@ TSubgoal Win::whatToDoToAchieve()
if(h->visitedTown && !vstd::contains(h->visitedTown->forbiddenBuildings, BuildingID::GRAIL))
{
const CGTownInstance *t = h->visitedTown;
return CGoal(BUILD_STRUCTURE).setbid(BuildingID::GRAIL).settown(t);
return Goals::BuildThis().setbid(BuildingID::GRAIL).settown(t);
}
else
{
@ -113,7 +113,7 @@ TSubgoal Win::whatToDoToAchieve()
boost::sort(towns, isCloser);
if(towns.size())
{
return CGoal(VISIT_TILE).sethero(h).settile(towns.front()->visitablePos());
return Goals::VisitTile(towns.front()->visitablePos()).sethero(h);
}
}
}
@ -121,25 +121,25 @@ TSubgoal Win::whatToDoToAchieve()
int3 grailPos = cb->getGrailPos(ratio);
if(ratio > 0.99)
{
return CGoal(DIG_AT_TILE).settile(grailPos);
return Goals::DigAtTile().settile(grailPos);
} //TODO: use FIND_OBJ
else if(const CGObjectInstance * obj = ai->getUnvisitedObj(objWithID<Obj::OBELISK>)) //there are unvisited Obelisks
{
return CGoal(GET_OBJ).setobjid(obj->id.getNum());
return Goals::GetObj(obj->id.getNum());
}
else
return CGoal(EXPLORE);
return Goals::Explore();
}
break;
case EVictoryConditionType::CAPTURECITY:
return CGoal(GET_OBJ).setobjid(vc.obj->id.getNum());
return Goals::GetObj(vc.obj->id.getNum());
case EVictoryConditionType::GATHERRESOURCE:
return CGoal(COLLECT_RES).setresID(static_cast<Res::ERes>(vc.objectId)).setvalue(vc.count);
return Goals::CollectRes().setresID(static_cast<Res::ERes>(vc.objectId)).setvalue(vc.count);
//TODO mines? piles? marketplace?
//save?
break;
case EVictoryConditionType::GATHERTROOP:
return CGoal(GATHER_TROOPS).setobjid(vc.objectId).setvalue(vc.count);
return Goals::GatherTroops().setobjid(vc.objectId).setvalue(vc.count);
break;
case EVictoryConditionType::TAKEDWELLINGS:
break;
@ -148,7 +148,7 @@ TSubgoal Win::whatToDoToAchieve()
case EVictoryConditionType::TRANSPORTITEM:
break;
case EVictoryConditionType::WINSTANDARD:
return CGoal(CONQUER);
return Goals::Conquer();
default:
assert(0);
}
@ -180,35 +180,35 @@ TSubgoal FindObj::whatToDoToAchieve()
}
}
if (o && isReachable(o))
return CGoal(GET_OBJ).setobjid(o->id.getNum());
return Goals::GetObj(o->id.getNum());
else
return CGoal(EXPLORE);
return Goals::Explore();
}
TSubgoal GetObj::whatToDoToAchieve()
{
const CGObjectInstance * obj = cb->getObj(ObjectInstanceID(objid));
if(!obj)
return CGoal(EXPLORE);
return Goals::Explore();
int3 pos = obj->visitablePos();
return CGoal(VISIT_TILE).settile(pos);
return Goals::VisitTile(pos);
}
TSubgoal VisitHero::whatToDoToAchieve()
{
const CGObjectInstance * obj = cb->getObj(ObjectInstanceID(objid));
if(!obj)
return CGoal(EXPLORE);
return Goals::Explore();
int3 pos = obj->visitablePos();
if (hero && ai->isAccessibleForHero(pos, hero, true) && isSafeToVisit(hero, pos)) //enemy heroes can get reinforcements
return CGoal(*this).settile(pos).setisElementar(true);
return (*this).settile(pos).setisElementar(true);
}
TSubgoal GetArtOfType::whatToDoToAchieve()
{
TSubgoal alternativeWay = CGoal::lookForArtSmart(aid); //TODO: use
if(alternativeWay.invalid())
return CGoal(FIND_OBJ).setobjid(Obj::ARTIFACT).setresID(aid);
return Goals::FindObj(Obj::ARTIFACT, aid);
}
TSubgoal ClearWayTo::whatToDoToAchieve()
@ -217,12 +217,12 @@ TSubgoal ClearWayTo::whatToDoToAchieve()
if(!cb->isVisible(tile))
{
logAi->errorStream() << "Clear way should be used with visible tiles!";
return CGoal(EXPLORE);
return Goals::Explore();
}
HeroPtr h = hero ? hero : ai->primaryHero();
if(!h)
return CGoal(RECRUIT_HERO);
return Goals::RecruitHero();
cb->setSelection(*h);
@ -235,7 +235,7 @@ TSubgoal ClearWayTo::whatToDoToAchieve()
//if(isSafeToVisit(h, tileToHit))
if(isBlockedBorderGate(tileToHit))
{ //FIXME: this way we'll not visit gate and activate quest :?
return CGoal(FIND_OBJ).setobjid(Obj::KEYMASTER).setresID(cb->getTile(tileToHit)->visitableObjects.back()->subID);
return Goals::FindObj (Obj::KEYMASTER, cb->getTile(tileToHit)->visitableObjects.back()->subID);
}
//FIXME: this code shouldn't be necessary
@ -253,7 +253,7 @@ TSubgoal ClearWayTo::whatToDoToAchieve()
throw cannotFulfillGoalException(problem);
}
return CGoal(VISIT_TILE).settile(tileToHit).sethero(h); //FIXME:: attempts to visit completely unreachable tile with hero results in stall
return Goals::VisitTile(tileToHit).sethero(h); //FIXME:: attempts to visit completely unreachable tile with hero results in stall
//TODO czy istnieje lepsza droga?
@ -292,7 +292,7 @@ TSubgoal Explore::whatToDoToAchieve()
auto pos = obj->visitablePos();
//FIXME: this confition fails if everything but guarded subterranen gate was explored. in this case we should gather army for hero
if (isSafeToVisit(hero, pos) && ai->isAccessibleForHero(pos, hero))
return CGoal(VISIT_TILE).settile(pos).sethero(hero);
return Goals::VisitTile(pos).sethero(hero);
}
}
else
@ -301,7 +301,7 @@ TSubgoal Explore::whatToDoToAchieve()
{
auto pos = obj->visitablePos();
if (ai->isAccessible (pos)) //TODO: check safety?
return CGoal(VISIT_TILE).settile(pos).sethero(hero);
return Goals::VisitTile(pos).sethero(hero);
}
}
}
@ -329,12 +329,12 @@ TSubgoal Explore::whatToDoToAchieve()
});
if (objs.size())
{
return CGoal (VISIT_TILE).settile(objs.front()->visitablePos()).sethero(hero).setisAbstract(true);
return Goals::VisitTile(objs.front()->visitablePos()).sethero(hero).setisAbstract(true);
}
else
throw cannotFulfillGoalException("Cannot explore - no possible ways found!");
}
return CGoal(VISIT_TILE).settile(t).sethero(hero);
return Goals::VisitTile(t).sethero(hero);
}
auto hs = cb->getHeroesInfo();
@ -347,7 +347,7 @@ TSubgoal Explore::whatToDoToAchieve()
if(hs.empty()) //all heroes are busy. buy new one
{
if (howManyHeroes < 3 && ai->findTownWithTavern()) //we may want to recruit second hero. TODO: make it smart finally
return CGoal(RECRUIT_HERO);
return Goals::RecruitHero();
else //find mobile hero with weakest army
{
hs = cb->getHeroesInfo();
@ -358,7 +358,7 @@ TSubgoal Explore::whatToDoToAchieve()
if (hs.empty())
{
if (howManyHeroes < GameConstants::MAX_HEROES_PER_PLAYER)
return CGoal(RECRUIT_HERO);
return Goals::RecruitHero();
else
throw cannotFulfillGoalException("No heroes with remaining MPs for exploring!\n");
}
@ -377,10 +377,10 @@ TSubgoal RecruitHero::whatToDoToAchieve()
{
const CGTownInstance *t = ai->findTownWithTavern();
if(!t)
return CGoal(BUILD_STRUCTURE).setbid(BuildingID::TAVERN);
return Goals::BuildThis().setbid(BuildingID::TAVERN);
if(cb->getResourceAmount(Res::GOLD) < HERO_GOLD_COST)
return CGoal(COLLECT_RES).setresID(Res::GOLD).setvalue(HERO_GOLD_COST);
return Goals::CollectRes().setresID(Res::GOLD).setvalue(HERO_GOLD_COST);
I_AM_ELEMENTAR;
}
@ -388,7 +388,7 @@ TSubgoal RecruitHero::whatToDoToAchieve()
TSubgoal VisitTile::whatToDoToAchieve()
{
if(!cb->isVisible(tile))
return CGoal(EXPLORE);
return Goals::Explore();
if(hero && !ai->isAccessibleForHero(tile, hero))
hero = nullptr;
@ -397,7 +397,7 @@ TSubgoal VisitTile::whatToDoToAchieve()
{
if(cb->getHeroesInfo().empty())
{
return CGoal(RECRUIT_HERO);
return Goals::RecruitHero();
}
for(const CGHeroInstance *h : cb->getHeroesInfo())
@ -413,15 +413,15 @@ TSubgoal VisitTile::whatToDoToAchieve()
if(hero)
{
if(isSafeToVisit(hero, tile))
return CGoal(*this).setisElementar(true);
return (*this).setisElementar(true);
else
{
return CGoal(GATHER_ARMY).sethero(hero).setvalue(evaluateDanger(tile, *hero) * SAFE_ATTACK_CONSTANT); //TODO: should it be abstract?
return Goals::GatherArmy().sethero(hero).setvalue(evaluateDanger(tile, *hero) * SAFE_ATTACK_CONSTANT); //TODO: should it be abstract?
}
}
else //inaccessible for all heroes
{
return CGoal(CLEAR_WAY_TO).settile(tile);
return Goals::ClearWayTo(tile);
}
}
@ -431,10 +431,10 @@ TSubgoal DigAtTile::whatToDoToAchieve()
if(firstObj && firstObj->ID == Obj::HERO && firstObj->tempOwner == ai->playerID) //we have hero at dest
{
const CGHeroInstance *h = dynamic_cast<const CGHeroInstance *>(firstObj);
return CGoal(*this).sethero(h).setisElementar(true);
return (*this).sethero(h).setisElementar(true);
}
return CGoal(VISIT_TILE).settile(tile);
return Goals::VisitTile(tile);
}
TSubgoal BuildThis::whatToDoToAchieve()
@ -478,7 +478,7 @@ TSubgoal CollectRes::whatToDoToAchieve()
for(const CGTownInstance *t : cb->getTownsInfo())
{
if(cb->canBuildStructure(t, BuildingID::MARKETPLACE) == EBuildingState::ALLOWED)
return CGoal(BUILD_STRUCTURE).settown(t).setbid(BuildingID::MARKETPLACE);
return Goals::BuildThis().settown(t).setbid(BuildingID::MARKETPLACE);
}
}
else
@ -500,11 +500,11 @@ TSubgoal CollectRes::whatToDoToAchieve()
auto backObj = backOrNull(cb->getVisitableObjs(m->o->visitablePos())); //it'll be a hero if we have one there; otherwise marketplace
assert(backObj);
if(backObj->tempOwner != ai->playerID)
return CGoal(GET_OBJ).setobjid(m->o->id.getNum());
return Goals::GetObj(m->o->id.getNum());
return setobjid(m->o->id.getNum()).setisElementar(true);
}
}
return CGoal(INVALID); //FIXME: unused?
return Goals::Invalid(); //FIXME: unused?
}
TSubgoal GatherTroops::whatToDoToAchieve()
@ -530,7 +530,7 @@ TSubgoal GatherTroops::whatToDoToAchieve()
}
else
{
return CGoal (BUILD_STRUCTURE).settown(t).setbid(bid);
return Goals::BuildThis().settown(t).setbid(bid);
}
}
}
@ -555,10 +555,10 @@ TSubgoal GatherTroops::whatToDoToAchieve()
if (dwellings.size())
{
boost::sort(dwellings, isCloser);
return CGoal(GET_OBJ).setobjid (dwellings.front()->id.getNum());
return Goals::GetObj(dwellings.front()->id.getNum());
}
else
return CGoal(EXPLORE);
return Goals::Explore();
//TODO: exchange troops between heroes
}
@ -574,7 +574,7 @@ TSubgoal Conquer::whatToDoToAchieve()
if(hs.empty()) //all heroes are busy. buy new one
{
if (howManyHeroes < 3 && ai->findTownWithTavern()) //we may want to recruit second hero. TODO: make it smart finally
return CGoal(RECRUIT_HERO);
return Goals::RecruitHero();
else //find mobile hero with weakest army
{
hs = cb->getHeroesInfo();
@ -585,7 +585,7 @@ TSubgoal Conquer::whatToDoToAchieve()
if (hs.empty())
{
if (howManyHeroes < GameConstants::MAX_HEROES_PER_PLAYER)
return CGoal(RECRUIT_HERO);
return Goals::RecruitHero();
else
throw cannotFulfillGoalException("No heroes with remaining MPs for exploring!\n");
}
@ -614,7 +614,7 @@ TSubgoal Conquer::whatToDoToAchieve()
}
if(objs.empty())
return CGoal(EXPLORE); //we need to find an enemy
return Goals::Explore(); //we need to find an enemy
erase_if(objs, [&](const CGObjectInstance *obj)
{
@ -632,13 +632,13 @@ TSubgoal Conquer::whatToDoToAchieve()
ai->reserveObject(h, obj); //no one else will capture same object until we fail
if (obj->ID == Obj::HERO)
return CGoal(VISIT_HERO).sethero(h).setobjid(obj->id.getNum()).setisAbstract(true); //track enemy hero
return Goals::VisitHero().sethero(h).setobjid(obj->id.getNum()).setisAbstract(true); //track enemy hero
else
return CGoal(VISIT_TILE).sethero(h).settile(obj->visitablePos());
return Goals::VisitTile(obj->visitablePos()).sethero(h);
}
}
return CGoal(EXPLORE); //enemy is inaccessible
return Goals::Explore(); //enemy is inaccessible
}
TSubgoal Build::whatToDoToAchieve()
@ -675,7 +675,7 @@ TSubgoal GatherArmy::whatToDoToAchieve()
if(townsReachable.size()) //try towns first
{
boost::sort(townsReachable, compareReinforcements);
return CGoal(VISIT_TILE).sethero(hero).settile(townsReachable.back()->visitablePos());
return Goals::VisitTile(townsReachable.back()->visitablePos()).sethero(hero);
}
else
{
@ -698,9 +698,9 @@ TSubgoal GatherArmy::whatToDoToAchieve()
secondaryPath = cb->getPathInfo(hero->visitablePos())->turns;
if (primaryPath < secondaryPath)
return CGoal(VISIT_HERO).setisAbstract(true).setobjid(h->id.getNum()).sethero(hero); //go to the other hero if we are faster
return Goals::VisitHero().setisAbstract(true).setobjid(h->id.getNum()).sethero(hero); //go to the other hero if we are faster
else
return CGoal(VISIT_HERO).setisAbstract(true).setobjid(hero->id.getNum()).sethero(h); //let the other hero come to us
return Goals::VisitHero().setisAbstract(true).setobjid(hero->id.getNum()).sethero(h); //let the other hero come to us
}
}
@ -736,7 +736,7 @@ TSubgoal GatherArmy::whatToDoToAchieve()
return true;
});
if(objs.empty()) //no possible objects, we did eveyrthing already
return CGoal(EXPLORE).sethero(hero);
return Goals::Explore().sethero(hero);
//TODO: check if we can recruit any creatures there, evaluate army
else
{
@ -756,31 +756,31 @@ TSubgoal GatherArmy::whatToDoToAchieve()
}
}
if (h && isSafeToVisit(h, pos) && ai->isAccessibleForHero(pos, h))
return CGoal(VISIT_TILE).sethero(h).settile(pos);
return Goals::VisitTile(pos).sethero(h);
}
}
}
return CGoal(EXPLORE).sethero(hero); //find dwelling. use current hero to prevent him from doing nothing.
return Goals::Explore().sethero(hero); //find dwelling. use current hero to prevent him from doing nothing.
}
TSubgoal CGoal::whatToDoToAchieve()
{
logAi->debugStream() << boost::format("Decomposing goal of type %s") % name();
return CGoal(EXPLORE);
return Goals::Explore();
}
TSubgoal CGoal::goVisitOrLookFor(const CGObjectInstance *obj)
{
if(obj)
return CGoal(GET_OBJ).setobjid(obj->id.getNum());
return Goals::GetObj(obj->id.getNum());
else
return CGoal(EXPLORE);
return Goals::Explore();
}
TSubgoal CGoal::lookForArtSmart(int aid)
{
return CGoal(INVALID);
return Goals::Invalid();
}
bool CGoal::invalid() const

View File

@ -113,61 +113,73 @@ struct CGoal
class Invalid : public CGoal
{
public:
Invalid() : CGoal (Goals::INVALID){};
TSubgoal whatToDoToAchieve() override;
};
class Win : public CGoal
{
public:
Win() : CGoal (Goals::WIN){};
TSubgoal whatToDoToAchieve() override;
};
class NotLose : public CGoal
{
public:
NotLose() : CGoal (Goals::DO_NOT_LOSE){};
TSubgoal whatToDoToAchieve() override;
};
class Conquer : public CGoal
{
public:
Conquer() : CGoal (Goals::CONQUER){};
TSubgoal whatToDoToAchieve() override;
};
class Build : public CGoal
{
public:
Build() : CGoal (Goals::BUILD){};
TSubgoal whatToDoToAchieve() override;
};
class Explore : public CGoal
{
public:
Explore() : CGoal (Goals::EXPLORE){};
TSubgoal whatToDoToAchieve() override;
};
class GatherArmy : public CGoal
{
public:
GatherArmy() : CGoal (Goals::GATHER_ARMY){};
TSubgoal whatToDoToAchieve() override;
};
class BoostHero : public CGoal
{
public:
BoostHero() : CGoal (Goals::INVALID){}; //TODO
TSubgoal whatToDoToAchieve() override;
};
class RecruitHero : public CGoal
{
public:
RecruitHero() : CGoal (Goals::RECRUIT_HERO){};
TSubgoal whatToDoToAchieve() override;
};
class BuildThis : public CGoal
{
public:
BuildThis() : CGoal (Goals::BUILD_STRUCTURE){};
TSubgoal whatToDoToAchieve() override;
};
class CollectRes : public CGoal
{
public:
CollectRes() : CGoal (Goals::COLLECT_RES){};
TSubgoal whatToDoToAchieve() override;
};
class GatherTroops : public CGoal
{
public:
GatherTroops() : CGoal (Goals::GATHER_TROOPS){};
TSubgoal whatToDoToAchieve() override;
};
class GetObj : public CGoal
@ -175,7 +187,7 @@ class GetObj : public CGoal
private:
GetObj() {}; // empty constructor not allowed
public:
GetObj(const int Objid) {setobjid(Objid);};
GetObj(const int Objid) : CGoal(Goals::GET_OBJ) {setobjid(Objid);};
TSubgoal whatToDoToAchieve() override;
};
class FindObj : public CGoal
@ -183,49 +195,52 @@ class FindObj : public CGoal
private:
FindObj() {}; // empty constructor not allowed
public:
FindObj(int ID) {setobjid(ID);};
FindObj(int ID, int subID) {setobjid(ID).setresID(subID);};
FindObj(int ID) : CGoal(Goals::FIND_OBJ) {setobjid(ID);};
FindObj(int ID, int subID) : CGoal(Goals::FIND_OBJ) {setobjid(ID).setresID(subID);};
TSubgoal whatToDoToAchieve() override;
};
class VisitHero : public CGoal
{
public:
VisitHero() : CGoal (Goals::VISIT_HERO){};
TSubgoal whatToDoToAchieve() override;
};
class GetArtOfType : public CGoal
{
public:
GetArtOfType() : CGoal (Goals::GET_ART_TYPE){};
TSubgoal whatToDoToAchieve() override;
};
class IssueCommand : public CGoal
{
public:
TSubgoal whatToDoToAchieve() override;
};
class VisitTile : public CGoal //tile, in conjunction with hero elementar; assumes tile is reachable
class VisitTile : public CGoal
//tile, in conjunction with hero elementar; assumes tile is reachable
{
private:
VisitTile() {}; // empty constructor not allowed
public:
VisitTile(int3 Tile) {settile(Tile);};
VisitTile(int3 Tile) : CGoal (Goals::VISIT_TILE) {settile(Tile);};
TSubgoal whatToDoToAchieve() override;
};
class ClearWayTo : public CGoal
{
public:
ClearWayTo(int3 Tile) : CGoal (Goals::CLEAR_WAY_TO) {settile(Tile);};
TSubgoal whatToDoToAchieve() override;
};
class DigAtTile : public CGoal //elementar with hero on tile
class DigAtTile : public CGoal
//elementar with hero on tile
{
public:
DigAtTile() : CGoal (Goals::DIG_AT_TILE){};
TSubgoal whatToDoToAchieve() override;
};
struct CIssueCommand : CGoal
class CIssueCommand : CGoal
{
std::function<bool()> command;
public:
CIssueCommand(std::function<bool()> _command): CGoal(ISSUE_COMMAND), command(_command) {}
TSubgoal whatToDoToAchieve() override;
};
}

View File

@ -1697,11 +1697,11 @@ void VCAI::striveToGoal(const Goals::CGoal &ultimateGoal)
if (ultimateGoal.invalid())
return;
Goals::CGoal abstractGoal;
Goals::CGoal &abstractGoal = Goals::CGoal(); //reference must be initialized
while(1)
{
Goals::CGoal goal = ultimateGoal;
Goals::CGoal &goal = const_cast<Goals::CGoal&>(ultimateGoal);
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)
@ -1710,7 +1710,7 @@ void VCAI::striveToGoal(const Goals::CGoal &ultimateGoal)
try
{
boost::this_thread::interruption_point();
goal = goal.whatToDoToAchieve();
goal = goal.whatToDoToAchieve(); //FIXME: must keep information about goal class
--maxGoals;
}
catch(std::exception &e)

View File

@ -231,7 +231,7 @@ public:
void performTypicalActions();
void buildArmyIn(const CGTownInstance * t);
void striveToGoal(const Goals::CGoal &ultimateGoal);
void striveToGoal(const Goals::CGoal & ultimateGoal);
void endTurn();
void wander(HeroPtr h);
void setGoal(HeroPtr h, const Goals::CGoal goal);