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();
}
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)
{
visitedObject = NULL;
@@ -1815,6 +1780,8 @@ bool VCAI::moveHeroToTile(int3 dst, HeroPtr h)
if (visitedObject) //we step into something interesting
{
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
@@ -1918,7 +1885,7 @@ void VCAI::tryRealize(CGoal g)
//{
if (ai->moveHeroToTile(g.tile, g.hero.get()))
{
throw goalFulfilledException("");
throw goalFulfilledException (g);
}
//}
//else
@@ -1931,7 +1898,7 @@ void VCAI::tryRealize(CGoal g)
throw cannotFulfillGoalException("Cannot visit tile: hero is out of MPs!");
if (ai->moveHeroToTile(g.tile, g.hero.get()))
{
throw goalFulfilledException("");
throw goalFulfilledException (g);
}
}
break;
@@ -2081,6 +2048,16 @@ void VCAI::endTurn()
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)
{
if (ultimateGoal.invalid())
@@ -2146,9 +2123,8 @@ void VCAI::striveToGoal(const CGoal &ultimateGoal)
catch(goalFulfilledException &e)
{
completeGoal (goal);
if (maxGoals > 98) //completed goal was main goal
//TODO: find better condition
return;
if (fulfillsGoal (goal, abstractGoal) || maxGoals > 98) //completed goal was main goal //TODO: find better condition
return;
}
catch(std::exception &e)
{
@@ -2193,9 +2169,8 @@ void VCAI::striveToGoal(const CGoal &ultimateGoal)
}
catch(goalFulfilledException &e)
{
completeGoal (goal);
if (maxGoals > 98) //completed goal was main goal
//TODO: find better condition
completeGoal (goal); //FIXME: deduce that we have realized GET_OBJ goal
if (fulfillsGoal (goal, abstractGoal) || maxGoals > 98) //completed goal was main goal
return;
}
catch(std::exception &e)
@@ -2210,7 +2185,7 @@ void VCAI::striveToGoal(const CGoal &ultimateGoal)
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;
q.quest.getRolloverText(ms, false);
@@ -2767,9 +2742,9 @@ TSubgoal CGoal::whatToDoToAchieve()
case EVictoryConditionType::ARTIFACT:
return CGoal(GET_ART_TYPE).setaid(vc.ID);
case EVictoryConditionType::BEATHERO:
return CGoal(GET_OBJ).setobjid(vc.ID);
return CGoal(GET_OBJ).setobjid(vc.obj->id);
case EVictoryConditionType::BEATMONSTER:
return CGoal(GET_OBJ).setobjid(vc.ID);
return CGoal(GET_OBJ).setobjid(vc.obj->id);
case EVictoryConditionType::BUILDCITY:
//TODO build castle/capitol
break;
@@ -2814,7 +2789,7 @@ TSubgoal CGoal::whatToDoToAchieve()
}
break;
case EVictoryConditionType::CAPTURECITY:
return CGoal(GET_OBJ).setobjid(vc.ID);
return CGoal(GET_OBJ).setobjid(vc.obj->id);
case EVictoryConditionType::GATHERRESOURCE:
return CGoal(COLLECT_RES).setresID(vc.ID).setvalue(vc.count);
//TODO mines? piles? marketplace?

View File

@@ -158,6 +158,16 @@ struct CGoal
HeroPtr hero; SETTER(HeroPtr, hero)
const CGTownInstance *town; SETTER(CGTownInstance *, town)
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};
@@ -344,7 +354,8 @@ public:
void setGoal(HeroPtr h, const CGoal goal);
void setGoal(HeroPtr h, EGoals goalType = INVALID);
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);
std::vector<const CGObjectInstance *> getPossibleDestinations(HeroPtr h);
@@ -391,6 +402,43 @@ public:
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>
bool objWithID(const CGObjectInstance *obj)