changeset 14398:72032c0e7bda draft

(svn r18955) -Feature: [NoAI] introduce GetBuildCost functions in several classes to get easier cost estimations before you start building
author yexo <yexo@openttd.org>
date Fri, 29 Jan 2010 23:56:42 +0000
parents 015c605b2543
children dd7bb047d40c
files bin/ai/regression/regression.nut bin/ai/regression/regression.txt src/ai/api/ai_gamesettings.cpp src/ai/api/ai_marine.cpp src/ai/api/ai_marine.hpp src/ai/api/ai_marine.hpp.sq src/ai/api/ai_rail.cpp src/ai/api/ai_rail.hpp src/ai/api/ai_rail.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_tile.cpp src/ai/api/ai_tile.hpp src/ai/api/ai_tile.hpp.sq
diffstat 15 files changed, 239 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/bin/ai/regression/regression.nut
+++ b/bin/ai/regression/regression.nut
@@ -504,6 +504,45 @@
 	}
 }
 
+function Regression::Prices()
+{
+	print("");
+	print("--Prices--");
+	print(" -Rail-");
+	print("  0,BT_TRACK:    " + AIRail.GetBuildCost(0, AIRail.BT_TRACK));
+	print("  0,BT_SIGNAL:   " + AIRail.GetBuildCost(0, AIRail.BT_SIGNAL));
+	print("  0,BT_DEPOT:    " + AIRail.GetBuildCost(0, AIRail.BT_DEPOT));
+	print("  0,BT_STATION:  " + AIRail.GetBuildCost(0, AIRail.BT_STATION));
+	print("  0,BT_WAYPOINT: " + AIRail.GetBuildCost(0, AIRail.BT_WAYPOINT));
+	print("  1,BT_TRACK:    " + AIRail.GetBuildCost(1, AIRail.BT_TRACK));
+	print("  1,BT_SIGNAL:   " + AIRail.GetBuildCost(1, AIRail.BT_SIGNAL));
+	print("  1,BT_DEPOT:    " + AIRail.GetBuildCost(1, AIRail.BT_DEPOT));
+	print("  1,BT_STATION:  " + AIRail.GetBuildCost(1, AIRail.BT_STATION));
+	print("  1,BT_WAYPOINT: " + AIRail.GetBuildCost(1, AIRail.BT_WAYPOINT));
+	print(" -Road-");
+	print("  ROADTYPE_ROAD,BT_ROAD:       " + AIRoad.GetBuildCost(AIRoad.ROADTYPE_ROAD, AIRoad.BT_ROAD));
+	print("  ROADTYPE_ROAD,BT_DEPOT:      " + AIRoad.GetBuildCost(AIRoad.ROADTYPE_ROAD, AIRoad.BT_DEPOT));
+	print("  ROADTYPE_ROAD,BT_BUS_STOP:   " + AIRoad.GetBuildCost(AIRoad.ROADTYPE_ROAD, AIRoad.BT_BUS_STOP));
+	print("  ROADTYPE_ROAD,BT_TRUCK_STOP: " + AIRoad.GetBuildCost(AIRoad.ROADTYPE_ROAD, AIRoad.BT_TRUCK_STOP));
+	print("  ROADTYPE_TRAM,BT_ROAD:       " + AIRoad.GetBuildCost(AIRoad.ROADTYPE_TRAM, AIRoad.BT_ROAD));
+	print("  ROADTYPE_TRAM,BT_DEPOT:      " + AIRoad.GetBuildCost(AIRoad.ROADTYPE_TRAM, AIRoad.BT_DEPOT));
+	print("  ROADTYPE_TRAM,BT_BUS_STOP:   " + AIRoad.GetBuildCost(AIRoad.ROADTYPE_TRAM, AIRoad.BT_BUS_STOP));
+	print("  ROADTYPE_TRAM,BT_TRUCK_STOP: " + AIRoad.GetBuildCost(AIRoad.ROADTYPE_TRAM, AIRoad.BT_TRUCK_STOP));
+	print(" -Water-");
+	print("  BT_DOCK:  " + AIMarine.GetBuildCost(AIMarine.BT_DOCK));
+	print("  BT_DEPOT: " + AIMarine.GetBuildCost(AIMarine.BT_DEPOT));
+	print("  BT_BUOY:  " + AIMarine.GetBuildCost(AIMarine.BT_BUOY));
+	print(" -Tile-");
+	print("  BT_FOUNDATION:   " + AITile.GetBuildCost(AITile.BT_FOUNDATION));
+	print("  BT_TERRAFORM:    " + AITile.GetBuildCost(AITile.BT_TERRAFORM));
+	print("  BT_BUILD_TREES:  " + AITile.GetBuildCost(AITile.BT_BUILD_TREES));
+	print("  BT_CLEAR_GRASS:  " + AITile.GetBuildCost(AITile.BT_CLEAR_GRASS));
+	print("  BT_CLEAR_ROUGH:  " + AITile.GetBuildCost(AITile.BT_CLEAR_ROUGH));
+	print("  BT_CLEAR_ROCKY:  " + AITile.GetBuildCost(AITile.BT_CLEAR_ROCKY));
+	print("  BT_CLEAR_FIELDS: " + AITile.GetBuildCost(AITile.BT_CLEAR_FIELDS));
+	print("  BT_CLEAR_HOUSE:  " + AITile.GetBuildCost(AITile.BT_CLEAR_HOUSE));
+}
+
 function cost_callback(old_path, new_tile, new_direction, self) { if (old_path == null) return 0; return old_path.GetCost() + 1; }
 function estimate_callback(tile, direction, goals, self) { return goals[0] - tile; }
 function neighbours_callback(path, cur_tile, self) { return [[cur_tile + 1, 1]]; }
