Simutrans Tools

## Schedule features: technical discussion

Started by jamespetts, January 22, 2018, 11:15:36 PM

0 Members and 1 Guest are viewing this topic.

#### Ranran

#140

QuoteThe logic for this is not written yet, but all the parameters are present. The logic will be that convoys will have to make a range stop every time that the distance to the next stop would exceed the distance specified in the last range parameter since the last range stop or last leaving the depot. For example, if a convoy had a range of 100km, and stops at 40km apart, the first stop after leaving the depot would be 40km from the last range stop or depot visit. The second stop would be 80km away, so the first stop would not need to be a range stop. The third stop, however, would be 140km away from the last depot visit or range stop, so the second stop would need to be a range stop. The third stop would then be 40km from the last range stop; the fourth stop would thus be 80km from the last range stop, so the third stop would not need to be a range stop, and so forth.
Are there parameters as if the station had refueling equipment?

QuoteThat is a nice idea. I wonder whether, instead of the green arrow symbol, it might be clearer to join the two lines in a loop after the first and last stops?
I find it difficult to draw. Drawing beyond table cells is tedious. simutrans is difficult to draw beautiful and thick curves. It's easy to draw a rough straight line. Display area problems with station name display, etc.

QuoteI cannot see an example of this in the displays above; but I wonder whether there might be a clearer way of designating a depot than a square; perhaps a square with an oversized triangle on top of it representing a gabled roof to depict a depot building?
The first design was at number one in the second image of reply # 126, but the design has changed as you suggested.

Anyway, due to the 2021 year, the schedule UI has transformed (hentai). (´・ω・｀)
Feel the essence of Jarápagos.

A big suggestion for changing the seasoning is to split the layout left and right.
I think this is necessary due to previous visual changes. The schedule list tends to be longer than before, so it's more convenient to have a more comprehensive view.
And the option buttons were crowded due to the large number of options. Group this into a vertical list.

QuoteOne thing that might be even better - although not a high priority - is a graphical difference between stops at which only convoys of this line (or only this convoy, if it does not belong to a line) stop and stops at which other lines/lineless convoys stop. This is common on maps of metro networks around the world. One might use a circle with a number to represent a non-interchange stop and a square with a number to represent an interchange stop.
For example, I think it is difficult to write a number in a circle to display a three-digit number. If you try to put a number in a circle, the height of the line will increase. Therefore I propose a distinction as shown in the picture above.
The stop with a white background is the interchange station.

QuoteI am not sure that this is the clearest way of representing this, as this looks as though it is giving general information - I wonder whether a set of diverging arrows with a red cross through it may be more suitable?
This can now be defined as:
`Obj=symbolname=IgnoreChoose`
But I haven't made a symbol. If the pakset does not have a symbol, the information symbol will be displayed as above.

QuoteIf send and receive  are already indicated by the triangle direction and color, the '+' and '-' indicators are probably redundant. They might also be confusing, since '+3' indicates trigger no. 3 rather than 3 triggers.
It was changed like this. It's good to save space.

(18) set down only;
(19) pick up only;

(0) flags, as above (32-bit);
I have added these parameters for testing the dialog.

Quote(7) maximum speed (32-bit).
But unfortunately this couldn't be implemented correctly so I didn't add it.
Therefore the speed limit input is currently dummy.
In my plan, if you set a number there, you will see a speed limit label in the space opposite the distance.

As a new feature,
(1) an electrical mark will be displayed if the line or convoy needs electrification.

(2) If the convoy or line has a convoy with a range limit, the range limit is displayed.
And if you stupidly set a schedule longer than that range limit, the distance display will turn red.
For example, in the image above, you are scolded by the schedule dialog because you are set to travel a distance of 31.1km even though you are using a horse with a 20km limit.
(At the moment it is checking the distance between two points, but this is expected to be improved to check between stations.)

EDIT:
The arrows for wait_for_trigger and broadcast_trigger were in opposite directions. It will be fixed.

EDIT2:
The schedule setting status is not reflected immediately except for the change of minimum load. I'm stuck on how to fix this.

memorandum:
- I thought about removing the entry by abolishing the remove button and putting a garbage button on each entry and clicking it, but it seems difficult to implement.
Placing the button there seemed complicated. The standard has a posbutton in the entry, but this was actually a fake image rather than a button.

- I noticed that there was an issue lying in the current travel distance logic. That is, there is a contradiction between the schedule display and the calculation.
The travel distance is calculated as a straight line distance, that is, the shortest distance. If you set a waypoint in the middle, the total value on the display will not be the shortest value, which is inconsistent with the value calculated by the player in his head.

EDIT2:
It was brushed up.

One problem with discharge is the combination with mirror schedule. For example, if you want to limit the speed to the next station, the mirror schedule will work correctly by referring to the speed limit of the previous station. But what about discharge?
This also makes it difficult to get the correct behavior that freddy said above. It is probably not recommended to use the mirror schedule in that case.

Ambition, I wonder if we can make something like this. This will give you a more modern game look.

#### jamespetts

My apologies for not having replied to this for a while: this is a rather large topic, and I have been preoccupied with other things of late; since I am still working from home, I have been preferring to spend my evenings doing something other than working on a computer in order to have some variety, so have been focussing on my model railway of late. This is still a worthwhile project, however, so I hope that you will forgive the delayed response.

Quote from: Ranran on January 04, 2021, 03:15:20 PM

Are there parameters as if the station had refueling equipment?

I do not think that any requirement for stations to have refuelling equipment has yet been encoded. I am not sure how significant that this would be in economic simulation; what would it have cost in reality to have a pile of coal at a station? Also, nearly every airport has refuelling facilities, so it would make little sense to have the ability to build an airport in game without this. It would require significant extra balancing and possibly significant extra work in producing graphics. However, if we decide that this is important in the future, it should in principle not be hard to add this.

Quote
I find it difficult to draw. Drawing beyond table cells is tedious. simutrans is difficult to draw beautiful and thick curves. It's easy to draw a rough straight line. Display area problems with station name display, etc.

That is understandable; do not worry if this is too hard to implement.

QuoteThe first design was at number one in the second image of reply # 126, but the design has changed as you suggested.

Excellent, thank you.

