1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-01-26 03:52:01 +02:00

First part of reformatting the code, renaming variables, rewriting tricky part. Basically making the code more readable, maintainable and ready for further additions.

This commit is contained in:
red1939 2009-10-22 22:04:42 +00:00
parent 142ec8e11a
commit ed9b75b447
11 changed files with 390 additions and 241 deletions

View File

@ -3,7 +3,7 @@
#define AI_PRIORITIES #define AI_PRIORITIES
#include "AIPriorities.h" #include "AIPriorities.h"
#include <sstream> #include <sstream>
using namespace GeniusAI; using namespace geniusai;
Network::Network() Network::Network()
{} {}
Network::Network(vector<unsigned int> whichFeatures)// random network Network::Network(vector<unsigned int> whichFeatures)// random network

View File

@ -5,7 +5,7 @@
#include "CGeniusAI.h" #include "CGeniusAI.h"
#include "neuralNetwork.h" #include "neuralNetwork.h"
namespace GeniusAI { namespace geniusai {
class Network class Network
{ {

View File

@ -7,7 +7,7 @@
#include <boost/algorithm/string.hpp> #include <boost/algorithm/string.hpp>
#include <boost/lexical_cast.hpp> #include <boost/lexical_cast.hpp>
using namespace GeniusAI::BattleAI; using namespace geniusai::BattleAI;
using namespace std; using namespace std;

View File

@ -3,7 +3,7 @@
#include "Common.h" #include "Common.h"
namespace GeniusAI { namespace BattleAI { namespace geniusai { namespace BattleAI {
class CBattleHelper class CBattleHelper
{ {

View File

@ -12,7 +12,7 @@ HANDLE handleIn;
HANDLE handleOut; HANDLE handleOut;
#endif #endif
using namespace GeniusAI::BattleAI; using namespace geniusai::BattleAI;
using namespace boost::lambda; using namespace boost::lambda;
using namespace std; using namespace std;

View File

@ -15,7 +15,7 @@
using namespace std; using namespace std;
namespace GeniusAI { namespace BattleAI { namespace geniusai { namespace BattleAI {
/** /**
* Class is responsible for making decision during the battle. * Class is responsible for making decision during the battle.

View File

@ -1,14 +1,17 @@
#include "CGeniusAI.h" #include "CGeniusAI.h"
#include "AIPriorities.h"
#include <iostream> #include <iostream>
#include <boost/lexical_cast.hpp>
#include "../../hch/CBuildingHandler.h" #include "../../hch/CBuildingHandler.h"
#include "../../hch/CHeroHandler.h" #include "../../hch/CHeroHandler.h"
#include "../../lib/VCMI_Lib.h" #include "../../lib/VCMI_Lib.h"
#include "../../lib/NetPacks.h" #include "../../lib/NetPacks.h"
#include <boost/lexical_cast.hpp> #include "AIPriorities.h"
using namespace std; using std::cout;
using namespace GeniusAI; using std::endl;
using geniusai::CGeniusAI;
#if defined (_MSC_VER) && (_MSC_VER >= 1020) || (__MINGW32__) #if defined (_MSC_VER) && (_MSC_VER >= 1020) || (__MINGW32__)
#define WIN32_LEAN_AND_MEAN //excludes rarely used stuff from windows headers - delete this line if something is missing #define WIN32_LEAN_AND_MEAN //excludes rarely used stuff from windows headers - delete this line if something is missing
@ -32,77 +35,114 @@ void DbgBox(const char *msg, bool messageBox)
} }
bool CGeniusAI::AIObjectContainer::operator<(const AIObjectContainer& b)const bool CGeniusAI::AIObjectContainer::operator<(
const AIObjectContainer& b) const
{ {
if (o->pos!=b.o->pos) if (o->pos != b.o->pos)
return o->pos<b.o->pos; return o->pos < b.o->pos;
return o->id<b.o->id; else
return o->id < b.o->id;
} }
CGeniusAI::HypotheticalGameState::HeroModel::HeroModel(const CGHeroInstance * h)
:h(h),finished(false) CGeniusAI::HypotheticalGameState::HeroModel::HeroModel(
const CGHeroInstance* h)
: h(h), finished(false)
{ {
pos = h->getPosition(false);remainingMovement = h->movement; pos = h->getPosition(false);
remainingMovement = h->movement;
} }
CGeniusAI::HypotheticalGameState::TownModel::TownModel(const CGTownInstance *t):t(t)
CGeniusAI::HypotheticalGameState::TownModel::TownModel(
const CGTownInstance *t)
: t(t)
{ {
hasBuilt = t->builded; hasBuilt = t->builded;
creaturesToRecruit = t->creatures; creaturesToRecruit = t->creatures;
creaturesInGarrison = t->army; creaturesInGarrison = t->army;
} }
CGeniusAI::HypotheticalGameState::HypotheticalGameState(CGeniusAI & ai)
:knownVisitableObjects(ai.knownVisitableObjects) CGeniusAI::HypotheticalGameState::HypotheticalGameState(
CGeniusAI& ai)
: knownVisitableObjects(ai.knownVisitableObjects)
{ {
AI = &ai; AI = &ai;
std::vector < const CGHeroInstance *> heroes = ai.m_cb->getHeroesInfo(); std::vector<const CGHeroInstance*> heroes = ai.m_cb->getHeroesInfo();
for(std::vector < const CGHeroInstance *>::iterator i = heroes.begin(); i != heroes.end(); i++) for (std::vector<const CGHeroInstance *>::iterator i = heroes.begin();
i != heroes.end();
i++)
heroModels.push_back(HeroModel(*i)); heroModels.push_back(HeroModel(*i));
std::vector < const CGTownInstance *> towns = ai.m_cb->getTownsInfo(); std::vector<const CGTownInstance*> towns = ai.m_cb->getTownsInfo();
for(std::vector < const CGTownInstance *>::iterator i = towns.begin(); i != towns.end(); i++) for (std::vector < const CGTownInstance *>::iterator i = towns.begin();
if((*i)->tempOwner==ai.m_cb->getMyColor()) i != towns.end();
townModels.push_back(TownModel(*i)); i++) {
if ( (*i)->tempOwner == ai.m_cb->getMyColor() )
townModels.push_back(TownModel(*i));
}
if(ai.m_cb->howManyTowns()!=0) if (ai.m_cb->howManyTowns() != 0) {
AvailableHeroesToBuy = ai.m_cb->getAvailableHeroes(ai.m_cb->getTownInfo(0,0)); AvailableHeroesToBuy =
ai.m_cb->getAvailableHeroes(ai.m_cb->getTownInfo(0,0));
}
for(int i = 0; i < 8;i++)resourceAmounts.push_back(ai.m_cb->getResourceAmount(i)); for (int i = 0; i < 8; i++)
resourceAmounts.push_back(ai.m_cb->getResourceAmount(i));
} }
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();
std::vector < const CGHeroInstance *> heroes = ai.m_cb->getHeroesInfo();
for(std::vector < const CGHeroInstance *>::iterator i = heroes.begin(); i != heroes.end(); i++) 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)); heroModels.push_back(HeroModel(*i));
for(int i = 0; i < oldModels.size();i++)
for(int ii = 0; ii < heroModels.size();ii++) for (int i = 0; i < oldModels.size(); i++) {
if(oldModels[i].h->subID==heroModels[ii].h->subID) for (int j = 0; j < heroModels.size(); j++) {
{ if (oldModels[i].h->subID == heroModels[j].h->subID) {
heroModels[ii].finished = oldModels[i].finished; heroModels[j].finished = oldModels[i].finished;
heroModels[ii].previouslyVisited_pos=oldModels[i].previouslyVisited_pos; heroModels[j].previouslyVisited_pos = oldModels[i].previouslyVisited_pos;
} }
}
}
townModels.clear(); townModels.clear();
std::vector < const CGTownInstance *> towns = ai.m_cb->getTownsInfo(); std::vector<const CGTownInstance*> towns = ai.m_cb->getTownsInfo();
for(std::vector < const CGTownInstance *>::iterator i = towns.begin(); i != towns.end(); i++) for (std::vector<const CGTownInstance*>::iterator i = towns.begin();
if((*i)->tempOwner==ai.m_cb->getMyColor()) i != towns.end();
i++) {
if ( (*i)->tempOwner == ai.m_cb->getMyColor() )
townModels.push_back(TownModel(*i)); townModels.push_back(TownModel(*i));
}
if(ai.m_cb->howManyTowns()!=0) if (ai.m_cb->howManyTowns() != 0) {
AvailableHeroesToBuy = ai.m_cb->getAvailableHeroes(ai.m_cb->getTownInfo(0,0)); AvailableHeroesToBuy =
ai.m_cb->getAvailableHeroes(ai.m_cb->getTownInfo(0,0));
}
resourceAmounts.clear(); resourceAmounts.clear();
for(int i = 0; i < 8;i++)resourceAmounts.push_back(ai.m_cb->getResourceAmount(i)); for (int i = 0; i < 8; i++)
resourceAmounts.push_back(ai.m_cb->getResourceAmount(i));
} }
CGeniusAI::HeroObjective::HeroObjective(const HypotheticalGameState &hgs,Type t,const CGObjectInstance * object,HypotheticalGameState::HeroModel *h,CGeniusAI * ai):object(object),hgs(hgs)
CGeniusAI::HeroObjective::HeroObjective(
const HypotheticalGameState &hgs,
Type t,
const CGObjectInstance* object,
HypotheticalGameState::HeroModel* h,
CGeniusAI* ai)
: object(object), hgs(hgs)
{ {
AI = ai; AI = ai;
pos = object->pos; pos = object->pos;
@ -111,228 +151,301 @@ CGeniusAI::HeroObjective::HeroObjective(const HypotheticalGameState &hgs,Type t,
_value = -1; _value = -1;
} }
float CGeniusAI::HeroObjective::getValue() const float CGeniusAI::HeroObjective::getValue() const
{ {
if(_value>=0) if (_value >= 0)
return _value-_cost; return _value - _cost;
vector<int> resourceCosts; //TODO: each object should have an associated cost to visit IE (tree of knowledge 1000 gold/10 gems) // TODO: each object should have an associated cost to visit IE
for(int i = 0; i < 8;i++) // (tree of knowledge 1000 gold/10 gems)
vector<int> resourceCosts;
for (int i = 0; i < 8; i++)
resourceCosts.push_back(0); resourceCosts.push_back(0);
if(object->ID==47) //school of magic
resourceCosts[6]+=1000; if (object->ID == 47) // School of magic
resourceCosts[6] += 1000;
float bestCost = 9e9; float bestCost = 9e9;
HypotheticalGameState::HeroModel * bestHero = NULL; 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 path3; CPath path3;
//from hero to object //from hero to object
if(AI->m_cb->getPath(whoCanAchieve[i]->pos,pos,whoCanAchieve[i]->h,path3)) if (AI->m_cb->getPath(whoCanAchieve[i]->pos,
pos,
whoCanAchieve[i]->h,
path3)) {
distOutOfTheWay+=path3.nodes[0].dist; distOutOfTheWay+=path3.nodes[0].dist;
//from object to goal }
if(AI->m_cb->getPath(pos,whoCanAchieve[i]->interestingPos,whoCanAchieve[i]->h,path3))
{ // from object to goal
distOutOfTheWay+=path3.nodes[0].dist; if (AI->m_cb->getPath(pos,
//from hero directly to goal whoCanAchieve[i]->interestingPos,
if(AI->m_cb->getPath(whoCanAchieve[i]->pos,whoCanAchieve[i]->interestingPos,whoCanAchieve[i]->h,path3)) whoCanAchieve[i]->h,
path3)) {
distOutOfTheWay += path3.nodes[0].dist;
// from hero directly to goal
if (AI->m_cb->getPath(whoCanAchieve[i]->pos,
whoCanAchieve[i]->interestingPos,
whoCanAchieve[i]->h,
path3))
distOutOfTheWay-=path3.nodes[0].dist; distOutOfTheWay-=path3.nodes[0].dist;
} }
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]; bestHero = whoCanAchieve[i];
} }
} // for (int i = 0; i < whoCanAchieve.size(); i++)
} else // if (type != AIObjective::finishTurn)
bestCost = 0;
} if (bestHero) {
}
else bestCost = 0;
if(bestHero)
{
whoCanAchieve.clear(); whoCanAchieve.clear();
whoCanAchieve.push_back(bestHero); 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;
} }
bool CGeniusAI::HeroObjective::operator < (const HeroObjective &other)const
bool CGeniusAI::HeroObjective::operator<(
const HeroObjective& other) const
{ {
if(type != other.type) if (type != other.type)
return type<other.type; return type < other.type;
if(pos!=other.pos) else if (pos != other.pos)
return pos < other.pos; return pos < other.pos;
if(object->id!=other.object->id) else if (object->id != other.object->id)
return object->id < other.object->id; return object->id < other.object->id;
if(dynamic_cast<const CGVisitableOPH *> (object)) else if (dynamic_cast<const CGVisitableOPH*> (object)) {
if(whoCanAchieve.front()->h->id!=other.whoCanAchieve.front()->h->id) if (whoCanAchieve.front()->h->id != other.whoCanAchieve.front()->h->id)
return whoCanAchieve.front()->h->id<other.whoCanAchieve.front()->h->id; return whoCanAchieve.front()->h->id < other.whoCanAchieve.front()->h->id;
return false; } else
return false;
} }
void CGeniusAI::HeroObjective::print() const void CGeniusAI::HeroObjective::print() const
{ {
switch(type) switch (type) {
{
case visit: case visit:
cout << "visit " << object->hoverName << " at (" <<object->pos.x << ","<<object->pos.y << ")" ; cout << "visit " << object->hoverName
<< " at (" <<object->pos.x << ","<< object->pos.y << ")" ;
break; break;
case attack: case attack:
cout << "attack " << object->hoverName; cout << "attack " << object->hoverName;
break; break;
case finishTurn: case finishTurn:
cout << "finish turn"; cout << "finish turn";
// TODO: Add a default, just in case.
} }
if(whoCanAchieve.size()==1) if (whoCanAchieve.size() == 1)
cout << " with " << whoCanAchieve.front()->h->hoverName; cout << " with " << whoCanAchieve.front()->h->hoverName;
} }
CGeniusAI::TownObjective::TownObjective(const HypotheticalGameState &hgs,Type t,HypotheticalGameState::TownModel * tn,int Which,CGeniusAI * ai)
:whichTown(tn),which(Which),hgs(hgs) CGeniusAI::TownObjective::TownObjective(
const HypotheticalGameState& hgs,
Type t,
HypotheticalGameState::TownModel* tn,
int Which,
CGeniusAI * ai)
: whichTown(tn), which(Which), hgs(hgs)
{ {
AI=ai; AI = ai;
type = t; type = t;
_value = -1; _value = -1;
} }
float CGeniusAI::TownObjective::getValue() const float CGeniusAI::TownObjective::getValue() const
{ {
if(_value>=0) if (_value >= 0)
return _value-_cost; return _value - _cost;
float cost;
float cost; // TODO: Initialize it!
// TODO: Include a constant stating the meaning of 8 (number of resources).
vector<int> resourceCosts(8,0); vector<int> resourceCosts(8,0);
CBuilding * b; CBuilding* b;
CCreature * creature; CCreature* creature;
int ID,newID, howMany; int ID;
switch(type) int newID;
{ int howMany;
ui32 creatures_max = 0;
switch (type) {
case recruitHero: case recruitHero:
resourceCosts[6]=2500; resourceCosts[6] = 2500; // TODO: Define somehow the meaning of gold etc.
break; break;
case buildBuilding: case buildBuilding:
b = VLC->buildh->buildings[whichTown->t->subID][which]; b = VLC->buildh->buildings[whichTown->t->subID][which];
for(int i = 0; b && i < b->resources.size();i++) for (int i = 0;
resourceCosts[i]=b->resources[i]; b && ( i < b->resources.size() ); // TODO: b what??
i++)
resourceCosts[i] = b->resources[i];
break; break;
case recruitCreatures: case recruitCreatures:
ID = whichTown->creaturesToRecruit[which].second.back(); //buy upgraded if possible // Buy upgraded if possible.
creature = &VLC->creh->creatures[ID]; ID = whichTown->creaturesToRecruit[which].second.back();
howMany = whichTown->creaturesToRecruit[which].first; creature = &VLC->creh->creatures[ID];
for(int i = 0; i < creature->cost.size();i++) howMany = whichTown->creaturesToRecruit[which].first;
amin(howMany,creature->cost[i]?hgs.resourceAmounts[i]/creature->cost[i]:INT_MAX); creatures_max = 0; // Max creatures you can recruit of this type.
for(int i = 0; creature && i < creature->cost.size();i++)
resourceCosts[i]=creature->cost[i]*howMany; for (int i = 0; i < creature->cost.size(); i++) {
if (creature->cost[i] != 0)
creatures_max = hgs.resourceAmounts[i]/creature->cost[i];
else
creatures_max = INT_MAX; // TODO: Will have to rewrite it.
// TODO: Buy the best units (the least I can buy)?
amin(howMany, creatures_max);
}
// The cost of recruiting the stack of creatures.
for (int i = 0;
creature && ( i < creature->cost.size() ); // TODO: Creature what??
i++)
resourceCosts[i] = creature->cost[i]*howMany;
break;
break; case upgradeCreatures:
case upgradeCreatures: UpgradeInfo ui = AI->m_cb->getUpgradeInfo(whichTown->t,which);
UpgradeInfo ui = AI->m_cb->getUpgradeInfo(whichTown->t,which); 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();
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;
newID = ui.newID.back();
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;
} }
_cost = AI->m_priorities->getCost(resourceCosts, NULL, 0);
_cost = AI->m_priorities->getCost(resourceCosts,NULL,0);
_value = AI->m_priorities->getValue(*this); _value = AI->m_priorities->getValue(*this);
return _value-_cost; return _value - _cost;
} }
bool CGeniusAI::TownObjective::operator < (const TownObjective &other)const bool CGeniusAI::TownObjective::operator<(const TownObjective &other) const
{ {
if(type != other.type) if (type != other.type)
return type<other.type; return type < other.type;
if(which!=other.which) else if (which != other.which)
return which<other.which; return which < other.which;
if(whichTown->t->id!=other.whichTown->t->id) else if (whichTown->t->id != other.whichTown->t->id)
return whichTown->t->id < other.whichTown->t->id; return whichTown->t->id < other.whichTown->t->id;
return false; return false;
} }
void CGeniusAI::TownObjective::print() const void CGeniusAI::TownObjective::print() const
{ {
CBuilding * b; CBuilding* b;
const CCreature *creature; const CCreature* creature;
HypotheticalGameState::HeroModel hm; HypotheticalGameState::HeroModel hm;
int ID, howMany, newID, hSlot; int ID;
switch(type) int howMany;
{ int newID;
int hSlot;
ui32 creatures_max;
switch (type) {
case recruitHero: case recruitHero:
cout << "recruit hero.";break; cout << "recruit hero.";
break;
case buildBuilding: case buildBuilding:
b = VLC->buildh->buildings[whichTown->t->subID][which]; b = VLC->buildh->buildings[whichTown->t->subID][which];
cout << "build " << b->Name() << " cost = "; cout << "build " << b->Name() << " cost = ";
if(b->resources.size()!=0) if (b->resources.size() != 0)
{ {
if(b->resources[0]!=0)cout << b->resources[0] << " wood. "; if (b->resources[0] != 0)
if(b->resources[1]!=0)cout << b->resources[1] << " mercury. "; cout << b->resources[0] << " wood. ";
if(b->resources[2]!=0)cout << b->resources[2] << " ore. "; if (b->resources[1] != 0)
if(b->resources[3]!=0)cout << b->resources[3] << " sulfur. "; cout << b->resources[1] << " mercury. ";
if(b->resources[4]!=0)cout << b->resources[4] << " cristal. "; if (b->resources[2] != 0)
if(b->resources[5]!=0)cout << b->resources[5] << " gems. "; cout << b->resources[2] << " ore. ";
if(b->resources[6]!=0)cout << b->resources[6] << " gold. "; if (b->resources[3] != 0)
cout << b->resources[3] << " sulfur. ";
if (b->resources[4] != 0)
cout << b->resources[4] << " cristal. ";
if (b->resources[5] != 0)
cout << b->resources[5] << " gems. ";
if (b->resources[6] != 0)
cout << b->resources[6] << " gold. ";
} }
break; break;
case recruitCreatures: case recruitCreatures:
ID = whichTown->creaturesToRecruit[which].second.back(); //buy upgraded if possible // Buy upgraded if possible.
ID = whichTown->creaturesToRecruit[which].second.back();
creature = &VLC->creh->creatures[ID]; creature = &VLC->creh->creatures[ID];
howMany = whichTown->creaturesToRecruit[which].first; howMany = whichTown->creaturesToRecruit[which].first;
for(int i = 0; i < creature->cost.size();i++) creatures_max = 0;
amin(howMany,creature->cost[i]?AI->m_cb->getResourceAmount(i)/creature->cost[i]:INT_MAX);
cout << "recruit " << howMany << " "<< creature->namePl << " (Total AI Strength " << creature->AIValue*howMany << "). cost = "; for (int i = 0; i < creature->cost.size(); i++) {
if (creature->cost[i] != 0)
creatures_max = hgs.resourceAmounts[i]/creature->cost[i];
else
creatures_max = INT_MAX;
amin(howMany, creatures_max);
}
cout << "recruit " << howMany << " " << creature->namePl
<< " (Total AI Strength " << creature->AIValue*howMany << "). cost = ";
if(creature->cost.size()!=0) if (creature->cost.size() != 0)
{ {
if(creature->cost[0]!=0)cout << creature->cost[0]*howMany << " wood. "; if (creature->cost[0] != 0)
if(creature->cost[1]!=0)cout << creature->cost[1]*howMany << " mercury. "; cout << creature->cost[0]*howMany << " wood. ";
if(creature->cost[2]!=0)cout << creature->cost[2]*howMany << " ore. "; if (creature->cost[1] != 0)
if(creature->cost[3]!=0)cout << creature->cost[3]*howMany << " sulfur. "; cout << creature->cost[1]*howMany << " mercury. ";
if(creature->cost[4]!=0)cout << creature->cost[4]*howMany << " cristal. "; if (creature->cost[2] != 0)
if(creature->cost[5]!=0)cout << creature->cost[5]*howMany << " gems. "; cout << creature->cost[2]*howMany << " ore. ";
if(creature->cost[6]!=0)cout << creature->cost[6]*howMany << " gold. "; if (creature->cost[3] != 0)
cout << creature->cost[3]*howMany << " sulfur. ";
if (creature->cost[4] != 0)
cout << creature->cost[4]*howMany << " cristal. ";
if (creature->cost[5] != 0)
cout << creature->cost[5]*howMany << " gems. ";
if (creature->cost[6] != 0)
cout << creature->cost[6]*howMany << " gold. ";
} }
break; break;
case upgradeCreatures: case upgradeCreatures:
UpgradeInfo ui = AI->m_cb->getUpgradeInfo(whichTown->t,which); UpgradeInfo ui = AI->m_cb->getUpgradeInfo(whichTown->t,which);
ID = whichTown->creaturesInGarrison.slots[which].first; ID = whichTown->creaturesInGarrison.slots[which].first;
cout << "upgrade " << VLC->creh->creatures[ID].namePl; cout << "upgrade " << VLC->creh->creatures[ID].namePl;
//ui.cost //ui.cost
break; break;
} // case buildBuilding
}
} }
CGeniusAI::CGeniusAI()
: m_generalAI(), m_state(NO_BATTLE) CGeniusAI::CGeniusAI() : m_generalAI(), m_state(NO_BATTLE)
{ {
m_priorities = new Priorities("AI/GeniusAI.brain"); m_priorities = new Priorities("AI/GeniusAI.brain");
} }
CGeniusAI::~CGeniusAI() CGeniusAI::~CGeniusAI()
{ {
delete m_priorities; delete m_priorities;
} }
void CGeniusAI::init(ICallback *CB) void CGeniusAI::init(ICallback *CB)
{ {
m_cb = CB; m_cb = CB;
@ -341,7 +454,8 @@ void CGeniusAI::init(ICallback *CB)
human = false; human = false;
playerID = m_cb->getMyColor(); playerID = m_cb->getMyColor();
serialID = m_cb->getMySerial(); serialID = m_cb->getMySerial();
std::string info = std::string("GeniusAI initialized for player ") + boost::lexical_cast<std::string>(playerID); std::string info = std::string("GeniusAI initialized for player ")
+ boost::lexical_cast<std::string>(playerID);
m_battleLogic = NULL; m_battleLogic = NULL;
DbgBox(info.c_str()); DbgBox(info.c_str());
} }
@ -350,8 +464,8 @@ void CGeniusAI::init(ICallback *CB)
void CGeniusAI::reportResources() void CGeniusAI::reportResources()
{ {
cout << "Day " << m_cb->getDate() << ": "; cout << "Day " << m_cb->getDate() << ": ";
cout << "AI Player " <<m_cb->getMySerial()<< " with " << m_cb->howManyHeroes(true) << " heroes. " << endl; cout << "AI Player " <<m_cb->getMySerial()<< " with "
<< m_cb->howManyHeroes(true) << " heroes. " << endl;
cout << m_cb->getResourceAmount(0) << " wood. "; cout << m_cb->getResourceAmount(0) << " wood. ";
cout << m_cb->getResourceAmount(1) << " mercury. "; cout << m_cb->getResourceAmount(1) << " mercury. ";
cout << m_cb->getResourceAmount(2) << " ore. "; cout << m_cb->getResourceAmount(2) << " ore. ";
@ -362,112 +476,146 @@ void CGeniusAI::reportResources()
cout << endl; cout << endl;
} }
void CGeniusAI::addHeroObjectives(CGeniusAI::HypotheticalGameState::HeroModel &h, CGeniusAI::HypotheticalGameState &hgs)
void CGeniusAI::addHeroObjectives(
CGeniusAI::HypotheticalGameState::HeroModel& h,
CGeniusAI::HypotheticalGameState& hgs)
{ {
int3 hpos, destination; int3 hpos = h.pos;
CPath path; int3 destination;
hpos = h.pos; int3 interestingPos;
CPath path;
int movement = h.remainingMovement; int movement = h.remainingMovement;
int3 interestingPos; int maxInteresting = 0;
int maxInteresting=0;
AIObjective::Type tp = AIObjective::visit; AIObjective::Type tp = AIObjective::visit;
if(h.finished) return;
for(std::set<AIObjectContainer>::const_iterator i = hgs.knownVisitableObjects.begin(); i != hgs.knownVisitableObjects.end();i++) if (h.finished)
{ return;
for (std::set<AIObjectContainer>::const_iterator i =
hgs.knownVisitableObjects.begin();
i != hgs.knownVisitableObjects.end();
i++) {
tp = AIObjective::visit; 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
// maybe the hero wants to visit a seemingly unguarded enemy town, but there is a hero on top of it. // maybe the hero wants to visit a seemingly unguarded enemy town,
//if(i->o->) // but there is a hero on top of it.
if(i->o->ID!=HEROI_TYPE) //unless you are trying to visit a hero // if(i->o->)
{ if (i->o->ID != HEROI_TYPE) {// Unless you are trying to visit a hero.
bool heroThere = false; bool heroThere = false;
for(int ii = 0; ii < hgs.heroModels.size();ii++) for(int j = 0; j < hgs.heroModels.size(); j++) {
if(hgs.heroModels[ii].pos==i->o->getSightCenter()) if (hgs.heroModels[j].pos == i->o->getSightCenter())
heroThere = true; heroThere = true;
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 if (i->o->ID == HEROI_TYPE && // Visiting friendly heroes not yet supported.
i->o->getOwner() == m_cb->getMyColor())
continue; 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;
// Don't visit a mine if you own, there's almost no
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). // point(maybe to leave guards or because the hero's trapped).
if (i->o->ID == 53
&& i->o->getOwner() == m_cb->getMyColor())
continue; continue;
if(i->o->getOwner()!=m_cb->getMyColor()) if (i->o->getOwner() != m_cb->getMyColor()) {
{ // 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. // We must get an approximation based on few, many, ... zounds etc.
// We must get an approximation based on few, many, ... zounds etc. int enemyStrength = 0;
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 // TODO: should be virtual maybe, army strength should be
if(dynamic_cast<const CGHeroInstance *> (i->o)) // comparable across objects.
enemyStrength = (dynamic_cast<const CGHeroInstance *> (i->o))->getTotalStrength(); // TODO: Rewrite all those damn i->o. For someone reading it the first
if(dynamic_cast<const CGTownInstance *> (i->o)) // time it's completely inconprehensible.
enemyStrength = (dynamic_cast<const CGTownInstance *> (i->o))->getArmyStrength()*1.2; if (dynamic_cast<const CArmedInstance *> (i->o))
enemyStrength =
(dynamic_cast<const CArmedInstance *> (i->o))->getArmyStrength();
if (dynamic_cast<const CGHeroInstance *> (i->o))
enemyStrength =
(dynamic_cast<const CGHeroInstance *> (i->o))->getTotalStrength();
// TODO: Make constants of those 1.2 & 2.5.
if (dynamic_cast<const CGTownInstance *> (i->o))
enemyStrength =
(dynamic_cast<const CGTownInstance *> (i->o))->getArmyStrength()*1.2;
float heroStrength = h.h->getTotalStrength(); float heroStrength = h.h->getTotalStrength();
if(enemyStrength*2.5 > heroStrength) //TODO: ballence these numbers using objective cost formula. // TODO: ballence these numbers using objective cost formula.
continue; // it would be nice to do a battle sim // TODO: it would be nice to do a battle simulation.
if(enemyStrength>0)tp = AIObjective::attack; if (enemyStrength*2.5 > heroStrength)
continue;
if (enemyStrength > 0)
tp = AIObjective::attack;
} }
//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. if (dynamic_cast<const CGVisitableOPW*> (i->o)
continue; && dynamic_cast<const CGVisitableOPW*> (i->o)->visited)
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
continue; continue;
//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))
continue;
// TODO: Some descriptions of those included so someone can undestand them.
if(i->o->ID==88||i->o->ID==89||i->o->ID==90) if (i->o->ID == 88 || i->o->ID == 89 || i->o->ID == 90) {
{
//TODO: if no spell book continue //TODO: if no spell book continue
//TODO: if the shrine's spell is identified, and the hero already has it, continue //TODO: if the shrine's spell is identified, and the hero already has it, continue
} }
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 // 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 // TODO: Will have to make some calculations so that the AI can enter the
if(m_cb->getPath(hpos,destination,h.h,path)) // underground.
{ if (hpos.z == destination.z) {
//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)) {
path.convert(0); path.convert(0);
if(path.nodes[0].dist<movement) if (path.nodes[0].dist < movement) {
{ // TODO: So easy to understand...
HeroObjective ho(hgs, tp, i->o, &h, this);
HeroObjective ho(hgs,tp,i->o,&h,this);
std::set<HeroObjective>::iterator found = currentHeroObjectives.find(ho); std::set<HeroObjective>::iterator found = currentHeroObjectives.find(ho);
if(found==currentHeroObjectives.end()) if (found == currentHeroObjectives.end())
currentHeroObjectives.insert(ho); currentHeroObjectives.insert(ho);
else { else {
HeroObjective *objective = (HeroObjective *)&(*found); HeroObjective *objective = (HeroObjective*)&(*found);
objective->whoCanAchieve.push_back(&h); objective->whoCanAchieve.push_back(&h);
} }
} }
// find the most interesting object that is eventually reachable, and set that position to the ultimate goal position // Find the most interesting object that is eventually reachable,
int hi = rand(); //TODO: replace random numbers with some sort of ranking system // and set that position to the ultimate goal position.
// TODO: replace random numbers with some sort of ranking system.
if(hi>maxInteresting) int hi = rand();
{ if (hi > maxInteresting) {
maxInteresting = hi; maxInteresting = hi;
interestingPos = destination; interestingPos = destination;
} }
} } // if (m_cb->getPath(hpos, destination, h.h, path))
} // if (hpos.z == destination.z)
} // for (std::set<AIObjectContainer>::const_iterator i = knownVisitableObjects.begin();
}
}
h.interestingPos = interestingPos; h.interestingPos = interestingPos;
// if(h.remainingMovement>0&&m_cb->getPath(hpos,interestingPos,h.h,path)) // there ought to be a path // there ought to be a path
currentHeroObjectives.insert(HeroObjective(hgs,HeroObjective::finishTurn,h.h,&h,this)); // if(h.remainingMovement>0&&m_cb->getPath(hpos,interestingPos,h.h,path))
currentHeroObjectives.insert(HeroObjective(hgs,
HeroObjective::finishTurn,
h.h,
&h,
this));
} }
void CGeniusAI::HeroObjective::fulfill(CGeniusAI & cg,HypotheticalGameState & hgs) void CGeniusAI::HeroObjective::fulfill(CGeniusAI & cg,HypotheticalGameState & hgs)
{ {
@ -623,6 +771,7 @@ void CGeniusAI::HeroObjective::fulfill(CGeniusAI & cg,HypotheticalGameState & hg
} }
void CGeniusAI::addTownObjectives(HypotheticalGameState::TownModel &t, HypotheticalGameState & hgs) void CGeniusAI::addTownObjectives(HypotheticalGameState::TownModel &t, HypotheticalGameState & hgs)
{ {
//recruitHero //recruitHero
@ -940,12 +1089,12 @@ void CGeniusAI::heroGotLevel(const CGHeroInstance *hero, int pskill, std::vector
callback(rand() % skills.size()); callback(rand() % skills.size());
} }
void GeniusAI::CGeniusAI::showGarrisonDialog( const CArmedInstance *up, const CGHeroInstance *down, bool removableUnits, boost::function<void()> &onEnd ) void geniusai::CGeniusAI::showGarrisonDialog( const CArmedInstance *up, const CGHeroInstance *down, bool removableUnits, boost::function<void()> &onEnd )
{ {
onEnd(); onEnd();
} }
void GeniusAI::CGeniusAI::playerBlocked( int reason ) void geniusai::CGeniusAI::playerBlocked( int reason )
{ {
if(reason == 0) //battle is coming... if(reason == 0) //battle is coming...
{ {
@ -953,7 +1102,7 @@ void GeniusAI::CGeniusAI::playerBlocked( int reason )
} }
} }
void GeniusAI::CGeniusAI::battleResultsApplied() void geniusai::CGeniusAI::battleResultsApplied()
{ {
assert(m_state.get() == ENDING_BATTLE); assert(m_state.get() == ENDING_BATTLE);
m_state.setn(NO_BATTLE); m_state.setn(NO_BATTLE);

View File

@ -11,7 +11,7 @@
class CBuilding; class CBuilding;
namespace GeniusAI { namespace geniusai {
enum BattleState enum BattleState
{ {
@ -28,9 +28,9 @@ class CGeniusAI : public CGlobalAI
{ {
private: private:
ICallback* m_cb; ICallback* m_cb;
GeniusAI::BattleAI::CBattleLogic* m_battleLogic; geniusai::BattleAI::CBattleLogic* m_battleLogic;
GeniusAI::GeneralAI::CGeneralAI m_generalAI; geniusai::GeneralAI::CGeneralAI m_generalAI;
GeniusAI::Priorities * m_priorities; geniusai::Priorities * m_priorities;
CondSh<BattleState> m_state; //are we engaged into battle? CondSh<BattleState> m_state; //are we engaged into battle?

View File

@ -4,7 +4,7 @@
#include "CGeniusAI.h" #include "CGeniusAI.h"
using namespace GeniusAI; using namespace geniusai;
const char *g_cszAiName = "Genius 1.0"; const char *g_cszAiName = "Genius 1.0";

View File

@ -1,7 +1,7 @@
#include "GeneralAI.h" #include "GeneralAI.h"
#include "../../CCallback.h" #include "../../CCallback.h"
using namespace GeniusAI::GeneralAI; using namespace geniusai::GeneralAI;
CGeneralAI::CGeneralAI() CGeneralAI::CGeneralAI()
: m_cb(NULL) : m_cb(NULL)

View File

@ -3,7 +3,7 @@
#include "Common.h" #include "Common.h"
namespace GeniusAI { namespace GeneralAI { namespace geniusai { namespace GeneralAI {
class CGeneralAI class CGeneralAI
{ {