@@ -1699,6 +1738,7 @@
 	this.IndustryTypeList();
 	this.Map();
 	this.Marine();
+	this.Prices();
 	this.Rail();
 	this.RailTypeList();
 	this.Road();
--- a/bin/ai/regression/regression.txt
+++ b/bin/ai/regression/regression.txt
@@ -7121,6 +7121,41 @@
   BuildWaterDepot():    true
   BuildDock():          true
 
+--Prices--
+ -Rail-
+  0,BT_TRACK:    75
+  0,BT_SIGNAL:   48
+  0,BT_DEPOT:    450
+  0,BT_STATION:  285
+  0,BT_WAYPOINT: 450
+  1,BT_TRACK:    -1
+  1,BT_SIGNAL:   -1
+  1,BT_DEPOT:    -1
+  1,BT_STATION:  -1
+  1,BT_WAYPOINT: -1
+ -Road-
+  ROADTYPE_ROAD,BT_ROAD:       71
+  ROADTYPE_ROAD,BT_DEPOT:      375
+  ROADTYPE_ROAD,BT_BUS_STOP:   150
+  ROADTYPE_ROAD,BT_TRUCK_STOP: 150
+  ROADTYPE_TRAM,BT_ROAD:       -1
+  ROADTYPE_TRAM,BT_DEPOT:      -1
+  ROADTYPE_TRAM,BT_BUS_STOP:   -1
+  ROADTYPE_TRAM,BT_TRUCK_STOP: -1
+ -Water-
+  BT_DOCK:  262
+  BT_DEPOT: 525
+  BT_BUOY:  262
+ -Tile-
+  BT_FOUNDATION:   187
+  BT_TERRAFORM:    187
+  BT_BUILD_TREES:  15
+  BT_CLEAR_GRASS:  15
+  BT_CLEAR_ROUGH:  30
+  BT_CLEAR_ROCKY:  150
+  BT_CLEAR_FIELDS: 375
+  BT_CLEAR_HOUSE:  1200
+
 --Rail--
     IsRailTile():                  false
     BuildRailTrack():              true
