TL;DR: Automatic tracing of supply lines is not really possible, or at least highly impractical, with current VASSAL
Let’s assume a traditional hex’n’counter wargame.
To trace supply lines, the module and VASSAL must be aware of
- all terrain and features of all hexes
- all locations of all counters (units, installations, etc.)
- “ownership” of all hexes - e.g., which factions unit last passed through or occupied a hex
- possibly roads, railways, rivers, and such
- possibly the movement factors (MF) of all units
Then, the module must be able to calculate a route from any given unit to a supply source (board edge, rail road leading to board edge, city, town, supply installation, and so on). This could involve tracing such a line that does not pass through enemy ZOC or similar. The most effective way to trace such a route would be to use an A* algorithm where the cost of of moving from one hex to another would depend on
- Terrain and features, including roads, railways, etc.
- Presence of enemy or friendly units or ZOC
- The units MFs
Currently, VASSAL does not track a counters location - the only way to get the location of a counter is to ask it - that is, the module will have to query all counters where it is (LocationName
) to check if a counter is in a given hex. One could possibly use the Board
attribute Key Command to apply to all units ending movement on this map to record unit locations in some GlobalPropery
Also, VASSAL has no notion of the terrain or features of a hex. The module designer would have to encode that somehow. This is doable. For example, one can have a GlobalProperty
called Woods
which contains a list - say :A1:C5:F6:...:Z3:
and CalculatedProperty
InWoods
as
Woods.contains(LocationName)
Furthermore, when a faction moves a unit, VASSAL only records from which hex to which hex that unit moves, and does not record any intermittent hexes passed through. That means that control of a hex is not easily recorded by VASSAL, since VASSAL has no idea about which hexes a unit passed through.
Looking a head, how could VASSAL possibly accommodate this. Well, to me, the best option seems to be to create a number of call backs and better tracking of counter positions. For example.
- A user selects a counter. This triggers VASSAL to try to calculate possible moves by that counter using an A* algorithm.
- VASSAL asks the module for the MF cost of a counter to move from one hex to another. The request sent to the module will contain
- which unit is moving so that the module can differentiate between for example mechanised or infantry movement
- which hex is the unit moving from (not the original hex, but the current hex in the path traced),
or possibly the full current candidate path
- which other units are present in the candidate hex
- It is up to the module to look up
- terrain and features of the candidate and source hexes
- MF of the moved unit
- possible enemy ZOC in candidate hex
- The module then reports back a “cost”, which could be the real MF cost or possibly just a 0 if the module can track the MFs spend (this part requires a bit of thinking)
- The A* star algorithm then either accepts of rejects the current path
- The A* start algorithm maps all possible paths until there is no more viable paths as determined by te module call-back
- Once the paths are determined then they are displayed by VASSAL to the user which then can select between these paths (again, requires a bit of thought).
- The selected path is then sent to the module which can then record ownership of the hexes the unit moves through.
A similar approach can be used for tracing supply lines or lines of sight, although there one would start from the target hex (or hexes) and work ones way backward toward the source counter.
Ideally, VASSAL would allow a module to record units on the map and which hex they are in and “user defined” properties - e.g.,
class Board
Hex getHex(column,row)
List<Hex> getNeighbors(Hex)
...
class Hex
addPiece(Piece)
removePiece(Piece)
List<Piece> getPieces()
...
setProperty(Name,Value)
getProperty(Name)
List<Property> getProperties()
...
addEdgeProperty(Edge,Name,Value)
getEdgeProperty(Edge,Name)
List<Property> getEdgeProperties(Edge)
...
User properties could then record ownership, terrain, features, roads (edges), etc.
With this in place, it would be possible to define modules that enforce game rules much easier than it currently is. For example, one could
- query if pieces are really adjacent and thus can conduct combat
- query offensive and defensive terrain and possible intermittent terrain
- restrict movements to what the game allows
- record owner ship
- … and much more
To a large extent it hinges on VASSAL doing in far more call-backs to the module, using A* to present “movement” (or trace) options, and allowing for more module defined recording so that queries can be optimised.
Anyway, my 2¢
Yours,
Christian