Help with CountLocation

I noticed the CountLocation function in the expression builder and tried using it, but unfortunately without success.

Regrettably, I am unable to use the expression builder effectively, as the required BeanShell syntax is completely unintelligible to me—it might as well be written in Arabic.

What I want to do is count the number of units of a specific type within a given hex.
The hex is specified by the global property “TargetHex,” and the condition to be met is “Type = Flak.”

After an endless series of attempts using various syntaxes, I gave up and saw no other option but to ask for guidance on the forum.

I would like to thank anyone who can offer assistance in advance.

P.S. I am still looking for a tutorial on using BeanShell.

Panther_2010

:joy:

The function CountLocation has a number of different prototypes (calling conventions). Some count pieces in the same location as the calling piece, while others count in a specified location. See the linked documentation page for more.

You have 4 different calling sequences to choose from

CountLocation(location, map)
CountLocation(location, map, prop)
CountLocation(location, map, expr)
CountLocation(location, map, prop, expr)

What you want, is the third one. If the global property that holds the location name is TargetHex (which contains a string value), and the map is named Map, and the counted piece property Type must be the string value "Flak", then you would do

CountLocation(TargetHex, "Map", "{Type==\"Flak\"}")

Note that

  • The map name must be specified. You can pass the property CurrentMap to use the name of the map the calling piece is on.
  • The string value "Flak" must have the quote marks " quoted.
  • The expression must be in a string
  • Testing for equality is done by the operator == (= is an assignment)
  • If your grid location may start with a 0, then to match - say - against 0123, you may need to remove leading zeros, or enable the option to maintain leading zeros.

General documenation on BeanShell can be found here. Note that Vassal’s use of BeanShell is relatively limited. The expresssion you write in are wrapped in the equivalent of

Object function() {
    return <your expression>;
}

which means you can only write simple expression and not more complicated loops, conditionals, etc.

Yours,
Christian

Hi Christian,
Many thanks for your invaluable help.

Everything is working now. You’re my hero! :partying_face:

Before posting my request on the forum, I had tried the following syntax: CountLocation(TargetHex,CurrentMap,Type == “Flak”), but it kept returning 0 as the result.

I’d appreciate some more information regarding the use of \ " within the string expression, as I’d like to better understand how to use it in the future.

Yes, I’m well aware that using complex expressions in BeanShell should be avoided—I’ve tried it in the past with disastrous results.

However, through experimentation, I discovered that it is possible to use many functions from Java’s Math class within BeanShell, which I found very useful.

Thanks also for the link to the Reference Manual (which I had lost) and the BeanShell documentation—though, unfortunately, I find the latter quite difficult to grasp given my current level of knowledge.

All the best,

Panther_2010

:star_struck:

The point of escaping the quote " with a backslash \, is that otherwise the BeanShell interpreter would parse the string incorrectly.

Consider the correct way first

"Type == \"Flak\"" 

Our goal is to compare the value of the property (or variable) Type, with the constant string value "Flak". To make a string value, we have to quote the value with "s.

That is, to find a string, the interpreter identifies the first quote ", and then looks for a matching quote " which is not escaped. That is, the interpreter will not consider a \" as an ending quote.

Now, in the call to CountLocation, the third argument must be a string, so we must pass the string value in quotes ". Under the hood, the string value - in this case, Type == "Flak" is passed to the BeanShell interpreter, which then evaluates it - i.e., compares the variable Type’s value to the constant string value "Flak".

Note, in the string that the interpreter evalutes, the backslash escapes (\) have been removed.

Now let us consider the incorrect way

"Type == "Flak""

The interpreter sees the first quote " (the one before the T), and then reads along until it finds another - non-escaped - quote, which will be the " just before the F. Thus, the interpreter sees the string value Type ==. Then the interpreter sees Flak, which represents nothing in this context, and then it sees a starting " immediately followed by an ending quote ", thus forming the empty string value. Thus, the interpreter ends up evaluating Type == - which is not legal, and so no piece matches that expression, and you get 0.

The BeanShell reference manual isn’t the most pedagogical of texts. It is clearly written for someone who has a bit of knowledge about programming in the first place.

There are not many other good resources on BeanShell out there - a testament to how little BeanShell is used.

In fact, you can use many of the Java static member functions - including static string member functions, array operations, and so on. The interpreter knows most of the standard Java, and you can often construct an object of a type to do even more. The main limitation is that the expression must be valid between a return and a ;.

Yours,
Christian

Backslashes are widely used for escaping characters which would otherwise have special meaning inside strings. E.g., for a double-quoted string to contain a literal double quote, you must escape that double quote with a backslash. Similarly, for a double-quoted string to contain a literal backslash, you must escape that backslash with a backslash. Those are the two cases you’re likely to encounter.

To get the string foo"bar\baz, you have to write "foo\"bar\\baz".

Great!
Many thanks to Christian and uckelman!!
This is exactly what I was looking for, and it explains why many of my attempts to use BeanShell were bound to fail miserably. I wasn’t aware of using \" to avoid the issue with double quotes.
Panther_2010

:sweat_smile:

Please remember to tick off the problem as solved - that really helps other find the solution to their problem. Only you, as OP, can do that.

Yours,
Christian