ai_object.cpp

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

Generated on Mon Dec 14 20:59:57 2009 for OpenTTD by  doxygen 1.5.6