فهرست منبع

AI heroes move to random safe objects.
AI recruits heroes.

Trevor Standley 16 سال پیش
والد
کامیت
b987f02cb0
4فایلهای تغییر یافته به همراه413 افزوده شده و 147 حذف شده
  1. 12 8
      AI/GeniusAI/BattleLogic.cpp
  2. 183 83
      AI/GeniusAI/CGeniusAI.cpp
  3. 217 55
      AI/GeniusAI/CGeniusAI.h
  4. 1 1
      AI/GeniusAI/Common.h

+ 12 - 8
AI/GeniusAI/BattleLogic.cpp

@@ -215,7 +215,7 @@ void CBattleLogic::MakeStatistics(int currentCreatureId)
 		(float)totalHitPoints / (float)totalEnemyHitPoints < 0.5f)
 	{
 		m_bEnemyDominates = true;
-		MsgBox("** EnemyDominates!");
+		DbgBox("** EnemyDominates!");
 	}
 	else
 	{
@@ -261,11 +261,11 @@ BattleAction CBattleLogic::MakeDecision(int stackID)
 	{
 		creatures = PerformDefaultAction(stackID, additionalInfo);
 	}
-	/*
-	std::string message("Creature will be attacked - ");
+	
+	/*std::string message("Creature will be attacked - ");
 	message += boost::lexical_cast<std::string>(creature_to_attack);
-	MsgBox(message.c_str());
-	*/
+	DbgBox(message.c_str());*/
+	
 
 	if (additionalInfo == -1 || creatures.empty())
 	{
@@ -288,7 +288,9 @@ BattleAction CBattleLogic::MakeDecision(int stackID)
 		}
 		else
 		{
+#if defined PRINT_DEBUG
 			PrintBattleAction(ba);
+#endif
 			return ba;
 		}
 	}
@@ -567,7 +569,9 @@ BattleAction CBattleLogic::MakeAttack(int attackerID, int destinationID)
 			{
 				ba.additionalInfo = dest_tile;
 				ba.actionType = action_walk_and_attack;
+#if defined PRINT_DEBUG
 				PrintBattleAction(ba);
+#endif
 				return ba;
 			}
 		}
@@ -578,7 +582,7 @@ BattleAction CBattleLogic::MakeAttack(int attackerID, int destinationID)
 			{
 				// attack!
 				ba.actionType = action_walk_and_attack;
-#if defined _DEBUG
+#if defined PRINT_DEBUG
 				PrintBattleAction(ba);
 #endif
 				return ba;
@@ -594,12 +598,12 @@ BattleAction CBattleLogic::MakeAttack(int attackerID, int destinationID)
 		message = "Attacker position X=";
 		message += boost::lexical_cast<std::string>(m_battleHelper.DecodeXPosition(nearest_pos)) + ", Y=";
 		message += boost::lexical_cast<std::string>(m_battleHelper.DecodeYPosition(nearest_pos));
-		MsgBox(message.c_str());
+		DbgBox(message.c_str());
 
 		ba.actionType = action_walk;
 		ba.destinationTile = (ui16)nearest_pos;
 		ba.additionalInfo  = -1;
-#if defined _DEBUG
+#if defined PRINT_DEBUG
 		PrintBattleAction(ba);
 #endif
 		return ba;

+ 183 - 83
AI/GeniusAI/CGeniusAI.cpp

@@ -8,9 +8,11 @@ using namespace GeniusAI;
 #include <windows.h>
 #endif
 
-void MsgBox(const char *msg, bool messageBox)
+void DbgBox(const char *msg, bool messageBox)
 {
+#if defined PRINT_DEBUG
 #if defined _DEBUG
+//#if 0
 #	if defined (_MSC_VER) && (_MSC_VER >= 1020)
 	if (messageBox)
 	{
@@ -19,10 +21,11 @@ void MsgBox(const char *msg, bool messageBox)
 #	endif
 	std::cout << msg << std::endl;
 #endif
+#endif
 }
 
 CGeniusAI::CGeniusAI()
-	: m_generalAI(),turn(0)
+	: m_generalAI(),turn(0),firstTurn(true)
 {
 }
 
@@ -40,7 +43,7 @@ void CGeniusAI::init(ICallback *CB)
 	serialID = m_cb->getMySerial();
 	std::string info = std::string("GeniusAI initialized for player ") + boost::lexical_cast<std::string>(playerID);
 	m_battleLogic = NULL;
-	MsgBox(info.c_str());
+	DbgBox(info.c_str());
 }
 
 unsigned long randomFromInt(unsigned long in)
@@ -48,99 +51,184 @@ unsigned long randomFromInt(unsigned long in)
 	return (in*214013+2531011);
 }
 
