1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-24 22:14:36 +02:00

#928 and #931 should be fixed.

Ignoring savegames from newer versions of VCMI.
This commit is contained in:
Michał W. Urbańczyk 2012-04-17 12:46:21 +00:00
parent 294276ea13
commit cd4c93318d
3 changed files with 78 additions and 9 deletions

View File

@ -59,6 +59,7 @@ typename Container::value_type frontOrNull(const Container &c) //returns first e
return NULL;
}
#define SET_GLOBAL_STATE(ai) SetGlobalState _hlpSetState(ai);
#define NET_EVENT_HANDLER SET_GLOBAL_STATE(this)
@ -658,6 +659,12 @@ void VCAI::objectRemoved(const CGObjectInstance *obj)
LOG_ENTRY;
if(remove_if_present(visitableObjs, obj))
assert(obj->isVisitable());
BOOST_FOREACH(auto &p, reservedHeroesMap)
remove_if_present(p.second, obj);
//TODO
//there are other places where CGObjectinstance ptrs are stored...
}
void VCAI::showHillFortWindow(const CGObjectInstance *object, const CGHeroInstance *visitor)
@ -1145,9 +1152,11 @@ void VCAI::wander(const CGHeroInstance * h)
{
while(1)
{
std::vector <const CGObjectInstance *> dests (reservedHeroesMap[h].begin(), reservedHeroesMap[h].end()); //copy constructor
std::vector <ObjectIdRef> dests;
range::copy(reservedHeroesMap[h], std::back_inserter(dests));
if (!dests.size())
dests = getPossibleDestinations(h);
range::copy(getPossibleDestinations(h), std::back_inserter(dests));
if(!dests.size())
{
auto compareReinforcements = [h](const CGTownInstance *lhs, const CGTownInstance *rhs) -> bool
@ -1170,7 +1179,7 @@ void VCAI::wander(const CGHeroInstance * h)
if(townsReachable.size())
{
boost::sort(townsReachable, compareReinforcements);
dests.push_back(townsReachable.back());
dests.emplace_back(townsReachable.back());
}
else if(townsNotReachable.size())
{
@ -1208,12 +1217,19 @@ void VCAI::wander(const CGHeroInstance * h)
break;
}
}
const CGObjectInstance * obj = dests.front();
if(!goVisitObj(obj, h))
const ObjectIdRef&dest = dests.front();
if(!goVisitObj(dest, h))
{
BNLOG("Hero %s apparently used all MPs (%d left)\n", h->name % h->movement);
reserveObject(h, obj); //reserve that object - we predict it will be reached soon
setGoal(h, CGoal(VISIT_TILE).sethero(h).settile(obj->visitablePos()));
if(!dest)
{
BNLOG("Visit attempt made the object (id=%d) gone...", dest.id);
}
else
{
BNLOG("Hero %s apparently used all MPs (%d left)\n", h->name % h->movement);
reserveObject(h, dest); //reserve that object - we predict it will be reached soon
setGoal(h, CGoal(VISIT_TILE).sethero(h).settile(dest->visitablePos()));
}
break;
}
@ -1238,6 +1254,7 @@ void VCAI::setGoal (const CGHeroInstance *h, EGoals goalType)
void VCAI::battleStart(const CCreatureSet *army1, const CCreatureSet *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool side)
{
NET_EVENT_HANDLER;
assert(playerID > GameConstants::PLAYER_LIMIT || status.getBattle() == UPCOMING_BATTLE);
status.setBattle(ONGOING_BATTLE);
const CGObjectInstance *presumedEnemy = backOrNull(cb->getVisitableObjs(tile)); //may be NULL in some very are cases -> eg. visited monolith and fighting with an enemy at the FoW covered exit
@ -1247,6 +1264,7 @@ void VCAI::battleStart(const CCreatureSet *army1, const CCreatureSet *army2, int
void VCAI::battleEnd(const BattleResult *br)
{
NET_EVENT_HANDLER;
assert(status.getBattle() == ONGOING_BATTLE);
status.setBattle(ENDING_BATTLE);
bool won = br->winner == myCb->battleGetMySide();
@ -2852,3 +2870,28 @@ unsigned char & SectorMap::retreiveTile(crint3 pos)
{
return retreiveTileN(sector, pos);
}
const CGObjectInstance * ObjectIdRef::operator->() const
{
return cb->getObj(id, false);
}
ObjectIdRef::operator const CGObjectInstance*() const
{
return cb->getObj(id, false);
}
ObjectIdRef::ObjectIdRef(int _id) : id(_id)
{
}
ObjectIdRef::ObjectIdRef(const CGObjectInstance *obj) : id(obj->id)
{
}
bool ObjectIdRef::operator<(const ObjectIdRef &rhs) const
{
return id < rhs.id;
}

View File

@ -148,6 +148,27 @@ struct CIssueCommand : CGoal
CIssueCommand(boost::function<bool()> _command): CGoal(ISSUE_COMMAND), command(_command) {}
};
// AI lives in a dangerous world. CGObjectInstances under pointer may got deleted/hidden.
// This class stores object id, so we can detect when we lose access to the underlying object.
struct ObjectIdRef
{
int id;
const CGObjectInstance *operator->() const;
operator const CGObjectInstance *() const;
ObjectIdRef(int _id);
ObjectIdRef(const CGObjectInstance *obj);
bool operator<(const ObjectIdRef &rhs) const;
};
class ObjsVector : public std::vector<ObjectIdRef>
{
private:
};
class VCAI : public CAdventureAI
{
public:

View File

@ -330,7 +330,12 @@ void CLoadFile::openNextFile(const std::string &fname, int minimalVersion)
*this >> myVersion;
if(myVersion < minimalVersion)
{
tlog1 << "Error: Old file format! (file " << fname << " )\n";
tlog1 << "Error: Too old file format! (file " << fname << " )\n";
sfile.release();
}
if(myVersion > version)
{
tlog1 << "Error: Too new file format! (file " << fname << " )\n";
sfile.release();
}
}