mirror of
https://github.com/vcmi/vcmi.git
synced 2025-08-13 19:54:17 +02:00
- Fixed possible crash at invalid quest
- Fixed incorrect victory condition for AI (capture town/monster/hero) - Possible fix for GET_OBJ not being completed (goal engine needs more work) - So tweaks
This commit is contained in:
@@ -1717,41 +1717,6 @@ bool VCAI::isAccessibleForHero(const int3 & pos, HeroPtr h, bool includeAllies /
|
|||||||
return cb->getPathInfo(pos)->reachable();
|
return cb->getPathInfo(pos)->reachable();
|
||||||
}
|
}
|
||||||
|
|
||||||
class cannotFulfillGoalException : public std::exception
|
|
||||||
{
|
|
||||||
std::string msg;
|
|
||||||
public:
|
|
||||||
explicit cannotFulfillGoalException(crstring _Message) : msg(_Message)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual ~cannotFulfillGoalException() throw ()
|
|
||||||
{
|
|
||||||
};
|
|
||||||
|
|
||||||
const char *what() const throw () OVERRIDE
|
|
||||||
{
|
|
||||||
return msg.c_str();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
class goalFulfilledException : public std::exception
|
|
||||||
{
|
|
||||||
std::string msg;
|
|
||||||
public:
|
|
||||||
explicit goalFulfilledException(crstring _Message) : msg(_Message)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual ~goalFulfilledException() throw ()
|
|
||||||
{
|
|
||||||
};
|
|
||||||
|
|
||||||
const char *what() const throw () OVERRIDE
|
|
||||||
{
|
|
||||||
return msg.c_str();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
bool VCAI::moveHeroToTile(int3 dst, HeroPtr h)
|
bool VCAI::moveHeroToTile(int3 dst, HeroPtr h)
|
||||||
{
|
{
|
||||||
visitedObject = NULL;
|
visitedObject = NULL;
|
||||||
@@ -1815,6 +1780,8 @@ bool VCAI::moveHeroToTile(int3 dst, HeroPtr h)
|
|||||||
if (visitedObject) //we step into something interesting
|
if (visitedObject) //we step into something interesting
|
||||||
{
|
{
|
||||||
performObjectInteraction (visitedObject, h);
|
performObjectInteraction (visitedObject, h);
|
||||||
|
//BNLOG("Hero %s moved from %s to %s at %s", h->name % startHpos % visitedObject->hoverName % h->visitablePos());
|
||||||
|
//throw goalFulfilledException (CGoal(GET_OBJ).setobjid(visitedObject->id));
|
||||||
}
|
}
|
||||||
|
|
||||||
if(h) //we could have lost hero after last move
|
if(h) //we could have lost hero after last move
|
||||||
@@ -1918,7 +1885,7 @@ void VCAI::tryRealize(CGoal g)
|
|||||||
//{
|
//{
|
||||||
if (ai->moveHeroToTile(g.tile, g.hero.get()))
|
if (ai->moveHeroToTile(g.tile, g.hero.get()))
|
||||||
{
|
{
|
||||||
throw goalFulfilledException("");
|
throw goalFulfilledException (g);
|
||||||
}
|
}
|
||||||
//}
|
//}
|
||||||
//else
|
//else
|
||||||
@@ -1931,7 +1898,7 @@ void VCAI::tryRealize(CGoal g)
|
|||||||
throw cannotFulfillGoalException("Cannot visit tile: hero is out of MPs!");
|
throw cannotFulfillGoalException("Cannot visit tile: hero is out of MPs!");
|
||||||
if (ai->moveHeroToTile(g.tile, g.hero.get()))
|
if (ai->moveHeroToTile(g.tile, g.hero.get()))
|
||||||
{
|
{
|
||||||
throw goalFulfilledException("");
|
throw goalFulfilledException (g);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -2081,6 +2048,16 @@ void VCAI::endTurn()
|
|||||||
tlog4 << "Player " << playerID << " ended turn\n";
|
tlog4 << "Player " << playerID << " ended turn\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool VCAI::fulfillsGoal (CGoal &goal, CGoal &mainGoal)
|
||||||
|
{
|
||||||
|
if (mainGoal.goalType == GET_OBJ && goal.goalType == VISIT_TILE) //deduce that GET_OBJ was completed by visiting object's tile
|
||||||
|
{ //TODO: more universal mechanism
|
||||||
|
if (cb->getObj(mainGoal.objid)->visitablePos() == goal.tile)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void VCAI::striveToGoal(const CGoal &ultimateGoal)
|
void VCAI::striveToGoal(const CGoal &ultimateGoal)
|
||||||
{
|
{
|
||||||
if (ultimateGoal.invalid())
|
if (ultimateGoal.invalid())
|
||||||
@@ -2146,9 +2123,8 @@ void VCAI::striveToGoal(const CGoal &ultimateGoal)
|
|||||||
catch(goalFulfilledException &e)
|
catch(goalFulfilledException &e)
|
||||||
{
|
{
|
||||||
completeGoal (goal);
|
completeGoal (goal);
|
||||||
if (maxGoals > 98) //completed goal was main goal
|
if (fulfillsGoal (goal, abstractGoal) || maxGoals > 98) //completed goal was main goal //TODO: find better condition
|
||||||
//TODO: find better condition
|
return;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
catch(std::exception &e)
|
catch(std::exception &e)
|
||||||
{
|
{
|
||||||
@@ -2193,9 +2169,8 @@ void VCAI::striveToGoal(const CGoal &ultimateGoal)
|
|||||||
}
|
}
|
||||||
catch(goalFulfilledException &e)
|
catch(goalFulfilledException &e)
|
||||||
{
|
{
|
||||||
completeGoal (goal);
|
completeGoal (goal); //FIXME: deduce that we have realized GET_OBJ goal
|
||||||
if (maxGoals > 98) //completed goal was main goal
|
if (fulfillsGoal (goal, abstractGoal) || maxGoals > 98) //completed goal was main goal
|
||||||
//TODO: find better condition
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
catch(std::exception &e)
|
catch(std::exception &e)
|
||||||
@@ -2210,7 +2185,7 @@ void VCAI::striveToGoal(const CGoal &ultimateGoal)
|
|||||||
|
|
||||||
void VCAI::striveToQuest (const QuestInfo &q)
|
void VCAI::striveToQuest (const QuestInfo &q)
|
||||||
{
|
{
|
||||||
if (q.quest.progress < CQuest::COMPLETE)
|
if (q.quest.missionType && q.quest.progress < CQuest::COMPLETE) //FIXME: quests are never synchronized. Pointer handling needed
|
||||||
{
|
{
|
||||||
MetaString ms;
|
MetaString ms;
|
||||||
q.quest.getRolloverText(ms, false);
|
q.quest.getRolloverText(ms, false);
|
||||||
@@ -2767,9 +2742,9 @@ TSubgoal CGoal::whatToDoToAchieve()
|
|||||||
case EVictoryConditionType::ARTIFACT:
|
case EVictoryConditionType::ARTIFACT:
|
||||||
return CGoal(GET_ART_TYPE).setaid(vc.ID);
|
return CGoal(GET_ART_TYPE).setaid(vc.ID);
|
||||||
case EVictoryConditionType::BEATHERO:
|
case EVictoryConditionType::BEATHERO:
|
||||||
return CGoal(GET_OBJ).setobjid(vc.ID);
|
return CGoal(GET_OBJ).setobjid(vc.obj->id);
|
||||||
case EVictoryConditionType::BEATMONSTER:
|
case EVictoryConditionType::BEATMONSTER:
|
||||||
return CGoal(GET_OBJ).setobjid(vc.ID);
|
return CGoal(GET_OBJ).setobjid(vc.obj->id);
|
||||||
case EVictoryConditionType::BUILDCITY:
|
case EVictoryConditionType::BUILDCITY:
|
||||||
//TODO build castle/capitol
|
//TODO build castle/capitol
|
||||||
break;
|
break;
|
||||||
@@ -2814,7 +2789,7 @@ TSubgoal CGoal::whatToDoToAchieve()
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case EVictoryConditionType::CAPTURECITY:
|
case EVictoryConditionType::CAPTURECITY:
|
||||||
return CGoal(GET_OBJ).setobjid(vc.ID);
|
return CGoal(GET_OBJ).setobjid(vc.obj->id);
|
||||||
case EVictoryConditionType::GATHERRESOURCE:
|
case EVictoryConditionType::GATHERRESOURCE:
|
||||||
return CGoal(COLLECT_RES).setresID(vc.ID).setvalue(vc.count);
|
return CGoal(COLLECT_RES).setresID(vc.ID).setvalue(vc.count);
|
||||||
//TODO mines? piles? marketplace?
|
//TODO mines? piles? marketplace?
|
||||||
|
@@ -158,6 +158,16 @@ struct CGoal
|
|||||||
HeroPtr hero; SETTER(HeroPtr, hero)
|
HeroPtr hero; SETTER(HeroPtr, hero)
|
||||||
const CGTownInstance *town; SETTER(CGTownInstance *, town)
|
const CGTownInstance *town; SETTER(CGTownInstance *, town)
|
||||||
int bid; SETTER(int, bid)
|
int bid; SETTER(int, bid)
|
||||||
|
|
||||||
|
bool operator== (CGoal &g)
|
||||||
|
{
|
||||||
|
switch (goalType)
|
||||||
|
{
|
||||||
|
case EGoals::GET_OBJ:
|
||||||
|
return objid == g.objid;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
enum {NOT_VISIBLE = 0, NOT_CHECKED = 1, NOT_AVAILABLE};
|
enum {NOT_VISIBLE = 0, NOT_CHECKED = 1, NOT_AVAILABLE};
|
||||||
@@ -344,7 +354,8 @@ public:
|
|||||||
void setGoal(HeroPtr h, const CGoal goal);
|
void setGoal(HeroPtr h, const CGoal goal);
|
||||||
void setGoal(HeroPtr h, EGoals goalType = INVALID);
|
void setGoal(HeroPtr h, EGoals goalType = INVALID);
|
||||||
void completeGoal (const CGoal goal); //safely removes goal from reserved hero
|
void completeGoal (const CGoal goal); //safely removes goal from reserved hero
|
||||||
void striveToQuest (const QuestInfo &q);
|
void striveToQuest (const QuestInfo &q);
|
||||||
|
bool fulfillsGoal (CGoal &goal, CGoal &mainGoal);
|
||||||
|
|
||||||
void recruitHero(const CGTownInstance * t);
|
void recruitHero(const CGTownInstance * t);
|
||||||
std::vector<const CGObjectInstance *> getPossibleDestinations(HeroPtr h);
|
std::vector<const CGObjectInstance *> getPossibleDestinations(HeroPtr h);
|
||||||
@@ -391,6 +402,43 @@ public:
|
|||||||
void requestActionASAP(boost::function<void()> whatToDo);
|
void requestActionASAP(boost::function<void()> whatToDo);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
std::string goalName(EGoals goalType); //TODO: move to CGoal class?
|
||||||
|
|
||||||
|
class cannotFulfillGoalException : public std::exception
|
||||||
|
{
|
||||||
|
std::string msg;
|
||||||
|
public:
|
||||||
|
explicit cannotFulfillGoalException(crstring _Message) : msg(_Message)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~cannotFulfillGoalException() throw ()
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
const char *what() const throw () OVERRIDE
|
||||||
|
{
|
||||||
|
return msg.c_str();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
class goalFulfilledException : public std::exception
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CGoal goal;
|
||||||
|
|
||||||
|
explicit goalFulfilledException(CGoal Goal) : goal(Goal)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~goalFulfilledException() throw ()
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
const char *what() const throw () OVERRIDE
|
||||||
|
{
|
||||||
|
return goalName(goal.goalType).c_str();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
template<int id>
|
template<int id>
|
||||||
bool objWithID(const CGObjectInstance *obj)
|
bool objWithID(const CGObjectInstance *obj)
|
||||||
|
Reference in New Issue
Block a user