1
0
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:
DjWarmonger
2012-10-03 09:29:55 +00:00
parent 3542bfdc63
commit 977acfafc8
2 changed files with 71 additions and 48 deletions

View File

@@ -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?

View File

@@ -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)