tron@3636: /* $Id$ */ tron@3636: rubidium@8604: /** @file slope_func.h Functions related to slopes. */ rubidium@8260: rubidium@8604: #ifndef SLOPE_FUNC_H rubidium@8604: #define SLOPE_FUNC_H tron@3636: rubidium@8609: #include "core/math_func.hpp" rubidium@8604: #include "slope_type.h" rubidium@8604: #include "direction_type.h" rubidium@8634: #include "tile_type.h" rubidium@8174: rubidium@8174: /** rubidium@8199: * Rangecheck for Corner enumeration. rubidium@8199: * rubidium@8199: * @param corner A #Corner. rubidium@8199: * @return true iff corner is in a valid range. rubidium@8199: */ rubidium@8199: static inline bool IsValidCorner(Corner corner) rubidium@8199: { skidd13@8450: return IsInsideMM(corner, 0, CORNER_END); rubidium@8199: } rubidium@8199: rubidium@8604: rubidium@8199: /** truelight@7805: * Checks if a slope is steep. truelight@7805: * truelight@7805: * @param s The given #Slope. truelight@7805: * @return True if the slope is steep, else false. truelight@7805: */ tron@3636: static inline bool IsSteepSlope(Slope s) tron@3636: { tron@3636: return (s & SLOPE_STEEP) != 0; tron@3636: } tron@3636: truelight@7805: /** rubidium@8260: * Checks for non-continuous slope on halftile foundations. rubidium@8260: * rubidium@8260: * @param s The given #Slope. rubidium@8260: * @return True if the slope is non-continuous, else false. rubidium@8260: */ rubidium@8260: static inline bool IsHalftileSlope(Slope s) rubidium@8260: { rubidium@8260: return (s & SLOPE_HALFTILE) != 0; rubidium@8260: } rubidium@8260: rubidium@8260: /** frosch@8909: * Removes a halftile slope from a slope frosch@8909: * frosch@8909: * Non-halftile slopes remain unmodified. frosch@8909: * frosch@8909: * @param s A #Slope. frosch@8909: * @return The slope s without it's halftile slope. frosch@8909: */ frosch@8909: static inline Slope RemoveHalftileSlope(Slope s) frosch@8909: { frosch@8909: return (Slope)(s & ~SLOPE_HALFTILE_MASK); frosch@8909: } frosch@8909: frosch@8909: /** truelight@7805: * Return the complement of a slope. truelight@7805: * truelight@7805: * This method returns the complement of a slope. The complement of a truelight@7805: * slope is a slope with raised corner which aren't raised in the given truelight@7805: * slope. truelight@7805: * rubidium@8260: * @pre The slope must neither be steep nor a halftile slope. truelight@7805: * @param s The #Slope to get the complement. truelight@7805: * @return a complement Slope of the given slope. truelight@7805: */ tron@3636: static inline Slope ComplementSlope(Slope s) tron@3636: { rubidium@8260: assert(!IsSteepSlope(s) && !IsHalftileSlope(s)); tron@3636: return (Slope)(0xF ^ s); tron@3636: } tron@3636: rubidium@7831: /** frosch@8909: * Tests if a specific slope has exactly one corner raised. frosch@8909: * frosch@8909: * @param s The #Slope frosch@8909: * @return true iff exactly one corner is raised frosch@8909: */ frosch@8909: static inline bool IsSlopeWithOneCornerRaised(Slope s) frosch@8909: { frosch@8909: return (s == SLOPE_W) || (s == SLOPE_S) || (s == SLOPE_E) || (s == SLOPE_N); frosch@8909: } frosch@8909: frosch@8909: /** frosch@8909: * Returns the slope with a specific corner raised. frosch@8909: * frosch@8909: * @param corner The #Corner. frosch@8909: * @return The #Slope with corner "corner" raised. frosch@8909: */ frosch@8909: static inline Slope SlopeWithOneCornerRaised(Corner corner) frosch@8909: { frosch@8909: assert(IsValidCorner(corner)); frosch@8909: return (Slope)(1 << corner); frosch@8909: } frosch@8909: frosch@8909: /** rubidium@8199: * Tests if a slope has a highest corner (i.e. one corner raised or a steep slope). rubidium@8199: * rubidium@8260: * Note: A halftile slope is ignored. rubidium@8260: * rubidium@8199: * @param s The #Slope. rubidium@8199: * @return true iff the slope has a highest corner. rubidium@8199: */ rubidium@8199: static inline bool HasSlopeHighestCorner(Slope s) rubidium@8199: { frosch@8909: s = RemoveHalftileSlope(s); frosch@8909: return IsSteepSlope(s) || IsSlopeWithOneCornerRaised(s); rubidium@8199: } rubidium@8199: rubidium@8199: /** rubidium@7831: * Returns the highest corner of a slope (one corner raised or a steep slope). rubidium@7831: * rubidium@8260: * @pre The slope must be a slope with one corner raised or a steep slope. A halftile slope is ignored. rubidium@7831: * @param s The #Slope. rubidium@8174: * @return Highest corner. rubidium@7831: */ rubidium@8174: static inline Corner GetHighestSlopeCorner(Slope s) rubidium@7831: { frosch@8909: switch (RemoveHalftileSlope(s)) { rubidium@7831: case SLOPE_W: rubidium@8174: case SLOPE_STEEP_W: return CORNER_W; rubidium@7831: case SLOPE_S: rubidium@8174: case SLOPE_STEEP_S: return CORNER_S; rubidium@7831: case SLOPE_E: rubidium@8174: case SLOPE_STEEP_E: return CORNER_E; rubidium@7831: case SLOPE_N: rubidium@8174: case SLOPE_STEEP_N: return CORNER_N; rubidium@7831: default: NOT_REACHED(); rubidium@7831: } rubidium@7831: } rubidium@7831: rubidium@8078: /** rubidium@8260: * Returns the leveled halftile of a halftile slope. rubidium@8260: * rubidium@8260: * @pre The slope must be a halftile slope. rubidium@8260: * @param s The #Slope. rubidium@8260: * @return The corner of the leveled halftile. rubidium@8260: */ rubidium@8260: static inline Corner GetHalftileSlopeCorner(Slope s) rubidium@8260: { rubidium@8260: assert(IsHalftileSlope(s)); rubidium@8260: return (Corner)((s >> 6) & 3); rubidium@8260: } rubidium@8260: rubidium@8260: /** rubidium@8078: * Returns the height of the highest corner of a slope relative to TileZ (= minimal height) rubidium@8078: * rubidium@8078: * @param s The #Slope. rubidium@8078: * @return Relative height of highest corner. rubidium@8078: */ rubidium@8078: static inline uint GetSlopeMaxZ(Slope s) rubidium@8078: { rubidium@8078: if (s == SLOPE_FLAT) return 0; rubidium@8078: if (IsSteepSlope(s)) return 2 * TILE_HEIGHT; rubidium@8078: return TILE_HEIGHT; rubidium@8078: } rubidium@8078: rubidium@8174: /** rubidium@8174: * Returns the opposite corner. rubidium@8174: * rubidium@8174: * @param corner A #Corner. rubidium@8174: * @return The opposite corner to "corner". rubidium@8174: */ rubidium@8174: static inline Corner OppositeCorner(Corner corner) rubidium@8174: { rubidium@8174: return (Corner)(corner ^ 2); rubidium@8174: } rubidium@8174: rubidium@8174: /** frosch@8909: * Tests if a specific slope has exactly three corners raised. rubidium@8174: * frosch@8909: * @param s The #Slope frosch@8909: * @return true iff exactly three corners are raised rubidium@8174: */ frosch@8909: static inline bool IsSlopeWithThreeCornersRaised(Slope s) rubidium@8174: { frosch@8909: return !IsHalftileSlope(s) && !IsSteepSlope(s) && IsSlopeWithOneCornerRaised(ComplementSlope(s)); rubidium@8174: } rubidium@8174: rubidium@8174: /** rubidium@8174: * Returns the slope with all except one corner raised. rubidium@8174: * rubidium@8174: * @param corner The #Corner. rubidium@8174: * @return The #Slope with all corners but "corner" raised. rubidium@8174: */ rubidium@8174: static inline Slope SlopeWithThreeCornersRaised(Corner corner) rubidium@8174: { rubidium@8174: return ComplementSlope(SlopeWithOneCornerRaised(corner)); rubidium@8174: } rubidium@8174: rubidium@8260: /** frosch@8909: * Returns a specific steep slope frosch@8909: * frosch@8909: * @param corner A #Corner. frosch@8909: * @return The steep #Slope with "corner" as highest corner. frosch@8909: */ frosch@8909: static inline Slope SteepSlope(Corner corner) frosch@8909: { frosch@8909: return (Slope)(SLOPE_STEEP | SlopeWithThreeCornersRaised(OppositeCorner(corner))); frosch@8909: } frosch@8909: frosch@8909: /** frosch@8909: * Tests if a specific slope is an inclined slope. frosch@8909: * frosch@8909: * @param s The #Slope frosch@8909: * @return true iff the slope is inclined. frosch@8909: */ frosch@8909: static inline bool IsInclinedSlope(Slope s) frosch@8909: { frosch@8909: return (s == SLOPE_NW) || (s == SLOPE_SW) || (s == SLOPE_SE) || (s == SLOPE_NE); frosch@8909: } frosch@8909: frosch@8909: /** frosch@8909: * Returns the direction of an inclined slope. frosch@8909: * frosch@8909: * @param s A #Slope frosch@8909: * @return The direction the slope goes up in. Or INVALID_DIAGDIR if the slope is not an inclined slope. frosch@8909: */ frosch@8909: static inline DiagDirection GetInclinedSlopeDirection(Slope s) frosch@8909: { frosch@8909: switch (s) { frosch@8909: case SLOPE_NE: return DIAGDIR_NE; frosch@8909: case SLOPE_SE: return DIAGDIR_SE; frosch@8909: case SLOPE_SW: return DIAGDIR_SW; frosch@8909: case SLOPE_NW: return DIAGDIR_NW; frosch@8909: default: return INVALID_DIAGDIR; frosch@8909: } frosch@8909: } frosch@8909: frosch@8909: /** frosch@8909: * Returns the slope, that is inclined in a specific direction. frosch@8909: * frosch@8909: * @param dir A #DiagDirection frosch@8909: * @return The #Slope that goes up in direction dir. frosch@8909: */ frosch@8909: static inline Slope InclinedSlope(DiagDirection dir) frosch@8909: { frosch@8909: switch (dir) { frosch@8909: case DIAGDIR_NE: return SLOPE_NE; frosch@8909: case DIAGDIR_SE: return SLOPE_SE; frosch@8909: case DIAGDIR_SW: return SLOPE_SW; frosch@8909: case DIAGDIR_NW: return SLOPE_NW; frosch@8909: default: NOT_REACHED(); frosch@8909: } frosch@8909: } frosch@8909: frosch@8909: /** rubidium@8260: * Adds a halftile slope to a slope. rubidium@8260: * rubidium@8260: * @param s #Slope without a halftile slope. rubidium@8260: * @param corner The #Corner of the halftile. rubidium@8260: * @return The #Slope s with the halftile slope added. rubidium@8260: */ rubidium@8260: static inline Slope HalftileSlope(Slope s, Corner corner) rubidium@8260: { rubidium@8260: assert(IsValidCorner(corner)); rubidium@8260: return (Slope)(s | SLOPE_HALFTILE | (corner << 6)); rubidium@8260: } rubidium@8260: rubidium@7831: rubidium@7831: /** rubidium@7831: * Tests for FOUNDATION_NONE. rubidium@7831: * rubidium@7831: * @param f Maybe a #Foundation. rubidium@7831: * @return true iff f is a foundation. rubidium@7831: */ rubidium@7831: static inline bool IsFoundation(Foundation f) rubidium@7831: { rubidium@7831: return f != FOUNDATION_NONE; rubidium@7831: } rubidium@7831: rubidium@7831: /** rubidium@7831: * Tests if the foundation is a leveled foundation. rubidium@7831: * rubidium@7831: * @param f The #Foundation. rubidium@7831: * @return true iff f is a leveled foundation. rubidium@7831: */ rubidium@7831: static inline bool IsLeveledFoundation(Foundation f) rubidium@7831: { rubidium@7831: return f == FOUNDATION_LEVELED; rubidium@7831: } rubidium@7831: rubidium@7831: /** rubidium@7831: * Tests if the foundation is an inclined foundation. rubidium@7831: * rubidium@7831: * @param f The #Foundation. rubidium@7831: * @return true iff f is an inclined foundation. rubidium@7831: */ rubidium@7831: static inline bool IsInclinedFoundation(Foundation f) rubidium@7831: { rubidium@7831: return (f == FOUNDATION_INCLINED_X) || (f == FOUNDATION_INCLINED_Y); rubidium@7831: } rubidium@7831: rubidium@7831: /** rubidium@8266: * Tests if a foundation is a non-continuous foundation, i.e. halftile-foundation or FOUNDATION_STEEP_BOTH. rubidium@8266: * rubidium@8266: * @param f The #Foundation. rubidium@8266: * @return true iff f is a non-continuous foundation rubidium@8266: */ rubidium@8266: static inline bool IsNonContinuousFoundation(Foundation f) rubidium@8266: { skidd13@8450: return IsInsideMM(f, FOUNDATION_STEEP_BOTH, FOUNDATION_HALFTILE_N + 1); rubidium@8266: } rubidium@8266: rubidium@8266: /** rubidium@8266: * Returns the halftile corner of a halftile-foundation rubidium@8266: * rubidium@8266: * @pre f != FOUNDATION_STEEP_BOTH rubidium@8266: * rubidium@8266: * @param f The #Foundation. rubidium@8266: * @return The #Corner with track. rubidium@8266: */ rubidium@8266: static inline Corner GetHalftileFoundationCorner(Foundation f) rubidium@8266: { skidd13@8450: assert(IsInsideMM(f, FOUNDATION_HALFTILE_W, FOUNDATION_HALFTILE_N + 1)); rubidium@8266: return (Corner)(f - FOUNDATION_HALFTILE_W); rubidium@8266: } rubidium@8266: rubidium@8266: /** rubidium@8266: * Tests if a foundation is a special rail foundation for single horizontal/vertical track. rubidium@8266: * rubidium@8266: * @param f The #Foundation. rubidium@8266: * @return true iff f is a special rail foundation for single horizontal/vertical track. rubidium@8266: */ rubidium@8266: static inline bool IsSpecialRailFoundation(Foundation f) rubidium@8266: { skidd13@8450: return IsInsideMM(f, FOUNDATION_RAIL_W, FOUNDATION_RAIL_N + 1); rubidium@8266: } rubidium@8266: rubidium@8266: /** rubidium@8266: * Returns the track corner of a special rail foundation rubidium@8266: * rubidium@8266: * @param f The #Foundation. rubidium@8266: * @return The #Corner with track. rubidium@8266: */ rubidium@8266: static inline Corner GetRailFoundationCorner(Foundation f) rubidium@8266: { rubidium@8266: assert(IsSpecialRailFoundation(f)); rubidium@8266: return (Corner)(f - FOUNDATION_RAIL_W); rubidium@8266: } rubidium@8266: rubidium@8266: /** rubidium@7831: * Returns the foundation needed to flatten a slope. rubidium@7831: * The returned foundation is either FOUNDATION_NONE if the tile was already flat, or FOUNDATION_LEVELED. rubidium@7831: * rubidium@7831: * @pre The slope must not be steep. rubidium@7831: * @param s The current #Slope. rubidium@7831: * @return The needed #Foundation. rubidium@7831: */ rubidium@7831: static inline Foundation FlatteningFoundation(Slope s) rubidium@7831: { rubidium@7831: assert(!IsSteepSlope(s)); rubidium@7831: return (s == SLOPE_FLAT ? FOUNDATION_NONE : FOUNDATION_LEVELED); rubidium@7831: } rubidium@7831: rubidium@7831: /** rubidium@7831: * Returns the along a specific axis inclined foundation. rubidium@7831: * rubidium@7831: * @param axis The #Axis. rubidium@7831: * @return The needed #Foundation. rubidium@7831: */ rubidium@7831: static inline Foundation InclinedFoundation(Axis axis) rubidium@7831: { rubidium@7831: return (axis == AXIS_X ? FOUNDATION_INCLINED_X : FOUNDATION_INCLINED_Y); rubidium@7831: } rubidium@7831: rubidium@8266: /** rubidium@8266: * Returns the halftile foundation for single horizontal/vertical track. rubidium@8266: * rubidium@8266: * @param corner The #Corner with the track. rubidium@8266: * @return The wanted #Foundation. rubidium@8266: */ rubidium@8266: static inline Foundation HalftileFoundation(Corner corner) rubidium@8266: { rubidium@8266: assert(IsValidCorner(corner)); rubidium@8266: return (Foundation)(FOUNDATION_HALFTILE_W + corner); rubidium@8266: } rubidium@8266: rubidium@8266: /** rubidium@8266: * Returns the special rail foundation for single horizontal/vertical track. rubidium@8266: * rubidium@8266: * @param corner The #Corner with the track. rubidium@8266: * @return The wanted #Foundation. rubidium@8266: */ rubidium@8266: static inline Foundation SpecialRailFoundation(Corner corner) rubidium@8266: { rubidium@8266: assert(IsValidCorner(corner)); rubidium@8266: return (Foundation)(FOUNDATION_RAIL_W + corner); rubidium@8266: } rubidium@8266: rubidium@8604: #endif /* SLOPE_FUNC_H */