1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-02-15 13:33:36 +02:00

Fixed #1430, work-around to make #1435 non-crashing.

Fixed at least one of the #1428 infinite turns cases.
This commit is contained in:
Michał W. Urbańczyk 2013-09-11 21:57:08 +00:00
parent 9aaaa0027e
commit b62bb096a7
5 changed files with 42 additions and 11 deletions

View File

@ -1228,9 +1228,7 @@ void VCAI::recruitCreatures(const CGDwelling * d)
// if(containsSavedRes(c->cost)) // if(containsSavedRes(c->cost))
// continue; // continue;
TResources myRes = cb->getResourceAmount(); amin(count, freeResources() / VLC->creh->creatures[creID]->cost);
myRes[Res::GOLD] -= GOLD_RESERVE;
amin(count, myRes / VLC->creh->creatures[creID]->cost);
if(count > 0) if(count > 0)
cb->recruitCreatures(d, creID, count, i); cb->recruitCreatures(d, creID, count, i);
} }
@ -1900,6 +1898,11 @@ void VCAI::tryRealize(CGoal g)
//cb->recalculatePaths(); //cb->recalculatePaths();
if(!g.hero->movement) if(!g.hero->movement)
throw cannotFulfillGoalException("Cannot visit tile: hero is out of MPs!"); throw cannotFulfillGoalException("Cannot visit tile: hero is out of MPs!");
if(g.tile == g.hero->visitablePos() && cb->getVisitableObjs(g.hero->visitablePos()).size() < 2)
{
logAi->warnStream() << boost::format("Why do I want to move hero %s to tile %s? Already standing on that tile! ") % g.hero->name % g.tile;
throw goalFulfilledException (g);
}
//if(!g.isBlockedBorderGate(g.tile)) //if(!g.isBlockedBorderGate(g.tile))
//{ //{
if (ai->moveHeroToTile(g.tile, g.hero.get())) if (ai->moveHeroToTile(g.tile, g.hero.get()))
@ -2614,6 +2617,14 @@ void VCAI::validateObject(ObjectIdRef obj)
} }
} }
TResources VCAI::freeResources() const
{
TResources myRes = cb->getResourceAmount();
myRes[Res::GOLD] -= GOLD_RESERVE;
vstd::amax(myRes[Res::GOLD], 0);
return myRes;
}
AIStatus::AIStatus() AIStatus::AIStatus()
{ {
battle = NO_BATTLE; battle = NO_BATTLE;
@ -3264,7 +3275,7 @@ TSubgoal CGoal::whatToDoToAchieve()
{ {
for (auto type : creature.second) for (auto type : creature.second)
{ {
if (type == objid) if (type == objid && ai->freeResources().canAfford(VLC->creh->creatures[type]->cost))
dwellings.push_back(d); dwellings.push_back(d);
} }
} }
@ -3273,7 +3284,7 @@ TSubgoal CGoal::whatToDoToAchieve()
if (dwellings.size()) if (dwellings.size())
{ {
boost::sort(dwellings, isCloser); boost::sort(dwellings, isCloser);
return CGoal(GET_OBJ).setobjid (dwellings.front()->id.getNum()); //TODO: consider needed resources return CGoal(GET_OBJ).setobjid (dwellings.front()->id.getNum());
} }
else else
return CGoal(EXPLORE); return CGoal(EXPLORE);
@ -3435,9 +3446,12 @@ TSubgoal CGoal::whatToDoToAchieve()
{ {
if(creLevel.first) if(creLevel.first)
{ {
auto creature = VLC->creh->creatures[creLevel.second.front()]; for(auto & creatureID : creLevel.second)
if(cb->getResourceAmount().canAfford(creature->cost)) {
return false; auto creature = VLC->creh->creatures[creatureID];
if(ai->freeResources().canAfford(creature->cost))
return false;
}
} }
} }
} }

View File

@ -420,6 +420,7 @@ public:
std::vector<HeroPtr> getUnblockedHeroes() const; std::vector<HeroPtr> getUnblockedHeroes() const;
HeroPtr primaryHero() const; HeroPtr primaryHero() const;
TResources freeResources() const; //owned resources minus gold reserve
TResources estimateIncome() const; TResources estimateIncome() const;
bool containsSavedRes(const TResources &cost) const; bool containsSavedRes(const TResources &cost) const;
void checkHeroArmy (HeroPtr h); void checkHeroArmy (HeroPtr h);

View File

@ -629,6 +629,15 @@ namespace vstd
return *pos; return *pos;
} }
template <typename Container>
typename Container::const_reference atOrDefault(const Container &r, size_t index, const typename Container::const_reference &defaultValue)
{
if(isValidIndex(r, index))
return r[index];
return defaultValue;
}
using boost::math::round; using boost::math::round;
} }
using vstd::operator-=; using vstd::operator-=;

View File

@ -1431,7 +1431,10 @@ void CBattleInterface::spellCast( const BattleSpellCast * sc )
break; break;
default: default:
text = CGI->generaltexth->allTexts[565]; //The %s casts %s text = CGI->generaltexth->allTexts[565]; //The %s casts %s
boost::algorithm::replace_first(text, "%s", CGI->creh->creatures[sc->attackerType]->namePl); //casting stack if(auto castingCreature = vstd::atOrDefault(CGI->creh->creatures, sc->attackerType, nullptr))
boost::algorithm::replace_first(text, "%s", castingCreature->namePl); //casting stack
else
boost::algorithm::replace_first(text, "%s", "@Unknown caster@"); //should not happen
} }
if (plural) if (plural)
{ {
@ -1459,9 +1462,9 @@ void CBattleInterface::spellCast( const BattleSpellCast * sc )
{ {
boost::algorithm::replace_first(text, "%s", curInt->cb->battleGetHeroInfo(sc->side).name); boost::algorithm::replace_first(text, "%s", curInt->cb->battleGetHeroInfo(sc->side).name);
} }
else if(sc->attackerType < CGI->creh->creatures.size()) if(auto castingCreature = vstd::atOrDefault(CGI->creh->creatures, sc->attackerType, nullptr))
{ {
boost::algorithm::replace_first(text, "%s", CGI->creh->creatures[sc->attackerType]->namePl); //creature caster boost::algorithm::replace_first(text, "%s", castingCreature->namePl); //creature caster
} }
else else
{ {

View File

@ -23,6 +23,10 @@ public:
ConstTransitivePtr(T *Ptr = nullptr) ConstTransitivePtr(T *Ptr = nullptr)
: ptr(Ptr) : ptr(Ptr)
{} {}
ConstTransitivePtr(std::nullptr_t)
: ptr(nullptr)
{}
const T& operator*() const const T& operator*() const
{ {