(svn r11237) -Codechange: reduce code duplication between GetRailFoundation() and CheckRailSlope(). Patch by frosch.

replace/41b28d7194a279bdc17475d4fbe2ea6ec885a466
rubidium 17 years ago
parent a71b7226c5
commit 6cebf4aa53

@ -103,6 +103,10 @@ extern const Trackdir _dir_to_diag_trackdir[] = {
TRACKDIR_X_NE, TRACKDIR_Y_SE, TRACKDIR_X_SW, TRACKDIR_Y_NW,
};
extern const TrackBits _corner_to_trackbits[] = {
TRACK_BIT_LEFT, TRACK_BIT_LOWER, TRACK_BIT_RIGHT, TRACK_BIT_UPPER,
};
RailType GetTileRailType(TileIndex tile)
{

@ -120,6 +120,19 @@ static inline TrackBits AxisToTrackBits(Axis a)
return TrackToTrackBits(AxisToTrack(a));
}
/**
* Returns a single horizontal/vertical trackbit, that is in a specific tile corner.
*
* @param corner The corner of a tile.
* @return The TrackBits of the track in the corner.
*/
static inline TrackBits CornerToTrackBits(Corner corner)
{
extern const TrackBits _corner_to_trackbits[];
assert(IsValidCorner(corner));
return _corner_to_trackbits[corner];
}
/**
* Enumeration for tracks and directions.

@ -150,10 +150,8 @@ static bool CheckTrackCombination(TileIndex tile, TrackBits to_build, uint flags
}
static const TrackBits _valid_tileh_slopes[][15] = {
/* set of normal ones */
{
/** Valid TrackBits on a specific (non-steep)-slope without foundation */
static const TrackBits _valid_tracks_without_foundation[15] = {
TRACK_BIT_ALL,
TRACK_BIT_RIGHT,
TRACK_BIT_UPPER,
@ -172,10 +170,10 @@ static const TrackBits _valid_tileh_slopes[][15] = {
TRACK_BIT_X,
TRACK_BIT_UPPER,
TRACK_BIT_RIGHT,
},
};
/* allowed rail for an evenly raised platform */
{
/** Valid TrackBits on a specific (non-steep)-slope with leveled foundation */
static const TrackBits _valid_tracks_on_leveled_foundation[15] = {
TRACK_BIT_NONE,
TRACK_BIT_LEFT,
TRACK_BIT_LOWER,
@ -194,62 +192,82 @@ static const TrackBits _valid_tileh_slopes[][15] = {
TRACK_BIT_Y | TRACK_BIT_UPPER | TRACK_BIT_RIGHT,
TRACK_BIT_ALL,
TRACK_BIT_ALL
}
};
/**
* Checks if a track combination is valid on a specific slope and returns the needed foundation.
*
* @param tileh Tile slope.
* @param bits Trackbits.
* @return Needed foundation or FOUNDATION_INVALID if track/slope combination is not allowed.
*/
Foundation GetRailFoundation(Slope tileh, TrackBits bits)
{
if (!IsSteepSlope(tileh)) {
if ((~_valid_tileh_slopes[0][tileh] & bits) == 0) return FOUNDATION_NONE;
if ((~_valid_tileh_slopes[1][tileh] & bits) == 0) return FOUNDATION_LEVELED;
}
if (bits == TRACK_BIT_NONE) return FOUNDATION_NONE;
switch (bits) {
default: NOT_REACHED();
case TRACK_BIT_X: return FOUNDATION_INCLINED_X;
case TRACK_BIT_Y: return FOUNDATION_INCLINED_Y;
case TRACK_BIT_LEFT: return (tileh == SLOPE_STEEP_W ? FOUNDATION_STEEP_HIGHER : FOUNDATION_STEEP_LOWER);
case TRACK_BIT_LOWER: return (tileh == SLOPE_STEEP_S ? FOUNDATION_STEEP_HIGHER : FOUNDATION_STEEP_LOWER);
case TRACK_BIT_RIGHT: return (tileh == SLOPE_STEEP_E ? FOUNDATION_STEEP_HIGHER : FOUNDATION_STEEP_LOWER);
case TRACK_BIT_UPPER: return (tileh == SLOPE_STEEP_N ? FOUNDATION_STEEP_HIGHER : FOUNDATION_STEEP_LOWER);
if (IsSteepSlope(tileh)) {
/* Test for inclined foundations */
if (bits == TRACK_BIT_X) return FOUNDATION_INCLINED_X;
if (bits == TRACK_BIT_Y) return FOUNDATION_INCLINED_Y;
/* Get higher track */
Corner highest_corner = GetHighestSlopeCorner(tileh);
TrackBits higher_track = CornerToTrackBits(highest_corner);
/* Only higher track? */
if (bits == higher_track) return FOUNDATION_STEEP_HIGHER;
/* Overlap with higher track? */
if (TracksOverlap(bits | higher_track)) return FOUNDATION_INVALID;
/* either lower track or both higher and lower track */
return ((bits & higher_track) != 0 ? FOUNDATION_INVALID : FOUNDATION_STEEP_LOWER);
} else {
if ((~_valid_tracks_without_foundation[tileh] & bits) == 0) return FOUNDATION_NONE;
bool valid_on_leveled = ((~_valid_tracks_on_leveled_foundation[tileh] & bits) == 0);
switch (bits) {
case TRACK_BIT_X:
if (HasSlopeHighestCorner(tileh)) return FOUNDATION_INCLINED_X;
return (valid_on_leveled ? FOUNDATION_LEVELED : FOUNDATION_INVALID);
case TRACK_BIT_Y:
if (HasSlopeHighestCorner(tileh)) return FOUNDATION_INCLINED_Y;
return (valid_on_leveled ? FOUNDATION_LEVELED : FOUNDATION_INVALID);
default:
return (valid_on_leveled ? FOUNDATION_LEVELED : FOUNDATION_INVALID);
}
}
}
/**
* Tests if a track can be build on a tile.
*
* @param tileh Tile slope.
* @param rail_bits Tracks to build.
* @param existing Tracks already built.
* @param tile Tile (used for water test)
* @return Error message or cost for foundation building.
*/
static CommandCost CheckRailSlope(Slope tileh, TrackBits rail_bits, TrackBits existing, TileIndex tile)
{
if (IsSteepSlope(tileh)) {
if (_patches.build_on_slopes && existing == 0) {
/* 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;
/* don't allow building on the lower side of a coast */
if (IsTileType(tile, MP_WATER)) {
if (!IsSteepSlope(tileh) && ((~_valid_tracks_on_leveled_foundation[tileh] & (rail_bits | existing)) != 0)) return_cmd_error(STR_3807_CAN_T_BUILD_ON_WATER);
}
/* don't allow building on the lower side of a coast */
if (IsTileType(tile, MP_WATER) &&
~_valid_tileh_slopes[1][tileh] & rail_bits) {
return_cmd_error(STR_3807_CAN_T_BUILD_ON_WATER);
}
Foundation f_new = GetRailFoundation(tileh, rail_bits | existing);
/* no special foundation */
if ((~_valid_tileh_slopes[0][tileh] & rail_bits) == 0) {
return CommandCost();
} else if (!_patches.build_on_slopes || _is_old_ai_player) {
return_cmd_error(STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION);
}
/* check track/slope combination */
if ((f_new == FOUNDATION_INVALID) ||
((f_new != FOUNDATION_NONE) && (!_patches.build_on_slopes || _is_old_ai_player))
) return_cmd_error(STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION);
if ((~_valid_tileh_slopes[1][tileh] & rail_bits) == 0 || ( // whole tile is leveled up
(rail_bits == TRACK_BIT_X || rail_bits == TRACK_BIT_Y) &&
(tileh == SLOPE_W || tileh == SLOPE_S || tileh == SLOPE_E || tileh == SLOPE_N)
)) { // partly up
return CommandCost((existing != 0) ? 0 : _price.terraform);
}
}
return_cmd_error(STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION);
Foundation f_old = GetRailFoundation(tileh, existing);
return CommandCost(f_new != f_old ? _price.terraform : 0);
}
/* Validate functions for rail building */

@ -48,8 +48,20 @@ enum Corner {
CORNER_S = 1,
CORNER_E = 2,
CORNER_N = 3,
CORNER_END
};
/**
* Rangecheck for Corner enumeration.
*
* @param corner A #Corner.
* @return true iff corner is in a valid range.
*/
static inline bool IsValidCorner(Corner corner)
{
return IS_INT_INSIDE(corner, 0, CORNER_END);
}
/**
* Checks if a slope is steep.
*
@ -78,6 +90,17 @@ static inline Slope ComplementSlope(Slope s)
return (Slope)(0xF ^ s);
}
/**
* Tests if a slope has a highest corner (i.e. one corner raised or a steep slope).
*
* @param s The #Slope.
* @return true iff the slope has a highest corner.
*/
static inline bool HasSlopeHighestCorner(Slope s)
{
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).
*
@ -132,7 +155,7 @@ static inline Corner OppositeCorner(Corner corner)
*/
static inline Slope SlopeWithOneCornerRaised(Corner corner)
{
assert(IS_INT_INSIDE(corner, 0, 4));
assert(IsValidCorner(corner));
return (Slope)(1 << corner);
}
@ -158,6 +181,8 @@ enum 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_INVALID = 0xFF ///< Used inside "rail_cmd.cpp" to indicate invalid slope/track combination.
};
/**

Loading…
Cancel
Save