--- a/src/ai/api/ai_gamesettings.cpp
+++ b/src/ai/api/ai_gamesettings.cpp
@@ -11,6 +11,7 @@
 
 #include "ai_gamesettings.hpp"
 #include "../../settings_internal.h"
+#include "../../economy_func.h"
 
 /* static */ bool AIGameSettings::IsValid(const char *setting)
 {
--- a/src/ai/api/ai_marine.cpp
+++ b/src/ai/api/ai_marine.cpp
@@ -13,6 +13,7 @@
 #include "ai_station.hpp"
 #include "../../station_base.h"
 #include "../../tile_cmd.h"
+#include "../../economy_func.h"
 
 
 /* static */ bool AIMarine::IsWaterDepotTile(TileIndex tile)
@@ -149,3 +150,13 @@
 
 	return AIObject::DoCommand(tile, 0, 0, CMD_LANDSCAPE_CLEAR);
 }
+
+/* static */ Money AIMarine::GetBuildCost(BuildType build_type)
+{
+	switch (build_type) {
+		case BT_DOCK:  return ::GetPrice(PR_BUILD_STATION_DOCK, 1, NULL);
+		case BT_DEPOT: return ::GetPrice(PR_BUILD_DEPOT_SHIP, 1, NULL);
+		case BT_BUOY:  return ::GetPrice(PR_BUILD_WAYPOINT_BUOY, 1, NULL);
+		default: return -1;
+	}
+}
--- a/src/ai/api/ai_marine.hpp
+++ b/src/ai/api/ai_marine.hpp
@@ -34,6 +34,15 @@
 	};
 
 	/**
+	 * Types of water-related objects in the game.
+	 */
+	enum BuildType {
+		BT_DOCK,  //!< Build a dock
+		BT_DEPOT, //!< Build a ship depot
+		BT_BUOY,  //!< Build a buoy
+	};
+
+	/**
 	 * Checks whether the given tile is actually a tile with a water depot.
 	 * @param tile The tile to check.
 	 * @pre AIMap::IsValidTile(tile).
@@ -191,6 +200,13 @@
 	 * @return Whether the canal has been/can be removed or not.
 	 */
 	static bool RemoveCanal(TileIndex tile);
+
+	/**
+	 * Get the baseprice of building a water-related object.
+	 * @param build_type the type of object to build
+	 * @return The baseprice of building the given object.
+	 */
+	static Money GetBuildCost(BuildType build_type);
 };
 
 #endif /* AI_MARINE_HPP */
--- a/src/ai/api/ai_marine.hpp.sq
+++ b/src/ai/api/ai_marine.hpp.sq
@@ -15,6 +15,8 @@
 	/* Allow enums to be used as Squirrel parameters */
 	template <> AIMarine::ErrorMessages GetParam(ForceType<AIMarine::ErrorMessages>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (AIMarine::ErrorMessages)tmp; }
 	template <> int Return<AIMarine::ErrorMessages>(HSQUIRRELVM vm, AIMarine::ErrorMessages res) { sq_pushinteger(vm, (int32)res); return 1; }
+	template <> AIMarine::BuildType GetParam(ForceType<AIMarine::BuildType>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (AIMarine::BuildType)tmp; }
+	template <> int Return<AIMarine::BuildType>(HSQUIRRELVM vm, AIMarine::BuildType res) { sq_pushinteger(vm, (int32)res); return 1; }
 
 	/* Allow AIMarine to be used as Squirrel parameter */
 	template <> AIMarine *GetParam(ForceType<AIMarine *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return  (AIMarine *)instance; }
@@ -32,6 +34,9 @@
 
 	SQAIMarine.DefSQConst(engine, AIMarine::ERR_MARINE_BASE,                   "ERR_MARINE_BASE");
 	SQAIMarine.DefSQConst(engine, AIMarine::ERR_MARINE_MUST_BE_BUILT_ON_WATER, "ERR_MARINE_MUST_BE_BUILT_ON_WATER");
+	SQAIMarine.DefSQConst(engine, AIMarine::BT_DOCK,                           "BT_DOCK");
+	SQAIMarine.DefSQConst(engine, AIMarine::BT_DEPOT,                          "BT_DEPOT");
+	SQAIMarine.DefSQConst(engine, AIMarine::BT_BUOY,                           "BT_BUOY");
 
 	AIError::RegisterErrorMap(STR_ERROR_MUST_BE_BUILT_ON_WATER, AIMarine::ERR_MARINE_MUST_BE_BUILT_ON_WATER);
 
@@ -53,6 +58,7 @@
 	SQAIMarine.DefSQStaticMethod(engine, &AIMarine::RemoveBuoy,             "RemoveBuoy",             2, ".i");
 	SQAIMarine.DefSQStaticMethod(engine, &AIMarine::RemoveLock,             "RemoveLock",             2, ".i");
 	SQAIMarine.DefSQStaticMethod(engine, &AIMarine::RemoveCanal,            "RemoveCanal",            2, ".i");
+	SQAIMarine.DefSQStaticMethod(engine, &AIMarine::GetBuildCost,           "GetBuildCost",           2, ".i");
 
 	SQAIMarine.PostRegister(engine);
 }
--- a/src/ai/api/ai_rail.cpp
+++ b/src/ai/api/ai_rail.cpp
@@ -19,6 +19,7 @@
 #include "../../newgrf.h"
 #include "../../newgrf_generic.h"
 #include "../../newgrf_station.h"
+#include "../../economy_func.h"
 
 /* static */ bool AIRail::IsRailTile(TileIndex tile)
 {
@@ -454,3 +455,17 @@
 
 	return AIObject::DoCommand(tile, track, 0, CMD_REMOVE_SIGNALS);
 }
+
+/* static */ Money AIRail::GetBuildCost(RailType railtype, BuildType build_type)
+{
+	if (!AIRail::IsRailTypeAvailable(railtype)) return -1;
+
+	switch (build_type) {
+		case BT_TRACK:    return ::RailBuildCost((::RailType)railtype);
+		case BT_SIGNAL:   return ::GetPrice(PR_BUILD_SIGNALS, 1, NULL);
+		case BT_DEPOT:    return ::GetPrice(PR_BUILD_DEPOT_TRAIN, 1, NULL);
+		case BT_STATION:  return ::GetPrice(PR_BUILD_STATION_RAIL, 1, NULL) + ::GetPrice(PR_BUILD_STATION_RAIL_LENGTH, 1, NULL);
+		case BT_WAYPOINT: return ::GetPrice(PR_BUILD_WAYPOINT_RAIL, 1, NULL);
+		default: return -1;
+	}
+}
--- a/src/ai/api/ai_rail.hpp
+++ b/src/ai/api/ai_rail.hpp
@@ -82,6 +82,17 @@
 	};
 
 	/**
+	 * Types of rail-related objects in the game.
+	 */
+	enum BuildType {
+		BT_TRACK,    //!< Build a track
+		BT_SIGNAL,   //!< Build a signal
+		BT_DEPOT,    //!< Build a depot
+		BT_STATION,  //!< Build a station
+		BT_WAYPOINT, //!< Build a rail waypoint
+	};
+
+	/**
 	 * Checks whether the given tile is actually a tile with rail that can be
 	 *  used to traverse a tile. This excludes rail depots but includes
 	 *  stations and waypoints.
@@ -419,6 +430,15 @@
 	 * @return Whether the signal has been/can be removed or not.
 	 */
 	static bool RemoveSignal(TileIndex tile, TileIndex front);
