# ai_object.cpp

Go to the documentation of this file.

    00001 /* $Id: ai_object.cpp 15299 2009-01-31 20:16:06Z smatz $ */
    00002
    00005 #include "ai_log.hpp"
    00006 #include "table/strings.h"
    00007 #include "../ai.hpp"
    00008 #include "../ai_storage.hpp"
    00009 #include "../ai_instance.hpp"
    00010
    00011 static AIStorage *GetStorage()
    00012 {
    00013   return AIInstance::GetStorage();
    00014 }
    00015
    00016 void AIObject::SetDoCommandDelay(uint ticks)
    00017 {
    00018   assert(ticks > 0);
    00019   GetStorage()->delay = ticks;
    00020 }
    00021
    00022 uint AIObject::GetDoCommandDelay()
    00023 {
    00024   return GetStorage()->delay;
    00025 }
    00026
    00027 void AIObject::SetDoCommandMode(AIModeProc *proc, AIObject *instance)
    00028 {
    00029   GetStorage()->mode = proc;
    00030   GetStorage()->mode_instance = instance;
    00031 }
    00032
    00033 AIModeProc *AIObject::GetDoCommandMode()
    00034 {
    00035   return GetStorage()->mode;
    00036 }
    00037
    00038 AIObject *AIObject::GetDoCommandModeInstance()
    00039 {
    00040   return GetStorage()->mode_instance;
    00041 }
    00042
    00043 void AIObject::SetDoCommandCosts(Money value)
    00044 {
    00045   GetStorage()->costs = CommandCost(value);
    00046 }
    00047
    00048 void AIObject::IncreaseDoCommandCosts(Money value)
    00049 {
    00050   GetStorage()->costs.AddCost(value);
    00051 }
    00052
    00053 Money AIObject::GetDoCommandCosts()
    00054 {
    00055   return GetStorage()->costs.GetCost();
    00056 }
    00057
    00058 void AIObject::SetLastError(AIErrorType last_error)
    00059 {
    00060   GetStorage()->last_error = last_error;
    00061 }
    00062
    00063 AIErrorType AIObject::GetLastError()
    00064 {
    00065   return GetStorage()->last_error;
    00066 }
    00067
    00068 void AIObject::SetLastCost(Money last_cost)
    00069 {
    00070   GetStorage()->last_cost = last_cost;
    00071 }
    00072
    00073 Money AIObject::GetLastCost()
    00074 {
    00075   return GetStorage()->last_cost;
    00076 }
    00077
    00078 void AIObject::SetRoadType(RoadType road_type)
    00079 {
    00080   GetStorage()->road_type = road_type;
    00081 }
    00082
    00083 RoadType AIObject::GetRoadType()
    00084 {
    00085   return GetStorage()->road_type;
    00086 }
    00087
    00088 void AIObject::SetRailType(RailType rail_type)
    00089 {
    00090   GetStorage()->rail_type = rail_type;
    00091 }
    00092
    00093 RailType AIObject::GetRailType()
    00094 {
    00095   return GetStorage()->rail_type;
    00096 }
    00097
    00098 void AIObject::SetLastCommandRes(bool res)
    00099 {
    00100   GetStorage()->last_command_res = res;
    00101   /* Also store the results of various global variables */
    00102   SetNewVehicleID(_new_vehicle_id);
    00103   SetNewSignID(_new_sign_id);
    00104   SetNewTunnelEndtile(_build_tunnel_endtile);
    00105   SetNewGroupID(_new_group_id);
    00106 }
    00107
    00108 bool AIObject::GetLastCommandRes()
    00109 {
    00110   return GetStorage()->last_command_res;
    00111 }
    00112
    00113 void AIObject::SetNewVehicleID(VehicleID vehicle_id)
    00114 {
    00115   GetStorage()->new_vehicle_id = vehicle_id;
    00116 }
    00117
    00118 VehicleID AIObject::GetNewVehicleID()
    00119 {
    00120   return GetStorage()->new_vehicle_id;
    00121 }
    00122
    00123 void AIObject::SetNewSignID(SignID sign_id)
    00124 {
    00125   GetStorage()->new_sign_id = sign_id;
    00126 }
    00127
    00128 SignID AIObject::GetNewSignID()
    00129 {
    00130   return GetStorage()->new_sign_id;
    00131 }
    00132
    00133 void AIObject::SetNewTunnelEndtile(TileIndex tile)
    00134 {
    00135   GetStorage()->new_tunnel_endtile = tile;
    00136 }
    00137
    00138 TileIndex AIObject::GetNewTunnelEndtile()
    00139 {
    00140   return GetStorage()->new_tunnel_endtile;
    00141 }
    00142
    00143 void AIObject::SetNewGroupID(GroupID group_id)
    00144 {
    00145   GetStorage()->new_group_id = group_id;
    00146 }
    00147
    00148 GroupID AIObject::GetNewGroupID()
    00149 {
    00150   return GetStorage()->new_group_id;
    00151 }
    00152
    00153 void AIObject::SetAllowDoCommand(bool allow)
    00154 {
    00155   GetStorage()->allow_do_command = allow;
    00156 }
    00157
    00158 bool AIObject::GetAllowDoCommand()
    00159 {
    00160   return GetStorage()->allow_do_command;
    00161 }
    00162
    00163 void *&AIObject::GetEventPointer()
    00164 {
    00165   return GetStorage()->event_data;
    00166 }
    00167
    00168 void *&AIObject::GetLogPointer()
    00169 {
    00170   return GetStorage()->log_data;
    00171 }
    00172
    00173 void AIObject::SetCallbackVariable(int index, int value)
    00174 {
    00175   if ((size_t)index >= GetStorage()->callback_value.size()) GetStorage()->callback_value.resize(index + 1);
    00176   GetStorage()->callback_value[index] = value;
    00177 }
    00178
    00179 int AIObject::GetCallbackVariable(int index)
    00180 {
    00181   return GetStorage()->callback_value[index];
    00182 }
    00183
    00184 bool AIObject::DoCommand(TileIndex tile, uint32 p1, uint32 p2, uint cmd, const char *text, AISuspendCallbackProc *callback)
    00185 {
    00186   if (AIObject::GetAllowDoCommand() == false) {
    00187     AILog::Error("You are not allowed to execute any DoCommand (even indirect) in your constructor, Save(), Load(), and any valuator.\n");
    00188     return false;
    00189   }
    00190
    00191   CommandCost res;
    00192
    00193   /* Set the default callback to return a true/false result of the DoCommand */
    00194   if (callback == NULL) callback = &AIInstance::DoCommandReturn;
    00195
    00196   /* Make sure the last error is reset, so we don't give faulty warnings */
    00197   SetLastError(AIError::ERR_NONE);
    00198
    00199   /* First, do a test-run to see if we can do this */
    00200   res = ::DoCommand(tile, p1, p2, CommandFlagsToDCFlags(GetCommandFlags(cmd)), cmd, text);
    00201   /* The command failed, so return */
    00202   if (::CmdFailed(res)) {
    00203     SetLastError(AIError::StringToError(_error_message));
    00204     return false;
    00205   }
    00206
    00207   /* Check what the callback wants us to do */
    00208   if (GetDoCommandMode() != NULL && !GetDoCommandMode()(tile, p1, p2, cmd, res)) {
    00209     IncreaseDoCommandCosts(res.GetCost());
    00210     return true;
    00211   }
    00212
    00213 #ifdef ENABLE_NETWORK
    00214   /* Send the command */
    00215   if (_networking) {
    00216     /* NetworkSend_Command needs _local_company to be set correctly, so
    00217      * adjust it, and put it back right after the function */
    00218     CompanyID old_company = _local_company;
    00219     _local_company = _current_company;
    00220     ::NetworkSend_Command(tile, p1, p2, cmd, CcAI, text);
    00221     _local_company = old_company;
    00222     SetLastCost(res.GetCost());
    00223
    00224     /* Suspend the AI till the command is really executed */
    00225     throw AI_VMSuspend(-(int)GetDoCommandDelay(), callback);
    00226   } else {
    00227 #else
    00228   {
    00229 #endif
    00230     /* For SinglePlayer we execute the command immediatly */
    00231     if (!::DoCommandP(tile, p1, p2, cmd, NULL, text)) res = CMD_ERROR;
    00232     SetLastCommandRes(!::CmdFailed(res));
    00233
    00234     if (::CmdFailed(res)) {
    00235       SetLastError(AIError::StringToError(_error_message));
    00236       return false;
    00237     }
    00238     SetLastCost(res.GetCost());
    00239     IncreaseDoCommandCosts(res.GetCost());
    00240
    00241     /* Suspend the AI player for 1+ ticks, so it simulates multiplayer. This
    00242      *  both avoids confusion when a developer launched his AI in a
    00243      *  multiplayer game, but also gives time for the GUI and human player
    00244      *  to interact with the game. */
    00245     throw AI_VMSuspend(GetDoCommandDelay(), callback);
    00246   }
    00247
    00248   NOT_REACHED();
    00249 }