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

Generated on Sat Dec 26 20:05:59 2009 for OpenTTD by  doxygen 1.5.6