- added initial code for switching dropped network players to AI (currently hard coded to normal CPU)

This commit is contained in:
Mark Vejvoda 2010-10-18 23:09:43 +00:00
parent 3d4ccb460c
commit 7564635643
7 changed files with 84 additions and 44 deletions

View File

@ -10,20 +10,16 @@
// ==============================================================
#include "ai.h"
#include <ctime>
#include "ai_interface.h"
#include "ai_rule.h"
#include "unit_type.h"
#include "unit.h"
#include "program.h"
#include "config.h"
//#include <limits>
#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();
}
}
}

View File

@ -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<AiRule*> AiRules;
//typedef vector<AiRule*> AiRules;
typedef vector<AiRule *> AiRules;
typedef list<const Task*> Tasks;
typedef deque<Vec2i> 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);

View File

@ -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");

View File

@ -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();

View File

@ -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();
}

View File

@ -186,6 +186,8 @@ private:
void renderWorker();
static int ErrorDisplayMessage(const char *msg, bool exitApp);
void ReplaceDisconnectedNetworkPlayersWithAI(bool isNetworkGame, NetworkRole role);
};
}}//end namespace

View File

@ -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: