1
0
Fork 0

Codechange: Replace HasVehicleOnPos and callbacks with HasVehicleOnTile and lambda-predicates.

pull/14082/head
frosch 2025-04-22 14:23:43 +02:00 committed by frosch
parent dacd77b2bd
commit 06c399b79e
7 changed files with 61 additions and 90 deletions

View File

@ -3032,14 +3032,6 @@ static CommandCost TestAutoslopeOnRailTile(TileIndex tile, DoCommandFlags flags,
return cost; return cost;
} }
/**
* Test-procedure for HasVehicleOnPos to check for a ship.
*/
static Vehicle *EnsureNoShipProc(Vehicle *v, void *)
{
return v->type == VEH_SHIP ? v : nullptr;
}
static CommandCost TerraformTile_Track(TileIndex tile, DoCommandFlags flags, int z_new, Slope tileh_new) static CommandCost TerraformTile_Track(TileIndex tile, DoCommandFlags flags, int z_new, Slope tileh_new)
{ {
auto [tileh_old, z_old] = GetTileSlopeZ(tile); auto [tileh_old, z_old] = GetTileSlopeZ(tile);
@ -3049,7 +3041,9 @@ static CommandCost TerraformTile_Track(TileIndex tile, DoCommandFlags flags, int
bool was_water = (GetRailGroundType(tile) == RAIL_GROUND_WATER && IsSlopeWithOneCornerRaised(tileh_old)); bool was_water = (GetRailGroundType(tile) == RAIL_GROUND_WATER && IsSlopeWithOneCornerRaised(tileh_old));
/* Allow clearing the water only if there is no ship */ /* Allow clearing the water only if there is no ship */
if (was_water && HasVehicleOnPos(tile, nullptr, &EnsureNoShipProc)) return CommandCost(STR_ERROR_SHIP_IN_THE_WAY); if (was_water && HasVehicleOnTile(tile, [](const Vehicle *v) {
return v->type == VEH_SHIP;
})) return CommandCost(STR_ERROR_SHIP_IN_THE_WAY);
/* First test autoslope. However if it succeeds we still have to test the rest, because non-autoslope terraforming is cheaper. */ /* First test autoslope. However if it succeeds we still have to test the rest, because non-autoslope terraforming is cheaper. */
CommandCost autoslope_result = TestAutoslopeOnRailTile(tile, flags, z_old, tileh_old, z_new, tileh_new, rail_bits); CommandCost autoslope_result = TestAutoslopeOnRailTile(tile, flags, z_old, tileh_old, z_new, tileh_new, rail_bits);

View File

@ -767,13 +767,6 @@ struct OvertakeData {
Trackdir trackdir; Trackdir trackdir;
}; };
static Vehicle *EnumFindVehBlockingOvertake(Vehicle *v, void *data)
{
const OvertakeData *od = (OvertakeData*)data;
return (v->type == VEH_ROAD && v->First() == v && v != od->u && v != od->v) ? v : nullptr;
}
/** /**
* Check if overtaking is possible on a piece of track * Check if overtaking is possible on a piece of track
* *
@ -792,7 +785,9 @@ static bool CheckRoadBlockedForOvertaking(OvertakeData *od)
if (!HasBit(trackdirbits, od->trackdir) || (trackbits & ~TRACK_BIT_CROSS) || (red_signals != TRACKDIR_BIT_NONE)) return true; if (!HasBit(trackdirbits, od->trackdir) || (trackbits & ~TRACK_BIT_CROSS) || (red_signals != TRACKDIR_BIT_NONE)) return true;
/* Are there more vehicles on the tile except the two vehicles involved in overtaking */ /* Are there more vehicles on the tile except the two vehicles involved in overtaking */
return HasVehicleOnPos(od->tile, od, EnumFindVehBlockingOvertake); return HasVehicleOnTile(od->tile, [&](const Vehicle *v) {
return v->type == VEH_ROAD && v->First() == v && v != od->u && v != od->v;
});
} }
static void RoadVehCheckOvertake(RoadVehicle *v, RoadVehicle *u) static void RoadVehCheckOvertake(RoadVehicle *v, RoadVehicle *u)

View File

