Range calculation

I’m currently working on a feature that will include range calculation on a hex grid. I’m sharing my work here in case it helps someone else and to invite improvement.

The key expression sits in a Calculated Property on the piece that is potentially going to need the range in hexes to another piece:

Math.max(Math.abs(CurrentY - oppMkr_CurrentY) / 75, Math.abs(CurrentX - (oppMkr_CurrentX + (Math.abs(CurrentY - oppMkr_CurrentY) / 75) * (oppMkr_CurrentX < CurrentX ? -44 : 44))) / 87)

The expression is designed for a sideways (“pointy-top”) hex grid of approx hex-size 75 x 87. Caveat: It has been tested on a small hex grid (9 x 11) where accuracy is only required in the range 1-6.

To explain the expression as best I can:

CurrentY / X are the coordinates of the centre of the hex where the piece in question sits.
oppMkr_CurrentY / X are the equivalent coordinates of the other piece*

Math.abs(CurrentY - oppMkr_CurrentY) / 75 …this component gives the distance for paths restricted to vertical steps on the hexgrid.

Math.abs(CurrentX - (oppMkr_CurrentX + (Math.abs(CurrentY - oppMkr_CurrentY) / 75) * (oppMkr_CurrentX < CurrentX ? -44 : 44))) / 87 …this component deals with paths restricted to horizontal steps but also the added complexity of a mixed path - here it is necessary to account for “half hex” x distance - an example being the distinction between the two blue pieces relative to the red piece below.

*This method relies on a new feature in Vassal v3.7 which allows oppMkr to be “attached”. This in turn allows Calculated Property to be used reliably. A different approach will be needed without that feature.


For further reading, there’s a comprehensive site by Red Blob Games that covers Hex grid maths.

Calculations such as my effort above are complicated on Vassal as the Regular Hex Grid provides only an offset coordinate system (as far as I can determine). A cube coordinates system, as explained on the site, would give much simpler formulae. Of course, one can convert between the coordinate systems but that comes with its own complexity and implementation challenges. I’d be interested to read about any other’s module work in this area.


This would be an awesome feature marktb1961. I am curious what method the existing “LOS/Range Finder” tool uses? Can not the code behind that be leveraged at all ?

1 Like

I will look into a range(x, y) function for Beanshell.


[quote=“Brent_Easton, post:4, topic:77035”]I
will look into a range(x, y) function for Beanshell.

Another nice feature to have would be an implementation of the A* algorithm. Given a grid - including knowledge of features - and other pieces of information - e.g. enemy ZOC, etc - it can calculate where a piece may move. Information could be handled via scripted call-backs in the module (e.g.,cost of moving from position one grid point to a neighbour grid point of a particular piece, where the target holds some number of pieces). Perhaps this is best done in VASSAL 4 since it seems scripting will be more integral there.

My two ¢


1 Like

My original post has been superceded by built-in Range functions now trialing in Vassal v3.7beta4.

A broad set of functions are available (see below). In particular, RangeInCells(x,y) has proved successful for me to replace the long and grid-specific formula that I presented earlier. Kudos and thanks to @Brent_Easton for delivering another great Vassal feature!


Seconded here. Still working through what this means for my World in Flames modules. Thus far it simplifies/removes a bunch of triggers and other traits. Have not run tests yet for workability, as the whole thing needs to be considered and dealt with. I do hope that using AoE with the new range equations will be great. So far, so good.