From 310c3692650deee3801cf89edab058f3e7760238 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20W=2E=20Urba=C5=84czyk?= Date: Wed, 5 Aug 2009 00:05:37 +0000 Subject: [PATCH] Fixed two possible block-ups in AI. Fixed possible problems with picking hero available to recruit (no more duplicates hopefully). --- AI/GeniusAI/BattleLogic.cpp | 4 +++- AI/GeniusAI/CGeniusAI.cpp | 2 +- lib/CGameState.cpp | 43 ++++++++++++++++++++++++------------- lib/CGameState.h | 2 +- lib/NetPacksLib.cpp | 1 + server/CGameHandler.cpp | 20 +++++++++++++---- 6 files changed, 50 insertions(+), 22 deletions(-) diff --git a/AI/GeniusAI/BattleLogic.cpp b/AI/GeniusAI/BattleLogic.cpp index 8859946af..364585d9c 100644 --- a/AI/GeniusAI/BattleLogic.cpp +++ b/AI/GeniusAI/BattleLogic.cpp @@ -685,13 +685,15 @@ list CBattleLogic::PerformDefaultAction(int stackID, int &additionalInfo) for (std::map::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; } diff --git a/AI/GeniusAI/CGeniusAI.cpp b/AI/GeniusAI/CGeniusAI.cpp index e571a8662..fdde9b15e 100644 --- a/AI/GeniusAI/CGeniusAI.cpp +++ b/AI/GeniusAI/CGeniusAI.cpp @@ -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 diff --git a/lib/CGameState.cpp b/lib/CGameState.cpp index 2c7d58841..92ebbe097 100644 --- a/lib/CGameState.cpp +++ b/lib/CGameState.cpp @@ -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 &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 pool; - int sum=0, r; + if(native) { - for(std::map::iterator i=heroesPool.begin(); i!=heroesPool.end(); i++) + for(std::map::iterator i=available.begin(); i!=available.end(); i++) { - if(pavailable[i->first] & 1<second->type->heroType/2 == town->typeID - && i->second->subID != notThatOne - ) + if(pavailable.find(i->first)->second & 1<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::iterator i=heroesPool.begin(); i!=heroesPool.end(); i++) + int sum=0, r; + + for(std::map::iterator i=available.begin(); i!=available.end(); i++) { - if(pavailable[i->first] & 1<second->subID != notThatOne - ) + if(pavailable.find(i->first)->second & 1<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; itype->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()) diff --git a/lib/CGameState.h b/lib/CGameState.h index de458bc84..aba605693 100644 --- a/lib/CGameState.h +++ b/lib/CGameState.h @@ -251,7 +251,7 @@ public: std::map heroesPool; //[subID] - heroes available to buy; NULL if not available std::map 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 &available) const; template void serialize(Handler &h, const int version) { diff --git a/lib/NetPacksLib.cpp b/lib/NetPacksLib.cpp index a136cdeb9..b7555cbd9 100644 --- a/lib/NetPacksLib.cpp +++ b/lib/NetPacksLib.cpp @@ -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); diff --git a/server/CGameHandler.cpp b/server/CGameHandler.cpp index 0b8ecad70..a16d06c0f 100644 --- a/server/CGameHandler.cpp +++ b/server/CGameHandler.cpp @@ -660,6 +660,8 @@ void CGameHandler::newTurn() n.day = gs->day + 1; n.resetBuilded = true; + std::map pool = gs->hpool.heroesPool; + for ( std::map::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 pool = gs->hpool.heroesPool; + for ( std::map::iterator i=gs->players.begin() ; i!=gs->players.end();i++) + for(std::vector::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);