diff --git a/source/glest_game/ai/ai.cpp b/source/glest_game/ai/ai.cpp index ca6c36ba..a02a6298 100644 --- a/source/glest_game/ai/ai.cpp +++ b/source/glest_game/ai/ai.cpp @@ -10,20 +10,16 @@ // ============================================================== #include "ai.h" -#include #include "ai_interface.h" #include "ai_rule.h" #include "unit_type.h" #include "unit.h" -#include "program.h" -#include "config.h" -//#include #include "leak_dumper.h" using namespace Shared::Graphics; using namespace Shared::Util; -namespace Glest{ namespace Game{ +namespace Glest { namespace Game { // ===================================================== // class ProduceTask @@ -111,42 +107,50 @@ string UpgradeTask::toString() const{ // class Ai // ===================================================== -void Ai::init(AiInterface *aiInterface){ +void Ai::init(AiInterface *aiInterface, int useStartLocation) { this->aiInterface= aiInterface; - startLoc= random.randRange(0, aiInterface->getMapMaxPlayers()-1); - upgradeCount= 0; + if(useStartLocation == -1) { + startLoc = random.randRange(0, aiInterface->getMapMaxPlayers()-1); + } + else { + startLoc = useStartLocation; + } minWarriors= minMinWarriors; randomMinWarriorsReached= false; //add ai rules - aiRules.resize(14); - aiRules[0]= new AiRuleWorkerHarvest(this); - aiRules[1]= new AiRuleRefreshHarvester(this); - aiRules[2]= new AiRuleScoutPatrol(this); - aiRules[3]= new AiRuleReturnBase(this); - aiRules[4]= new AiRuleMassiveAttack(this); - aiRules[5]= new AiRuleAddTasks(this); - aiRules[6]= new AiRuleProduceResourceProducer(this); - aiRules[7]= new AiRuleBuildOneFarm(this); - aiRules[8]= new AiRuleProduce(this); - aiRules[9]= new AiRuleBuild(this); - aiRules[10]= new AiRuleUpgrade(this); - aiRules[11]= new AiRuleExpand(this); - aiRules[12]= new AiRuleRepair(this); - aiRules[13]= new AiRuleRepair(this); + aiRules.clear(); + aiRules.push_back(new AiRuleWorkerHarvest(this)); + aiRules.push_back(new AiRuleRefreshHarvester(this)); + aiRules.push_back(new AiRuleScoutPatrol(this)); + aiRules.push_back(new AiRuleReturnBase(this)); + aiRules.push_back(new AiRuleMassiveAttack(this)); + aiRules.push_back(new AiRuleAddTasks(this)); + aiRules.push_back(new AiRuleProduceResourceProducer(this)); + aiRules.push_back(new AiRuleBuildOneFarm(this)); + aiRules.push_back(new AiRuleProduce(this)); + aiRules.push_back(new AiRuleBuild(this)); + aiRules.push_back(new AiRuleUpgrade(this)); + aiRules.push_back(new AiRuleExpand(this)); + aiRules.push_back(new AiRuleRepair(this)); + aiRules.push_back(new AiRuleRepair(this)); } -Ai::~Ai(){ +Ai::~Ai() { deleteValues(tasks.begin(), tasks.end()); deleteValues(aiRules.begin(), aiRules.end()); } -void Ai::update(){ +void Ai::update() { //process ai rules - for(AiRules::iterator it= aiRules.begin(); it!=aiRules.end(); ++it){ - if((aiInterface->getTimer() % ((*it)->getTestInterval()*GameConstants::updateFps/1000))==0){ - if((*it)->test()){ - aiInterface->printLog(3, intToStr(1000*aiInterface->getTimer()/GameConstants::updateFps) + ": Executing rule: " + (*it)->getName() + '\n'); - (*it)->execute(); + for(int ruleIdx = 0; ruleIdx < aiRules.size(); ++ruleIdx) { + AiRule *rule = aiRules[ruleIdx]; + if(rule == NULL) { + throw runtime_error("rule == NULL"); + } + if((aiInterface->getTimer() % (rule->getTestInterval() * GameConstants::updateFps / 1000)) == 0){ + if(rule->test()) { + aiInterface->printLog(3, intToStr(1000 * aiInterface->getTimer() / GameConstants::updateFps) + ": Executing rule: " + rule->getName() + '\n'); + rule->execute(); } } } diff --git a/source/glest_game/ai/ai.h b/source/glest_game/ai/ai.h index 4f5be024..b475557b 100644 --- a/source/glest_game/ai/ai.h +++ b/source/glest_game/ai/ai.h @@ -111,7 +111,7 @@ public: /// Main AI class // =============================== -class Ai{ +class Ai { private: static const int harvesterPercent= 30; static const int maxBuildRadius= 40; @@ -123,7 +123,7 @@ private: static const int villageRadius= 15; public: - enum ResourceUsage{ + enum ResourceUsage { ruHarvester, ruWarrior, ruBuilding, @@ -131,7 +131,8 @@ public: }; private: - typedef vector AiRules; + //typedef vector AiRules; + typedef vector AiRules; typedef list Tasks; typedef deque Positions; @@ -140,7 +141,6 @@ private: AiRules aiRules; int startLoc; bool randomMinWarriorsReached; - int upgradeCount; Tasks tasks; Positions expansionPositions; RandomGen random; @@ -148,12 +148,12 @@ private: public: int minWarriors; ~Ai(); - void init(AiInterface *aiInterface); + void init(AiInterface *aiInterface,int useStartLocation=-1); void update(); //state requests AiInterface *getAiInterface() const {return aiInterface;} - RandomGen* getRandom() {return &random;} + RandomGen* getRandom() {return &random;} int getCountOfType(const UnitType *ut); int getCountOfClass(UnitClass uc); diff --git a/source/glest_game/ai/ai_interface.cpp b/source/glest_game/ai/ai_interface.cpp index b7a775e1..c6e1d201 100644 --- a/source/glest_game/ai/ai_interface.cpp +++ b/source/glest_game/ai/ai_interface.cpp @@ -31,7 +31,7 @@ using namespace Shared::Graphics; namespace Glest{ namespace Game{ -AiInterface::AiInterface(Game &game, int factionIndex, int teamIndex){ +AiInterface::AiInterface(Game &game, int factionIndex, int teamIndex, int useStartLocation) { SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); this->world= game.getWorld(); @@ -44,7 +44,7 @@ AiInterface::AiInterface(Game &game, int factionIndex, int teamIndex){ timer= 0; //init ai - ai.init(this); + ai.init(this,useStartLocation); //config logLevel= Config::getInstance().getInt("AiLog"); diff --git a/source/glest_game/ai/ai_interface.h b/source/glest_game/ai/ai_interface.h index afc1407e..58f07683 100644 --- a/source/glest_game/ai/ai_interface.h +++ b/source/glest_game/ai/ai_interface.h @@ -48,7 +48,7 @@ private: int logLevel; public: - AiInterface(Game &game, int factionIndex, int teamIndex); + AiInterface(Game &game, int factionIndex, int teamIndex, int useStartLocation=-1); //main void update(); diff --git a/source/glest_game/game/game.cpp b/source/glest_game/game/game.cpp index d440891d..d97527ab 100644 --- a/source/glest_game/game/game.cpp +++ b/source/glest_game/game/game.cpp @@ -633,15 +633,18 @@ void Game::update() { if(chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s] Line: %d took msecs: %lld\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis()); NetworkManager &networkManager= NetworkManager::getInstance(); + bool enableServerControlledAI = this->gameSettings.getEnableServerControlledAI(); + bool isNetworkGame = this->gameSettings.isNetworkGame(); + NetworkRole role = networkManager.getNetworkRole(); + + // Check to see if we are playing a network game and if any players + // have disconnected? + ReplaceDisconnectedNetworkPlayersWithAI(isNetworkGame, role); + //update for(int i = 0; i < updateLoops; ++i) { chrono.start(); - Renderer &renderer= Renderer::getInstance(); - //SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); - bool enableServerControlledAI = this->gameSettings.getEnableServerControlledAI(); - bool isNetworkGame = this->gameSettings.isNetworkGame(); - NetworkRole role = networkManager.getNetworkRole(); //AiInterface for(int i = 0; i < world.getFactionCount(); ++i) { @@ -683,6 +686,7 @@ void Game::update() { if(chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s] Line: %d took msecs: %lld [weather particle updating]\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis()); if(chrono.getMillis() > 0) chrono.start(); + Renderer &renderer= Renderer::getInstance(); renderer.updateParticleManager(rsGame,avgRenderFps); if(chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s] Line: %d took msecs: %lld [particle manager updating]\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis()); if(chrono.getMillis() > 0) chrono.start(); @@ -726,6 +730,34 @@ void Game::update() { } } +void Game::ReplaceDisconnectedNetworkPlayersWithAI(bool isNetworkGame, NetworkRole role) { + if(role == nrServer && isNetworkGame == true) { + Logger &logger= Logger::getInstance(); + ServerInterface *server = NetworkManager::getInstance().getServerInterface(); + + for(int i = 0; i < world.getFactionCount(); ++i) { + Faction *faction = world.getFaction(i); + if( faction->getControlType() == ctNetwork || + faction->getControlType() == ctNetworkCpuEasy || + faction->getControlType() == ctNetworkCpu || + faction->getControlType() == ctNetworkCpuUltra || + faction->getControlType() == ctNetworkCpuMega) { + ConnectionSlot *slot = server->getSlot(i); + if(aiInterfaces[i] == NULL && (slot == NULL || slot->isConnected() == false)) { + + faction->setControlType(ctCpu); + aiInterfaces[i] = new AiInterface(*this, i, faction->getTeam(), faction->getStartLocationIndex()); + logger.add("Creating AI for faction " + intToStr(i), true); + + char szBuf[255]=""; + sprintf(szBuf,"Player #%d [%s] has disconnected, switching player to AI mode!",i+1,this->gameSettings.getNetworkPlayerName(i).c_str()); + server->sendTextMessage(szBuf,-1,true); + } + } + } + } +} + void Game::updateCamera(){ gameCamera.update(); } diff --git a/source/glest_game/game/game.h b/source/glest_game/game/game.h index dbffc194..89fdba1c 100644 --- a/source/glest_game/game/game.h +++ b/source/glest_game/game/game.h @@ -186,6 +186,8 @@ private: void renderWorker(); static int ErrorDisplayMessage(const char *msg, bool exitApp); + + void ReplaceDisconnectedNetworkPlayersWithAI(bool isNetworkGame, NetworkRole role); }; }}//end namespace diff --git a/source/glest_game/type_instances/faction.h b/source/glest_game/type_instances/faction.h index 9c4f4e2d..d07744d7 100644 --- a/source/glest_game/type_instances/faction.h +++ b/source/glest_game/type_instances/faction.h @@ -141,6 +141,8 @@ public: void incResourceAmount(const ResourceType *rt, int amount); void setResourceBalance(const ResourceType *rt, int balance); + void setControlType(ControlType value) { control = value; } + std::string toString() const; private: