I've finally checked out DFHack's "watch-minecarts" script and can definitely say that way too often the data have been misinterpreted.
The cause is a simple rounding issue: the data printed to console have a "co-ordinate" field. And to find the actual tile on which the cart is present (and which affects it) you have to round
down or up to the nearest integer. I verified this by stepping through moves of a minecart and checking against the watch script, taking note of the exact location data whenever a cart
visibly moved from one tile to another. This
always happens when the coordinate shown goes past x.5. This simple fact elegantly explains why ramps and rollers on tile (x) start affecting a cart as soon as coordinate is at least (x-1).5, and no longer have any effect once the coordinate is (x).5 - those coordinates are the actual borders of tile (x). Track features like corners, ramps and rollers only affect the cart while it's on their tile, their influence doesn't stretch into the previous tile.
If i read the earlier interpretation of a data dump right, the author mistook the decimal points in the dump for data-field separators, which led to the misconception that the game tile was explicitly shown in the dump and sub-coordinates were a separate item in the dump, showing a location "within the tile". Effectively, this led to rounding by truncation, which simply isn't how the game processes coordinates. This mismatch between interpretation and actual game behaviour produced complicated and utterly wrong statements on the wiki.
In other words: tile (20:20) contains the coordinates (19,5:19,5) to (20,5:20,5). The exact coordinates (20,0:20,0) represent the
middle of the tile. If the tile's a corner, the corner applies when the cart passes the x,5000 point - and since rounding is done arithmetically and
not by truncation, that means it applies at the very
end of the tile.
I'll try to remove the misinterpretations currently present in the minecart article.
PS: Lifting a dump from
this thread thanks to user fricy, because i just won't install DFHack for that purpose:
(1.)016-65.905400590001535400
(2.)016.29990.29990.29990.299959000153000
(3.)016.59980.29990.2999059000153000
(4.)016.89960.29980.2998-0.000159000153000
[...]
018.39710.29930.2993-0.000159000153000
(10.)018.63880.24170.2992-0.000159000152-100
(11.)018.884930.246130.34810.048959000152000
019.165630.28070.3970.048959000152000
[...]
(25.)025.961160.730191.03270.048959000145-100
I added cardinal numbers for lines of interest and cut out uninteresting data.
It shows a cart coming off a medium-speed roller and diving into plain downward ramps after two tiles of flat floor.
I don't know how faithful the dump is to the game's internal data structures, but i'll assume it's generally correct:
My interpretation:
All the periods in this dump are not delimiters between data chunks, but plain old decimal points. If you see a point, whatever's left of it is
probably the full part, and what's right of it the fractional part of a single number. The borders between individual numbers are mostly invisible.
So the first number we're seeing is
not a "tile identifier" that stops at the period, it's the
coordinate given to four decimal places, which must be rounded arithmetically to find the current tile occupied. The actual game tile occupied is
not shown directly by the script, it must be derived by rounding the coordinate. As i said above (and put onto the wiki), the middle of the tile is the zero-fraction sub-coordinate, the borders are the +/- 0,5 coordinates.
The cart starts out in the middle of tile 16 (shown as "16", i.e. 16.0000). In the first line, the other data are a bit iffy to interpret, for the basic structure, let's first look at
the second line:
current location: 16.2999 (speaks for itself, just over halfway between the start - middle of the tile - and the tile border.
movement since last measurement: 0.2999 (the zero belongs to this value, not to the current location co-ordinate; see above - the script usually strikes "trailing" zeroes), on the x-axis.
current speed: 0.2999 (positive, on the x-axis)
speed change since last measurement: 0.2999 (accelerated to medium-roller speed by the roller, then decelerated by one tick due to track friction)
This also resolves the most likely meanings for the remaining entries:
current y-location: 59 (.00000) - middle of tile 59 in the other "flat" dimension
movement on y-axis since last measurement: 0
current speed on y-axis: 0
net change in y-speed during last turn: 0
current z-location: 153 (.00000) - standard floor (notional middle!) of z-level 153
movement on z-axis since last measurement: 0
current speed on z-axis: 0
net change in z-speed during last turn: 0
- each of the zero values (location change, speed, speed change) is given as a plain zero without decimal points or anything, without any indicator that a new datum has begun. Since the cart moves in a straight line, the y-parameter data stay the same throughout the run, while the z-parameter changes by a flat one everytime a new ramp down is entered, but this happens without actually generating z-axis speed, it shows -1/0/0. It's not a "minus one hundred", it's a "minus one" followed by two zeroes, three distinct data; the dump script unfortunately doesn't separate individual entries in the data structure in a recognisable way. We need to internally decipher e.g. line two
016.29990.29990.29990.299959000153000
into
(0/)16.2999/0.2999/0.2999/0.2999/59/0/0/0/153/0/0/0.
thus, the data past the x-coordinate on line one would be
x-movement since last measurement: - 65.9054 (odd distance, the cart may have been stopped by track stops)
current x-speed: 0
last x-speed change: 0
y-dimension data: 59/0/0/0, as always
z-dimension data: 153/54/0/0 - cart was carried up 54 z-levels since last measurement, currently without speed on the z-axis
My cursory check of the DFHack script told me that the movement datum is indeed "since last measurement", not "on the last turn". If you step the game twice between script activations, you get the cart's movement during the last two steps, even more if you don't measure for longer periods, e.g. while the cart is carried around.
In the third line, the cart moves to the next tile (16.5998 rounds to 17). The net zero speed change shows that acceleration/friction are processed
before the cart moves - the cart begins its move on a roller tile and ends it on a non-roller tile; its speed at the end of turn is determined by the roller tile, i.e. the turn's starting tile. (NB: the same applies to ramps - ramp acceleration takes place before a cart takes its turn, thus a cart moving into a ramp tile is not accelerated on the turn in which it enters the ramp, only during turns which start on the ramp, including the turn on which the cart eventually leaves the ramp.) (NB2: the cart has a zero
net speed change, the roller tile is not frictionless. What happens is that the roller first accelerates the cart from 29990 to 30000 (medium roller's operation speed), then track friction reduces it back to 29990.)
In the fourth line, the cart begins its turn on a flat non-roller tile. It is slowed down by track friction before taking its move, thus drops to 0.2998 speed before moving 0.2998 of a tile. The speed change is shown with the negative sign, as -0.0001. As far as i can tell, speed and movement are tracked only in two dimensions, i.e. depending on whether a cart's moving north or south it has negative or positive speed/acceleration.
In the tenth line, the cart moves onto the ramps. The first ramp is tile 19, which begins at coordinate 18.5. Entering the tile immediately moves the cart down a z-level without generating vertical speed (the -1/0/0 on the right) and the distance calculations switch to ramp mode. Presumably, the cart moves 0.1029 on the track until the ramp, then uses its remaining ~0.196 distance to move into the ramp itself, with changed distance calculations. The different distances are easier to see on the
Eleventh line
Movement since last: 0.24613
Speed: 0.3481
Speed change: 0.0489
I.e. speed is tracked without change, but distances on the tile are divided by sqrt(2). Feeding the numbers into my calculator gives divisors ranging from 1.41428 to 1.41432, i.e. the game probably uses a constant divisor (1.4143 or so), producing a very small rounding instability. Notably, distances on the ramp are tracked to five decimal places, while speed, speed increments and flat-track distances only really make use of four decimal places.
Twenty-fifth line:
Movement since last: 0.73019
Speed: 1.0327
Here, speed goes past one standard tile per step for the first time. I think this line shows quite clearly that the many zeroes seen before decimal points in previous lines indeed just display the "full" part of the numbers, periods shouldn't be mistaken for delimiters between data.
Minecart data dumps get much funnier when going around corners, because carts "teleport" from one tile border to another, giving substantial distance increments, and the direction change produces fairly large displayed speed changes. When multiple speed changes take place in the same turn, the data dump script isn't very enlightening, since it just records the net change: a cart leaving a ramp actually accelerates on the ramp, suffers the related track friction, makes its standard move, then gets teleported to the end of the checkpoint tile and is checkpoint-accelerated in the opposite direction, all in the same turn. The net speed change is a paltry ten ordinary friction, and that's all the data dump script is able to show.
PPS: carts pushed by a dwarf onto normal track leave the new tile a mere two steps after first showing up in the pushed-to square. This doesn't seem to fit expectations: cart is pushed to the middle (
not the start!
) of the tile, then must move thrice (at ~20k push speed) to leave the tile, but we see this happening a mere two steps after we see the push. How come? The reason is simply move order - there's more than just the push happening in the turn of the push. Dwarfs' slot in the movement queue comes before minecarts', and the push is the
dwarf's, not the minecart's action. I.e. the dwarf uses his or her turn to "set" the cart into the middle of the adjacent tile and provide it with 20k speed. The cart still has to take its own turn
for the same game step, which it does by losing 10 speed to friction, then moving 19990 distance units forward: the cart finishes the push turn 0,2 tiles past the middle of the pushed-to tile and only takes two more turns to pass over the tile's border. Or, differently put, it does take three moves to get off the tile, but the first move is already taken on the turn on which it's pushed.
Move order may be worth working into the wiki somewhere...