+
+	/**
+	 * Get the baseprice of building a rail-related object.
+	 * @param railtype the railtype that is build (on)
+	 * @param build_type the type of object to build
+	 * @pre IsRailTypeAvailable(railtype)
+	 * @return The baseprice of building the given object.
+	 */
+	static Money GetBuildCost(RailType railtype, BuildType build_type);
 };
 
 #endif /* AI_RAIL_HPP */
--- a/src/ai/api/ai_rail.hpp.sq
+++ b/src/ai/api/ai_rail.hpp.sq
@@ -21,6 +21,8 @@
 	template <> int Return<AIRail::RailTrack>(HSQUIRRELVM vm, AIRail::RailTrack res) { sq_pushinteger(vm, (int32)res); return 1; }
 	template <> AIRail::SignalType GetParam(ForceType<AIRail::SignalType>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (AIRail::SignalType)tmp; }
 	template <> int Return<AIRail::SignalType>(HSQUIRRELVM vm, AIRail::SignalType res) { sq_pushinteger(vm, (int32)res); return 1; }
+	template <> AIRail::BuildType GetParam(ForceType<AIRail::BuildType>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (AIRail::BuildType)tmp; }
+	template <> int Return<AIRail::BuildType>(HSQUIRRELVM vm, AIRail::BuildType res) { sq_pushinteger(vm, (int32)res); return 1; }
 
 	/* Allow AIRail to be used as Squirrel parameter */
 	template <> AIRail *GetParam(ForceType<AIRail *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return  (AIRail *)instance; }
@@ -60,6 +62,11 @@
 	SQAIRail.DefSQConst(engine, AIRail::SIGNALTYPE_EXIT_TWOWAY,           "SIGNALTYPE_EXIT_TWOWAY");
 	SQAIRail.DefSQConst(engine, AIRail::SIGNALTYPE_COMBO_TWOWAY,          "SIGNALTYPE_COMBO_TWOWAY");
 	SQAIRail.DefSQConst(engine, AIRail::SIGNALTYPE_NONE,                  "SIGNALTYPE_NONE");
+	SQAIRail.DefSQConst(engine, AIRail::BT_TRACK,                         "BT_TRACK");
+	SQAIRail.DefSQConst(engine, AIRail::BT_SIGNAL,                        "BT_SIGNAL");
+	SQAIRail.DefSQConst(engine, AIRail::BT_DEPOT,                         "BT_DEPOT");
+	SQAIRail.DefSQConst(engine, AIRail::BT_STATION,                       "BT_STATION");
+	SQAIRail.DefSQConst(engine, AIRail::BT_WAYPOINT,                      "BT_WAYPOINT");
 
 	AIError::RegisterErrorMap(STR_ERROR_CROSSING_ON_ONEWAY_ROAD,        AIRail::ERR_CROSSING_ON_ONEWAY_ROAD);
 	AIError::RegisterErrorMap(STR_ERROR_NO_SUITABLE_RAILROAD_TRACK,     AIRail::ERR_UNSUITABLE_TRACK);
@@ -98,6 +105,7 @@
 	SQAIRail.DefSQStaticMethod(engine, &AIRail::GetSignalType,                   "GetSignalType",                   3, ".ii");
 	SQAIRail.DefSQStaticMethod(engine, &AIRail::BuildSignal,                     "BuildSignal",                     4, ".iii");
 	SQAIRail.DefSQStaticMethod(engine, &AIRail::RemoveSignal,                    "RemoveSignal",                    3, ".ii");
+	SQAIRail.DefSQStaticMethod(engine, &AIRail::GetBuildCost,                    "GetBuildCost",                    3, ".ii");
 
 	SQAIRail.PostRegister(engine);
 }
--- a/src/ai/api/ai_road.cpp
+++ b/src/ai/api/ai_road.cpp
@@ -579,3 +579,16 @@
 
 	return AIObject::DoCommand(tile, 0, GetRoadStopType(tile), CMD_REMOVE_ROAD_STOP);
 }
