Property Match Expression

I have a game where there are leaders counters on the main map and leader mats on a private map.
The mats contain the combat units.
I’d like to sum the SPs of the combat units and show them on the leader.

I build a previous release of the game as few years ago with the old Sum function. It worked but was a bit sluggish. I ran the same module on a recent version of vassal and it worked much faster.

I am now rebuilding the module from scratch and would like to use the newer functions.

so I have a leader counter BasicName pd_leader_BELLGARDE

and a mat counter BasicName pd-mat-BELLGARDE

yes the - and _ are what they are.

I figured this should do the match

  SumMap("MATSP","{BasicName==$BasicName$.replace(\"_leader_\",\"-mat-\")}")

If I just do SumMap(“MATSP”,“AutoAOD”)
It sums just fine but for all the mats on that board.
So I am confident that it is the property match expression that is incorrect.

If I put this expression in a text label the name looks correct.

`{$BasicName$.replace("_leader_","-mat-")}`

I tried to add .trim() but it caused an expression error.

cheers
Gus

Check out this recent reply to a similar question. The technique outlines there should select based on current mat or current cargo.

If you want the leader counter on the privat window to know about properties of the leader counters on the main map, make those two counters Attachments one way or the other. I do something similar in Littoral Commander: Indo-Pacific: The unit counters on the main map are associated with a tracker card on another map. When the hit points on the tracker goes to zero, then both the counter on the main map and the tracker are eliminated. When the resource count of Long Range Strike (LRS) - for example - hits zero on the tracker card, it is no longer possible to declare LRS combat with the counter on the main map - and so on.

Yours,
Christian

Thanks Christian,

I had a look at the module.

I hardcoded a property LNAME and managed to match to it as an attachment and a SumMap using LNAME=“$LNAME$”

In practise though the easiest mapping is through the leader name.
And the leader name is part of the basicname. I am using nat-type-leadername for the basicnames.
In the end I asked copilot to give it a go… and it got it right first time.

SumMap("MATSP","AutoAOD","{BasicName == \\\"$BasicName$\\\".replace(\\\"_leader_\\\", \\\"-mat-\\\")}")

if only I asked a couple days ago :slight_smile:

Is there way to initialise markers or dynamic properties based on an expression?

I tried extracting the leadername to a calculated property but that creates an infinite loop and I then have to kill the JRE.

I have been really surprised how well copilot has worked and how VASSAL aware it was.

I didn’t know anything about graphics. It guided me through snipping the countersheet images, scaling the map, OCRing the counters to create a register and so on.

cheers
Gus

The benefit of using an Attachment trait, is that Vassal does not have to query every single piece on the map. Indead, it only needs to query the attached or attached to piece(s).

Actually not a very good suggestion. This will query all pieces on the map, which potentially can be a great deal, and will be relatively slow.

If your leader counter is indeed a Mat - and the units are Mat Cargo - then addressing the carried units with selection criteria

{CurrentMatID == $MatID$}

will be more efficent. If the carried units need to address the carrier (the mat), then the selection would be

{MatID == $CurrentMatID$}

Mat and Mat Cargo traits are - however - really only useful if the leader counter does indeed carry around other counters, and these counters may change their leader - or mat. You should of course use Mat based sum and count functions.

If carried counters are only ever associated with a single specific leader counter, then the Attachment trait is more suitable. You should of course use Attachment based sum and count functions.

“aware” is a funny adjective to use about a piece of mechanics that guesses most of the time :slight_smile:

Do you mean Marker and Dynamic Property - then no. The value stored by a Marker is by definition a constant. The same goes for the initial value of Dynamic Property.

What you can do is provide a command for Dynamic Property - say initLeader - which will set the property to its initial calculated value. You can then trigger that command by a Startup GKC.

Take a look at Tools for module developers which has a bunch of links to tools that are useful for module developers - including Script to make common operations on piece images

Yours,
Christian

There are two counters for each leader, a regular counter on the main map and a mat on the organisational chart. The mat holds all the units that a leader commands. The units are mat cargo.

