Use vehicle tile hash for finding wagons/engines in depots

This commit is contained in:
Jonathan G Rennison 2024-06-27 22:32:22 +01:00
parent fced6d0eb2
commit 618ed0a0ce
2 changed files with 40 additions and 22 deletions

View File

@ -1504,17 +1504,22 @@ static CommandCost CmdBuildRailWagon(TileIndex tile, DoCommandFlag flags, const
CheckConsistencyOfArticulatedVehicle(v); CheckConsistencyOfArticulatedVehicle(v);
/* Try to connect the vehicle to one of free chains of wagons. */ /* Try to connect the vehicle to one of free chains of wagons. */
for (Train *w : Train::IterateFrontOnly()) { std::vector<Train *> candidates;
if (w->tile == tile && ///< Same depot for (Train *w = Train::From(GetFirstVehicleOnPos(tile, VEH_TRAIN)); w != nullptr; w = w->HashTileNext()) {
w->IsFreeWagon() && ///< A free wagon chain if (w->IsFreeWagon() && ///< A free wagon chain
w->engine_type == e->index && ///< Same type w->engine_type == e->index && ///< Same type
w->First() != v && ///< Don't connect to ourself w->First() != v && ///< Don't connect to ourself
!(w->vehstatus & VS_CRASHED) && ///< Not crashed/flooded !(w->vehstatus & VS_CRASHED) && ///< Not crashed/flooded
w->owner == v->owner && ///< Same owner w->owner == v->owner) { ///< Same owner
!w->IsVirtual()) { ///< Not virtual candidates.push_back(w);
if (DoCommand(0, v->index | 1 << 20, w->Last()->index, DC_EXEC, CMD_MOVE_RAIL_VEHICLE).Succeeded()) { }
break; }
} std::sort(candidates.begin(), candidates.end(), [](const Train *a, const Train *b) {
return a->index < b->index;
});
for (Train *w : candidates) {
if (DoCommand(0, v->index | 1 << 20, w->Last()->index, DC_EXEC, CMD_MOVE_RAIL_VEHICLE).Succeeded()) {
break;
} }
} }
@ -1528,16 +1533,20 @@ static CommandCost CmdBuildRailWagon(TileIndex tile, DoCommandFlag flags, const
void NormalizeTrainVehInDepot(const Train *u) void NormalizeTrainVehInDepot(const Train *u)
{ {
assert(u->IsEngine()); assert(u->IsEngine());
for (const Train *v : Train::IterateFrontOnly()) { std::vector<Train *> candidates;
if (v->IsFreeWagon() && v->tile == u->tile && for (Train *v = Train::From(GetFirstVehicleOnPos(u->tile, VEH_TRAIN)); v != nullptr; v = v->HashTileNext()) {
if (v->IsFreeWagon() &&
v->track == TRACK_BIT_DEPOT && v->track == TRACK_BIT_DEPOT &&
v->owner == u->owner && v->owner == u->owner) {
!v->IsVirtual()) { candidates.push_back(v);
if (DoCommand(0, v->index | 1 << 20, u->index, DC_EXEC,
CMD_MOVE_RAIL_VEHICLE).Failed())
break;
} }
} }
std::sort(candidates.begin(), candidates.end(), [](const Train *a, const Train *b) {
return a->index < b->index;
});
for (Train *v : candidates) {
if (DoCommand(0, v->index | 1 << 20, u->index, DC_EXEC, CMD_MOVE_RAIL_VEHICLE).Failed()) break;
}
} }
static void AddRearEngineToMultiheadedTrain(Train *v) static void AddRearEngineToMultiheadedTrain(Train *v)
@ -1670,23 +1679,32 @@ CommandCost CmdBuildRailVehicle(TileIndex tile, DoCommandFlag flags, const Engin
return CommandCost(); return CommandCost();
} }
static Train *FindGoodVehiclePos(const Train *src) static std::vector<Train *> FindGoodVehiclePosList(const Train *src)
{ {
EngineID eng = src->engine_type; EngineID eng = src->engine_type;
TileIndex tile = src->tile; TileIndex tile = src->tile;
for (Train *dst : Train::IterateFrontOnly()) { std::vector<Train *> candidates;
if (dst->IsFreeWagon() && dst->tile == tile && !(dst->vehstatus & VS_CRASHED) && dst->owner == src->owner && !dst->IsVirtual()) {
for (Train *dst = Train::From(GetFirstVehicleOnPos(tile, VEH_TRAIN)); dst != nullptr; dst = dst->HashTileNext()) {
if (dst->IsFreeWagon() && !(dst->vehstatus & VS_CRASHED) && dst->owner == src->owner) {
/* check so all vehicles in the line have the same engine. */ /* check so all vehicles in the line have the same engine. */
Train *t = dst; Train *t = dst;
while (t->engine_type == eng) { while (t->engine_type == eng) {
t = t->Next(); t = t->Next();
if (t == nullptr) return dst; if (t == nullptr) {
candidates.push_back(dst);
break;
}
} }
} }
} }
return nullptr; if (candidates.empty()) return nullptr;
return *std::min_element(candidates.begin(), candidates.end(), [&](const Train *a, const Train *b) {
return a->index < b->index;
});
} }
/** Helper type for lists/vectors of trains */ /** Helper type for lists/vectors of trains */

View File

@ -36,8 +36,8 @@ void CcBuildWagon(const CommandCost &result, TileIndex tile, uint32_t p1, uint32
/* find a locomotive in the depot. */ /* find a locomotive in the depot. */
const Vehicle *found = nullptr; const Vehicle *found = nullptr;
for (const Train *t : Train::IterateFrontOnly()) { for (const Train *t = Train::From(GetFirstVehicleOnPos(tile, VEH_TRAIN)); t != nullptr; t = t->HashTileNext()) {
if (t->IsFrontEngine() && t->tile == tile && t->IsStoppedInDepot() && !t->IsVirtual()) { if (t->IsFrontEngine() && t->IsStoppedInDepot()) {
if (found != nullptr) return; // must be exactly one. if (found != nullptr) return; // must be exactly one.
found = t; found = t;
} }