浏览代码

Various fixes. Temporarily replaced neural network's output with random number.

Trevor Standley 16 年之前
父节点
当前提交
f4743d2fc6
共有 5 个文件被更改,包括 800 次插入126 次删除
  1. 710 26
      AI/GeniusAI.brain
  2. 36 36
      AI/GeniusAI/AIPriorities.cpp
  3. 1 1
      AI/GeniusAI/AIPriorities.h
  4. 50 60
      AI/GeniusAI/CGeniusAI.cpp
  5. 3 3
      AI/GeniusAI/CGeniusAI.h

+ 710 - 26
AI/GeniusAI.brain

@@ -1,52 +1,736 @@
-34 16 17
+o 34 16 17
 R
 R
-34 16 17
+o 34 16 17
 R
 R
-47 16
+o 47 16
 R
 R
-101 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 24
+o 101 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 24
 R
 R
-98 16 17
+o 98 16 17
 R
 R
-98 16 17
+o 98 16 17
 R
 R
-100 16
+o 100 16
 R
 R
-38 16
+o 38 16
 R
 R
-61 16
+o 61 16
 R
 R
-53 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
+o 53 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
 R
 R
-53 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
+o 53 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
 R
 R
-53 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
+o 53 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
 R
 R
-53 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
+o 53 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
 R
 R
-53 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
+o 53 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
 R
 R
-53 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
+o 53 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
 R
 R
-53 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
+o 53 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
 R
 R
-53 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
+o 53 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
 R
 R
-28 16
+o 28 16
 R
 R
-81 16
+o 81 16
 R
 R
-83 25
+o 83 25
 R
 R
-31 16
+o 31 16
 R
 R
-57 24
+o 57 24
 R
 R
-23 16
+o 23 16
 R
 R
-102 16
+o 102 16
 R
 R
-37 24
+o 37 24
 R
 R
