(svn r11107) -Feature: some tool so one can still build tunnels under rails (and other structures) when the owner of the structure built it on foundations and if you have enough "empty" space ofcourse. One could use the tool for some other construction needs too. Patch by frosch.
authorrubidium
Fri, 14 Sep 2007 22:27:40 +0000
changeset 8078 bdf94bf88568
parent 8077 92edb3688fdf
child 8079 037a8b09887c
(svn r11107) -Feature: some tool so one can still build tunnels under rails (and other structures) when the owner of the structure built it on foundations and if you have enough "empty" space ofcourse. One could use the tool for some other construction needs too. Patch by frosch.
source.list
src/industry_cmd.cpp
src/lang/english.txt
src/newgrf_callbacks.h
src/rail_cmd.cpp
src/road_cmd.cpp
src/saveload.cpp
src/settings.cpp
src/settings_gui.cpp
src/slope.h
src/station_cmd.cpp
src/town_cmd.cpp
src/tunnelbridge_cmd.cpp
src/unmovable_cmd.cpp
src/variables.h
--- a/source.list	Fri Sep 14 22:25:00 2007 +0000
+++ b/source.list	Fri Sep 14 22:27:40 2007 +0000
@@ -100,6 +100,7 @@
 airport.h
 airport_movement.h
 articulated_vehicles.h
+autoslope.h
 aystar.h
 bmp.h
 cargopacket.h
--- a/src/industry_cmd.cpp	Fri Sep 14 22:25:00 2007 +0000
+++ b/src/industry_cmd.cpp	Fri Sep 14 22:27:40 2007 +0000
@@ -36,6 +36,7 @@
 #include "newgrf_industrytiles.h"
 #include "newgrf_callbacks.h"
 #include "misc/autoptr.hpp"
+#include "autoslope.h"
 
 void ShowIndustryViewWindow(int industry);
 void BuildOilRig(TileIndex tile);
@@ -1974,6 +1975,30 @@
 
 static CommandCost TerraformTile_Industry(TileIndex tile, uint32 flags, uint z_new, Slope tileh_new)
 {
+	if (AutoslopeEnabled()) {
+		/* We imitate here TTDP's behaviour:
+		 *  - Both new and old slope must not be steep.
+		 *  - TileMaxZ must not be changed.
+		 *  - Allow autoslope by default.
+		 *  - Disallow autoslope if callback succeeds and returns non-zero.
+		 */
+		Slope tileh_old = GetTileSlope(tile, NULL);
+		/* TileMaxZ must not be changed. Slopes must not be steep. */
+		if (!IsSteepSlope(tileh_old) && !IsSteepSlope(tileh_new) && (GetTileMaxZ(tile) == z_new + GetSlopeMaxZ(tileh_new))) {
+			const IndustryGfx gfx = GetIndustryGfx(tile);
+			const IndustryTileSpec *itspec = GetIndustryTileSpec(gfx);
+
+			/* Call callback 3C 'disable autosloping for industry tiles'. */
+			if (HASBIT(itspec->callback_flags, CBM_INDT_AUTOSLOPE)) {
+				/* If the callback fails, allow autoslope. */
+				uint16 res = GetIndustryTileCallback(CBID_INDUSTRY_AUTOSLOPE, 0, 0, gfx, GetIndustryByTile(tile), tile);
+				if ((res == 0) || (res == CALLBACK_FAILED)) return _price.terraform;
+			} else {
+				// allow autoslope
+				return _price.terraform;
+			}
+		}
+	}
 	return DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR); // funny magic bulldozer
 }
 
--- a/src/lang/english.txt	Fri Sep 14 22:25:00 2007 +0000
+++ b/src/lang/english.txt	Fri Sep 14 22:27:40 2007 +0000
@@ -1020,6 +1020,7 @@
 STR_CONFIG_PATCHES_ON                                           :On
 STR_CONFIG_PATCHES_VEHICLESPEED                                 :{LTBLUE}Show vehicle speed in status bar: {ORANGE}{STRING1}
 STR_CONFIG_PATCHES_BUILDONSLOPES                                :{LTBLUE}Allow building on slopes and coasts: {ORANGE}{STRING1}
