(svn r12431) [NoAI] -Add: added AIEventSubsidiaryOffer, which keeps you informed about new Subsidiaries
/* $Id$ */
/** @file ai_object.cpp handles the commands-related functions of the AIObject class */
#include "ai_object.hpp"
#include "../../command_func.h"
#include "../../network/network.h"
#include "../../player_func.h"
#include "../../signs.h" // for _new_sign_id
#include "../../vehicle_func.h"
#include "../ai.h"
#include "../ai_threads.h"
void AIObject::SetDoCommandDelay(uint ticks)
{
assert(ticks > 0);
AIObject::GetDoCommandStruct(_current_player)->delay = ticks;
}
uint AIObject::GetDoCommandDelay()
{
return AIObject::GetDoCommandStruct(_current_player)->delay;
}
void AIObject::SetDoCommandMode(AIModeProc *proc, AIObject *instance)
{
AIObject::GetDoCommandStruct(_current_player)->mode = proc;
AIObject::GetDoCommandStruct(_current_player)->mode_instance = instance;
}
AIModeProc *AIObject::GetDoCommandMode()
{
return AIObject::GetDoCommandStruct(_current_player)->mode;
}
AIObject *AIObject::GetDoCommandModeInstance()
{
return AIObject::GetDoCommandStruct(_current_player)->mode_instance;
}
void AIObject::SetDoCommandCosts(Money value)
{
AIObject::GetDoCommandStruct(_current_player)->costs = CommandCost(value);
}
void AIObject::IncreaseDoCommandCosts(Money value)
{
AIObject::GetDoCommandStruct(_current_player)->costs.AddCost(value);
}
Money AIObject::GetDoCommandCosts()
{
return AIObject::GetDoCommandStruct(_current_player)->costs.GetCost();
}
void AIObject::SetLastCommandRes(bool res)
{
AIObject::GetDoCommandStruct(_current_player)->last_command_res = res;
}
bool AIObject::GetLastCommandRes()
{
return AIObject::GetDoCommandStruct(_current_player)->last_command_res;
}
void AIObject::SetNewVehicleID(VehicleID vehicle)
{
AIObject::GetDoCommandStruct(_current_player)->new_vehicle_id = vehicle;
}
VehicleID AIObject::GetNewVehicleID()
{
return AIObject::GetDoCommandStruct(_current_player)->new_vehicle_id;
}
void AIObject::SetNewSignID(SignID sign)
{
AIObject::GetDoCommandStruct(_current_player)->new_sign_id = sign;
}
SignID AIObject::GetNewSignID()
{
return AIObject::GetDoCommandStruct(_current_player)->new_sign_id;
}
void *&AIObject::GetEventPointer()
{
return AIObject::GetDoCommandStruct(_current_player)->event_data;
}
AIObject::AIDoCommandStruct *AIObject::GetDoCommandStruct(PlayerID player)
{
/* Storage for data on per-AI level */
static AIObject::AIDoCommandStruct command_struct[MAX_PLAYERS];
static bool initialized = false;
/* Make sure all memory is NULL when we start */
if (!initialized) {
initialized = true;
memset(&command_struct, 0, sizeof(command_struct));
}
return &command_struct[player];
}
void AIObject::ResetInternalPlayerData()
{
AIObject::AIDoCommandStruct *command_struct = GetDoCommandStruct(_current_player);
command_struct->mode = NULL;
command_struct->delay = 1;
command_struct->costs = CommandCost();
if (command_struct->event_data != NULL) AIEventController::FreeEventPointer();
command_struct->event_data = NULL;
}
bool AIObject::DoCommand(TileIndex tile, uint32 p1, uint32 p2, uint procc, bool water_protection)
{
uint32 flags = 0;
PlayerID old_lp;
CommandCost res;
const char *tmp_cmdtext;
if (procc != CMD_LANDSCAPE_CLEAR) flags |= DC_AUTO;
if (water_protection) flags |= DC_NO_WATER;
/* The test already resets _cmd_text, so backup the pointer */
tmp_cmdtext = _cmd_text;
/* First, do a test-run to see if we can do this */
res = ::DoCommand(tile, p1, p2, flags, procc);
/* The command failed, so return */
if (::CmdFailed(res)) return false;
/* Restore _cmd_text */
_cmd_text = tmp_cmdtext;
/* Check what the callback wants us to do */
if (AIObject::GetDoCommandMode() != NULL && !AIObject::GetDoCommandMode()(tile, p1, p2, procc, res)) {
AIObject::IncreaseDoCommandCosts(res.GetCost());
return true;
}
/* If we did a DC_EXEC, and the command did not return an error, execute it
* over the network */
if (flags & DC_NO_WATER) procc |= CMD_NO_WATER;
#ifdef ENABLE_NETWORK
/* Send the command */
if (_networking) {
/* NetworkSend_Command needs _local_player to be set correctly, so
* adjust it, and put it back right after the function */
old_lp = _local_player;
_local_player = _current_player;
::NetworkSend_Command(tile, p1, p2, procc, CcAI);
_local_player = old_lp;
/* Suspend the AI till the command is really executed */
AI_SuspendPlayer(_current_player, -(int)AIObject::GetDoCommandDelay());
/* Check if the callback still agrees with us, else return error */
if (!AIObject::GetLastCommandRes()) res = CMD_ERROR;
} else {
#else
{
#endif
/* For SinglePlayer we execute the command immediatly */
::DoCommandP(tile, p1, p2, NULL, procc);
/* Store some values inside the AIObject static memory */
AIObject::SetNewVehicleID(_new_vehicle_id);
AIObject::SetNewSignID(_new_sign_id);
/* Suspend the AI player for 1 tick, so it simulates MultiPlayer */
AI_SuspendPlayer(_current_player, AIObject::GetDoCommandDelay());
}
if (::CmdFailed(res)) return false;
AIObject::IncreaseDoCommandCosts(res.GetCost());
return true;
}