+
+/* static */ Money AIRoad::GetBuildCost(RoadType roadtype, BuildType build_type)
+{
+	if (!AIRoad::IsRoadTypeAvailable(roadtype)) return -1;
+
+	switch (build_type) {
+		case BT_ROAD:       return ::GetPrice(PR_BUILD_ROAD, 1, NULL);
+		case BT_DEPOT:      return ::GetPrice(PR_BUILD_DEPOT_ROAD, 1, NULL);
+		case BT_BUS_STOP:   return ::GetPrice(PR_BUILD_STATION_BUS, 1, NULL);
+		case BT_TRUCK_STOP: return ::GetPrice(PR_BUILD_STATION_TRUCK, 1, NULL);
+		default: return -1;
+	}
+}
--- a/src/ai/api/ai_road.hpp
+++ b/src/ai/api/ai_road.hpp
@@ -64,6 +64,16 @@
 	};
 
 	/**
+	 * Types of road-related objects in the game.
+	 */
+	enum BuildType {
+		BT_ROAD,       //!< Build a piece of road
+		BT_DEPOT,      //!< Build a road depot
+		BT_BUS_STOP,   //!< Build a bus stop
+		BT_TRUCK_STOP, //!< Build a truck stop
+	};
+
+	/**
 	 * Determines whether a busstop or a truckstop is needed to transport a certain cargo.
 	 * @param cargo_type The cargo to test.
 	 * @pre AICargo::IsValidCargo(cargo_type).
@@ -451,6 +461,15 @@
 	 */
 	static bool RemoveRoadStation(TileIndex tile);
 
+	/**
+	 * Get the baseprice of building a road-related object.
+	 * @param roadtype the roadtype that is build (on)
+	 * @param build_type the type of object to build
+	 * @pre IsRoadTypeAvailable(railtype)
+	 * @return The baseprice of building the given object.
+	 */
+	static Money GetBuildCost(RoadType roadtype, BuildType build_type);
+
 private:
 
 	/**
--- a/src/ai/api/ai_road.hpp.sq
+++ b/src/ai/api/ai_road.hpp.sq
@@ -19,6 +19,8 @@
 	template <> int Return<AIRoad::RoadType>(HSQUIRRELVM vm, AIRoad::RoadType res) { sq_pushinteger(vm, (int32)res); return 1; }
 	template <> AIRoad::RoadVehicleType GetParam(ForceType<AIRoad::RoadVehicleType>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (AIRoad::RoadVehicleType)tmp; }
 	template <> int Return<AIRoad::RoadVehicleType>(HSQUIRRELVM vm, AIRoad::RoadVehicleType res) { sq_pushinteger(vm, (int32)res); return 1; }
+	template <> AIRoad::BuildType GetParam(ForceType<AIRoad::BuildType>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (AIRoad::BuildType)tmp; }
+	template <> int Return<AIRoad::BuildType>(HSQUIRRELVM vm, AIRoad::BuildType 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, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return  (AIRoad *)instance; }
@@ -44,6 +46,10 @@
 	SQAIRoad.DefSQConst(engine, AIRoad::ROADTYPE_INVALID,                             "ROADTYPE_INVALID");
 	SQAIRoad.DefSQConst(engine, AIRoad::ROADVEHTYPE_BUS,                              "ROADVEHTYPE_BUS");
 	SQAIRoad.DefSQConst(engine, AIRoad::ROADVEHTYPE_TRUCK,                            "ROADVEHTYPE_TRUCK");
+	SQAIRoad.DefSQConst(engine, AIRoad::BT_ROAD,                                      "BT_ROAD");
+	SQAIRoad.DefSQConst(engine, AIRoad::BT_DEPOT,                                     "BT_DEPOT");
+	SQAIRoad.DefSQConst(engine, AIRoad::BT_BUS_STOP,                                  "BT_BUS_STOP");
+	SQAIRoad.DefSQConst(engine, AIRoad::BT_TRUCK_STOP,                                "BT_TRUCK_STOP");
 
 	AIError::RegisterErrorMap(STR_ERROR_ROAD_WORKS_IN_PROGRESS,           AIRoad::ERR_ROAD_WORKS_IN_PROGRESS);
 	AIError::RegisterErrorMap(STR_ERROR_DRIVE_THROUGH_DIRECTION,          AIRoad::ERR_ROAD_DRIVE_THROUGH_WRONG_DIRECTION);
@@ -82,6 +88,7 @@
 	SQAIRoad.DefSQStaticMethod(engine, &AIRoad::RemoveRoadFull,                 "RemoveRoadFull",                 3, ".ii");
 	SQAIRoad.DefSQStaticMethod(engine, &AIRoad::RemoveRoadDepot,                "RemoveRoadDepot",                2, ".i");
 	SQAIRoad.DefSQStaticMethod(engine, &AIRoad::RemoveRoadStation,              "RemoveRoadStation",              2, ".i");
+	SQAIRoad.DefSQStaticMethod(engine, &AIRoad::GetBuildCost,                   "GetBuildCost",                   3, ".ii");
 
 	SQAIRoad.PostRegister(engine);
 }
--- a/src/ai/api/ai_tile.cpp
+++ b/src/ai/api/ai_tile.cpp
@@ -19,6 +19,7 @@
 #include "../../tree_map.h"
 #include "../../town.h"
 #include "../../landscape.h"
+#include "../../economy_func.h"
 
 /* static */ bool AITile::IsBuildable(TileIndex tile)
 {
@@ -271,3 +272,18 @@
 
 	return ::ClosestTownFromTile(tile, UINT_MAX)->index;
 }