+STR_CONFIG_PATCHES_AUTOSLOPE                                    :{LTBLUE}Allow terraforming under buildings, tracks, etc. (autoslope): {ORANGE}{STRING1}
 STR_CONFIG_PATCHES_CATCHMENT                                    :{LTBLUE}Allow more realistically sized catchment areas: {ORANGE}{STRING1}
 STR_CONFIG_PATCHES_EXTRADYNAMITE                                :{LTBLUE}Allow removal of more town-owned roads, bridges, etc: {ORANGE}{STRING1}
 STR_CONFIG_PATCHES_MAMMOTHTRAINS                                :{LTBLUE}Enable building very long trains: {ORANGE}{STRING1}
--- a/src/newgrf_callbacks.h	Fri Sep 14 22:25:00 2007 +0000
+++ b/src/newgrf_callbacks.h	Fri Sep 14 22:27:40 2007 +0000
@@ -160,7 +160,7 @@
 	CBID_INDUSTRY_SPECIAL_EFFECT         = 0x3B,
 
 	/** Called to determine if industry can alter the ground below industry tile */
-	CBID_INDUSTRY_AUTOSLOPE              = 0x3C, // not implemented
+	CBID_INDUSTRY_AUTOSLOPE              = 0x3C,
 
 	/** Called to determine if the industry can still accept or refuse more cargo arrival */
 	CBID_INDUSTRY_REFUSE_CARGO           = 0x3D,
--- a/src/rail_cmd.cpp	Fri Sep 14 22:25:00 2007 +0000
+++ b/src/rail_cmd.cpp	Fri Sep 14 22:27:40 2007 +0000
@@ -39,6 +39,7 @@
 #include "newgrf_station.h"
 #include "train.h"
 #include "misc/autoptr.hpp"