Typically, each side has less than 20 leaders on the map and less than 40 counters on the org chart.

My previous version used the same number of counters. It has just older art and was hacked from another module.
but it runs very fast with the deprecated sum function in the recent versions of vassal.

I would prefer, though, to use the plain leadername as an attachment. But I haven’t figured out a way on how to get the leader names into a marker or into the attachment name automatically.
All up there are about 100 leaders and a100 mats to cover all the scenarios.

The only way I can think off is to export the leaders as an xml.Edit the names and the then delete and reimport.

At the moment I just have one prototype that covers all leaders from all sides.

I had a look at the shell script before but I don’t have a linux box at home.
It didn’t take long to snip the counters with copilot/imagemagick. I got stuck on the bevelling. so I’ll have another look at those later.

vassal-python and pywargame might be what I am looking for. Are they up to date? And widely used?

The one thing that was easier than expected was scanning all the counters with easyocr in python. It extracted all the horizontal text with perhaps 2 corrections in 500+ counters.

Having a counter register in excel made it easy to generate the mat images using pillow in python. I would love to use it to initialise marker or dynamic property traits for each counter.

True, I am still getting used to dealing with AI and how to describe it accurately. :upside_down_face:

cheers
Gus

Ah I just saw that pywargame is yours. :blush:

I would make the two leader counters of each leader Attached to each other so they can effectively communicate.

Some questions:

  • Are there counters for the units on the main map? If so, I would also make them Attached to their counter-parts on the org-map.
  • Can units change between leaders?
    • If not, then you can fix the leader Attachement of each unit - or possibly prototype - explicitly mentioning the leader Attachement name
    • If they can, then you can use Key Command to apply to all units ending movement on this map of the org-map (see Map Window) to discover which leader ( Mat) a unit is currently sitting on.

The name of an Attachement trait is not an expression, so you can only give it a constant value.

But, I think that you want is that

  • The pair of Leader counters are mutually Attached to each other.
  • If there are unit counters on the main map and on the org-map, then those pairs are also mutually Attached to each other.
  • The unit counters on the org-map are not Attached to the leaders on the org-map.
  • Instead, they are Mat Cargo, as the probably do not need to communicate with their leaders.
  • I don’t know what the status of vassal-python is.
  • pywargame is actively maintained - by yours truly. I have no idea how much it is used by other people. Personally I use it all the time, and I know of a hand-full of other people who are or have used it.

If you use pywargame you can keep the counter stats, etc., externally in some sort of database (a spreadsheet, JSON files, SQLite, …) and then read it via Python and then use pywargame to build - or patch - your counters.

If you have a MacOS machine, then you should be able to use the script too. If you are on Windows, you may have some luck with the so-called “PowerShell”. Alternatively, there’s Windows Subsystem for Linux - which will give you a almost full Linux installation.

The “Intelligence” part of AI is certainly a misnomer of epic proportions :slight_smile:

Yours,
Christian

That is a shame that would mean that we to hardcode all the attachment names. I had hoped the prototypes would be more flexible.

Your python module looks great. I am getting f-string expression part cannot include a backslash errors even on an empty vmod.
I am a bit of a python newby any idea what might be happening there?

cheers
Gus

Prototypes are directly substituted in when piece are built, and unfortunately they can not be parameterised - which would be kinda nice.

Thanks. I hope you will find it useful. Please let me know if you have any troubles, complaints, suggestions, etc.

Does the error come from pywargame or your code?

  • If the error comes from pywargame, then please make a new Issue at GitLab. There, just like here, you can use MarkDown to mark-up your text. Please provide the full error message and other relevant information and code. You may want to link to the issue from here so that others may easily find it.
  • If the error comes from your code, it is probably because you have something like
     s = f'blah blah {blah}\n'
    
    It should be
    s = f'blah blah {blah}'+'\n'
    

Hope that helps you.

Yours
Christian

