Regarding the last FFFs about trains
Posted: Tue Jan 30, 2024 4:03 pm
Regarding the last FFFs about trains, i have some concerns about the upcoming changes.
I think that using station names for game logic it hacky. It feels like trying to anticipate some specific user stories and cover these exact scenarios by implementing legalized workarounds. I don't think it will be beneficial long term as there will always be some unforeseen scenarios.
It might be better to revisit the train system as a whole. Each station should have a wide exposed variety of properties: immutable unique id, name, resource types to import or export, current stockpile, target stockpile, priority as a provider AND as a requester (two distinct values), train limit and allowed composition, and user defined tags. Some of them configurable with GUI, signals, or both. Then provide access to these fields to schedule conditions.
Stations in the schedule should be defined by an ID, not a name (obviously, represented by a name in GUI), so you can safely rename a station without compromising existing schedules (name is supposed to be just a label, after all).
I also don't understand the necessity of BOTH ordinary schedules and interrupts. Just the idea of "If Condition then Go to" is enough. Just evaluate that list from top to bottom each time a train departs a station. If you need to force specific order of stations, just add "current_station" to the list of the available conditions. It may even be a default condition for a newly added station to the schedule, so those who don't want to bother with train logic, won't have to.
Example of a very simple schedule:
0. If fuel < 200MJ
+ Go to station with id:0 ("Refuel")
+ Wait until fuel >= 1000MJ
1. If cargo is empty
+ Go to station with id:1 ("Iron Ore load")
+ Wait until cargo full
2. If iron_ore > 0
+ Go to station with id:2 ("Iron Ore drop off")
+ Wait until cargo empty
3. Else (No condition) // if no condition was satisfied or corresponding station was unavailable
+ Go to station with id:3 ("Depot")
+ Wait until target_station is not id:3 ("Depot") // so the train will not circle back to this station every time schedule is evaluated
Example of a generic schedule (Refuel and depot omitted for brevity)
0. If cargo is empty
+ Go to station with any_item in exports // generic signal from the latest FFF. Train will travel to any station which has at least one signal in exports
+ Wait until cargo full
1. If any_item in cargo > 0 // any_item is evaluated to the first item which passes the condition
+ Go to station with any_item in imports
+ Wait until cargo empty
Then you can do pretty much everything with your trains. You can optimize them in a way that train fills from multiple providers and delivers to different drop offs. After that it is just about exposing additional properties of a station for the conditions to make the system more robust.
I think that using station names for game logic it hacky. It feels like trying to anticipate some specific user stories and cover these exact scenarios by implementing legalized workarounds. I don't think it will be beneficial long term as there will always be some unforeseen scenarios.
It might be better to revisit the train system as a whole. Each station should have a wide exposed variety of properties: immutable unique id, name, resource types to import or export, current stockpile, target stockpile, priority as a provider AND as a requester (two distinct values), train limit and allowed composition, and user defined tags. Some of them configurable with GUI, signals, or both. Then provide access to these fields to schedule conditions.
Stations in the schedule should be defined by an ID, not a name (obviously, represented by a name in GUI), so you can safely rename a station without compromising existing schedules (name is supposed to be just a label, after all).
I also don't understand the necessity of BOTH ordinary schedules and interrupts. Just the idea of "If Condition then Go to" is enough. Just evaluate that list from top to bottom each time a train departs a station. If you need to force specific order of stations, just add "current_station" to the list of the available conditions. It may even be a default condition for a newly added station to the schedule, so those who don't want to bother with train logic, won't have to.
Example of a very simple schedule:
0. If fuel < 200MJ
+ Go to station with id:0 ("Refuel")
+ Wait until fuel >= 1000MJ
1. If cargo is empty
+ Go to station with id:1 ("Iron Ore load")
+ Wait until cargo full
2. If iron_ore > 0
+ Go to station with id:2 ("Iron Ore drop off")
+ Wait until cargo empty
3. Else (No condition) // if no condition was satisfied or corresponding station was unavailable
+ Go to station with id:3 ("Depot")
+ Wait until target_station is not id:3 ("Depot") // so the train will not circle back to this station every time schedule is evaluated
Example of a generic schedule (Refuel and depot omitted for brevity)
0. If cargo is empty
+ Go to station with any_item in exports // generic signal from the latest FFF. Train will travel to any station which has at least one signal in exports
+ Wait until cargo full
1. If any_item in cargo > 0 // any_item is evaluated to the first item which passes the condition
+ Go to station with any_item in imports
+ Wait until cargo empty
Then you can do pretty much everything with your trains. You can optimize them in a way that train fills from multiple providers and delivers to different drop offs. After that it is just about exposing additional properties of a station for the conditions to make the system more robust.