Train carriage order logic

Place to get help with not working mods / modding interface.
Post Reply
Honktown
Smart Inserter
Smart Inserter
Posts: 1025
Joined: Thu Oct 03, 2019 7:10 am
Contact:

Train carriage order logic

Post by Honktown »

Issue: what is the logic for train carriage order when using 'connect stock'? A train and all the wagons can reorient (carriage.orientation) when making a connection - including a reversal of all the carriages in train.carriages. This causes problems if a uniform carriage order is necessary, as in the comfy scenario "Mountain Fortress v3"

I've assumed some agnostic methods would be:
/1. the least x then least y carriage orientation, or reversed, least y then least x
/2. first locomotive orientation based on position
/3. orientation of the frontmost entity in 'leading' locomotive's orientation
/4. something with selected train orientation when 'connect stock' is used
But none of these seem to be it.

Included is an example save. Image for reference:
trains.jpg
trains.jpg (416.56 KiB) Viewed 1485 times
On the bottom loop for example, if the train is on the top side, disconnecting the carriages and reversing either locomotive then reconnecting everything has the effect of not re-orienting the train, but on the bottom the train carriage order reverses when either locomotive is rotated.

Here is an example command to show which things are changing:

Code: Select all

/c
local train = game.player.selected.train
local string = ""
for i, carriage in pairs(train.carriages) do
  string = string.."\n"..i..": "..carriage.name.." orientation: "..carriage.orientation
end
game.print(string)
Attachments
carriages_test.zip
(1.16 MiB) Downloaded 60 times
I have mods! I guess!
Link

User avatar
boskid
Factorio Staff
Factorio Staff
Posts: 2247
Joined: Thu Dec 14, 2017 6:56 pm
Contact:

Re: Train carriage order logic

Post by boskid »

I would say the best approach would be to make your code to be not dependent on any particular rolling stock order.

From the code (1.0), when train is created (including cases of connecting rollling stocks and disconnecting rolling stocks when the train is rebuilt), there is a check to decide which border rolling stock will be the front of a train:
- take the end that has most of the locomotives pointing in that direction and make it front. In case of same amount:
- take the end that has X position lower and use it as a front. In case of same x position:
- take the end that has Y position lower and use it as a front. In case of same y position - it should be only possible when a train has only 1 rolling stock that is not a locomotive.

However keep in mind this is nothing guaranteed and may change any time.

Honktown
Smart Inserter
Smart Inserter
Posts: 1025
Joined: Thu Oct 03, 2019 7:10 am
Contact:

Re: Train carriage order logic

Post by Honktown »

boskid wrote:
Sun Sep 06, 2020 2:21 pm
...
Thank you for your reply. There was an idea that since one of the locomotives is special in this case, a solution could be find which way it faces when disconnected (maybe update the record if someone rotates it), and recreating the original carriage order by decrementing/incrementing in the direction of "front" in a lua table. Any other trains would be forced into a "least y then least x locomotive direction" order or something, to at least make it more predictable.
I have mods! I guess!
Link

User avatar
boskid
Factorio Staff
Factorio Staff
Posts: 2247
Joined: Thu Dec 14, 2017 6:56 pm
Contact:

Re: Train carriage order logic

Post by boskid »

I have added LuaEntity::get_connected_rolling_stock() (for 1.1.0 release) that allows implementing custom iteration over rolling stocks without using LuaTrain::carriages. If you have a rolling stock and want to know what is connected to its back, this will simply allow this, and for going farther than 1 rolling stock, there is also second value that says to which end of rolling stock this was connected, so you can flip it to the other side and again call get_connected_rolling_stock to get next rolling stock. Will it be good enough to solve your problem?
89144.png
89144.png (20.22 KiB) Viewed 1418 times
It is O(1) and will return exactly the same values as following O(N) workaround code:
lua code

Honktown
Smart Inserter
Smart Inserter
Posts: 1025
Joined: Thu Oct 03, 2019 7:10 am
Contact:

Re: Train carriage order logic

Post by Honktown »

boskid wrote:
Sat Sep 12, 2020 7:48 am
...
It's useful, but not quite consistent with what I might like to have happen, I suppose:
oddtrain.jpg
oddtrain.jpg (94.63 KiB) Viewed 1386 times
Some small tweaks only to the print code:

Code: Select all

lib.print_carriages = function(event)
  local player = game.players[1]
  if player == nil then return end
  local ent = player.selected
  if ent == nil then return end
  local train = ent.train
  if train == nil then return end

  local outstring = ""
  for _, carriage in pairs(train.carriages) do
    outstring = outstring.."\nPerspective: "..carriage.name
    local stock, joint_of_connected_stock = get_connected_rolling_stock(carriage, defines.rail_direction.front)
    if stock then
      outstring = outstring.."\nfront stock.type: "..stock.type
      outstring = outstring.."\nfront joint_of_connected_stock: "..joint_of_connected_stock
    else
      outstring = outstring.."\nfront no stock"
    end

    stock, joint_of_connected_stock = get_connected_rolling_stock(carriage, defines.rail_direction.back)
    if stock then
      outstring = outstring.."\nback stock.type: "..stock.type
      outstring = outstring.."\nback joint_of_connected_stock: "..joint_of_connected_stock
    else
      outstring = outstring.."\nback no stock"
    end
  end
  log(outstring)
end
I receive:

Code: Select all

Perspective: cargo-wagon
front stock.type: locomotive
front joint_of_connected_stock: 0
back no stock
Perspective: locomotive
front stock.type: cargo-wagon
front joint_of_connected_stock: 0
back no stock
I think this is all well and good, but I'll need some extra logic: start with a specific carriage, then get an entity in the front direction. If the "front" of that entity returns the carriage I am basing my direction on, reverse the direction, and get the next entity. Repeat until nil. This is the "front" of the train from the perspective of the original entity's facing. I can then reverse the process, inserting each entity into a table before I go on to the next, flipping the direction if needed. The hardest part I imagined originally was having a way to determine which connected stocks are "forwards" and "backwards", with consideration for how the game defines orientations and the concept of carriage direction being a bit messy. Thanks.

A quick additional question: is there a license restriction for your function? If I were to use the code before 1.1, it may end up in a GPLv3 scenario, MIT, or Unlicensed (most likely licenses). Nothing that says "this is mine", but I would like to be careful, you know?
I have mods! I guess!
Link

User avatar
boskid
Factorio Staff
Factorio Staff
Posts: 2247
Joined: Thu Dec 14, 2017 6:56 pm
Contact:

Re: Train carriage order logic

Post by boskid »

Honktown wrote:
Mon Sep 14, 2020 5:51 am
A quick additional question: is there a license restriction for your function? If I were to use the code before 1.1, it may end up in a GPLv3 scenario, MIT, or Unlicensed (most likely licenses). Nothing that says "this is mine", but I would like to be careful, you know?
I dont care, feel free to use with any license.

-- edit:
Every rolling stock has front and back, in oddtrain.jpg you have locomotive's front connected to cargo wagon's front (joint_of_connected_stock==0 which means front) so this is what the results will be. In all cases front joint is forward based on the orientation and back joint is behind based on orientation. If you do not have some super long rolling stocks that would bend on curved rails so much that position of front rolling stock would go behind the decision line this function should work correct (native function will always work correct).

Honktown
Smart Inserter
Smart Inserter
Posts: 1025
Joined: Thu Oct 03, 2019 7:10 am
Contact:

Re: Train carriage order logic

Post by Honktown »

...I was looking at this before bed and was way overthinking it. Once I have the carriage in front of the locomotive, the desired order of train.carriages is known. Increment/decrement from there. This should solve the problem.
I have mods! I guess!
Link

Post Reply

Return to “Modding help”