GKC Trait Matching Properties not working

I have a Piece level GKC Trait in a Prototype that has a Matching Properties expression that is not working no matter what I do. It seems very straightforward and actually matches precisely the example provided on Page 48 of the Designer’s Guide. I have a Marker named Power above the GKC Trait in the Piece and Markers named Power in all the GKC targets. It always evaluates the expression {Power==$Power$} as true no matter what the value of the target Marker is. So if Power=Germany for the Active Piece, the GKC triggers on every target, whether Power equals “Germany”, “Italy”, “China”, or anything. The nutty thing is when I change the expression to {Power==“Germany”}, it works fine. So what I’ve done is taken the GKC out of the Prototype and specified that target Power manually for every single Piece. But it’s driving my nuts why I can’t get this to work using the Prototype…

You need to understand the difference between the old classic syntax and the beanshell syntax. Stop doing this: {Power==$Power$}. It mixes beanshell and classic syntax in a beanshell expression. In classic, Power is a string, and $Power$ dereferences a property to its value (e.g. “Germany”). In beanshell, Power is a property that is dereferenced, and $Power$ should either be seen as a property, $ included, or it should create an error because beanshell doesn’t really know what to do with those $. Brent probably added code have beanshell understand, but I think that was a mistake.

How does vassal know when to use classic vs beanshell? These: { }. That’s beanshell. You want classic? Don’t use them.

So what you are saying with this {Power == $Power$} is: test if the contents of Power equal the contents of Power. Of course it’s true all the time!

I suspect your problems stem from a scope misunderstanding, but you don’t provide enough information about how Power is defined to unravel this. Just understand this: when a piece makes a test, it’s using properties AS IT SEES THEM, and it doesn’t matter if stuff is in a prototype or not. There is a great temptation to think you are passing or referencing a property the caller sees, but that’s not the case. You can’t pass arguments to a piece like you can in a function call. You CAN do it, but you must put the value in a global property that has a different name than Power.

Thanks. That is helpful. I didn’t know that $ was deprecated by beanshell. There is no mention of beanshall at all in the Designer’s Guide so I’m sort of stumbling blind and learning by trial and error and asking frequent questions here. Is there some document that describes beanshell in detail?

It’s definitely not an issue with scope because it evaluates correctly when I enter an expression with a fixed value i.e. Power=“Germany”. It’s just a matter of syntax. I can’t figure out the correct syntax for the comparison =. “Power” is Marker defined for all Pieces involved.

OK. I got it working. Again the misunderstanding on my part is not knowing where certain syntax applies or does not apply. I had originally written: {Name==“Income”&&Power==$Power$}, which failed. Then I tried:

{Name==“Income”&&Power==Power}
{Name==“Income”&&Power==GetProperty(Power)}
{Name==“Income”&&Power==GetProperty($Power$)}
Name=“Income”&&Power=$Power$
Name=“Income”&&Power=Power
Name=“Income”&&Power=GetProperty(Power)
Name=“Income”&&Power=GetProperty($Power$)

Some of those were absurd, I know, but I was pulling my hair out. Turns out the issue is that beanshell wants quotations, classic doesn’t. This worked:

Name=Income&&Power=$Power$.

Quick rule of thumb is that any time you’re inside a { } then you should not use $ $.

After wasting hours on something that usually takes me seconds, that is crystal clear now. What about the quotations? My understanding is quotations denote a value, no quotations denote an expression. That’s programming 101, but it’s not always the case here apparently.

About classic:
It’s all about string concatenation and deranged operator notation, e.g. “=” means “test if equal.” Forget about integer arithmetic or even arithmetic operators. When you type Power, it means “Power” in classic. Want to get a property value? Enclose it in $ like this $Power$.

