NIMBY Rails devblog 2024-07

Where next?

The first half of July was devoted to deciding “where next?”, advancing a little on the design a variety of options, both for roadmap and non-roadmap objectives. One of the ways I work is by collecting thoughts and ideas under some heading, like “signals” or “orders”, which at some point are tidied up, elaborated further into its own project, then designed and implemented in a given version. As the game matures in Early Access I’ve been trying to make sure these align more and more with the roadmap (like v1.12) and less with core system rewrites (like v1.5 or v1.9).

Core system rewrites are required because when the game was originally released in EA it was basically a prototype. Every system was due for a remake of some sort. For the game to fully realize its potential it was required to quite literally delete a lot of code and restart from scratch. The most representative example of this process is probably v1.5, which introduced timetables.

Many of these rewrites have happened already, but there’s a very major one pending still, signals. And this has been in the roadmap for 3 years, it’s not just because of signals existing in a simplified/prototype state. But before a proper signal system is implemented I want to make sure the train orders system receives a couple of major upgrades I’ve been thinking about for some time, to make sure signals v2 are implemented with the train orders system already in its most finished state. So v1.14 will be about a train orders review/expansion.

Schedules 2.0: A new design for train scheduling, which will never be implemented

There’s some unrealized goals I would like to see in the train orders system, both mine and adapted from the community suggestions:

  • Train orders should be more front-and-center in the game design. NIMBY Rails is quite unique in its one-second precision, fully simulation achievable timetable system. But both the visibility and interface of timetables are buried in a tab in the train editor. Timetables should be a top level feature of the game.

  • The “copier trains” system is too limited. Schedule shifts should be a full feature object, with more flexibility.

  • Schedules and shifts should not be tied to particular trains, just like in the real world. It should be possible for trains to change schedules non deterministically during the week, when it makes sense to do so (so not in the middle of a pax servicing line stop, for example.) Shifts can only be assigned to one train at a time, but the set of assignable trains can be arbitrary.

  • Replace “train orders” with a new concept, plans. A plan is a sequence of lines to run, always without any waiting between them (but including any required paths between them). A Schedule is then a sequence of plans, and waiting between plans is always visible and explicit in the UI, instead of automatically making some stops longer than expected. This would solve a major UX problems with timetables.

  • Line services at the schedule plan level. This means that (part of) the line service options would be available when making a schedule plan, so the player would be able to change stop time for particular instances of stops directly in the plan, without having to introduce new line services. This would go hand in hand with the previous point.

  • Schedule-level technical stops. It would be possible to create station stops directly at the Schedule Plan level, without involving a line. These would always be a technical stop and would always cancel pax planning for that train ride. This would eliminate the need to create most technical mode lines being used for depots.

The big problem with this design is backwards compatibility. Plans in particular would be hard to translate automatically from existing train orders, with players probably expecting their carefully “stacked” orders to be automatically recognized as a Plan plus Plan-level line service rather than a direct one-to-one mapping. I could write a lot of the subtleties of this 2.0 design that do not fit at all with existing saves and the existing player expectations/experience. I spent most of the second half of July trying to solve this in a sane way, both for me and for players, but in the end I decided it was not worth the effort to implement this system at the current level of maturity the game has. Its complexity is made worse with the effort to also implement the importer system it would require, which in the end would still be judged inadequate. So I decided to instead settle for a middle ground design which preserves existing train orders identically but gives up on some of the features.

Schedules 1.5: A new design for train scheduling, which is being implemented

The current Schedules 1.0 (v1.13) train orders system looks like this:

Each (manual mode) train contains one or more orders, from which runs are automatically generated. Trains always run the orders they own, and nothing else. These orders are a configuration detail of trains, owned by the trains, which, in a way, directly translates into how they are edited in the UI.

To arrive to a middle ground between the 1.0 and the 2.0 design I first selected what I consider the must have features from 2.0, which can be made compatible with 1.0 train orders:

  • Train orders as a top level game feature, renamed to Schedules.

  • Schedules support a new object, Shift, which replaces train copier groups.

  • Trains do not have a fixed schedule anymore. Instead they can be dynamically assigned to one at run time. The assignable train set is kept at the Shift level. See section on at end of the post

So the diagram will look like this instead in v1.14:

The game UI would gain a new top level editor, Schedules, which would allow the creation of new Schedule objects. After creating an Schedule you can then edit its Orders. This new Schedule Order editor would be identical to the v1.13 Train Order editor, in order to preserve existing saves Train Orders. So no new objects like Plans would be introduced, and the resulting Runs should be identical to v1.13, most of the time. But for which train, if Schedules do not have a train assigned by themselves? This is the one possible timing change in v1.14: runs glue path timing will be calculated using the reference train assigned to the line.

The new section of the Schedule editor will be the Shifts editor. In this new section will be possible to add one or more Shifts to a Schedule. Shifts responsibility is to record the set of trains which are allowed to run the Schedule for that particular shift, and what are the parameters of the shift. It will also display the dynamic state of the Shifts: which Shifts are currently assigned to which trains, out of the allowed set of trains to run them.

Open question: Shift parameters feature set

“Shift parameters” is something I don’t have a good name or even a good design for now. These are meant to represent how a Shift is a modification of a Schedule sequence of runs. In the 1.0 design this was the train copier system, which was limited to a manual per-train time shift or some auto shift based on durations (line or manual). In 1.5 the idea is to make Shifts similar to the concept of line services, so given the base order sequence of the Schedule, each Shift modifies the orders in some way. Here’s some ideas I will test:

  • Orders can set the number of loops for their runs, rather than choosing between 1 and maximum. As always, the last run will pad time as needed. This could also be modified at the Shift level.

  • Shifts can disable orders, including specific days of multi day orders.

  • In addition to modifying all order start times, like it is possible with the 1.13 train copier system, it should also be possible to select individual orders and change their time offset.

Dynamic scheduling has been discarded

The original version of this post included the description of a dynamic scheduling system for Schedules 1.5. After making this post and advancing a bit on the design and implementation, I realized that the possibility of creating more shifts than trains means pax can plan paths by selecting shifts which won’t be serviced by any train. Therefore the new scheduling system in 1.14 won’t feature dynamic scheduling, but it will still feature new Schedules and Shift system.

If you are curious about the original post, here’s the deleted sections: https://gist.github.com/carloscm/5875883379b2e64c9ea7924c1b2883a6