Quote
Anyway, due to the 2021 year, the schedule UI has transformed (hentai). (´・ω・｀)
Feel the essence of Jarápagos.

A big suggestion for changing the seasoning is to split the layout left and right.
I think this is necessary due to previous visual changes. The schedule list tends to be longer than before, so it's more convenient to have a more comprehensive view.

And the option buttons were crowded due to the large number of options. Group this into a vertical list.

That does look good, and makes it nice and easy to understand. Excellent!

Quote
For example, I think it is difficult to write a number in a circle to display a three-digit number. If you try to put a number in a circle, the height of the line will increase. Therefore I propose a distinction as shown in the picture above.

The stop with a white background is the interchange station.

Yes, I can see the advantage of doing it that way. That does look good.

Quote
This can now be defined as:
`Obj=symbolname=IgnoreChoose`
But I haven't made a symbol. If the pakset does not have a symbol, the information symbol will be displayed as above.

Thank you for clarifying - we should probably have a custom symbol at some point, since the "i" symbol is potentially confusing in this context, but it is a reasonable fallback where we do not have a symbol defined.

Quote
It was changed like this. It's good to save space.

Excellent, thank you.

Quote
I have added these parameters for testing the dialog.

But unfortunately this couldn't be implemented correctly so I didn't add it.
Therefore the speed limit input is currently dummy.

In my plan, if you set a number there, you will see a speed limit label in the space opposite the distance.

QuoteAs a new feature,
(1) an electrical mark will be displayed if the line or convoy needs electrification.

This is very useful indeed!

Quote
(2) If the convoy or line has a convoy with a range limit, the range limit is displayed.
And if you stupidly set a schedule longer than that range limit, the distance display will turn red.
For example, in the image above, you are scolded by the schedule dialog because you are set to travel a distance of 31.1km even though you are using a horse with a 20km limit.
(At the moment it is checking the distance between two points, but this is expected to be improved to check between stations.)

This is also very useful and will make players' lives much easier - thank you.

Quote
EDIT:
The arrows for wait_for_trigger and broadcast_trigger were in opposite directions. It will be fixed.

EDIT2:
The schedule setting status is not reflected immediately except for the change of minimum load. I'm stuck on how to fix this.

Do you mean that the underlying data does not update until the dialogue box is closed?

Quote
memorandum:
- I thought about removing the entry by abolishing the remove button and putting a garbage button on each entry and clicking it, but it seems difficult to implement.
Placing the button there seemed complicated. The standard has a posbutton in the entry, but this was actually a fake image rather than a button.

This would be a nice feature to have, but do not worry if this is too much work.

Quote
- I noticed that there was an issue lying in the current travel distance logic. That is, there is a contradiction between the schedule display and the calculation.
The travel distance is calculated as a straight line distance, that is, the shortest distance. If you set a waypoint in the middle, the total value on the display will not be the shortest value, which is inconsistent with the value calculated by the player in his head.

Can I clarify - is this an error in your code or in the code already existing in Simutrans-Extended?

Quote
EDIT2:
It was brushed up.

Interesting! That looks splendid. May I ask what the orange highlighting on the line represents?

Quote

One problem with discharge is the combination with mirror schedule. For example, if you want to limit the speed to the next station, the mirror schedule will work correctly by referring to the speed limit of the previous station. But what about discharge?
This also makes it difficult to get the correct behavior that freddy said above. It is probably not recommended to use the mirror schedule in that case.

This is an interesting thought. I wonder whether mirror schedule ought to work in a special way in conjunction with discharge and do the opposite thing if the convoy is in its reverse direction?

Quote
Ambition, I wonder if we can make something like this. This will give you a more modern game look.

Interesting - is this intended for the display when adding items to a schedule or viewing a schedule? If so, that would be very useful indeed.

Want to help with development? See here for things to do for coding, and here for information on how to make graphics/objects.

QuoteI do not think that any requirement for stations to have refuelling equipment has yet been encoded. I am not sure how significant that this would be in economic simulation; what would it have cost in reality to have a pile of coal at a station?

A pile of coal is indeed not a big deal. But a water tower is. Also a gas/petrol station is definitely not on every bus stop. Compare refueling facilities to the cheapest stop, not to a big station. Airports without refueling exist in remote places, where the only way to bring fuel is by plane.

#### Sirius

#143
Quote from: jamespetts on April 02, 2021, 01:19:11 PMI do not think that any requirement for stations to have refuelling equipment has yet been encoded. I am not sure how significant that this would be in economic simulation; what would it have cost in reality to have a pile of coal at a station?

In the real-world it's not as simple as piling up some coal at the station.
You need special infrastructure to load the coal as swell as infrastructure to refuel water.
The same goes for Diesel, Hydrogen or any other kind of fuel. Even for electricity in case of battery vehicles.

I like the very last image. It really gives a more modern look at the map.
I'd really love to see the route itself to be painted on the map. I am aware that this route might depend on the actual vehicle on the line, so we could use the very first vehicle of the line to calculate the route and a dummy when there is no vehicle assigned yet.

As this thread is all about schedules, I'd like to throw in a consieration about timed schedules aka timetables:
In the real-world, routes are scheduled with a fixed waiting time in stations and a fixed journey time between these.
The scheduled time should usually be longer than the time it actually takes to wait at a station or to travel in between stations at full speed.
Once the scheduled time is shorter, we have a delay, in which case the train might exceed the scheduled speed or spend les time in a station time to catch up.
In simutrans, we cannot handle delays at all. Either we don't schedule a stop at all (depart when ready) or we schedule it to depart at a fixed time, in which case we will wait for the next time slot as soon as we are delayed by only a second.

I don't want to "request" a feature to handle delays here, but the above discussed scheduling concept should at least keep this in mind.
An "is delayed" condition to allow for exceeding the scheduled maximum speed, as well as an attribute to allow for delayed departures should be enough in most cases.
Optionally, a field to enter a maximum delay at which a train may still depart.
In that case, we'll also have to consider what to do when a train is much too late (more delay than the maximum delay).
Currently, maximum delay is 0 and trains exceeding that delay will simply wait for the next schedule slot.

#### Matthew