+#include "autoslope.h"
 
 const byte _track_sloped_sprites[14] = {
 	14, 15, 22, 13,
@@ -219,8 +220,11 @@
 {
 	if (IsSteepSlope(tileh)) {
 		if (_patches.build_on_slopes && existing == 0) {
-			TrackBits valid = TRACK_BIT_CROSS | (HASBIT(1 << SLOPE_STEEP_W | 1 << SLOPE_STEEP_E, tileh) ? TRACK_BIT_VERT : TRACK_BIT_HORZ);
-			if (valid & rail_bits) return _price.terraform;
+			/* There may only be one track on steep slopes. (Autoslope calls with multiple bits in rail_bits) */
+			if (KILL_FIRST_BIT(rail_bits & TRACK_BIT_MASK) == 0) {
+				TrackBits valid = TRACK_BIT_CROSS | (HASBIT(1 << SLOPE_STEEP_W | 1 << SLOPE_STEEP_E, tileh) ? TRACK_BIT_VERT : TRACK_BIT_HORZ);
+				if (valid & rail_bits) return _price.terraform;
+			}
 		}
 	} else {
 		rail_bits |= existing;
@@ -2189,15 +2193,62 @@
 	return VETSB_CONTINUE;
 }
 
+/**
+ * Tests if autoslope is allowed.
+ *
+ * @param tile The tile.
+ * @param flags Terraform command flags.
+ * @param z_old Old TileZ.
+ * @param tileh_old Old TileSlope.
+ * @param z_new New TileZ.
+ * @param tileh_new New TileSlope.
+ * @param rail_bits Trackbits.
+ */
+static CommandCost TestAutoslopeOnRailTile(TileIndex tile, uint flags, uint z_old, Slope tileh_old, uint z_new, Slope tileh_new, TrackBits rail_bits)
+{
+	if (!_patches.build_on_slopes || !AutoslopeEnabled()) return CMD_ERROR;
+
+	/* Is the slope-rail_bits combination valid in general? I.e. is it save to call GetRailFoundation() ? */
+	if (CmdFailed(CheckRailSlope(tileh_new, rail_bits, TRACK_BIT_NONE, tile))) return CMD_ERROR;
+
+	/* Get the slopes on top of the foundations */
+	z_old += ApplyFoundationToSlope(GetRailFoundation(tileh_old, rail_bits), &tileh_old);
+	z_new += ApplyFoundationToSlope(GetRailFoundation(tileh_new, rail_bits), &tileh_new);
+
+	Slope track_corner;
+	switch (rail_bits) {
+		case TRACK_BIT_LEFT:  track_corner = SLOPE_W; break;
+		case TRACK_BIT_LOWER: track_corner = SLOPE_S; break;
+		case TRACK_BIT_RIGHT: track_corner = SLOPE_E; break;
+		case TRACK_BIT_UPPER: track_corner = SLOPE_N; break;
+
+		/* Surface slope must not be changed */
+		default: return (((z_old != z_new) || (tileh_old != tileh_new)) ? CMD_ERROR : _price.terraform);
+	}
+
+	/* The height of the track_corner must not be changed. The rest ensures GetRailFoundation() already. */
+	if ((tileh_old & track_corner) != 0) z_old += TILE_HEIGHT;
+	if ((tileh_new & track_corner) != 0) z_new += TILE_HEIGHT;
+	if (z_old != z_new) return CMD_ERROR;
+
+	/* Make the ground dirty, if surface slope has changed */
+	if ((tileh_old != tileh_new) && ((flags & DC_EXEC) != 0)) SetRailGroundType(tile, RAIL_GROUND_BARREN);
+
+	return _price.terraform;
+}
+
 static CommandCost TerraformTile_Track(TileIndex tile, uint32 flags, uint z_new, Slope tileh_new)
 {
+	uint z_old;
+	Slope tileh_old = GetTileSlope(tile, &z_old);
 	if (IsPlainRailTile(tile)) {
-		uint z_old;
-		Slope tileh_old = GetTileSlope(tile, &z_old);
 		TrackBits rail_bits = GetTrackBits(tile);
 
 		_error_message = STR_1008_MUST_REMOVE_RAILROAD_TRACK;
 
+		/* First test autoslope. However if it succeeds we still have to test the rest, because non-autoslope terraforming is cheaper. */
+		CommandCost autoslope_result = TestAutoslopeOnRailTile(tile, flags, z_old, tileh_old, z_new, tileh_new, rail_bits);
+
 		/* When there is only a single horizontal/vertical track, one corner can be terraformed. */
 		Slope allowed_corner;
 		switch (rail_bits) {
@@ -2205,7 +2256,7 @@
 			case TRACK_BIT_UPPER: allowed_corner = SLOPE_S; break;
 			case TRACK_BIT_LEFT:  allowed_corner = SLOPE_E; break;
 			case TRACK_BIT_LOWER: allowed_corner = SLOPE_N; break;
-			default: return CMD_ERROR;
+			default: return autoslope_result;
 		}
 
 		Slope track_corners = ComplementSlope(allowed_corner);
@@ -2221,28 +2272,28 @@
 					z_new += TILE_HEIGHT;
 				} else {
 					/* do not build a foundation */
-					if ((tileh_new != SLOPE_FLAT) && (tileh_new != allowed_corner)) return CMD_ERROR;
+					if ((tileh_new != SLOPE_FLAT) && (tileh_new != allowed_corner)) return autoslope_result;
 				}
 
 				/* Track height must remain unchanged */
-				if (z_old != z_new) return CMD_ERROR;
+				if (z_old != z_new) return autoslope_result;
 				break;
 
 			case FOUNDATION_LEVELED:
 				/* Is allowed_corner covered by the foundation? */
-				if ((tileh_old & allowed_corner) == 0) return CMD_ERROR;
+				if ((tileh_old & allowed_corner) == 0) return autoslope_result;
 
 				/* allowed_corner may only be raised -> steep slope */
-				if ((z_old != z_new) || (tileh_new != (tileh_old | SLOPE_STEEP))) return CMD_ERROR;
+				if ((z_old != z_new) || (tileh_new != (tileh_old | SLOPE_STEEP))) return autoslope_result;
 				break;
 
 			case FOUNDATION_STEEP_LOWER:
 				/* Only allow to lower highest corner */
-				if ((z_old != z_new) || (tileh_new != (tileh_old & ~SLOPE_STEEP))) return CMD_ERROR;
+				if ((z_old != z_new) || (tileh_new != (tileh_old & ~SLOPE_STEEP))) return autoslope_result;
 				break;
 
 			case FOUNDATION_STEEP_HIGHER:
-				return CMD_ERROR;
+				return autoslope_result;
 
 			default: NOT_REACHED();
 		}
@@ -2252,6 +2303,22 @@
 
 		/* allow terraforming, no extra costs */
 		return CommandCost();
+	} else {
+		if (_patches.build_on_slopes && AutoslopeEnabled()) {
+			switch (GetRailTileType(tile)) {
+				case RAIL_TILE_WAYPOINT: {
+					CommandCost cost = TestAutoslopeOnRailTile(tile, flags, z_old, tileh_old, z_new, tileh_new, GetRailWaypointBits(tile));
+					if (!CmdFailed(cost)) return cost; // allow autoslope
+					break;
+				}
+
+				case RAIL_TILE_DEPOT:
+					if (AutoslopeCheckForEntranceEdge(tile, z_new, tileh_new, GetRailDepotDirection(tile))) return _price.terraform;
+					break;
+
+				default: NOT_REACHED();
+			}
+		}
 	}
 	return DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
 }
