changeset 8413:5c456105e68a draft

(svn r11983) -Codechange: Add some helper functions for slopes and use them.
author frosch <frosch@openttd.org>
date Fri, 25 Jan 2008 15:47:58 +0000
parents d7441720c6e3
children 124ea89a5409
files src/ai/trolly/pathfinder.cpp src/dock_gui.cpp src/elrail.cpp src/landscape.cpp src/rail_cmd.cpp src/road_cmd.cpp src/slope_func.h src/station_cmd.cpp src/tunnelbridge_cmd.cpp src/viewport.cpp src/water_cmd.cpp
diffstat 11 files changed, 150 insertions(+), 107 deletions(-) [+]
line wrap: on
line diff
--- a/src/ai/trolly/pathfinder.cpp
+++ b/src/ai/trolly/pathfinder.cpp
@@ -341,14 +341,11 @@
 		// Next, check for tunnels!
 		// Tunnels can only be built on slopes corresponding to the direction
 		//  For now, we check both sides for this tile.. terraforming gives fuzzy result
-		if ((dir == DIAGDIR_NE && tileh == SLOPE_NE) ||
-				(dir == DIAGDIR_SE && tileh == SLOPE_SE) ||
-				(dir == DIAGDIR_SW && tileh == SLOPE_SW) ||
-				(dir == DIAGDIR_NW && tileh == SLOPE_NW)) {
+		if (tileh == InclinedSlope(dir)) {
 			// Now simply check if a tunnel can be build
 			ret = AI_DoCommand(tile, (PathFinderInfo->rail_or_road?0:0x200), 0, DC_AUTO, CMD_BUILD_TUNNEL);
 			tileh = GetTileSlope(_build_tunnel_endtile, NULL);
-			if (CmdSucceeded(ret) && (tileh == SLOPE_SW || tileh == SLOPE_SE || tileh == SLOPE_NW || tileh == SLOPE_NE)) {
+			if (CmdSucceeded(ret) && IsInclinedSlope(tileh)) {
 				aystar->neighbours[aystar->num_neighbours].tile = _build_tunnel_endtile;
 				aystar->neighbours[aystar->num_neighbours].user_data[0] = AI_PATHFINDER_FLAG_TUNNEL + (dir << 8);
 				aystar->neighbours[aystar->num_neighbours++].direction = 0;
@@ -400,10 +397,9 @@
 	if (parent_tileh != SLOPE_FLAT && parent->path.parent != NULL) {
 		// Skip if the tile was from a bridge or tunnel
 		if (parent->path.node.user_data[0] == 0 && current->user_data[0] == 0) {
-			static const uint32 SLOPED_TILEHS = (1 << SLOPE_NW) | (1 << SLOPE_SW) |  (1 << SLOPE_SE) | (1 << SLOPE_NE);
 			if (PathFinderInfo->rail_or_road) {
 				Foundation f = GetRailFoundation(parent_tileh, (TrackBits)(1 << AiNew_GetRailDirection(parent->path.parent->node.tile, parent->path.node.tile, current->tile)));
-				if (IsInclinedFoundation(f) || (!IsFoundation(f) && HasBit(SLOPED_TILEHS, parent_tileh))) {
+				if (IsInclinedFoundation(f) || (!IsFoundation(f) && IsInclinedSlope(parent_tileh))) {
 					res += AI_PATHFINDER_TILE_GOES_UP_PENALTY;
 				} else {
 					res += AI_PATHFINDER_FOUNDATION_PENALTY;
@@ -411,7 +407,7 @@
 			} else {
 				if (!IsRoad(parent->path.node.tile) || !IsTileType(parent->path.node.tile, MP_TUNNELBRIDGE)) {
 					Foundation f = GetRoadFoundation(parent_tileh, (RoadBits)AiNew_GetRoadDirection(parent->path.parent->node.tile, parent->path.node.tile, current->tile));
-					if (IsInclinedFoundation(f) || (!IsFoundation(f) && HasBit(SLOPED_TILEHS, parent_tileh))) {
+					if (IsInclinedFoundation(f) || (!IsFoundation(f) && IsInclinedSlope(parent_tileh))) {
 						res += AI_PATHFINDER_TILE_GOES_UP_PENALTY;
 					} else {
 						res += AI_PATHFINDER_FOUNDATION_PENALTY;
--- a/src/dock_gui.cpp
+++ b/src/dock_gui.cpp
@@ -19,6 +19,7 @@
 #include "viewport_func.h"
 #include "gfx_func.h"
 #include "player_func.h"
+#include "slope_func.h"
 
 #include "table/sprites.h"
 #include "table/strings.h"
@@ -189,14 +190,11 @@
 		TileIndex tile_from;
 		TileIndex tile_to;
 
-		tile_from = tile_to = e->we.place.tile;
-		switch (GetTileSlope(tile_from, NULL)) {
-			case SLOPE_SW: tile_to += TileDiffXY(-1,  0); break;
-			case SLOPE_SE: tile_to += TileDiffXY( 0, -1); break;
-			case SLOPE_NW: tile_to += TileDiffXY( 0,  1); break;
-			case SLOPE_NE: tile_to += TileDiffXY( 1,  0); break;
-			default: break;
-		}
+		tile_from = e->we.place.tile;
+
+		DiagDirection dir = GetInclinedSlopeDirection(GetTileSlope(tile_from, NULL));
+		tile_to = (dir != INVALID_DIAGDIR ? TileAddByDiagDir(tile_from, ReverseDiagDir(dir)) : tile_from);
+
 		VpSetPresizeRange(tile_from, tile_to);
 	} break;
 
--- a/src/elrail.cpp
+++ b/src/elrail.cpp
@@ -130,13 +130,7 @@
 		} else if (*tileh != SLOPE_FLAT) {
 			*tileh = SLOPE_FLAT;
 		} else {
-			switch (GetTunnelBridgeDirection(tile)) {
-				case DIAGDIR_NE: *tileh = SLOPE_NE; break;
-				case DIAGDIR_SE: *tileh = SLOPE_SE; break;
-				case DIAGDIR_SW: *tileh = SLOPE_SW; break;
-				case DIAGDIR_NW: *tileh = SLOPE_NW; break;
-				default: NOT_REACHED();
-			}
+			*tileh = InclinedSlope(GetTunnelBridgeDirection(tile));
 		}
 	}
 }
--- a/src/landscape.cpp
+++ b/src/landscape.cpp
@@ -142,7 +142,7 @@
 
 	int z = 0;
 
-	switch (corners & ~SLOPE_HALFTILE_MASK) {
+	switch (RemoveHalftileSlope(corners)) {
 	case SLOPE_W:
 		if (x - y >= 0)
 			z = (x - y) >> 1;
@@ -254,10 +254,7 @@
 int GetSlopeZInCorner(Slope tileh, Corner corner)
 {
 	assert(!IsHalftileSlope(tileh));
-	static const int _corner_slopes[4][2] = {
-		{ SLOPE_W, SLOPE_STEEP_W }, { SLOPE_S, SLOPE_STEEP_S }, { SLOPE_E, SLOPE_STEEP_E }, { SLOPE_N, SLOPE_STEEP_N }
-	};
-	return ((tileh & _corner_slopes[corner][0]) != 0 ? TILE_HEIGHT : 0) + (tileh == _corner_slopes[corner][1] ? TILE_HEIGHT : 0);
+	return ((tileh & SlopeWithOneCornerRaised(corner)) != 0 ? TILE_HEIGHT : 0) + (tileh == SteepSlope(corner) ? TILE_HEIGHT : 0);
 }
 
 /**
@@ -289,10 +286,18 @@
 
 	if ((tileh & corners[edge][0]) != 0) *z1 += TILE_HEIGHT; // z1 is raised
 	if ((tileh & corners[edge][1]) != 0) *z2 += TILE_HEIGHT; // z2 is raised
-	if ((tileh & ~SLOPE_HALFTILE_MASK) == corners[edge][2]) *z1 += TILE_HEIGHT; // z1 is highest corner of a steep slope
-	if ((tileh & ~SLOPE_HALFTILE_MASK) == corners[edge][3]) *z2 += TILE_HEIGHT; // z2 is highest corner of a steep slope
+	if (RemoveHalftileSlope(tileh) == corners[edge][2]) *z1 += TILE_HEIGHT; // z1 is highest corner of a steep slope
+	if (RemoveHalftileSlope(tileh) == corners[edge][3]) *z2 += TILE_HEIGHT; // z2 is highest corner of a steep slope
 }
 
+/**
+ * Get slope of a tile on top of a (possible) foundation
+ * If a tile does not have a foundation, the function returns the same as GetTileSlope.
+ *
+ * @param tile The tile of interest.
+ * @param z returns the z of the foundation slope. (Can be NULL, if not needed)
+ * @return The slope on top of the foundation.
+ */
 Slope GetFoundationSlope(TileIndex tile, uint* z)
 {
 	Slope tileh = GetTileSlope(tile, z);
--- a/src/rail_cmd.cpp
+++ b/src/rail_cmd.cpp
@@ -239,11 +239,11 @@
 				return (valid_on_leveled ? FOUNDATION_LEVELED : FOUNDATION_INVALID);
 
 			case TRACK_BIT_X:
-				if (HasSlopeHighestCorner(tileh)) return FOUNDATION_INCLINED_X;
+				if (IsSlopeWithOneCornerRaised(tileh)) return FOUNDATION_INCLINED_X;
 				return (valid_on_leveled ? FOUNDATION_LEVELED : FOUNDATION_INVALID);
 
 			case TRACK_BIT_Y:
-				if (HasSlopeHighestCorner(tileh)) return FOUNDATION_INCLINED_Y;
+				if (IsSlopeWithOneCornerRaised(tileh)) return FOUNDATION_INCLINED_Y;
 				return (valid_on_leveled ? FOUNDATION_LEVELED : FOUNDATION_INVALID);
 
 			default:
@@ -255,7 +255,7 @@
 		if (!valid_on_leveled) return FOUNDATION_INVALID;
 
 		/* If slope has three raised corners, build leveled foundation */
-		if (HasSlopeHighestCorner(ComplementSlope(tileh))) return FOUNDATION_LEVELED;
+		if (IsSlopeWithThreeCornersRaised(tileh)) return FOUNDATION_LEVELED;
 
 		/* If neighboured corners of track_corner are lowered, build halftile foundation */
 		if ((tileh & SlopeWithThreeCornersRaised(OppositeCorner(track_corner))) == SlopeWithOneCornerRaised(track_corner)) return HalftileFoundation(track_corner);
@@ -396,7 +396,7 @@
 			/* FALLTHROUGH */
 
 		default:
-			bool water_ground = IsTileType(tile, MP_WATER) && !IsSteepSlope(tileh) && HasSlopeHighestCorner(tileh);
+			bool water_ground = IsTileType(tile, MP_WATER) && IsSlopeWithOneCornerRaised(tileh);
 
 			ret = CheckRailSlope(tileh, trackbit, TRACK_BIT_NONE, tile);
 			if (CmdFailed(ret)) return ret;
@@ -540,7 +540,7 @@
 	Slope tileh = GetTileSlope(t, NULL);
 	TrackBits rail_bits = GetTrackBits(t);
 
-	if (!IsSteepSlope(tileh) && HasSlopeHighestCorner(tileh)) {
+	if (IsSlopeWithOneCornerRaised(tileh)) {
 		TrackBits lower_track = CornerToTrackBits(OppositeCorner(GetHighestSlopeCorner(tileh)));
 
 		TrackBits to_remove = lower_track & rail_bits;
@@ -1497,9 +1497,7 @@
  */
 static void DrawTrackFence_NS_1(const TileInfo *ti)
 {
-	int z = ti->z;
-	if (ti->tileh & SLOPE_W) z += TILE_HEIGHT;
-	if (IsSteepSlope(ti->tileh)) z += TILE_HEIGHT;
+	uint z = ti->z + GetSlopeZInCorner(RemoveHalftileSlope(ti->tileh), CORNER_W);
 	AddSortableSpriteToDraw(SPR_TRACK_FENCE_FLAT_VERT, _drawtile_track_palette,
 		ti->x + TILE_SIZE / 2, ti->y + TILE_SIZE / 2, 1, 1, 4, z);
 }
@@ -1509,9 +1507,7 @@
  */
 static void DrawTrackFence_NS_2(const TileInfo *ti)
 {
-	int z = ti->z;
-	if (ti->tileh & SLOPE_E) z += TILE_HEIGHT;
-	if (IsSteepSlope(ti->tileh)) z += TILE_HEIGHT;
+	uint z = ti->z + GetSlopeZInCorner(RemoveHalftileSlope(ti->tileh), CORNER_E);
 	AddSortableSpriteToDraw(SPR_TRACK_FENCE_FLAT_VERT, _drawtile_track_palette,
 		ti->x + TILE_SIZE / 2, ti->y + TILE_SIZE / 2, 1, 1, 4, z);
 }
@@ -1521,9 +1517,7 @@
  */
 static void DrawTrackFence_WE_1(const TileInfo *ti)
 {
-	int z = ti->z;
-	if (ti->tileh & SLOPE_N) z += TILE_HEIGHT;
-	if (IsSteepSlope(ti->tileh)) z += TILE_HEIGHT;
+	uint z = ti->z + GetSlopeZInCorner(RemoveHalftileSlope(ti->tileh), CORNER_N);
 	AddSortableSpriteToDraw(SPR_TRACK_FENCE_FLAT_HORZ, _drawtile_track_palette,
 		ti->x + TILE_SIZE / 2, ti->y + TILE_SIZE / 2, 1, 1, 4, z);
 }
@@ -1533,9 +1527,7 @@
  */
 static void DrawTrackFence_WE_2(const TileInfo *ti)
 {
-	int z = ti->z;
-	if (ti->tileh & SLOPE_S) z += TILE_HEIGHT;
-	if (IsSteepSlope(ti->tileh)) z += TILE_HEIGHT;
+	uint z = ti->z + GetSlopeZInCorner(RemoveHalftileSlope(ti->tileh), CORNER_S);
 	AddSortableSpriteToDraw(SPR_TRACK_FENCE_FLAT_HORZ, _drawtile_track_palette,
 		ti->x + TILE_SIZE / 2, ti->y + TILE_SIZE / 2, 1, 1, 4, z);
 }
@@ -2217,8 +2209,8 @@
 	}
 
 	/* The height of the track_corner must not be changed. The rest ensures GetRailFoundation() already. */
-	z_old += GetSlopeZInCorner((Slope)(tileh_old & ~SLOPE_HALFTILE_MASK), track_corner);
-	z_new += GetSlopeZInCorner((Slope)(tileh_new & ~SLOPE_HALFTILE_MASK), track_corner);
+	z_old += GetSlopeZInCorner(RemoveHalftileSlope(tileh_old), track_corner);
+	z_new += GetSlopeZInCorner(RemoveHalftileSlope(tileh_new), track_corner);
 	if (z_old != z_new) return CMD_ERROR;
 
 	CommandCost cost = CommandCost(EXPENSES_CONSTRUCTION, _price.terraform);
--- a/src/road_cmd.cpp
+++ b/src/road_cmd.cpp
@@ -376,7 +376,7 @@
 	*pieces |= MirrorRoadBits(*pieces);
 
 	/* partly leveled up tile, only if there's no road on that tile */
-	if ((existing == ROAD_NONE || existing == *pieces) && (tileh == SLOPE_W || tileh == SLOPE_S || tileh == SLOPE_E || tileh == SLOPE_N)) {
+	if ((existing == ROAD_NONE || existing == *pieces) && IsSlopeWithOneCornerRaised(tileh)) {
 		if (*pieces == ROAD_X || *pieces == ROAD_Y) return CommandCost(EXPENSES_CONSTRUCTION, _price.terraform);
 	}
 	return CMD_ERROR;
--- a/src/slope_func.h
+++ b/src/slope_func.h
@@ -45,6 +45,19 @@
 }
 
 /**
+ * Removes a halftile slope from a slope
+ *
+ * Non-halftile slopes remain unmodified.
+ *
+ * @param s A #Slope.
+ * @return The slope s without it's halftile slope.
+ */
+static inline Slope RemoveHalftileSlope(Slope s)
+{
+	return (Slope)(s & ~SLOPE_HALFTILE_MASK);
+}
+
+/**
  * Return the complement of a slope.
  *
  * This method returns the complement of a slope. The complement of a
@@ -62,6 +75,29 @@
 }
 
 /**
+ * Tests if a specific slope has exactly one corner raised.
+ *
+ * @param s The #Slope
+ * @return true iff exactly one corner is raised
+ */
+static inline bool IsSlopeWithOneCornerRaised(Slope s)
+{
+	return (s == SLOPE_W) || (s == SLOPE_S) || (s == SLOPE_E) || (s == SLOPE_N);
+}
+
+/**
+ * Returns the slope with a specific corner raised.
+ *
+ * @param corner The #Corner.
+ * @return The #Slope with corner "corner" raised.
+ */
+static inline Slope SlopeWithOneCornerRaised(Corner corner)
+{
+	assert(IsValidCorner(corner));
+	return (Slope)(1 << corner);
+}
+
+/**
  * Tests if a slope has a highest corner (i.e. one corner raised or a steep slope).
  *
  * Note: A halftile slope is ignored.
@@ -71,8 +107,8 @@
  */
 static inline bool HasSlopeHighestCorner(Slope s)
 {
-	s = (Slope)(s & ~SLOPE_HALFTILE_MASK);
-	return IsSteepSlope(s) || (s == SLOPE_W) || (s == SLOPE_S) || (s == SLOPE_E) || (s == SLOPE_N);
+	s = RemoveHalftileSlope(s);
+	return IsSteepSlope(s) || IsSlopeWithOneCornerRaised(s);
 }
 
 /**
@@ -84,7 +120,7 @@
  */
 static inline Corner GetHighestSlopeCorner(Slope s)
 {
-	switch (s & ~SLOPE_HALFTILE_MASK) {
+	switch (RemoveHalftileSlope(s)) {
 		case SLOPE_W:
 		case SLOPE_STEEP_W: return CORNER_W;
 		case SLOPE_S:
@@ -135,15 +171,14 @@
 }
 
 /**
- * Returns the slope with a specific corner raised.
+ * Tests if a specific slope has exactly three corners raised.
  *
- * @param corner The #Corner.
- * @return The #Slope with corner "corner" raised.
+ * @param s The #Slope
+ * @return true iff exactly three corners are raised
  */
-static inline Slope SlopeWithOneCornerRaised(Corner corner)
+static inline bool IsSlopeWithThreeCornersRaised(Slope s)
 {
-	assert(IsValidCorner(corner));
-	return (Slope)(1 << corner);
+	return !IsHalftileSlope(s) && !IsSteepSlope(s) && IsSlopeWithOneCornerRaised(ComplementSlope(s));
 }
 
 /**
@@ -158,6 +193,62 @@
 }
 
 /**
+ * Returns a specific steep slope
+ *
+ * @param corner A #Corner.
+ * @return The steep #Slope with "corner" as highest corner.
+ */
+static inline Slope SteepSlope(Corner corner)
+{
+	return (Slope)(SLOPE_STEEP | SlopeWithThreeCornersRaised(OppositeCorner(corner)));
+}
+
+/**
+ * Tests if a specific slope is an inclined slope.
+ *
+ * @param s The #Slope
+ * @return true iff the slope is inclined.
+ */
+static inline bool IsInclinedSlope(Slope s)
+{
+	return (s == SLOPE_NW) || (s == SLOPE_SW) || (s == SLOPE_SE) || (s == SLOPE_NE);
+}
+
+/**
+ * Returns the direction of an inclined slope.
+ *
+ * @param s A #Slope
+ * @return The direction the slope goes up in. Or INVALID_DIAGDIR if the slope is not an inclined slope.
+ */
+static inline DiagDirection GetInclinedSlopeDirection(Slope s)
+{
+	switch (s) {
+		case SLOPE_NE: return DIAGDIR_NE;
+		case SLOPE_SE: return DIAGDIR_SE;
+		case SLOPE_SW: return DIAGDIR_SW;
+		case SLOPE_NW: return DIAGDIR_NW;
+		default: return INVALID_DIAGDIR;
+	}
+}
+
+/**
+ * Returns the slope, that is inclined in a specific direction.
+ *
+ * @param dir A #DiagDirection
+ * @return The #Slope that goes up in direction dir.
+ */
+static inline Slope InclinedSlope(DiagDirection dir)
+{
+	switch (dir) {
+		case DIAGDIR_NE: return SLOPE_NE;
+		case DIAGDIR_SE: return SLOPE_SE;
+		case DIAGDIR_SW: return SLOPE_SW;
+		case DIAGDIR_NW: return SLOPE_NW;
+		default: NOT_REACHED();
+	}
+}
+
+/**
  * Adds a halftile slope to a slope.
  *
  * @param s #Slope without a halftile slope.
--- a/src/station_cmd.cpp
+++ b/src/station_cmd.cpp
@@ -1945,14 +1945,9 @@
 {
 	CommandCost cost;
 
-	DiagDirection direction;
-	switch (GetTileSlope(tile, NULL)) {
-		case SLOPE_SW: direction = DIAGDIR_NE; break;
-		case SLOPE_SE: direction = DIAGDIR_NW; break;
-		case SLOPE_NW: direction = DIAGDIR_SE; break;
-		case SLOPE_NE: direction = DIAGDIR_SW; break;
-		default: return_cmd_error(STR_304B_SITE_UNSUITABLE);
-	}
+	DiagDirection direction = GetInclinedSlopeDirection(GetTileSlope(tile, NULL));
+	if (direction == INVALID_DIAGDIR) return_cmd_error(STR_304B_SITE_UNSUITABLE);
+	direction = ReverseDiagDir(direction);
 
 	/* Docks cannot be placed on rapids */
 	if (IsRiverTile(tile)) return_cmd_error(STR_304B_SITE_UNSUITABLE);
--- a/src/tunnelbridge_cmd.cpp
+++ b/src/tunnelbridge_cmd.cpp
@@ -465,14 +465,8 @@
 	}
 
 	start_tileh = GetTileSlope(start_tile, &start_z);
-
-	switch (start_tileh) {
-		case SLOPE_SW: direction = DIAGDIR_SW; break;
-		case SLOPE_SE: direction = DIAGDIR_SE; break;
-		case SLOPE_NW: direction = DIAGDIR_NW; break;
-		case SLOPE_NE: direction = DIAGDIR_NE; break;
-		default: return_cmd_error(STR_500B_SITE_UNSUITABLE_FOR_TUNNEL);
-	}
+	direction = GetInclinedSlopeDirection(start_tileh);
+	if (direction == INVALID_DIAGDIR) return_cmd_error(STR_500B_SITE_UNSUITABLE_FOR_TUNNEL);
 
 	if (IsRiverTile(start_tile)) return_cmd_error(STR_3807_CAN_T_BUILD_ON_WATER);
 
--- a/src/viewport.cpp
+++ b/src/viewport.cpp
@@ -909,7 +909,7 @@
 	int offset;
 
 	FoundationPart foundation_part = FOUNDATION_PART_NORMAL;
-	Slope autorail_tileh = (Slope)(ti->tileh & ~SLOPE_HALFTILE_MASK);
+	Slope autorail_tileh = RemoveHalftileSlope(ti->tileh);
 	if (IsHalftileSlope(ti->tileh)) {
 		static const uint _lower_rail[4] = { 5U, 2U, 4U, 3U };
 		Corner halftile_corner = GetHalftileSlopeCorner(ti->tileh);
@@ -958,7 +958,7 @@
 			FoundationPart foundation_part = FOUNDATION_PART_NORMAL;
 			if (ti->tileh & SLOPE_N) {
 				z += TILE_HEIGHT;
-				if ((ti->tileh & ~SLOPE_HALFTILE_MASK) == SLOPE_STEEP_N) z += TILE_HEIGHT;
+				if (RemoveHalftileSlope(ti->tileh) == SLOPE_STEEP_N) z += TILE_HEIGHT;
 			}
 			if (IsHalftileSlope(ti->tileh)) {
 				Corner halftile_corner = GetHalftileSlopeCorner(ti->tileh);
--- a/src/water_cmd.cpp
+++ b/src/water_cmd.cpp
@@ -70,11 +70,6 @@
 };
 
 /**
- * Slopes that contain flat water and not only shore.
- */
-static const uint32 _active_water_slopes = (1 << SLOPE_FLAT) | (1 << SLOPE_W) | (1 << SLOPE_S) | (1 << SLOPE_E) | (1 << SLOPE_N);
-
-/**
  * Makes a tile canal or water depending on the surroundings.
  * This as for example docks and shipdepots do not store
  * whether the tile used to be canal or 'normal' water.
@@ -276,15 +271,8 @@
  */
 CommandCost CmdBuildLock(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
 {
-	DiagDirection dir;
-
-	switch (GetTileSlope(tile, NULL)) {
-		case SLOPE_SW: dir = DIAGDIR_SW; break;
-		case SLOPE_SE: dir = DIAGDIR_SE; break;
-		case SLOPE_NW: dir = DIAGDIR_NW; break;
-		case SLOPE_NE: dir = DIAGDIR_NE; break;
-		default: return_cmd_error(STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION);
-	}
+	DiagDirection dir = GetInclinedSlopeDirection(GetTileSlope(tile, NULL));
+	if (dir == INVALID_DIAGDIR) return_cmd_error(STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION);
 
 	/* Disallow building of locks on river rapids */
 	if (IsRiverTile(tile)) return_cmd_error(STR_0239_SITE_UNSUITABLE);
@@ -296,7 +284,7 @@
  * @param tile end tile of stretch-dragging
  * @param flags type of operation
  * @param p1 start tile of stretch-dragging
- * @param p2 ctrl pressed - toggles ocean / canals at sealevel (ocean only allowed in the scenario editor)
+ * @param p2 specifies canal (0), water (1) or river (2); last two can only be built in scenario editor
  */
 CommandCost CmdBuildCanal(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
 {
@@ -328,7 +316,7 @@
 		CommandCost ret;
 
 		Slope slope = GetTileSlope(tile, NULL);
-		if (slope != SLOPE_FLAT && (p2 != 2 || (slope != SLOPE_NW && slope != SLOPE_NE && slope != SLOPE_SW && slope != SLOPE_SE))) {
+		if (slope != SLOPE_FLAT && (p2 != 2 || !IsInclinedSlope(slope))) {
 			return_cmd_error(STR_0007_FLAT_LAND_REQUIRED);
 		}
 
@@ -389,7 +377,7 @@
 			if (!EnsureNoVehicleOnGround(tile)) return CMD_ERROR;
 
 			if (flags & DC_EXEC) DoClearSquare(tile);
-			if (slope == SLOPE_N || slope == SLOPE_E || slope == SLOPE_S || slope == SLOPE_W) {
+			if (IsSlopeWithOneCornerRaised(slope)) {
 				return CommandCost(EXPENSES_CONSTRUCTION, _price.clear_water);
 			} else {
 				return CommandCost(EXPENSES_CONSTRUCTION, _price.clear_roughland);
@@ -424,17 +412,7 @@
 	switch (GetTileType(tile)) {
 		case MP_WATER:
 			if (!IsCoast(tile)) return true;
-
-			switch (GetTileSlope(tile, NULL)) {
-				case SLOPE_W:
-				case SLOPE_S:
-				case SLOPE_E:
-				case SLOPE_N:
-					return true;
-
-				default:
-					return false;
-			}
+			return IsSlopeWithOneCornerRaised(GetTileSlope(tile, NULL));
 
 		case MP_RAILWAY:  return GetRailGroundType(tile) == RAIL_GROUND_WATER;
 		case MP_STATION:  return IsOilRig(tile) || IsDock(tile) || IsBuoy(tile);
@@ -811,7 +789,7 @@
 		case MP_WATER:
 			if (IsCoast(tile)) {
 				Slope tileh = GetTileSlope(tile, NULL);
-				return (HasBit(_active_water_slopes, tileh) ? FLOOD_ACTIVE : FLOOD_DRYUP);
+				return (IsSlopeWithOneCornerRaised(tileh) ? FLOOD_ACTIVE : FLOOD_DRYUP);
 			} else {
 				return ((IsSea(tile) || (IsShipDepot(tile) && (GetShipDepotWaterOwner(tile) == OWNER_WATER))) ? FLOOD_ACTIVE : FLOOD_NONE);
 			}
@@ -984,7 +962,7 @@
 					FOR_EACH_SET_BIT(dir, check_dirs) {
 						TileIndex dest = TILE_ADD(tile, TileOffsByDir((Direction)dir));
 						Slope slope_dest = (Slope)(GetTileSlope(dest, NULL) & ~SLOPE_STEEP);
-						if (HasBit(_active_water_slopes, slope_dest)) {
+						if (slope_dest == SLOPE_FLAT || IsSlopeWithOneCornerRaised(slope_dest)) {
 							MakeShore(tile);
 							break;
 						}