Quote from: Freahk on April 02, 2021, 04:52:30 PM
As this thread is all about schedules, I'd like to throw in a consieration about timed schedules aka timetables:
In the real-world, routes are scheduled with a fixed waiting time in stations and a fixed journey time between these.
The scheduled time should usually be longer than the time it actually takes to wait at a station or to travel in between stations at full speed.
Once the scheduled time is shorter, we have a delay, in which case the train might exceed the scheduled speed or spend les time in a station time to catch up.
In simutrans, we cannot handle delays at all. Either we don't schedule a stop at all (depart when ready) or we schedule it to depart at a fixed time, in which case we will wait for the next time slot as soon as we are delayed by only a second.

I don't want to "request" a feature to handle delays here, but the above discussed scheduling concept should at least keep this in mind.
An "is delayed" condition to allow for exceeding the scheduled maximum speed, as well as an attribute to allow for delayed departures should be enough in most cases.
Optionally, a field to enter a maximum delay at which a train may still depart.
In that case, we'll also have to consider what to do when a train is much too late (more delay than the maximum delay).
Currently, maximum delay is 0 and trains exceeding that delay will simply wait for the next schedule slot.

Perhaps worth mentioning that OTRP has already implemented this feature.
(Signature being tested) If you enjoy playing Simutrans, then you might also enjoy watching Japan Railway Journal
Available in English and simplified Chinese

#### PJMack

I am looking forward to this feature, however there are three things that have not been mentioned.  One is that a mechanism would need to be in place to ensure that a consist does not exceed the weight restrictions of bridges.  The method of doing that would have a setting of not only the maximum weight, but the maximum weight per tile, as short bridges sometimes only need to support part of a train.

The second issue is, at the risk of sounding like a feature request, is dead toeing of locomotives and cars.  What I mean by that is in some cases, have the locomotives part of the consist but not powered on or staffed, just along for the ride; or empty passenger or dining cars en-route to the depot since they would not need staffing, meal service, or even AC or lighting.  Although this has been mentioned before, there would also be live toeing where a vehicle would not be staffed, but operated by remote control (e.g. 2 DMUs).  For the technical side, it would require in addition to layover and running states, vehicles would also have a dead toe state, live toe state, and empty toe to/from depot state.  (An additional state may could an un-catered state to close the kitchen for some shorter trips, but that would involve a feature request).  Such states would need to be specified in the consist, and the packset would need a set of vehicle costs for each state.  (One possible addition would be allowing some relaxed coupling constraints in the empty toe to/from depot state to allow new passenger cars to hitch a ride with the freight trains, but again, that would be a feature request.)

A third issue is that comes to mind is with ships and planes where the "vehicles" are actually holds and interior configurations that could not be rearranged easily at port.  A simple "ishold" flag for the "vehicles" in the packset would need to be added to ensure that such holds can only be rearranged within an actual depot.  Alternatively, if various refueling and/or small repair facilities at stations/docks are incorporated, the packset would have a variable to limit which such facilities could rearrange holds.

#### Ranran

I remember posting a bug list for this branch somewhere before, but I couldn't find it correctly.
Anyway I write a note.
When loading an old save with ver15, all convoys do not belong to line because the judgment by schedule->matches is always false in convoi_t::finish_rd().
The line information has been loaded correctly from save.
If we skip this comparison process and run line->add_convoy(self, true); with the old line, we can make convoy belong to the line correctly, but it would not be the right way. Anyway it needs to be fixed. Otherwise it will practically ruin the past save.

#### Octavius

I recently returned to simutrans-extended. Nice to see some progress, but I also found out that I may need a new computer, as I can only run the game on fairly small maps.

The thing is, in a forgotten directory on my hard drive I found an almost forgotten file with some notes concerning a way to do scheduling in simutrans-extended, some of which pretty detailed. The ideas would support at least:
- splitting trains to operate on different branches of a line and recombining on the way back;
- changing locomotive for different portions of a line;
- parking wagons, trailers or unpowered barges at a stop waiting for cargo, only to call a locomotive/tractor/pushboat when full;
- a locomotive pool providing banking service for heavy goods trains of any owner on a mountain pass;
- putting lorries on RoRo-ferries, making services to small islands much easier (and more profitable);
- trains being rerouted or cancelled on excessive delay;
- setting waiting points for goods trains, where they are scheduled to be overtaken by passenger trains;
- as a bonus, loading and unloading cargo without stopping (or needing a platform at least as long as the train). This was actually done by some travelling post offices and is still done by bulk trains.

Of course, some work has already been done on this and it wouldn't be good to undo all of it to go some different direction, but would some of you like it if I translated some of these notes and put them here? (I ask first, because I don't want to sound too pushy and it's quite a long write.)

BTW, I'm actually a decent coder, in particular in C, but my use of C++ is more incidental and I'm completely unfamiliar with the simutrans code, so working on something big like this wouldn't be my first choice.

#### jamespetts

Octavius - thank you for your thoughts and apologies for the delay in responding. I would suggest that you post your notes on this topic in a different thread, as this thread is intended to be focussed on discussing the precise implementational details of the current 15 branch, and so discussion of a different system on this thread is likely to be disruptive. However, it would be interesting to see what you had envisaged in a separate thread.

Want to help with development? See here for things to do for coding, and here for information on how to make graphics/objects.

#### jamespetts

I am beginning work on trying to merge all the latest changes from Standard into the vehicle-management-new branch. So far, I have been able to get it to compile, but I get errors loading any saved game or generating any new game, both relating to inter-city roads (although probably in different parts of the code), so it is not currently usable.

It may take a considerable time to pick through the various issues with this, as merging diverged codebases is much harder than adding new code, so any assistance (especially from those who have added any of the code that conflicted with the original vehicle-management code) would be much appreciated.

I should note that I am not quite sure of the UI status of this branch at present, as, as indicated, I have not been able to get it running beyond the loading screen because I can neither load nor generate a game.

I think that the work in this branch needs to be prioritised at this time, as vehicles that never wear out are causing notable imbalances in the current game and distorting player incentives to do tedious and unrealistic things as opposed to interesting and realistic things.

Want to help with development? See here for things to do for coding, and here for information on how to make graphics/objects.

#### jamespetts

#150
I have noticed that Ranran has produced an ex-15-2022 branch, which has merged the latest changes up to about March this year from master. I have copied this branch and created my own ex-15 branch with this version of the code. This seems to work better than the vehicle-management-new branch, in that I can now load and save games with this.

