mirror of https://github.com/OpenTTD/OpenTTD
Codechange: Replace HasVehicleOnPos and callbacks with HasVehicleOnTile and lambda-predicates.
parent
dacd77b2bd
commit
06c399b79e
|
@ -3032,14 +3032,6 @@ static CommandCost TestAutoslopeOnRailTile(TileIndex tile, DoCommandFlags flags,
|
|||
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)
|
||||
{
|
||||
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));
|
||||
|
||||
/* 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. */
|
||||
CommandCost autoslope_result = TestAutoslopeOnRailTile(tile, flags, z_old, tileh_old, z_new, tileh_new, rail_bits);
|
||||
|
|
|
@ -767,13 +767,6 @@ struct OvertakeData {
|
|||
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
|
||||
*
|
||||
|
@ -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;
|
||||
|
||||
/* 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)
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
/* 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 */
|
||||
/* 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;
|
||||
Axis axis = GetShipDepotAxis(tile);
|
||||
|
|
|
@ -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 */
|
||||
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;
|
||||
return v->type == VEH_TRAIN && Train::From(v)->track != TRACK_BIT_DEPOT;
|
||||
}
|
||||
|
||||
|
||||
|
@ -280,13 +278,13 @@ static SigFlags ExploreSegment(Owner owner)
|
|||
|
||||
if (IsRailDepot(tile)) {
|
||||
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);
|
||||
tile += TileOffsByDiagDir(exitdir);
|
||||
enterdir = ReverseDiagDir(exitdir);
|
||||
break;
|
||||
} 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;
|
||||
} else {
|
||||
continue;
|
||||
|
@ -303,7 +301,7 @@ static SigFlags ExploreSegment(Owner owner)
|
|||
if (!flags.Test(SigFlag::Train) && EnsureNoTrainOnTrackBits(tile, tracks).Failed()) flags. Set(SigFlag::Train);
|
||||
} else {
|
||||
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? */
|
||||
|
@ -358,7 +356,7 @@ static SigFlags ExploreSegment(Owner owner)
|
|||
if (DiagDirToAxis(enterdir) != GetRailStationAxis(tile)) continue; // different axis
|
||||
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);
|
||||
break;
|
||||
|
||||
|
@ -367,7 +365,7 @@ static SigFlags ExploreSegment(Owner owner)
|
|||
if (GetTileOwner(tile) != owner) continue;
|
||||
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);
|
||||
break;
|
||||
|
||||
|
@ -377,13 +375,13 @@ static SigFlags ExploreSegment(Owner owner)
|
|||
DiagDirection dir = GetTunnelBridgeDirection(tile);
|
||||
|
||||
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;
|
||||
exitdir = ReverseDiagDir(dir);
|
||||
tile += TileOffsByDiagDir(exitdir); // just skip to next tile
|
||||
} else { // NOT incoming from the wormhole!
|
||||
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
|
||||
enterdir = INVALID_DIAGDIR;
|
||||
exitdir = INVALID_DIAGDIR;
|
||||
|
|
|
@ -1664,15 +1664,14 @@ void ReverseTrainSwapVeh(Train *v, int l, int r)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check if the vehicle is a train
|
||||
* @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));
|
||||
|
||||
return HasVehicleOnPos(tile, nullptr, &TrainOnTileEnum);
|
||||
return HasVehicleOnTile(tile, IsTrain);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Checks if a train is approaching a rail-road crossing
|
||||
* @param v vehicle on tile
|
||||
* @param data tile with crossing we are testing
|
||||
* @return v if it is approaching a crossing, nullptr otherwise
|
||||
* @param tile tile with crossing we are testing
|
||||
* @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);
|
||||
if (!t->IsFrontEngine()) return nullptr;
|
||||
const Train *t = Train::From(v);
|
||||
if (!t->IsFrontEngine()) return false;
|
||||
|
||||
TileIndex tile = *(TileIndex *)data;
|
||||
|
||||
if (TrainApproachingCrossingTile(t) != tile) return nullptr;
|
||||
|
||||
return t;
|
||||
return TrainApproachingCrossingTile(t) == tile;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1723,12 +1717,16 @@ static bool TrainApproachingCrossing(TileIndex tile)
|
|||
DiagDirection dir = AxisToDiagDir(GetCrossingRailAxis(tile));
|
||||
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);
|
||||
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;
|
||||
}
|
||||
|
||||
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.
|
||||
* @param v First vehicle to move.
|
||||
|
@ -3384,7 +3367,17 @@ bool TrainController(Train *v, Vehicle *nomove, bool reverse)
|
|||
exitdir = ReverseDiagDir(exitdir);
|
||||
|
||||
/* 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));
|
||||
|
||||
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) {
|
||||
if (HasVehicleOnPos(t, nullptr, &TrainOnTileEnum)) return true;
|
||||
if (HasVehicleOnTile(t, IsTrain)) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
|
|
@ -544,21 +544,6 @@ void FindVehicleOnPos(TileIndex tile, void *data, VehicleFromPosProc *proc)
|
|||
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 .
|
||||
* @param v Vehicle to examine.
|
||||
|
|
|
@ -98,13 +98,25 @@ private:
|
|||
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);
|
||||
|
||||
void VehicleServiceInDepot(Vehicle *v);
|
||||
uint CountVehiclesInChain(const Vehicle *v);
|
||||
void FindVehicleOnPos(TileIndex tile, 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);
|
||||
void CallVehicleTicks();
|
||||
uint8_t CalcPercentVehicleFilled(const Vehicle *v, StringID *colour);
|
||||
|
|
Loading…
Reference in New Issue