(svn r12621) [NoAI] -Add: support for GetLastError in AIRoad. Patch by Morloth. noai
authorrubidium
Mon, 07 Apr 2008 22:08:28 +0000
branchnoai
changeset 10091 e4feb2f9fedf
parent 10090 d6a6cac2fb25
child 10093 b3849a19d137
(svn r12621) [NoAI] -Add: support for GetLastError in AIRoad. Patch by Morloth.
src/ai/api/ai_airport.hpp
src/ai/api/ai_bridge.hpp
src/ai/api/ai_bridge.hpp.sq
src/ai/api/ai_error.hpp
src/ai/api/ai_error.hpp.sq
src/ai/api/ai_road.cpp
src/ai/api/ai_road.hpp
src/ai/api/ai_road.hpp.sq
src/ai/api/ai_tunnel.hpp
--- a/src/ai/api/ai_airport.hpp	Mon Apr 07 18:41:49 2008 +0000
+++ b/src/ai/api/ai_airport.hpp	Mon Apr 07 22:08:28 2008 +0000
@@ -105,7 +105,7 @@
 	 * Removes a airport.
 	 * @param tile Any tile of the airport.
 	 * @pre AIMap::IsValidTile(tile).
-	 * @exception AIError::ERR_AREA_IS_OWNED_BY_ANOTHER_COMPANY
+	 * @exception AIError::ERR_OWNED_BY_ANOTHER_COMPANY
 	 * @return Whether the airport has been/can be removed or not.
 	 */
 	static bool RemoveAirport(TileIndex tile);
--- a/src/ai/api/ai_bridge.hpp	Mon Apr 07 18:41:49 2008 +0000
+++ b/src/ai/api/ai_bridge.hpp	Mon Apr 07 22:08:28 2008 +0000
@@ -34,9 +34,6 @@
 		/** One (or more) of the bridge head(s) ends in water. */
 		ERR_BRIDGE_CANNOT_END_IN_WATER,      // [STR_02A0_ENDS_OF_BRIDGE_MUST_BOTH]
 
-		/** Slope of the land does not allow the required bridge head. */
-		ERR_BRIDGE_SLOPE_WRONG,              // [STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION]
-
 		/** The bride heads need to be on the same height */
 		ERR_BRIDGE_HEADS_NOT_ON_SAME_HEIGHT, // [STR_BRIDGEHEADS_NOT_SAME_HEIGHT]
 	};
@@ -122,9 +119,10 @@
 	 * @pre 'vehicle_type' is either AIVehicle::VEHICLE_RAIL or AIVehicle::VEHICLE_ROAD.
 	 * @exception AIError::ERR_ALREADY_BUILT
 	 * @exception AIError::ERR_AREA_NOT_CLEAR
+	 * @exception AIError::ERR_LAND_SLOPED_WRONG
+	 * @exception AIError::ERR_VEHICLE_IN_THE_WAY
 	 * @exception AIBridge::ERR_BRIDGE_TYPE_UNAVAILABLE
 	 * @exception AIBridge::ERR_BRIDGE_CANNOT_END_IN_WATER
-	 * @exception AIBridge::ERR_BRIDGE_SLOPE_WRONG
 	 * @exception AIBridge::ERR_BRIDGE_HEADS_NOT_ON_SAME_HEIGHT
 	 * @return Whether the bridge has been/can be build or not.
 	 */
@@ -134,6 +132,7 @@
 	 * Removes a bridge, by executing it on either the start or end tile.
 	 * @param tile An end or start tile of the bridge.
 	 * @pre AIMap::IsValidTile(tile).
+	 * @exception AIError::ERR_OWNED_BY_ANOTHER_COMPANY
 	 * @return Whether the bridge has been/can be removed or not.
 	 */
 	static bool RemoveBridge(TileIndex tile);
--- a/src/ai/api/ai_bridge.hpp.sq	Mon Apr 07 18:41:49 2008 +0000
+++ b/src/ai/api/ai_bridge.hpp.sq	Mon Apr 07 22:08:28 2008 +0000
@@ -21,17 +21,14 @@
 	SQAIBridge.DefSQConst(engine, AIBridge::ERR_BRIDGE_BASE,                     "ERR_BRIDGE_BASE");
 	SQAIBridge.DefSQConst(engine, AIBridge::ERR_BRIDGE_TYPE_UNAVAILABLE,         "ERR_BRIDGE_TYPE_UNAVAILABLE");
 	SQAIBridge.DefSQConst(engine, AIBridge::ERR_BRIDGE_CANNOT_END_IN_WATER,      "ERR_BRIDGE_CANNOT_END_IN_WATER");
-	SQAIBridge.DefSQConst(engine, AIBridge::ERR_BRIDGE_SLOPE_WRONG,              "ERR_BRIDGE_SLOPE_WRONG");
 	SQAIBridge.DefSQConst(engine, AIBridge::ERR_BRIDGE_HEADS_NOT_ON_SAME_HEIGHT, "ERR_BRIDGE_HEADS_NOT_ON_SAME_HEIGHT");
 
