瀏覽代碼

AI now attacks randomly.

Trevor Standley 16 年之前
父節點
當前提交
45d311a9f5
共有 2 個文件被更改,包括 186 次插入128 次删除
  1. 88 51
      AI/GeniusAI/CGeniusAI.cpp
  2. 98 77
      AI/GeniusAI/CGeniusAI.h

+ 88 - 51
AI/GeniusAI/CGeniusAI.cpp

@@ -1,6 +1,6 @@
 #include "CGeniusAI.h"
 #include <iostream>
-
+#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<AIObjectContainer>::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<int, CBuilding *> thisTownsBuildings = m_cb->getCBuildingsByID(t.t);
+	for(std::map<int, CBuilding *>::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 <CGeniusAI::HypotheticalGameState::HeroModel>::iterator i = hgs.heroModels.begin(); i != hgs.heroModels.end(); i++)
-		addHeroObjectives(*i,hgs);
-
-	for(std::vector <CGeniusAI::HypotheticalGameState::TownModel>::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 <CGeniusAI::HypotheticalGameState::HeroModel>::iterator i = hgs.heroModels.begin(); i != hgs.heroModels.end(); i++)
+		addHeroObjectives(*i,hgs);
+
+	for(std::vector <CGeniusAI::HypotheticalGameState::TownModel>::iterator i = hgs.townModels.begin(); i != hgs.townModels.end(); i++)
+		addTownObjectives(*i,hgs);
+	for(std::set<CGeniusAI::HeroObjective>::iterator i = currentHeroObjectives.begin(); i != currentHeroObjectives.end(); i++)
+		objectiveQueue.push_back(AIObjectivePtrCont(&(*i)));
+	for(std::set<CGeniusAI::TownObjective>::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<pos.x;x++)
 		for(int y = 0;y<pos.y;y++)
 			for(int z = 0;z<pos.z;z++)
 				tileRevealed(int3(x,y,z));
+	///////////////////////////////////////////////////////////////////////////////////
 
-	reportResources();
+//	reportResources();
 	turn++;
-	HypotheticalGameState hgs(*this);
-	getObjectives(hgs);
-	vector<AIObjectivePtrCont> 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<CGeniusAI::HeroObjective>::iterator i = currentHeroObjectives.begin(); i != currentHeroObjectives.end(); i++)
-			AIObjectiveQueue.push_back(AIObjectivePtrCont(&(*i)));
-		for(std::set<CGeniusAI::TownObjective>::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::tileHidden(int3 pos)
+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 <AIObjectContainer>::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<ui16> &skills, boost::function<void(ui32)> &callback)

+ 98 - 77
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 <set>
 #include <list>
 #include <queue>
-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<BattleState> m_state; //are we engaged into battle?
+
 	class AIObjectContainer
 	{
 	public:
@@ -37,11 +45,11 @@ private:
 			return o->id<b.o->id;
 		}
 	};
-	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<const CGHeroInstance *> AvailableHeroesToBuy;
+		std::vector<int> resourceAmounts;
 		std::vector<HeroModel> heroModels;
 		std::vector<TownModel> 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<BattleState> 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()<other.obj->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<HeroObjective> currentHeroObjectives;	//can be fulfilled right now
 	std::set<TownObjective> currentTownObjectives;
+	std::vector<AIObjectivePtrCont> objectiveQueue;
+
+public:
+	CGeniusAI();
+	virtual ~CGeniusAI();
 
-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<CSelectableComponent*> & components, int askID){};
-	virtual void showBlockingDialog(const std::string &text, const std::vector<Component> &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 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<CSelectableComponent*> & components, int askID){};
+	virtual void showBlockingDialog(const std::string &text, const std::vector<Component> &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<ui16> &skills, boost::function<void(ui32)> &callback);
-	virtual void showGarrisonDialog(const CArmedInstance *up, const CGHeroInstance *down, boost::function<void()> &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<BattleStackAttacked> & 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<CObstacle*> 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<ui16> &skills, boost::function<void(ui32)> &callback);
+	virtual void showGarrisonDialog(const CArmedInstance *up, const CGHeroInstance *down, boost::function<void()> &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<BattleStackAttacked> & 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<CObstacle*> 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__