Unfortunately, attempting to merge with the master branch produces irreconcilable conflicts in the schedule GUI code which are virtually impossible for me to resolve because I know very little about how the new GUI schedule works. I wonder whether Ranran might be able to look into the merging of this part of the code?

Edit: I see that Ranran had already implemented a sophisticated alternative GUI for the schedule in the ex-15-2022 branch. Unfortunatelly, trying to merge this by simply ignoring the changes on the master branch and overriding this with the changes from the ex-15-2022 branch produces a compile error as follows:

`1>C:\Users\James E. Petts\Documents\Development\Simutrans\simutrans-extended-sources\gui\components\gui_aligned_container.h(120,47): error C2668: 'gui_colored_route_bar_t::gui_colored_route_bar_t': ambiguous call to overloaded function (compiling source file gui\schedule_gui.cc)1>C:\Users\James E. Petts\Documents\Development\Simutrans\simutrans-extended-sources\gui\components\gui_schedule_item.h(35,2): message : could be 'gui_colored_route_bar_t::gui_colored_route_bar_t(PIXVAL,uint8)' (compiling source file gui\schedule_gui.cc)1>C:\Users\James E. Petts\Documents\Development\Simutrans\simutrans-extended-sources\gui\components\gui_schedule_item.h(34,2): message : or       'gui_colored_route_bar_t::gui_colored_route_bar_t(uint8,uint8)' (compiling source file gui\schedule_gui.cc)1>C:\Users\James E. Petts\Documents\Development\Simutrans\simutrans-extended-sources\gui\components\gui_aligned_container.h(120,47): message : while trying to match the argument list '(const A1, const A2)'`
This message is somewhat inexplicable in the circumstances.

Want to help with development? See here for things to do for coding, and here for information on how to make graphics/objects.

#### Ranran

It's nice to see the progress of this again. I believe conflict has been resolved.

EDIT:
The new schedule marker seems to have lost its functionality.

#### jamespetts

Excellent, thank you! This does work. It is excellent to see your improved schedule UI in operation.

This is quite a long-term and large project, and I have not done major work on this since 2018, so it will take some time for me to set myself up with the work in this and see how far that I had got and what other things may need to be changed based on feedback since. It may well be that I will have to split out certain parts for a future update.

Your assistance with this is much appreciated. For new features that require new user interactions, assistance with the UI, especially of this quality, is highly valuable.

Want to help with development? See here for things to do for coding, and here for information on how to make graphics/objects.

#### jamespetts

I have been doing some implementation work on this in the last few days. All the work on this project is now in the ex-15 branch on my Github repository.

In particular, I have been adding the vehicle type data (i.e., the data specified in .dat files for vehicles and stored in game in vehicle_desc_t objects).

Here is an extract from the code, including some brief documentation by way of comments, to give an overview of what has been added:

`uint32 base_initial_overhaul_cost = 0; // Overhaul cost (without scale factor and increase for multiple overhauls)uint32 initial_overhaul_cost = 0; // Overhaul cost (before increse for multiple overhauls)uint32 base_max_overhaul_cost = 0; // Overhaul cost (without scale factor after full increase for multiple overhauls)uint32 max_overhaul_cost = 0; // Overhaul cost (after full increase for multiple overhauls)uint16 overhauls_before_max_cost = 0; // The number of overhauls before the maximum overhaul cost is reached. 0: no changeuint32 max_distance_between_overhauls = 0; // The maximum distnace in km between overhauls. 0: no overhauls requireduint32 max_takeoffs = 0; // The maximum number of takeoffs (flight cycles) between overhauls for an aircraft. 0: unlimiteduint32 availability_decay_start_km = 0; // The number of km since the last overhaul when the availability begins to decay. 0: no decayuint8 starting_availability = 100; // The percentage availablility of this vehicle when new. 100: needs no maintenanceuint8 minimum_availability = 100; // The percentage availability of this vehicle when at max_distance_between_overhauls since the last overhaul 100: needs no maintenanceuint32 calibration_speed = 0; // Used for calibrating the fuel consumption (km/h). 0 = fuel consumption does not vary with speed.// A non-zero value represents the speed (assuming accelerating or physics limited to this speed)// against which the fuel consumption per unit of distance is calibrated.uint32 cut_off_speed = 0; // The minimum speed below which fuel consumption per km does not reduce (km/h)uint32 fuel_per_km = 0; // Fuel cost calibrated according to the above. Not all powered vehicles (e.g. sailing ships) use fuel. The traction type records the fuel type.bool self_contained_catering = false; // Whether any catering provided by this vehicle is available to the whole consist or only this vehicle./*** Staff data.* Hashtable: key: staff cost type; value: number of staff for this vehicle.* Introduced for version 15*/typedef inthashtable_tpl<uint8, sint32, N_BAGS_SMALL> staff_map;staff_map drivers; // Staff who need to be present if the vehicle needs to be driven.staff_map conductors; // Staff who need to be present if the vehicle is at the rear.staff_map staff; // Staff who need to be present at all times.uint8 multiple_working_type = 0; // This determines whether multiple powered vehicles need drivers only in the first of them. If the numbers match (and are non-zero), then yes; otherwise, no.`
Note that the above code extract has been abridged to show only new data.

Once the data members are fully in place, work can start on both the logic and UI (indeed, that work can go on in parallel once the data members are in place). Ranran - if you have any questions about the intention of any of these data members for the purposes of UI implementation, please let me know.

A few notes for reference for the UI design:

* availability is a percentage;
* the intention is that only the current availability percentage should be displayed to the player (this will be calculated in vehicle_t not vehicle_desc_t);
* the intention is that only the cost for the next overhaul should be displayed to the player (this will be calculated in vehicle_t not vehicle_desc_t);
* I am not sure how best to represent the fuel economy data in the UI;
* the intention is for the fuel specified in the code to be unit agnostic, so long as the pakset authors consistently use the same units; and
* I have yet to implement the global data (the .tab files and the new simuconf.tab settings).

Want to help with development? See here for things to do for coding, and here for information on how to make graphics/objects.

#### Ranran

