(svn r9374) [NoAI] -Add: functionality to modify orders. noai
authorrubidium
Tue, 20 Mar 2007 14:27:54 +0000
branchnoai
changeset 9500 d67653613da4
parent 9499 c02cf5bf4f7a
child 9501 15689f09d1f5
(svn r9374) [NoAI] -Add: functionality to modify orders.
projects/openttd.vcproj
projects/openttd_vs80.vcproj
source.list
src/ai/api/ai_order.cpp
src/ai/api/ai_order.hpp
--- a/projects/openttd.vcproj	Tue Mar 20 13:55:04 2007 +0000
+++ b/projects/openttd.vcproj	Tue Mar 20 14:27:54 2007 +0000
@@ -1048,6 +1048,9 @@
 				RelativePath=".\..\src\ai\api\ai_object.hpp">
 			</File>
 			<File
+				RelativePath=".\..\src\ai\api\ai_order.hpp">
+			</File>
+			<File
 				RelativePath=".\..\src\ai\api\ai_road.hpp">
 			</File>
 			<File
@@ -1097,6 +1100,9 @@
 				RelativePath=".\..\src\ai\api\ai_object.cpp">
 			</File>
 			<File
+				RelativePath=".\..\src\ai\api\ai_order.cpp">
+			</File>
+			<File
 				RelativePath=".\..\src\ai\api\ai_road.cpp">
 			</File>
 			<File
--- a/projects/openttd_vs80.vcproj	Tue Mar 20 13:55:04 2007 +0000
+++ b/projects/openttd_vs80.vcproj	Tue Mar 20 14:27:54 2007 +0000
@@ -1616,6 +1616,10 @@
 				>
 			</File>
 			<File
+				RelativePath=".\..\src\ai\api\ai_order.hpp"
+				>
+			</File>
+			<File
 				RelativePath=".\..\src\ai\api\ai_road.hpp"
 				>
 			</File>
@@ -1680,6 +1684,10 @@
 				>
 			</File>
 			<File
+				RelativePath=".\..\src\ai\api\ai_order.cpp"
+				>
+			</File>
+			<File
 				RelativePath=".\..\src\ai\api\ai_road.cpp"
 				>
 			</File>
--- a/source.list	Tue Mar 20 13:55:04 2007 +0000
+++ b/source.list	Tue Mar 20 14:27:54 2007 +0000
@@ -321,6 +321,7 @@
 ai/api/ai_industry.hpp
 ai/api/ai_map.hpp
 ai/api/ai_object.hpp
+ai/api/ai_order.hpp
 ai/api/ai_road.hpp
 ai/api/ai_settings.hpp
 ai/api/ai_town.hpp
@@ -338,6 +339,7 @@
 ai/api/ai_industry.cpp
 ai/api/ai_map.cpp
 ai/api/ai_object.cpp
+ai/api/ai_order.cpp
 ai/api/ai_road.cpp
 ai/api/ai_settings.cpp
 ai/api/ai_town.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ai/api/ai_order.cpp	Tue Mar 20 14:27:54 2007 +0000