Are you using a pre-3.12 version of Python? From Python 3.12 and on, the limitation on \ in f-strings has been lifted.

Yours,
Christian

Yes 3.11. I’ll bump it up.
Cheers
Gus

OK. Great.

If the problem was pywargame I would still like to see the error in a GitLab issue - so that I can fix it for backward compatibility.

Thanks.

Yours,
Christian

I’ll put something in GitLab.

It is supposed to look like this.
Each leader has a mat. The mat contains the combat units and subordinate leaders by the leader.

The total SP are summed per mat just using the SumMat. (blue number on mat and green number on leader).

The strength are passed from the mats to the leader counters using SumMap.

Leaders on the map can also belong to a multihex force.

The leaders on the main map belong to Force Red and have the force strength calculated using SumMap.

This way I just have 3 prototypes, Leaders, Mats and Units.

The only specific marker is the leader initiative used in a hidden init roll. I briefly thought of embedding the init in the image name to make it available through BasicName. But that didn’t feel quite right either.

I had a play with the attachment property but having to hard code all the names felt a bit painful.

It is such a shame that we can have expressions in Marker & Dynamic Property Initialisation & Attachment names. It would just be evaluated once on startup. But I am not familiar with the internal architecture and there is bound to be a good reason for it.

All the numbers are just text labels until I figure out how to do layered graphics like the GCACW counters.

Cheers
Gus

OK, so as far as I can tell, the individual units - say “Bajalich” are never present on the board - only their commander - say “Quasdanovich” - are represented on the main map. Is that correct?

However, a commander may also be sub-ordinate to another commander - say “Bellegarde” to “Quasdanovich”. Can the sub-ordinate commander be present on the main map too? That would complicate matters a bit.

How does the Commander pieces on your organisational chart (AutoAOD map) look like? Are they, for example for “Quasdanovich”, a piece that spans several rows and columns - like the gray area indicates?

OK, so that seems straight forward.

That, I don’t quite get. If the large gray piece “Quasdanovich” on “AutoAOD” has the property - say - TotalSP with value 9 - calculated using SumMat - then why would you need to do another calculation to get the same value on the main map? If the commander piece on the map - say “Quasdanovich” is Attached to the equivalent piece on the “AutoAOD”, it can simply get that value with GetAttachProperty. This is by far the most efficient way to do that.

Everytime you use something like SumMap your performance will suffer.

Note that there’s no reason to think that you couldn’t use a pieces name as its attachment name. E.g., the two pieces for the commander “Quasdanovich” - the map representation and the AutoAOD representation - could have the attachment “Quasdanovich”. Yes, you would need to add that trait to individual pieces and they cannot be in a prototype, but on the other hand, it is fairly straight-forward.

Of course, if you use pywargame, you can ensure proper reference in code :slight_smile:

How does the module make that assignment? Is it a user choice, or built in to the module. Again, it may make sense to make this a kind of mutual a
Attachement, depending on how long that assignment may last.

In most of the modules I’ve done, I have logic that allows the user to calculate combat odds. The user selects all belligerents of a combat, and then press a short-cut key, button, or select from the context menu. The module then sums up attacking and defending combat factors - possibly with modifiers due to terrain and features - and calculates the combat odds. An odds marker is then placed on one of the defending stacks and a combat marker placed on all belligerents. The user can then select the odds marker, press a short-cut key, button, or select a context menu item to resolve the combat. A combat result marker then replaces the combat odds marker. If this is something like what you want to do, you can check out one of the modules I’ve done.

How do you set the text labels? Be careful about setting them (directly or indirectly) by a calculation like SumMap - or similar. Every time the label has to be redrawn - which happens relatively often - the expression has to be reevaluated which can potentially be costly. That also applies to Layer trait with Levels follow expression value.

If you use a Dynamic Property - rather than a Calculated Property - to store the calculation in, then a new value will only be calculated on a specific request - for example when a piece is removed from or added to the “AutoAOD” commander piece mat, or when commanders are attached to or detached from a task force on the main map.

Yours,
Christian