From 45d311a9f5bba0630f200c2cafa589d25bb97211 Mon Sep 17 00:00:00 2001 From: Trevor Standley Date: Tue, 4 Aug 2009 08:56:38 +0000 Subject: [PATCH] AI now attacks randomly. --- AI/GeniusAI/CGeniusAI.cpp | 139 +++++++++++++++++++----------- AI/GeniusAI/CGeniusAI.h | 175 +++++++++++++++++++++----------------- 2 files changed, 186 insertions(+), 128 deletions(-) diff --git a/AI/GeniusAI/CGeniusAI.cpp b/AI/GeniusAI/CGeniusAI.cpp index a243e1894..8badbc2ce 100644 --- a/AI/GeniusAI/CGeniusAI.cpp +++ b/AI/GeniusAI/CGeniusAI.cpp @@ -1,6 +1,6 @@ #include "CGeniusAI.h" #include - +#include "../../hch/CBuildingHandler.h" using namespace std; using namespace GeniusAI; @@ -74,10 +74,11 @@ void CGeniusAI::addHeroObjectives(CGeniusAI::HypotheticalGameState::HeroModel &h int movement = h.remainingMovement; for(std::set::const_iterator i = hgs.knownVisitableObjects.begin(); i != hgs.knownVisitableObjects.end();i++) { - if(i->o->ID==54||i->o->ID==34) //creatures, another hero - continue; + // if(i->o->ID==54||i->o->ID==34) //creatures, another hero + // continue; - if(i->o->getOwner()==m_cb->getMyColor()) + if(i->o->ID==53) //mine + if(i->o->getOwner()==m_cb->getMyColor())//don't visit if you own, there's almost no point(maybe to leave guards or because the hero's trapped). continue; destination = i->o->getSightCenter(); @@ -105,8 +106,7 @@ void CGeniusAI::addTownObjectives(HypotheticalGameState::TownModel &t, Hypotheti //recruitCreatures //upgradeCreatures //buildBuilding - - if(hgs.heroModels.size()<3) //recruitHero + if(hgs.heroModels.size()<3&&hgs.resourceAmounts[6]>=2500) //recruitHero { if(!t.visitingHero) { @@ -120,43 +120,43 @@ void CGeniusAI::addTownObjectives(HypotheticalGameState::TownModel &t, Hypotheti } } +/* for(int i = 0; i < t.t->creatures.size() ;i++) + { + if(t.t->creatures[i].second.empty()) continue; -// for(int i = 0; i < t.t->creatures.size() ;i++) -// { -// int ID = t.t->creatures[i].second.back(); -// CCreature -// cout << "town has " << t.t->creatures[i].first << " level " << i+1 << " " << creature->namePl << endl; -// } - - + int ID = t.t->creatures[i].second.back(); + + const CCreature *creature = m_cb->getCCreatureByID(ID); + cout << "town has " << t.t->creatures[i].first << " "<< creature->namePl << " (AI Strength " << creature->AIValue << ")." << endl; + } + //buildBuilding + std::map thisTownsBuildings = m_cb->getCBuildingsByID(t.t); + for(std::map::iterator i = thisTownsBuildings.begin(); i != thisTownsBuildings.end();i++) + cout << "structure "<< i->first << ", " << i->second->Name() << ", build?= " << m_cb->canBuildStructure(t.t,i->first) << endl; +*/ } -void CGeniusAI::TownObjective::fulfill(CGeniusAI & cg, HypotheticalGameState & hgs) +void CGeniusAI::TownObjective::fulfill(CGeniusAI & cg,HypotheticalGameState &hgs) { + cg.m_cb->waitTillRealize = true; switch(type) { case recruitHero: cg.m_cb->recruitHero(whichTown->t,hgs.AvailableHeroesToBuy[which]); hgs.heroModels.push_back(hgs.AvailableHeroesToBuy[which]); whichTown->visitingHero = true; + //TODO: sub 2500 gold from hgs here } -} -void CGeniusAI::getObjectives(CGeniusAI::HypotheticalGameState & hgs) -{ - currentHeroObjectives.clear(); - currentTownObjectives.clear(); - for(std::vector ::iterator i = hgs.heroModels.begin(); i != hgs.heroModels.end(); i++) - addHeroObjectives(*i,hgs); - - for(std::vector ::iterator i = hgs.townModels.begin(); i != hgs.townModels.end(); i++) - addTownObjectives(*i,hgs); + cg.m_cb->waitTillRealize = false; } -void CGeniusAI::HeroObjective::fulfill(CGeniusAI & cg, HypotheticalGameState & hgs) + +void CGeniusAI::HeroObjective::fulfill(CGeniusAI & cg,HypotheticalGameState & hgs) { + cg.m_cb->waitTillRealize = true; switch(type) { case visit: @@ -170,8 +170,16 @@ void CGeniusAI::HeroObjective::fulfill(CGeniusAI & cg, HypotheticalGameState & h if(cg.m_cb->getPath(hpos,destination,h->h,path)) { path.convert(0); - for(int i = path.nodes.size()-2;i>=0;i--) + //wait over, battle over too. hero might be killed. check. + for(int i = path.nodes.size()-2;i>=0&&(cg.m_cb->getHeroSerial(h->h) >= 0);i--) + { cg.m_cb->moveHero(h->h,path.nodes[i].coord); + + if(cg.m_state.get() != NO_BATTLE) + cg.m_state.waitUntil(NO_BATTLE);//wait for battle end + } + + h->remainingMovement-=path.nodes[0].dist; if(object->blockVisit) h->pos = path.nodes[1].coord; @@ -184,49 +192,64 @@ void CGeniusAI::HeroObjective::fulfill(CGeniusAI & cg, HypotheticalGameState & h } + cg.m_cb->waitTillRealize = false; } +void CGeniusAI::fillObjectiveQueue(HypotheticalGameState & hgs) +{ + objectiveQueue.clear(); + currentHeroObjectives.clear(); + currentTownObjectives.clear(); + + for(std::vector ::iterator i = hgs.heroModels.begin(); i != hgs.heroModels.end(); i++) + addHeroObjectives(*i,hgs); + + for(std::vector ::iterator i = hgs.townModels.begin(); i != hgs.townModels.end(); i++) + addTownObjectives(*i,hgs); + for(std::set::iterator i = currentHeroObjectives.begin(); i != currentHeroObjectives.end(); i++) + objectiveQueue.push_back(AIObjectivePtrCont(&(*i))); + for(std::set::iterator i = currentTownObjectives.begin(); i != currentTownObjectives.end(); i++) + objectiveQueue.push_back(AIObjectivePtrCont(&(*i))); +} +CGeniusAI::AIObjective * CGeniusAI::getBestObjective() +{ + trueGameState = HypotheticalGameState(*this); + + fillObjectiveQueue(trueGameState); + + if(!objectiveQueue.empty()) + return max_element(objectiveQueue.begin(),objectiveQueue.end())->obj; + return NULL; + +} void CGeniusAI::yourTurn() { + static int seed = rand(); srand(seed); if(firstTurn) { //m_cb->sendMessage("vcmieagles"); + //m_cb->sendMessage("vcmiformenos"); + //m_cb->sendMessage("vcmiformenos"); firstTurn = false; - - } + //////////////TODO: replace with updates. Also add suspected objects list.///////// knownVisitableObjects.clear(); int3 pos = m_cb->getMapSize(); for(int x = 0;x AIObjectiveQueue; - do{ - - //std::cout << "I have " << currentHeroObjectives.size() << " things I could do with my heroes!" << std::endl; - //std::cout << "I have " << currentTownObjectives.size() << " things I could do with my towns!" << std::endl; - - AIObjectiveQueue.clear(); - for(std::set::iterator i = currentHeroObjectives.begin(); i != currentHeroObjectives.end(); i++) - AIObjectiveQueue.push_back(AIObjectivePtrCont(&(*i))); - for(std::set::iterator i = currentTownObjectives.begin(); i != currentTownObjectives.end(); i++) - AIObjectiveQueue.push_back(AIObjectivePtrCont(&(*i))); - if(!AIObjectiveQueue.empty()) - max_element(AIObjectiveQueue.begin(),AIObjectiveQueue.end())->obj->fulfill(*this, hgs); - - getObjectives(hgs); - - }while(!currentHeroObjectives.empty()); + AIObjective * objective; + while((objective = getBestObjective())!=NULL) + objective->fulfill(*this,trueGameState); seed = rand(); m_cb->endTurn(); @@ -252,14 +275,28 @@ void CGeniusAI::tileRevealed(int3 pos) knownVisitableObjects.insert(*o); } +void CGeniusAI::newObject(const CGObjectInstance * obj) //eg. ship built in shipyard +{ + knownVisitableObjects.insert(obj); +} + +void CGeniusAI::objectRemoved(const CGObjectInstance *obj) //eg. collected resource, picked artifact, beaten hero +{ + std::set ::iterator o = knownVisitableObjects.find(obj); + if(o!=knownVisitableObjects.end()) + knownVisitableObjects.erase(o); +} + void CGeniusAI::tileHidden(int3 pos) { - + } void CGeniusAI::heroMoved(const TryMoveHero &TMH) { - DbgBox("** CGeniusAI::heroMoved **"); + //DbgBox("** CGeniusAI::heroMoved **"); + + } void CGeniusAI::heroGotLevel(const CGHeroInstance *hero, int pskill, std::vector &skills, boost::function &callback) diff --git a/AI/GeniusAI/CGeniusAI.h b/AI/GeniusAI/CGeniusAI.h index bde2a2c24..e8ecf6044 100644 --- a/AI/GeniusAI/CGeniusAI.h +++ b/AI/GeniusAI/CGeniusAI.h @@ -1,30 +1,38 @@ -#ifndef __CGENIUSAI_H__ -#define __CGENIUSAI_H__ - -#include "Common.h" -#include "BattleLogic.h" -#include "GeneralAI.h" -#include "..\..\lib\CondSh.h" -#include "../../lib/VCMI_Lib.h" +#ifndef __CGENIUSAI_H__ +#define __CGENIUSAI_H__ + +#include "Common.h" +#include "BattleLogic.h" +#include "GeneralAI.h" +#include "..\..\lib\CondSh.h" +//#include "../../lib/VCMI_Lib.h" +//#include "../../global.h" +//#include "../../client/CGameInfo.h" #include #include #include -namespace GeniusAI { - -enum BattleState -{ - NO_BATTLE, - UPCOMING_BATTLE, - ONGOING_BATTLE, - ENDING_BATTLE -}; - -class CGeniusAI : public CGlobalAI -{ -private: - ICallback* m_cb; - GeniusAI::BattleAI::CBattleLogic* m_battleLogic; - GeniusAI::GeneralAI::CGeneralAI m_generalAI; + +class CBuilding; + +namespace GeniusAI { + +enum BattleState +{ + NO_BATTLE, + UPCOMING_BATTLE, + ONGOING_BATTLE, + ENDING_BATTLE +}; + +class CGeniusAI : public CGlobalAI +{ +private: + ICallback* m_cb; + GeniusAI::BattleAI::CBattleLogic* m_battleLogic; + GeniusAI::GeneralAI::CGeneralAI m_generalAI; + + CondSh m_state; //are we engaged into battle? + class AIObjectContainer { public: @@ -37,11 +45,11 @@ private: return o->idid; } }; - std::set< AIObjectContainer > knownVisitableObjects; - + class HypotheticalGameState { public: + HypotheticalGameState(){} HypotheticalGameState(CGeniusAI & AI) :knownVisitableObjects(AI.knownVisitableObjects) { @@ -55,6 +63,8 @@ private: if(AI.m_cb->howManyTowns()!=0) AvailableHeroesToBuy = AI.m_cb->getAvailableHeroes(AI.m_cb->getTownInfo(0,0)); + + for(int i = 0; i < 7;i++)resourceAmounts.push_back(AI.m_cb->getResourceAmount(i)); } class TownModel @@ -75,19 +85,12 @@ private: const CGHeroInstance * h; }; std::vector AvailableHeroesToBuy; + std::vector resourceAmounts; std::vector heroModels; std::vector townModels; std::set< AIObjectContainer > knownVisitableObjects; }; - void addHeroObjectives(HypotheticalGameState::HeroModel &h, HypotheticalGameState & hgs); - void addTownObjectives(HypotheticalGameState::TownModel &h, HypotheticalGameState & hgs); - void getObjectives(HypotheticalGameState & hgs); - void reportResources(); - int turn; - CondSh m_state; //are we engaged into battle? - bool firstTurn; - - + class AIObjective { public: @@ -112,6 +115,7 @@ private: //virtual bool operator < (const AIObjective &)const=0; //virtual bool stillPossible(const HypotheticalGameState &)const = 0; virtual void fulfill(CGeniusAI &,HypotheticalGameState & hgs)=0; + virtual HypotheticalGameState pretend(const HypotheticalGameState &) =0; virtual float getValue() const=0; //how much is it worth to the AI to achieve }; @@ -141,18 +145,18 @@ private: return object->id < other.object->id; return false; } - //bool stillPossible(const HypotheticalGameState &) const; void fulfill(CGeniusAI &,HypotheticalGameState & hgs); + HypotheticalGameState pretend(const HypotheticalGameState &hgs){return hgs;}; float getValue() const{return _value;} private: float _value; }; - //town objectives - //recruitHero, - //recruitCreatures, - //upgradeCreatures, - //buildBuilding + //town objectives + //recruitHero, + //recruitCreatures, + //upgradeCreatures, + //buildBuilding class TownObjective: public AIObjective { @@ -171,6 +175,7 @@ private: return false; } void fulfill(CGeniusAI &,HypotheticalGameState & hgs); + HypotheticalGameState pretend(const HypotheticalGameState &hgs){return hgs;}; float getValue() const {return _value;} private: float _value; @@ -186,44 +191,60 @@ private: {return obj->getValue()getValue();} }; + HypotheticalGameState trueGameState; + AIObjective * getBestObjective(); + void addHeroObjectives(HypotheticalGameState::HeroModel &h, HypotheticalGameState & hgs); + void addTownObjectives(HypotheticalGameState::TownModel &h, HypotheticalGameState & hgs); + void fillObjectiveQueue(HypotheticalGameState & hgs); + + void reportResources(); + int turn; + bool firstTurn; + std::set< AIObjectContainer > knownVisitableObjects; std::set currentHeroObjectives; //can be fulfilled right now std::set currentTownObjectives; + std::vector objectiveQueue; -public: - CGeniusAI(); - virtual ~CGeniusAI(); - - virtual void init(ICallback * CB); - virtual void yourTurn(); - virtual void heroKilled(const CGHeroInstance *); - virtual void heroCreated(const CGHeroInstance *); - virtual void heroMoved(const TryMoveHero &); - virtual void heroPrimarySkillChanged(const CGHeroInstance * hero, int which, int val) {}; - virtual void showSelDialog(std::string text, std::vector & components, int askID){}; - virtual void showBlockingDialog(const std::string &text, const std::vector &components, ui32 askID, const int soundID, bool selection, bool cancel); //Show a dialog, player must take decision. If selection then he has to choose between one of given components, if cancel he is allowed to not choose. After making choice, CCallback::selectionMade should be called with number of selected component (1 - n) or 0 for cancel (if allowed) and askID. +public: + CGeniusAI(); + virtual ~CGeniusAI(); + + virtual void init(ICallback * CB); + virtual void yourTurn(); + virtual void heroKilled(const CGHeroInstance *); + virtual void heroCreated(const CGHeroInstance *); + virtual void heroMoved(const TryMoveHero &); + virtual void heroPrimarySkillChanged(const CGHeroInstance * hero, int which, int val) {}; + virtual void showSelDialog(std::string text, std::vector & components, int askID){}; + virtual void showBlockingDialog(const std::string &text, const std::vector &components, ui32 askID, const int soundID, bool selection, bool cancel); //Show a dialog, player must take decision. If selection then he has to choose between one of given components, if cancel he is allowed to not choose. After making choice, CCallback::selectionMade should be called with number of selected component (1 - n) or 0 for cancel (if allowed) and askID. virtual void tileRevealed(int3 pos); virtual void tileHidden(int3 pos); - virtual void heroGotLevel(const CGHeroInstance *hero, int pskill, std::vector &skills, boost::function &callback); - virtual void showGarrisonDialog(const CArmedInstance *up, const CGHeroInstance *down, boost::function &onEnd); - virtual void playerBlocked(int reason); - // battle - virtual void actionFinished(const BattleAction *action);//occurs AFTER every action taken by any stack or by the hero - virtual void actionStarted(const BattleAction *action);//occurs BEFORE every action taken by any stack or by the hero - virtual void battleAttack(BattleAttack *ba); //called when stack is performing attack - virtual void battleStacksAttacked(std::set & bsa); //called when stack receives damage (after battleAttack()) - virtual void battleEnd(BattleResult *br); - virtual void battleNewRound(int round); //called at the beggining of each turn, round=-1 is the tactic phase, round=0 is the first "normal" turn - virtual void battleStackMoved(int ID, int dest, int distance, bool end); - virtual void battleSpellCast(SpellCast *sc); - virtual void battleStart(CCreatureSet *army1, CCreatureSet *army2, int3 tile, CGHeroInstance *hero1, CGHeroInstance *hero2, bool side); //called by engine when battle starts; side=0 - left, side=1 - right - virtual void battlefieldPrepared(int battlefieldType, std::vector obstacles); //called when battlefield is prepared, prior the battle beginning - // - virtual void battleStackMoved(int ID, int dest, bool startMoving, bool endMoving); - virtual void battleStackAttacking(int ID, int dest); - virtual void battleStackIsAttacked(int ID, int dmg, int killed, int IDby, bool byShooting); - virtual BattleAction activeStack(int stackID); - void battleResultsApplied(); -}; -} - -#endif // __CGENIUSAI_H__ + virtual void heroGotLevel(const CGHeroInstance *hero, int pskill, std::vector &skills, boost::function &callback); + virtual void showGarrisonDialog(const CArmedInstance *up, const CGHeroInstance *down, boost::function &onEnd); + virtual void playerBlocked(int reason); + + virtual void objectRemoved(const CGObjectInstance *obj); //eg. collected resource, picked artifact, beaten hero + virtual void newObject(const CGObjectInstance * obj); //eg. ship built in shipyard + + + // battle + virtual void actionFinished(const BattleAction *action);//occurs AFTER every action taken by any stack or by the hero + virtual void actionStarted(const BattleAction *action);//occurs BEFORE every action taken by any stack or by the hero + virtual void battleAttack(BattleAttack *ba); //called when stack is performing attack + virtual void battleStacksAttacked(std::set & bsa); //called when stack receives damage (after battleAttack()) + virtual void battleEnd(BattleResult *br); + virtual void battleNewRound(int round); //called at the beggining of each turn, round=-1 is the tactic phase, round=0 is the first "normal" turn + virtual void battleStackMoved(int ID, int dest, int distance, bool end); + virtual void battleSpellCast(SpellCast *sc); + virtual void battleStart(CCreatureSet *army1, CCreatureSet *army2, int3 tile, CGHeroInstance *hero1, CGHeroInstance *hero2, bool side); //called by engine when battle starts; side=0 - left, side=1 - right + virtual void battlefieldPrepared(int battlefieldType, std::vector obstacles); //called when battlefield is prepared, prior the battle beginning + // + virtual void battleStackMoved(int ID, int dest, bool startMoving, bool endMoving); + virtual void battleStackAttacking(int ID, int dest); + virtual void battleStackIsAttacked(int ID, int dmg, int killed, int IDby, bool byShooting); + virtual BattleAction activeStack(int stackID); + void battleResultsApplied(); +}; +} + +#endif // __CGENIUSAI_H__