#154
QuoteRanran - if you have any questions about the intention of any of these data members for the purposes of UI implementation, please let me know.
How is the overhaul controlled?
(1) Specifically in relation to replacement of vehicles; is it possible to overhaul only certain vehicles and replace only certain vehicles when visiting a depot for convoy inspection(overhauling) work?
(2) Will vehicle flags such as deferring overhaul be added? (I mean, where is the overhaul postponement flag for each vehicle? Or am I misunderstanding something?) Is this some sort of replacement related data? I am not familiar with the replacing code.
(3) Is the penalty for postponing the overhaul incurred when it falls below minimum_availability?

Quote* I am not sure how best to represent the fuel economy data in the UI;
* the intention is for the fuel specified in the code to be unit agnostic, so long as the pakset authors consistently use the same units;
Distinguishing units for each fuel type can make it difficult for players to understand and track expenses.
Also, displaying variations in fuel economy based on usage conditions can be difficult to understand. In the real world, fuel economy is only indicated in catalog specifications under specific conditions.
One of the difficulties in expressing this is that, for example, the only vehicle among several vehicles that has data directly related to fuel consumption is the power vehicle. In other words, what the player wants to know is the fuel consumption of the convoy.
However, the multiple powered vehicles that the convoy has could be of different speeds and different traction types. If the fuel economy varies with external factors such as operating speed, the predicted fuel economy is too complex.

Quoteuint32 calibration_speed = 0; // Used for calibrating the fuel consumption (km/h). 0 = fuel consumption does not vary with speed.
// A non-zero value represents the speed (assuming accelerating or physics limited to this speed)
// against which the fuel consumption per unit of distance is calibrated.
uint32 cut_off_speed = 0; // The minimum speed below which fuel consumption per km does not reduce (km/h)
The reduction in fuel consumption due to reduced speed in this regard may seem somewhat odd.
For example, first prepare one locomotive. Then, imagine that freight wagons are added so that the maximum speed does not decrease. The expected event at this point is that fuel consumption will worsen with each additional freight wagon. Perhaps adding too many cars will also reduce the maximum speed. But might the system reduce fuel consumption?

Quotestaff_map conductors; // Staff who need to be present if the vehicle is at the rear.
The approach I had in mind for the placement of conductors was not that each car would have a fixed number of conductors, but that each car would have a factor regarding the "need" for a conductor.
The idea was to simulate the Japanese rail scene correctly, but also to give the player choices as a game element. In this regard, very unusually, I do not think Japan deviates from the common sense of the world.
Large vehicles such as airplanes and ships that cannot be reconfigured may have a fixed number of staff, but trains have smaller units, so the overall configuration will change the number of conductors required. In other words, the required labor costs will fluctuate. The same may be true for ships whose pak.britain configuration can be changed.
For example, in the case of Japan, even if the number of vehicles is the same, the more first-class vehicles there are, the greater the need for conductors, and multiple conductors are required. However, one conductor per car is too much. This means that unlike airplanes and ships, the unit of railway is small. In other words, it needs a conductor number of less than a decimal point, and the fraction is finally rounded up. This also makes a difference when combining multiple trains. If the need for the conductor is low, the extra conductor will be omitted when combined trains.

Simulating this correctly simulates the benefits of combining multiple convoys. Otherwise the disadvantage of the loss of time waiting for the combined convoy at the station will be emphasized.
In addition, modern trains may not need a conductor due to automatic broadcasting equipment, in-vehicle monitoring monitors, and so on. If all vehicles in the convoy have a conductor need of 0, then no conductor is placed in the convoy. However, if even one vehicle that requires a conductor is mixed in the convoy, a conductor will be assigned. The driver must always be in the cab, but I don't think the conductor's whereabouts are that important. For example, for a freight wagon without brakes in the old age, define a required conductor factor of 1. There is no need to flag the conductor's need on the brake van at its tale end. In the case of push-pull, there may not be a vehicle that defines the number of conductors at the end because the coach does not come to the end.

The following is an example based on the Japanese railway scene. (Scaling with a small number of vehicles)

My idea is that the conductor factor is 1-100 and the cost of one conductor is added. 101-200 will cost 2 conductors.
In the case of a conductor less vehicle, a conductor is not required if it consists only of it.
The comuuter train generally has less need for a conductor. For example, 10cars is enough for one person, but limited express trains are not enough. Of course, the limited express train has a smaller capacity, so it can be said that the need for a conductor is not based on the capacity alone. The more high-grade vehicles are connected, the more conductors are needed. (Safety aspect, etc.)
A dedicated attendant may be assigned to the vehicle, which will be classified as "staff".
Therefore, while high-grade vehicles earn a lot of ticket income, labor costs tend to be high. However, the difference is that fuel economy is the same if the performance is the same, and this choice can be simulated correctly.
This idea differs from James's idea in that, as seen in the difference between C and D, the conductor cost on trains that are too long or where the conductor has a lot of work is not underestimated. This point cannot be replaced by the method of placing a vehicle-specific "staff".

I think the concept is similar to the required tiles on a convoy.

#### Ranran

From previous notes I left
Quote from: Ranran on February 06, 2022, 05:22:55 PMI remember posting a bug list for this branch somewhere before, but I couldn't find it correctly.
Anyway I write a note.
When loading an old save with ver15, all convoys do not belong to line because the judgment by schedule->matches is always false in convoi_t::finish_rd().
The line information has been loaded correctly from save.
If we skip this comparison process and run line->add_convoy(self, true); with the old line, we can make convoy belong to the line correctly, but it would not be the right way. Anyway it needs to be fixed. Otherwise it will practically ruin the past save.
As far as I can guess from the comments in the code, I presume that this may have resulted in removing the assigned line before extended 15 by the processing when standard lost the compatibility of line data in ver101.
So I've modified the code as follows, and I don't think it's going to be a big problem, but I'd love to hear from someone familiar with this.

Anyway, it is inconvenient because the line is not inherited from the old save. This will be useful, at least for testing.

#### jamespetts

Ranran - thank you for your work on this, and apologies for the delay in replying. I realised that I had not fully worked out the answers to some of the questions and that some things that I had implemented needed to be modified to deal with some of the points raised. I will deal with the questions under headings below.

Staff

Thank you for that very useful explanation of the system that you had proposed. This is actually a very good idea and significantly reduces the complexity of the logic needed to implement the system.