-	AIError::RegisterErrorMap(STR_5015_CAN_T_BUILD_BRIDGE_HERE,        AIBridge::ERR_BRIDGE_TYPE_UNAVAILABLE);
-	AIError::RegisterErrorMap(STR_02A0_ENDS_OF_BRIDGE_MUST_BOTH,       AIBridge::ERR_BRIDGE_CANNOT_END_IN_WATER);
-	AIError::RegisterErrorMap(STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION, AIBridge::ERR_BRIDGE_SLOPE_WRONG);
-	AIError::RegisterErrorMap(STR_BRIDGEHEADS_NOT_SAME_HEIGHT,         AIBridge::ERR_BRIDGE_HEADS_NOT_ON_SAME_HEIGHT);
+	AIError::RegisterErrorMap(STR_5015_CAN_T_BUILD_BRIDGE_HERE,  AIBridge::ERR_BRIDGE_TYPE_UNAVAILABLE);
+	AIError::RegisterErrorMap(STR_02A0_ENDS_OF_BRIDGE_MUST_BOTH, AIBridge::ERR_BRIDGE_CANNOT_END_IN_WATER);
+	AIError::RegisterErrorMap(STR_BRIDGEHEADS_NOT_SAME_HEIGHT,   AIBridge::ERR_BRIDGE_HEADS_NOT_ON_SAME_HEIGHT);
 
 	AIError::RegisterErrorMapString(AIBridge::ERR_BRIDGE_TYPE_UNAVAILABLE,         "ERR_BRIDGE_TYPE_UNAVAILABLE");
 	AIError::RegisterErrorMapString(AIBridge::ERR_BRIDGE_CANNOT_END_IN_WATER,      "ERR_BRIDGE_CANNOT_END_IN_WATER");
-	AIError::RegisterErrorMapString(AIBridge::ERR_BRIDGE_SLOPE_WRONG,              "ERR_BRIDGE_SLOPE_WRONG");
 	AIError::RegisterErrorMapString(AIBridge::ERR_BRIDGE_HEADS_NOT_ON_SAME_HEIGHT, "ERR_BRIDGE_HEADS_NOT_ON_SAME_HEIGHT");
 
 	SQAIBridge.DefSQStaticMethod(engine, &AIBridge::GetClassName,     "GetClassName",     1, "x");
--- a/src/ai/api/ai_error.hpp	Mon Apr 07 18:41:49 2008 +0000
+++ b/src/ai/api/ai_error.hpp	Mon Apr 07 22:08:28 2008 +0000
@@ -38,6 +38,7 @@
 		ERR_CAT_TUNNEL,   //!< Error messages related to building / removing tunnels.
 		ERR_CAT_TILE,     //!< Error messages related to raising / lowering and demolishing tiles.
 		ERR_CAT_SIGN,     //!< Error messages related to building / removing signs.
+		ERR_CAT_ROAD,     //!< Error messages related to building / maintaining roads.
 
 		/**
 		 * DO NOT USE! The error bitsize determines how many errors can be stored in
@@ -74,14 +75,20 @@
 		/** Area isn't clear, try to demolish the building on it */
 		ERR_AREA_NOT_CLEAR,                           // [STR_2004_BUILDING_MUST_BE_DEMOLISHED, STR_5007_MUST_DEMOLISH_BRIDGE_FIRST, STR_300B_MUST_DEMOLISH_RAILROAD, STR_300E_MUST_DEMOLISH_AIRPORT_FIRST, STR_MUST_DEMOLISH_CARGO_TRAM_STATION, STR_3047_MUST_DEMOLISH_TRUCK_STATION, STR_MUST_DEMOLISH_PASSENGER_TRAM_STATION, STR_3046_MUST_DEMOLISH_BUS_STATION, STR_306A_BUOY_IN_THE_WAY, STR_304D_MUST_DEMOLISH_DOCK_FIRST, STR_4800_IN_THE_WAY, STR_5804_COMPANY_HEADQUARTERS_IN, STR_5800_OBJECT_IN_THE_WAY, STR_1801_MUST_REMOVE_ROAD_FIRST, STR_1008_MUST_REMOVE_RAILROAD_TRACK, STR_5007_MUST_DEMOLISH_BRIDGE_FIRST, STR_5006_MUST_DEMOLISH_TUNNEL_FIRST, STR_1002_EXCAVATION_WOULD_DAMAGE]
 
-		/** Area is owned by another company */
-		ERR_AREA_IS_OWNED_BY_ANOTHER_COMPANY,         // [STR_1024_AREA_IS_OWNED_BY_ANOTHER]
+		/** Area / property is owned by another company */
+		ERR_OWNED_BY_ANOTHER_COMPANY,                 // [STR_1024_AREA_IS_OWNED_BY_ANOTHER, STR_013B_OWNED_BY]
 
 		/** The name given is not unique for the object type */
 		ERR_NAME_IS_NOT_UNIQUE,                       // [STR_NAME_MUST_BE_UNIQUE]
 
 		/** The building you want to build requires flat land */
 		ERR_FLAT_LAND_REQUIRED,                       // [STR_0007_FLAT_LAND_REQUIRED]