+
+/* static */ Money AITile::GetBuildCost(BuildType build_type)
+{
+	switch (build_type) {
+		case BT_FOUNDATION:   return ::GetPrice(PR_BUILD_FOUNDATION, 1, NULL);
+		case BT_TERRAFORM:    return ::GetPrice(PR_TERRAFORM, 1, NULL);
+		case BT_BUILD_TREES:  return ::GetPrice(PR_BUILD_TREES, 1, NULL);
+		case BT_CLEAR_GRASS:  return ::GetPrice(PR_CLEAR_GRASS, 1, NULL);
+		case BT_CLEAR_ROUGH:  return ::GetPrice(PR_CLEAR_ROUGH, 1, NULL);
+		case BT_CLEAR_ROCKY:  return ::GetPrice(PR_CLEAR_ROCKS, 1, NULL);
+		case BT_CLEAR_FIELDS: return ::GetPrice(PR_CLEAR_FIELDS, 1, NULL);
+		case BT_CLEAR_HOUSE:  return ::GetPrice(PR_CLEAR_HOUSE, 1, NULL);
+		default: return -1;
+	}
+}
--- a/src/ai/api/ai_tile.hpp
+++ b/src/ai/api/ai_tile.hpp
@@ -104,6 +104,20 @@
 	};
 
 	/**
+	 * Get the base cost for building/clearing several things.
+	 */
+	enum BuildType {
+		BT_FOUNDATION,   //!< Build a foundation under something
+		BT_TERRAFORM,    //!< Terraform
+		BT_BUILD_TREES,  //!< Build trees
+		BT_CLEAR_GRASS,  //!< Clear a tile with just grass
+		BT_CLEAR_ROUGH,  //!< Clear a rough tile
+		BT_CLEAR_ROCKY,  //!< Clear a tile with rocks
+		BT_CLEAR_FIELDS, //!< Clear a tile with farm fields
+		BT_CLEAR_HOUSE,  //!< Clear a tile with a house
+	};
+
+	/**
 	 * Check if this tile is buildable, i.e. no things on it that needs
 	 *  demolishing.
 	 * @param tile The tile to check on.
@@ -435,6 +449,13 @@
 	 * @return The TownID of the town closest to the tile.
 	 */
 	static TownID GetClosestTown(TileIndex tile);
