Postscriptum: Corners, how do they work?
(Open for refinement/correction, as always, i'm just presenting my findings)
Let's start by grossly simplifying the way a tile is presumably handled by the minecart routines: we assume a tile divided into 100 by 100 sub-co-ordinates (i.e. 100 centitiles "wide" and 100 "long"). Sub-coordinates of the corners are 1/1, 1/100, 100/1 and 100/100, with 50/50 being the centre. A minecart "occupies" the full tile, but its actual location _on_ the tile is identified by a sub-coordinate of specific width and length. A cart leaves a tile when its sub-coordinates go "out of bounds", i.e. above 100 or below 1.
This is all simplifying and assuming a lot
- the game presumably works with 1/100 000 tiles as basic length
- an even-numbered range has no individual middle value
- i don't know the details of how a cart's location within a tile is tracked by the game's mechanics; i only know that some tracking is taking place and the given model explains the observable effects reasonably well.
Aside: ramp tiles are of course 140x140 centitiles.
Thus, in a grid of three by three tiles like this:
+---+---+---+
| | | |
| a | b | c |
| | | |
+---+---+---+
| | | |
| d | e | f |
| | | |
+---+---+---+
| | | |
| g | h | j |
| | | |
+---+---+---+
a cart moving across tile "e" would stay on this tile as long as sub-coordinates are in the 1-100 range on both axes and (counting west-to-east and south-to-north) would go to tile "b" if SC went to 50/120, to tile "f" if SC became 130/60, or to tile "g" if SC became -40/-20.
Which influence do track directions have on the cart's movement? If they aren't corners, none at all! If our cart is moving south-to-north across tile "e", it doesn't matter whether that tile has EW, NS, NSE, SEW track, the cart behaves the same in all cases. Similarly when the cart moves diagonally - "straight" track doesn't "straighten out" a diagonally-moving cart. Non-corner track is primarily a "this is track" marker - rollers and pressure plates on the tile can affect/react to carts, carts moving across the tile towards a downward ramp will try to dive into the ramp. For those purposes, the exact direction of the track is entirely meaningless. Dwarfs "guiding" a cart will follow engraved track directions, that's the only influence non-corner track has on pathing - notably, it affects only the pathing of a _dwarf_.
For an explicit example of diagonal movement: the cart moves at 40 centitiles/step north, 15 centitiles/step east, enters tile "h" in the middle of the southern side (50/1). In the first step, the cart moves to subtile 65/41, in the second to 80/81, in the third to 95/121, i.e. leaves to tile "e" and occupies subtile 95/21 there; on the fourth step, it moves to 110/61, i.e. leaves to tile "f", subtile 10/61, on the fifth step it goes to 25/101, i.e. subtile 25/1 on tile "c", which it leaves on step eight.
What we see is the cart spending three steps on tile "h", then apparently moving one step north, then one east, then another north and taking another three steps to leave tile "c", again to the north.
And yes, the exact track layout on those tiles is completely irrelevant, unless there are corners involved.
So, what about corners?Let's put a corner track on tile "h", sticking to our diagonal-cart example. First of all, if the corner doesn't "block" the direction in which the cart tries to leave the tile, it's again ignored. A NE or NW corner does nothing to the cart. So let's go with a SW corner. On step 3, the cart tries to leave the tile, crossing the northern border at 80/100 (going to /121). The corner prevents that. The cart now leaves to the west (on step three), to tile "g" - in the middle of the eastern border of that tile (emerging at 100/50 on tile "g" but using up the remaining distance units, reaching 79/50 at the end of the step), going straight west at 40 centitiles/step (put differently, at a speed of -40 on the W->E axis).
What happened? According to my tests, the corner is not modelled within the tile, the corner test takes place the moment the cart tries to leave. If the corner comes into play, the cart is "teleported" to the corner-dictated exit co-ordinate, which is the middle of the target tile's border. In addition, only the speed component in the direction the cart tried to leave is preserved, converted into movement in the new direction: in the example, northward speed is converted into westward speed, eastward speed is dropped. The speed conversion is more obvious when applying a corner to the "weaker" movement component: a NW corner on tile "e" would bend our cart to the north (it tries to leave east, eastern direction is blocked by the corner) - going at a speed of 15 centitiles/step: the 15 c/s eastward speed get converted, the previous 40 c/s northward speed disappear.
The corner only affects carts trying to leave towards the corner's two "blocked" directions. If our given diagonally-moving cart finds a SE corner on a tile it tries to leave to the east, it keeps its diagonal trajectory. The game doesn't check the northward movement component against the status of the northern tile border, it only checks the border the cart is actually trying to cross. In addition, a cart leaving to a diagonally adjacent tile isn't affected, either: a cart with the same starting location but moving 40n + 20e will leave tile "h" on the third step, as above, but with a target subcoordinate of 110/121, i.e. tile "f", northeast of "h". A corner, no matter how aligned, will have no effect.
More fun with sub-coordinatesThe exact location of a cart within the tile influences cart behaviour in various cases and is pretty persistent: a cart crashing into a wall will come to rest pretty much scraping on it. If it's again set in motion by rollers or a cart collision, this "hugging the wall" alignment persists and the smallest diagonal shift can push the cart across the border. Carts driving up blocked ramps and bouncing off the wall/blockage and rolling back down will keep their lateral sub-coordinate. Carts blocked from going around a corner will stop at the border they tried to cross, not at a location related to their corner exit:
Cart moves w->e, over a NW corner, but finds a door blocking the northern path. The cart doesn't stop at the northern, but rather at the eastern border of the tile. If it's subsequently pushed north by roller or other cart, the tiniest eastward push will move it to the next eastern tile.
All this also affects ramps to some degree - carts bouncing against walls and rolling off a lateral ramp, banging against a ceiling or other obstacle and the like. Corners on ramps have their own peculiarities, but they observe basic corner rules.
Dwarfs re-set carts to the centre of the tile when handling them. A push to the north basically teleports the cart to 50/50 on the next tile north (or 70/70 if that tile is a "full" ramp).
PPS: if a dwarf rides a cart, observable cart weight changes to that of the cart plus dwarf (including all worn items). Interestingly, the weight is not properly cleared after a ride. An empty wooden cart weighs 24 before a dwarf rides it, ~120 after. If another dwarf rides it, the new weight is properly calculated and carts revert to their proper empty weight eventually, but it usually takes a while.
EDIT -
a quick heads-up on ramps and pathing:I've treated ramp acceleration and several effects with them, but neglected the rules of carts pathing to different z-levels via ramps.
I strongly suspect that ramps are internally modelled as plain flat floor with a few extra rules. The sub-coordinates probably only use the two (x- and y-) dimensions, while "height" is _not_ tracked in this fashion when moving on ramps. Notably, gaining or losing speed on ramps is not done by converting a presumed intra-tile height into speed, there's simply an "accelerates toward <direction>" tag on full ramps, and such acceleration is simply applied to a cart as long as it is on the ramp.
Flippantly, we could claim that "impulse ramps" don't really exist (or that all ramps that provide acceleration are impulse ramps). Ramp acceleration just isn't connected to z-level changes.
When leaving a ramp tile, a cart may simply move on to an adjacent tile on the same z-level. This is fairly uncomplicated, it's rather like the normal way a cart moves from one tile to another.
A cart moves from a tracked tile to a
lower z-level if there's no solid floor in the direction it's going in, but rather a "downward ramp" (i.e. an open air tile with a ramp below it). If the tile the cart comes from is not track/bridge but plain floor (or e.g. a hatch over open space), a downward ramp will not be followed, the cart jumps instead. If the cart is moving at derail speed, it will not follow a downward ramp if it's coming from a flat track tile or bridge. It will follow the ramp if it comes from a full ramp (i.e. one that can accelerate carts).
The layout of the ramp on the lower level doesn't matter for the path choice. Carts path to properly connected track ramps just like they path to ramps with poorly fitting track or in fact non-track ramps.
Carts can also move _up_ z-levels, and moving up levels while on track seems to absolutely require ramps. It appears that the game engine checks in the direction the cart's trying to move in, and if there's a wall there on the same level but open floor on the level above, the cart may move to the upper level
if it's currently on a ramp that has a track connection in that compass direction. For that upward movement, only the existence of the track connection is required: a "dead end" track branch going North will allow carts to climb up to the north - and doesn't slow down the cart while it goes up. If the ramp has no track connection towards the potential way up, the game treats the direction as a solid wall and disregards the open floor on the upper level. A simple pit in the floor containing a track ramp with some "blank" direction:
..║..
..║.. ###
..▼.. #╩#
..║.. ###
..║..
z+0 z-1
can be passed freely in some directions, but not in all - in the shown example, a cart coming from south can pass, one from east or west will jump over the hole (don't come from track), a cart from the north would move into the hole and stop there. The cart's speed will also not change while going through this ramp, because the ramp provides no acceleration - it has no "down" connection.
These are just the basic rules; actual upward pathing occasionally throws odd errors. A "frictionless" upward slope consisting only of upward-connected ramps with no downward connections let a dwarf-pushed cart pass multiple levels (over 40), but a faster cart will fail to climb at some fairly early point (after six or so z-levels). It may be that the level changes are converted into "jumps" which at some point don't properly line up with the track underneath, but that's pure speculation for now. For single-z-level changes, the track connection rule holds up very well.
Abstract:Track ramps have two possible effects on carts: acceleration and movement between levels. Those two effects are completely separate - it's entirely possible to have level changes without speed changes and vice versa.
- to provide acceleration, a ramp must have at least one "up" track connection (to a wall) and exactly one "down" connection (to floor or a ramp on the same level or to a hole). Acceleration is a flat 4900 speed units per step towards the "down" direction.
- to allow downward level changes, any ramp works, but the tile from which a cart approaches the ramp must be track or a bridge.
- to allow upward level changes, the ramp must have track connection in the "up" direction (other track on the ramp is irrelevant for the purpose).
Carts will also enter lower z-levels by falling there and higher z-levels while on the ascending branch of a ballistic flight path, and can also enter different z-levels by being carried by dwarfs
PPPS: extremely minor datum - the cutoff for the "shotgun" effect (i.e. carts jettisoning their cargo upon collision) is somewhere between 55.000 and 56.000 speed. A cart going just faster than 5 tiles in 9 steps (i.e. there was the occasional 4 tiles in 7 steps interspersed) dropped its cargo upon hitting a wall, a cart going just slower (had exactly one more step on a medium-friction track stop, i.e. 500 speed less, so interspersing 6 tiles in 11 steps instead) didn't. I don't use DFHack, so couldn't measure speed with any higher precision; and tuning cart speed to within 500 of the actual cutoff is a bit of a production anyway.
Upshot is that one dwarven push and two ramps are _barely_ insufficient to get a shot. If you want any shot at all, you need three ramps (or a roller+ramp combo of some kind), if you want decent effect, you should go for high speed anyway - the faster the ammo goes, the more punch it delivers: momentum matters.