I've made some big balance changes, and want to explain what my goals are and how I think the changes will support them.
Worker speed
Long trains are a bit too favored by the old mechanics. I want to adjust mechanics to give shorter trains a bit more advantage, because that will lead to more shorter trains, and having more trains will lead to more interesting traffic management.
Also, with the old worker logic, the platforms at a station take too similar of an amount of time to unload trains. The result is that the simplest signaling approach of blue -> orange at the entrance of stations, which results in a round-robin distribution is almost always optimal. The extra cost of extra rails or increased waiting time at junctions of other approaches don't result in more efficient train distribution. If there is a larger time discrepancy for unloading different platforms, this could result in more interesting signaling decisions. e.g. a small station could use the round-robin approach, and a large station could have fancier signaling.
Both of those goals are achieved by reducing the walking speed of workers. Or, more specifically, increasing the time spent walking relative to the time spent waiting. Currently the time spent waiting is 80 ticks, and the walking speed is 8 ticks per tile. I would like to keep the loading rate approximately equal to the current speed. In a fairly typical station I think a worker walking about 5 tiles is normal, so I will keep the loading speed the same for a worker in that case. This means that the time to unload a train of length 10 would remain about the same.
Old: 5 * 8 + 80 = 120
New: 5 * 24 = 120
You would think that setting the worker waiting time to zero would make farther stations much slower. It does make them somewhat slower, but there is overhead from getting a replacement train into the station that is significant enough for the round-robin method to remain quite effective.
A side effect is aesthetic. After this change, the workers don't walk faster than the top speed of an oil train. Also, the workers were hard to see since they moved so fast. They are still fast, but a bit less frenetic now. They also spend a larger percentage of the time outside, so the station looks busier.
Cargo weight
In the old mechanics, cargo contributed to the weight of a train car, which affected the acceleration. However the weight was a fairly low percentage of the total with an empty car weighing 10 and the cargo of a full car weighing 5, for a total of 15 for a full car. With the fast acceleration that the trains currently have, this difference is almost imperceptible. The question was if cargo weight was an important mechanic, in which case, it should be increased relative to the empty car weight.
The difficulty is that for shared tracks between lines to be worthwhile, junctions should not to take too long to clear. This requires that trains accelerate fairly quickly. So, a fully loaded train still needs to accelerate fast. If cargo weight is significant, that means an unloaded train would accelerate to top speed nearly instantly, which looks bad.
My conclusion is that cargo weight can't be made more significant, and thus that it should be removed and cars will always weigh 10. This makes the mechanics a bit easier to understand to players and optimize around. It also slightly simplifies the simulation code.
Slopes and curves
In the old code, curvature limiting train speed was calculated in 3D so that curves up and down would affect the max speed of a train as much as curves side to side. This means that straight bridges would limit a train's speed from the track curvature. This makes some sort of sense in that cresting a hill at speed could cause a train to fly into the air or something, but that only makes sense for cresting a hill, not for going through a valley, and the curvature was treating both cases the same.
Another problem is that I'm not intending the track representation in the game to be a physically exact 1-to-1 representation of scale. The slopes of bridges are exaggeratedly large so that things fit on a map. Also the game isn't trying to be a realistic simulator, but is instead trying to induce interesting design choices.
The solution is to split the calculations of curvature and slope. The curvature only considers the 2d layout in the x,y axes, and slope only considers the changes in z. Before the speed going down was also limited, with the argument being that trains had to slow down by braking to maintain control and stop in the same distance. But that looked a bit weird, and also is inconsistent with the game world in that the trains can stop instantly at signals. The speed is now only limited when going up a slope, and the train can go down a slope at full speed.
The slope now limits the max speed of trains as before, but instead of multiplying the speed for each engine type, it caps the max speed to the same limit regardless of engine type. Similarly to how curves work, this is intended to encourage to use of weaker engines, which otherwise server little purpose. I've also changed the code to depend on the summed weight of cars on the slopes instead of the average slope of the train cars. This will penalize long trains more than before.
The multiplier also applies to the acceleration so that it is slower to accelerate up a slope. This will affect optimal station designs to align down slopes, and junction placement to have trains accelerate into the junction to improve train packing. I think this is important to make the terrain more impactful to designs, because in the old version, the hills basically didn't matter. This is also a mechanic that benefits low power engines and shorter trains, because they spend less time accelerating compared to big powerful trains.
As before, the slopes will never cause trains to stop or stall. This is because having a train stall would only be dynamically determinable during simulation, and I would like to have track layout problems be statically determined and reported as errors at the start of the simulation.