--- a/src/road_cmd.cpp	Fri Sep 14 22:25:00 2007 +0000
+++ b/src/road_cmd.cpp	Fri Sep 14 22:27:40 2007 +0000
@@ -32,6 +32,12 @@
 #include "station_map.h"
 #include "tunnel_map.h"
 #include "misc/autoptr.hpp"
+#include "autoslope.h"
+
+#define M(x) (1 << (x))
+/* Level crossings may only be built on these slopes */
+static const uint32 VALID_LEVEL_CROSSING_SLOPES = (M(SLOPE_SEN) | M(SLOPE_ENW) | M(SLOPE_NWS) | M(SLOPE_NS) | M(SLOPE_WSE) | M(SLOPE_EW) | M(SLOPE_FLAT));
+#undef M
 
 bool CheckAllowRemoveRoad(TileIndex tile, RoadBits remove, Owner owner, bool *edge_road, RoadType rt)
 {
@@ -405,12 +411,10 @@
 				return_cmd_error(STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION);
 			}
 
-#define M(x) (1 << (x))
 			/* Level crossings may only be built on these slopes */
-			if (!HASBIT(M(SLOPE_SEN) | M(SLOPE_ENW) | M(SLOPE_NWS) | M(SLOPE_NS) | M(SLOPE_WSE) | M(SLOPE_EW) | M(SLOPE_FLAT), tileh)) {
+			if (!HASBIT(VALID_LEVEL_CROSSING_SLOPES, tileh)) {
 				return_cmd_error(STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION);
 			}
-#undef M
 
 			if (GetRailTileType(tile) != RAIL_TILE_NORMAL) goto do_clear;
 			switch (GetTrackBits(tile)) {
@@ -1372,6 +1376,41 @@
 
 static CommandCost TerraformTile_Road(TileIndex tile, uint32 flags, uint z_new, Slope tileh_new)
 {
+	if (_patches.build_on_slopes && AutoslopeEnabled()) {
+		switch (GetRoadTileType(tile)) {
+			case ROAD_TILE_CROSSING:
+				if (!IsSteepSlope(tileh_new) && (GetTileMaxZ(tile) == z_new + GetSlopeMaxZ(tileh_new)) && HASBIT(VALID_LEVEL_CROSSING_SLOPES, tileh_new)) return _price.terraform;
+				break;
+
+			case ROAD_TILE_DEPOT:
+				if (AutoslopeCheckForEntranceEdge(tile, z_new, tileh_new, GetRoadDepotDirection(tile))) return _price.terraform;
+				break;
+
+			case ROAD_TILE_NORMAL: {
+				RoadBits bits = GetAllRoadBits(tile);
+				RoadBits bits_copy = bits;
+				/* Check if the slope-road_bits combination is valid at all, i.e. it is save to call GetRoadFoundation(). */
+				if (!CmdFailed(CheckRoadSlope(tileh_new, &bits_copy, ROAD_NONE))) {
+					/* CheckRoadSlope() sometimes changes the road_bits, if it does not agree with them. */
+					if (bits == bits_copy) {
+						uint z_old;
+						Slope tileh_old = GetTileSlope(tile, &z_old);
+
+						/* Get the slope on top of the foundation */
+						z_old += ApplyFoundationToSlope(GetRoadFoundation(tileh_old, bits), &tileh_old);
+						z_new += ApplyFoundationToSlope(GetRoadFoundation(tileh_new, bits), &tileh_new);
+
+						/* The surface slope must not be changed */
+						if ((z_old == z_new) && (tileh_old == tileh_new)) return _price.terraform;
+					}
+				}
+				break;
+			}
+
+			default: NOT_REACHED();
+		}
+	}
+
 	return DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
 }
 
--- a/src/saveload.cpp	Fri Sep 14 22:25:00 2007 +0000
+++ b/src/saveload.cpp	Fri Sep 14 22:27:40 2007 +0000
@@ -29,7 +29,7 @@
 #include "strings.h"
 #include <list>
 
-extern const uint16 SAVEGAME_VERSION = 74;
+extern const uint16 SAVEGAME_VERSION = 75;
 uint16 _sl_version;       ///< the major savegame version identifier
 byte   _sl_minor_version; ///< the minor savegame version, DO NOT USE!
 
--- a/src/settings.cpp	Fri Sep 14 22:25:00 2007 +0000
+++ b/src/settings.cpp	Fri Sep 14 22:27:40 2007 +0000
@@ -1362,6 +1362,7 @@
 	/***************************************************************************/
 	/* Construction section of the GUI-configure patches window */
 	SDT_BOOL(Patches, build_on_slopes,               0, 0,  true,        STR_CONFIG_PATCHES_BUILDONSLOPES,       NULL),
+	SDT_CONDBOOL(Patches, autoslope,                75, SL_MAX_VERSION, 0, 0, true,  STR_CONFIG_PATCHES_AUTOSLOPE,            NULL),
 	SDT_BOOL(Patches, extra_dynamite,                0, 0, false,        STR_CONFIG_PATCHES_EXTRADYNAMITE,       NULL),
 	SDT_BOOL(Patches, longbridges,                   0, 0,  true,        STR_CONFIG_PATCHES_LONGBRIDGES,         NULL),
 	SDT_BOOL(Patches, signal_side,                   N, 0,  true,        STR_CONFIG_PATCHES_SIGNALSIDE,          RedrawScreen),
--- a/src/settings_gui.cpp	Fri Sep 14 22:25:00 2007 +0000
+++ b/src/settings_gui.cpp	Fri Sep 14 22:27:40 2007 +0000
@@ -664,6 +664,7 @@
 
 static const char *_patches_construction[] = {
 	"build_on_slopes",
+	"autoslope",
 	"extra_dynamite",
 	"longbridges",
 	"signal_side",
--- a/src/slope.h	Fri Sep 14 22:25:00 2007 +0000
+++ b/src/slope.h	Fri Sep 14 22:27:40 2007 +0000
@@ -90,6 +90,19 @@
 	}
 }
 
+/**
+ * Returns the height of the highest corner of a slope relative to TileZ (= minimal height)
+ *
+ * @param s The #Slope.
+ * @return Relative height of highest corner.
+ */
+static inline uint GetSlopeMaxZ(Slope s)
+{
+	if (s == SLOPE_FLAT) return 0;
+	if (IsSteepSlope(s)) return 2 * TILE_HEIGHT;
+	return TILE_HEIGHT;
+}
+
 
 /**
  * Enumeration for Foundations.
--- a/src/station_cmd.cpp	Fri Sep 14 22:25:00 2007 +0000
+++ b/src/station_cmd.cpp	Fri Sep 14 22:27:40 2007 +0000
@@ -42,6 +42,7 @@
 #include "road.h"
 #include "cargotype.h"
 #include "strings.h"
+#include "autoslope.h"
 
 DEFINE_OLD_POOL_GENERIC(Station, Station)
 DEFINE_OLD_POOL_GENERIC(RoadStop, RoadStop)
@@ -2880,6 +2881,36 @@
 
 static CommandCost TerraformTile_Station(TileIndex tile, uint32 flags, uint z_new, Slope tileh_new)
 {
+	if (_patches.build_on_slopes && AutoslopeEnabled()) {
+		/* TODO: If you implement newgrf callback 149 'land slope check', you have to decide what to do with it here.
+		 *       TTDP does not call it.
+		 */
+		if (!IsSteepSlope(tileh_new) && (GetTileMaxZ(tile) == z_new + GetSlopeMaxZ(tileh_new))) {
+			switch (GetStationType(tile)) {
+				case STATION_RAIL: {
+					DiagDirection direction = AxisToDiagDir(GetRailStationAxis(tile));
+					if (!AutoslopeCheckForEntranceEdge(tile, z_new, tileh_new, direction)) break;
+					if (!AutoslopeCheckForEntranceEdge(tile, z_new, tileh_new, ReverseDiagDir(direction))) break;
+					return _price.terraform;
+				}
+
+				case STATION_AIRPORT:
+					return _price.terraform;
+
+				case STATION_TRUCK:
+				case STATION_BUS: {
+					DiagDirection direction = GetRoadStopDir(tile);
+					if (!AutoslopeCheckForEntranceEdge(tile, z_new, tileh_new, direction)) break;
+					if (IsDriveThroughStopTile(tile)) {
+						if (!AutoslopeCheckForEntranceEdge(tile, z_new, tileh_new, ReverseDiagDir(direction))) break;
+					}
+					return _price.terraform;
+				}
+
+				default: break;
+			}
+		}
+	}
 	return DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
 }
 
