1
0
Fork 0

Codechange: Use EnumBitSet for RailTypes.

pull/13892/head
Peter Nelson 2025-03-24 20:35:57 +00:00 committed by Peter Nelson
parent 732109e444
commit 47d078c033
14 changed files with 67 additions and 77 deletions

View File

@ -71,7 +71,7 @@ bool CheckAutoreplaceValidity(EngineID from, EngineID to, CompanyID company)
switch (type) {
case VEH_TRAIN: {
/* make sure the railtypes are compatible */
if ((GetRailTypeInfo(e_from->u.rail.railtype)->compatible_railtypes & GetRailTypeInfo(e_to->u.rail.railtype)->compatible_railtypes) == 0) return false;
if (!GetRailTypeInfo(e_from->u.rail.railtype)->compatible_railtypes.Any(GetRailTypeInfo(e_to->u.rail.railtype)->compatible_railtypes)) return false;
/* make sure we do not replace wagons with engines or vice versa */
if ((e_from->u.rail.railveh_type == RAILVEH_WAGON) != (e_to->u.rail.railveh_type == RAILVEH_WAGON)) return false;

View File

@ -1780,19 +1780,19 @@ struct CompanyInfrastructureWindow : Window
void UpdateRailRoadTypes()
{
this->railtypes = RAILTYPES_NONE;
this->railtypes = {};
this->roadtypes = {};
/* Find the used railtypes. */
for (const Engine *e : Engine::IterateType(VEH_TRAIN)) {
if (!e->info.climates.Test(_settings_game.game_creation.landscape)) continue;
this->railtypes |= GetRailTypeInfo(e->u.rail.railtype)->introduces_railtypes;
this->railtypes.Set(GetRailTypeInfo(e->u.rail.railtype)->introduces_railtypes);
}
/* Get the date introduced railtypes as well. */
this->railtypes = AddDateIntroducedRailTypes(this->railtypes, CalendarTime::MAX_DATE);
this->railtypes &= ~_railtypes_hidden_mask;
this->railtypes.Reset(_railtypes_hidden_mask);
/* Find the used roadtypes. */
for (const Engine *e : Engine::IterateType(VEH_ROAD)) {
@ -1814,7 +1814,7 @@ struct CompanyInfrastructureWindow : Window
uint32_t rail_total = c->infrastructure.GetRailTotal();
for (RailType rt = RAILTYPE_BEGIN; rt != RAILTYPE_END; rt++) {
if (HasBit(this->railtypes, rt)) total += RailMaintenanceCost(rt, c->infrastructure.rail[rt], rail_total);
if (this->railtypes.Test(rt)) total += RailMaintenanceCost(rt, c->infrastructure.rail[rt], rail_total);
}
total += SignalMaintenanceCost(c->infrastructure.signal);
@ -1853,12 +1853,12 @@ struct CompanyInfrastructureWindow : Window
size.width = std::max(size.width, GetStringBoundingBox(STR_COMPANY_INFRASTRUCTURE_VIEW_RAIL_SECT).width + padding.width);
for (const auto &rt : _sorted_railtypes) {
if (HasBit(this->railtypes, rt)) {
if (this->railtypes.Test(rt)) {
lines++;
size.width = std::max(size.width, GetStringBoundingBox(GetRailTypeInfo(rt)->strings.name).width + padding.width + WidgetDimensions::scaled.hsep_indent);
}
}
if (this->railtypes != RAILTYPES_NONE) {
if (this->railtypes.Any()) {
lines++;
size.width = std::max(size.width, GetStringBoundingBox(STR_COMPANY_INFRASTRUCTURE_VIEW_SIGNALS).width + padding.width + WidgetDimensions::scaled.hsep_indent);
}
@ -1978,10 +1978,10 @@ struct CompanyInfrastructureWindow : Window
case WID_CI_RAIL_DESC:
DrawString(r.left, r.right, y, STR_COMPANY_INFRASTRUCTURE_VIEW_RAIL_SECT);
if (this->railtypes != RAILTYPES_NONE) {
if (this->railtypes.Any()) {
/* Draw name of each valid railtype. */
for (const auto &rt : _sorted_railtypes) {
if (HasBit(this->railtypes, rt)) {
if (this->railtypes.Test(rt)) {
DrawString(ir.left, ir.right, y += GetCharacterHeight(FS_NORMAL), GetRailTypeInfo(rt)->strings.name, TC_WHITE);
}
}
@ -1997,11 +1997,11 @@ struct CompanyInfrastructureWindow : Window
/* Draw infrastructure count for each valid railtype. */
uint32_t rail_total = c->infrastructure.GetRailTotal();
for (const auto &rt : _sorted_railtypes) {
if (HasBit(this->railtypes, rt)) {
if (this->railtypes.Test(rt)) {
this->DrawCountLine(r, y, c->infrastructure.rail[rt], RailMaintenanceCost(rt, c->infrastructure.rail[rt], rail_total));
}
}
if (this->railtypes != RAILTYPES_NONE) {
if (this->railtypes.Any()) {
this->DrawCountLine(r, y, c->infrastructure.signal, SignalMaintenanceCost(c->infrastructure.signal));
}
break;

View File

@ -622,7 +622,7 @@ void UpdateDisableElrailSettingState(bool disable, bool update_vehicles)
if (t->railtype == RAILTYPE_ELECTRIC) {
/* this railroad vehicle is now compatible only with elrail,
* so add there also normal rail compatibility */
t->compatible_railtypes |= RAILTYPES_RAIL;
t->compatible_railtypes.Set(RAILTYPE_RAIL);
t->railtype = RAILTYPE_RAIL;
SetBit(t->flags, VRF_EL_ENGINE_ALLOWED_NORMAL_RAIL);
}

View File

@ -1276,7 +1276,7 @@ bool IsEngineBuildable(EngineID engine, VehicleType type, CompanyID company)
if (type == VEH_TRAIN && company != OWNER_DEITY) {
/* Check if the rail type is available to this company */
const Company *c = Company::Get(company);
if (((GetRailTypeInfo(e->u.rail.railtype))->compatible_railtypes & c->avail_railtypes) == 0) return false;
if (!GetRailTypeInfo(e->u.rail.railtype)->compatible_railtypes.Any(c->avail_railtypes)) return false;
}
if (type == VEH_ROAD && company != OWNER_DEITY) {
/* Check if the road type is available to this company */

View File

@ -86,10 +86,10 @@ static ChangeInfoResult RailTypeChangeInfo(uint first, uint last, int prop, Byte
RailType resolved_rt = GetRailTypeByLabel(std::byteswap(label), false);
if (resolved_rt != INVALID_RAILTYPE) {
switch (prop) {
case 0x0F: SetBit(rti->powered_railtypes, resolved_rt); [[fallthrough]]; // Powered implies compatible.
case 0x0E: SetBit(rti->compatible_railtypes, resolved_rt); break;
case 0x18: SetBit(rti->introduction_required_railtypes, resolved_rt); break;
case 0x19: SetBit(rti->introduces_railtypes, resolved_rt); break;
case 0x0F: rti->powered_railtypes.Set(resolved_rt); [[fallthrough]]; // Powered implies compatible.
case 0x0E: rti->compatible_railtypes.Set(resolved_rt); break;
case 0x18: rti->introduction_required_railtypes.Set(resolved_rt); break;
case 0x19: rti->introduces_railtypes.Set(resolved_rt); break;
}
}
}

View File

@ -333,7 +333,7 @@ protected:
/* rail transport is possible only on compatible rail types */
if (IsRailTT()) {
RailType rail_type = GetTileRailType(this->new_tile);
if (!HasBit(this->railtypes, rail_type)) {
if (!this->railtypes.Test(rail_type)) {
/* incompatible rail type */
this->err = EC_RAIL_ROAD_TYPE;
return false;

View File

@ -22,12 +22,12 @@ public:
void SetDestination(const Train *v, bool override_rail_type = false)
{
this->compatible_railtypes = v->compatible_railtypes;
if (override_rail_type) this->compatible_railtypes |= GetRailTypeInfo(v->railtype)->compatible_railtypes;
if (override_rail_type) this->compatible_railtypes.Set(GetRailTypeInfo(v->railtype)->compatible_railtypes);
}
bool IsCompatibleRailType(RailType rt)
{
return HasBit(this->compatible_railtypes, rt);
return this->compatible_railtypes.Test(rt);
}
RailTypes GetCompatibleRailTypes() const

View File

@ -185,7 +185,7 @@ RailType GetTileRailType(Tile tile)
*/
bool HasRailTypeAvail(const CompanyID company, const RailType railtype)
{
return !HasBit(_railtypes_hidden_mask, railtype) && HasBit(Company::Get(company)->avail_railtypes, railtype);
return !_railtypes_hidden_mask.Test(railtype) && Company::Get(company)->avail_railtypes.Test(railtype);
}
/**
@ -195,7 +195,9 @@ bool HasRailTypeAvail(const CompanyID company, const RailType railtype)
*/
bool HasAnyRailTypesAvail(const CompanyID company)
{
return (Company::Get(company)->avail_railtypes & ~_railtypes_hidden_mask) != 0;
RailTypes avail = Company::Get(company)->avail_railtypes;
avail.Reset(_railtypes_hidden_mask);
return avail.Any();
}
/**
@ -234,7 +236,7 @@ RailTypes AddDateIntroducedRailTypes(RailTypes current, TimerGameCalendar::Date
RailTypes required = rti->introduction_required_railtypes;
if ((rts & required) != required) continue;
rts |= rti->introduces_railtypes;
rts.Set(rti->introduces_railtypes);
}
/* When we added railtypes we need to run this method again; the added
@ -250,7 +252,7 @@ RailTypes AddDateIntroducedRailTypes(RailTypes current, TimerGameCalendar::Date
*/
RailTypes GetCompanyRailTypes(CompanyID company, bool introduces)
{
RailTypes rts = RAILTYPES_NONE;
RailTypes rts{};
for (const Engine *e : Engine::IterateType(VEH_TRAIN)) {
const EngineInfo *ei = &e->info;
@ -262,9 +264,9 @@ RailTypes GetCompanyRailTypes(CompanyID company, bool introduces)
if (rvi->railveh_type != RAILVEH_WAGON) {
assert(rvi->railtype < RAILTYPE_END);
if (introduces) {
rts |= GetRailTypeInfo(rvi->railtype)->introduces_railtypes;
rts.Set(GetRailTypeInfo(rvi->railtype)->introduces_railtypes);
} else {
SetBit(rts, rvi->railtype);
rts.Set(rvi->railtype);
}
}
}
@ -281,7 +283,7 @@ RailTypes GetCompanyRailTypes(CompanyID company, bool introduces)
*/
RailTypes GetRailTypes(bool introduces)
{
RailTypes rts = RAILTYPES_NONE;
RailTypes rts{};
for (const Engine *e : Engine::IterateType(VEH_TRAIN)) {
const EngineInfo *ei = &e->info;
@ -291,9 +293,9 @@ RailTypes GetRailTypes(bool introduces)
if (rvi->railveh_type != RAILVEH_WAGON) {
assert(rvi->railtype < RAILTYPE_END);
if (introduces) {
rts |= GetRailTypeInfo(rvi->railtype)->introduces_railtypes;
rts.Set(GetRailTypeInfo(rvi->railtype)->introduces_railtypes);
} else {
SetBit(rts, rvi->railtype);
rts.Set(rvi->railtype);
}
}
}

View File

@ -314,7 +314,7 @@ inline const RailTypeInfo *GetRailTypeInfo(RailType railtype)
*/
inline bool IsCompatibleRail(RailType enginetype, RailType tiletype)
{
return HasBit(GetRailTypeInfo(enginetype)->compatible_railtypes, tiletype);
return GetRailTypeInfo(enginetype)->compatible_railtypes.Test(tiletype);
}
/**
@ -327,7 +327,7 @@ inline bool IsCompatibleRail(RailType enginetype, RailType tiletype)
*/
inline bool HasPowerOnRail(RailType enginetype, RailType tiletype)
{
return HasBit(GetRailTypeInfo(enginetype)->powered_railtypes, tiletype);
return GetRailTypeInfo(enginetype)->powered_railtypes.Test(tiletype);
}
/**

View File

@ -64,12 +64,12 @@ enum SignalOffsets {
*/
void ResetRailTypes()
{
static_assert(lengthof(_original_railtypes) <= lengthof(_railtypes));
static_assert(std::size(_original_railtypes) <= std::size(_railtypes));
auto insert = std::copy(std::begin(_original_railtypes), std::end(_original_railtypes), std::begin(_railtypes));
std::fill(insert, std::end(_railtypes), RailTypeInfo{});
_railtypes_hidden_mask = RAILTYPES_NONE;
_railtypes_hidden_mask = {};
}
void ResolveRailTypeGUISprites(RailTypeInfo *rti)
@ -132,7 +132,7 @@ void InitRailTypes()
for (RailType rt = RAILTYPE_BEGIN; rt != RAILTYPE_END; rt++) {
RailTypeInfo *rti = &_railtypes[rt];
ResolveRailTypeGUISprites(rti);
if (rti->flags.Test(RailTypeFlag::Hidden)) SetBit(_railtypes_hidden_mask, rt);
if (rti->flags.Test(RailTypeFlag::Hidden)) _railtypes_hidden_mask.Set(rt);
}
_sorted_railtypes.clear();
@ -158,11 +158,11 @@ RailType AllocateRailType(RailTypeLabel label)
rti->alternate_labels.clear();
/* Make us compatible with ourself. */
rti->powered_railtypes = (RailTypes)(1LL << rt);
rti->compatible_railtypes = (RailTypes)(1LL << rt);
rti->powered_railtypes = rt;
rti->compatible_railtypes = rt;
/* We also introduce ourself. */
rti->introduces_railtypes = (RailTypes)(1LL << rt);
rti->introduces_railtypes = rt;
/* Default sort order; order of allocation, but with some
* offsets so it's easier for NewGRF to pick a spot without

View File

@ -2052,9 +2052,9 @@ DropDownList GetRailTypeDropDownList(bool for_replacement, bool all_option)
Dimension d = { 0, 0 };
/* Get largest icon size, to ensure text is aligned on each menu item. */
if (!for_replacement) {
used_railtypes &= ~_railtypes_hidden_mask;
used_railtypes.Reset(_railtypes_hidden_mask);
for (const auto &rt : _sorted_railtypes) {
if (!HasBit(used_railtypes, rt)) continue;
if (!used_railtypes.Test(rt)) continue;
const RailTypeInfo *rti = GetRailTypeInfo(rt);
d = maxdim(d, GetSpriteSize(rti->gui_sprites.build_x_rail));
}
@ -2065,17 +2065,17 @@ DropDownList GetRailTypeDropDownList(bool for_replacement, bool all_option)
for (const auto &rt : _sorted_railtypes) {
/* If it's not used ever, don't show it to the user. */
if (!HasBit(used_railtypes, rt)) continue;
if (!used_railtypes.Test(rt)) continue;
const RailTypeInfo *rti = GetRailTypeInfo(rt);
if (for_replacement) {
list.push_back(MakeDropDownListBadgeItem(badge_class_list, rti->badges, GSF_RAILTYPES, rti->introduction_date, GetString(rti->strings.replace_text), rt, !HasBit(avail_railtypes, rt)));
list.push_back(MakeDropDownListBadgeItem(badge_class_list, rti->badges, GSF_RAILTYPES, rti->introduction_date, GetString(rti->strings.replace_text), rt, !avail_railtypes.Test(rt)));
} else {
std::string str = rti->max_speed > 0
? GetString(STR_TOOLBAR_RAILTYPE_VELOCITY, rti->strings.menu_text, rti->max_speed)
: GetString(rti->strings.menu_text);
list.push_back(MakeDropDownListBadgeIconItem(badge_class_list, rti->badges, GSF_RAILTYPES, rti->introduction_date, d, rti->gui_sprites.build_x_rail, PAL_NONE, std::move(str), rt, !HasBit(avail_railtypes, rt)));
list.push_back(MakeDropDownListBadgeIconItem(badge_class_list, rti->badges, GSF_RAILTYPES, rti->introduction_date, d, rti->gui_sprites.build_x_rail, PAL_NONE, std::move(str), rt, !avail_railtypes.Test(rt)));
}
}

View File

@ -21,8 +21,6 @@ static const RailTypeLabel RAILTYPE_LABEL_MAGLEV = 'MGLV';
/**
* Enumeration for all possible railtypes.
*
* This enumeration defines all 4 possible railtypes.
*/
enum RailType : uint8_t {
RAILTYPE_BEGIN = 0, ///< Used for iterations
@ -37,18 +35,8 @@ enum RailType : uint8_t {
/** Allow incrementing of Track variables */
DECLARE_INCREMENT_DECREMENT_OPERATORS(RailType)
/**
* The different railtypes we support, but then a bitmask of them.
* @note Must be treated as a uint64_t type, narrowing it causes bit membership tests to give wrong results, as in bug #6951.
*/
enum RailTypes : uint64_t {
RAILTYPES_NONE = 0, ///< No rail types
RAILTYPES_RAIL = 1 << RAILTYPE_RAIL, ///< Non-electrified rails
RAILTYPES_ELECTRIC = 1 << RAILTYPE_ELECTRIC, ///< Electrified rails
RAILTYPES_MONO = 1 << RAILTYPE_MONO, ///< Monorail!
RAILTYPES_MAGLEV = 1 << RAILTYPE_MAGLEV, ///< Ever fast maglev
INVALID_RAILTYPES = UINT64_MAX, ///< Invalid railtypes
};
DECLARE_ENUM_AS_BIT_SET(RailTypes)
using RailTypes = EnumBitSet<RailType, uint64_t>;
static constexpr RailTypes INVALID_RAILTYPES{UINT64_MAX};
#endif /* RAIL_TYPE_H */

View File

@ -60,10 +60,10 @@ static const RailTypeInfo _original_railtypes[] = {
SPR_RAIL_SNOW_OFFSET,
/* Powered railtypes */
RAILTYPES_RAIL | RAILTYPES_ELECTRIC,
{RAILTYPE_RAIL, RAILTYPE_ELECTRIC},
/* Compatible railtypes */
RAILTYPES_RAIL | RAILTYPES_ELECTRIC,
{RAILTYPE_RAIL, RAILTYPE_ELECTRIC},
/* bridge offset */
0,
@ -102,10 +102,10 @@ static const RailTypeInfo _original_railtypes[] = {
CalendarTime::INVALID_DATE,
/* railtypes required for this to be introduced */
RAILTYPES_NONE,
{},
/* introduction rail types */
RAILTYPES_RAIL,
{RAILTYPE_RAIL},
/* sort order */
0 << 4 | 7,
@ -162,10 +162,10 @@ static const RailTypeInfo _original_railtypes[] = {
SPR_RAIL_SNOW_OFFSET,
/* Powered railtypes */
RAILTYPES_ELECTRIC,
{RAILTYPE_ELECTRIC},
/* Compatible railtypes */
RAILTYPES_ELECTRIC | RAILTYPES_RAIL,
{RAILTYPE_RAIL, RAILTYPE_ELECTRIC},
/* bridge offset */
0,
@ -204,10 +204,10 @@ static const RailTypeInfo _original_railtypes[] = {
CalendarTime::INVALID_DATE,
/* railtypes required for this to be introduced */
RAILTYPES_NONE,
{},
/* introduction rail types */
RAILTYPES_ELECTRIC,
{RAILTYPE_ELECTRIC},
/* sort order */
1 << 4 | 7,
@ -260,10 +260,10 @@ static const RailTypeInfo _original_railtypes[] = {
SPR_MONO_SNOW_OFFSET,
/* Powered railtypes */
RAILTYPES_MONO,
{RAILTYPE_MONO},
/* Compatible Railtypes */
RAILTYPES_MONO,
{RAILTYPE_MONO},
/* bridge offset */
16,
@ -302,10 +302,10 @@ static const RailTypeInfo _original_railtypes[] = {
CalendarTime::INVALID_DATE,
/* railtypes required for this to be introduced */
RAILTYPES_NONE,
{},
/* introduction rail types */
RAILTYPES_MONO,
{RAILTYPE_MONO},
/* sort order */
2 << 4 | 7,
@ -358,10 +358,10 @@ static const RailTypeInfo _original_railtypes[] = {
SPR_MGLV_SNOW_OFFSET,
/* Powered railtypes */
RAILTYPES_MAGLEV,
{RAILTYPE_MAGLEV},
/* Compatible Railtypes */
RAILTYPES_MAGLEV,
{RAILTYPE_MAGLEV},
/* bridge offset */
24,
@ -400,10 +400,10 @@ static const RailTypeInfo _original_railtypes[] = {
CalendarTime::INVALID_DATE,
/* railtypes required for this to be introduced */
RAILTYPES_NONE,
{},
/* introduction rail types */
RAILTYPES_MAGLEV,
{RAILTYPE_MAGLEV},
/* sort order */
3 << 4 | 7,

View File

@ -114,7 +114,7 @@ void Train::ConsistChanged(ConsistChangeFlags allowed_changes)
const RailVehicleInfo *rvi_v = RailVehInfo(this->engine_type);
EngineID first_engine = this->IsFrontEngine() ? this->engine_type : EngineID::Invalid();
this->gcache.cached_total_length = 0;
this->compatible_railtypes = RAILTYPES_NONE;
this->compatible_railtypes = {};
bool train_can_tilt = true;
int16_t min_curve_speed_mod = INT16_MAX;
@ -172,14 +172,14 @@ void Train::ConsistChanged(ConsistChangeFlags allowed_changes)
/* Do not count powered wagons for the compatible railtypes, as wagons always
have railtype normal */
if (rvi_u->power > 0) {
this->compatible_railtypes |= GetRailTypeInfo(u->railtype)->powered_railtypes;
this->compatible_railtypes.Set(GetRailTypeInfo(u->railtype)->powered_railtypes);
}
/* Some electric engines can be allowed to run on normal rail. It happens to all
* existing electric engines when elrails are disabled and then re-enabled */
if (HasBit(u->flags, VRF_EL_ENGINE_ALLOWED_NORMAL_RAIL)) {
u->railtype = RAILTYPE_RAIL;
u->compatible_railtypes |= RAILTYPES_RAIL;
u->compatible_railtypes.Set(RAILTYPE_RAIL);
}
/* max speed is the minimum of the speed limits of all vehicles in the consist */
@ -3031,7 +3031,7 @@ static void TrainEnterStation(Train *v, StationID station)
static inline bool CheckCompatibleRail(const Train *v, TileIndex tile)
{
return IsTileOwner(tile, v->owner) &&
(!v->IsFrontEngine() || HasBit(v->compatible_railtypes, GetRailType(tile)));
(!v->IsFrontEngine() || v->compatible_railtypes.Test(GetRailType(tile)));
}
/** Data structure for storing engine speed changes of an acceleration type. */