(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: noai
authorrubidium
Sat, 12 Apr 2008 22:28:07 +0000
branchnoai
changeset 10146 ddbb8d2ae3ea
parent 10142 56ee7da4ad56
child 10149 a273c164cfab
(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.
src/ai/api/ai_order.cpp
src/ai/api/ai_order.hpp
src/ai/api/ai_order.hpp.sq
--- 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);