--- a/src/town_cmd.cpp	Fri Sep 14 22:25:00 2007 +0000
+++ b/src/town_cmd.cpp	Fri Sep 14 22:27:40 2007 +0000
@@ -41,6 +41,7 @@
 #include "newgrf_commons.h"
 #include "newgrf_townname.h"
 #include "misc/autoptr.hpp"
+#include "autoslope.h"
 
 /* Initialize the town-pool */
 DEFINE_OLD_POOL_GENERIC(Town, Town)
@@ -2309,6 +2310,15 @@
 
 static CommandCost TerraformTile_Town(TileIndex tile, uint32 flags, uint z_new, Slope tileh_new)
 {
+	if (AutoslopeEnabled()) {
+		HouseID house = GetHouseType(tile);
+		HouseSpec *hs = GetHouseSpecs(house);
+
+		/* Here we differ from TTDP by checking TILE_NOT_SLOPED */
+		if (((hs->building_flags & TILE_NOT_SLOPED) == 0) && !IsSteepSlope(tileh_new) &&
+			(GetTileMaxZ(tile) == z_new + GetSlopeMaxZ(tileh_new))) return _price.terraform;
+	}
+
 	return DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
 }
 
--- a/src/tunnelbridge_cmd.cpp	Fri Sep 14 22:25:00 2007 +0000
+++ b/src/tunnelbridge_cmd.cpp	Fri Sep 14 22:27:40 2007 +0000
@@ -32,6 +32,7 @@
 #include "yapf/yapf.h"
 #include "date.h"
 #include "newgrf_sound.h"