Indeed, with this system, there is no need to distinguish between conductors and other staff. What I have implemented, therefore, are two datasets: (1) drivers; and (2) staff_hundredths. Each of the two types can be of any of the 255 possible enumerated types wages of which will be able to be set in a staff.tab when I implement that. Drivers will work as previously discussed. Staff hundredths will work as you suggested.

The reason that there is no need to distinguish between staff and conductors is that players who want to specify a vehicle that always has a fixed number of staff (e.g. a buffet car which always has somebody behind the counter, or a passenger brake carriage before continuously braked trains that always has a guard in it) can just specify a multiple of 100. This will not interfere with any lower number set to represent any other staff as multiples of 100 will always increment staff by exactly 1.

To facilitate this, I have altered the interface in the .dat files to allow pakset authors to specify either staff[0]= or staff_hundredths[0]= (or substituting any other number for 0 for different wage groups for staff).

Note that the ability to specify staff of different pay grades in this way should address the issue raised by Matthew in this post.

Fuel consumption

The calculation for fuel consumption has been discussed at some length elsewhere – I do not believe that anyone has come up with a more workable formula than I have specified here. However, there may be some misunderstanding of what is proposed. The calibration speed assumes that the vehicle in question is taxed so heavily (e.g. with a heavy load) that that is its maximum possible speed. A more lightly taxed vehicle would consume proportionately less fuel.

I would suggest not trying to compute the in-service fuel economy in advance, but giving a catalogue like figure, being the economy at the calibration speed assuming that the vehicle be fully taxed at that speed (and perhaps even giving the load on the level at which it would be so taxed). Where the calibration speed is zero, disabling the dynamic fuel calculation for the vehicle in question, what will have to be given instead is the basic static per km fuel consumption.

Overhauls and replacements

I am not sure how, in detail, best to handle replacement yet. However, I have added, as you will see, an auto upgrade index datum to the vehicles' .dat files. The intended algorithm for this is that, whenever the vehicle to which the index specified in the .dat file refers becomes available, the vehicle is upgraded automatically to this type when it is overhauled. With upgrades, as opposed to replacements, the intention is for the vehicle's existing maintenance data (especially the number of overhauls) to be preserved. Obviously, with a replacement to a new vehicle, this number will start at zero. In general terms apropos replacements, the idea is that these will occur on the next depot visit rather than forthwith, unless the player specifically commands an immediate replacement. It should be possible to replace only certain vehicles rather than all vehicles.

As to deferring overhauls, there will need to be a limit on how far that overhauls can be deferred. That limit is intended to be set at max_distance_between_overhauls or max_takeoffs for aircraft. However, the default overhaul should happen well before this point, and players should be able to defer up to this point. What I have not worked out yet is how best to calibrate the default overhaul point. The decay in availability and increase in maintenance cost after the last overhaul is intended to work on a sigmoid function (I have not yet worked out how best to implement that function using only integers; if you have any idea, I should be most interested; my current implementation is very crude). Quite at what point it is best to default to an overhaul I am not sure. If you have any ideas, I should be interested. The most straightforward option is probably a percentage of the difference between the base and maximum running costs specified in simuconf.tab, with the option to override this in the UI and have the vehicles overhauled when they fall below a certain availability % or above a certain running cost.

***

I hope that this clarifies matters. For reference, the latest set of data  in vehicles' .dat files is as follows:

`uint32 base_initial_overhaul_cost = 0; // Overhaul cost (without scale factor and increase for multiple overhauls) uint32 initial_overhaul_cost = 0; // Overhaul cost (before increse for multiple overhauls) uint32 base_max_overhaul_cost = 0; // Overhaul cost (without scale factor after full increase for multiple overhauls) uint32 max_overhaul_cost = 0; // Overhaul cost (after full increase for multiple overhauls) uint16 overhauls_before_max_cost = 0; // The number of overhauls before the maximum overhaul cost is reached. 0: no change uint32 max_distance_between_overhauls = 0; // The maximum distance in km between overhauls. 0: no overhauls required uint32 maintenance_interval_km = 0; // The distance between maintenance depot visits (when the next depot visit will be triggered). 1.5x this will trigger an emergency depot visit wherever the convoy is on its schedule. uint16 max_running_cost = UINT32_MAX_VALUE; // The maximum running cost of vehicles at max_distance_between_overhauls. Sigmoid interpolation between running_cost and this after availabiliuty_decay_start_km uint32 max_takeoffs = 0; // The maximum number of takeoffs (flight cycles) between overhauls for an aircraft. 0: unlimited uint32 availability_decay_start_km = 0; // The number of km since the last overhaul when the availability begins to decay and running costs increase. 0: no decay uint8  starting_availability = 100; // The percentage availablility of this vehicle when new. 100: needs no maintenance uint8  minimum_availability = 100; // The percentage availability of this vehicle when at max_distance_between_overhauls since the last overhaul 100: needs no maintenance uint32 replenishment_seconds = 60; // The number of seconds required for this vehicle to replenish (refuel) at a replenishment stop. uint32 calibration_speed = 0; // Used for calibrating the fuel consumption (km/h). 0 = fuel consumption does not vary with speed. // A non-zero value represents the speed (assuming accelerating or physics limited to this speed) // against which the fuel consumption per unit of distance is calibrated. uint32 cut_off_speed = 0; // The minimum speed below which fuel consumption per km does not reduce (km/h) uint32 fuel_per_km = 0; // Fuel cost calibrated according to the above. Not all powered vehicles (e.g. sailing ships) use fuel. The traction type records the fuel type. ... uint8 auto_upgrade_index = 255; // The index of the vehicle upgrade to which this vehicle upgrades automatically during the first overhaul in which the upgrade is available. Default: 255: no auto upgrade bool self_contained_catering = false; // Whether any catering provided by this vehicle is available to the whole consist or only this vehicle. /** * Staff data. * Hashtable: key: staff cost type; value: number of staff for this vehicle. * Introduced for version 15 */ typedef inthashtable_tpl<uint8, sint32, N_BAGS_SMALL> staff_map; staff_map drivers; // Staff who need to be present if the vehicle needs to be driven. staff_map staff_hundredths; // Other staff, expressed as a fraction of 100, but always rounded up to the nearest 100 to allow staff to be added incrementally if necessary. uint8 multiple_working_type = 0; // This determines whether multiple powered vehicles need drivers only in the first of them. If the numbers match (and are non-zero), then yes; otherwise, no.`
As before, only new data are shown.