@ -359,14 +359,6 @@ void Ship::UpdateDeltaXY()
} }
} }
/**
* Test-procedure for HasVehicleOnPos to check for any ships which are moving.
*/
static Vehicle *EnsureNoMovingShipProc(Vehicle *v, void *)
{
return v->type == VEH_SHIP && v->cur_speed != 0 ? v : nullptr;
}
static bool CheckReverseShip(const Ship *v, Trackdir *trackdir = nullptr) static bool CheckReverseShip(const Ship *v, Trackdir *trackdir = nullptr)
{ {
/* Ask pathfinder for best direction */ /* Ask pathfinder for best direction */
@ -392,7 +384,9 @@ static bool CheckShipLeaveDepot(Ship *v)
/* Don't leave depot if another vehicle is already entering/leaving */ /* Don't leave depot if another vehicle is already entering/leaving */
/* This helps avoid CPU load if many ships are set to start at the same time */ /* This helps avoid CPU load if many ships are set to start at the same time */
if (HasVehicleOnPos(v->tile, nullptr, &EnsureNoMovingShipProc)) return true; if (HasVehicleOnTile(v->tile, [](const Vehicle *u) {
return u->type == VEH_SHIP && u->cur_speed != 0;
})) return true;
TileIndex tile = v->tile; TileIndex tile = v->tile;
Axis axis = GetShipDepotAxis(tile); Axis axis = GetShipDepotAxis(tile);

View File

@ -189,11 +189,9 @@ static SmallSet<DiagDirection, SIG_GLOB_SIZE> _globset("_globset"); ///< set of
/** Check whether there is a train on rail, not in a depot */ /** Check whether there is a train on rail, not in a depot */
static Vehicle *TrainOnTileEnum(Vehicle *v, void *) static bool IsTrainAndNotInDepot(const Vehicle *v)
{ {
if (v->type != VEH_TRAIN || Train::From(v)->track == TRACK_BIT_DEPOT) return nullptr; return v->type == VEH_TRAIN && Train::From(v)->track != TRACK_BIT_DEPOT;
return v;
} }
@ -280,13 +278,13 @@ static SigFlags ExploreSegment(Owner owner)
if (IsRailDepot(tile)) { if (IsRailDepot(tile)) {
if (enterdir == INVALID_DIAGDIR) { // from 'inside' - train just entered or left the depot if (enterdir == INVALID_DIAGDIR) { // from 'inside' - train just entered or left the depot
if (!flags.Test(SigFlag::Train) && HasVehicleOnPos(tile, nullptr, &TrainOnTileEnum)) flags.Set(SigFlag::Train); if (!flags.Test(SigFlag::Train) && HasVehicleOnTile(tile, IsTrainAndNotInDepot)) flags.Set(SigFlag::Train);
exitdir = GetRailDepotDirection(tile); exitdir = GetRailDepotDirection(tile);
tile += TileOffsByDiagDir(exitdir); tile += TileOffsByDiagDir(exitdir);
enterdir = ReverseDiagDir(exitdir); enterdir = ReverseDiagDir(exitdir);
break; break;
} else if (enterdir == GetRailDepotDirection(tile)) { // entered a depot } else if (enterdir == GetRailDepotDirection(tile)) { // entered a depot
if (!flags.Test(SigFlag::Train) && HasVehicleOnPos(tile, nullptr, &TrainOnTileEnum)) flags.Set(SigFlag::Train); if (!flags.Test(SigFlag::Train) && HasVehicleOnTile(tile, IsTrainAndNotInDepot)) flags.Set(SigFlag::Train);
continue; continue;
} else { } else {
continue; continue;
@ -303,7 +301,7 @@ static SigFlags ExploreSegment(Owner owner)
if (!flags.Test(SigFlag::Train) && EnsureNoTrainOnTrackBits(tile, tracks).Failed()) flags. Set(SigFlag::Train); if (!flags.Test(SigFlag::Train) && EnsureNoTrainOnTrackBits(tile, tracks).Failed()) flags. Set(SigFlag::Train);
} else { } else {
if (tracks_masked == TRACK_BIT_NONE) continue; // no incidating track if (tracks_masked == TRACK_BIT_NONE) continue; // no incidating track
if (!flags.Test(SigFlag::Train) && HasVehicleOnPos(tile, nullptr, &TrainOnTileEnum)) flags.Set(SigFlag::Train); if (!flags.Test(SigFlag::Train) && HasVehicleOnTile(tile, IsTrainAndNotInDepot)) flags.Set(SigFlag::Train);
} }
/* Is this a track merge or split? */ /* Is this a track merge or split? */
@ -358,7 +356,7 @@ static SigFlags ExploreSegment(Owner owner)
if (DiagDirToAxis(enterdir) != GetRailStationAxis(tile)) continue; // different axis if (DiagDirToAxis(enterdir) != GetRailStationAxis(tile)) continue; // different axis
if (IsStationTileBlocked(tile)) continue; // 'eye-candy' station tile if (IsStationTileBlocked(tile)) continue; // 'eye-candy' station tile
if (!flags.Test(SigFlag::Train) && HasVehicleOnPos(tile, nullptr, &TrainOnTileEnum)) flags.Set(SigFlag::Train); if (!flags.Test(SigFlag::Train) && HasVehicleOnTile(tile, IsTrainAndNotInDepot)) flags.Set(SigFlag::Train);
tile += TileOffsByDiagDir(exitdir); tile += TileOffsByDiagDir(exitdir);
break; break;
@ -367,7 +365,7 @@ static SigFlags ExploreSegment(Owner owner)
if (GetTileOwner(tile) != owner) continue; if (GetTileOwner(tile) != owner) continue;
if (DiagDirToAxis(enterdir) == GetCrossingRoadAxis(tile)) continue; // different axis if (DiagDirToAxis(enterdir) == GetCrossingRoadAxis(tile)) continue; // different axis
if (!flags.Test(SigFlag::Train) && HasVehicleOnPos(tile, nullptr, &TrainOnTileEnum)) flags.Set(SigFlag::Train); if (!flags.Test(SigFlag::Train) && HasVehicleOnTile(tile, IsTrainAndNotInDepot)) flags.Set(SigFlag::Train);
tile += TileOffsByDiagDir(exitdir); tile += TileOffsByDiagDir(exitdir);
break; break;
@ -377,13 +375,13 @@ static SigFlags ExploreSegment(Owner owner)
DiagDirection dir = GetTunnelBridgeDirection(tile); DiagDirection dir = GetTunnelBridgeDirection(tile);
if (enterdir == INVALID_DIAGDIR) { // incoming from the wormhole if (enterdir == INVALID_DIAGDIR) { // incoming from the wormhole
if (!flags.Test(SigFlag::Train) && HasVehicleOnPos(tile, nullptr, &TrainOnTileEnum)) flags.Set(SigFlag::Train); if (!flags.Test(SigFlag::Train) && HasVehicleOnTile(tile, IsTrainAndNotInDepot)) flags.Set(SigFlag::Train);
enterdir = dir; enterdir = dir;
exitdir = ReverseDiagDir(dir); exitdir = ReverseDiagDir(dir);
tile += TileOffsByDiagDir(exitdir); // just skip to next tile tile += TileOffsByDiagDir(exitdir); // just skip to next tile
} else { // NOT incoming from the wormhole! } else { // NOT incoming from the wormhole!
if (ReverseDiagDir(enterdir) != dir) continue; if (ReverseDiagDir(enterdir) != dir) continue;
if (!flags.Test(SigFlag::Train) && HasVehicleOnPos(tile, nullptr, &TrainOnTileEnum)) flags.Set(SigFlag::Train); if (!flags.Test(SigFlag::Train) && HasVehicleOnTile(tile, IsTrainAndNotInDepot)) flags.Set(SigFlag::Train);
tile = GetOtherTunnelBridgeEnd(tile); // just skip to exit tile tile = GetOtherTunnelBridgeEnd(tile); // just skip to exit tile
enterdir = INVALID_DIAGDIR; enterdir = INVALID_DIAGDIR;
exitdir = INVALID_DIAGDIR; exitdir = INVALID_DIAGDIR;

View File

@ -1664,15 +1664,14 @@ void ReverseTrainSwapVeh(Train *v, int l, int r)
} }
} }
/** /**
* Check if the vehicle is a train * Check if the vehicle is a train
* @param v vehicle on tile * @param v vehicle on tile
* @return v if it is a train, nullptr otherwise * @return true if v is a train
*/ */
static Vehicle *TrainOnTileEnum(Vehicle *v, void *) static bool IsTrain(const Vehicle *v)
{ {
return (v->type == VEH_TRAIN) ? v : nullptr; return v->type == VEH_TRAIN;
} }
/** /**
@ -1685,28 +1684,23 @@ bool TrainOnCrossing(TileIndex tile)
{ {
assert(IsLevelCrossingTile(tile)); assert(IsLevelCrossingTile(tile));
return HasVehicleOnPos(tile, nullptr, &TrainOnTileEnum); return HasVehicleOnTile(tile, IsTrain);
} }
/** /**
* Checks if a train is approaching a rail-road crossing * Checks if a train is approaching a rail-road crossing
* @param v vehicle on tile * @param v vehicle on tile
* @param data tile with crossing we are testing * @param tile tile with crossing we are testing
* @return v if it is approaching a crossing, nullptr otherwise * @return true if v is approaching a crossing
*/ */
static Vehicle *TrainApproachingCrossingEnum(Vehicle *v, void *data) static bool TrainApproachingCrossingEnum(const Vehicle *v, TileIndex tile)
{ {
if (v->type != VEH_TRAIN || v->vehstatus.Test(VehState::Crashed)) return nullptr; if (v->type != VEH_TRAIN || v->vehstatus.Test(VehState::Crashed)) return false;
Train *t = Train::From(v); const Train *t = Train::From(v);
if (!t->IsFrontEngine()) return nullptr; if (!t->IsFrontEngine()) return false;
TileIndex tile = *(TileIndex *)data; return TrainApproachingCrossingTile(t) == tile;
if (TrainApproachingCrossingTile(t) != tile) return nullptr;
return t;
} }
@ -1723,12 +1717,16 @@ static bool TrainApproachingCrossing(TileIndex tile)
DiagDirection dir = AxisToDiagDir(GetCrossingRailAxis(tile)); DiagDirection dir = AxisToDiagDir(GetCrossingRailAxis(tile));
TileIndex tile_from = tile + TileOffsByDiagDir(dir); TileIndex tile_from = tile + TileOffsByDiagDir(dir);
if (HasVehicleOnPos(tile_from, &tile, &TrainApproachingCrossingEnum)) return true; if (HasVehicleOnTile(tile_from, [&](const Vehicle *v) {
return TrainApproachingCrossingEnum(v, tile);
})) return true;
dir = ReverseDiagDir(dir); dir = ReverseDiagDir(dir);
tile_from = tile + TileOffsByDiagDir(dir); tile_from = tile + TileOffsByDiagDir(dir);
return HasVehicleOnPos(tile_from, &tile, &TrainApproachingCrossingEnum); return HasVehicleOnTile(tile_from, [&](const Vehicle *v) {
return TrainApproachingCrossingEnum(v, tile);
});
} }
/** /**
@ -3252,21 +3250,6 @@ static bool CheckTrainCollision(Train *v)
return true; return true;
} }
static Vehicle *CheckTrainAtSignal(Vehicle *v, void *data)
{
if (v->type != VEH_TRAIN || v->vehstatus.Test(VehState::Crashed)) return nullptr;
Train *t = Train::From(v);
DiagDirection exitdir = *(DiagDirection *)data;
/* not front engine of a train, inside wormhole or depot, crashed */
if (!t->IsFrontEngine() || !(t->track & TRACK_BIT_MASK)) return nullptr;
if (t->cur_speed > 5 || VehicleExitDir(t->direction, t->track) != exitdir) return nullptr;
return t;
}
/** /**
* Move a vehicle chain one movement stop forwards. * Move a vehicle chain one movement stop forwards.
* @param v First vehicle to move. * @param v First vehicle to move.
@ -3384,7 +3367,17 @@ bool TrainController(Train *v, Vehicle *nomove, bool reverse)
exitdir = ReverseDiagDir(exitdir); exitdir = ReverseDiagDir(exitdir);
/* check if a train is waiting on the other side */ /* check if a train is waiting on the other side */
if (!HasVehicleOnPos(o_tile, &exitdir, &CheckTrainAtSignal)) return false; if (!HasVehicleOnTile(o_tile, [&exitdir](const Vehicle *u) {
if (u->type != VEH_TRAIN || u->vehstatus.Test(VehState::Crashed)) return false;
const Train *t = Train::From(u);
/* not front engine of a train, inside wormhole or depot, crashed */
if (!t->IsFrontEngine() || !(t->track & TRACK_BIT_MASK)) return false;
if (t->cur_speed > 5 || VehicleExitDir(t->direction, t->track) != exitdir) return false;
return true;
})) return false;
} }
} }
@ -3617,10 +3610,10 @@ static bool IsRailStationPlatformOccupied(TileIndex tile)
TileIndexDiff delta = TileOffsByAxis(GetRailStationAxis(tile)); TileIndexDiff delta = TileOffsByAxis(GetRailStationAxis(tile));
for (TileIndex t = tile; IsCompatibleTrainStationTile(t, tile); t -= delta) { for (TileIndex t = tile; IsCompatibleTrainStationTile(t, tile); t -= delta) {
if (HasVehicleOnPos(t, nullptr, &TrainOnTileEnum)) return true; if (HasVehicleOnTile(t, IsTrain)) return true;
} }
for (TileIndex t = tile + delta; IsCompatibleTrainStationTile(t, tile); t += delta) { for (TileIndex t = tile + delta; IsCompatibleTrainStationTile(t, tile); t += delta) {
if (HasVehicleOnPos(t, nullptr, &TrainOnTileEnum)) return true; if (HasVehicleOnTile(t, IsTrain)) return true;
} }
return false; return false;