-51 16
+o 51 16
+R
+t 0 0 25
+R
+t 0 1 25
+R
+t 0 2 25
+R
+t 0 3 25
+R
+t 0 4 25
+R
+t 0 5 25
+R
+t 0 6 25
+R
+t 0 7 25
+R
+t 0 8 25
+R
+t 0 9 25
+R
+t 0 10 25
+R
+t 0 11 25
+R
+t 0 12 25
+R
+t 0 13 25
+R
+t 0 14 25
+R
+t 0 15 25
+R
+t 0 16 25
+R
+t 0 17 25
+R
+t 0 18 25
+R
+t 0 19 25
+R
+t 0 20 25
+R
+t 0 21 25
+R
+t 0 22 25
+R
+t 0 23 25
+R
+t 0 30 25
+R
+t 0 31 25
+R
+t 0 32 25
+R
+t 0 33 25
+R
+t 0 34 25
+R
+t 0 35 25
+R
+t 0 36 25
+R
+t 0 37 25
+R
+t 0 38 25
+R
+t 0 39 25
+R
+t 0 40 25
+R
+t 0 41 25
+R
+t 0 42 25
+R
+t 0 43 25
+R
+t 1 0 25
+R
+t 1 1 25
+R
+t 1 2 25
+R
+t 1 3 25
+R
+t 1 4 25
+R
+t 1 5 25
+R
+t 1 6 25
+R
+t 1 7 25
+R
+t 1 8 25
+R
+t 1 9 25
+R
+t 1 10 25
+R
+t 1 11 25
+R
+t 1 12 25
+R
+t 1 13 25
+R
+t 1 14 25
+R
+t 1 15 25
+R
+t 1 16 25
+R
+t 1 17 25
+R
+t 1 18 25
+R
+t 1 19 25
+R
+t 1 20 25
+R
+t 1 21 25
+R
+t 1 22 25
+R
+t 1 23 25
+R
+t 1 30 25
+R
+t 1 31 25
+R
+t 1 32 25
+R
+t 1 33 25
+R
+t 1 34 25
+R
+t 1 35 25
+R
+t 1 36 25
+R
+t 1 37 25
+R
+t 1 38 25
+R
+t 1 39 25
+R
+t 1 40 25
+R
+t 1 41 25
+R
+t 1 42 25
+R
+t 1 43 25
+R
+t 2 0 25
+R
+t 2 1 25
+R
+t 2 2 25
+R
+t 2 3 25
+R
+t 2 4 25
+R
+t 2 5 25
+R
+t 2 6 25
+R
+t 2 7 25
+R
+t 2 8 25
+R
+t 2 9 25
+R
+t 2 10 25
+R
+t 2 11 25
+R
+t 2 12 25
+R
+t 2 13 25
+R
+t 2 14 25
+R
+t 2 15 25
+R
+t 2 16 25
+R
+t 2 17 25
+R
+t 2 18 25
+R
+t 2 19 25
+R
+t 2 20 25
+R
+t 2 21 25
+R
+t 2 22 25
+R
+t 2 23 25
+R
+t 2 30 25
+R
+t 2 31 25
+R
+t 2 32 25
+R
+t 2 33 25
+R
+t 2 34 25
+R
+t 2 35 25
+R
+t 2 36 25
+R
+t 2 37 25
+R
+t 2 38 25
+R
+t 2 39 25
+R
+t 2 40 25
+R
+t 2 41 25
+R
+t 2 42 25
+R
+t 2 43 25
+R
+t 3 0 25
+R
+t 3 1 25
+R
+t 3 2 25
+R
+t 3 3 25
+R
+t 3 4 25
+R
+t 3 5 25
+R
+t 3 6 25
+R
+t 3 7 25
+R
+t 3 8 25
+R
+t 3 9 25
+R
+t 3 10 25
+R
+t 3 11 25
+R
+t 3 12 25
+R
+t 3 13 25
+R
+t 3 14 25
+R
+t 3 15 25
+R
+t 3 16 25
+R
+t 3 17 25
+R
+t 3 18 25
+R
+t 3 19 25
+R
+t 3 20 25
+R
+t 3 21 25
+R
+t 3 22 25
+R
+t 3 23 25
+R
+t 3 30 25
+R
+t 3 31 25
+R
+t 3 32 25
+R
+t 3 33 25
+R
+t 3 34 25
+R
+t 3 35 25
+R
+t 3 36 25
+R
+t 3 37 25
+R
+t 3 38 25
+R
+t 3 39 25
+R
+t 3 40 25
+R
+t 3 41 25
+R
+t 3 42 25
+R
+t 3 43 25
+R
+t 4 0 25
+R
+t 4 1 25
+R
+t 4 2 25
+R
+t 4 3 25
+R
+t 4 4 25
+R
+t 4 5 25
+R
+t 4 6 25
+R
+t 4 7 25
+R
+t 4 8 25
+R
+t 4 9 25
+R
+t 4 10 25
+R
+t 4 11 25
+R
+t 4 12 25
+R
+t 4 13 25
+R
+t 4 14 25
+R
+t 4 15 25
+R
+t 4 16 25
+R
+t 4 17 25
+R
+t 4 18 25
+R
+t 4 19 25
+R
+t 4 20 25
+R
+t 4 21 25
+R
+t 4 22 25
+R
+t 4 23 25
+R
+t 4 30 25
+R
+t 4 31 25
+R
+t 4 32 25
+R
+t 4 33 25
+R
+t 4 34 25
+R
+t 4 35 25
+R
+t 4 36 25
+R
+t 4 37 25
+R
+t 4 38 25
+R
+t 4 39 25
+R
+t 4 40 25
+R
+t 4 41 25
+R
+t 4 42 25
+R
+t 4 43 25
+R
+t 5 0 25
+R
+t 5 1 25
+R
+t 5 2 25
+R
+t 5 3 25
+R
+t 5 4 25
+R
+t 5 5 25
+R
+t 5 6 25
+R
+t 5 7 25
+R
+t 5 8 25
+R
+t 5 9 25
+R
+t 5 10 25
+R
+t 5 11 25
+R
+t 5 12 25
+R
+t 5 13 25
+R
+t 5 14 25
+R
+t 5 15 25
+R
+t 5 16 25
+R
+t 5 17 25
+R
+t 5 18 25
+R
+t 5 19 25
+R
+t 5 20 25
+R
+t 5 21 25
+R
+t 5 22 25
+R
+t 5 23 25
+R
+t 5 30 25
+R
+t 5 31 25
+R
+t 5 32 25
+R
+t 5 33 25
+R
+t 5 34 25
+R
+t 5 35 25
+R
+t 5 36 25
+R
+t 5 37 25
+R
+t 5 38 25
+R
+t 5 39 25
+R
+t 5 40 25
+R
+t 5 41 25
+R
+t 5 42 25
+R
+t 5 43 25
+R
+t 6 0 25
+R
+t 6 1 25
+R
+t 6 2 25
+R
+t 6 3 25
+R
+t 6 4 25
+R
+t 6 5 25
+R
+t 6 6 25
+R
+t 6 7 25
+R
+t 6 8 25
+R
+t 6 9 25
+R
+t 6 10 25
+R
+t 6 11 25
+R
+t 6 12 25
+R
+t 6 13 25
+R
+t 6 14 25
+R
+t 6 15 25
+R
+t 6 16 25
+R
+t 6 17 25
+R
+t 6 18 25
+R
+t 6 19 25
+R
+t 6 20 25
+R
+t 6 21 25
+R
+t 6 22 25
+R
+t 6 23 25
+R
+t 6 30 25
+R
+t 6 31 25
+R
+t 6 32 25
+R
+t 6 33 25
+R
+t 6 34 25
+R
+t 6 35 25
+R
+t 6 36 25
+R
+t 6 37 25
+R
+t 6 38 25
+R
+t 6 39 25
+R
+t 6 40 25
+R
+t 6 41 25
+R
+t 6 42 25
+R
+t 6 43 25
+R
+t 7 0 25
+R
+t 7 1 25
+R
+t 7 2 25
+R
+t 7 3 25
+R
+t 7 4 25
+R
+t 7 5 25
+R
+t 7 6 25
+R
+t 7 7 25
+R
+t 7 8 25
+R
+t 7 9 25
+R
+t 7 10 25
+R
+t 7 11 25
+R
+t 7 12 25
+R
+t 7 13 25
+R
+t 7 14 25
+R
+t 7 15 25
+R
+t 7 16 25
+R
+t 7 17 25
+R
+t 7 18 25
+R
+t 7 19 25
+R
+t 7 20 25
+R
+t 7 21 25
+R
+t 7 22 25
+R
+t 7 23 25
+R
+t 7 30 25
+R
+t 7 31 25
+R
+t 7 32 25
+R
+t 7 33 25
+R
+t 7 34 25
+R
+t 7 35 25
+R
+t 7 36 25
+R
+t 7 37 25
+R
+t 7 38 25
+R
+t 7 39 25
+R
+t 7 40 25
+R
+t 7 41 25
+R
+t 7 42 25
+R
+t 7 43 25
+R
+t 8 0 25
+R
+t 8 1 25
+R
+t 8 2 25
+R
+t 8 3 25
+R
+t 8 4 25
+R
+t 8 5 25
+R
+t 8 6 25
+R
+t 8 7 25
+R
+t 8 8 25
+R
+t 8 9 25
+R
+t 8 10 25
+R
+t 8 11 25
+R
+t 8 12 25
+R
+t 8 13 25
+R
+t 8 14 25
+R
+t 8 15 25
+R
+t 8 16 25
+R
+t 8 17 25
+R
+t 8 18 25
+R
+t 8 19 25
+R
+t 8 20 25
+R
+t 8 21 25
+R
+t 8 22 25
+R
+t 8 23 25
+R
+t 8 30 25
+R
+t 8 31 25
+R
+t 8 32 25
+R
+t 8 33 25
+R
+t 8 34 25
+R
+t 8 35 25
+R
+t 8 36 25
+R
+t 8 37 25
+R
+t 8 38 25
+R
+t 8 39 25
+R
+t 8 40 25
+R
+t 8 41 25
+R
+t 8 42 25
+R
+t 8 43 25
 R
 R