-void CGeniusAI::doHero(const CGHeroInstance * h)
-{
 
+void CGeniusAI::reportResources()
+{
+	std::cout << "AI Player " <<m_cb->getMySerial()<< " with " <<  m_cb->howManyHeroes(true) << " heroes. " << std::endl;
 	
-	if(!h==NULL)
+	std::cout << m_cb->getResourceAmount(0) << " wood. ";
+	std::cout << m_cb->getResourceAmount(1) << " mercury. ";
+	std::cout << m_cb->getResourceAmount(2) << " ore. ";
+	std::cout << m_cb->getResourceAmount(3) << " sulfer. ";
+	std::cout << m_cb->getResourceAmount(4) << " cristal. ";
+	std::cout << m_cb->getResourceAmount(5) << " gems. ";
+	std::cout << m_cb->getResourceAmount(6) << " gold.";
+	std::cout << std::endl;
+}
+
+void CGeniusAI::addHeroObjectives(CGeniusAI::HypotheticalGameState::HeroModel &h, CGeniusAI::HypotheticalGameState &hgs)
+{
+	int3 hpos, destination;
+	CPath path;
+	hpos = h.pos;
+	int movement = h.remainingMovement;
+	for(std::set<AIObjectContainer>::const_iterator i = hgs.knownVisitableObjects.begin(); i != hgs.knownVisitableObjects.end();i++)
 	{
-		int3 destination, pos;
-		pos=h->convertPosition(h->pos,false);
-		
-		vector<int3> buildingPath;
+		if(i->o->ID==54||i->o->ID==34)	//creatures, another hero
+			continue;
 
-		int movement = h->movement;
-		int usedMovement = 0;
-		int attempts = 0;
-		CPath path;
-		do{
-			do{
-				destination=pos;
-				attempts++;
-				destination.x+=randomFromInt((attempts*1243)+turn)%9-4;
-				destination.y+=randomFromInt((attempts*1243)+turn+1234)%9-4;
-			}while((!m_cb->getPath(pos,destination,h,path)||(path.nodes[0].dist>=(movement-usedMovement))) && attempts<100);
-			
-			if(attempts<100)
+		if(i->o->getOwner()==m_cb->getMyColor())
+			continue;
+		
+		destination = i->o->getSightCenter();
+		if(hpos.z==destination.z)
+			if(m_cb->getPath(hpos,destination,h.h,path))
+		{
+			path.convert(0);
+			if(path.nodes[0].dist<movement)
 			{
-				pos = destination;
-				usedMovement += path.nodes[0].dist;
-				path.convert(0);
-				for(int i = path.nodes.size()-2;i>=0;i--)
-					buildingPath.push_back(path.nodes[i].coord);
+				AIObjective::Type tp = AIObjective::visit;
+				
+				HeroObjective ho(tp,i->o,&h);
+				std::set<HeroObjective>::iterator found = currentHeroObjectives.find(ho);
+				if(found==currentHeroObjectives.end())
+					currentHeroObjectives.insert(ho);
+				else
+					found->whoCanAchieve.push_back(&h);
 			}
-			else break;
-		}while(movement-usedMovement>=50);
+		}
+	}
+}
+void CGeniusAI::addTownObjectives(HypotheticalGameState::TownModel &t, HypotheticalGameState & hgs)
+{
+	//recruitHero
+	//recruitCreatures
+	//upgradeCreatures
+	//buildBuilding
 
-		for(int i = 0; i < buildingPath.size();i++)
+	if(hgs.heroModels.size()<3) //recruitHero
+	{
+		if(!t.visitingHero)
 		{
-			m_cb->moveHero(h,buildingPath[i]);
-			//std::cout << "(" << buildingPath[i].x << ", " << buildingPath[i].y << ")" << std::endl;
+			for(int i =0; i < hgs.AvailableHeroesToBuy.size();i++)
+				if(hgs.AvailableHeroesToBuy[i]->army.slots.size()>1)//only buy heros with units
+				{
+					TownObjective to(AIObjective::recruitHero,&t,0);
+					currentTownObjectives.insert(to);
+				}
+
 		}
+	}
+	
 
+//	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;
+//	}
+	
+
+
+}
+
+void CGeniusAI::TownObjective::fulfill(CGeniusAI & cg, HypotheticalGameState & hgs)
+{
+	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);
 }
 