+#include "autoslope.h"
 
 #include "table/bridge_land.h"
 
@@ -1416,6 +1417,30 @@
 
 static CommandCost TerraformTile_TunnelBridge(TileIndex tile, uint32 flags, uint z_new, Slope tileh_new)
 {
+	if (_patches.build_on_slopes && AutoslopeEnabled() && IsBridge(tile)) {
+		DiagDirection direction = GetBridgeRampDirection(tile);
+		Axis axis = DiagDirToAxis(direction);
+		CommandCost res;
+
+		/* Check if new slope is valid for bridges in general (so we can savely call GetBridgeFoundation()) */
+		if ((direction == DIAGDIR_NW) || (direction == DIAGDIR_NE)) {
+			res = CheckBridgeSlopeSouth(axis, tileh_new);
+		} else {
+			res = CheckBridgeSlopeNorth(axis, tileh_new);
+		}
+
+		if (!CmdFailed(res)) {
+			uint z_old;
+			Slope tileh_old = GetTileSlope(tile, &z_old);
+
+			z_old += ApplyFoundationToSlope(GetBridgeFoundation(tileh_old, axis), &tileh_old);
+			z_new += ApplyFoundationToSlope(GetBridgeFoundation(tileh_new, axis), &tileh_new);
+
+			/* Surface slope remains unchanged? */
+			if ((z_old == z_new) && (tileh_old == tileh_new)) return _price.terraform;
+		}
+	}
+
 	return DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
 }
 
--- a/src/unmovable_cmd.cpp	Fri Sep 14 22:25:00 2007 +0000
+++ b/src/unmovable_cmd.cpp	Fri Sep 14 22:27:40 2007 +0000
@@ -24,6 +24,7 @@
 #include "table/unmovable_land.h"
 #include "genworld.h"
 #include "bridge.h"
+#include "autoslope.h"
 
 /** Destroy a HQ.
  * During normal gameplay you can only implicitely destroy a HQ when you are
@@ -408,6 +409,10 @@
 	/* Owned land remains unsold */
 	if (IsOwnedLand(tile) && CheckTileOwnership(tile)) return CommandCost();
 
+	if (AutoslopeEnabled() && (IsStatue(tile) || IsCompanyHQ(tile))) {
+		if (!IsSteepSlope(tileh_new) && (z_new + GetSlopeMaxZ(tileh_new) == GetTileMaxZ(tile))) return _price.terraform;
+	}
+
 	return DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
 }
 
--- a/src/variables.h	Fri Sep 14 22:25:00 2007 +0000
+++ b/src/variables.h	Fri Sep 14 22:27:40 2007 +0000
@@ -240,6 +240,8 @@
 
 	bool timetabling;        ///< Whether to allow timetabling.
 	bool timetable_in_ticks; ///< Whether to show the timetable in ticks rather than days.
+
+	bool autoslope;          ///< Allow terraforming under things.
 };
 
 VARDEF Patches _patches;