At this point, I'm going to be totally off the wall, because:
- A - I've not actually studied the theory behind this, so I can't draw upon great reserves of prior knowledge,
- B - Those that have have probably spent a lot of time fine-tuning the known methods using a lot of effort that I couldn't even hope to equal,
- C - I've had this idea for a while (back at least to original Doom days), meaning to apply it to a vectorised 'Levels Of Detail' environment of my own conceit, and a rasterised one can always be boiled down into a particularly limited (and ragged) vector environment, so there should be some crossover available.
Of course, combine A, B and C (especially the time-scale of the latter) and I'm probably not innovative at all. Apologies if it's a tried and tested and possiby rejected method. From what I've already read in this thread, I recognise some of the features, or at least related ideas.
Ultimately every cell (a.k. tile) is a box (or square, in 2D) with access or not to each of its neighbours. Multiple modes of travel mean multiple types of access to neighbours or not (ground-only, water-only, amphibian, aerial and (especially for DF) additional magma-tolerent, pet-passable, climbing/jumping access and 'tunellable' options), but for now we'll ignore that. A cell has access or not to its neighbours, and not necessarily bi-directionally if so.
The idea is to group cells together into hierarchies of "free travel zones" that at each level act like cells in and of themselves, and that a 'travel request' is passed up to the first 'uber-zone' level containing both source and destination, and thus able to coarsely guide the travel between its subzones.
A binary tree would seem to be the obvious (or at least grouping in 2^n squares/cubes of cells) but, including diagonal transits, there are eight potential 2D and twenty-six potential 3D exits to a cell, which is 3
d - 1, so consider reflecting this structure. The first-level zoning is a trinary grouping of cells.
...
...
...
The possibility of transit (and prefered routing, if so) between any two cells in this grid would be simply maintained based upon the relevent border-passing information.
Then group first-level trinaries into second-level trinaries:
+-+-+-+ :::::::
|.|.|.| :.:.:.:
+-+-+-+ :::::::
|.|.|.| or alternately notated as :.:.:.:
+-+-+-+ :::::::
|.|.|.| :.:.:.:
+-+-+-+ :::::::
Note, for later, that in the second notation (where ":" indicates a shared border, and thus representation in multiple sub-trinaries), 7
2 cells have 105 'records' (83 if the external borders of that particular grouping don't actually go anywhere, and if I've added it up right), so obviously a large data overhead at this stage, and greater and greater the more levels we go up... So, how do we sort that out?
By merging these most basic of zones into their parents, insofar as we can create "convex" zones of arbitrary size. i.e. where all routes across a zone can be simplified to simple staggered 'across-by-N, sideways-by-1' line steps (at least at the level where a zone encompasses individual tiles). Absorb multipe leaf zones (tiles) into their parents first-level zone (to become a 'leaf' in their own right) such that the entity remains convex (remember that this was originally for a vector-based environment). In this case, convex means that from any particular tile to any other tile within the boundaries of the zone is a staggered line (actually a straight then a diagonal side-step, rather than a straight then a perpendicularly-straight sidestep) that does not cross the border, e.g.:
............
......----+.
.+----....|.
.|........|.
.+........|.
..\......|..
...+--...|..
......---+..
O...........
Where the "+" parts are limiting features that contain the zone (are not, in themselves, passable), and the straight lines (of whatever kind) are representative of the line-of-appropriate-stagger between the limiting features that forms the boundary to the zone. Which are, as with the second-level trinary diagram, shared (at least theoretically) with neighbouring zones. To maintain the validity of being totally convex, wholely contained paths from not-offically-a-corner tiles, like that border tile at (6,7) relative to the marked 'O'rigin, are allowed to start their stagger on a diagonal before continuing in the required pattern cycle. If (5,6) was also a limiting obstacle, then it could not be convex, and the absorbtion of sub-zones would have stopped at the point where two different convex sub-zones could not be merged into a single 'convexity', e.g.
............
........--+.
.+---+--..|.
.|....\...|.
.+.....|..|.
..\....|.|..
...+--..\|..
......---+..
O...........
(BTW, current pathing doesn't tend to use nice 'staggered' straight-line across a field of play, from my observations, but will use orthagonals and diagonals in such a way as to have a long 45-degree diagonal for part of the leg with an orthagonal for the other, for any journey across open ground that cannot be purely by one or the other. This is no longer than a 'proper' diagonal on a grid, but looks more unnatural. I'd prefer the engine to take a necessary displacement of 20 east and 5 north and turn it into (3e,1ne)*5 rather than (15e,5ne). Obviously this can be changed variations like 2e,1ne,(3e,1ne)*4,1e or (1ne,3e)*5 if obstacles along the way require such fudging to avoid individual obstacles and yet maintain such a stagger, or just randomly where all paths are as likely, meaning an almost anti-aliased look to the line, when superpositioning all possibilities, looking at relative 'footstep-frequency' along the way.
So, how to apply this.... One of DFs flat plains (or at least one that is undulating but ramp-enabled, if we introduce that fudge for surface travel) with no obstacles would find itself defined as a simple leaf-zone, constrained by only by such things as the edges of river gorges, the intrusion of a constructed defensive wall or certain key trees along the the edge of a forested area. From a few key locations, travel across that plain would be a matter of "Am I within the bounds of this free-travel area? Yes? Then let's plot an appropriate stagger across it!" Simple routing at very little cost.
If an orthagonal channel was dug across the plain, leaving a gap (of arbitrary size), then this would be two adjoining leaf-zones, sharing up to three 'borders', as defined by two channel terminations (between them is a passable border) and the two points on the edge extermities of the channel serving as limiting features (between which and the inner channel termination is a non-passable border). The channelling may perversely 'open up' an expanse of plain that could not have been included in the original convex area, for whatever reason, but is a valid inclusion to increases the size of one or both of the spliced-off areas, while maintaining a convex nature. But when it comes to travel across the plain, requiring navigation through the gap that was left, the superzone that might-have-been the result of the smaller zones merged into it understands that routing from anywhere within the first leaf-zone to anywhere within the second leaf-zone means traversing the border. As such, a stagger-path needs to be plotted from A (within the first leaf-zone) towards 'B' (upon the passable border between the two leaf-zones) and then a new stagger onwards to C (within the second leaf-zone). If there is only one tile of channel-gap forming the border, then B is obvious. If the border is wider (whether that be two, ten or thirty eight tiles in width) then some intelligent guesswork can be used to work out where to aim at. e.g. calculating the intersection of the line defines the passable border with the one that defines the direct trip from A to C, and chose the point nearest that intersection, or the end nearest it if the boundary forces a dog-leg.
If a series of channels are dug across the plain (or any other obstacle, such as arbitrarily placed pillars), then the leaf-zones could find themselves sharing a number of passable-borders. Again, calculate the intersection of A->C with each passable border. Whichever border has the best 'bid' (cuts across A->C, or has the closest border-end to the point beyond the segment where it would have done) gets to have 'B' upon it.
Scale that up accordingly. In an area with trees, the convex leaf-zones would be more numerous, giving the increased number of limiting features (OTOH, there more of the borders would be fully passable, unless significantly numbers of limiting features sat side-by-side). Travel between A and C would probably require passage across not only multiple leaf-zones, but multiple zones of the level above (being formed of convex groups
of convex groups of tiles, BTW), perhaps more levels above that. But once the level of overview increases so that A and C are contained within a single zone of that level, routing can begin. This level knows which borders are open, and which are not, between immediate sub-level zones it commands, and performs an A->B->C calculation accordingly. Then the A->B calculation is passed to the zone containing A and (on the border), B. If this is a leaf-zone, all very well, otherwise the A->B is treated as A->C
B and a new B
A->B worked out to sit between them. Ditto any A
B->B
B->C->C that is necessary. And down the tree of zones we go, as far as necessary.
Definite issues:
- - I'm not sure travel weighting could be reinforced well enough. A path between adjacent leaf zones that has a heavy expense that's still light enough for travel between near-adjacent cells could propogate it's 'usefulness' up through the zone hierarchy. At some point, though, there could be a source and destination where the appropriate zone level to contain them both brings up this choke-point as a 'win', where the two termini are both near the edges and actual best path involes a trip outside of that zone (as a simple example, imagine a large "R"estricted travel designation, where corner-to-corner travel (including opposing corners, but especially when not) would be best taken by exiting the zone at adjacent exits and wandering along a path outside the perimiter and then entering again). A fact that the next zone level up might or might not 'know', if interrogated, given that it contains the source/destination zone and those adjacent zones that allow the detour. But it would never be consulted about this without some sort of additional notation propogated down.
- - There's a 'parity'or displacement of zoning that must be addressed. Why is a certain initial level of zoning
[/li][/list]
+-+-+-+ -+-+-+- |.|.|.| .|.|.|.
|.|.|.| .|.|.|. +-+-+-+ -+-+-+-
+-+-+-+ -+-+-+- |.|.|.| .|.|.|.
|.|.|.| when it could be .|.|.|. or +-+-+-+ or even -+-+-+-
+-+-+-+ -+-+-+- |.|.|.| .|.|.|.
|.|.|.| .|.|.|. +-+-+-+ -+-+-+-
+-+-+-+ -+-+-+- |.|.|.| .|.|.|.
, when laid out over any particular grouping of 7x7 cells? Similarly, there is no 'one' way to place convex spaces upon a feature-limited area, though undoubtedly there are better ways than others. (If having to split an existing convex space due to the introduction of a limiting feature within it, then I would aim at selecting the option where the additional border length is as minimal as possible, to avoid creating long and thin parallel zones that are far less likely to require purely internal pathing than inter-zone pathing. The same philosophy when merging suitable leafs into larger ones (or creating cumulative zones out of 'optimised' ones of the level below) would probably be how I would go.)
- - For multiple modes of travel, the choice appears to be: 1) give each border a passability flag according to the different (ground, water, amphibious, etc) modes of travel, but put up with some limiting features (e.g. ponds and rivers) not actually needing to limiting features for a whole skein of possible travellers, or 2) build up totally separate zone-trees for each situation.
I rather think the latter would be best. Aerial creatures, innate swimmers in multi-Z water-bodies and diggers who can tunnel through rock (at some small expense of effort?) would not actually need different zoning algorithms from one that can handle Z-travel by surface-routers through treating the 'open borders' between levels that are ramps and stairs (and even climbing/plummeting opportunities, if forced to) as mere 'pinch-points' in a 3D-convex definition, but considering how much open air, ocean or unmined rock could be a convex routing container for the appropriate creatures, it would seem rather less efficient to constrain them to 'traditional' layers of 2D convex boundaries and have to calculate 3D stagger intersections with the Z-boundaries as well.
- - None of this addresses transient open/closed border situations. e.g. the bridge that might be raised/lowered though is currently lowered/raised, the door that is or is not pet-passable but could be inadvertently left open or the freezable river survace, but allowing boundaries to maintain boundary information between upper levels of zones to contain "boundary open if[/if] <some season/bridge/door-status>" information and maintain one (or more) alternate route would probably mean