-void CGeniusAI::doTown(const CGTownInstance * t)
+void CGeniusAI::HeroObjective::fulfill(CGeniusAI & cg, HypotheticalGameState & hgs)
 {
-	if(m_cb->howManyHeroes(true)<3)		//recrute up to 3 heroes
+	switch(type)
 	{
-		if(t->visitingHero==NULL)
+	case visit:
+		HypotheticalGameState::HeroModel * h = whoCanAchieve[rand()%whoCanAchieve.size()];
+		int3 hpos, destination;
+		CPath path;
+		hpos = h->pos;
+		//std::cout << "trying to visit " << object->hoverName << std::endl;
+		
+		destination = object->getSightCenter();
+		if(cg.m_cb->getPath(hpos,destination,h->h,path))
 		{
-			std::vector<const CGHeroInstance *> toBuy = m_cb->getAvailableHeroes(t);
-			if(toBuy[0]->army.slots.size()>1)//only buy heros with units
-			{
-				m_cb->recruitHero(t,toBuy[0]);
-			}
+			path.convert(0);
+			for(int i = path.nodes.size()-2;i>=0;i--)
+				cg.m_cb->moveHero(h->h,path.nodes[i].coord);
+			h->remainingMovement-=path.nodes[0].dist;
+			if(object->blockVisit)
+				h->pos = path.nodes[1].coord;
+			else
+				h->pos=destination;
+			std::set<AIObjectContainer>::iterator i = hgs.knownVisitableObjects.find(AIObjectContainer(object));
+			if(i!=hgs.knownVisitableObjects.end())
+				hgs.knownVisitableObjects.erase(i);
 		}
 
-	}
-
-//	m_cb->recruitCreatures(t, ui32 ID, ui32 amount)
 
-	
+	}
 }
 
 
 void CGeniusAI::yourTurn()
 {
-	//static boost::mutex mutex;
-	//boost::mutex::scoped_lock scoped_lock(mutex);
-	turn++;
-
-	std::cout << "AI Player " <<m_cb->getMySerial()<< " with " <<  m_cb->howManyHeroes(true) << " heroes. " << std::endl;
-
-	
-	std::cout << m_cb->getResourceAmount(0) << " wood. ";
-	std::cout << m_cb->getResourceAmount(1) << " mercury. ";
-	std::cout << m_cb->getResourceAmount(2) << " ore. ";
-	std::cout << m_cb->getResourceAmount(3) << " sulfer. ";
-	std::cout << m_cb->getResourceAmount(4) << " cristal. ";
-	std::cout << m_cb->getResourceAmount(5) << " gems. ";
-	std::cout << m_cb->getResourceAmount(6) << " gold.";
-	std::cout << std::endl;
+	static int seed = rand();
+	srand(seed);
+	if(firstTurn)
+	{
+		//m_cb->sendMessage("vcmieagles");
+		firstTurn = false;
 
+			
+	}
+	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();
+	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);
 
-	std::vector < const CGHeroInstance *> heroes = m_cb->getHeroesInfo();	
-	for(std::vector < const CGHeroInstance *>::iterator i = heroes.begin(); i < heroes.end(); i++)
-		doHero(*i);
+		getObjectives(hgs);
 
-//	std::vector < const CGTownInstance *> towns = m_cb->getTownsInfo();	
-//	for(std::vector < const CGTownInstance *>::iterator i = towns.begin(); i < towns.end(); i++)
-//		doTown(*i);
+	}while(!currentHeroObjectives.empty());
 
 
+	seed = rand();
 	m_cb->endTurn();
 }
 
@@ -154,14 +242,26 @@ void CGeniusAI::heroCreated(const CGHeroInstance *hero)
 
 }
 