+ 36 - 36
AI/GeniusAI/AIPriorities.cpp

@@ -28,6 +28,7 @@ Network::Network(istream & input)
 
 
 float Network::feedForward(const vector<float> & stateFeatures)
 float Network::feedForward(const vector<float> & stateFeatures)
 {
 {
+	return (rand()%1000)/800.0;
 	double * input = new double[whichFeatures.size()];
 	double * input = new double[whichFeatures.size()];
 	for(int i = 0; i < whichFeatures.size();i++)
 	for(int i = 0; i < whichFeatures.size();i++)
 		input[i]=stateFeatures[whichFeatures[i]];
 		input[i]=stateFeatures[whichFeatures[i]];
@@ -38,37 +39,6 @@ float Network::feedForward(const vector<float> & stateFeatures)
 	return ans;
 	return ans;
 }
 }
 
 
-
-Priorities::Priorities()//random brain
-:numSpecialFeatures(8)
-{
-/*	vector<unsigned int> whichFeatures;//(512);
-	whichFeatures.push_back(16);
-	whichFeatures.push_back(17);
-	objectNetworks.push_back(Network(whichFeatures));	//for a friendly hero
-	objectNetworks.push_back(Network(whichFeatures));	//for an enemy hero
-
-	whichFeatures.clear();
-	whichFeatures.push_back(16);				//hero's AI value
-	objectNetworks.push_back(Network(whichFeatures));	//for school of magic
-
-	whichFeatures.clear();
-	for(int i = 0; i <=16;i++)
-		whichFeatures.push_back(i);				//hero's AI value is 16
-
-	objectNetworks.push_back(Network(whichFeatures));	//for treasure chest
-
-	whichFeatures.clear();
-	whichFeatures.push_back(17);
-	objectNetworks.push_back(Network(whichFeatures));	//for a friendly town
-	objectNetworks.push_back(Network(whichFeatures));	//for an enemy town
-
-	whichFeatures.clear();
-	whichFeatures.push_back(16);
-	objectNetworks.push_back(Network(whichFeatures));	//for learning stone
-*/
-}
-
 Priorities::Priorities(const string & filename)	//read brain from file
 Priorities::Priorities(const string & filename)	//read brain from file
 :numSpecialFeatures(8)
 :numSpecialFeatures(8)
 {
 {
@@ -77,10 +47,26 @@ Priorities::Priorities(const string & filename)	//read brain from file
 	// object_num [list of features]
 	// object_num [list of features]
 	// brain data or "R" for random brain
 	// brain data or "R" for random brain
 	objectNetworks.resize(255);
 	objectNetworks.resize(255);
+	buildingNetworks.resize(9);
+
+	char type;
 	int object_num;
 	int object_num;
-	while(infile>>object_num)
+	int town_num;
+	int building_num;
+	while(infile>>type)
 	{
 	{
-		objectNetworks[object_num].push_back(Network(infile));
+		switch(type)
+		{
+		case 'o'://map object
+			infile >> object_num;
+			objectNetworks[object_num].push_back(Network(infile));
+			break;
+		case 't'://town building
+			infile >> town_num >> building_num;
+			buildingNetworks[town_num][building_num]=Network(infile);
+
+			break;
+		}
 	}
 	}
 }
 }
 
 
