ai_vehicle.cpp

Go to the documentation of this file.
00001 /* $Id: ai_vehicle.cpp 18500 2009-12-14 20:50:32Z rubidium $ */
00002 
00005 #include "ai_engine.hpp"
00006 #include "ai_cargo.hpp"
00007 #include "ai_gamesettings.hpp"
00008 #include "ai_group.hpp"
00009 #include "../ai_instance.hpp"
00010 #include "../../company_func.h"
00011 #include "../../aircraft.h"
00012 #include "../../string_func.h"
00013 #include "../../strings_func.h"
00014 #include "../../command_func.h"
00015 #include "../../roadveh.h"
00016 #include "../../train.h"
00017 #include "../../vehicle_func.h"
00018 #include "table/strings.h"
00019 
00020 /* static */ bool AIVehicle::IsValidVehicle(VehicleID vehicle_id)
00021 {
00022   if (!::IsValidVehicleID(vehicle_id)) return false;
00023   const Vehicle *v = ::GetVehicle(vehicle_id);
00024   return v->owner == _current_company && (v->IsPrimaryVehicle() || (v->type == VEH_TRAIN && ::IsFreeWagon(v)));
00025 }
00026 
00027 /* static */ int32 AIVehicle::GetNumWagons(VehicleID vehicle_id)
00028 {
00029   if (!IsValidVehicle(vehicle_id)) return -1;
00030 
00031   int num = 1;
00032   if (::GetVehicle(vehicle_id)->type == VEH_TRAIN) {
00033     const Vehicle *v = ::GetVehicle(vehicle_id);
00034     while ((v = GetNextUnit(v)) != NULL) num++;
00035   }
00036 
00037   return num;
00038 }
00039 
00040 /* static */ int AIVehicle::GetLength(VehicleID vehicle_id)
00041 {
00042   if (!IsValidVehicle(vehicle_id)) return -1;
00043 
00044   const Vehicle *v = ::GetVehicle(vehicle_id);
00045   switch (v->type) {
00046     case VEH_ROAD: {
00047       uint total_length = 0;
00048       for (const Vehicle *u = v; u != NULL; u = u->Next()) {
00049         total_length += u->u.road.cached_veh_length;
00050       }
00051       return total_length;
00052     }
00053     case VEH_TRAIN: return v->u.rail.cached_total_length;
00054     default: return -1;
00055   }
00056 }
00057 
00058 /* static */ VehicleID AIVehicle::BuildVehicle(TileIndex depot, EngineID engine_id)
00059 {
00060   EnforcePrecondition(INVALID_VEHICLE, AIEngine::IsValidEngine(engine_id));
00061 
00062 	::VehicleType type = ::GetEngine(engine_id)->type;
00063 
00064   EnforcePreconditionCustomError(INVALID_VEHICLE, !AIGameSettings::IsDisabledVehicleType((AIVehicle::VehicleType)type), AIVehicle::ERR_VEHICLE_BUILD_DISABLED);
00065 
00066   if (!AIObject::DoCommand(depot, engine_id, 0, ::GetCmdBuildVeh(type), NULL, &AIInstance::DoCommandReturnVehicleID)) return INVALID_VEHICLE;
00067 
00068   /* In case of test-mode, we return VehicleID 0 */
00069   return 0;
00070 }
00071 
00072 /* static */ VehicleID AIVehicle::CloneVehicle(TileIndex depot, VehicleID vehicle_id, bool share_orders)
00073 {
00074   EnforcePrecondition(false, IsValidVehicle(vehicle_id));
00075 
00076   if (!AIObject::DoCommand(depot, vehicle_id, share_orders, CMD_CLONE_VEHICLE, NULL, &AIInstance::DoCommandReturnVehicleID)) return INVALID_VEHICLE;
00077 
00078   /* In case of test-mode, we return VehicleID 0 */
00079   return 0;
00080 }
00081 
00082 /* static */ bool AIVehicle::_MoveWagonInternal(VehicleID source_vehicle_id, int source_wagon, bool move_attached_wagons, int dest_vehicle_id, int dest_wagon)
00083 {
00084   EnforcePrecondition(false, IsValidVehicle(source_vehicle_id) && source_wagon < GetNumWagons(source_vehicle_id));
00085   EnforcePrecondition(false, dest_vehicle_id == -1 || (IsValidVehicle(dest_vehicle_id) && dest_wagon < GetNumWagons(dest_vehicle_id)));
00086   EnforcePrecondition(false, ::GetVehicle(source_vehicle_id)->type == VEH_TRAIN);
00087   EnforcePrecondition(false, dest_vehicle_id == -1 || ::GetVehicle(dest_vehicle_id)->type == VEH_TRAIN);
00088 
00089   const Vehicle *v = ::GetVehicle(source_vehicle_id);
00090   while (source_wagon-- > 0) v = GetNextUnit(v);
00091   const Vehicle *w = NULL;
00092   if (dest_vehicle_id != -1) {
00093     w = ::GetVehicle(dest_vehicle_id);
00094     while (dest_wagon-- > 0) w = GetNextUnit(w);
00095   }
00096 
00097   return AIObject::DoCommand(0, v->index | ((w == NULL ? INVALID_VEHICLE : w->index) << 16), move_attached_wagons ? 1 : 0, CMD_MOVE_RAIL_VEHICLE);
00098 }
00099 
00100 /* static */ bool AIVehicle::MoveWagon(VehicleID source_vehicle_id, int source_wagon, int dest_vehicle_id, int dest_wagon)
00101 {
00102   return _MoveWagonInternal(source_vehicle_id, source_wagon, false, dest_vehicle_id, dest_wagon);
00103 }
00104 
00105 /* static */ bool AIVehicle::MoveWagonChain(VehicleID source_vehicle_id, int source_wagon, int dest_vehicle_id, int dest_wagon)
00106 {
00107   return _MoveWagonInternal(source_vehicle_id, source_wagon, true, dest_vehicle_id, dest_wagon);
00108 }
00109 
00110 /* static */ int AIVehicle::GetRefitCapacity(VehicleID vehicle_id, CargoID cargo)
00111 {
00112   if (!IsValidVehicle(vehicle_id)) return -1;
00113   if (!AICargo::IsValidCargo(cargo)) return -1;
00114 
00115   CommandCost res = ::DoCommand(0, vehicle_id, cargo, DC_QUERY_COST, GetCmdRefitVeh(::GetVehicle(vehicle_id)));
00116   return CmdSucceeded(res) ? _returned_refit_capacity : -1;
00117 }
00118 
00119 /* static */ bool AIVehicle::RefitVehicle(VehicleID vehicle_id, CargoID cargo)
00120 {
00121   EnforcePrecondition(false, IsValidVehicle(vehicle_id) && AICargo::IsValidCargo(cargo));
00122 
00123   return AIObject::DoCommand(0, vehicle_id, cargo, GetCmdRefitVeh(::GetVehicle(vehicle_id)));
00124 }
00125 
00126 
00127 /* static */ bool AIVehicle::SellVehicle(VehicleID vehicle_id)
00128 {
00129   EnforcePrecondition(false, IsValidVehicle(vehicle_id));
00130 
00131   const Vehicle *v = ::GetVehicle(vehicle_id);
00132   return AIObject::DoCommand(0, vehicle_id, v->type == VEH_TRAIN ? 1 : 0, GetCmdSellVeh(v));
00133 }
00134 
00135 /* static */ bool AIVehicle::_SellWagonInternal(VehicleID vehicle_id, int wagon, bool sell_attached_wagons)
00136 {
00137   EnforcePrecondition(false, IsValidVehicle(vehicle_id) && wagon < GetNumWagons(vehicle_id));
00138   EnforcePrecondition(false, ::GetVehicle(vehicle_id)->type == VEH_TRAIN);
00139 
00140   const Vehicle *v = ::GetVehicle(vehicle_id);
00141   while (wagon-- > 0) v = GetNextUnit(v);
00142 
00143   return AIObject::DoCommand(0, v->index, sell_attached_wagons ? 1 : 0, CMD_SELL_RAIL_WAGON);
00144 }
00145 
00146 /* static */ bool AIVehicle::SellWagon(VehicleID vehicle_id, int wagon)
00147 {
00148   return _SellWagonInternal(vehicle_id, wagon, false);
00149 }
00150 
00151 /* static */ bool AIVehicle::SellWagonChain(VehicleID vehicle_id, int wagon)
00152 {
00153   return _SellWagonInternal(vehicle_id, wagon, true);
00154 }
00155 
00156 /* static */ bool AIVehicle::SendVehicleToDepot(VehicleID vehicle_id)
00157 {
00158   EnforcePrecondition(false, IsValidVehicle(vehicle_id));
00159 
00160   return AIObject::DoCommand(0, vehicle_id, 0, GetCmdSendToDepot(::GetVehicle(vehicle_id)));
00161 }
00162 
00163 /* static */ bool AIVehicle::SendVehicleToDepotForServicing(VehicleID vehicle_id)
00164 {
00165   EnforcePrecondition(false, IsValidVehicle(vehicle_id));
00166 
00167   return AIObject::DoCommand(0, vehicle_id, DEPOT_SERVICE, GetCmdSendToDepot(::GetVehicle(vehicle_id)));
00168 }
00169 
00170 /* static */ bool AIVehicle::IsInDepot(VehicleID vehicle_id)
00171 {
00172   if (!IsValidVehicle(vehicle_id)) return false;
00173   return ::GetVehicle(vehicle_id)->IsInDepot();
00174 }
00175 
00176 /* static */ bool AIVehicle::IsStoppedInDepot(VehicleID vehicle_id)
00177 {
00178   if (!IsValidVehicle(vehicle_id)) return false;
00179   return ::GetVehicle(vehicle_id)->IsStoppedInDepot();
00180 }
00181 
00182 /* static */ bool AIVehicle::StartStopVehicle(VehicleID vehicle_id)
00183 {
00184   EnforcePrecondition(false, IsValidVehicle(vehicle_id));
00185 
00186   return AIObject::DoCommand(0, vehicle_id, 0, CMD_START_STOP_VEHICLE);
00187 }
00188 
00189 /* static */ bool AIVehicle::SkipToVehicleOrder(VehicleID vehicle_id, AIOrder::OrderPosition order_position)
00190 {
00191   return AIOrder::SkipToOrder(vehicle_id, order_position);
00192 }
00193 
00194 /* static */ bool AIVehicle::ReverseVehicle(VehicleID vehicle_id)
00195 {
00196   EnforcePrecondition(false, IsValidVehicle(vehicle_id));
00197   EnforcePrecondition(false, ::GetVehicle(vehicle_id)->type == VEH_ROAD || ::GetVehicle(vehicle_id)->type == VEH_TRAIN);
00198 
00199   switch (::GetVehicle(vehicle_id)->type) {
00200     case VEH_ROAD: return AIObject::DoCommand(0, vehicle_id, 0, CMD_TURN_ROADVEH);
00201     case VEH_TRAIN: return AIObject::DoCommand(0, vehicle_id, 0, CMD_REVERSE_TRAIN_DIRECTION);
00202     default: NOT_REACHED();
00203   }
00204 }
00205 
00206 /* static */ bool AIVehicle::SetName(VehicleID vehicle_id, const char *name)
00207 {
00208   EnforcePrecondition(false, IsValidVehicle(vehicle_id));
00209   EnforcePrecondition(false, !::StrEmpty(name));
00210   EnforcePreconditionCustomError(false, ::strlen(name) < MAX_LENGTH_VEHICLE_NAME_BYTES, AIError::ERR_PRECONDITION_STRING_TOO_LONG);
00211 
00212   return AIObject::DoCommand(0, vehicle_id, 0, CMD_RENAME_VEHICLE, name);
00213 }
00214 
00215 /* static */ TileIndex AIVehicle::GetLocation(VehicleID vehicle_id)
00216 {
00217   if (!IsValidVehicle(vehicle_id)) return INVALID_TILE;
00218 
00219   const Vehicle *v = ::GetVehicle(vehicle_id);
00220   if (v->type == VEH_AIRCRAFT) {
00221     uint x = Clamp(v->x_pos / TILE_SIZE, 0, ::MapSizeX() - 2);
00222     uint y = Clamp(v->y_pos / TILE_SIZE, 0, ::MapSizeY() - 2);
00223     return ::TileXY(x, y);
00224   }
00225 
00226   return v->tile;
00227 }
00228 
00229 /* static */ EngineID AIVehicle::GetEngineType(VehicleID vehicle_id)
00230 {
00231   if (!IsValidVehicle(vehicle_id)) return INVALID_ENGINE;
00232 
00233   return ::GetVehicle(vehicle_id)->engine_type;
00234 }
00235 
00236 /* static */ EngineID AIVehicle::GetWagonEngineType(VehicleID vehicle_id, int wagon)
00237 {
00238   if (!IsValidVehicle(vehicle_id)) return INVALID_ENGINE;
00239   if (wagon >= GetNumWagons(vehicle_id)) return INVALID_ENGINE;
00240 
00241   const Vehicle *v = ::GetVehicle(vehicle_id);
00242   if (v->type == VEH_TRAIN) {
00243     while (wagon-- > 0) v = GetNextUnit(v);
00244   }
00245   return v->engine_type;
00246 }
00247 
00248 /* static */ int32 AIVehicle::GetUnitNumber(VehicleID vehicle_id)
00249 {
00250   if (!IsValidVehicle(vehicle_id)) return -1;
00251 
00252   return ::GetVehicle(vehicle_id)->unitnumber;
00253 }
00254 
00255 /* static */ char *AIVehicle::GetName(VehicleID vehicle_id)
00256 {
00257   if (!IsValidVehicle(vehicle_id)) return NULL;
00258 
00259   static const int len = 64;
00260   char *vehicle_name = MallocT<char>(len);
00261 
00262   ::SetDParam(0, vehicle_id);
00263   ::GetString(vehicle_name, STR_VEHICLE_NAME, &vehicle_name[len - 1]);
00264   return vehicle_name;
00265 }
00266 
00267 /* static */ int32 AIVehicle::GetAge(VehicleID vehicle_id)
00268 {
00269   if (!IsValidVehicle(vehicle_id)) return -1;
00270 
00271   return ::GetVehicle(vehicle_id)->age;
00272 }
00273 
00274 /* static */ int32 AIVehicle::GetWagonAge(VehicleID vehicle_id, int wagon)
00275 {
00276   if (!IsValidVehicle(vehicle_id)) return -1;
00277   if (wagon >= GetNumWagons(vehicle_id)) return -1;
00278 
00279   const Vehicle *v = ::GetVehicle(vehicle_id);
00280   if (v->type == VEH_TRAIN) {
00281     while (wagon-- > 0) v = GetNextUnit(v);
00282   }
00283   return v->age;
00284 }
00285 
00286 /* static */ int32 AIVehicle::GetMaxAge(VehicleID vehicle_id)
00287 {
00288   if (!IsValidVehicle(vehicle_id)) return -1;
00289 
00290   return ::GetVehicle(vehicle_id)->max_age;
00291 }
00292 
00293 /* static */ int32 AIVehicle::GetAgeLeft(VehicleID vehicle_id)
00294 {
00295   if (!IsValidVehicle(vehicle_id)) return -1;
00296 
00297   return ::GetVehicle(vehicle_id)->max_age - ::GetVehicle(vehicle_id)->age;
00298 }
00299 
00300 /* static */ int32 AIVehicle::GetCurrentSpeed(VehicleID vehicle_id)
00301 {
00302   if (!IsValidVehicle(vehicle_id)) return -1;
00303 
00304   return ::GetVehicle(vehicle_id)->GetDisplaySpeed(); // km-ish/h
00305 }
00306 
00307 /* static */ AIVehicle::VehicleState AIVehicle::GetState(VehicleID vehicle_id)
00308 {
00309   if (!IsValidVehicle(vehicle_id)) return AIVehicle::VS_INVALID;
00310 
00311   const Vehicle *v = ::GetVehicle(vehicle_id);
00312   byte vehstatus = v->vehstatus;
00313 
00314   if (vehstatus & ::VS_CRASHED) return AIVehicle::VS_CRASHED;
00315   if (v->breakdown_ctr != 0) return AIVehicle::VS_BROKEN;
00316   if (v->IsStoppedInDepot()) return AIVehicle::VS_IN_DEPOT;
00317   if (vehstatus & ::VS_STOPPED) return AIVehicle::VS_STOPPED;
00318   if (v->current_order.IsType(OT_LOADING)) return AIVehicle::VS_AT_STATION;
00319   return AIVehicle::VS_RUNNING;
00320 }
00321 
00322 /* static */ Money AIVehicle::GetRunningCost(VehicleID vehicle_id)
00323 {
00324   if (!IsValidVehicle(vehicle_id)) return -1;
00325 
00326   return ::GetVehicle(vehicle_id)->GetRunningCost() >> 8;
00327 }
00328 
00329 /* static */ Money AIVehicle::GetProfitThisYear(VehicleID vehicle_id)
00330 {
00331   if (!IsValidVehicle(vehicle_id)) return -1;
00332 
00333   return ::GetVehicle(vehicle_id)->GetDisplayProfitThisYear();
00334 }
00335 
00336 /* static */ Money AIVehicle::GetProfitLastYear(VehicleID vehicle_id)
00337 {
00338   if (!IsValidVehicle(vehicle_id)) return -1;
00339 
00340   return ::GetVehicle(vehicle_id)->GetDisplayProfitLastYear();
00341 }
00342 
00343 /* static */ Money AIVehicle::GetCurrentValue(VehicleID vehicle_id)
00344 {
00345   if (!IsValidVehicle(vehicle_id)) return -1;
00346 
00347   return ::GetVehicle(vehicle_id)->value;
00348 }
00349 
00350 /* static */ AIVehicle::VehicleType AIVehicle::GetVehicleType(VehicleID vehicle_id)
00351 {
00352   if (!IsValidVehicle(vehicle_id)) return VT_INVALID;
00353 
00354   switch (::GetVehicle(vehicle_id)->type) {
00355     case VEH_ROAD:     return VT_ROAD;
00356     case VEH_TRAIN:    return VT_RAIL;
00357     case VEH_SHIP:     return VT_WATER;
00358     case VEH_AIRCRAFT: return VT_AIR;
00359     default:           return VT_INVALID;
00360   }
00361 }
00362 
00363 /* static */ AIRoad::RoadType AIVehicle::GetRoadType(VehicleID vehicle_id)
00364 {
00365   if (!IsValidVehicle(vehicle_id)) return AIRoad::ROADTYPE_INVALID;
00366   if (GetVehicleType(vehicle_id) != VT_ROAD) return AIRoad::ROADTYPE_INVALID;
00367 
00368   return (AIRoad::RoadType)::GetVehicle(vehicle_id)->u.road.roadtype;
00369 }
00370 
00371 /* static */ int32 AIVehicle::GetCapacity(VehicleID vehicle_id, CargoID cargo)
00372 {
00373   if (!IsValidVehicle(vehicle_id)) return -1;
00374   if (!AICargo::IsValidCargo(cargo)) return -1;
00375 
00376   uint32 amount = 0;
00377   for (const Vehicle *v = ::GetVehicle(vehicle_id); v != NULL; v = v->Next()) {
00378     if (v->cargo_type == cargo) amount += v->cargo_cap;
00379   }
00380 
00381   return amount;
00382 }
00383 
00384 /* static */ int32 AIVehicle::GetCargoLoad(VehicleID vehicle_id, CargoID cargo)
00385 {
00386   if (!IsValidVehicle(vehicle_id)) return -1;
00387   if (!AICargo::IsValidCargo(cargo)) return -1;
00388 
00389   uint32 amount = 0;
00390   for (const Vehicle *v = ::GetVehicle(vehicle_id); v != NULL; v = v->Next()) {
00391     if (v->cargo_type == cargo) amount += v->cargo.Count();
00392   }
00393 
00394   return amount;
00395 }
00396 
00397 /* static */ GroupID AIVehicle::GetGroupID(VehicleID vehicle_id)
00398 {
00399   if (!IsValidVehicle(vehicle_id)) return AIGroup::GROUP_INVALID;
00400 
00401   return ::GetVehicle(vehicle_id)->group_id;
00402 }
00403 
00404 /* static */ bool AIVehicle::IsArticulated(VehicleID vehicle_id)
00405 {
00406   if (!IsValidVehicle(vehicle_id)) return false;
00407   if (GetVehicleType(vehicle_id) != VT_ROAD && GetVehicleType(vehicle_id) != VT_RAIL) return false;
00408 
00409   const Vehicle *v = ::GetVehicle(vehicle_id);
00410   switch (v->type) {
00411     case VEH_ROAD: return RoadVehHasArticPart(v);
00412     case VEH_TRAIN: return EngineHasArticPart(v);
00413     default: NOT_REACHED();
00414   }
00415 }
00416 
00417 /* static */ bool AIVehicle::HasSharedOrders(VehicleID vehicle_id)
00418 {
00419   if (!IsValidVehicle(vehicle_id)) return false;
00420 
00421   Vehicle *v = ::GetVehicle(vehicle_id);
00422   return v->orders.list != NULL && v->orders.list->GetNumVehicles() > 1;
00423 }
00424 
00425 /* static */ int AIVehicle::GetReliability(VehicleID vehicle_id)
00426 {
00427   if (!IsValidVehicle(vehicle_id)) return -1;
00428 
00429   const Vehicle *v = ::GetVehicle(vehicle_id);
00430   return v->reliability * 100 >> 16;
00431 }

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