ai_object.cpp

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

Generated on Sun Jan 9 16:01:51 2011 for OpenTTD by  doxygen 1.6.1