About beanshell:
The world is your oyster, so to speak, and I think thanks to Brent. Forget all about the classic crap. It’s more like real programming. “==”, not “=”. In beanshell, if you write Power, beanshell sees a property and gets its value. Want it as a string? Enclose it as double quotes. For example if country is a property containing “Greenland”, then {"I live in " + country} creates “I live in Greenland”. If a property can be translated to a number, then beanshell and vassal will do integer arithmetic for you.
For example, debt = cash - spent will compute a number if cash and spent are numeric properties.

In addition, in beanshell you can use a limited set of functions. See the Alert() function I talked about in another thread. You can have popup windows. Getproperty if you want to if the value of a property is a property and you want to get its value. Note to Brent if you are watching: could you add a random integer method and slip it into 3.3? Pretty please?

You will also see the “If” method. It is powerful and essential – and now deprecated. To everyone who is watching, "If’ can fail at times. (See the Alert discussion.) Instead, use the “?:” operator. For example, I want to set the property ‘thing’ to -10 if ‘elevation’ is negative and +10 if it is 0 or positive. I would write (in various property commands) thing = (elevation < 0)? -10 : 10

Beanshell also provides a bunch of other functions such as Math functions (random, round, et al) plus others no one has discovered yet.

In short, don’t use the classic method unless you absolutely have to. If you mix it up, you’ll be sorry and confused.

Q: When can I use beanshell, and how can I tell when I can’t?
In vassal, beanshell is almost everywhere. If you look just to the right of an field and see what looks like a microscopic calculator, it means you can use beanshell. Press the calculator, and it opens the beanshell expression builder. As you type, you will see either a red x or green check, which tells you if your syntax is very roughly correct. When you close the builder, your expression will be enclosed in curly braces. Those braces tells vassal you are astutely using beanshell, and it now sees you with some respect. Maybe it won’t core dump on you anymore. Maybe.

The only places you won’t see the micro-calculator is when vassal wants a printable string. Places where in a programming language you would use printf or format statements. In vassal, it’s always in reports and in the text trait. In those cases, you are building strings, and you must use the $$ to de-reference properties. (I wish it used a printf syntax, but so it goes.)

Been there. Part of the “steep onramp” for Vassal is comprehending the mix of legacy expressions and beanshell expressions, especially insituations where both are supported.

Inside { } i.e. beanshell, quotations mean what’s inside is a literal string value. In non-beanshell (old-style Vassal, where you might see some $ $) you never use quotes AFAIK, but there are some left-side / right-side exceptions that are special.

So one thing that’s now pretty hard and fast for me – if field I’m typing in using supports using Beanshell (e.g. the { } expressions), then I always use that. Because it’s more sane, more like programming, mostly supports more, etc, etc.

Alas there are plenty of e.g. text display fields where one is still limited to $ $ but that’s the only place I use them.

I would definitely be in favor of Vassal 4 enforcing eradication of most/all of the old-style stuff when one “upconverts” a module, converting it all to “Beanshell” (or whatever it is that corresponds to Beanshell). Substitution in text lines may be the steepest climb.

Brian

p.s. EDIT - I see shilinksi and I posted at the same time, and w/ the same general conclusion: INSIDE THE { } LIES SANITY! OUTSIDE, MADNESS!

You reminded me of some things in classic that I’ve forgotten that I almost never use it anymore. If I recall, you can write an expression to be evaluated as true or false like this: Power=Germany. It will treat ‘Power’ as a property if it is on the left side of the single ‘=’ and ‘Germany’ as a string. If ‘Germany’ were a property, you’d have to write $Germany$.

I know for a fact that Vassal judges you by how you write your code. It’s built into the code. If you use classic when you don’t have to, it thinks little of you as a person. Watch out if it every becomes sentient and can talk. Trust me; this is all true.

Excellent summary by Shilinksi.

Think Beanshell = Java. Whatever is written inside a {} is executed as if it is Java Code. If something looks like a Java variable, then it will be bound to the value of the corresponding Vassal property based on the piece it is being executed against.. All unbound variables in the Beanshell expression are bound to the property values from the same piece at the same time.

