(svn r9144) [NoAI] -Change: moved command functions to AIObject, and made AIBase depend on AIObject
-Change: split AIBase into AIBase and AIController, where the last should be extended by the real AI
-Remove: removed the SP queue-code, as it is no longer needed with the new message system
/* $Id$ */
/** @file ai.cpp handles the communication between the AI layer and the OpenTTD core */
#include "../../stdafx.h"
#include "../../openttd.h"
#include "../../variables.h"
#include "../../command.h"
#include "../../network/network.h"
#include "../../helpers.hpp"
#include "ai.h"
#include "ai_base.hpp"
#include "../NoAI/NoAI.hpp"
static AIController *_ai_player[MAX_PLAYERS];
static uint _ai_frame_counter;
static bool _ai_enabled;
/**
* Run 1 tick of the AI. Don't overdo it, keep it realistic.
*/
static void AI_RunTick(PlayerID player)
{
_current_player = player;
_ai_player[player]->IncreaseTick();
_ai_player[player]->GameLoop();
}
/**
* The gameloop for AIs.
* Handles one tick for all the AIs.
*/
void AI_RunGameLoop()
{
/* Don't do anything if ai is disabled */
if (!_ai_enabled) return;
/* Don't do anything if we are a network-client, or the AI has been disabled */
if (_networking && (!_network_server || !_patches.ai_in_multiplayer)) return;
/* New tick */
_ai_frame_counter++;
/* Make sure the AI follows the difficulty rule.. */
assert(_opt.diff.competitor_speed <= 4);
if ((_ai_frame_counter & ((1 << (4 - _opt.diff.competitor_speed)) - 1)) != 0) return;
/* Check for AI-client (so joining a network with an AI) */
if (!_networking || _network_server) {
/* Check if we want to run AIs (server or SP only) */
const Player* p;
FOR_ALL_PLAYERS(p) {
if (p->is_active && p->is_ai) {
/* Run the script */
AI_RunTick(p->index);
}
}
}
_current_player = OWNER_NONE;
}
/**
* A new AI sees the day of light. You can do here what ever you think is needed.
*/
void AI_StartNewAI(PlayerID player)
{
assert(IsValidPlayer(player));
if (!_ai_enabled) return;
if (_networking && !_network_server) return;
/* Called if a new AI is booted */
_ai_player[player] = new NoAI();
}
/**
* This AI player died. Give it some chance to make a final puf.
*/
void AI_PlayerDied(PlayerID player)
{
if (!_ai_enabled) return;
/* Called if this AI died */
delete _ai_player[player];
}
/**
* Initialize some AI-related stuff.
*/
void AI_Initialize()
{
/* First, make sure all AIs are DEAD! */
AI_Uninitialize();
memset(&_ai_player, 0, sizeof(_ai_player));
_ai_frame_counter = 0;
_ai_enabled = true;
}
/**
* Deinitializer for AI-related stuff.
*/
void AI_Uninitialize()
{
const Player* p;
FOR_ALL_PLAYERS(p) {
if (p->is_active && p->is_ai) AI_PlayerDied(p->index);
}
}
/**
* Is it allowed to start a new AI.
* This function checks some boundries to see if we should launch a new AI.
* @return True if we can start a new AI.
*/
bool AI_AllowNewAI()
{
/* If disabled, no AI */
if (!_ai_enabled) return false;
/* If in network, but no server, no AI */
if (_networking && !_network_server) return false;
/* If in network, and server, possible AI */
if (_networking && _network_server) {
/* Do we want AIs in multiplayer? */
if (!_patches.ai_in_multiplayer) return false;
}
return true;
}