src/slope.h
branchnoai
changeset 9722 ebf0ece7d8f6
parent 9718 f82a4facea8b
--- a/src/slope.h	Thu Nov 22 23:01:41 2007 +0000
+++ b/src/slope.h	Fri Nov 23 16:59:30 2007 +0000
@@ -9,12 +9,32 @@
 #define SLOPE_H
 
 /**
+ * Enumeration of tile corners
+ */
+enum Corner {
+	CORNER_W = 0,
+	CORNER_S = 1,
+	CORNER_E = 2,
+	CORNER_N = 3,
+	CORNER_END,
+	CORNER_INVALID = 0xFF
+};
+
+/**
  * Enumeration for the slope-type.
  *
  * This enumeration use the chars N,E,S,W corresponding the
  * direction north, east, south and west. The top corner of a tile
  * is the north-part of the tile. The whole slope is encoded with
  * 5 bits, 4 bits for each corner and 1 bit for a steep-flag.
+ *
+ * For halftile slopes an extra 3 bits are used to represent this
+ * properly; 1 bit for a halftile-flag and 2 bits to encode which
+ * extra side (corner) is leveled when the slope of the first 5
+ * bits is applied. This means that there can only be one leveled
+ * slope for steep slopes, which is logical because two leveled
+ * slopes would mean that it is not a steep slope as halftile
+ * slopes only span one height level.
  */
 enum Slope {
 	SLOPE_FLAT     = 0x00,                                  ///< a flat tile
@@ -37,18 +57,14 @@
 	SLOPE_STEEP_W  = SLOPE_STEEP | SLOPE_NWS,               ///< a steep slope falling to east (from west)
 	SLOPE_STEEP_S  = SLOPE_STEEP | SLOPE_WSE,               ///< a steep slope falling to north (from south)
 	SLOPE_STEEP_E  = SLOPE_STEEP | SLOPE_SEN,               ///< a steep slope falling to west (from east)
-	SLOPE_STEEP_N  = SLOPE_STEEP | SLOPE_ENW                ///< a steep slope falling to south (from north)
-};
+	SLOPE_STEEP_N  = SLOPE_STEEP | SLOPE_ENW,               ///< a steep slope falling to south (from north)
 
-/**
- * Enumeration of tile corners
- */
-enum Corner {
-	CORNER_W = 0,
-	CORNER_S = 1,
-	CORNER_E = 2,
-	CORNER_N = 3,
-	CORNER_END
+	SLOPE_HALFTILE = 0x20,                                  ///< one halftile is leveled (non continuous slope)
+	SLOPE_HALFTILE_MASK = 0xE0,                             ///< three bits used for halftile slopes
+	SLOPE_HALFTILE_W = SLOPE_HALFTILE | (CORNER_W << 6),    ///< the west halftile is leveled (non continuous slope)
+	SLOPE_HALFTILE_S = SLOPE_HALFTILE | (CORNER_S << 6),    ///< the south halftile is leveled (non continuous slope)
+	SLOPE_HALFTILE_E = SLOPE_HALFTILE | (CORNER_E << 6),    ///< the east halftile is leveled (non continuous slope)
+	SLOPE_HALFTILE_N = SLOPE_HALFTILE | (CORNER_N << 6),    ///< the north halftile is leveled (non continuous slope)
 };
 
 /**
@@ -74,43 +90,57 @@
 }
 
 /**
+ * Checks for non-continuous slope on halftile foundations.
+ *
+ * @param s The given #Slope.
+ * @return True if the slope is non-continuous, else false.
+ */
+static inline bool IsHalftileSlope(Slope s)
+{
+	return (s & SLOPE_HALFTILE) != 0;
+}
+
+/**
  * Return the complement of a slope.
  *
  * This method returns the complement of a slope. The complement of a
  * slope is a slope with raised corner which aren't raised in the given
  * slope.
  *
- * @pre The slope must not be steep.
+ * @pre The slope must neither be steep nor a halftile slope.
  * @param s The #Slope to get the complement.
  * @return a complement Slope of the given slope.
  */
 static inline Slope ComplementSlope(Slope s)
 {
-	assert(!IsSteepSlope(s));
+	assert(!IsSteepSlope(s) && !IsHalftileSlope(s));
 	return (Slope)(0xF ^ s);
 }
 
 /**
  * Tests if a slope has a highest corner (i.e. one corner raised or a steep slope).
  *
+ * Note: A halftile slope is ignored.
+ *
  * @param s The #Slope.
  * @return  true iff the slope has a highest corner.
  */
 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);
 }
 
 /**
  * Returns the highest corner of a slope (one corner raised or a steep slope).
  *
- * @pre      The slope must be a slope with one corner raised or a steep slope.
+ * @pre      The slope must be a slope with one corner raised or a steep slope. A halftile slope is ignored.
  * @param s  The #Slope.
  * @return   Highest corner.
  */
 static inline Corner GetHighestSlopeCorner(Slope s)
 {
-	switch (s) {
+	switch (s & ~SLOPE_HALFTILE_MASK) {
 		case SLOPE_W:
 		case SLOPE_STEEP_W: return CORNER_W;
 		case SLOPE_S:
@@ -124,6 +154,19 @@
 }
 
 /**
+ * Returns the leveled halftile of a halftile slope.
+ *
+ * @pre     The slope must be a halftile slope.
+ * @param s The #Slope.
+ * @return  The corner of the leveled halftile.
+ */
+static inline Corner GetHalftileSlopeCorner(Slope s)
+{
+	assert(IsHalftileSlope(s));
+	return (Corner)((s >> 6) & 3);
+}
+
+/**
  * Returns the height of the highest corner of a slope relative to TileZ (= minimal height)
  *
  * @param s The #Slope.
@@ -170,6 +213,19 @@
 	return ComplementSlope(SlopeWithOneCornerRaised(corner));
 }
 
+/**
+ * Adds a halftile slope to a slope.
+ *
+ * @param s #Slope without a halftile slope.
+ * @param corner The #Corner of the halftile.
+ * @return The #Slope s with the halftile slope added.
+ */
+static inline Slope HalftileSlope(Slope s, Corner corner)
+{
+	assert(IsValidCorner(corner));
+	return (Slope)(s | SLOPE_HALFTILE | (corner << 6));
+}
+
 
 /**
  * Enumeration for Foundations.
@@ -179,8 +235,20 @@
 	FOUNDATION_LEVELED,          ///< The tile is leveled up to a flat slope.
 	FOUNDATION_INCLINED_X,       ///< The tile has an along X-axis inclined foundation.
 	FOUNDATION_INCLINED_Y,       ///< The tile has an along Y-axis inclined foundation.
-	FOUNDATION_STEEP_LOWER,      ///< The tile has a steep slope. The lowerst corner is raised by a foundation to allow building railroad on the lower halftile.
-	FOUNDATION_STEEP_HIGHER,     ///< The tile has a steep slope. Three corners are raised by a foundation to allow building railroad on the higher halftile.
+	FOUNDATION_STEEP_LOWER,      ///< The tile has a steep slope. The lowest corner is raised by a foundation to allow building railroad on the lower halftile.
+
+/* Halftile foundations */
+	FOUNDATION_STEEP_BOTH,       ///< The tile has a steep slope. The lowest corner is raised by a foundation and the upper halftile is leveled.
+	FOUNDATION_HALFTILE_W,       ///< Level west halftile non-continuously.
+	FOUNDATION_HALFTILE_S,       ///< Level south halftile non-continuously.
+	FOUNDATION_HALFTILE_E,       ///< Level east halftile non-continuously.
+	FOUNDATION_HALFTILE_N,       ///< Level north halftile non-continuously.
+
+/* Special anti-zig-zag foundations for single horizontal/vertical track */
+	FOUNDATION_RAIL_W,           ///< Foundation for TRACK_BIT_LEFT, but not a leveled foundation.
+	FOUNDATION_RAIL_S,           ///< Foundation for TRACK_BIT_LOWER, but not a leveled foundation.
+	FOUNDATION_RAIL_E,           ///< Foundation for TRACK_BIT_RIGHT, but not a leveled foundation.
+	FOUNDATION_RAIL_N,           ///< Foundation for TRACK_BIT_UPPER, but not a leveled foundation.
 
 	FOUNDATION_INVALID = 0xFF    ///< Used inside "rail_cmd.cpp" to indicate invalid slope/track combination.
 };
@@ -219,6 +287,54 @@
 }
 
 /**
+ * Tests if a foundation is a non-continuous foundation, i.e. halftile-foundation or FOUNDATION_STEEP_BOTH.
+ *
+ * @param f  The #Foundation.
+ * @return   true iff f is a non-continuous foundation
+ */
+static inline bool IsNonContinuousFoundation(Foundation f)
+{
+	return IS_INT_INSIDE(f, FOUNDATION_STEEP_BOTH, FOUNDATION_HALFTILE_N + 1);
+}
+
+/**
+ * Returns the halftile corner of a halftile-foundation
+ *
+ * @pre f != FOUNDATION_STEEP_BOTH
+ *
+ * @param f  The #Foundation.
+ * @return   The #Corner with track.
+ */
+static inline Corner GetHalftileFoundationCorner(Foundation f)
+{
+	assert(IS_INT_INSIDE(f, FOUNDATION_HALFTILE_W, FOUNDATION_HALFTILE_N + 1));
+	return (Corner)(f - FOUNDATION_HALFTILE_W);
+}
+
+/**
+ * Tests if a foundation is a special rail foundation for single horizontal/vertical track.
+ *
+ * @param f  The #Foundation.
+ * @return   true iff f is a special rail foundation for single horizontal/vertical track.
+ */
+static inline bool IsSpecialRailFoundation(Foundation f)
+{
+	return IS_INT_INSIDE(f, FOUNDATION_RAIL_W, FOUNDATION_RAIL_N + 1);
+}
+
+/**
+ * Returns the track corner of a special rail foundation
+ *
+ * @param f  The #Foundation.
+ * @return   The #Corner with track.
+ */
+static inline Corner GetRailFoundationCorner(Foundation f)
+{
+	assert(IsSpecialRailFoundation(f));
+	return (Corner)(f - FOUNDATION_RAIL_W);
+}
+
+/**
  * Returns the foundation needed to flatten a slope.
  * The returned foundation is either FOUNDATION_NONE if the tile was already flat, or FOUNDATION_LEVELED.
  *
@@ -243,4 +359,28 @@
 	return (axis == AXIS_X ? FOUNDATION_INCLINED_X : FOUNDATION_INCLINED_Y);
 }
 
+/**
+ * Returns the halftile foundation for single horizontal/vertical track.
+ *
+ * @param corner The #Corner with the track.
+ * @return       The wanted #Foundation.
+ */
+static inline Foundation HalftileFoundation(Corner corner)
+{
+	assert(IsValidCorner(corner));
+	return (Foundation)(FOUNDATION_HALFTILE_W + corner);
+}
+
+/**
+ * Returns the special rail foundation for single horizontal/vertical track.
+ *
+ * @param corner The #Corner with the track.
+ * @return       The wanted #Foundation.
+ */
+static inline Foundation SpecialRailFoundation(Corner corner)
+{
+	assert(IsValidCorner(corner));
+	return (Foundation)(FOUNDATION_RAIL_W + corner);
+}
+
 #endif /* SLOPE_H */