How to manage counts of pieces and reporting of movement


Suppose you have army units, each of which have has a different value. Further the map is divided into a number of zones and there are two sides Argies and Britties. For each zone you need to know the total value of the Argies and Britties respectively. Ideally for each zone X you would have two properties ArgiesX and BrittiesX.

Or for an actual example in Module:Tigris & Euphrates, each player has five scores Red, Blue, Green, Black and Treasure. You want to track how many of each type of point each player has in their private window.

In this HowTo we will work through the first example focusing on one particular property. The T&E example is similar, with the main difference being that Maps (i.e. the player hands) are used rather than Zones. We will also discuss how best to do reporting.

Set up the properties

We assume that you already have the Main Map, the Zones. You will need to set up the properties.


Each piece will need a marker indicating it’s strength.

For some modules you will want to display the properties on the board as shown in the example above. Or else you may need this initially for debugging purposes.

Tracking Piece Movements

The key step is that when a piece moves it receives a hot key, off which we can hang other processing. Set “Key Command to apply to all units ending movement on this map” in your Windows in the module. You cannot guess where users may send their pieces, so apply this command on ALL your windows: Map Windows, Private Windows, Player Hands etc.

The idea is that we use pairs of properties such as CurrentZone/OldZone or CurrentMap/OldMap to work out whether the piece has moved into or out of the area of interest. (Note: A previous version of this page recommended against using the “Old…” properties. However this advice related to a bug that had been fixed years ago.)

Set up the change property traits

Everything that follows on this page will be a trait in pieces and so ideally belongs in a Game Piece Prototype. For each property/zone combination we need an increment and decrement key command. Add the appropriate Set Global Property traits to the prototype to create corresponding “inc…” and “dec…” key commands.

Set up Triggers

To connect all this together we need to create triggers that increment the relevant property when the piece has moved into the relevant zone; and a corresponding trigger to decrement the relevant property when the piece has moved out of the relevant zone.

Additional programming for Delete commands

If you want to be able to delete pieces you should create the right-click menu option in a Trigger trait. The big gotcha is that you must make sure that you do any necessary housekeeping on the piece before the actual delete. Otherwise all the processing will be lost.

In the above picture, the actual delete is done by the “ultdel” key command and all the previous key commands are the housekeeping. The “ultdel” command is defined by the actual Delete trait.


In this example the Trigger was defined specifically for the Argies pieces. We need to call a key command for each zone that the Argy piece may have been deleted from: “beforeDelAA”, “beforeDelAB” and “beforeDelAC”. These traits check if the CurrentZone proerty matches that the key command is handling; if it is the corresponding count property is decremented.

Additional programming for reporting

A lot of these techniques can be adapted to report movement to chat. This can be important to clarify what a player is doing. (Be careful however. Some people feel reporting can be overdone and annoying.) Often it makes sense to make the reporting totally generic and put it in a “reporting” prototype that is used by most or all objects in the module.

The key part of the prototype is a Report Action trait that listens to the “onmove” key command discussed above. I like to have it report something like: “$PlayerSide$ moved $BasicName$ from $OldLocationName$ to $LocationName$.” However the $PlayerSide$ property only works if the game defines Sides and accordingly the VASSAL default does not use $PlayerSide$. Secondly it often happens that the $LocationName$ and $OldLocationName$ properties do not quite return what is desired.

If these properties do not yield the desired values the first thing to check is the Location Format field in the relevant zone definition. By default this would be “$name$”. However if you want the LocationName property to be a grid reference you must set this field to “$gridLocation$” or perhaps some combination of the two.


Sometimes however $LocationName$ and $OldLocationName$ still do not yield the required values. Sometimes I defined Calculated Properties in terms of $LocationName$ and $OldLocationName$ and use those instead.

In the section on handling delete, you may notice that one of the pre-deletion housekeeping key commands was “report_delete”. This should have a similar format to your main movement Report Action trait but will have a message like “$PlayerSide$ deleted $BasicName$ at $LocationName$.” Note that we need to use $LocationName$ not $OldLocationName$.

Things to think about

Remember that this is just how I tend to do modules. Maybe you can think of improvements or issues. Look at how other modules do it. Would this method scale? Do you have more scalable alternatives?

Test module

Here is test module with example of our engine.

Filename Filetype Size Date Compatibility
HowToSum_v1.0.vmod module 5 KB 2022-05-02 3.6.5