Improve train speed adaptation with realistic braking
Take into account recorded speeds at signals along the reservation As noted in the lookahead See: #613
This commit is contained in:
44
src/pbs.cpp
44
src/pbs.cpp
@@ -14,6 +14,7 @@
|
|||||||
#include "pathfinder/follow_track.hpp"
|
#include "pathfinder/follow_track.hpp"
|
||||||
#include "tracerestrict.h"
|
#include "tracerestrict.h"
|
||||||
#include "newgrf_newsignals.h"
|
#include "newgrf_newsignals.h"
|
||||||
|
#include "train_speed_adaptation.h"
|
||||||
|
|
||||||
#include "safeguards.h"
|
#include "safeguards.h"
|
||||||
|
|
||||||
@@ -408,6 +409,14 @@ static uint16 GetTrainSpeedLimitForRailtype(const Train *v, RailType rt, TileInd
|
|||||||
return speed;
|
return speed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void AddSignalToLookAhead(const Train *v, TrainReservationLookAhead *lookahead, uint16 signal_speed, uint16 signal_flags, TileIndex signal_tile, uint16 signal_track, int offset, int16 z_pos)
|
||||||
|
{
|
||||||
|
lookahead->AddSignal(signal_speed, offset, z_pos, signal_flags);
|
||||||
|
if (_settings_game.vehicle.train_speed_adaptation) {
|
||||||
|
lookahead->AddSpeedAdaptation(signal_tile, signal_track, offset, z_pos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** Follow a reservation starting from a specific tile to the end. */
|
/** Follow a reservation starting from a specific tile to the end. */
|
||||||
static PBSTileInfo FollowReservation(Owner o, RailTypes rts, TileIndex tile, Trackdir trackdir, FollowReservationFlags flags, const Train *v, TrainReservationLookAhead *lookahead)
|
static PBSTileInfo FollowReservation(Owner o, RailTypes rts, TileIndex tile, Trackdir trackdir, FollowReservationFlags flags, const Train *v, TrainReservationLookAhead *lookahead)
|
||||||
{
|
{
|
||||||
@@ -589,7 +598,7 @@ static PBSTileInfo FollowReservation(Owner o, RailTypes rts, TileIndex tile, Tra
|
|||||||
const uint16 signal_flags = GetTunnelBridgeSignalStyle(tile) << 8;
|
const uint16 signal_flags = GetTunnelBridgeSignalStyle(tile) << 8;
|
||||||
|
|
||||||
/* Entrance signal */
|
/* Entrance signal */
|
||||||
lookahead->AddSignal(signal_speed, 0, z, signal_flags);
|
AddSignalToLookAhead(v, lookahead, signal_speed, signal_flags, tile, TrackdirToTrack(trackdir), 0, z);
|
||||||
|
|
||||||
update_z(tile, trackdir, false);
|
update_z(tile, trackdir, false);
|
||||||
|
|
||||||
@@ -603,7 +612,8 @@ static PBSTileInfo FollowReservation(Owner o, RailTypes rts, TileIndex tile, Tra
|
|||||||
int offset = start_offset - TILE_SIZE;
|
int offset = start_offset - TILE_SIZE;
|
||||||
for (int i = 0; i < signals; i++) {
|
for (int i = 0; i < signals; i++) {
|
||||||
offset += TILE_SIZE * spacing;
|
offset += TILE_SIZE * spacing;
|
||||||
lookahead->AddSignal(signal_speed, offset, chunnel ? LookaheadTileHeightForChunnel(length, i * spacing) : z, signal_flags);
|
const int signal_z = chunnel ? LookaheadTileHeightForChunnel(length, i * spacing) : z;
|
||||||
|
AddSignalToLookAhead(v, lookahead, signal_speed, signal_flags, tile, 0x100 + i, offset, signal_z);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Exit signal */
|
/* Exit signal */
|
||||||
@@ -617,7 +627,7 @@ static PBSTileInfo FollowReservation(Owner o, RailTypes rts, TileIndex tile, Tra
|
|||||||
if (signal_speed == 0 || (bridge_speed != 0 && bridge_speed < signal_speed)) signal_speed = bridge_speed;
|
if (signal_speed == 0 || (bridge_speed != 0 && bridge_speed < signal_speed)) signal_speed = bridge_speed;
|
||||||
}
|
}
|
||||||
|
|
||||||
lookahead->AddSignal(signal_speed, end_offset, z, signal_flags);
|
AddSignalToLookAhead(v, lookahead, signal_speed, signal_flags, end, FindFirstTrack(GetAcrossTunnelBridgeTrackBits(end)), end_offset, z);
|
||||||
|
|
||||||
lookahead->SetNextExtendPositionIfUnset();
|
lookahead->SetNextExtendPositionIfUnset();
|
||||||
} else {
|
} else {
|
||||||
@@ -672,7 +682,7 @@ static PBSTileInfo FollowReservation(Owner o, RailTypes rts, TileIndex tile, Tra
|
|||||||
SetBit(signal_flags, TRSLAI_COMBINED);
|
SetBit(signal_flags, TRSLAI_COMBINED);
|
||||||
UpdateLookaheadCombinedNormalShuntSignalDeferred(tile, trackdir, lookahead->RealEndPosition());
|
UpdateLookaheadCombinedNormalShuntSignalDeferred(tile, trackdir, lookahead->RealEndPosition());
|
||||||
}
|
}
|
||||||
lookahead->AddSignal(signal_speed, 0, z, signal_flags);
|
AddSignalToLookAhead(v, lookahead, signal_speed, signal_flags, tile, TrackdirToTrack(trackdir), 0, z);
|
||||||
lookahead->SetNextExtendPositionIfUnset();
|
lookahead->SetNextExtendPositionIfUnset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1073,7 +1083,8 @@ void TryCreateLookAheadForTrainInTunnelBridge(Train *t)
|
|||||||
int offset = -(int)TILE_SIZE;
|
int offset = -(int)TILE_SIZE;
|
||||||
for (int i = 0; i < signals; i++) {
|
for (int i = 0; i < signals; i++) {
|
||||||
offset += TILE_SIZE * spacing;
|
offset += TILE_SIZE * spacing;
|
||||||
t->lookahead->AddSignal(signal_speed, offset, HasBit(t->lookahead->flags, TRLF_CHUNNEL) ? LookaheadTileHeightForChunnel(length, i * spacing) : z, signal_flags);
|
const int signal_z = HasBit(t->lookahead->flags, TRLF_CHUNNEL) ? LookaheadTileHeightForChunnel(length, i * spacing) : z;
|
||||||
|
AddSignalToLookAhead(t, t->lookahead.get(), signal_speed, signal_flags, t->tile, 0x100 + i, offset, signal_z);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Exit signal */
|
/* Exit signal */
|
||||||
@@ -1086,7 +1097,7 @@ void TryCreateLookAheadForTrainInTunnelBridge(Train *t)
|
|||||||
if (signal_speed == 0 || (bridge_speed != 0 && bridge_speed < signal_speed)) signal_speed = bridge_speed;
|
if (signal_speed == 0 || (bridge_speed != 0 && bridge_speed < signal_speed)) signal_speed = bridge_speed;
|
||||||
}
|
}
|
||||||
|
|
||||||
t->lookahead->AddSignal(signal_speed, end_offset, z, signal_flags);
|
AddSignalToLookAhead(t, t->lookahead.get(), signal_speed, signal_flags, end, FindFirstTrack(GetAcrossTunnelBridgeTrackBits(end)), end_offset, z);
|
||||||
|
|
||||||
t->lookahead->SetNextExtendPositionIfUnset();
|
t->lookahead->SetNextExtendPositionIfUnset();
|
||||||
}
|
}
|
||||||
@@ -1174,6 +1185,8 @@ void FillTrainReservationLookAhead(Train *v)
|
|||||||
if (v->lookahead == nullptr) return;
|
if (v->lookahead == nullptr) return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int32 old_reservation_end_position = 0;
|
||||||
|
|
||||||
if (v->lookahead == nullptr) {
|
if (v->lookahead == nullptr) {
|
||||||
v->lookahead.reset(new TrainReservationLookAhead());
|
v->lookahead.reset(new TrainReservationLookAhead());
|
||||||
v->lookahead->current_position = 0;
|
v->lookahead->current_position = 0;
|
||||||
@@ -1205,6 +1218,7 @@ void FillTrainReservationLookAhead(Train *v)
|
|||||||
v->lookahead->reservation_end_position += station_offset_tiles * TILE_SIZE;
|
v->lookahead->reservation_end_position += station_offset_tiles * TILE_SIZE;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
old_reservation_end_position = v->lookahead->reservation_end_position;
|
||||||
tile = v->lookahead->reservation_end_tile;
|
tile = v->lookahead->reservation_end_tile;
|
||||||
trackdir = v->lookahead->reservation_end_trackdir;
|
trackdir = v->lookahead->reservation_end_trackdir;
|
||||||
if (IsTunnelBridgeSignalSimulationEntranceTile(tile) && TrackdirEntersTunnelBridge(tile, trackdir)) {
|
if (IsTunnelBridgeSignalSimulationEntranceTile(tile) && TrackdirEntersTunnelBridge(tile, trackdir)) {
|
||||||
@@ -1263,6 +1277,24 @@ void FillTrainReservationLookAhead(Train *v)
|
|||||||
|
|
||||||
FlushDeferredDetermineCombineNormalShuntMode(v);
|
FlushDeferredDetermineCombineNormalShuntMode(v);
|
||||||
SetTrainReservationLookaheadEnd(v);
|
SetTrainReservationLookaheadEnd(v);
|
||||||
|
|
||||||
|
if (_settings_game.vehicle.train_speed_adaptation && v->signal_speed_restriction > 0 && v->lookahead->reservation_end_position > old_reservation_end_position) {
|
||||||
|
for (const TrainReservationLookAheadItem &item : v->lookahead->items) {
|
||||||
|
if (item.type == TRLIT_SPEED_ADAPTATION && item.end + 1 >= old_reservation_end_position && item.end + 1 < v->lookahead->reservation_end_position) {
|
||||||
|
uint16 signal_speed = GetLowestSpeedTrainAdaptationSpeedAtSignal(item.data_id, item.data_aux);
|
||||||
|
|
||||||
|
if (signal_speed == 0) {
|
||||||
|
/* unrestricted signal ahead, remove current speed adaptation */
|
||||||
|
v->signal_speed_restriction = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (signal_speed > v->signal_speed_restriction) {
|
||||||
|
/* signal ahead with higher speed, increase current speed adaptation */
|
||||||
|
v->signal_speed_restriction = signal_speed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
11
src/pbs.h
11
src/pbs.h
@@ -57,6 +57,7 @@ enum TrainReservationLookAheadItemType : byte {
|
|||||||
TRLIT_SPEED_RESTRICTION = 3, ///< Speed restriction
|
TRLIT_SPEED_RESTRICTION = 3, ///< Speed restriction
|
||||||
TRLIT_SIGNAL = 4, ///< Signal
|
TRLIT_SIGNAL = 4, ///< Signal
|
||||||
TRLIT_CURVE_SPEED = 5, ///< Curve speed limit
|
TRLIT_CURVE_SPEED = 5, ///< Curve speed limit
|
||||||
|
TRLIT_SPEED_ADAPTATION = 6, ///< Train speed adaptation ahead
|
||||||
};
|
};
|
||||||
|
|
||||||
enum TrainReservationSignalLookAheadItemFlags {
|
enum TrainReservationSignalLookAheadItemFlags {
|
||||||
@@ -70,9 +71,11 @@ struct TrainReservationLookAheadItem {
|
|||||||
int32 start;
|
int32 start;
|
||||||
int32 end;
|
int32 end;
|
||||||
int16 z_pos;
|
int16 z_pos;
|
||||||
uint16 data_id;
|
/* gap: 2 bytes */
|
||||||
|
uint32 data_id;
|
||||||
uint16 data_aux;
|
uint16 data_aux;
|
||||||
TrainReservationLookAheadItemType type;
|
TrainReservationLookAheadItemType type;
|
||||||
|
/* gap: 1 byte */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TrainReservationLookAheadCurve {
|
struct TrainReservationLookAheadCurve {
|
||||||
@@ -145,6 +148,12 @@ struct TrainReservationLookAhead {
|
|||||||
this->items.push_back({ end + offset, end + offset, z_pos, target_speed, 0, TRLIT_CURVE_SPEED });
|
this->items.push_back({ end + offset, end + offset, z_pos, target_speed, 0, TRLIT_CURVE_SPEED });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AddSpeedAdaptation(TileIndex signal_tile, uint16 signal_track, int offset, int16 z_pos)
|
||||||
|
{
|
||||||
|
int end = this->RealEndPosition();
|
||||||
|
this->items.push_back({ end + offset, end + offset, z_pos, signal_tile, signal_track, TRLIT_SPEED_ADAPTATION });
|
||||||
|
}
|
||||||
|
|
||||||
void SetNextExtendPosition();
|
void SetNextExtendPosition();
|
||||||
|
|
||||||
void SetNextExtendPositionIfUnset()
|
void SetNextExtendPositionIfUnset()
|
||||||
|
@@ -157,7 +157,7 @@ const SlxiSubChunkInfo _sl_xv_sub_chunk_infos[] = {
|
|||||||
{ XSLFI_ANIMATED_TILE_EXTRA, XSCF_NULL, 1, 1, "animated_tile_extra", nullptr, nullptr, nullptr },
|
{ XSLFI_ANIMATED_TILE_EXTRA, XSCF_NULL, 1, 1, "animated_tile_extra", nullptr, nullptr, nullptr },
|
||||||
{ XSLFI_NEWGRF_INFO_EXTRA, XSCF_NULL, 1, 1, "newgrf_info_extra", nullptr, nullptr, nullptr },
|
{ XSLFI_NEWGRF_INFO_EXTRA, XSCF_NULL, 1, 1, "newgrf_info_extra", nullptr, nullptr, nullptr },
|
||||||
{ XSLFI_INDUSTRY_CARGO_ADJ, XSCF_IGNORABLE_UNKNOWN, 1, 1, "industry_cargo_adj", nullptr, nullptr, nullptr },
|
{ XSLFI_INDUSTRY_CARGO_ADJ, XSCF_IGNORABLE_UNKNOWN, 1, 1, "industry_cargo_adj", nullptr, nullptr, nullptr },
|
||||||
{ XSLFI_REALISTIC_TRAIN_BRAKING, XSCF_NULL, 9, 9, "realistic_train_braking", nullptr, nullptr, "VLKA" },
|
{ XSLFI_REALISTIC_TRAIN_BRAKING, XSCF_NULL, 10, 10, "realistic_train_braking", nullptr, nullptr, "VLKA" },
|
||||||
{ XSLFI_INFLATION_FIXED_DATES, XSCF_IGNORABLE_ALL, 1, 1, "inflation_fixed_dates", nullptr, nullptr, nullptr },
|
{ XSLFI_INFLATION_FIXED_DATES, XSCF_IGNORABLE_ALL, 1, 1, "inflation_fixed_dates", nullptr, nullptr, nullptr },
|
||||||
{ XSLFI_WATER_FLOODING, XSCF_NULL, 2, 2, "water_flooding", nullptr, nullptr, nullptr },
|
{ XSLFI_WATER_FLOODING, XSCF_NULL, 2, 2, "water_flooding", nullptr, nullptr, nullptr },
|
||||||
{ XSLFI_MORE_HOUSES, XSCF_NULL, 2, 2, "more_houses", nullptr, nullptr, nullptr },
|
{ XSLFI_MORE_HOUSES, XSCF_NULL, 2, 2, "more_houses", nullptr, nullptr, nullptr },
|
||||||
|
@@ -1513,7 +1513,8 @@ const SaveLoadTable GetVehicleLookAheadItemDescription()
|
|||||||
SLE_VAR(TrainReservationLookAheadItem, start, SLE_INT32),
|
SLE_VAR(TrainReservationLookAheadItem, start, SLE_INT32),
|
||||||
SLE_VAR(TrainReservationLookAheadItem, end, SLE_INT32),
|
SLE_VAR(TrainReservationLookAheadItem, end, SLE_INT32),
|
||||||
SLE_VAR(TrainReservationLookAheadItem, z_pos, SLE_INT16),
|
SLE_VAR(TrainReservationLookAheadItem, z_pos, SLE_INT16),
|
||||||
SLE_VAR(TrainReservationLookAheadItem, data_id, SLE_UINT16),
|
SLE_CONDVAR_X(TrainReservationLookAheadItem, data_id, SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_REALISTIC_TRAIN_BRAKING, 0, 9)),
|
||||||
|
SLE_CONDVAR_X(TrainReservationLookAheadItem, data_id, SLE_UINT32, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_REALISTIC_TRAIN_BRAKING, 10)),
|
||||||
SLE_CONDVAR_X(TrainReservationLookAheadItem, data_aux, SLE_UINT16, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_REALISTIC_TRAIN_BRAKING, 9)),
|
SLE_CONDVAR_X(TrainReservationLookAheadItem, data_aux, SLE_UINT16, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_REALISTIC_TRAIN_BRAKING, 9)),
|
||||||
SLE_VAR(TrainReservationLookAheadItem, type, SLE_UINT8),
|
SLE_VAR(TrainReservationLookAheadItem, type, SLE_UINT8),
|
||||||
};
|
};
|
||||||
|
@@ -401,6 +401,15 @@ class NIHVehicle : public NIHelper {
|
|||||||
if (_settings_game.vehicle.train_acceleration_model != AM_ORIGINAL) print_braking_speed(item.start, item.data_id, item.z_pos);
|
if (_settings_game.vehicle.train_acceleration_model != AM_ORIGINAL) print_braking_speed(item.start, item.data_id, item.z_pos);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
case TRLIT_SPEED_ADAPTATION: {
|
||||||
|
TileIndex tile = item.data_id;
|
||||||
|
uint16 td = item.data_aux;
|
||||||
|
b += seprintf(b, lastof(buffer), "speed adaptation: tile: %X, trackdir: %X", tile, td);
|
||||||
|
if (item.end + 1 < l.reservation_end_position) {
|
||||||
|
b += seprintf(b, lastof(buffer), " --> %u", GetLowestSpeedTrainAdaptationSpeedAtSignal(tile, td));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
output.print(buffer);
|
output.print(buffer);
|
||||||
}
|
}
|
||||||
@@ -1411,17 +1420,17 @@ class NIHSignals : public NIHelper {
|
|||||||
DumpTunnelBridgeSignalsInfo(buffer, lastof(buffer), index, output);
|
DumpTunnelBridgeSignalsInfo(buffer, lastof(buffer), index, output);
|
||||||
}
|
}
|
||||||
if (_settings_game.vehicle.train_speed_adaptation) {
|
if (_settings_game.vehicle.train_speed_adaptation) {
|
||||||
for (const auto &it : _signal_speeds) {
|
SignalSpeedKey speed_key = { index, 0, (Trackdir)0 };
|
||||||
if (it.first.signal_tile == index) {
|
for (auto iter = _signal_speeds.lower_bound(speed_key); iter != _signal_speeds.end() && iter->first.signal_tile == index; ++iter) {
|
||||||
char *b = buffer + seprintf(buffer, lastof(buffer), "Speed adaptation: Track: %X, last dir: %X --> speed: %u",
|
const auto &it = *iter;
|
||||||
it.first.signal_track, it.first.last_passing_train_dir, it.second.train_speed);
|
char *b = buffer + seprintf(buffer, lastof(buffer), "Speed adaptation: Track: %X, last dir: %X --> speed: %u",
|
||||||
if (it.second.IsOutOfDate()) {
|
it.first.signal_track, it.first.last_passing_train_dir, it.second.train_speed);
|
||||||
b += seprintf(b, lastof(buffer), ", expired");
|
if (it.second.IsOutOfDate()) {
|
||||||
} else {
|
b += seprintf(b, lastof(buffer), ", expired");
|
||||||
b += seprintf(b, lastof(buffer), ", expires in %u ticks", (uint)(it.second.time_stamp - _scaled_date_ticks));
|
} else {
|
||||||
}
|
b += seprintf(b, lastof(buffer), ", expires in %u ticks", (uint)(it.second.time_stamp - _scaled_date_ticks));
|
||||||
output.print(buffer);
|
|
||||||
}
|
}
|
||||||
|
output.print(buffer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -81,7 +81,7 @@ enum ChooseTrainTrackFlags {
|
|||||||
};
|
};
|
||||||
DECLARE_ENUM_AS_BIT_SET(ChooseTrainTrackFlags)
|
DECLARE_ENUM_AS_BIT_SET(ChooseTrainTrackFlags)
|
||||||
|
|
||||||
std::unordered_map<SignalSpeedKey, SignalSpeedValue, SignalSpeedKeyHashFunc> _signal_speeds(1 << 16);
|
btree::btree_map<SignalSpeedKey, SignalSpeedValue> _signal_speeds;
|
||||||
|
|
||||||
static void TryLongReserveChooseTrainTrackFromReservationEnd(Train *v, bool no_reserve_vehicle_tile = false);
|
static void TryLongReserveChooseTrainTrackFromReservationEnd(Train *v, bool no_reserve_vehicle_tile = false);
|
||||||
static Track ChooseTrainTrack(Train *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks, ChooseTrainTrackFlags flags, bool *p_got_reservation, ChooseTrainTrackLookAheadState lookahead_state = {});
|
static Track ChooseTrainTrack(Train *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks, ChooseTrainTrackFlags flags, bool *p_got_reservation, ChooseTrainTrackLookAheadState lookahead_state = {});
|
||||||
@@ -966,6 +966,9 @@ static void ApplyLookAheadItem(const Train *v, const TrainReservationLookAheadIt
|
|||||||
case TRLIT_CURVE_SPEED:
|
case TRLIT_CURVE_SPEED:
|
||||||
if (_settings_game.vehicle.train_acceleration_model != AM_ORIGINAL) limit_speed(item.start, item.data_id, item.z_pos);
|
if (_settings_game.vehicle.train_acceleration_model != AM_ORIGINAL) limit_speed(item.start, item.data_id, item.z_pos);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case TRLIT_SPEED_ADAPTATION:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -7566,27 +7569,70 @@ void SetSignalTrainAdaptationSpeed(const Train *v, TileIndex tile, uint16 track)
|
|||||||
_signal_speeds[speed_key] = speed_value;
|
_signal_speeds[speed_key] = speed_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ApplySignalTrainAdaptationSpeed(Train *v, TileIndex tile, uint16 track)
|
static uint16 GetTrainAdaptationSpeed(TileIndex tile, uint16 track, Trackdir last_passing_train_dir)
|
||||||
{
|
{
|
||||||
SignalSpeedKey speed_key = {
|
SignalSpeedKey speed_key = {
|
||||||
speed_key.signal_tile = tile,
|
speed_key.signal_tile = tile,
|
||||||
speed_key.signal_track = track,
|
speed_key.signal_track = track,
|
||||||
speed_key.last_passing_train_dir = v->GetVehicleTrackdir()
|
speed_key.last_passing_train_dir = last_passing_train_dir
|
||||||
};
|
};
|
||||||
const auto found_speed_restriction = _signal_speeds.find(speed_key);
|
const auto found_speed_restriction = _signal_speeds.find(speed_key);
|
||||||
|
|
||||||
if (found_speed_restriction != _signal_speeds.end()) {
|
if (found_speed_restriction != _signal_speeds.end()) {
|
||||||
if (found_speed_restriction->second.IsOutOfDate()) {
|
if (found_speed_restriction->second.IsOutOfDate()) {
|
||||||
_signal_speeds.erase(found_speed_restriction);
|
_signal_speeds.erase(found_speed_restriction);
|
||||||
v->signal_speed_restriction = 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
v->signal_speed_restriction = std::max<uint16>(25, found_speed_restriction->second.train_speed);
|
return std::max<uint16>(25, found_speed_restriction->second.train_speed);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
v->signal_speed_restriction = 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ApplySignalTrainAdaptationSpeed(Train *v, TileIndex tile, uint16 track)
|
||||||
|
{
|
||||||
|
uint16 speed = GetTrainAdaptationSpeed(tile, track, v->GetVehicleTrackdir());
|
||||||
|
|
||||||
|
if (speed > 0 && v->lookahead != nullptr) {
|
||||||
|
for (const TrainReservationLookAheadItem &item : v->lookahead->items) {
|
||||||
|
if (item.type == TRLIT_SPEED_ADAPTATION && item.end + 1 < v->lookahead->reservation_end_position) {
|
||||||
|
uint16 signal_speed = GetLowestSpeedTrainAdaptationSpeedAtSignal(item.data_id, item.data_aux);
|
||||||
|
|
||||||
|
if (signal_speed == 0) {
|
||||||
|
/* unrestricted signal ahead, disregard speed adaptation at earlier signal */
|
||||||
|
v->signal_speed_restriction = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (signal_speed > speed) {
|
||||||
|
/* signal ahead with higher speed adaptation speed, override speed adaptation at earlier signal */
|
||||||
|
speed = signal_speed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
v->signal_speed_restriction = speed;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16 GetLowestSpeedTrainAdaptationSpeedAtSignal(TileIndex tile, uint16 track)
|
||||||
|
{
|
||||||
|
uint16 lowest_speed = 0;
|
||||||
|
|
||||||
|
SignalSpeedKey speed_key = { tile, track, (Trackdir)0 };
|
||||||
|
for (auto iter = _signal_speeds.lower_bound(speed_key); iter != _signal_speeds.end() && iter->first.signal_tile == tile && iter->first.signal_track == track;) {
|
||||||
|
if (iter->second.IsOutOfDate()) {
|
||||||
|
iter = _signal_speeds.erase(iter);
|
||||||
|
} else {
|
||||||
|
uint16 adapt_speed = std::max<uint16>(25, iter->second.train_speed);
|
||||||
|
if (lowest_speed == 0 || adapt_speed < lowest_speed) lowest_speed = adapt_speed;
|
||||||
|
++iter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return lowest_speed;
|
||||||
|
}
|
||||||
|
|
||||||
uint16 Train::GetMaxWeight() const
|
uint16 Train::GetMaxWeight() const
|
||||||
{
|
{
|
||||||
uint16 weight = CargoSpec::Get(this->cargo_type)->WeightOfNUnitsInTrain(this->GetEngine()->DetermineCapacity(this));
|
uint16 weight = CargoSpec::Get(this->cargo_type)->WeightOfNUnitsInTrain(this->GetEngine()->DetermineCapacity(this));
|
||||||
|
@@ -14,8 +14,7 @@
|
|||||||
#include "date_func.h"
|
#include "date_func.h"
|
||||||
#include "track_type.h"
|
#include "track_type.h"
|
||||||
#include "tile_type.h"
|
#include "tile_type.h"
|
||||||
|
#include "3rdparty/cpp-btree/btree_map.h"
|
||||||
#include <unordered_map>
|
|
||||||
|
|
||||||
struct SignalSpeedKey {
|
struct SignalSpeedKey {
|
||||||
TileIndex signal_tile;
|
TileIndex signal_tile;
|
||||||
@@ -28,6 +27,11 @@ struct SignalSpeedKey {
|
|||||||
signal_track == other.signal_track &&
|
signal_track == other.signal_track &&
|
||||||
last_passing_train_dir == other.last_passing_train_dir;
|
last_passing_train_dir == other.last_passing_train_dir;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool operator<(const SignalSpeedKey& other) const
|
||||||
|
{
|
||||||
|
return std::tie(this->signal_tile, this->signal_track, this->last_passing_train_dir) < std::tie(other.signal_tile, other.signal_track, other.last_passing_train_dir);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SignalSpeedValue {
|
struct SignalSpeedValue {
|
||||||
@@ -41,21 +45,11 @@ struct SignalSpeedValue {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SignalSpeedKeyHashFunc {
|
extern btree::btree_map<SignalSpeedKey, SignalSpeedValue> _signal_speeds;
|
||||||
std::size_t operator() (const SignalSpeedKey &key) const
|
|
||||||
{
|
|
||||||
const std::size_t h1 = std::hash<TileIndex>()(key.signal_tile);
|
|
||||||
const std::size_t h2 = std::hash<Trackdir>()(key.last_passing_train_dir);
|
|
||||||
const std::size_t h3 = std::hash<uint16>()(key.signal_track);
|
|
||||||
|
|
||||||
return (h1 ^ h2) ^ h3;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
extern std::unordered_map<SignalSpeedKey, SignalSpeedValue, SignalSpeedKeyHashFunc> _signal_speeds;
|
|
||||||
|
|
||||||
struct Train;
|
struct Train;
|
||||||
void SetSignalTrainAdaptationSpeed(const Train *v, TileIndex tile, uint16 track);
|
void SetSignalTrainAdaptationSpeed(const Train *v, TileIndex tile, uint16 track);
|
||||||
void ApplySignalTrainAdaptationSpeed(Train *v, TileIndex tile, uint16 track);
|
void ApplySignalTrainAdaptationSpeed(Train *v, TileIndex tile, uint16 track);
|
||||||
|
uint16 GetLowestSpeedTrainAdaptationSpeedAtSignal(TileIndex tile, uint16 track);
|
||||||
|
|
||||||
#endif /* TRAIN_SPEED_ADAPTATION_H */
|
#endif /* TRAIN_SPEED_ADAPTATION_H */
|
||||||
|
Reference in New Issue
Block a user