View File

@ -544,21 +544,6 @@ void FindVehicleOnPos(TileIndex tile, void *data, VehicleFromPosProc *proc)
VehicleFromPos(tile, data, proc, false); VehicleFromPos(tile, data, proc, false);
} }
/**
* Checks whether a vehicle is on a specific location. It will call \a proc for
* vehicles until it returns non-nullptr.
* @note Use #FindVehicleOnPos when you have the intention that all vehicles
* should be iterated over.
* @param tile The location on the map
* @param data Arbitrary data passed to \a proc.
* @param proc The \a proc that determines whether a vehicle will be "found".
* @return True if proc returned non-nullptr.
*/
bool HasVehicleOnPos(TileIndex tile, void *data, VehicleFromPosProc *proc)
{
return VehicleFromPos(tile, data, proc, true) != nullptr;
}
/** /**
* Callback that returns 'real' vehicles lower or at height \c *(int*)data . * Callback that returns 'real' vehicles lower or at height \c *(int*)data .
* @param v Vehicle to examine. * @param v Vehicle to examine.

View File

@ -98,13 +98,25 @@ private:
Iterator start; Iterator start;
}; };
/**
* Loop over vehicles on a tile, and check whether a predicate is true for any of them.
* The predicate must have the signature: bool Predicate(const Vehicle *);
*/
template <class UnaryPred>
bool HasVehicleOnTile(TileIndex tile, UnaryPred &&predicate)
{
for (const auto *v : VehiclesOnTile(tile)) {
if (predicate(v)) return true;
}
return false;
}
typedef Vehicle *VehicleFromPosProc(Vehicle *v, void *data); typedef Vehicle *VehicleFromPosProc(Vehicle *v, void *data);
void VehicleServiceInDepot(Vehicle *v); void VehicleServiceInDepot(Vehicle *v);
uint CountVehiclesInChain(const Vehicle *v); uint CountVehiclesInChain(const Vehicle *v);
void FindVehicleOnPos(TileIndex tile, void *data, VehicleFromPosProc *proc); void FindVehicleOnPos(TileIndex tile, void *data, VehicleFromPosProc *proc);
void FindVehicleOnPosXY(int x, int y, void *data, VehicleFromPosProc *proc); void FindVehicleOnPosXY(int x, int y, void *data, VehicleFromPosProc *proc);
bool HasVehicleOnPos(TileIndex tile, void *data, VehicleFromPosProc *proc);
bool HasVehicleOnPosXY(int x, int y, void *data, VehicleFromPosProc *proc); bool HasVehicleOnPosXY(int x, int y, void *data, VehicleFromPosProc *proc);
void CallVehicleTicks(); void CallVehicleTicks();
uint8_t CalcPercentVehicleFilled(const Vehicle *v, StringID *colour); uint8_t CalcPercentVehicleFilled(const Vehicle *v, StringID *colour);