Want to help with development? See here for things to do for coding, and here for information on how to make graphics/objects.

#### Ranran

QuoteNote that the ability to specify staff of different pay grades in this way should address the issue raised by Matthew in this post.
I think it is necessary to consider the high salary depending on the type of staff. However, I don't think I understand the issue correctly. It may be helpful if someone just elaborate on this point.
Inflation needs to be implemented together with fares, fuel costs, etc., so I think it can be considered separately.

QuoteI do not believe that anyone has come up with a more workable formula than I have specified here. However, there may be some misunderstanding of what is proposed. The calibration speed assumes that the vehicle in question is taxed so heavily (e.g. with a heavy load) that that is its maximum possible speed. A more lightly taxed vehicle would consume proportionately less fuel.
Thank you for your detailed explanation. I think that method makes sense.

QuoteThe intended algorithm for this is that, whenever the vehicle to which the index specified in the .dat file refers becomes available, the vehicle is upgraded automatically to this type when it is overhauled. With upgrades, as opposed to replacements, the intention is for the vehicle's existing maintenance data (especially the number of overhauls) to be preserved. Obviously, with a replacement to a new vehicle, this number will start at zero. In general terms apropos replacements, the idea is that these will occur on the next depot visit rather than forthwith, unless the player specifically commands an immediate replacement. It should be possible to replace only certain vehicles rather than all vehicles.

As to deferring overhauls, there will need to be a limit on how far that overhauls can be deferred. That limit is intended to be set at max_distance_between_overhauls or max_takeoffs for aircraft. However, the default overhaul should happen well before this point, and players should be able to defer up to this point.

The overhaul controller I came up with is as follows

The operation is performed by two combo boxes for each vehicle.
The "timing" selector selects when to perform the overhaul (or upgrade).
timing has three options that I have come up with.
(1) "Auto" is executed based on certain set conditions. (Default)
(2) The visit de pot will be postponed until convoy go to the depot. This is intended to be performed together with another vehicle overhaul visit within the maximum postponement deadline, skipping condition (1).
(3) I couldn't come up with a good name, but when convoy visits the depot for another vehicle overhaul, it has plenty of time to spare but at the same time carries out the overhaul. This is intended to avoid frequent visits to the depot when the overhaul timing of the vehicle is different. must specify a condition internally or in simconf that will not be executed if the deadline is sufficient.

Upgrade options will only list upgrade choices on vehicles that can be upgraded. The index selected here will be saved in auto_upgrade_index and will be upgraded when it visit the depot.
However, the problem here is that vehicle upgrades can break connectivity constraints between vehicles. The UI should check for constraints on selection and give a warning or eventually prevent it from being executed.

Are this table and operation represented as intended by the overhaul system?

#### jamespetts

Quote from: RanranI think it is necessary to consider the high salary depending on the type of staff. However, I don't think I understand the issue correctly. It may be helpful if someone just elaborate on this point.
Inflation needs to be implemented together with fares, fuel costs, etc., so I think it can be considered separately.

The idea is that there will be different staff types defined with different salaries. So, for example, one might have in staff.tab:

# Train driver
0=1750,10,1800,15,1850,20,1900,50,1930,65,1950,75,1975,150,1990,200,2020,250
# Fireman
1=1750,5,1800,10,1850,15,1900,30,1930,45,1950,55,1975,100,1990,170,2020,200
# Guard
2=(etc.)
# Buffet car attendant
3=(etc.)

Then, in a locomotive, one might have something like this:

driver[0]=1 # 1* staff type 0 (train driver)
staff[1]=1 # 1 * staff type 1 (fireman)

And in a carriage something like this:

staff[3]=2 # 2 * staff type 3 (buffet car attendant)
staff_hundredths[2]=1 # 1/100th of a guard (staff type 2).

The actual cost per month of each type of staff would depend on the numbers in staff.tab. So, for example, for our locomotive, in 1950, it would cost the following per month:

1 * staff type 0 in 1950: 75c + 1 * staff type 1 in 1950: 55 = 130

whereas in 1900 it would be:

1 * staff type 0 in 1900: 50c + 1 * staff type 1 in 1900: 30 = 70

Between the specified points, there would be simple linear interpolation.

I hope that this makes it clear?

Incidentally, I am having some difficulty with the implementation of this system in respect of drivers. For some reason that I have been unable to understand despite extensive testing, the driver data are not written to the .pak files even when these data are present in the .dat files. The same does not happen for the staff data. I cannot see any material differences between the code for staff and drivers in the makeobj sources, and I have not been able to run a debugger on makeobj despite spending a great amount of time attempting to do so because, for some reason that I cannot understand, passing an address for a .dat file to be read and turned into a .pak file as a command line argument in the Visual Studio debugger results in Makeobj being unable to find the file even when executing the identical command on the command line gives rise to no trouble at all in finding the file. Any assistance in resolving this issue woudl be much appreciated.

Thank you for your thoughts in relation to overhauls. Can I clarify what the intention is with the "auto" setting? The idea is for convoys always to have a depot stop somewhere in their schedules , albeit this will be skipped if no maintenance should be required. I think only in emergencies (i.e., where the player has let the distance to overhaul or maintenance exceed the maximum possible threshold) should convoys be sent to a depot immediately no matter where they are in their schedule. One possibility would be to allow players to choose between overhauling when the next maintenance would otherwise be due rather than at the next time that the convoy passes the depot, although I am not sure how useful that this would be.

As to early overhauls, I am not sure that this entirely works for overhauls (as opposed to maintenance), as there is a fixed capital cost for overhauls where there is not for maintenance, and overhaul timings are calculate differently to maintenance timings (I have yet to add the overhaul timing code: I intend to make this fixed per waytype in fractions of a game month from simuconf.tab settings).

In terms of the table, the "distance between overhauls" is potentially ambiguous, as there are in principle many different things that this could be measuring:

