diff --git a/src/elrail.cpp b/src/elrail.cpp index 0188f16cc1..708d79539d 100644 --- a/src/elrail.cpp +++ b/src/elrail.cpp @@ -83,7 +83,7 @@ static inline TLG GetTLG(TileIndex t) * @param override pointer to PCP override, can be nullptr * @return trackbits of tile if it is electrified */ -static TrackBits GetRailTrackBitsUniversal(TileIndex t, uint8_t *override) +static TrackBits GetRailTrackBitsUniversal(TileIndex t, DiagDirections *override) { switch (GetTileType(t)) { case MP_RAILWAY: @@ -100,7 +100,7 @@ static TrackBits GetRailTrackBitsUniversal(TileIndex t, uint8_t *override) if (GetTunnelBridgeTransportType(t) != TRANSPORT_RAIL) return TRACK_BIT_NONE; if (!HasRailCatenary(GetRailType(t))) return TRACK_BIT_NONE; if (override != nullptr && (IsTunnel(t) || GetTunnelBridgeLength(t, GetOtherBridgeEnd(t)) > 0)) { - *override = 1 << GetTunnelBridgeDirection(t); + *override = GetTunnelBridgeDirection(t); } return DiagDirToDiagTrackBits(GetTunnelBridgeDirection(t)); @@ -295,10 +295,10 @@ static void DrawRailCatenaryRailway(const TileInfo *ti) } TLG tlg = GetTLG(ti->tile); - uint8_t pcp_status = 0; - uint8_t override_pcp = 0; - uint8_t ppp_preferred[DIAGDIR_END]; - uint8_t ppp_allowed[DIAGDIR_END]; + DiagDirections pcp_status{}; + DiagDirections override_pcp{}; + std::array ppp_preferred{}; + std::array ppp_allowed{}; /* Find which rail bits are present, and select the override points. * We don't draw a pylon: @@ -343,7 +343,7 @@ static void DrawRailCatenaryRailway(const TileInfo *ti) isflat[TS_NEIGHBOUR] = ((trackconfig[TS_NEIGHBOUR] & (TRACK_BIT_HORZ | TRACK_BIT_VERT)) != 0); - ppp_preferred[i] = 0xFF; // We start with preferring everything (end-of-line in any direction) + ppp_preferred[i] = DIRECTIONS_ALL; // We start with preferring everything (end-of-line in any direction) ppp_allowed[i] = AllowedPPPonPCP[i]; /* We cycle through all the existing tracks at a PCP and see what @@ -363,19 +363,19 @@ static void DrawRailCatenaryRailway(const TileInfo *ti) /* track found, if track is in the neighbour tile, adjust the number * of the PCP for preferred/allowed determination*/ pcp_pos = (TrackSourceTile[i][k] == TS_HOME) ? i : ReverseDiagDir(i); - SetBit(pcp_status, i); // This PCP is in use + pcp_status.Set(i); // This PCP is in use ppp_preferred[i] &= PreferredPPPofTrackAtPCP[TracksAtPCP[i][k]][pcp_pos]; } if (HasBit(trackconfig[TrackSourceTile[i][k]], TracksAtPCP[i][k])) { - ppp_allowed[i] &= ~DisallowedPPPofTrackAtPCP[TracksAtPCP[i][k]][pcp_pos]; + ppp_allowed[i].Reset(DisallowedPPPofTrackAtPCP[TracksAtPCP[i][k]][pcp_pos]); } } /* Deactivate all PPPs if PCP is not used */ - if (!HasBit(pcp_status, i)) { - ppp_preferred[i] = 0; - ppp_allowed[i] = 0; + if (!pcp_status.Test(i)) { + ppp_preferred[i].Reset(); + ppp_allowed[i].Reset(); } Foundation foundation = FOUNDATION_NONE; @@ -402,7 +402,7 @@ static void DrawRailCatenaryRailway(const TileInfo *ti) * Level means that the slope is the same, or the track is flat */ if (tileh[TS_HOME] == tileh[TS_NEIGHBOUR] || (isflat[TS_HOME] && isflat[TS_NEIGHBOUR])) { for (uint k = 0; k < NUM_IGNORE_GROUPS; k++) { - if (ppp_preferred[i] == IgnoredPCP[k][tlg][i]) ClrBit(pcp_status, i); + if (ppp_preferred[i] == IgnoredPCP[k][tlg][i]) pcp_status.Reset(i); } } @@ -410,7 +410,7 @@ static void DrawRailCatenaryRailway(const TileInfo *ti) * In that case, we try the any of the allowed ones. if they don't exist either, don't draw * anything. Note that the preferred PPPs still contain the end-of-line markers. * Remove those (simply by ANDing with allowed, since these markers are never allowed) */ - if ((ppp_allowed[i] & ppp_preferred[i]) != 0) ppp_allowed[i] &= ppp_preferred[i]; + if (ppp_allowed[i].Any(ppp_preferred[i])) ppp_allowed[i] &= ppp_preferred[i]; if (IsBridgeAbove(ti->tile)) { Track bridgetrack = GetBridgeAxis(ti->tile) == AXIS_X ? TRACK_X : TRACK_Y; @@ -418,21 +418,23 @@ static void DrawRailCatenaryRailway(const TileInfo *ti) if ((height <= GetTileMaxZ(ti->tile) + 1) && (i == PCPpositions[bridgetrack][0] || i == PCPpositions[bridgetrack][1])) { - SetBit(override_pcp, i); + override_pcp.Set(i); } } - if (ppp_allowed[i] != 0 && HasBit(pcp_status, i) && !HasBit(override_pcp, i) && + if (ppp_allowed[i].Any() && pcp_status.Test(i) && !override_pcp.Test(i) && (!IsRailStationTile(ti->tile) || CanStationTileHavePylons(ti->tile))) { - for (Direction k = DIR_BEGIN; k < DIR_END; k++) { - uint8_t temp = PPPorder[i][GetTLG(ti->tile)][k]; - if (HasBit(ppp_allowed[i], temp)) { - uint x = ti->x + x_pcp_offsets[i] + x_ppp_offsets[temp]; - uint y = ti->y + y_pcp_offsets[i] + y_ppp_offsets[temp]; + const auto &ppp_orders = PPPorder[i][GetTLG(ti->tile)]; + for (Direction k = DIR_BEGIN; k < DIR_END; k++) { + Direction temp = ppp_orders[k]; + + if (ppp_allowed[i].Test(temp)) { + uint x = ti->x + x_pcp_offsets[i] + x_ppp_offsets[temp]; + uint y = ti->y + y_pcp_offsets[i] + y_ppp_offsets[temp]; /* Don't build the pylon if it would be outside the tile */ - if (!HasBit(OwnedPPPonPCP[i], temp)) { + if (!OwnedPPPonPCP[i].Test(temp)) { /* We have a neighbour that will draw it, bail out */ if (trackconfig[TS_NEIGHBOUR] != TRACK_BIT_NONE) break; continue; // No neighbour, go looking for a better position @@ -474,8 +476,8 @@ static void DrawRailCatenaryRailway(const TileInfo *ti) /* Drawing of pylons is finished, now draw the wires */ for (Track t : SetTrackBitIterator(wireconfig[TS_HOME])) { SpriteID wire_base = (t == halftile_track) ? wire_halftile : wire_normal; - uint8_t pcp_config = HasBit(pcp_status, PCPpositions[t][0]) + - (HasBit(pcp_status, PCPpositions[t][1]) << 1); + uint8_t pcp_config = pcp_status.Test(PCPpositions[t][0]) + + (pcp_status.Test(PCPpositions[t][1]) << 1); const SortableSpriteStruct *sss; int tileh_selector = !(tileh[TS_HOME] % 3) * tileh[TS_HOME] / 3; // tileh for the slopes, 0 otherwise diff --git a/src/table/elrail_data.h b/src/table/elrail_data.h index 4c5ec7f4e3..8f10e15563 100644 --- a/src/table/elrail_data.h +++ b/src/table/elrail_data.h @@ -40,11 +40,11 @@ enum TileSource : uint8_t { static const uint NUM_TRACKS_AT_PCP = 6; /** Which PPPs are possible at all on a given PCP */ -static const uint8_t AllowedPPPonPCP[DIAGDIR_END] = { - 1 << DIR_N | 1 << DIR_E | 1 << DIR_SE | 1 << DIR_S | 1 << DIR_W | 1 << DIR_NW, - 1 << DIR_N | 1 << DIR_NE | 1 << DIR_E | 1 << DIR_S | 1 << DIR_SW | 1 << DIR_W, - 1 << DIR_N | 1 << DIR_E | 1 << DIR_SE | 1 << DIR_S | 1 << DIR_W | 1 << DIR_NW, - 1 << DIR_N | 1 << DIR_NE | 1 << DIR_E | 1 << DIR_S | 1 << DIR_SW | 1 << DIR_W, +static const Directions AllowedPPPonPCP[DIAGDIR_END] = { + {DIR_N, DIR_E, DIR_SE, DIR_S, DIR_W, DIR_NW}, + {DIR_N, DIR_NE, DIR_E, DIR_S, DIR_SW, DIR_W}, + {DIR_N, DIR_E, DIR_SE, DIR_S, DIR_W, DIR_NW}, + {DIR_N, DIR_NE, DIR_E, DIR_S, DIR_SW, DIR_W}, }; /** @@ -52,11 +52,11 @@ static const uint8_t AllowedPPPonPCP[DIAGDIR_END] = { * the following system is used: if you rotate the PCP so that it is in the * north, the eastern PPP belongs to the tile. */ -static const uint8_t OwnedPPPonPCP[DIAGDIR_END] = { - 1 << DIR_SE | 1 << DIR_S | 1 << DIR_SW | 1 << DIR_W, - 1 << DIR_N | 1 << DIR_SW | 1 << DIR_W | 1 << DIR_NW, - 1 << DIR_N | 1 << DIR_NE | 1 << DIR_E | 1 << DIR_NW, - 1 << DIR_NE | 1 << DIR_E | 1 << DIR_SE | 1 << DIR_S +static const Directions OwnedPPPonPCP[DIAGDIR_END] = { + {DIR_SE, DIR_S, DIR_SW, DIR_W}, + {DIR_N, DIR_SW, DIR_W, DIR_NW}, + {DIR_N, DIR_NE, DIR_E, DIR_NW}, + {DIR_NE, DIR_E, DIR_SE, DIR_S}, }; /** Maps a track bit onto two PCP positions */ @@ -69,138 +69,137 @@ static const DiagDirection PCPpositions[TRACK_END][2] = { {DIAGDIR_NE, DIAGDIR_SE}, // RIGHT }; -#define PCP_NOT_ON_TRACK 0xFF /** * Preferred points of each trackbit. Those are the ones perpendicular to the * track, plus the point in extension of the track (to mark end-of-track). PCPs * which are not on either end of the track are fully preferred. * @see PCPpositions */ -static const uint8_t PreferredPPPofTrackAtPCP[TRACK_END][DIAGDIR_END] = { - { // X - 1 << DIR_NE | 1 << DIR_SE | 1 << DIR_NW, // NE - PCP_NOT_ON_TRACK, // SE - 1 << DIR_SE | 1 << DIR_SW | 1 << DIR_NW, // SW - PCP_NOT_ON_TRACK // NE - }, { // Y - PCP_NOT_ON_TRACK, - 1 << DIR_NE | 1 << DIR_SE | 1 << DIR_SW, - PCP_NOT_ON_TRACK, - 1 << DIR_SW | 1 << DIR_NW | 1 << DIR_NE - }, { // UPPER - 1 << DIR_E | 1 << DIR_N | 1 << DIR_S, - PCP_NOT_ON_TRACK, - PCP_NOT_ON_TRACK, - 1 << DIR_W | 1 << DIR_N | 1 << DIR_S - }, { // LOWER - PCP_NOT_ON_TRACK, - 1 << DIR_E | 1 << DIR_N | 1 << DIR_S, - 1 << DIR_W | 1 << DIR_N | 1 << DIR_S, - PCP_NOT_ON_TRACK - }, { // LEFT - PCP_NOT_ON_TRACK, - PCP_NOT_ON_TRACK, - 1 << DIR_S | 1 << DIR_E | 1 << DIR_W, - 1 << DIR_N | 1 << DIR_E | 1 << DIR_W - }, { // RIGHT - 1 << DIR_N | 1 << DIR_E | 1 << DIR_W, - 1 << DIR_S | 1 << DIR_E | 1 << DIR_W, - PCP_NOT_ON_TRACK, - PCP_NOT_ON_TRACK - } +static const Directions PreferredPPPofTrackAtPCP[TRACK_END][DIAGDIR_END] = { + { // X + {DIR_NE, DIR_SE, DIR_NW}, // NE + DIRECTIONS_ALL, // SE + {DIR_SE, DIR_SW, DIR_NW}, // SW + DIRECTIONS_ALL // NE + }, + { // Y + DIRECTIONS_ALL, + {DIR_NE, DIR_SE, DIR_SW}, + DIRECTIONS_ALL, + {DIR_SW, DIR_NW, DIR_NE}, + }, + { // UPPER + {DIR_E, DIR_N, DIR_S}, + DIRECTIONS_ALL, + DIRECTIONS_ALL, + {DIR_W, DIR_N, DIR_S}, + }, + { // LOWER + DIRECTIONS_ALL, + {DIR_E, DIR_N, DIR_S}, + {DIR_W, DIR_N, DIR_S}, + DIRECTIONS_ALL, + }, + { // LEFT + DIRECTIONS_ALL, + DIRECTIONS_ALL, + {DIR_S, DIR_E, DIR_W}, + {DIR_N, DIR_E, DIR_W}, + }, + { // RIGHT + {DIR_N, DIR_E, DIR_W}, + {DIR_S, DIR_E, DIR_W}, + DIRECTIONS_ALL, + DIRECTIONS_ALL, + }, }; -#undef PCP_NOT_ON_TRACK - #define NUM_IGNORE_GROUPS 3 -#define IGNORE_NONE 0xFF /** * In case we have a straight line, we place pylon only every two tiles, * so there are certain tiles which we ignore. A straight line is found if * we have exactly two PPPs. */ -static const uint8_t IgnoredPCP[NUM_IGNORE_GROUPS][TLG_END][DIAGDIR_END] = { +static const Directions IgnoredPCP[NUM_IGNORE_GROUPS][TLG_END][DIAGDIR_END] = { { // Ignore group 1, X and Y tracks { // X even, Y even - IGNORE_NONE, - 1 << DIR_NE | 1 << DIR_SW, - 1 << DIR_NW | 1 << DIR_SE, - IGNORE_NONE + DIRECTIONS_ALL, + {DIR_NE, DIR_SW}, + {DIR_NW, DIR_SE}, + DIRECTIONS_ALL, }, { // X even, Y odd - IGNORE_NONE, - IGNORE_NONE, - 1 << DIR_NW | 1 << DIR_SE, - 1 << DIR_NE | 1 << DIR_SW + DIRECTIONS_ALL, + DIRECTIONS_ALL, + {DIR_NW, DIR_SE}, + {DIR_NE, DIR_SW}, }, { // X odd, Y even - 1 << DIR_NW | 1 << DIR_SE, - 1 << DIR_NE | 1 << DIR_SW, - IGNORE_NONE, - IGNORE_NONE + {DIR_NW, DIR_SE}, + {DIR_NE, DIR_SW}, + DIRECTIONS_ALL, + DIRECTIONS_ALL, }, { // X odd, Y odd - 1 << DIR_NW | 1 << DIR_SE, - IGNORE_NONE, - IGNORE_NONE, - 1 << DIR_NE | 1 << DIR_SW + {DIR_NW, DIR_SE}, + DIRECTIONS_ALL, + DIRECTIONS_ALL, + {DIR_NE, DIR_SW}, } }, { // Ignore group 2, LEFT and RIGHT tracks { - 1 << DIR_E | 1 << DIR_W, - IGNORE_NONE, - IGNORE_NONE, - 1 << DIR_E | 1 << DIR_W + {DIR_E, DIR_W}, + DIRECTIONS_ALL, + DIRECTIONS_ALL, + {DIR_E, DIR_W}, }, { - IGNORE_NONE, - 1 << DIR_E | 1 << DIR_W, - 1 << DIR_E | 1 << DIR_W, - IGNORE_NONE + DIRECTIONS_ALL, + {DIR_E, DIR_W}, + {DIR_E, DIR_W}, + DIRECTIONS_ALL, }, { - IGNORE_NONE, - 1 << DIR_E | 1 << DIR_W, - 1 << DIR_E | 1 << DIR_W, - IGNORE_NONE + DIRECTIONS_ALL, + {DIR_E, DIR_W}, + {DIR_E, DIR_W}, + DIRECTIONS_ALL, }, { - 1 << DIR_E | 1 << DIR_W, - IGNORE_NONE, - IGNORE_NONE, - 1 << DIR_E | 1 << DIR_W + {DIR_E, DIR_W}, + DIRECTIONS_ALL, + DIRECTIONS_ALL, + {DIR_E, DIR_W}, } }, { // Ignore group 3, UPPER and LOWER tracks { - 1 << DIR_N | 1 << DIR_S, - 1 << DIR_N | 1 << DIR_S, - IGNORE_NONE, - IGNORE_NONE + {DIR_N, DIR_S}, + {DIR_N, DIR_S}, + DIRECTIONS_ALL, + DIRECTIONS_ALL, }, { - IGNORE_NONE, - IGNORE_NONE, - 1 << DIR_N | 1 << DIR_S, - 1 << DIR_N | 1 << DIR_S + DIRECTIONS_ALL, + DIRECTIONS_ALL, + {DIR_N, DIR_S}, + {DIR_N, DIR_S}, }, { - IGNORE_NONE, - IGNORE_NONE, - 1 << DIR_N | 1 << DIR_S , - 1 << DIR_N | 1 << DIR_S + DIRECTIONS_ALL, + DIRECTIONS_ALL, + {DIR_N, DIR_S}, + {DIR_N, DIR_S}, }, { - 1 << DIR_N | 1 << DIR_S, - 1 << DIR_N | 1 << DIR_S, - IGNORE_NONE, - IGNORE_NONE + {DIR_N, DIR_S}, + {DIR_N, DIR_S}, + DIRECTIONS_ALL, + DIRECTIONS_ALL, } } }; -#undef NO_IGNORE - /** Which pylons can definitely NOT be built */ -static const uint8_t DisallowedPPPofTrackAtPCP[TRACK_END][DIAGDIR_END] = { - {1 << DIR_SW | 1 << DIR_NE, 0, 1 << DIR_SW | 1 << DIR_NE, 0 }, // X - {0, 1 << DIR_NW | 1 << DIR_SE, 0, 1 << DIR_NW | 1 << DIR_SE}, // Y - {1 << DIR_W | 1 << DIR_E, 0, 0, 1 << DIR_W | 1 << DIR_E }, // UPPER - {0, 1 << DIR_W | 1 << DIR_E, 1 << DIR_W | 1 << DIR_E, 0 }, // LOWER - {0, 0, 1 << DIR_S | 1 << DIR_N, 1 << DIR_N | 1 << DIR_S }, // LEFT - {1 << DIR_S | 1 << DIR_N, 1 << DIR_S | 1 << DIR_N, 0, 0, }, // RIGHT +static const Directions DisallowedPPPofTrackAtPCP[TRACK_END][DIAGDIR_END] = { + {{DIR_SW, DIR_NE}, {}, {DIR_SW, DIR_NE}, {} }, // X + {{}, {DIR_NW, DIR_SE}, {}, {DIR_NW, DIR_SE}}, // Y + {{DIR_W, DIR_E}, {}, {}, {DIR_W, DIR_E} }, // UPPER + {{}, {DIR_W, DIR_E}, {DIR_W, DIR_E}, {} }, // LOWER + {{}, {}, {DIR_S, DIR_N}, {DIR_N, DIR_S} }, // LEFT + {{DIR_S, DIR_N}, {DIR_S, DIR_N}, {}, {}, }, // RIGHT }; /* This array stores which track bits can meet at a tile edge */