ai_object.cpp

Go to the documentation of this file.
00001 /* $Id$ */
00002 
00003 /*
00004  * This file is part of OpenTTD.
00005  * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
00006  * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00007  * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
00008  */
00009 
00012 #include "../../stdafx.h"
00013 #include "../../script/squirrel.hpp"
00014 #include "../../command_func.h"
00015 #include "../../company_base.h"
00016 #include "../../company_func.h"
00017 #include "../../network/network.h"
00018 #include "../../tunnelbridge.h"
00019 
00020 #include "../ai_storage.hpp"
00021 #include "../ai_instance.hpp"
00022 #include "ai_error.hpp"
00023 
00028 static AIStorage *GetStorage()
00029 {
00030   return AIInstance::GetStorage();
00031 }
00032 
00033 void AIObject::SetDoCommandDelay(uint ticks)
00034 {
00035   assert(ticks > 0);
00036   GetStorage()->delay = ticks;
00037 }
00038 
00039 uint AIObject::GetDoCommandDelay()
00040 {
00041   return GetStorage()->delay;
00042 }
00043 
00044 void AIObject::SetDoCommandMode(AIModeProc *proc, AIObject *instance)
00045 {
00046   GetStorage()->mode = proc;
00047   GetStorage()->mode_instance = instance;
00048 }
00049 
00050 AIModeProc *AIObject::GetDoCommandMode()
00051 {
00052   return GetStorage()->mode;
00053 }
00054 
00055 AIObject *AIObject::GetDoCommandModeInstance()
00056 {
00057   return GetStorage()->mode_instance;
00058 }
00059 
00060 void AIObject::SetDoCommandCosts(Money value)
00061 {
00062   GetStorage()->costs = CommandCost(value);
00063 }
00064 
00065 void AIObject::IncreaseDoCommandCosts(Money value)
00066 {
00067   GetStorage()->costs.AddCost(value);
00068 }
00069 
00070 Money AIObject::GetDoCommandCosts()
00071 {
00072   return GetStorage()->costs.GetCost();
00073 }
00074 
00075 void AIObject::SetLastError(AIErrorType last_error)
00076 {
00077   GetStorage()->last_error = last_error;
00078 }
00079 
00080 AIErrorType AIObject::GetLastError()
00081 {
00082   return GetStorage()->last_error;
00083 }
00084 
00085 void AIObject::SetLastCost(Money last_cost)
00086 {
00087   GetStorage()->last_cost = last_cost;
00088 }
00089 
00090 Money AIObject::GetLastCost()
00091 {
00092   return GetStorage()->last_cost;
00093 }
00094 
00095 void AIObject::SetRoadType(RoadType road_type)
00096 {
00097   GetStorage()->road_type = road_type;
00098 }
00099 
00100 RoadType AIObject::GetRoadType()
00101 {
00102   return GetStorage()->road_type;
00103 }
00104 
00105 void AIObject::SetRailType(RailType rail_type)
00106 {
00107   GetStorage()->rail_type = rail_type;
00108 }
00109 
00110 RailType AIObject::GetRailType()
00111 {
00112   return GetStorage()->rail_type;
00113 }
00114 
00115 void AIObject::SetLastCommandRes(bool res)
00116 {
00117   GetStorage()->last_command_res = res;
00118   /* Also store the results of various global variables */
00119   SetNewVehicleID(_new_vehicle_id);
00120   SetNewSignID(_new_sign_id);
00121   SetNewTunnelEndtile(_build_tunnel_endtile);
00122   SetNewGroupID(_new_group_id);
00123 }
00124 
00125 bool AIObject::GetLastCommandRes()
00126 {
00127   return GetStorage()->last_command_res;
00128 }
00129 
00130 void AIObject::SetNewVehicleID(VehicleID vehicle_id)
00131 {
00132   GetStorage()->new_vehicle_id = vehicle_id;
00133 }
00134 
00135 VehicleID AIObject::GetNewVehicleID()
00136 {
00137   return GetStorage()->new_vehicle_id;
00138 }
00139 
00140 void AIObject::SetNewSignID(SignID sign_id)
00141 {
00142   GetStorage()->new_sign_id = sign_id;
00143 }
00144 
00145 SignID AIObject::GetNewSignID()
00146 {
00147   return GetStorage()->new_sign_id;
00148 }
00149 
00150 void AIObject::SetNewTunnelEndtile(TileIndex tile)
00151 {
00152   GetStorage()->new_tunnel_endtile = tile;
00153 }
00154 
00155 TileIndex AIObject::GetNewTunnelEndtile()
00156 {
00157   return GetStorage()->new_tunnel_endtile;
00158 }
00159 
00160 void AIObject::SetNewGroupID(GroupID group_id)
00161 {
00162   GetStorage()->new_group_id = group_id;
00163 }
00164 
00165 GroupID AIObject::GetNewGroupID()
00166 {
00167   return GetStorage()->new_group_id;
00168 }
00169 
00170 void AIObject::SetAllowDoCommand(bool allow)
00171 {
00172   GetStorage()->allow_do_command = allow;
00173 }
00174 
00175 bool AIObject::GetAllowDoCommand()
00176 {
00177   return GetStorage()->allow_do_command;
00178 }
00179 
00180 bool AIObject::CanSuspend()
00181 {
00182   Squirrel *squirrel = Company::Get(_current_company)->ai_instance->engine;
00183   return GetStorage()->allow_do_command && squirrel->CanSuspend();
00184 }
00185 
00186 void *&AIObject::GetEventPointer()
00187 {
00188   return GetStorage()->event_data;
00189 }
00190 
00191 void *&AIObject::GetLogPointer()
00192 {
00193   return GetStorage()->log_data;
00194 }
00195 
00196 void AIObject::SetCallbackVariable(int index, int value)
00197 {
00198   if ((size_t)index >= GetStorage()->callback_value.size()) GetStorage()->callback_value.resize(index + 1);
00199   GetStorage()->callback_value[index] = value;
00200 }
00201 
00202 int AIObject::GetCallbackVariable(int index)
00203 {
00204   return GetStorage()->callback_value[index];
00205 }
00206 
00207 bool AIObject::DoCommand(TileIndex tile, uint32 p1, uint32 p2, uint cmd, const char *text, AISuspendCallbackProc *callback)
00208 {
00209   if (!AIObject::CanSuspend()) {
00210     throw AI_FatalError("You are not allowed to execute any DoCommand (even indirect) in your constructor, Save(), Load(), and any valuator.");
00211   }
00212 
00213   /* Set the default callback to return a true/false result of the DoCommand */
00214   if (callback == NULL) callback = &AIInstance::DoCommandReturn;
00215 
00216   /* Are we only interested in the estimate costs? */
00217   bool estimate_only = GetDoCommandMode() != NULL && !GetDoCommandMode()();
00218 
00219 #ifdef ENABLE_NETWORK
00220   /* Only set p2 when the command does not come from the network. */
00221   if (GetCommandFlags(cmd) & CMD_CLIENT_ID && p2 == 0) p2 = UINT32_MAX;
00222 #endif
00223 
00224   /* Try to perform the command. */
00225   CommandCost res = ::DoCommandPInternal(tile, p1, p2, cmd, _networking ? CcAI : NULL, text, false, estimate_only);
00226 
00227   /* We failed; set the error and bail out */
00228   if (res.Failed()) {
00229     SetLastError(AIError::StringToError(res.GetErrorMessage()));
00230     return false;
00231   }
00232 
00233   /* No error, then clear it. */
00234   SetLastError(AIError::ERR_NONE);
00235 
00236   /* Estimates, update the cost for the estimate and be done */
00237   if (estimate_only) {
00238     IncreaseDoCommandCosts(res.GetCost());
00239     return true;
00240   }
00241 
00242   /* Costs of this operation. */
00243   SetLastCost(res.GetCost());
00244   SetLastCommandRes(true);
00245 
00246   if (_networking) {
00247     /* Suspend the AI till the command is really executed. */
00248     throw AI_VMSuspend(-(int)GetDoCommandDelay(), callback);
00249   } else {
00250     IncreaseDoCommandCosts(res.GetCost());
00251 
00252     /* Suspend the AI player for 1+ ticks, so it simulates multiplayer. This
00253      *  both avoids confusion when a developer launched his AI in a
00254      *  multiplayer game, but also gives time for the GUI and human player
00255      *  to interact with the game. */
00256     throw AI_VMSuspend(GetDoCommandDelay(), callback);
00257   }
00258 
00259   NOT_REACHED();
00260 }

Generated on Sun Jun 5 04:19:53 2011 for OpenTTD by  doxygen 1.6.1