If a Beanshell expression contains $xxxxx$ expressions, then these will be stripped out and replaced by the corresponding Vassal property on piece or component that is generating the expression before the Beanshell expression is evaluated. Think of it like a pre-processor macro expansion.

The need to include the $xxxx$ expressions is for Global Key Commands where the expression is generated by one piece, but executed against another piece. The $xxxx$ expressions allows a limited type of parameter passing that would otherwise be very clunky to implement.

So, assuming a piece issuing a GKC belongs to Germany, {Power=="$Power$} in the matching expression gets changed to {Power==“Germany”} before being checked against the Target pieces. The target pieces are checking their Power against the Power of the piece that issued Matching expression. {Power==GetProperty(“Power”)} will always return true because this is being executed on the target pieces, so it is comparing the target pieces Power to its own Power).

The Classic syntax is a very different beast. It assumes anything on the left side of a comparison is the name of the property and anything on the right side of the comparison is a string value without quotes. It uses ‘=’ instead of ‘==’, does not support () and using and (&&) and or (||) does not not follow proper operator precedence. The $xxxxx$ expansion works in the same way though.

I did NOT realize that $$ could work in GKC filters that way! Key useful tidbit!

A GKC Manual update has been added to my 3.3 fix-up list.

You know, I sort of wonder if as of Vassal 4, the whole “manual” should really be a Wiki “and nowhere else” – a centralized spot that can also evolve as people have time to improve and edit it.

Brian

The problem was that a not insignificant number of people where using Vassal offline and we needed the reference manual built in. Now, the manual pages are just (braindead) HTML, and the same pages could be built into a Website. Someone looked into this, but it ended up being too difficult to incorporate the same pages into the wiki so this didn’t go anywhere.

It would be great if we could work out some way of having one source for the reference manual pages that could be used for both Vassal internally and also accessible from the web.

Guys, all the responses on this thread have been super helpful and really gave me some clarity. Thanks! I’m starting to see the big picture now. I realized my mistake was treating the outdated Designer’s Guide as a bible. I always started with beanshell but if it didn’t work, I’d rely on the DG for guidance so I’d inevitably start mixing classic with beanshell. I’m going to purge it from my hard drive ;-)

So when I parse what has been explained in this thread, my conclusion is that the classic expression:

BasicName=Income&&Power=$Power$ (which is working)

in Beanshell would be:

{BasicName==“Income”&&Power=="$Power$"}

Unfortunately, this does not work. Am I still missing something? The left side of the equation is fine so reducing it down to:

Power=$Power$ vs. {Power=="$Power$"}

This syntax works elsewhere, but it’s not working for any GKC.

I suspect the quotation marks are preventing the dollar signs from being processed. Have you tried just {Power==$Power$}?

Edit: On the otherhand, you said that syntax works elsewhere, so I’m probably on completely the wrong track there.

Now that you mention it, I do seem to remember something about that, but I got sidetracked before looking into it. Yes, I seem to remember you do need to use classic syntax for GKC property match expressions to get the $xxxx$ expansion to work at the destination end.

I consider that a bug and can fix it, but I’m concerned that there may now be modules that depend on this ‘feature’. This is unlikely because it doesn’t do what it is supposed to, but someone may have got something that is currently working by accident.

I guess I need to add a ‘Evaluate $…$ expressions in Beanshell on the this Piece/Map/Deck’ option to the GKC Definitions…And update the manual and add examples…

Low priority AFAIC. I was more concerned with understanding how to arrive at the correct syntax. I’ve got it working in my module using classic expressions. Thankfully, if you ever fix this in the future, my programming style lends itself to switching out to beanshell very easily. The only reason I need to use GKCs in this manner is because of my zealous use of Prototypes. I’ve literally reduced every Piece down to Prototypes prefaced only by Markers. The workaround I’m using to make classic expressions arbitrarily complex is to use Calculated Property to backdoor in any portion it can’t handle…

As of VASSAL-3.3.1-test-35, the following syntax now works for the GKC:
{(DeckName==“xyz”) && ($Type$==Type)}. It was not previously.