+
+	/**
+	 * Get the baseprice of building/clearing various tile-related things.
+	 * @param build_type the type to build
+	 * @return The baseprice of building or removing the given object.
+	 */
+	static Money GetBuildCost(BuildType build_type);
 };
 
 #endif /* AI_TILE_HPP */
--- a/src/ai/api/ai_tile.hpp.sq
+++ b/src/ai/api/ai_tile.hpp.sq
@@ -21,6 +21,8 @@
 	template <> int Return<AITile::Slope>(HSQUIRRELVM vm, AITile::Slope res) { sq_pushinteger(vm, (int32)res); return 1; }
 	template <> AITile::TransportType GetParam(ForceType<AITile::TransportType>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (AITile::TransportType)tmp; }
 	template <> int Return<AITile::TransportType>(HSQUIRRELVM vm, AITile::TransportType res) { sq_pushinteger(vm, (int32)res); return 1; }
+	template <> AITile::BuildType GetParam(ForceType<AITile::BuildType>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (AITile::BuildType)tmp; }
+	template <> int Return<AITile::BuildType>(HSQUIRRELVM vm, AITile::BuildType res) { sq_pushinteger(vm, (int32)res); return 1; }
 
 	/* Allow AITile to be used as Squirrel parameter */
 	template <> AITile *GetParam(ForceType<AITile *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return  (AITile *)instance; }
@@ -73,6 +75,14 @@
 	SQAITile.DefSQConst(engine, AITile::TRANSPORT_WATER,             "TRANSPORT_WATER");
 	SQAITile.DefSQConst(engine, AITile::TRANSPORT_AIR,               "TRANSPORT_AIR");
 	SQAITile.DefSQConst(engine, AITile::TRANSPORT_INVALID,           "TRANSPORT_INVALID");
+	SQAITile.DefSQConst(engine, AITile::BT_FOUNDATION,               "BT_FOUNDATION");
+	SQAITile.DefSQConst(engine, AITile::BT_TERRAFORM,                "BT_TERRAFORM");
+	SQAITile.DefSQConst(engine, AITile::BT_BUILD_TREES,              "BT_BUILD_TREES");
+	SQAITile.DefSQConst(engine, AITile::BT_CLEAR_GRASS,              "BT_CLEAR_GRASS");
+	SQAITile.DefSQConst(engine, AITile::BT_CLEAR_ROUGH,              "BT_CLEAR_ROUGH");
+	SQAITile.DefSQConst(engine, AITile::BT_CLEAR_ROCKY,              "BT_CLEAR_ROCKY");
+	SQAITile.DefSQConst(engine, AITile::BT_CLEAR_FIELDS,             "BT_CLEAR_FIELDS");
+	SQAITile.DefSQConst(engine, AITile::BT_CLEAR_HOUSE,              "BT_CLEAR_HOUSE");
 
 	AIError::RegisterErrorMap(STR_ERROR_ALREADY_AT_SEA_LEVEL,    AITile::ERR_TILE_TOO_HIGH);
 	AIError::RegisterErrorMap(STR_ERROR_ALREADY_AT_SEA_LEVEL,    AITile::ERR_TILE_TOO_LOW);
@@ -116,6 +126,7 @@
 	SQAITile.DefSQStaticMethod(engine, &AITile::PlantTreeRectangle,         "PlantTreeRectangle",         4, ".iii");
 	SQAITile.DefSQStaticMethod(engine, &AITile::IsWithinTownInfluence,      "IsWithinTownInfluence",      3, ".ii");
 	SQAITile.DefSQStaticMethod(engine, &AITile::GetClosestTown,             "GetClosestTown",             2, ".i");
+	SQAITile.DefSQStaticMethod(engine, &AITile::GetBuildCost,               "GetBuildCost",               2, ".i");
 
 	SQAITile.PostRegister(engine);
 }