@@ -116,13 +102,15 @@ float Priorities::getCost(vector<int> &resourceCosts,const CGHeroInstance * move
 
 
 float Priorities::getValue(const CGeniusAI::AIObjective & obj)
 float Priorities::getValue(const CGeniusAI::AIObjective & obj)
 {	//resource
 {	//resource
-
+	
 	vector<int> resourceAmounts(8,0);
 	vector<int> resourceAmounts(8,0);
 	int amount;
 	int amount;
 
 
 	if(obj.type==CGeniusAI::AIObjective::finishTurn)	//TODO: replace with value of visiting that object divided by days till completed
 	if(obj.type==CGeniusAI::AIObjective::finishTurn)	//TODO: replace with value of visiting that object divided by days till completed
 		return .0001;			//small nonzero
 		return .0001;			//small nonzero
 	float a;
 	float a;
+	if(obj.type==CGeniusAI::AIObjective::attack)
+		return 100;
 	if(dynamic_cast<const CGeniusAI::HeroObjective* >(&obj))
 	if(dynamic_cast<const CGeniusAI::HeroObjective* >(&obj))
 	{
 	{
 		const CGeniusAI::HeroObjective* hobj = dynamic_cast<const CGeniusAI::HeroObjective* >(&obj);
 		const CGeniusAI::HeroObjective* hobj = dynamic_cast<const CGeniusAI::HeroObjective* >(&obj);
@@ -133,7 +121,7 @@ float Priorities::getValue(const CGeniusAI::AIObjective & obj)
 		{
 		{
 		case 5: //artifact //TODO: return value of each artifact
 		case 5: //artifact //TODO: return value of each artifact
 			return 0;
 			return 0;
-		case 79:
+		case 79://resources on the ground
 			switch(hobj->object->subID)
 			switch(hobj->object->subID)
 			{
 			{
 			case 6:
 			case 6:
@@ -235,7 +223,19 @@ float Priorities::getValue(const CGeniusAI::AIObjective & obj)
 	}
 	}
 	else	//town objective
 	else	//town objective
 	{
 	{
-		
+		if(obj.type == CGeniusAI::AIObjective::buildBuilding)
+		{
+			const CGeniusAI::TownObjective* tnObj = dynamic_cast<const CGeniusAI::TownObjective* >(&obj);
+			if(buildingNetworks[tnObj->whichTown->t->subID].find(tnObj->which)!=buildingNetworks[tnObj->whichTown->t->subID].end())
+				return buildingNetworks[tnObj->whichTown->t->subID][tnObj->which].feedForward(stateFeatures);
+			else
+			{
+				cout << "don't know the value of ";
+				obj.print();
+				cout << endl;
+			}
+
+		}
 	}
 	}
 
 
 
 

+ 1 - 1
AI/GeniusAI/AIPriorities.h

@@ -22,7 +22,6 @@ public:
 class Priorities
 class Priorities
 {
 {
 public:
 public:
-	Priorities();								//random brain
 	Priorities(const string & filename);	//read brain from file
 	Priorities(const string & filename);	//read brain from file
 
 
 
 
@@ -33,6 +32,7 @@ public:
 	float getValue(const CGeniusAI::AIObjective & obj);
 	float getValue(const CGeniusAI::AIObjective & obj);
 	float getCost(vector<int> &resourceCosts,const CGHeroInstance * moved,int distOutOfTheWay);
 	float getCost(vector<int> &resourceCosts,const CGHeroInstance * moved,int distOutOfTheWay);
 	vector<vector<Network> > objectNetworks;
 	vector<vector<Network> > objectNetworks;
+	vector<map<int,Network> > buildingNetworks;
 };
 };
 
 
 }
 }

+ 50 - 60
AI/GeniusAI/CGeniusAI.cpp

@@ -73,7 +73,7 @@ CGeniusAI::HypotheticalGameState::HypotheticalGameState(CGeniusAI & ai)
 void CGeniusAI::HypotheticalGameState::update(CGeniusAI & ai)
 void CGeniusAI::HypotheticalGameState::update(CGeniusAI & ai)
 {
 {
 	AI = &ai;
 	AI = &ai;
-//	knownVisitableObjects = ai.knownVisitableObjects;
+	knownVisitableObjects = ai.knownVisitableObjects;
 
 
 	std::vector<HeroModel> oldModels = heroModels;
 	std::vector<HeroModel> oldModels = heroModels;
 	heroModels.clear();
 	heroModels.clear();
@@ -122,22 +122,23 @@ float CGeniusAI::HeroObjective::getValue() const
 		resourceCosts[6]+=1000;
 		resourceCosts[6]+=1000;
 
 
 	float bestCost = 9e9;
 	float bestCost = 9e9;
+	HypotheticalGameState::HeroModel * bestHero = NULL;
 	if(type !=AIObjective::finishTurn)
 	if(type !=AIObjective::finishTurn)
 	{
 	{
 		for(int i = 0; i < whoCanAchieve.size();i++)
 		for(int i = 0; i < whoCanAchieve.size();i++)
 		{
 		{
 			int distOutOfTheWay = 0;
 			int distOutOfTheWay = 0;
-			CPath path;
+			CPath path3;
 			//from hero to object
 			//from hero to object
-			if(AI->m_cb->getPath(whoCanAchieve[i]->pos,pos,whoCanAchieve[i]->h,path))
-				distOutOfTheWay+=path.nodes[0].dist;
+			if(AI->m_cb->getPath(whoCanAchieve[i]->pos,pos,whoCanAchieve[i]->h,path3))
+				distOutOfTheWay+=path3.nodes[0].dist;
 			//from object to goal
 			//from object to goal
-			if(AI->m_cb->getPath(pos,whoCanAchieve[i]->interestingPos,whoCanAchieve[i]->h,path))
+			if(AI->m_cb->getPath(pos,whoCanAchieve[i]->interestingPos,whoCanAchieve[i]->h,path3))
 			{
 			{
-				distOutOfTheWay+=path.nodes[0].dist;
+				distOutOfTheWay+=path3.nodes[0].dist;
 				//from hero directly to goal
 				//from hero directly to goal
-				if(AI->m_cb->getPath(whoCanAchieve[i]->pos,whoCanAchieve[i]->interestingPos,whoCanAchieve[i]->h,path))
-					distOutOfTheWay-=path.nodes[0].dist;
+				if(AI->m_cb->getPath(whoCanAchieve[i]->pos,whoCanAchieve[i]->interestingPos,whoCanAchieve[i]->h,path3))
+					distOutOfTheWay-=path3.nodes[0].dist;
 			}
 			}
 			
 			
 			
 			
@@ -145,12 +146,20 @@ float CGeniusAI::HeroObjective::getValue() const
 
 
 			float cost = AI->m_priorities->getCost(resourceCosts,whoCanAchieve[i]->h,distOutOfTheWay);
 			float cost = AI->m_priorities->getCost(resourceCosts,whoCanAchieve[i]->h,distOutOfTheWay);
 			if(cost < bestCost)
 			if(cost < bestCost)
+			{
 				bestCost = cost;
 				bestCost = cost;
+				bestHero = whoCanAchieve[i];
+			}
 
 
 		}
 		}
 	}
 	}
 	else bestCost = 0;
 	else bestCost = 0;
-	//if(bestCost < 10000) cout << "best cost = " << bestCost << endl;
+	if(bestHero)
+	{
+		whoCanAchieve.clear();
+		whoCanAchieve.push_back(bestHero);
+	}
+
 	_value = AI->m_priorities->getValue(*this);
 	_value = AI->m_priorities->getValue(*this);
 	_cost=bestCost;
 	_cost=bestCost;
 	return _value-_cost;
 	return _value-_cost;
@@ -178,6 +187,7 @@ void CGeniusAI::HeroObjective::print() const
 		break;
 		break;
 	case attack:
 	case attack:
 		cout << "attack " << object->hoverName;
 		cout << "attack " << object->hoverName;
+		break;
 	case finishTurn:
 	case finishTurn:
 		cout << "finish turn";
 		cout << "finish turn";
 	}
 	}
@@ -230,8 +240,9 @@ float CGeniusAI::TownObjective::getValue() const
 		ID = whichTown->creaturesInGarrison.slots[which].first;
 		ID = whichTown->creaturesInGarrison.slots[which].first;
 		howMany = whichTown->creaturesInGarrison.slots[which].second;
 		howMany = whichTown->creaturesInGarrison.slots[which].second;
 		newID = ui.newID.back();
 		newID = ui.newID.back();
-		for(std::set<std::pair<int,int> >::iterator i = ui.cost[which].begin();i!=ui.cost[which].end();i++)
-			resourceCosts[i->first] = i->second*howMany;
+		int upgrade_serial = ui.newID.size()-1;
+		for (std::set<std::pair<int,int> >::iterator j=ui.cost[upgrade_serial].begin(); j!=ui.cost[upgrade_serial].end(); j++)
+			resourceCosts[j->first] = j->second*howMany;
 	
 	
 		break;
 		break;
 
 
@@ -362,6 +373,7 @@ void CGeniusAI::addHeroObjectives(CGeniusAI::HypotheticalGameState::HeroModel &h
 	if(h.finished) return;
 	if(h.finished) return;
 	for(std::set<AIObjectContainer>::const_iterator i = hgs.knownVisitableObjects.begin(); i != hgs.knownVisitableObjects.end();i++)
 	for(std::set<AIObjectContainer>::const_iterator i = hgs.knownVisitableObjects.begin(); i != hgs.knownVisitableObjects.end();i++)
 	{
 	{
+		tp = AIObjective::visit;
 		if(	h.previouslyVisited_pos==i->o->getSightCenter())
 		if(	h.previouslyVisited_pos==i->o->getSightCenter())
 			continue;
 			continue;
 		//TODO: what would the hero actually visit if he went to that spot
 		//TODO: what would the hero actually visit if he went to that spot
@@ -376,9 +388,14 @@ void CGeniusAI::addHeroObjectives(CGeniusAI::HypotheticalGameState::HeroModel &h
 			if(heroThere)			//it won't work if there is already someone visiting that spot.
 			if(heroThere)			//it won't work if there is already someone visiting that spot.
 				continue;
 				continue;
 		}
 		}
+		if(i->o->ID==HEROI_TYPE&&i->o->getOwner()==m_cb->getMyColor())//visiting friendly heroes not yet supported
+			continue;
 		if(i->o->id==h.h->id)	//don't visit yourself (should be caught by above)
 		if(i->o->id==h.h->id)	//don't visit yourself (should be caught by above)
 			continue;
 			continue;
 		
 		
+		if(i->o->ID==53&&i->o->getOwner()==m_cb->getMyColor())//don't visit a mine if you own, there's almost no point(maybe to leave guards or because the hero's trapped).
+			continue;
+
 		if(i->o->getOwner()!=m_cb->getMyColor())	
 		if(i->o->getOwner()!=m_cb->getMyColor())	
 		{
 		{
 			int enemyStrength = 0;							//TODO: I feel like the AI shouldn't have access to this information.
 			int enemyStrength = 0;							//TODO: I feel like the AI shouldn't have access to this information.
@@ -386,17 +403,16 @@ void CGeniusAI::addHeroObjectives(CGeniusAI::HypotheticalGameState::HeroModel &h
 			if(dynamic_cast<const CArmedInstance *> (i->o))
 			if(dynamic_cast<const CArmedInstance *> (i->o))
 				enemyStrength = (dynamic_cast<const CArmedInstance *> (i->o))->getArmyStrength();//TODO: should be virtual maybe, Army strength should be comparable across objects
 				enemyStrength = (dynamic_cast<const CArmedInstance *> (i->o))->getArmyStrength();//TODO: should be virtual maybe, Army strength should be comparable across objects
 			if(dynamic_cast<const CGHeroInstance *> (i->o))
 			if(dynamic_cast<const CGHeroInstance *> (i->o))
-				enemyStrength = (dynamic_cast<const CGHeroInstance *> (i->o))->getHeroStrength();
+				enemyStrength = (dynamic_cast<const CGHeroInstance *> (i->o))->getTotalStrength();
 			if(dynamic_cast<const CGTownInstance *> (i->o))
 			if(dynamic_cast<const CGTownInstance *> (i->o))
 				enemyStrength = (dynamic_cast<const CGTownInstance *> (i->o))->getArmyStrength()*1.2;
 				enemyStrength = (dynamic_cast<const CGTownInstance *> (i->o))->getArmyStrength()*1.2;
-			
-			if(enemyStrength*1.2 > h.h->getHeroStrength())  //TODO: ballence these numbers using objective cost formula.
+			float heroStrength = h.h->getTotalStrength();
+			if(enemyStrength*2.5 > heroStrength)  //TODO: ballence these numbers using objective cost formula.
 				continue;									//      it would be nice to do a battle sim
 				continue;									//      it would be nice to do a battle sim
-			if(enemyStrength!=0)tp  = AIObjective::attack;
+			if(enemyStrength>0)tp  = AIObjective::attack;
 		}
 		}
 
 
-		if(i->o->ID==53&&i->o->getOwner()==m_cb->getMyColor())//don't visit a mine if you own, there's almost no point(maybe to leave guards or because the hero's trapped).
-			continue;
+		
 		if(dynamic_cast<const CGVisitableOPW *> (i->o)&&dynamic_cast<const CGVisitableOPW *> (i->o)->visited)//don't visit things that have already been visited this week.
 		if(dynamic_cast<const CGVisitableOPW *> (i->o)&&dynamic_cast<const CGVisitableOPW *> (i->o)->visited)//don't visit things that have already been visited this week.
 			continue;
 			continue;
 		if(dynamic_cast<const CGVisitableOPH *> (i->o)&&vstd::contains(dynamic_cast<const CGVisitableOPH *> (i->o)->visitors,h.h->id))//don't visit things that you have already visited OPH
 		if(dynamic_cast<const CGVisitableOPH *> (i->o)&&vstd::contains(dynamic_cast<const CGVisitableOPH *> (i->o)->visitors,h.h->id))//don't visit things that you have already visited OPH
@@ -414,7 +430,7 @@ void CGeniusAI::addHeroObjectives(CGeniusAI::HypotheticalGameState::HeroModel &h
 		destination = i->o->getSightCenter();
 		destination = i->o->getSightCenter();
 
 
 		if(hpos.z==destination.z)							//don't try to take a path from the underworld to the top or vice versa
 		if(hpos.z==destination.z)							//don't try to take a path from the underworld to the top or vice versa
-		{
+		{	//TODO: fix get path so that it doesn't return a path unless z's are the same, or path goes through sub gate
 			if(m_cb->getPath(hpos,destination,h.h,path))
 			if(m_cb->getPath(hpos,destination,h.h,path))
 			{
 			{
 				path.convert(0);
 				path.convert(0);
@@ -445,7 +461,7 @@ void CGeniusAI::addHeroObjectives(CGeniusAI::HypotheticalGameState::HeroModel &h
 	}
 	}
 	
 	
 	h.interestingPos = interestingPos;
 	h.interestingPos = interestingPos;
-	if(h.remainingMovement>0&&m_cb->getPath(hpos,interestingPos,h.h,path)) // there ought to be a path   
+//	if(h.remainingMovement>0&&m_cb->getPath(hpos,interestingPos,h.h,path)) // there ought to be a path   
 		currentHeroObjectives.insert(HeroObjective(hgs,HeroObjective::finishTurn,h.h,&h,this));
 		currentHeroObjectives.insert(HeroObjective(hgs,HeroObjective::finishTurn,h.h,&h,this));
 		
 		
 
 
@@ -469,7 +485,7 @@ void CGeniusAI::HeroObjective::fulfill(CGeniusAI & cg,HypotheticalGameState & hg
 		hpos = h->pos;
 		hpos = h->pos;
 		destination = h->interestingPos;
 		destination = h->interestingPos;
 		if(!cg.m_cb->getPath(hpos,destination,h->h,path)) {cout << "AI error: invalid destination" << endl; return;}
 		if(!cg.m_cb->getPath(hpos,destination,h->h,path)) {cout << "AI error: invalid destination" << endl; return;}
-//		path.convert(0);
+
 		destination = h->pos;
 		destination = h->pos;
 		for(int i = path.nodes.size()-2;i>=0;i--)		//find closest coord that we can get to
 		for(int i = path.nodes.size()-2;i>=0;i--)		//find closest coord that we can get to
 			if(cg.m_cb->getPath(hpos,path.nodes[i].coord,h->h,path2)&&path2.nodes[0].dist<=h->remainingMovement)
 			if(cg.m_cb->getPath(hpos,path.nodes[i].coord,h->h,path2)&&path2.nodes[0].dist<=h->remainingMovement)
@@ -506,43 +522,13 @@ void CGeniusAI::HeroObjective::fulfill(CGeniusAI & cg,HypotheticalGameState & hg
 			
 			
 		destination = bestPos;
 		destination = bestPos;
 		//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 		//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
+		cg.m_cb->getPath(hpos,destination,h->h,path);
+		path.convert(0);
 		break;
 		break;
 	case visit:case attack:
 	case visit:case attack:
-		float bestCost = 9e9;
-		int bestHero = 0;
-		vector<int> resourceCosts;
-		for(int i = 0; i < 8;i++)
-			resourceCosts.push_back(0);
-		for(int i = 0; i < whoCanAchieve.size();i++)
-		{
-			int distOutOfTheWay = 0;
-			CPath path;
-			//from hero to object
-			if(AI->m_cb->getPath(whoCanAchieve[i]->pos,pos,whoCanAchieve[i]->h,path)) distOutOfTheWay+=path.nodes[0].dist;
-			//from object to goal
-			if(AI->m_cb->getPath(pos,whoCanAchieve[i]->interestingPos,whoCanAchieve[i]->h,path))
-			{
-				distOutOfTheWay+=path.nodes[0].dist;
-				//from hero directly to goal
-				if(AI->m_cb->getPath(whoCanAchieve[i]->pos,whoCanAchieve[i]->interestingPos,whoCanAchieve[i]->h,path)) distOutOfTheWay-=path.nodes[0].dist;
-			}
-			
 
 
-
-			float cost = AI->m_priorities->getCost(resourceCosts,whoCanAchieve[i]->h,distOutOfTheWay);
-			if(cost < bestCost)
-			{
-				bestCost = cost;
-				bestHero = i;
-			}
-
-		}
-
-		h = whoCanAchieve[bestHero];		//lowest cost hero
+		h = whoCanAchieve.front();		//lowest cost hero
 		h->previouslyVisited_pos=object->getSightCenter();
 		h->previouslyVisited_pos=object->getSightCenter();
-		//if(dynamic_cast<const CGVisitableOPH *> (object))
-		//	std::cout << h->h->name << " is visiting " << object->hoverName << std::endl;
 		hpos = h->pos;
 		hpos = h->pos;
 		destination = object->getSightCenter();
 		destination = object->getSightCenter();
 
 
@@ -669,7 +655,6 @@ void CGeniusAI::addTownObjectives(HypotheticalGameState::TownModel &t, Hypotheti
 			{
 			{
 				TownObjective to(hgs,AIObjective::buildBuilding,&t,i->first,this);
 				TownObjective to(hgs,AIObjective::buildBuilding,&t,i->first,this);
 				currentTownObjectives.insert(to);
 				currentTownObjectives.insert(to);
-				//cout <<"can build " << i->first << " "<< i->second->Name() << endl;
 			}
 			}
 		}
 		}
 	}
 	}
@@ -693,8 +678,8 @@ void CGeniusAI::addTownObjectives(HypotheticalGameState::TownModel &t, Hypotheti
 		currentTownObjectives.insert(to);
 		currentTownObjectives.insert(to);
 
 
 	}
 	}
-	//upgradeCreatures
 
 
+	//upgradeCreatures
 
 
 	for(std::map<si32,std::pair<ui32,si32> >::iterator i = t.creaturesInGarrison.slots.begin();i!=t.creaturesInGarrison.slots.end();i++)
 	for(std::map<si32,std::pair<ui32,si32> >::iterator i = t.creaturesInGarrison.slots.begin();i!=t.creaturesInGarrison.slots.end();i++)
 	{
 	{
@@ -702,10 +687,11 @@ void CGeniusAI::addTownObjectives(HypotheticalGameState::TownModel &t, Hypotheti
 		if(ui.newID.size()!=0)
 		if(ui.newID.size()!=0)
 		{
 		{
 			bool canAfford = true;
 			bool canAfford = true;
-			for(int ii=0;ii<ui.cost.size();ii++)
-				for (std::set<std::pair<int,int> >::iterator j=ui.cost[ii].begin(); j!=ui.cost[ii].end(); j++)
-					if(hgs.resourceAmounts[j->first] < j->second*i->second.second)
-						canAfford = false;
+			
+			int upgrade_serial = ui.newID.size()-1;
+			for (std::set<std::pair<int,int> >::iterator j=ui.cost[upgrade_serial].begin(); j!=ui.cost[upgrade_serial].end(); j++)
+				if(hgs.resourceAmounts[j->first] < j->second*i->second.second)
+					canAfford = false;
 			if(canAfford)
 			if(canAfford)
 			{
 			{
 				TownObjective to(hgs,AIObjective::upgradeCreatures,&t,i->first,this);
 				TownObjective to(hgs,AIObjective::upgradeCreatures,&t,i->first,this);
@@ -1034,13 +1020,17 @@ void CGeniusAI::battleStart(CCreatureSet *army1, CCreatureSet *army2, int3 tile,
  */
  */
 void CGeniusAI::battleEnd(BattleResult *br)
 void CGeniusAI::battleEnd(BattleResult *br)
 {
 {
+
 	switch(br->winner)
 	switch(br->winner)
 	{
 	{
 		case 0:	std::cout << "The winner is the attacker." << std::endl;break;
 		case 0:	std::cout << "The winner is the attacker." << std::endl;break;
 		case 1:	std::cout << "The winner is the defender." << std::endl;break;
 		case 1:	std::cout << "The winner is the defender." << std::endl;break;
 		case 2:	std::cout << "It's a draw." << std::endl;break;
 		case 2:	std::cout << "It's a draw." << std::endl;break;
 	};
 	};
-	
+	cout << "lost ";
+	for(std::set<std::pair<ui32,si32> >::iterator i = br->casualties[0].begin(); i !=br->casualties[0].end();i++)
+		cout << i->second << " " << VLC->creh->creatures[i->first].namePl << endl;
+				
 	delete m_battleLogic;
 	delete m_battleLogic;
 	m_battleLogic = NULL;
 	m_battleLogic = NULL;
 
 

+ 3 - 3
AI/GeniusAI/CGeniusAI.h

@@ -110,10 +110,10 @@ private:
 		HypotheticalGameState hgs;
 		HypotheticalGameState hgs;
 		int3 pos;
 		int3 pos;
 		const CGObjectInstance * object;
 		const CGObjectInstance * object;
-		std::vector<HypotheticalGameState::HeroModel *> whoCanAchieve;
+		mutable std::vector<HypotheticalGameState::HeroModel *> whoCanAchieve;
 		
 		
-		HeroObjective(){}
-		HeroObjective(Type t):object(NULL){type = t;}
+		//HeroObjective(){}
+		//HeroObjective(Type t):object(NULL){type = t;}
 		HeroObjective(const HypotheticalGameState &hgs,Type t,const CGObjectInstance * object,HypotheticalGameState::HeroModel *h,CGeniusAI * AI);
 		HeroObjective(const HypotheticalGameState &hgs,Type t,const CGObjectInstance * object,HypotheticalGameState::HeroModel *h,CGeniusAI * AI);
 		bool operator < (const HeroObjective &other)const;
 		bool operator < (const HeroObjective &other)const;
 		void fulfill(CGeniusAI &,HypotheticalGameState & hgs);
 		void fulfill(CGeniusAI &,HypotheticalGameState & hgs);