(1) the maximum possible distance between overhauls before the vehicle will immediately go to the depot for an overhaul no matter what the player does (but a player would be well advised to overhaul before this point, as availability will have reduced and running costs increased significantly by this point);
(2) the minimum distance after the last overhaul at which availability starts to drop and maintenance costs start to increase (but these will initially increase only slightly, so it is rarely likely to be optimal for the player to overhaul the vehicle at this point);
(3) the optimum distance for the player to overhaul the vehicle (which is likely to be highly complex to calculate with an in-game algorithm); and
(4) the distance that the player has actually set since the last overhaul for the next overhaul.

The same therefore applies by reference to the "distance to next overhaul" setting.

In terms of "upgrade instead of overhaul", one would probably want to think about offering the player a further alternative: "replace instead of overhaul".

I hope that this assists.

Want to help with development? See here for things to do for coding, and here for information on how to make graphics/objects.

#### jamespetts

A brief update. I have added logic for the following features:

• overhaul timing;
• availability based maintenance timing;
• limits on the maximum number of vehicles that can be undergoing maintenance or overhaul in a depot at any given time (a queue based system);
• reading values from fuel.tab and presenting fuel costs to other parts of game logic (not yet written);
• reading values from staff.tab and deducting correctly computed staff salaries in respect of vehicles*;
• the self-contained catering feature;
• auto upgrades on overhaul (albeit the logic for sending vehicles for overhaul has not been implemented yet); and
• per km maintenance cost increase based on distance since last overhaul.

* I have still not managed to fix the bug when reading data relating to drivers for reasons that I still do not understand. Any help with this would be much appreciated.

The next things on my list are implementing the fuel consumption logic and hopefully writing a better sigmoid function based on Prissi's advice. I will also need to think about the implementation of inflation more generally.

A few questions for Ranran (and anyone else following this) at this stage about the interface between the game logic and UI code.

• How best to deal with the vehicle replacer and its interaction with auto upgrades? My current thought is to have any replace data override an automatic upgrade and to add replace data specifying when the replacement should take place (immediately (the current behaviour), on next possible depot visit, on next maintenance, on next overhaul). We also need to think of a sensible default for these; I would think that on next maintenance would be a good default, but on next overhaul might also be a candidate. Note that if the vehicle is replaced with a non-upgrade type, there will be no overhaul, whereas if the vehicle is simply upgraded, an overhaul will still be performed (but the only cost will be the upgrade cost).
• Do we need to store any other maintenance or overhaul based options for player control in the vehicle_t objects? I imagine that we should at least need to store the overhaul interval setting - but how to calibrate that by default is not an easy question and and will need some careful thought.
• Do we need any logic to allow the player to control the depot maintenance queue, for example, by bumping individual vehicles/convoys to the top/bottom of the queue?
• How is it best to deal with multi-vehicle convoys (e.g. trains) on maintenance overhaul? For technical reasons, it is very difficult to do other than have a convoi_t object that is undergoing maintenance or overhaul, and this is what I have implemented. However, players may not want to maintain/overhaul all vehicles at once, and this may be inefficient. The only way around that I can think of is to allow the players to split the convoys at the point of maintenance/overhaul using the consist orders system, but I am not sure that the current system allows for this. Quite how to handle this will need careful thought and any input on this question (most especially any input that does not require vast amounts of coding effort and entire new abstractions and systems) would be much appreciated.

Want to help with development? See here for things to do for coding, and here for information on how to make graphics/objects.

#### jamespetts

I have now completed the work for adding fuel consumption mechanics and fixed the bug stopping the drivers system from working, as well as having fixed another bug relating to the accounting for the cost of staff in vehicles.

Want to help with development? See here for things to do for coding, and here for information on how to make graphics/objects.

#### Ranran

Currently I'm testing the updated one, but convoy may make a strange eternal stop.
For example, demo save's (97) LNER Tyneside EMU's staffs will start an eternal strike around 1:00:00.

#### Ranran

I've added a maintenance display to the convoy detail, but strangely many vehicles show a running cost increase of 200%.
This conflicts with the depot display and the current master branch value.
Does get_running_cost(welt) also include different factors such as fuel and staff costs?

The added display is tentative, and the restrictions on the display conditions have been intentionally removed so that it can also be displayed in demo.save. (Originally, some items may not be displayed in the simple maintenance settings.)

#### jamespetts

Quote from: Ranran on Today at 08:56:35 AMCurrently I'm testing the updated one, but convoy may make a strange eternal stop.
For example, demo save's (97) LNER Tyneside EMU's staffs will start an eternal strike around 1:00:00.
Thank you for this. I have merged your UI work so far into the ex-15 branch for testing.

I have carried out some initial investigation into this, and the problem appears to be that the spacing is not set in the convoys' schedules but the go_on_ticks value is set to WAIT_INFINITE. Looking at the current schedule UI, I cannot see where the spacing setting is; it seems to be missing from the dialogue. If you could restore this, it would be much easier for me to test what the problem is with a view to fixing it.

Want to help with development? See here for things to do for coding, and here for information on how to make graphics/objects.

#### jamespetts

Quote from: Ranran on Today at 02:35:45 PMI've added a maintenance display to the convoy detail, but strangely many vehicles show a running cost increase of 200%.
This conflicts with the depot display and the current master branch value.
Does get_running_cost(welt) also include different factors such as fuel and staff costs?

I think that I have fixed the bug causing this; the problem was that, where the vehicle had 0 (the default) specified for maximum distance between overhauls and the actual distance since the last overhaul was a non-zero value, the maintenance cost was given as the maximum, whereas in fact it ought to have been given as the base cost.

Want to help with development? See here for things to do for coding, and here for information on how to make graphics/objects.

#### Ranran

Quote from: jamespetts on Today at 03:50:57 PMI have carried out some initial investigation into this, and the problem appears to be that the spacing is not set in the convoys' schedules but the go_on_ticks value is set to WAIT_INFINITE. Looking at the current schedule UI, I cannot see where the spacing setting is; it seems to be missing from the dialogue. If you could restore this, it would be much easier for me to test what the problem is with a view to fixing it.
It looks like there are no missing inputs compared to the schedule UI in the master branch. I think the spacing setting is under "Wait for time".

However, with a recent update, the schedule UI doesn't seem to record the schedule correctly after closing the dialog. The changes will be discarded. This is a symptom that wasn't there a year ago.