(svn r12677) [NoAI] -Change [API CHANGE]: rework of the OrderFlags to support the new order possibilities in OpenTTD. As a result of this the following has changed:
* AIOF_UNLOAD and AIOF_TRANSFER cannot be used at the same time anymore. Use AIOF_NO_LOAD and AIOF_TRANSFER for the same result.
* AIOF_FULL_LOAD will now always full load the vehicle and not full load any when the corresponding patch setting has been set. Full load any can be achieved with AIOF_FULL_LOAD_ANY.
* AIOF_NON_STOP has been replaced by AIOF_NON_STOP_AT_INTERMEDIATE_STATIONS and AIOF_NON_STOP_AT_DESTINATION_STATION instead of determining the non-stop workings based on a patch setting.
--- a/src/ai/api/ai_order.cpp Sat Apr 12 21:38:49 2008 +0000
+++ b/src/ai/api/ai_order.cpp Sat Apr 12 22:28:07 2008 +0000
@@ -49,9 +49,18 @@
/* static */ bool AIOrder::AreOrderFlagsValid(TileIndex destination, AIOrderFlags order_flags)
{
switch (::GetOrderTypeByTile(destination)) {
- case OT_GOTO_DEPOT: return (order_flags & ~(AIOF_NON_STOP | AIOF_SERVICE_IF_NEEDED)) == 0;
- case OT_GOTO_STATION: return (order_flags & ~(AIOF_NON_STOP | AIOF_TRANSFER | AIOF_UNLOAD | AIOF_FULL_LOAD)) == 0 && ((order_flags & AIOF_UNLOAD) == 0 || (order_flags & AIOF_FULL_LOAD) == 0);
- case OT_GOTO_WAYPOINT: return (order_flags & ~(AIOF_NON_STOP)) == 0;
+ case OT_GOTO_STATION:
+ return ((order_flags & ~(AIOF_NON_STOP_FLAGS | AIOF_UNLOAD_FLAGS | AIOF_LOAD_FLAGS)) == 0) &&
+ /* Test the different mutual exclusive flags. */
+ (((order_flags & AIOF_TRANSFER) == 0) || ((order_flags & AIOF_UNLOAD) == 0)) &&
+ (((order_flags & AIOF_TRANSFER) == 0) || ((order_flags & AIOF_NO_UNLOAD) == 0)) &&
+ (((order_flags & AIOF_UNLOAD) == 0) || ((order_flags & AIOF_NO_UNLOAD) == 0)) &&
+ (((order_flags & AIOF_UNLOAD) == 0) || ((order_flags & AIOF_NO_UNLOAD) == 0)) &&
+ (((order_flags & AIOF_NO_UNLOAD) == 0) || ((order_flags & AIOF_NO_LOAD) == 0)) &&
+ (((order_flags & AIOF_FULL_LOAD_ANY) == 0) || ((order_flags & AIOF_NO_LOAD) == 0));
+
+ case OT_GOTO_DEPOT: return (order_flags & ~(AIOF_NON_STOP_FLAGS | AIOF_SERVICE_IF_NEEDED)) == 0;
+ case OT_GOTO_WAYPOINT: return (order_flags & ~(AIOF_NON_STOP_FLAGS)) == 0;
default: return false;
}
}
@@ -83,17 +92,16 @@
Order *order = ::GetVehicle(vehicle_id)->orders;
for (uint i = 0; i < order_id; i++) order = order->next;
- AIOrderFlags order_flags= AIOF_NONE;
- if (order->GetNonStopType() != ONSF_STOP_EVERYWHERE) order_flags |= AIOF_NON_STOP;
+ AIOrderFlags order_flags = AIOF_NONE;
+ order_flags |= (AIOrderFlags)order->GetNonStopType();
switch (order->GetType()) {
case OT_GOTO_DEPOT:
if (order->GetDepotOrderType() & ODTFB_SERVICE) order_flags |= AIOF_SERVICE_IF_NEEDED;
break;
case OT_GOTO_STATION:
- if (order->GetLoadType() & OLFB_FULL_LOAD) order_flags |= AIOF_FULL_LOAD;
- if (order->GetUnloadType() & OUFB_UNLOAD) order_flags |= AIOF_UNLOAD;
- if (order->GetUnloadType() & OUFB_TRANSFER) order_flags |= AIOF_TRANSFER;
+ order_flags |= (AIOrderFlags)(order->GetLoadType() << 5);
+ order_flags |= (AIOrderFlags)(order->GetUnloadType() << 2);
break;
default: break;
@@ -118,14 +126,13 @@
Order order;
switch (::GetOrderTypeByTile(destination)) {
case OT_GOTO_DEPOT:
- order.MakeGoToDepot(::GetDepotByTile(destination)->index, ODTFB_PART_OF_ORDERS);
- if (order_flags & AIOF_SERVICE_IF_NEEDED) order.SetDepotOrderType(ODTFB_SERVICE);
+ order.MakeGoToDepot(::GetDepotByTile(destination)->index, (OrderDepotTypeFlags)(ODTFB_PART_OF_ORDERS | ((order_flags & AIOF_SERVICE_IF_NEEDED) ? ODTFB_SERVICE : 0)));
break;
case OT_GOTO_STATION:
order.MakeGoToStation(::GetStationIndex(destination));
- if (order_flags & AIOF_FULL_LOAD) order.SetLoadType(OLFB_FULL_LOAD);
- order.SetUnloadType((OrderUnloadFlags)(((order_flags & AIOF_TRANSFER) ? OUFB_TRANSFER : 0) | ((order_flags & AIOF_UNLOAD) ? OUFB_UNLOAD : 0)));
+ order.SetLoadType((OrderLoadFlags)GB(order_flags, 5, 3));
+ order.SetUnloadType((OrderUnloadFlags)GB(order_flags, 2, 3));
break;
case OT_GOTO_WAYPOINT:
@@ -136,7 +143,7 @@
return false;
}
- if (order_flags & AIOF_NON_STOP) order.SetNonStopType(ONSF_NO_STOP_AT_DESTINATION_STATION);
+ order.SetNonStopType((OrderNonStopFlags)GB(order_flags, 0, 2));
return AIObject::DoCommand(0, vehicle_id | (order_id << 16), order.Pack(), CMD_INSERT_ORDER);
}
@@ -153,16 +160,41 @@
EnforcePrecondition(false, IsValidVehicleOrder(vehicle_id, order_id));
EnforcePrecondition(false, AreOrderFlagsValid(GetOrderDestination(vehicle_id, order_id), order_flags));
- for (;;) {
- /* Loop as long as there is a difference between the requested and
- * the current orders of the vehicle. */
- AIOrderFlags current = GetOrderFlags(vehicle_id, order_id);
- AIOrderFlags diff = current ^ order_flags;
- if (diff == 0) return true;
+ Order *order = ::GetVehicle(vehicle_id)->orders;
+ for (uint i = 0; i < order_id; i++) order = order->next;
- bool res = AIObject::DoCommand(0, vehicle_id | (order_id << 16), FIND_FIRST_BIT(diff), CMD_MODIFY_ORDER);
+ AIOrderFlags current = GetOrderFlags(vehicle_id, order_id);
+
+ if ((current & AIOF_NON_STOP_FLAGS) != (order_flags & AIOF_NON_STOP_FLAGS)) {
+ bool res = AIObject::DoCommand(0, vehicle_id | (order_id << 16), (order_flags & AIOF_NON_STOP_FLAGS) << 4 | MOF_NON_STOP, CMD_MODIFY_ORDER);
if (!res) return false;
}
+
+ switch (order->GetType()) {
+ case OT_GOTO_DEPOT:
+ if ((current & AIOF_SERVICE_IF_NEEDED) != (order_flags & AIOF_SERVICE_IF_NEEDED)) {
+ bool res = AIObject::DoCommand(0, vehicle_id | (order_id << 16), MOF_DEPOT_ACTION, CMD_MODIFY_ORDER);
+ if (!res) return false;
+ }
+ break;
+
+ case OT_GOTO_STATION:
+ if ((current & AIOF_UNLOAD_FLAGS) != (order_flags & AIOF_UNLOAD_FLAGS)) {
+ bool res = AIObject::DoCommand(0, vehicle_id | (order_id << 16), (order_flags & AIOF_UNLOAD_FLAGS) << 2 | MOF_UNLOAD, CMD_MODIFY_ORDER);
+ if (!res) return false;
+ }
+ if ((current & AIOF_LOAD_FLAGS) != (order_flags & AIOF_LOAD_FLAGS)) {
+ bool res = AIObject::DoCommand(0, vehicle_id | (order_id << 16), (order_flags & AIOF_LOAD_FLAGS) >> 1 | MOF_LOAD, CMD_MODIFY_ORDER);
+ if (!res) return false;
+ }
+ break;
+
+ default: break;
+ }
+
+ assert(GetOrderFlags(vehicle_id, order_id) == order_flags);
+
+ return true;
}
/* static */ bool AIOrder::MoveOrder(VehicleID vehicle_id, uint32 order_id_move, uint32 order_id_target)
--- a/src/ai/api/ai_order.hpp Sat Apr 12 21:38:49 2008 +0000
+++ b/src/ai/api/ai_order.hpp Sat Apr 12 22:28:07 2008 +0000
@@ -36,18 +36,34 @@
/** Just go to the station/depot, stop unload if possible and load if needed. */
AIOF_NONE = 0,
- /** Transfer instead of deliver the goods; only for stations. */
- AIOF_TRANSFER = 1 << 0,
- /** Always unload the vehicle; only for stations. Cannot be set when AIOF_FULL_LOAD is set. */
- AIOF_UNLOAD = 1 << 1,
- /** Wait till the the vehicle is fully loaded; only for stations. Cannot be set when AIOF_UNLOAD is set. */
- AIOF_FULL_LOAD = 1 << 2,
+ /** Do not stop at the stations that are passed when going to the destination. */
+ AIOF_NON_STOP_AT_INTERMEDIATE_STATIONS = 1 << 0,
+ /** Do not stop at the destionation station. */
+ AIOF_NON_STOP_AT_DESTINATION_STATION = 1 << 1,
+
+ /** Always unload the vehicle; only for stations. Cannot be set when AIOF_TRANSFER or AIOF_NO_UNLOAD is set. */
+ AIOF_UNLOAD = 1 << 2,
+ /** Transfer instead of deliver the goods; only for stations. Cannot be set when AIOF_UNLOAD or AIOF_NO_UNLOAD is set. */
+ AIOF_TRANSFER = 1 << 3,
+ /** Never unload the vehicle; only for stations. Cannot be set when AIOF_UNLOAD, AIOF_TRANSFER or AIOF_NO_LOAD is set. */
+ AIOF_NO_UNLOAD = 1 << 4,
+
+ /** Wait till the vehicle is fully loaded; only for stations. Cannot be set when AIOF_NO_LOAD is set. */
+ AIOF_FULL_LOAD = 2 << 5,
+ /** Wait till at least one cargo of the vehicle is fully loaded; only for stations. Cannot be set when AIOF_NO_LOAD is set. */
+ AIOF_FULL_LOAD_ANY = 3 << 5,
+ /** Do not load any cargo; only for stations. Cannot be set when AIOF_NO_UNLOAD, AIOF_FULL_LOAD or AIOF_FULL_LOAD_ANY is set. */
+ AIOF_NO_LOAD = 1 << 7,
/** Service the vehicle when needed, otherwise skip this order; only for depots. */
AIOF_SERVICE_IF_NEEDED = 1 << 2,
- /** Do not stop at the stations that are passed when going to the destination. */
- AIOF_NON_STOP = 1 << 3,
+ /** All flags related to non-stop settings. */
+ AIOF_NON_STOP_FLAGS = AIOF_NON_STOP_AT_INTERMEDIATE_STATIONS | AIOF_NON_STOP_AT_DESTINATION_STATION,
+ /** All flags related to unloading. */
+ AIOF_UNLOAD_FLAGS = AIOF_TRANSFER | AIOF_UNLOAD | AIOF_NO_UNLOAD,
+ /** All flags related to loading. */
+ AIOF_LOAD_FLAGS = AIOF_FULL_LOAD | AIOF_FULL_LOAD_ANY | AIOF_NO_LOAD,
/** For marking invalid order flags */
AIOF_INVALID = 0xFFFF,
--- a/src/ai/api/ai_order.hpp.sq Sat Apr 12 21:38:49 2008 +0000
+++ b/src/ai/api/ai_order.hpp.sq Sat Apr 12 22:28:07 2008 +0000
@@ -24,11 +24,18 @@
SQAIOrder.DefSQConst(engine, AIOrder::ERR_ORDER_TOO_MANY, "ERR_ORDER_TOO_MANY");
SQAIOrder.DefSQConst(engine, AIOrder::ERR_ORDER_TOO_FAR_AWAY_FROM_PREVIOUS_DESTINATION, "ERR_ORDER_TOO_FAR_AWAY_FROM_PREVIOUS_DESTINATION");
SQAIOrder.DefSQConst(engine, AIOrder::AIOF_NONE, "AIOF_NONE");
- SQAIOrder.DefSQConst(engine, AIOrder::AIOF_TRANSFER, "AIOF_TRANSFER");
+ SQAIOrder.DefSQConst(engine, AIOrder::AIOF_NON_STOP_AT_INTERMEDIATE_STATIONS, "AIOF_NON_STOP_AT_INTERMEDIATE_STATIONS");
+ SQAIOrder.DefSQConst(engine, AIOrder::AIOF_NON_STOP_AT_DESTINATION_STATION, "AIOF_NON_STOP_AT_DESTINATION_STATION");
SQAIOrder.DefSQConst(engine, AIOrder::AIOF_UNLOAD, "AIOF_UNLOAD");
+ SQAIOrder.DefSQConst(engine, AIOrder::AIOF_TRANSFER, "AIOF_TRANSFER");
+ SQAIOrder.DefSQConst(engine, AIOrder::AIOF_NO_UNLOAD, "AIOF_NO_UNLOAD");
SQAIOrder.DefSQConst(engine, AIOrder::AIOF_FULL_LOAD, "AIOF_FULL_LOAD");
+ SQAIOrder.DefSQConst(engine, AIOrder::AIOF_FULL_LOAD_ANY, "AIOF_FULL_LOAD_ANY");
+ SQAIOrder.DefSQConst(engine, AIOrder::AIOF_NO_LOAD, "AIOF_NO_LOAD");
SQAIOrder.DefSQConst(engine, AIOrder::AIOF_SERVICE_IF_NEEDED, "AIOF_SERVICE_IF_NEEDED");
- SQAIOrder.DefSQConst(engine, AIOrder::AIOF_NON_STOP, "AIOF_NON_STOP");
+ SQAIOrder.DefSQConst(engine, AIOrder::AIOF_NON_STOP_FLAGS, "AIOF_NON_STOP_FLAGS");
+ SQAIOrder.DefSQConst(engine, AIOrder::AIOF_UNLOAD_FLAGS, "AIOF_UNLOAD_FLAGS");
+ SQAIOrder.DefSQConst(engine, AIOrder::AIOF_LOAD_FLAGS, "AIOF_LOAD_FLAGS");
SQAIOrder.DefSQConst(engine, AIOrder::AIOF_INVALID, "AIOF_INVALID");
AIError::RegisterErrorMap(STR_8831_NO_MORE_SPACE_FOR_ORDERS, AIOrder::ERR_ORDER_TOO_MANY);