-void CGeniusAI::heroMoved(const TryMoveHero &TMH)
+void CGeniusAI::tileRevealed(int3 pos)
 {
-	MsgBox("** CGeniusAI::heroMoved **");
+	std::vector < const CGObjectInstance * > objects = 	m_cb->getVisitableObjs(pos);
+	for(std::vector < const CGObjectInstance * >::iterator o = objects.begin();o!=objects.end();o++)
+		knownVisitableObjects.insert(*o);
+	objects = m_cb->getFlaggableObjects(pos);
+	for(std::vector < const CGObjectInstance * >::iterator o = objects.begin();o!=objects.end();o++)
+		knownVisitableObjects.insert(*o);
+}
 
-	
+void CGeniusAI::tileHidden(int3 pos)
+{
 
 }
 
+void CGeniusAI::heroMoved(const TryMoveHero &TMH)
+{
+	DbgBox("** CGeniusAI::heroMoved **");
+}
+
 void CGeniusAI::heroGotLevel(const CGHeroInstance *hero, int pskill, std::vector<ui16> &skills, boost::function<void(ui32)> &callback)
 {
 	callback(rand() % skills.size());
@@ -187,7 +287,7 @@ void CGeniusAI::actionFinished(const BattleAction *action)
 	message += "), side(";
 	message += boost::lexical_cast<std::string>((unsigned)action->side);
 	message += ")";
-	MsgBox(message.c_str());
+	DbgBox(message.c_str());
 }
 /**
  * occurs BEFORE every action taken by any stack or by the hero
@@ -199,21 +299,21 @@ void CGeniusAI::actionStarted(const BattleAction *action)
 	message += "), side(";
 	message += boost::lexical_cast<std::string>((unsigned)action->side);
 	message += ")";
-	MsgBox(message.c_str());
+	DbgBox(message.c_str());
 }
 /**
  * called when stack is performing attack
  */
 void CGeniusAI::battleAttack(BattleAttack *ba)
 {
-	MsgBox("\t\t\tCGeniusAI::battleAttack");
+	DbgBox("\t\t\tCGeniusAI::battleAttack");
 }
 /**
  * called when stack receives damage (after battleAttack())
  */
 void CGeniusAI::battleStacksAttacked(std::set<BattleStackAttacked> & bsa)
 {
-	MsgBox("\t\t\tCGeniusAI::battleStacksAttacked");
+	DbgBox("\t\t\tCGeniusAI::battleStacksAttacked");
 }
 /**
  * called by engine when battle starts; side=0 - left, side=1 - right
@@ -224,7 +324,7 @@ void CGeniusAI::battleStart(CCreatureSet *army1, CCreatureSet *army2, int3 tile,
 	assert(!m_battleLogic); //************** assert fails when AI starts two battles at same time? ***************
 	m_battleLogic = new BattleAI::CBattleLogic(m_cb, army1, army2, tile, hero1, hero2, side);
 
-	MsgBox("** CGeniusAI::battleStart **");
+	DbgBox("** CGeniusAI::battleStart **");
 }
 /**
  *
@@ -241,7 +341,7 @@ void CGeniusAI::battleEnd(BattleResult *br)
 	delete m_battleLogic;
 	m_battleLogic = NULL;
 
-	MsgBox("** CGeniusAI::battleEnd **");
+	DbgBox("** CGeniusAI::battleEnd **");
 }
 /**
  * called at the beggining of each turn, round=-1 is the tactic phase, round=0 is the first "normal" turn
@@ -250,7 +350,7 @@ void CGeniusAI::battleNewRound(int round)
 {
 	std::string message("\tCGeniusAI::battleNewRound - ");
 	message += boost::lexical_cast<std::string>(round);
-	MsgBox(message.c_str());
+	DbgBox(message.c_str());
 
 	m_battleLogic->SetCurrentTurn(round);
 }
@@ -264,42 +364,42 @@ void CGeniusAI::battleStackMoved(int ID, int dest, int distance, bool end)
 	message += "), dest(";
 	message += boost::lexical_cast<std::string>(dest);
 	message += ")";
-	MsgBox(message.c_str());
+	DbgBox(message.c_str());
 }
 /**
  *
  */
 void CGeniusAI::battleSpellCast(SpellCast *sc)
 {
-	MsgBox("\t\t\tCGeniusAI::battleSpellCast");
+	DbgBox("\t\t\tCGeniusAI::battleSpellCast");
 }
 /**
  * called when battlefield is prepared, prior the battle beginning
  */
 void CGeniusAI::battlefieldPrepared(int battlefieldType, std::vector<CObstacle*> obstacles)
 {
-	MsgBox("CGeniusAI::battlefieldPrepared");
+	DbgBox("CGeniusAI::battlefieldPrepared");
 }
 /**
  *
  */
 void CGeniusAI::battleStackMoved(int ID, int dest, bool startMoving, bool endMoving)
 {
-	MsgBox("\t\t\tCGeniusAI::battleStackMoved");
+	DbgBox("\t\t\tCGeniusAI::battleStackMoved");
 }
 /**
  *
  */
 void CGeniusAI::battleStackAttacking(int ID, int dest)
 {
-	MsgBox("\t\t\tCGeniusAI::battleStackAttacking");
+	DbgBox("\t\t\tCGeniusAI::battleStackAttacking");
 }
 /**
  *
  */
 void CGeniusAI::battleStackIsAttacked(int ID, int dmg, int killed, int IDby, bool byShooting)
 {
-	MsgBox("\t\t\tCGeniusAI::battleStackIsAttacked");
+	DbgBox("\t\t\tCGeniusAI::battleStackIsAttacked");
 }
 
 /**
@@ -311,7 +411,7 @@ BattleAction CGeniusAI::activeStack(int stackID)
 
 	message += boost::lexical_cast<std::string>(stackID);
 	message += ")";
-	MsgBox(message.c_str());
+	DbgBox(message.c_str());
 
 	return m_battleLogic->MakeDecision(stackID);
 };

+ 217 - 55
AI/GeniusAI/CGeniusAI.h

@@ -1,55 +1,217 @@
-#ifndef __CGENIUSAI_H__
-#define __CGENIUSAI_H__
-
-#include "Common.h"
-#include "BattleLogic.h"
-#include "GeneralAI.h"
-namespace GeniusAI {
-
-class CGeniusAI : public CGlobalAI
-{
-private:
-	ICallback*							m_cb;
-	GeniusAI::BattleAI::CBattleLogic*	m_battleLogic;
-	GeniusAI::GeneralAI::CGeneralAI		m_generalAI;
-
-	void doHero(const CGHeroInstance * h);
-	void doTown(const CGTownInstance * t);
-	int turn;
-
-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 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);
-	// 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);
-};
-}
-
-#endif // __CGENIUSAI_H__
+#ifndef __CGENIUSAI_H__
+#define __CGENIUSAI_H__
+
+#include "Common.h"
+#include "BattleLogic.h"
+#include "GeneralAI.h"
+#include "../../lib/VCMI_Lib.h"
+#include <set>
+#include <list>
+#include <queue>
+namespace GeniusAI {
+
+class CGeniusAI : public CGlobalAI
+{
+private:
+	ICallback*							m_cb;
+	GeniusAI::BattleAI::CBattleLogic*	m_battleLogic;
+	GeniusAI::GeneralAI::CGeneralAI		m_generalAI;
+	class AIObjectContainer
+	{
+	public:
+		AIObjectContainer(const CGObjectInstance * o):o(o){}
+		const CGObjectInstance * o;
+		bool operator<(const AIObjectContainer& b)const
+		{
+			if (o->pos!=b.o->pos)
+				return o->pos<b.o->pos;
+			return o->id<b.o->id;
+		}
+	};
+	std::set< AIObjectContainer > knownVisitableObjects;
+
+	class HypotheticalGameState
+	{
+	public:
+		HypotheticalGameState(CGeniusAI & AI)
+			:knownVisitableObjects(AI.knownVisitableObjects)
+		{
+			std::vector < const CGHeroInstance *> heroes = AI.m_cb->getHeroesInfo();	
+			for(std::vector < const CGHeroInstance *>::iterator i = heroes.begin(); i != heroes.end(); i++)
+				heroModels.push_back(HeroModel(*i));
+			
+			std::vector < const CGTownInstance *> towns = AI.m_cb->getTownsInfo();	
+			for(std::vector < const CGTownInstance *>::iterator i = towns.begin(); i != towns.end(); i++)
+				townModels.push_back(TownModel(*i));
+
+			if(AI.m_cb->howManyTowns()!=0)
+				AvailableHeroesToBuy = AI.m_cb->getAvailableHeroes(AI.m_cb->getTownInfo(0,0));
+		}
+
+		class TownModel
+		{
+		public:
+			TownModel(const CGTownInstance *t):t(t){visitingHero=(t->visitingHero!=NULL);}
+			const CGTownInstance *t;
+			bool visitingHero;
+		};
+		class HeroModel
+		{
+		public:
+			HeroModel(const CGHeroInstance * h):h(h){
+				pos = h->getPosition(false);remainingMovement = h->movement;
+			}
+			int3 pos;
+			int remainingMovement;
+			const CGHeroInstance * h;
+		};
+		std::vector<const CGHeroInstance *> AvailableHeroesToBuy;
+		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;
+	bool firstTurn;
+
+
+	class AIObjective
+	{
+	public: 
+		enum Type
+		{
+			//hero objectives
+			visit,
+			attack,
+			flee,
+			dismissUnits,
+			dismissYourself,
+			finishTurn,			//uses up remaining motion to get somewhere nice.
+
+			//town objectives
+			recruitHero,
+			recruitCreatures,
+			upgradeCreatures,
+			buildBuilding
+		};
+		
+		Type type;
+		//virtual bool operator < (const AIObjective &)const=0;
+		//virtual bool stillPossible(const HypotheticalGameState &)const = 0;
+		virtual void fulfill(CGeniusAI &,HypotheticalGameState & hgs)=0;
+		virtual float getValue() const=0;	//how much is it worth to the AI to achieve
+	};
+
+	class HeroObjective: public AIObjective
+	{
+	public:
+		int3 pos;
+		const CGObjectInstance * object;
+		std::vector<HypotheticalGameState::HeroModel *> whoCanAchieve;
+		
+		HeroObjective(){}
+		HeroObjective(Type t):object(NULL){type = t;}
+		HeroObjective(Type t,const CGObjectInstance * object,HypotheticalGameState::HeroModel *h):object(object)
+		{
+			pos = object->pos;
+			type = t;
+			whoCanAchieve.push_back(h);
+			_value = rand();
+		}
+		bool operator < (const HeroObjective &other)const
+		{
+			if(type != other.type)
+				return type<other.type;
+			if(pos!=other.pos)
+				return pos < other.pos;
+			if(object->id!=other.object->id)
+				return object->id < other.object->id;
+			return false;
+		}
+		//bool stillPossible(const HypotheticalGameState &) const;
+		void fulfill(CGeniusAI &,HypotheticalGameState & hgs);
+		float getValue() const{return _value;}
+	private:
+		float _value;
+	};
+
+				//town objectives
+			//recruitHero,
+			//recruitCreatures,
+			//upgradeCreatures,
+			//buildBuilding
+
+	class TownObjective: public AIObjective
+	{
+	public:
+		HypotheticalGameState::TownModel * whichTown;
+		int which;				//which hero, which building, which creature, 
+
+		TownObjective(Type t,HypotheticalGameState::TownModel * tn,int which):whichTown(tn),which(which){type = t;_value = rand();}
+		
+		bool operator < (const TownObjective &other)const
+		{
+			if(type != other.type)
+				return type<other.type;
+			if(whichTown->t->id!=other.whichTown->t->id)
+				return whichTown->t->id < other.whichTown->t->id;
+			return false;
+		}
+		void fulfill(CGeniusAI &,HypotheticalGameState & hgs);
+		float getValue() const {return _value;}
+	private:
+		float _value;
+	};
+
+	class AIObjectivePtrCont
+	{
+	public:
+		AIObjectivePtrCont():obj(NULL){}
+		AIObjectivePtrCont(AIObjective * obj):obj(obj){};
+		AIObjective * obj;
+		bool operator < (const AIObjectivePtrCont & other) const
+		{return obj->getValue()<other.obj->getValue();}
+
+	};
+	std::set<HeroObjective> currentHeroObjectives;	//can be fulfilled right now
+	std::set<TownObjective> currentTownObjectives;
+
+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 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);
+	// 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);
+};
+}
+
+#endif // __CGENIUSAI_H__

+ 1 - 1
AI/GeniusAI/Common.h

@@ -11,6 +11,6 @@
 #include "../../AI_Base.h"
 #pragma warning (default: 4100 4244)
 
-void MsgBox(const char *msg, bool messageBox = false);
+void DbgBox(const char *msg, bool messageBox = false);
 
 #endif/*__GENIUS_COMMON__*/