ai_order.cpp

Go to the documentation of this file.
00001 /* $Id: ai_order.cpp 16248 2009-05-06 23:21:43Z rubidium $ */
00002 
00005 #include "ai_order.hpp"
00006 #include "ai_vehicle.hpp"
00007 #include "ai_log.hpp"
00008 #include "../ai_instance.hpp"
00009 #include "../../debug.h"
00010 #include "../../vehicle_base.h"
00011 #include "../../depot_base.h"
00012 #include "../../station_map.h"
00013 #include "../../waypoint.h"
00014 
00020 static OrderType GetOrderTypeByTile(TileIndex t)
00021 {
00022   if (!::IsValidTile(t)) return OT_END;
00023 
00024   switch (::GetTileType(t)) {
00025     default: break;
00026     case MP_STATION:
00027       if (IsHangar(t)) return OT_GOTO_DEPOT;
00028       return OT_GOTO_STATION;
00029       break;
00030     case MP_WATER:   if (::IsShipDepot(t)) return OT_GOTO_DEPOT; break;
00031     case MP_ROAD:    if (::GetRoadTileType(t) == ROAD_TILE_DEPOT) return OT_GOTO_DEPOT; break;
00032     case MP_RAILWAY:
00033       switch (::GetRailTileType(t)) {
00034         case RAIL_TILE_DEPOT:    return OT_GOTO_DEPOT;
00035         case RAIL_TILE_WAYPOINT: return OT_GOTO_WAYPOINT;
00036         default: break;
00037       }
00038       break;
00039   }
00040 
00041   return OT_END;
00042 }
00043 
00044 /* static */ bool AIOrder::IsValidVehicleOrder(VehicleID vehicle_id, OrderPosition order_position)
00045 {
00046   return AIVehicle::IsValidVehicle(vehicle_id) && order_position >= 0 && (order_position < ::GetVehicle(vehicle_id)->GetNumOrders() || order_position == ORDER_CURRENT);
00047 }
00048 
00054 static const Order *ResolveOrder(VehicleID vehicle_id, AIOrder::OrderPosition order_position)
00055 {
00056   const Vehicle *v = ::GetVehicle(vehicle_id);
00057   if (order_position == AIOrder::ORDER_CURRENT) {
00058     const Order *order = &v->current_order;
00059     if (order->GetType() == OT_GOTO_DEPOT && !(order->GetDepotOrderType() & ODTFB_PART_OF_ORDERS)) return order;
00060     order_position = AIOrder::ResolveOrderPosition(vehicle_id, order_position);
00061     if (order_position == AIOrder::ORDER_INVALID) return NULL;
00062   }
00063   return ::GetVehicleOrder(v, order_position);
00064 }
00065 
00066 /* static */ bool AIOrder::IsGotoStationOrder(VehicleID vehicle_id, OrderPosition order_position)
00067 {
00068   if (!IsValidVehicleOrder(vehicle_id, order_position)) return false;
00069 
00070   const Order *order = ::ResolveOrder(vehicle_id, order_position);
00071   return order != NULL && order->GetType() == OT_GOTO_STATION;
00072 }
00073 
00074 /* static */ bool AIOrder::IsGotoDepotOrder(VehicleID vehicle_id, OrderPosition order_position)
00075 {
00076   if (!IsValidVehicleOrder(vehicle_id, order_position)) return false;
00077 
00078   const Order *order = ::ResolveOrder(vehicle_id, order_position);
00079   return order != NULL && order->GetType() == OT_GOTO_DEPOT;
00080 }
00081 
00082 /* static */ bool AIOrder::IsGotoWaypointOrder(VehicleID vehicle_id, OrderPosition order_position)
00083 {
00084   if (!IsValidVehicleOrder(vehicle_id, order_position)) return false;
00085 
00086   const Order *order = ::ResolveOrder(vehicle_id, order_position);
00087   return order != NULL && order->GetType() == OT_GOTO_WAYPOINT;
00088 }
00089 
00090 /* static */ bool AIOrder::IsConditionalOrder(VehicleID vehicle_id, OrderPosition order_position)
00091 {
00092   if (order_position == ORDER_CURRENT) return false;
00093   if (!IsValidVehicleOrder(vehicle_id, order_position)) return false;
00094 
00095   const Order *order = ::GetVehicleOrder(GetVehicle(vehicle_id), order_position);
00096   return order->GetType() == OT_CONDITIONAL;
00097 }
00098 
00099 /* static */ bool AIOrder::IsCurrentOrderPartOfOrderList(VehicleID vehicle_id)
00100 {
00101   if (AIVehicle::IsValidVehicle(vehicle_id)) return false;
00102   if (GetOrderCount(vehicle_id) == 0) return false;
00103 
00104   const Order *order = &::GetVehicle(vehicle_id)->current_order;
00105   if (order->GetType() != OT_GOTO_DEPOT) return true;
00106   return (order->GetDepotOrderType() & ODTFB_PART_OF_ORDERS) != 0;
00107 }
00108 
00109 /* static */ AIOrder::OrderPosition AIOrder::ResolveOrderPosition(VehicleID vehicle_id, OrderPosition order_position)
00110 {
00111   if (!AIVehicle::IsValidVehicle(vehicle_id)) return ORDER_INVALID;
00112 
00113   if (order_position == ORDER_CURRENT) return (AIOrder::OrderPosition)::GetVehicle(vehicle_id)->cur_order_index;
00114   return (order_position >= 0 && order_position < ::GetVehicle(vehicle_id)->GetNumOrders()) ? order_position : ORDER_INVALID;
00115 }
00116 
00117 
00118 /* static */ bool AIOrder::AreOrderFlagsValid(TileIndex destination, AIOrderFlags order_flags)
00119 {
00120   switch (::GetOrderTypeByTile(destination)) {
00121     case OT_GOTO_STATION:
00122       return ((order_flags & ~(AIOF_NON_STOP_FLAGS | AIOF_UNLOAD_FLAGS | AIOF_LOAD_FLAGS)) == 0) &&
00123           /* Test the different mutual exclusive flags. */
00124           (((order_flags & AIOF_TRANSFER)      == 0) || ((order_flags & AIOF_UNLOAD)    == 0)) &&
00125           (((order_flags & AIOF_TRANSFER)      == 0) || ((order_flags & AIOF_NO_UNLOAD) == 0)) &&
00126           (((order_flags & AIOF_UNLOAD)        == 0) || ((order_flags & AIOF_NO_UNLOAD) == 0)) &&
00127           (((order_flags & AIOF_UNLOAD)        == 0) || ((order_flags & AIOF_NO_UNLOAD) == 0)) &&
00128           (((order_flags & AIOF_NO_UNLOAD)     == 0) || ((order_flags & AIOF_NO_LOAD)   == 0)) &&
00129           (((order_flags & AIOF_FULL_LOAD_ANY) == 0) || ((order_flags & AIOF_NO_LOAD)   == 0));
00130 
00131     case OT_GOTO_DEPOT:
00132       return ((order_flags & ~(AIOF_NON_STOP_FLAGS | AIOF_DEPOT_FLAGS)) == 0) &&
00133           (((order_flags & AIOF_SERVICE_IF_NEEDED) == 0) || ((order_flags & AIOF_STOP_IN_DEPOT) == 0));
00134 
00135     case OT_GOTO_WAYPOINT: return (order_flags & ~(AIOF_NON_STOP_FLAGS)) == 0;
00136     default:               return false;
00137   }
00138 }
00139 
00140 /* static */ bool AIOrder::IsValidConditionalOrder(OrderCondition condition, CompareFunction compare)
00141 {
00142   switch (condition) {
00143     case OC_LOAD_PERCENTAGE:
00144     case OC_RELIABILITY:
00145     case OC_MAX_SPEED:
00146     case OC_AGE:
00147       return compare >= CF_EQUALS && compare <= CF_MORE_EQUALS;
00148 
00149     case OC_REQUIRES_SERVICE:
00150       return compare == CF_IS_TRUE || compare == CF_IS_FALSE;
00151 
00152     case OC_UNCONDITIONALLY:
00153       return true;
00154 
00155     default: return false;
00156   }
00157 }
00158 
00159 /* static */ int32 AIOrder::GetOrderCount(VehicleID vehicle_id)
00160 {
00161   return AIVehicle::IsValidVehicle(vehicle_id) ? ::GetVehicle(vehicle_id)->GetNumOrders() : -1;
00162 }
00163 
00164 /* static */ TileIndex AIOrder::GetOrderDestination(VehicleID vehicle_id, OrderPosition order_position)
00165 {
00166   if (!IsValidVehicleOrder(vehicle_id, order_position)) return INVALID_TILE;
00167 
00168   const Order *order = ::ResolveOrder(vehicle_id, order_position);
00169   if (order == NULL || order->GetType() == OT_CONDITIONAL) return INVALID_TILE;
00170   const Vehicle *v = ::GetVehicle(vehicle_id);
00171 
00172   switch (order->GetType()) {
00173     case OT_GOTO_DEPOT: {
00174       if (v->type != VEH_AIRCRAFT) return ::GetDepot(order->GetDestination())->xy;
00175       /* Aircraft's hangars are referenced by StationID, not DepotID */
00176       const Station *st = ::GetStation(order->GetDestination());
00177       const AirportFTAClass *airport = st->Airport();
00178       if (airport == NULL || airport->nof_depots == 0) return INVALID_TILE;
00179       return st->airport_tile + ::ToTileIndexDiff(st->Airport()->airport_depots[0]);
00180     }
00181 
00182     case OT_GOTO_STATION: {
00183       const Station *st = ::GetStation(order->GetDestination());
00184       if (st->train_tile != INVALID_TILE) {
00185         for (uint i = 0; i < st->trainst_w; i++) {
00186           TileIndex t = st->train_tile + TileDiffXY(i, 0);
00187           if (st->TileBelongsToRailStation(t)) return t;
00188         }
00189       } else if (st->dock_tile != INVALID_TILE) {
00190         return st->dock_tile;
00191       } else if (st->bus_stops != NULL) {
00192         return st->bus_stops->xy;
00193       } else if (st->truck_stops != NULL) {
00194         return st->truck_stops->xy;
00195       } else if (st->airport_tile != INVALID_TILE) {
00196         const AirportFTAClass *fta = st->Airport();
00197         BEGIN_TILE_LOOP(tile, fta->size_x, fta->size_y, st->airport_tile) {
00198           if (!::IsHangar(tile)) return tile;
00199         } END_TILE_LOOP(tile, fta->size_x, fta->size_y, st->airport_tile)
00200       }
00201       return INVALID_TILE;
00202     }
00203     case OT_GOTO_WAYPOINT: return ::GetWaypoint(order->GetDestination())->xy;
00204     default:               return INVALID_TILE;
00205   }
00206 }
00207 
00208 /* static */ AIOrder::AIOrderFlags AIOrder::GetOrderFlags(VehicleID vehicle_id, OrderPosition order_position)
00209 {
00210   if (!IsValidVehicleOrder(vehicle_id, order_position)) return AIOF_INVALID;
00211 
00212   const Order *order = ::ResolveOrder(vehicle_id, order_position);
00213   if (order == NULL || order->GetType() == OT_CONDITIONAL) return AIOF_INVALID;
00214 
00215   AIOrderFlags order_flags = AIOF_NONE;
00216   order_flags |= (AIOrderFlags)order->GetNonStopType();
00217   switch (order->GetType()) {
00218     case OT_GOTO_DEPOT:
00219       if (order->GetDepotOrderType() & ODTFB_SERVICE) order_flags |= AIOF_SERVICE_IF_NEEDED;
00220       if (order->GetDepotActionType() & ODATFB_HALT) order_flags |= AIOF_STOP_IN_DEPOT;
00221       break;
00222 
00223     case OT_GOTO_STATION:
00224       order_flags |= (AIOrderFlags)(order->GetLoadType()   << 5);
00225       order_flags |= (AIOrderFlags)(order->GetUnloadType() << 2);
00226       break;
00227 
00228     default: break;
00229   }
00230 
00231   return order_flags;
00232 }
00233 
00234 /* static */ AIOrder::OrderPosition AIOrder::GetOrderJumpTo(VehicleID vehicle_id, OrderPosition order_position)
00235 {
00236   if (!IsValidVehicleOrder(vehicle_id, order_position)) return ORDER_INVALID;
00237   if (order_position == ORDER_CURRENT || !IsConditionalOrder(vehicle_id, order_position)) return ORDER_INVALID;
00238 
00239   const Order *order = ::GetVehicleOrder(GetVehicle(vehicle_id), order_position);
00240   return (OrderPosition)order->GetConditionSkipToOrder();
00241 }
00242 
00243 /* static */ AIOrder::OrderCondition AIOrder::GetOrderCondition(VehicleID vehicle_id, OrderPosition order_position)
00244 {
00245   if (!IsValidVehicleOrder(vehicle_id, order_position)) return OC_INVALID;
00246   if (order_position == ORDER_CURRENT || !IsConditionalOrder(vehicle_id, order_position)) return OC_INVALID;
00247 
00248   const Order *order = ::GetVehicleOrder(GetVehicle(vehicle_id), order_position);
00249   return (OrderCondition)order->GetConditionVariable();
00250 }
00251 
00252 /* static */ AIOrder::CompareFunction AIOrder::GetOrderCompareFunction(VehicleID vehicle_id, OrderPosition order_position)
00253 {
00254   if (!IsValidVehicleOrder(vehicle_id, order_position)) return CF_INVALID;
00255   if (order_position == ORDER_CURRENT || !IsConditionalOrder(vehicle_id, order_position)) return CF_INVALID;
00256 
00257   const Order *order = ::GetVehicleOrder(GetVehicle(vehicle_id), order_position);
00258   return (CompareFunction)order->GetConditionComparator();
00259 }
00260 
00261 /* static */ int32 AIOrder::GetOrderCompareValue(VehicleID vehicle_id, OrderPosition order_position)
00262 {
00263   if (!IsValidVehicleOrder(vehicle_id, order_position)) return -1;
00264   if (order_position == ORDER_CURRENT || !IsConditionalOrder(vehicle_id, order_position)) return -1;
00265 
00266   const Order *order = ::GetVehicleOrder(GetVehicle(vehicle_id), order_position);
00267   int32 value = order->GetConditionValue();
00268   if (order->GetConditionVariable() == OCV_MAX_SPEED) value = value * 16 / 10;
00269   return value;
00270 }
00271 
00272 /* static */ bool AIOrder::SetOrderJumpTo(VehicleID vehicle_id, OrderPosition order_position, OrderPosition jump_to)
00273 {
00274   EnforcePrecondition(false, IsValidVehicleOrder(vehicle_id, order_position));
00275   EnforcePrecondition(false, order_position != ORDER_CURRENT && IsConditionalOrder(vehicle_id, order_position));
00276   EnforcePrecondition(false, IsValidVehicleOrder(vehicle_id, jump_to) && jump_to != ORDER_CURRENT);
00277 
00278   return AIObject::DoCommand(0, vehicle_id | (order_position << 16), MOF_COND_DESTINATION | (jump_to << 4), CMD_MODIFY_ORDER);
00279 }
00280 
00281 /* static */ bool AIOrder::SetOrderCondition(VehicleID vehicle_id, OrderPosition order_position, OrderCondition condition)
00282 {
00283   EnforcePrecondition(false, IsValidVehicleOrder(vehicle_id, order_position));
00284   EnforcePrecondition(false, order_position != ORDER_CURRENT && IsConditionalOrder(vehicle_id, order_position));
00285   EnforcePrecondition(false, condition >= OC_LOAD_PERCENTAGE && condition <= OC_UNCONDITIONALLY);
00286 
00287   return AIObject::DoCommand(0, vehicle_id | (order_position << 16), MOF_COND_VARIABLE | (condition << 4), CMD_MODIFY_ORDER);
00288 }
00289 
00290 /* static */ bool AIOrder::SetOrderCompareFunction(VehicleID vehicle_id, OrderPosition order_position, CompareFunction compare)
00291 {
00292   EnforcePrecondition(false, IsValidVehicleOrder(vehicle_id, order_position));
00293   EnforcePrecondition(false, order_position != ORDER_CURRENT && IsConditionalOrder(vehicle_id, order_position));
00294   EnforcePrecondition(false, compare >= CF_EQUALS && compare <= CF_IS_FALSE);
00295 
00296   return AIObject::DoCommand(0, vehicle_id | (order_position << 16), MOF_COND_COMPARATOR | (compare << 4), CMD_MODIFY_ORDER);
00297 }
00298 
00299 /* static */ bool AIOrder::SetOrderCompareValue(VehicleID vehicle_id, OrderPosition order_position, int32 value)
00300 {
00301   EnforcePrecondition(false, IsValidVehicleOrder(vehicle_id, order_position));
00302   EnforcePrecondition(false, order_position != ORDER_CURRENT && IsConditionalOrder(vehicle_id, order_position));
00303   EnforcePrecondition(false, value >= 0 && value < 2048);
00304   if (GetOrderCondition(vehicle_id, order_position) == OC_MAX_SPEED) value = value * 10 / 16;
00305 
00306   return AIObject::DoCommand(0, vehicle_id | (order_position << 16), MOF_COND_VALUE | (value << 4), CMD_MODIFY_ORDER);
00307 }
00308 
00309 /* static */ bool AIOrder::AppendOrder(VehicleID vehicle_id, TileIndex destination, AIOrderFlags order_flags)
00310 {
00311   EnforcePrecondition(false, AIVehicle::IsValidVehicle(vehicle_id));
00312   EnforcePrecondition(false, AreOrderFlagsValid(destination, order_flags));
00313 
00314   return InsertOrder(vehicle_id, (AIOrder::OrderPosition)::GetVehicle(vehicle_id)->GetNumOrders(), destination, order_flags);
00315 }
00316 
00317 /* static */ bool AIOrder::AppendConditionalOrder(VehicleID vehicle_id, OrderPosition jump_to)
00318 {
00319   EnforcePrecondition(false, AIVehicle::IsValidVehicle(vehicle_id));
00320   EnforcePrecondition(false, IsValidVehicleOrder(vehicle_id, jump_to));
00321 
00322   return InsertConditionalOrder(vehicle_id, (AIOrder::OrderPosition)::GetVehicle(vehicle_id)->GetNumOrders(), jump_to);
00323 }
00324 
00325 /* static */ bool AIOrder::InsertOrder(VehicleID vehicle_id, OrderPosition order_position, TileIndex destination, AIOrder::AIOrderFlags order_flags)
00326 {
00327   /* IsValidVehicleOrder is not good enough because it does not allow appending. */
00328   if (order_position == ORDER_CURRENT) order_position = AIOrder::ResolveOrderPosition(vehicle_id, order_position);
00329 
00330   EnforcePrecondition(false, AIVehicle::IsValidVehicle(vehicle_id));
00331   EnforcePrecondition(false, order_position >= 0 && order_position <= ::GetVehicle(vehicle_id)->GetNumOrders());
00332   EnforcePrecondition(false, AreOrderFlagsValid(destination, order_flags));
00333 
00334   Order order;
00335   switch (::GetOrderTypeByTile(destination)) {
00336     case OT_GOTO_DEPOT: {
00337       OrderDepotTypeFlags odtf = (OrderDepotTypeFlags)(ODTFB_PART_OF_ORDERS | ((order_flags & AIOF_SERVICE_IF_NEEDED) ? ODTFB_SERVICE : 0));
00338       OrderDepotActionFlags odaf = (OrderDepotActionFlags)(ODATF_SERVICE_ONLY | ((order_flags & AIOF_STOP_IN_DEPOT) ? ODATFB_HALT : 0));
00339       OrderNonStopFlags onsf = (OrderNonStopFlags)((order_flags & AIOF_NON_STOP_INTERMEDIATE) ? ONSF_NO_STOP_AT_INTERMEDIATE_STATIONS : ONSF_STOP_EVERYWHERE);
00340       /* Check explicitly if the order is to a station (for aircraft) or
00341        * to a depot (other vehicle types). */
00342       if (::GetVehicle(vehicle_id)->type == VEH_AIRCRAFT) {
00343         if (!::IsTileType(destination, MP_STATION)) return false;
00344         order.MakeGoToDepot(::GetStationIndex(destination), odtf, onsf, odaf);
00345       } else {
00346         if (::IsTileType(destination, MP_STATION)) return false;
00347         order.MakeGoToDepot(::GetDepotByTile(destination)->index, odtf, onsf, odaf);
00348       }
00349       break;
00350     }
00351 
00352     case OT_GOTO_STATION:
00353       order.MakeGoToStation(::GetStationIndex(destination));
00354       order.SetLoadType((OrderLoadFlags)GB(order_flags, 5, 3));
00355       order.SetUnloadType((OrderUnloadFlags)GB(order_flags, 2, 3));
00356       break;
00357 
00358     case OT_GOTO_WAYPOINT:
00359       order.MakeGoToWaypoint(::GetWaypointIndex(destination));
00360       break;
00361 
00362     default:
00363       return false;
00364   }
00365 
00366   order.SetNonStopType((OrderNonStopFlags)GB(order_flags, 0, 2));
00367 
00368   return AIObject::DoCommand(0, vehicle_id | (order_position << 16), order.Pack(), CMD_INSERT_ORDER);
00369 }
00370 
00371 /* static */ bool AIOrder::InsertConditionalOrder(VehicleID vehicle_id, OrderPosition order_position, OrderPosition jump_to)
00372 {
00373   /* IsValidVehicleOrder is not good enough because it does not allow appending. */
00374   if (order_position == ORDER_CURRENT) order_position = AIOrder::ResolveOrderPosition(vehicle_id, order_position);
00375 
00376   EnforcePrecondition(false, AIVehicle::IsValidVehicle(vehicle_id));
00377   EnforcePrecondition(false, IsValidVehicleOrder(vehicle_id, jump_to));
00378 
00379   Order order;
00380   order.MakeConditional(jump_to);
00381 
00382   return AIObject::DoCommand(0, vehicle_id | (order_position << 16), order.Pack(), CMD_INSERT_ORDER);
00383 }
00384 
00385 /* static */ bool AIOrder::RemoveOrder(VehicleID vehicle_id, OrderPosition order_position)
00386 {
00387   order_position = AIOrder::ResolveOrderPosition(vehicle_id, order_position);
00388 
00389   EnforcePrecondition(false, IsValidVehicleOrder(vehicle_id, order_position));
00390 
00391   return AIObject::DoCommand(0, vehicle_id, order_position, CMD_DELETE_ORDER);
00392 }
00393 
00394 /* static */ bool AIOrder::SkipToOrder(VehicleID vehicle_id, OrderPosition next_order)
00395 {
00396   EnforcePrecondition(false, IsValidVehicleOrder(vehicle_id, next_order));
00397 
00398   return AIObject::DoCommand(0, vehicle_id, next_order, CMD_SKIP_TO_ORDER);
00399 }
00400 
00409 static void _DoCommandReturnSetOrderFlags(class AIInstance *instance)
00410 {
00411   AIObject::SetLastCommandRes(AIOrder::_SetOrderFlags());
00412   AIInstance::DoCommandReturn(instance);
00413 }
00414 
00415 /* static */ bool AIOrder::_SetOrderFlags()
00416 {
00417   /* Make sure we don't go into an infinite loop */
00418   int retry = AIObject::GetCallbackVariable(3) - 1;
00419   if (retry < 0) {
00420     DEBUG(ai, 0, "Possible infinite loop in SetOrderFlags() detected");
00421     return false;
00422   }
00423   AIObject::SetCallbackVariable(3, retry);
00424 
00425   VehicleID vehicle_id = (VehicleID)AIObject::GetCallbackVariable(0);
00426   OrderPosition order_position = (OrderPosition)AIObject::GetCallbackVariable(1);
00427   AIOrderFlags order_flags = (AIOrderFlags)AIObject::GetCallbackVariable(2);
00428 
00429   order_position = AIOrder::ResolveOrderPosition(vehicle_id, order_position);
00430 
00431   EnforcePrecondition(false, IsValidVehicleOrder(vehicle_id, order_position));
00432   EnforcePrecondition(false, AreOrderFlagsValid(GetOrderDestination(vehicle_id, order_position), order_flags));
00433 
00434   const Order *order = ::GetVehicleOrder(GetVehicle(vehicle_id), order_position);
00435 
00436   AIOrderFlags current = GetOrderFlags(vehicle_id, order_position);
00437 
00438   if ((current & AIOF_NON_STOP_FLAGS) != (order_flags & AIOF_NON_STOP_FLAGS)) {
00439     return AIObject::DoCommand(0, vehicle_id | (order_position << 16), (order_flags & AIOF_NON_STOP_FLAGS) << 4 | MOF_NON_STOP, CMD_MODIFY_ORDER, NULL, &_DoCommandReturnSetOrderFlags);
00440   }
00441 
00442   switch (order->GetType()) {
00443     case OT_GOTO_DEPOT:
00444       if ((current & AIOF_DEPOT_FLAGS) != (order_flags & AIOF_DEPOT_FLAGS)) {
00445         uint data = DA_ALWAYS_GO;
00446         if (order_flags & AIOF_SERVICE_IF_NEEDED) data = DA_SERVICE;
00447         if (order_flags & AIOF_STOP_IN_DEPOT) data = DA_STOP;
00448         return AIObject::DoCommand(0, vehicle_id | (order_position << 16), (data << 4) | MOF_DEPOT_ACTION, CMD_MODIFY_ORDER, NULL, &_DoCommandReturnSetOrderFlags);
00449       }
00450       break;
00451 
00452     case OT_GOTO_STATION:
00453       if ((current & AIOF_UNLOAD_FLAGS) != (order_flags & AIOF_UNLOAD_FLAGS)) {
00454         return AIObject::DoCommand(0, vehicle_id | (order_position << 16), (order_flags & AIOF_UNLOAD_FLAGS) << 2 | MOF_UNLOAD, CMD_MODIFY_ORDER, NULL, &_DoCommandReturnSetOrderFlags);
00455       }
00456       if ((current & AIOF_LOAD_FLAGS) != (order_flags & AIOF_LOAD_FLAGS)) {
00457         return AIObject::DoCommand(0, vehicle_id | (order_position << 16), (order_flags & AIOF_LOAD_FLAGS) >> 1 | MOF_LOAD, CMD_MODIFY_ORDER, NULL, &_DoCommandReturnSetOrderFlags);
00458       }
00459       break;
00460 
00461     default: break;
00462   }
00463 
00464   assert(GetOrderFlags(vehicle_id, order_position) == order_flags);
00465 
00466   return true;
00467 }
00468 
00469 /* static */ bool AIOrder::SetOrderFlags(VehicleID vehicle_id, OrderPosition order_position, AIOrder::AIOrderFlags order_flags)
00470 {
00471   AIObject::SetCallbackVariable(0, vehicle_id);
00472   AIObject::SetCallbackVariable(1, order_position);
00473   AIObject::SetCallbackVariable(2, order_flags);
00474   /* In case another client(s) change orders at the same time we could
00475    * end in an infinite loop. This stops that from happening ever. */
00476   AIObject::SetCallbackVariable(3, 8);
00477   return AIOrder::_SetOrderFlags();
00478 }
00479 
00480 /* static */ bool AIOrder::ChangeOrder(VehicleID vehicle_id, OrderPosition order_position, AIOrder::AIOrderFlags order_flags)
00481 {
00482   AILog::Warning("AIOrder::ChangeOrder is deprecated and will be removed soon, please use AIOrder::SetOrderFlags instead.");
00483   return SetOrderFlags(vehicle_id, order_position, order_flags);
00484 }
00485 
00486 /* static */ bool AIOrder::MoveOrder(VehicleID vehicle_id, OrderPosition order_position_move, OrderPosition order_position_target)
00487 {
00488   order_position_move   = AIOrder::ResolveOrderPosition(vehicle_id, order_position_move);
00489   order_position_target = AIOrder::ResolveOrderPosition(vehicle_id, order_position_target);
00490 
00491   EnforcePrecondition(false, IsValidVehicleOrder(vehicle_id, order_position_move));
00492   EnforcePrecondition(false, IsValidVehicleOrder(vehicle_id, order_position_target));
00493 
00494   return AIObject::DoCommand(0, vehicle_id, order_position_move | (order_position_target << 16), CMD_MOVE_ORDER);
00495 }
00496 
00497 /* static */ bool AIOrder::CopyOrders(VehicleID vehicle_id, VehicleID main_vehicle_id)
00498 {
00499   EnforcePrecondition(false, AIVehicle::IsValidVehicle(vehicle_id));
00500   EnforcePrecondition(false, AIVehicle::IsValidVehicle(main_vehicle_id));
00501 
00502   return AIObject::DoCommand(0, vehicle_id | (main_vehicle_id << 16), CO_COPY, CMD_CLONE_ORDER);
00503 }
00504 
00505 /* static */ bool AIOrder::ShareOrders(VehicleID vehicle_id, VehicleID main_vehicle_id)
00506 {
00507   EnforcePrecondition(false, AIVehicle::IsValidVehicle(vehicle_id));
00508   EnforcePrecondition(false, AIVehicle::IsValidVehicle(main_vehicle_id));
00509 
00510   return AIObject::DoCommand(0, vehicle_id | (main_vehicle_id << 16), CO_SHARE, CMD_CLONE_ORDER);
00511 }
00512 
00513 /* static */ bool AIOrder::UnshareOrders(VehicleID vehicle_id)
00514 {
00515   EnforcePrecondition(false, AIVehicle::IsValidVehicle(vehicle_id));
00516 
00517   return AIObject::DoCommand(0, vehicle_id, CO_UNSHARE, CMD_CLONE_ORDER);
00518 }

Generated on Tue Jul 21 18:48:21 2009 for OpenTTD by  doxygen 1.5.6