+
+		/** Land is sloped in the wrong direction for this build action */
+		ERR_LAND_SLOPED_WRONG,                        // [STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION]
+
+		/** A vehicle is in the way */
+		ERR_VEHICLE_IN_THE_WAY,                  // [STR_8803_TRAIN_IN_THE_WAY, STR_9000_ROAD_VEHICLE_IN_THE_WAY, STR_980E_SHIP_IN_THE_WAY, STR_A015_AIRCRAFT_IN_THE_WAY]
 	};
 
 	/**
--- a/src/ai/api/ai_error.hpp.sq	Mon Apr 07 18:41:49 2008 +0000
+++ b/src/ai/api/ai_error.hpp.sq	Mon Apr 07 22:08:28 2008 +0000
@@ -20,27 +20,30 @@
 	SQAIError.PreRegister(engine);
 	SQAIError.AddConstructor<void (AIError::*)(), 1>(engine, "x");
 
-	SQAIError.DefSQConst(engine, AIError::ERR_CAT_NONE,                         "ERR_CAT_NONE");
-	SQAIError.DefSQConst(engine, AIError::ERR_CAT_GENERAL,                      "ERR_CAT_GENERAL");
-	SQAIError.DefSQConst(engine, AIError::ERR_CAT_VEHICLE,                      "ERR_CAT_VEHICLE");
-	SQAIError.DefSQConst(engine, AIError::ERR_CAT_STATION,                      "ERR_CAT_STATION");
-	SQAIError.DefSQConst(engine, AIError::ERR_CAT_BRIDGE,                       "ERR_CAT_BRIDGE");
-	SQAIError.DefSQConst(engine, AIError::ERR_CAT_TUNNEL,                       "ERR_CAT_TUNNEL");
-	SQAIError.DefSQConst(engine, AIError::ERR_CAT_TILE,                         "ERR_CAT_TILE");
-	SQAIError.DefSQConst(engine, AIError::ERR_CAT_SIGN,                         "ERR_CAT_SIGN");
-	SQAIError.DefSQConst(engine, AIError::ERR_CAT_BIT_SIZE,                     "ERR_CAT_BIT_SIZE");
-	SQAIError.DefSQConst(engine, AIError::ERR_NONE,                             "ERR_NONE");
-	SQAIError.DefSQConst(engine, AIError::ERR_UNKNOWN,                          "ERR_UNKNOWN");
-	SQAIError.DefSQConst(engine, AIError::ERR_PRECONDITION_FAILED,              "ERR_PRECONDITION_FAILED");
-	SQAIError.DefSQConst(engine, AIError::ERR_NEWGRF_SUPPLIED_ERROR,            "ERR_NEWGRF_SUPPLIED_ERROR");
-	SQAIError.DefSQConst(engine, AIError::ERR_GENERAL_BASE,                     "ERR_GENERAL_BASE");
-	SQAIError.DefSQConst(engine, AIError::ERR_NOT_ENOUGH_CASH,                  "ERR_NOT_ENOUGH_CASH");
-	SQAIError.DefSQConst(engine, AIError::ERR_LOCAL_AUTHORITY_REFUSES,          "ERR_LOCAL_AUTHORITY_REFUSES");
-	SQAIError.DefSQConst(engine, AIError::ERR_ALREADY_BUILT,                    "ERR_ALREADY_BUILT");
-	SQAIError.DefSQConst(engine, AIError::ERR_AREA_NOT_CLEAR,                   "ERR_AREA_NOT_CLEAR");
-	SQAIError.DefSQConst(engine, AIError::ERR_AREA_IS_OWNED_BY_ANOTHER_COMPANY, "ERR_AREA_IS_OWNED_BY_ANOTHER_COMPANY");
-	SQAIError.DefSQConst(engine, AIError::ERR_NAME_IS_NOT_UNIQUE,               "ERR_NAME_IS_NOT_UNIQUE");
-	SQAIError.DefSQConst(engine, AIError::ERR_FLAT_LAND_REQUIRED,               "ERR_FLAT_LAND_REQUIRED");
+	SQAIError.DefSQConst(engine, AIError::ERR_CAT_NONE,                 "ERR_CAT_NONE");
+	SQAIError.DefSQConst(engine, AIError::ERR_CAT_GENERAL,              "ERR_CAT_GENERAL");
+	SQAIError.DefSQConst(engine, AIError::ERR_CAT_VEHICLE,              "ERR_CAT_VEHICLE");
+	SQAIError.DefSQConst(engine, AIError::ERR_CAT_STATION,              "ERR_CAT_STATION");
+	SQAIError.DefSQConst(engine, AIError::ERR_CAT_BRIDGE,               "ERR_CAT_BRIDGE");
+	SQAIError.DefSQConst(engine, AIError::ERR_CAT_TUNNEL,               "ERR_CAT_TUNNEL");
+	SQAIError.DefSQConst(engine, AIError::ERR_CAT_TILE,                 "ERR_CAT_TILE");
+	SQAIError.DefSQConst(engine, AIError::ERR_CAT_SIGN,                 "ERR_CAT_SIGN");
+	SQAIError.DefSQConst(engine, AIError::ERR_CAT_ROAD,                 "ERR_CAT_ROAD");
+	SQAIError.DefSQConst(engine, AIError::ERR_CAT_BIT_SIZE,             "ERR_CAT_BIT_SIZE");
+	SQAIError.DefSQConst(engine, AIError::ERR_NONE,                     "ERR_NONE");
+	SQAIError.DefSQConst(engine, AIError::ERR_UNKNOWN,                  "ERR_UNKNOWN");
+	SQAIError.DefSQConst(engine, AIError::ERR_PRECONDITION_FAILED,      "ERR_PRECONDITION_FAILED");
+	SQAIError.DefSQConst(engine, AIError::ERR_NEWGRF_SUPPLIED_ERROR,    "ERR_NEWGRF_SUPPLIED_ERROR");
+	SQAIError.DefSQConst(engine, AIError::ERR_GENERAL_BASE,             "ERR_GENERAL_BASE");
+	SQAIError.DefSQConst(engine, AIError::ERR_NOT_ENOUGH_CASH,          "ERR_NOT_ENOUGH_CASH");
+	SQAIError.DefSQConst(engine, AIError::ERR_LOCAL_AUTHORITY_REFUSES,  "ERR_LOCAL_AUTHORITY_REFUSES");
+	SQAIError.DefSQConst(engine, AIError::ERR_ALREADY_BUILT,            "ERR_ALREADY_BUILT");
+	SQAIError.DefSQConst(engine, AIError::ERR_AREA_NOT_CLEAR,           "ERR_AREA_NOT_CLEAR");
+	SQAIError.DefSQConst(engine, AIError::ERR_OWNED_BY_ANOTHER_COMPANY, "ERR_OWNED_BY_ANOTHER_COMPANY");
+	SQAIError.DefSQConst(engine, AIError::ERR_NAME_IS_NOT_UNIQUE,       "ERR_NAME_IS_NOT_UNIQUE");
+	SQAIError.DefSQConst(engine, AIError::ERR_FLAT_LAND_REQUIRED,       "ERR_FLAT_LAND_REQUIRED");
+	SQAIError.DefSQConst(engine, AIError::ERR_LAND_SLOPED_WRONG,        "ERR_LAND_SLOPED_WRONG");
+	SQAIError.DefSQConst(engine, AIError::ERR_VEHICLE_IN_THE_WAY,       "ERR_VEHICLE_IN_THE_WAY");
 
 	AIError::RegisterErrorMap(STR_0003_NOT_ENOUGH_CASH_REQUIRES,        AIError::ERR_NOT_ENOUGH_CASH);
 	AIError::RegisterErrorMap(STR_2009_LOCAL_AUTHORITY_REFUSES,         AIError::ERR_LOCAL_AUTHORITY_REFUSES);
@@ -64,21 +67,29 @@
 	AIError::RegisterErrorMap(STR_5007_MUST_DEMOLISH_BRIDGE_FIRST,      AIError::ERR_AREA_NOT_CLEAR);
 	AIError::RegisterErrorMap(STR_5006_MUST_DEMOLISH_TUNNEL_FIRST,      AIError::ERR_AREA_NOT_CLEAR);
 	AIError::RegisterErrorMap(STR_1002_EXCAVATION_WOULD_DAMAGE,         AIError::ERR_AREA_NOT_CLEAR);
-	AIError::RegisterErrorMap(STR_1024_AREA_IS_OWNED_BY_ANOTHER,        AIError::ERR_AREA_IS_OWNED_BY_ANOTHER_COMPANY);
+	AIError::RegisterErrorMap(STR_1024_AREA_IS_OWNED_BY_ANOTHER,        AIError::ERR_OWNED_BY_ANOTHER_COMPANY);
+	AIError::RegisterErrorMap(STR_013B_OWNED_BY,                        AIError::ERR_OWNED_BY_ANOTHER_COMPANY);
 	AIError::RegisterErrorMap(STR_NAME_MUST_BE_UNIQUE,                  AIError::ERR_NAME_IS_NOT_UNIQUE);
 	AIError::RegisterErrorMap(STR_0007_FLAT_LAND_REQUIRED,              AIError::ERR_FLAT_LAND_REQUIRED);
+	AIError::RegisterErrorMap(STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION,  AIError::ERR_LAND_SLOPED_WRONG);
+	AIError::RegisterErrorMap(STR_8803_TRAIN_IN_THE_WAY,                AIError::ERR_VEHICLE_IN_THE_WAY);
+	AIError::RegisterErrorMap(STR_9000_ROAD_VEHICLE_IN_THE_WAY,         AIError::ERR_VEHICLE_IN_THE_WAY);
+	AIError::RegisterErrorMap(STR_980E_SHIP_IN_THE_WAY,                 AIError::ERR_VEHICLE_IN_THE_WAY);
+	AIError::RegisterErrorMap(STR_A015_AIRCRAFT_IN_THE_WAY,             AIError::ERR_VEHICLE_IN_THE_WAY);
 
-	AIError::RegisterErrorMapString(AIError::ERR_NONE,                             "ERR_NONE");
-	AIError::RegisterErrorMapString(AIError::ERR_UNKNOWN,                          "ERR_UNKNOWN");
-	AIError::RegisterErrorMapString(AIError::ERR_PRECONDITION_FAILED,              "ERR_PRECONDITION_FAILED");
-	AIError::RegisterErrorMapString(AIError::ERR_NEWGRF_SUPPLIED_ERROR,            "ERR_NEWGRF_SUPPLIED_ERROR");
-	AIError::RegisterErrorMapString(AIError::ERR_NOT_ENOUGH_CASH,                  "ERR_NOT_ENOUGH_CASH");
-	AIError::RegisterErrorMapString(AIError::ERR_LOCAL_AUTHORITY_REFUSES,          "ERR_LOCAL_AUTHORITY_REFUSES");
-	AIError::RegisterErrorMapString(AIError::ERR_ALREADY_BUILT,                    "ERR_ALREADY_BUILT");
-	AIError::RegisterErrorMapString(AIError::ERR_AREA_NOT_CLEAR,                   "ERR_AREA_NOT_CLEAR");
-	AIError::RegisterErrorMapString(AIError::ERR_AREA_IS_OWNED_BY_ANOTHER_COMPANY, "ERR_AREA_IS_OWNED_BY_ANOTHER_COMPANY");
-	AIError::RegisterErrorMapString(AIError::ERR_NAME_IS_NOT_UNIQUE,               "ERR_NAME_IS_NOT_UNIQUE");
-	AIError::RegisterErrorMapString(AIError::ERR_FLAT_LAND_REQUIRED,               "ERR_FLAT_LAND_REQUIRED");
+	AIError::RegisterErrorMapString(AIError::ERR_NONE,                     "ERR_NONE");
+	AIError::RegisterErrorMapString(AIError::ERR_UNKNOWN,                  "ERR_UNKNOWN");
+	AIError::RegisterErrorMapString(AIError::ERR_PRECONDITION_FAILED,      "ERR_PRECONDITION_FAILED");
+	AIError::RegisterErrorMapString(AIError::ERR_NEWGRF_SUPPLIED_ERROR,    "ERR_NEWGRF_SUPPLIED_ERROR");
+	AIError::RegisterErrorMapString(AIError::ERR_NOT_ENOUGH_CASH,          "ERR_NOT_ENOUGH_CASH");
+	AIError::RegisterErrorMapString(AIError::ERR_LOCAL_AUTHORITY_REFUSES,  "ERR_LOCAL_AUTHORITY_REFUSES");
+	AIError::RegisterErrorMapString(AIError::ERR_ALREADY_BUILT,            "ERR_ALREADY_BUILT");
+	AIError::RegisterErrorMapString(AIError::ERR_AREA_NOT_CLEAR,           "ERR_AREA_NOT_CLEAR");
+	AIError::RegisterErrorMapString(AIError::ERR_OWNED_BY_ANOTHER_COMPANY, "ERR_OWNED_BY_ANOTHER_COMPANY");
+	AIError::RegisterErrorMapString(AIError::ERR_NAME_IS_NOT_UNIQUE,       "ERR_NAME_IS_NOT_UNIQUE");
+	AIError::RegisterErrorMapString(AIError::ERR_FLAT_LAND_REQUIRED,       "ERR_FLAT_LAND_REQUIRED");
+	AIError::RegisterErrorMapString(AIError::ERR_LAND_SLOPED_WRONG,        "ERR_LAND_SLOPED_WRONG");
+	AIError::RegisterErrorMapString(AIError::ERR_VEHICLE_IN_THE_WAY,       "ERR_VEHICLE_IN_THE_WAY");
 
 	SQAIError.DefSQStaticMethod(engine, &AIError::GetClassName,           "GetClassName",           1, "x");
 	SQAIError.DefSQStaticMethod(engine, &AIError::GetErrorCategory,       "GetErrorCategory",       1, "x");
--- a/src/ai/api/ai_road.cpp	Mon Apr 07 18:41:49 2008 +0000
+++ b/src/ai/api/ai_road.cpp	Mon Apr 07 22:08:28 2008 +0000
@@ -89,33 +89,29 @@
 
 /* static */ bool AIRoad::BuildRoad(TileIndex start, TileIndex end)
 {
-	if (start == end) return false;
-	if (!::IsValidTile(start)) return false;
-	if (!::IsValidTile(end)) return false;
-	/* Not on one line */
-	if (TileX(start) != TileX(end) &&
-			TileY(start) != TileY(end)) return false;
+	EnforcePrecondition(false, start != end);
+	EnforcePrecondition(false, ::IsValidTile(start));
+	EnforcePrecondition(false, ::IsValidTile(end));
+	EnforcePrecondition(false, TileX(start) == TileX(end) || TileY(start) == TileY(end));
 
 	return AIObject::DoCommand(end, start, (TileY(start) != TileY(end) ? 4 : 0) | (start < end ? 1 : 2) | (ROADTYPE_ROAD << 3), CMD_BUILD_LONG_ROAD);
 }
 
 /* static */ bool AIRoad::BuildRoadFull(TileIndex start, TileIndex end)
 {
-	if (start == end) return false;
-	if (!::IsValidTile(start)) return false;
-	if (!::IsValidTile(end)) return false;
-	/* Not on one line */
-	if (TileX(start) != TileX(end) &&
-			TileY(start) != TileY(end)) return false;
+	EnforcePrecondition(false, start != end);
+	EnforcePrecondition(false, ::IsValidTile(start));
+	EnforcePrecondition(false, ::IsValidTile(end));
+	EnforcePrecondition(false, TileX(start) == TileX(end) || TileY(start) == TileY(end));
 
 	return AIObject::DoCommand(end, start, (TileY(start) != TileY(end) ? 4 : 0) | (start < end ? 2 : 1), CMD_BUILD_LONG_ROAD);
 }
 
 /* static */ bool AIRoad::BuildRoadDepot(TileIndex tile, TileIndex front)
 {
-	if (tile == front) return false;
-	if (!::IsValidTile(tile)) return false;
-	if (!::IsValidTile(front)) return false;
+	EnforcePrecondition(false, tile != front);
+	EnforcePrecondition(false, ::IsValidTile(tile));
+	EnforcePrecondition(false, ::IsValidTile(front));
 
 	uint entrance_dir = (TileX(tile) == TileX(front)) ? (TileY(tile) < TileY(front) ? 1 : 3) : (TileX(tile) < TileX(front) ? 2 : 0);
 
@@ -124,9 +120,9 @@
 
 /* static */ bool AIRoad::BuildRoadStation(TileIndex tile, TileIndex front, bool truck, bool drive_through)
 {
-	if (tile == front) return false;
-	if (!::IsValidTile(tile)) return false;
-	if (!::IsValidTile(front)) return false;
+	EnforcePrecondition(false, tile != front);
+	EnforcePrecondition(false, ::IsValidTile(tile));
+	EnforcePrecondition(false, ::IsValidTile(front));
 
 	uint entrance_dir;
 	if (drive_through) {
@@ -140,38 +136,34 @@
 
 /* static */ bool AIRoad::RemoveRoad(TileIndex start, TileIndex end)
 {
-	if (!::IsValidTile(start)) return false;
-	if (!::IsValidTile(end)) return false;
-	/* Not on one line */
-	if (TileX(start) != TileX(end) &&
-			TileY(start) != TileY(end)) return false;
+	EnforcePrecondition(false, ::IsValidTile(start));
+	EnforcePrecondition(false, ::IsValidTile(end));
+	EnforcePrecondition(false, TileX(start) == TileX(end) || TileY(start) == TileY(end));
 
 	return AIObject::DoCommand(end, start, (TileY(start) != TileY(end) ? 4 : 0) | (start < end ? 1 : 2) | (ROADTYPE_ROAD << 3), CMD_REMOVE_LONG_ROAD);
 }
 
 /* static */ bool AIRoad::RemoveRoadFull(TileIndex start, TileIndex end)
 {
-	if (!::IsValidTile(start)) return false;
-	if (!::IsValidTile(end)) return false;
-	/* Not on one line */
-	if (TileX(start) != TileX(end) &&
-			TileY(start) != TileY(end)) return false;
+	EnforcePrecondition(false, ::IsValidTile(start));
+	EnforcePrecondition(false, ::IsValidTile(end));
+	EnforcePrecondition(false, TileX(start) == TileX(end) || TileY(start) == TileY(end));
 
 	return AIObject::DoCommand(end, start, (TileY(start) != TileY(end) ? 4 : 0) | (start < end ? 2 : 1), CMD_REMOVE_LONG_ROAD);
 }
 
 /* static */ bool AIRoad::RemoveRoadDepot(TileIndex tile)
 {
-	if (!::IsValidTile(tile)) return false;
-	if (!IsTileType(tile, MP_ROAD) || GetRoadTileType(tile) != ROAD_TILE_DEPOT) return false;
+	EnforcePrecondition(false, ::IsValidTile(tile));
+	EnforcePrecondition(false, IsTileType(tile, MP_ROAD) && GetRoadTileType(tile) == ROAD_TILE_DEPOT);
 
 	return AIObject::DoCommand(tile, 0, 0, CMD_LANDSCAPE_CLEAR);
 }
 
 /* static */ bool AIRoad::RemoveRoadStation(TileIndex tile)
 {
-	if (!::IsValidTile(tile)) return false;
-	if (!IsTileType(tile, MP_STATION) || !IsRoadStop(tile)) return false;
+	EnforcePrecondition(false, ::IsValidTile(tile));
+	EnforcePrecondition(false, IsTileType(tile, MP_STATION) && IsRoadStop(tile));
 
 	return AIObject::DoCommand(tile, 0, GetRoadStopType(tile), CMD_REMOVE_ROAD_STOP);
 }
--- a/src/ai/api/ai_road.hpp	Mon Apr 07 18:41:49 2008 +0000
+++ b/src/ai/api/ai_road.hpp	Mon Apr 07 22:08:28 2008 +0000
@@ -6,6 +6,7 @@
 #define AI_ROAD_HPP
 
 #include "ai_object.hpp"
+#include "ai_error.hpp"
 
 /**
  * Class that handles all road related functions.
@@ -14,6 +15,32 @@
 public:
 	static const char *GetClassName() { return "AIRoad"; }
 
+	enum ErrorMessages {
+		/** Base for road building / maintaining errors */
+		ERR_ROAD_BASE = AIError::ERR_CAT_ROAD << AIError::ERR_CAT_BIT_SIZE,
+
+		/** Road works are in progress */
+		ERR_ROAD_WORKS_IN_PROGRESS,                   // [STR_ROAD_WORKS_IN_PROGRESS]
+
+		/** Drive through is in the wrong direction */
+		ERR_ROAD_DRIVE_THROUGH_WRONG_DIRECTION,       // [STR_DRIVE_THROUGH_ERROR_DIRECTION]
+
+		/** Drive through roads can't be build on town owned roads */
+		ERR_ROAD_CANNOT_BUILD_ON_TOWN_ROAD,           // [STR_DRIVE_THROUGH_ERROR_ON_TOWN_ROAD]
+
+		/** There are too many stations in the game */
+		ERR_ROAD_TOO_MANY_STATIONS,                   // [STR_3008_TOO_MANY_STATIONS_LOADING, STR_TOO_MANY_TRUCK_STOPS, STR_TOO_MANY_BUS_STOPS]
+
+		/** There are too many stations in a town */
+		ERR_ROAD_TOO_MANY_STATIONS_IN_TOWN,           // [STR_3007_TOO_MANY_STATIONS_LOADING]
+
+		/** The station is too close to another station */
+		ERR_ROAD_TOO_CLOSE_TO_ANOTHER_STATION,        // [STR_3009_TOO_CLOSE_TO_ANOTHER_STATION]
+
+		/** One way roads can't have junctions */
+		ERR_ROAD_ONE_WAY_ROADS_CANNOT_HAVE_JUNCTIONS, // [STR_ERR_ONEWAY_ROADS_CAN_T_HAVE_JUNCTION]
+	};
+
 	/**
 	 * Checks whether the given tile is actually a tile with road that can be
 	 *  used to traverse a tile. This excludes road depots and 'normal' road
@@ -106,6 +133,12 @@
 	 * @pre 'start' and 'end' are in a straight line, i.e.
 	 *  AIMap::GetTileX(start) == AIMap::GetTileX(end) or
 	 *  AIMap::GetTileY(start) == AIMap::GetTileY(end).
+	 * @exception AIError::ERR_ALREADY_BUILT
+	 * @exception AIError::ERR_LAND_SLOPED_WRONG
+	 * @exception AIError::ERR_AREA_NOT_CLEAR
+	 * @exception AIRoad::ERR_ROAD_ONE_WAY_ROADS_CANNOT_HAVE_JUNCTIONS
+	 * @exception AIRoad::ERR_ROAD_WORKS_IN_PROGRESS
+	 * @exception AIRoad::ERR_VEHICLE_IN_THE_WAY
 	 * @return Whether the road has been/can be build or not.
 	 */
 	static bool BuildRoad(TileIndex start, TileIndex end);
@@ -121,6 +154,12 @@
 	 * @pre 'start' and 'end' are in a straight line, i.e.
 	 *  AIMap::GetTileX(start) == AIMap::GetTileX(end) or
 	 *  AIMap::GetTileY(start) == AIMap::GetTileY(end).
+	 * @exception AIError::ERR_ALREADY_BUILT
+	 * @exception AIError::ERR_LAND_SLOPED_WRONG
+	 * @exception AIError::ERR_AREA_NOT_CLEAR
+	 * @exception AIRoad::ERR_ROAD_ONE_WAY_ROADS_CANNOT_HAVE_JUNCTIONS
+	 * @exception AIRoad::ERR_ROAD_WORKS_IN_PROGRESS
+	 * @exception AIRoad::ERR_VEHICLE_IN_THE_WAY
 	 * @return Whether the road has been/can be build or not.
 	 */
 	static bool BuildRoadFull(TileIndex start, TileIndex end);
@@ -132,6 +171,8 @@
 	 * @pre AIMap::IsValidTile(tile).
 	 * @pre AIMap::IsValidTile(front).
 	 * @pre Tile is not equal to front.
+	 * @exception AIError::ERR_FLAT_LAND_REQUIRED
+	 * @exception AIError::ERR_AREA_NOT_CLEAR
 	 * @return Whether the road depot has been/can be build or not.
 	 */
 	static bool BuildRoadDepot(TileIndex tile, TileIndex front);
@@ -146,6 +187,15 @@
 	 * @pre AIMap::IsValidTile(tile).
 	 * @pre AIMap::IsValidTile(front).
 	 * @pre 'tile' is not equal to 'front'.
+	 * @exception AIError::ERR_OWNED_BY_ANOTHER_COMPANY
+	 * @exception AIError::ERR_AREA_NOT_CLEAR
+	 * @exception AIError::ERR_FLAT_LAND_REQUIRED
+	 * @exception AIRoad::ERR_ROAD_DRIVE_THROUGH_WRONG_DIRECTION
+	 * @exception AIRoad::ERR_ROAD_CANNOT_BUILD_ON_TOWN_ROAD
+	 * @exception AIRoad::ERR_VEHICLE_IN_THE_WAY
+	 * @exception AIRoad::ERR_ROAD_TOO_CLOSE_TO_ANOTHER_STATION
+	 * @exception AIRoad::ERR_ROAD_TOO_MANY_STATIONS
+	 * @exception AIRoad::ERR_ROAD_TOO_MANY_STATIONS_IN_TOWN
 	 * @return Whether the station has been/can be build or not.
 	 */
 	static bool BuildRoadStation(TileIndex tile, TileIndex front, bool truck, bool drive_through);
@@ -159,6 +209,9 @@
 	 * @pre 'start' and 'end' are in a straight line, i.e.
 	 *  AIMap::GetTileX(start) == AIMap::GetTileX(end) or
 	 *  AIMap::GetTileY(start) == AIMap::GetTileY(end).
+	 * @exception AIError::ERR_OWNED_BY_ANOTHER_COMPANY
+	 * @exception AIRoad::ERR_VEHICLE_IN_THE_WAY
+	 * @exception AIRoad::ERR_ROAD_WORKS_IN_PROGRESS
 	 * @return Whether the road has been/can be removed or not.
 	 */
 	static bool RemoveRoad(TileIndex start, TileIndex end);
@@ -173,6 +226,9 @@
 	 * @pre 'start' and 'end' are in a straight line, i.e.
 	 *  AIMap::GetTileX(start) == AIMap::GetTileX(end) or
 	 *  AIMap::GetTileY(start) == AIMap::GetTileY(end).
+	 * @exception AIError::ERR_OWNED_BY_ANOTHER_COMPANY
+	 * @exception AIRoad::ERR_VEHICLE_IN_THE_WAY
+	 * @exception AIRoad::ERR_ROAD_WORKS_IN_PROGRESS
 	 * @return Whether the road has been/can be removed or not.
 	 */
 	static bool RemoveRoadFull(TileIndex start, TileIndex end);
@@ -182,6 +238,8 @@
 	 * @param tile Place to remove the depot from.
 	 * @pre AIMap::IsValidTile(tile).
 	 * @pre Tile is a road depot.
+	 * @exception AIError::ERR_OWNED_BY_ANOTHER_COMPANY
+	 * @exception AIRoad::ERR_VEHICLE_IN_THE_WAY
 	 * @return Whether the road depot has been/can be removed or not.
 	 */
 	static bool RemoveRoadDepot(TileIndex tile);
@@ -191,6 +249,8 @@
 	 * @param tile Place to remove the station from.
 	 * @pre AIMap::IsValidTile(tile).
 	 * @pre Tile is a road station.
+	 * @exception AIError::ERR_OWNED_BY_ANOTHER_COMPANY
+	 * @exception AIRoad::ERR_VEHICLE_IN_THE_WAY
 	 * @return Whether the station has been/can be removed or not.
 	 */
 	static bool RemoveRoadStation(TileIndex tile);
--- a/src/ai/api/ai_road.hpp.sq	Mon Apr 07 18:41:49 2008 +0000
+++ b/src/ai/api/ai_road.hpp.sq	Mon Apr 07 22:08:28 2008 +0000
@@ -1,6 +1,10 @@
 #include "ai_road.hpp"
 
 namespace SQConvert {
+	/* Allow enums to be used as Squirrel parameters */
+	template <> AIRoad::ErrorMessages GetParam(ForceType<AIRoad::ErrorMessages>, HSQUIRRELVM vm, int index) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (AIRoad::ErrorMessages)tmp; }
+	template <> int Return<AIRoad::ErrorMessages>(HSQUIRRELVM vm, AIRoad::ErrorMessages res) { sq_pushinteger(vm, (int32)res); return 1; }
+
 	/* Allow AIRoad to be used as Squirrel parameter */
 	template <> AIRoad *GetParam(ForceType<AIRoad *>, HSQUIRRELVM vm, int index) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return  (AIRoad *)instance; }
 	template <> AIRoad &GetParam(ForceType<AIRoad &>, HSQUIRRELVM vm, int index) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(AIRoad *)instance; }
