1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-01-24 03:47:18 +02:00

Fixed two possible block-ups in AI. Fixed possible problems with picking hero available to recruit (no more duplicates hopefully).

This commit is contained in:
Michał W. Urbańczyk 2009-08-05 00:05:37 +00:00
parent 1872c2d575
commit 310c369265
6 changed files with 50 additions and 22 deletions

View File

@ -685,13 +685,15 @@ list<int> CBattleLogic::PerformDefaultAction(int stackID, int &additionalInfo)
for (std::map<int, int>::iterator it = votes.begin(); it != votes.end(); ++it)
{
if (it->second > max_vote)
if (m_cb->battleGetStackByID(it->first)->attackerOwned == m_side //it's hostile stack
&& it->second > max_vote)
{
max_vote = it->second;
creatures.push_front(it->first);
}
}
additionalInfo = 0; // list contains creatures which shoud be attacked
return creatures;
}

View File

@ -108,7 +108,7 @@ void CGeniusAI::addTownObjectives(HypotheticalGameState::TownModel &t, Hypotheti
//buildBuilding
if(hgs.heroModels.size()<3&&hgs.resourceAmounts[6]>=2500) //recruitHero
{
if(!t.visitingHero)
if(!t.visitingHero && vstd::contains(t.t->builtBuildings, 5)) //no visiting hero and built tavern
{
for(int i =0; i < hgs.AvailableHeroesToBuy.size();i++)
if(hgs.AvailableHeroesToBuy[i]!=NULL&&hgs.AvailableHeroesToBuy[i]->army.slots.size()>1)//only buy heros with units

View File

@ -662,39 +662,45 @@ bool CStack::willMove()
&& ! hasFeatureOfType(StackFeature::NOT_ACTIVE); //eg. Ammo Cart
}
CGHeroInstance* CGameState::HeroesPool::pickHeroFor(bool native, int player, const CTown *town, int notThatOne)
CGHeroInstance * CGameState::HeroesPool::pickHeroFor(bool native, int player, const CTown *town, std::map<ui32,CGHeroInstance *> &available) const
{
CGHeroInstance *ret = NULL;
if(player<0 || player>=PLAYER_LIMIT)
{
tlog1 << "Cannot pick hero for " << town->Name() << ". Wrong owner!\n";
return NULL;
}
std::vector<CGHeroInstance *> pool;
int sum=0, r;
if(native)
{
for(std::map<ui32,CGHeroInstance *>::iterator i=heroesPool.begin(); i!=heroesPool.end(); i++)
for(std::map<ui32,CGHeroInstance *>::iterator i=available.begin(); i!=available.end(); i++)
{
if(pavailable[i->first] & 1<<player
&& i->second->type->heroType/2 == town->typeID
&& i->second->subID != notThatOne
)
if(pavailable.find(i->first)->second & 1<<player
&& i->second->type->heroType/2 == town->typeID)
{
pool.push_back(i->second);
}
}
if(!pool.size())
return pickHeroFor(false,player,town,notThatOne);
{
tlog1 << "Cannot pick native hero for " << player << ". Picking any...\n";
return pickHeroFor(false, player, town, available);
}
else
return pool[rand()%pool.size()];
{
ret = pool[rand()%pool.size()];
}
}
else
{
for(std::map<ui32,CGHeroInstance *>::iterator i=heroesPool.begin(); i!=heroesPool.end(); i++)
int sum=0, r;
for(std::map<ui32,CGHeroInstance *>::iterator i=available.begin(); i!=available.end(); i++)
{
if(pavailable[i->first] & 1<<player
&& i->second->subID != notThatOne
)
if(pavailable.find(i->first)->second & 1<<player)
{
pool.push_back(i->second);
sum += i->second->type->heroClass->selectionProbability[town->typeID];
@ -705,17 +711,24 @@ CGHeroInstance* CGameState::HeroesPool::pickHeroFor(bool native, int player, con
tlog1 << "There are no heroes available for player " << player<<"!\n";
return NULL;
}
r = rand()%sum;
for(unsigned int i=0; i<pool.size(); i++)
{
r -= pool[i]->type->heroClass->selectionProbability[town->typeID];
if(r<0)
return pool[i];
ret = pool[i];
}
return pool[pool.size()-1];
if(!ret)
ret = pool.back();
}
available.erase(ret->subID);
return ret;
}
//void CGameState::apply(CPack * pack)
//{
// while(!mx->try_lock())

View File

@ -251,7 +251,7 @@ public:
std::map<ui32,CGHeroInstance *> heroesPool; //[subID] - heroes available to buy; NULL if not available
std::map<ui32,ui8> pavailable; // [subid] -> which players can recruit hero
CGHeroInstance * pickHeroFor(bool native, int player, const CTown *town, int notThatOne=-1);
CGHeroInstance * pickHeroFor(bool native, int player, const CTown *town, std::map<ui32,CGHeroInstance *> &available) const;
template <typename Handler> void serialize(Handler &h, const int version)
{

View File

@ -455,6 +455,7 @@ DLL_EXPORT void SetHeroArtifacts::setArtAtPos(ui16 pos, int art)
DLL_EXPORT void HeroRecruited::applyGs( CGameState *gs )
{
assert(vstd::contains(gs->hpool.heroesPool, hid));
CGHeroInstance *h = gs->hpool.heroesPool[hid];
CGTownInstance *t = gs->getTown(tid);
h->setOwner(player);

View File

@ -660,6 +660,8 @@ void CGameHandler::newTurn()
n.day = gs->day + 1;
n.resetBuilded = true;
std::map<ui32,CGHeroInstance *> pool = gs->hpool.heroesPool;
for ( std::map<ui8, PlayerState>::iterator i=gs->players.begin() ; i!=gs->players.end();i++)
{
if(i->first == 255) continue;
@ -667,12 +669,12 @@ void CGameHandler::newTurn()
{
SetAvailableHeroes sah;
sah.player = i->first;
CGHeroInstance *h = gs->hpool.pickHeroFor(true,i->first,&VLC->townh->towns[gs->scenarioOps->getIthPlayersSettings(i->first).castle]);
CGHeroInstance *h = gs->hpool.pickHeroFor(true,i->first,&VLC->townh->towns[gs->scenarioOps->getIthPlayersSettings(i->first).castle], pool);
if(h)
sah.hid1 = h->subID;
else
sah.hid1 = -1;
h = gs->hpool.pickHeroFor(false,i->first,&VLC->townh->towns[gs->scenarioOps->getIthPlayersSettings(i->first).castle],sah.hid1);
h = gs->hpool.pickHeroFor(false,i->first,&VLC->townh->towns[gs->scenarioOps->getIthPlayersSettings(i->first).castle], pool);
if(h)
sah.hid2 = h->subID;
else
@ -2236,6 +2238,7 @@ bool CGameHandler::hireHero( ui32 tid, ui8 hid )
)
return false;
CGHeroInstance *nh = gs->getPlayer(t->tempOwner)->availableHeroes[hid];
assert(nh);
HeroRecruited hr;
hr.tid = tid;
@ -2244,9 +2247,18 @@ bool CGameHandler::hireHero( ui32 tid, ui8 hid )
hr.tile = t->pos - int3(1,0,0);
sendAndApply(&hr);
std::map<ui32,CGHeroInstance *> pool = gs->hpool.heroesPool;
for ( std::map<ui8, PlayerState>::iterator i=gs->players.begin() ; i!=gs->players.end();i++)
for(std::vector<CGHeroInstance *>::iterator j = i->second.availableHeroes.begin(); j != i->second.availableHeroes.end(); j++)
if(*j)
pool.erase((**j).subID);
SetAvailableHeroes sah;
(hid ? sah.hid2 : sah.hid1) = gs->hpool.pickHeroFor(false,t->tempOwner,t->town)->subID;
(hid ? sah.hid1 : sah.hid2) = gs->getPlayer(t->tempOwner)->availableHeroes[!hid]->subID;
CGHeroInstance *h1 = gs->hpool.pickHeroFor(false,t->tempOwner,t->town, pool),
*h2 = gs->getPlayer(t->tempOwner)->availableHeroes[!hid];
(hid ? sah.hid2 : sah.hid1) = h1 ? h1->subID : -1;
(hid ? sah.hid1 : sah.hid2) = h2 ? h2->subID : -1;
sah.player = t->tempOwner;
sah.flags = hid+1;
sendAndApply(&sah);