@@ -0,0 +1,147 @@
+/* $Id$ */
+
+/** @file ai_order.cpp handles the functions of the AIOrder class */
+
+#include "ai_order.hpp"
+#include "ai_map.hpp"
+#include "ai_vehicle.hpp"
+#include "../../command.h"
+#include "../../order.h"
+
+#include "../../depot.h"
+#include "../../rail_map.h"
+#include "../../road_map.h"
+#include "../../station_map.h"
+#include "../../water_map.h"
+#include "../../waypoint.h"
+
+/**
+ * Gets the order type given a tile
+ * @param t the tile to get the order from
+ * @return the order type, or OT_END when there is no order
+ */
+static OrderType GetOrderTypeByTile(TileIndex t)
+{
+	if (!::IsValidTile(t)) return OT_END;
+
+	switch (::GetTileType(t)) {
+		default: break;
+		case MP_STATION: return OT_GOTO_STATION; break;
+		case MP_WATER:   if (::IsShipDepot(t)) return OT_GOTO_DEPOT; break;
+		case MP_STREET:  if (::GetRoadTileType(t) == ROAD_TILE_DEPOT) return OT_GOTO_DEPOT; break;
+		case MP_RAILWAY:
+			switch (::GetRailTileType(t)) {
+				case RAIL_TILE_DEPOT:    return OT_GOTO_DEPOT;
+				case RAIL_TILE_WAYPOINT: return OT_GOTO_WAYPOINT;
+				default: break;
+			}
+			break;
+	}
+
+	return OT_END;
+}
+
+/* static */ bool AIOrder::IsValidVehicleOrder(VehicleID vehicle_id, uint32 order_id)
+{
+	return AIVehicle::IsValidVehicle(vehicle_id) && order_id < ::GetVehicle(vehicle_id)->num_orders;
+}
+
+/* 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;
+		case OT_GOTO_WAYPOINT: return (order_flags & ~(AIOF_NON_STOP)) == 0;
+		default:               return false;
+	}
+}
+
+int32 AIOrder::GetNumberOfOrders(VehicleID vehicle_id)
+{
+	return AIVehicle::IsValidVehicle(vehicle_id) ? ::GetVehicle(vehicle_id)->num_orders : -1;
+}
+
+TileIndex AIOrder::GetOrderDestination(VehicleID vehicle_id, uint32 order_id)
+{
+	if (!AIOrder::IsValidVehicleOrder(vehicle_id, order_id)) return INVALID_TILE;
+
+	Order *order = ::GetVehicle(vehicle_id)->orders;
+	for (uint i = 0; i < order_id; i++) order = order->next;
+
+	switch (order->type) {
+		case OT_GOTO_DEPOT:    return ::GetDepot(order->dest)->xy;
+		case OT_GOTO_STATION:  return ::GetStation(order->dest)->xy;
+		case OT_GOTO_WAYPOINT: return ::GetWaypoint(order->dest)->xy;
+		default:               return INVALID_TILE;
+	}
+}
+
+AIOrder::AIOrderFlags AIOrder::GetOrderFlags(VehicleID vehicle_id, uint32 order_id)
+{
+	if (!AIOrder::IsValidVehicleOrder(vehicle_id, order_id)) return AIOF_INVALID;
+
+	Order *order = ::GetVehicle(vehicle_id)->orders;
+	for (uint i = 0; i < order_id; i++) order = order->next;
+
+	return (AIOrder::AIOrderFlags)order->flags;
+}
+
+bool AIOrder::AppendOrder(VehicleID vehicle_id, TileIndex destination, AIOrderFlags order_flags)
+{
+	if (!AIVehicle::IsValidVehicle(vehicle_id)) return false;
+	return this->InsertOrder(vehicle_id, GetVehicle(vehicle_id)->num_orders, destination, order_flags);
+}
+
+bool AIOrder::InsertOrder(VehicleID vehicle_id, uint32 order_id, TileIndex destination, AIOrder::AIOrderFlags order_flags)
+{
+	if (!IsValidVehicleOrder(vehicle_id, order_id) ||
+		!this->AreOrderFlagsValid(destination, order_flags)) return false;
+
+	Order order;
+	order.type  = ::GetOrderTypeByTile(destination);
+	order.flags = order_flags;
+	switch (order.type) {
+		case OT_GOTO_DEPOT:    order.dest = ::GetDepotByTile(destination)->index;
+		case OT_GOTO_STATION:  order.dest = ::GetStationIndex(destination);
+		case OT_GOTO_WAYPOINT: order.dest = ::GetWaypointIndex(destination);
+		default: NOT_REACHED(); return false;
+	}
+
+	return this->DoCommand(0, vehicle_id | (order_id << 16), PackOrder(&order), CMD_INSERT_ORDER);
+}
+
+bool AIOrder::RemoveOrder(VehicleID vehicle_id, uint32 order_id)
+{
+	if (!IsValidVehicleOrder(vehicle_id, order_id)) return false;
+
+	return this->DoCommand(0, vehicle_id, order_id, CMD_DELETE_ORDER);
+}
+
+bool AIOrder::ChangeOrder(VehicleID vehicle_id, uint32 order_id, AIOrder::AIOrderFlags order_flags)
+{
+	if (!IsValidVehicleOrder(vehicle_id, order_id) ||
+		!this->AreOrderFlagsValid(GetOrderDestination(vehicle_id, order_id), order_flags)) return false;
+
+	return this->DoCommand(0, vehicle_id | (order_id << 16), order_flags, CMD_MODIFY_ORDER);
+}
+
+bool AIOrder::CopyOrders(VehicleID vehicle_id, VehicleID main_vehicle_id)
+{
+	if (!AIVehicle::IsValidVehicle(vehicle_id) || !AIVehicle::IsValidVehicle(main_vehicle_id)) return false;
+
+	return this->DoCommand(0, vehicle_id | (main_vehicle_id << 16), CO_COPY, CMD_CLONE_ORDER);
+}
+
+bool AIOrder::ShareOrders(VehicleID vehicle_id, VehicleID main_vehicle_id)
+{
+	if (!AIVehicle::IsValidVehicle(vehicle_id) || !AIVehicle::IsValidVehicle(main_vehicle_id)) return false;
+
+	return this->DoCommand(0, vehicle_id | (main_vehicle_id << 16), CO_SHARE, CMD_CLONE_ORDER);
+}
+
+bool AIOrder::UnshareOrders(VehicleID vehicle_id)
+{
+	if (!AIVehicle::IsValidVehicle(vehicle_id)) return false;
+
+	return this->DoCommand(0, vehicle_id, CO_UNSHARE, CMD_CLONE_ORDER);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ai/api/ai_order.hpp	Tue Mar 20 14:27:54 2007 +0000
@@ -0,0 +1,179 @@
+/* $Id$ */
+
+/** @file ai_order.hpp Everything to query and build Orders */
+
+#ifndef AI_ORDER_HPP
+#define AI_ORDER_HPP
+
+#include "ai_object.hpp"
+
+/**
+ * Class that handles all order related functions.
+ */
+class AIOrder : public AIObject {
+public:
+	/**
+	 * Flags that can be used to modify the behaviour of orders.
+	 */
+	enum AIOrderFlags {
+		/** 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. */
+		AIOF_UNLOAD            = 1 << 1,
+		/** Wait till the the vehicle is fully loaded; only for stations. */
+		AIOF_FULL_LOAD         = 1 << 2,
+
+		/** 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,
+
+		/** For marking invalid order flags */
+		AIOF_INVALID           = 0xFFFF,
+	};
+
+	/**
+	 * Checks whether the given order id is valid for the given vehicle.
+	 * @param vehicle_id the vehicle to check the order index for.
+	 * @param order_id   the order index to check.
+	 * @pre AIVehicle::IsValidVehicle(vehicle_id).
+	 * @return true if and only if the order_id is valid for the given vehicle.
+	 */
+	static bool IsValidVehicleOrder(VehicleID vehicle_id, uint32 order_id);
+
+	/**
+	 * Checks whether the given order flags are valid for the given destination.
+	 * @param destination the destination of the order.
+	 * @param order_flags the flags given to the order.
+	 * @return true if and only if the order_flags are valid for the given location.
+	 */
+	static bool AreOrderFlagsValid(TileIndex destination, AIOrderFlags order_flags);
+
+	/**
+	 * Returns the number of orders for the given vehicle.
+	 * @param vehicle_id the vehicle to get the order count of.
+	 * @pre AIVehicle::IsValidVehicle(vehicle_id).
+	 * @return the number of orders for the given vehicle or a negative
+	 *   value when the vehicle does not exist.
+	 */
+	int32 GetNumberOfOrders(VehicleID vehicle_id);
+
+	/**
+	 * Gets the destination of the given order for the given vehicle.
+	 * @param vehicle_id the vehicle to get the destination for.
+	 * @param order_id   the order to get the destination for.
+	 * @pre IsValidVehicleOrder(vehicle_id, order_id).
+	 * @return the destination tile of the order.
+	 */
+	TileIndex GetOrderDestination(VehicleID vehicle_id, uint32 order_id);
+
+	/**
+	 * Gets the AIOrderFlags of the given order for the given vehicle.
+	 * @param vehicle_id the vehicle to get the destination for.
+	 * @param order_id   the order to get the destination for.
+	 * @pre IsValidVehicleOrder(vehicle_id, order_id).
+	 * @return the AIOrderFlags of the order.
+	 */
+	AIOrderFlags GetOrderFlags(VehicleID vehicle_id, uint32 order_id);
+
+	/**
+	 * Appends an order to the end of the vehicle's order list.
+	 * @param vehicle_id  the vehicle to append the order to.
+	 * @param destination the destination of the order.
+	 * @param order_flags the flags given to the order.
+	 * @pre AIVehicle::IsValidVehicle(vehicle_id).
+	 * @pre AreOrderFlagsValid(destination, order_flags).
+	 * @return true if and only if the order was appended.
+	 */
+	bool AppendOrder(VehicleID vehicle_id, TileIndex destination, AIOrderFlags order_flags);
+
+	/**
+	 * Inserts an order before the given order_id into the vehicle's order list.
+	 * @param vehicle_id  the vehicle to add the order to.
+	 * @param order_id    the order to place the new order before.
+	 * @param destination the destination of the order.
+	 * @param order_flags the flags given to the order.
+	 * @pre IsValidVehicleOrder(vehicle_id, order_id).
+	 * @pre AreOrderFlagsValid(destination, order_flags).
+	 * @return true if and only if the order was inserted.
+	 */
+	bool InsertOrder(VehicleID vehicle_id, uint32 order_id, TileIndex destination, AIOrderFlags order_flags);
+
+	/**
+	 * Removes an order from the vehicle's order list.
+	 * @param vehicle_id  the vehicle to remove the order from.
+	 * @param order_id    the order to remove from the order list.
+	 * @pre AIVehicle::IsValidVehicleOrder(vehicle_id, order_id).
+	 * @return true if and only if the order was removed.
+	 */
+	bool RemoveOrder(VehicleID vehicle_id, uint32 order_id);
+
+	/**
+	 * Changes the order flags of the given order.
+	 * @param vehicle_id  the vehicle to change the order of.
+	 * @param order_id    the order to change.
+	 * @param order_flags the new flags given to the order.
+	 * @pre IsValidVehicleOrder(vehicle_id, order_id).
+	 * @pre AreOrderFlagsValid(GetOrderDestination(vehicle_id, order_id), order_flags).
+	 * @return true if and only if the order was changed.
+	 */
+	bool ChangeOrder(VehicleID vehicle_id, uint32 order_id, AIOrderFlags order_flags);
+
+	/**
+	 * Copies the orders from another vehicle. The orders of the main
+	 * vehicle are going to be the orders of the changed vehicle.
+	 * @param vehicle_id      the vehicle to copy the orders to.
+	 * @param main_vehicle_id the vehicle to copy the orders from.
+	 * @pre AIVehicle::IsValidVehicle(vehicle_id).
+	 * @pre AIVehicle::IsValidVehicle(main_vehicle_id).
+	 * @return true if and only if the copying succeeded.
+	 */
+	bool CopyOrders(VehicleID vehicle_id, VehicleID main_vehicle_id);
+
+	/**
+	 * Shares the orders between two vehicles. The orders of the main
+	 * vehicle are going to be the orders of the changed vehicle.
+	 * @param vehicle_id      the vehicle to add to the shared order list.
+	 * @param main_vehicle_id the vehicle to share the orders with.
+	 * @pre AIVehicle::IsValidVehicle(vehicle_id).
+	 * @pre AIVehicle::IsValidVehicle(main_vehicle_id).
+	 * @return true if and only if the sharing succeeded.
+	 */
+	bool ShareOrders(VehicleID vehicle_id, VehicleID main_vehicle_id);
+
+	/**
+	 * Removes the given vehicle from a shared orders list.
+	 * @param vehicle_id the vehicle to remove from the shared order list.
+	 * @pre AIVehicle::IsValidVehicle(vehicle_id).
+	 * @return true if and only if the unsharing succeeded.
+	 */
+	bool UnshareOrders(VehicleID vehicle_id);
+};
+DECLARE_ENUM_AS_BIT_SET(AIOrder::AIOrderFlags);
+
+#ifdef DEFINE_SQUIRREL_CLASS
+void SQAIOrderRegister(Squirrel *engine) {
+	DefSQClass <AIOrder> SQAIOrder("AIOrder");
+	SQAIOrder.PreRegister(engine);
+	SQAIOrder.AddConstructor(engine);
+	SQAIOrder.DefSQFunction(engine, &AIOrder::IsValidVehicleOrder, "IsValidVehicleOrder");
+	SQAIOrder.DefSQFunction(engine, &AIOrder::ShareOrders,         "ShareOrders");
+	SQAIOrder.DefSQFunction(engine, &AIOrder::UnshareOrders,       "UnshareOrders");
+	SQAIOrder.DefSQFunction(engine, &AIOrder::AreOrderFlagsValid,  "AreOrderFlagsValid");
+	SQAIOrder.DefSQFunction(engine, &AIOrder::GetNumberOfOrders,   "GetNumberOfOrders");
+	SQAIOrder.DefSQFunction(engine, &AIOrder::GetOrderDestination, "GetOrderDestination");
+	SQAIOrder.DefSQFunction(engine, &AIOrder::GetOrderFlags,       "GetOrderFlags");
+	SQAIOrder.DefSQFunction(engine, &AIOrder::AppendOrder,         "AppendOrder");
+	SQAIOrder.DefSQFunction(engine, &AIOrder::InsertOrder,         "InsertOrder");
+	SQAIOrder.DefSQFunction(engine, &AIOrder::RemoveOrder,         "RemoveOrder");
+	SQAIOrder.DefSQFunction(engine, &AIOrder::ChangeOrder,         "ChangeOrder");
+	SQAIOrder.DefSQFunction(engine, &AIOrder::CopyOrders,          "CopyOrders");
+	SQAIOrder.PostRegister(engine);
+}
+#endif /* SQUIRREL_CLASS */
+
+#endif /* AI_ORDER_HPP */