@@ -14,6 +18,33 @@
 	SQAIRoad.PreRegister(engine);
 	SQAIRoad.AddConstructor<void (AIRoad::*)(), 1>(engine, "x");
 
+	SQAIRoad.DefSQConst(engine, AIRoad::ERR_ROAD_BASE,                                "ERR_ROAD_BASE");
+	SQAIRoad.DefSQConst(engine, AIRoad::ERR_ROAD_WORKS_IN_PROGRESS,                   "ERR_ROAD_WORKS_IN_PROGRESS");
+	SQAIRoad.DefSQConst(engine, AIRoad::ERR_ROAD_DRIVE_THROUGH_WRONG_DIRECTION,       "ERR_ROAD_DRIVE_THROUGH_WRONG_DIRECTION");
+	SQAIRoad.DefSQConst(engine, AIRoad::ERR_ROAD_CANNOT_BUILD_ON_TOWN_ROAD,           "ERR_ROAD_CANNOT_BUILD_ON_TOWN_ROAD");
+	SQAIRoad.DefSQConst(engine, AIRoad::ERR_ROAD_TOO_MANY_STATIONS,                   "ERR_ROAD_TOO_MANY_STATIONS");
+	SQAIRoad.DefSQConst(engine, AIRoad::ERR_ROAD_TOO_MANY_STATIONS_IN_TOWN,           "ERR_ROAD_TOO_MANY_STATIONS_IN_TOWN");
+	SQAIRoad.DefSQConst(engine, AIRoad::ERR_ROAD_TOO_CLOSE_TO_ANOTHER_STATION,        "ERR_ROAD_TOO_CLOSE_TO_ANOTHER_STATION");
+	SQAIRoad.DefSQConst(engine, AIRoad::ERR_ROAD_ONE_WAY_ROADS_CANNOT_HAVE_JUNCTIONS, "ERR_ROAD_ONE_WAY_ROADS_CANNOT_HAVE_JUNCTIONS");
+
+	AIError::RegisterErrorMap(STR_ROAD_WORKS_IN_PROGRESS,               AIRoad::ERR_ROAD_WORKS_IN_PROGRESS);
+	AIError::RegisterErrorMap(STR_DRIVE_THROUGH_ERROR_DIRECTION,        AIRoad::ERR_ROAD_DRIVE_THROUGH_WRONG_DIRECTION);
+	AIError::RegisterErrorMap(STR_DRIVE_THROUGH_ERROR_ON_TOWN_ROAD,     AIRoad::ERR_ROAD_CANNOT_BUILD_ON_TOWN_ROAD);
+	AIError::RegisterErrorMap(STR_3008_TOO_MANY_STATIONS_LOADING,       AIRoad::ERR_ROAD_TOO_MANY_STATIONS);
+	AIError::RegisterErrorMap(STR_TOO_MANY_TRUCK_STOPS,                 AIRoad::ERR_ROAD_TOO_MANY_STATIONS);
+	AIError::RegisterErrorMap(STR_TOO_MANY_BUS_STOPS,                   AIRoad::ERR_ROAD_TOO_MANY_STATIONS);
+	AIError::RegisterErrorMap(STR_3007_TOO_MANY_STATIONS_LOADING,       AIRoad::ERR_ROAD_TOO_MANY_STATIONS_IN_TOWN);
+	AIError::RegisterErrorMap(STR_3009_TOO_CLOSE_TO_ANOTHER_STATION,    AIRoad::ERR_ROAD_TOO_CLOSE_TO_ANOTHER_STATION);
+	AIError::RegisterErrorMap(STR_ERR_ONEWAY_ROADS_CAN_T_HAVE_JUNCTION, AIRoad::ERR_ROAD_ONE_WAY_ROADS_CANNOT_HAVE_JUNCTIONS);
+
+	AIError::RegisterErrorMapString(AIRoad::ERR_ROAD_WORKS_IN_PROGRESS,                   "ERR_ROAD_WORKS_IN_PROGRESS");
+	AIError::RegisterErrorMapString(AIRoad::ERR_ROAD_DRIVE_THROUGH_WRONG_DIRECTION,       "ERR_ROAD_DRIVE_THROUGH_WRONG_DIRECTION");
+	AIError::RegisterErrorMapString(AIRoad::ERR_ROAD_CANNOT_BUILD_ON_TOWN_ROAD,           "ERR_ROAD_CANNOT_BUILD_ON_TOWN_ROAD");
+	AIError::RegisterErrorMapString(AIRoad::ERR_ROAD_TOO_MANY_STATIONS,                   "ERR_ROAD_TOO_MANY_STATIONS");
+	AIError::RegisterErrorMapString(AIRoad::ERR_ROAD_TOO_MANY_STATIONS_IN_TOWN,           "ERR_ROAD_TOO_MANY_STATIONS_IN_TOWN");
+	AIError::RegisterErrorMapString(AIRoad::ERR_ROAD_TOO_CLOSE_TO_ANOTHER_STATION,        "ERR_ROAD_TOO_CLOSE_TO_ANOTHER_STATION");
+	AIError::RegisterErrorMapString(AIRoad::ERR_ROAD_ONE_WAY_ROADS_CANNOT_HAVE_JUNCTIONS, "ERR_ROAD_ONE_WAY_ROADS_CANNOT_HAVE_JUNCTIONS");
+
 	SQAIRoad.DefSQStaticMethod(engine, &AIRoad::GetClassName,                  "GetClassName",                  1, "x");
 	SQAIRoad.DefSQStaticMethod(engine, &AIRoad::IsRoadTile,                    "IsRoadTile",                    2, "xi");
 	SQAIRoad.DefSQStaticMethod(engine, &AIRoad::IsRoadDepotTile,               "IsRoadDepotTile",               2, "xi");
--- a/src/ai/api/ai_tunnel.hpp	Mon Apr 07 18:41:49 2008 +0000
+++ b/src/ai/api/ai_tunnel.hpp	Mon Apr 07 22:08:28 2008 +0000
@@ -76,6 +76,7 @@
 	 * Remove the tunnel whose entrance is located at tile.
 	 * @param tile The tile that is an entrance to a tunnel.
 	 * @pre AIMap::IsValidTile(tile) && IsTunnelTile(tile).
+	 * @exception AIError::ERR_OWNED_BY_ANOTHER_COMPANY
 	 * @return Whether the tunnel has been/can be removed or not.
 	 */
 	static bool RemoveTunnel(TileIndex tile);