Why does Vassal stop when you have ~15 nested If(,,)?

You can get about 10 nested If(,) conditions working with a small delay, but when you get to about 15 Vassal comes to a grinding halt for literally minutes, no matter how simple the calculation.

Why is this?

Is there any workaround?

Have you tried X ? Y : Z instead?

Can you elaborate a bit?

In the Alert thread it was discussed how this construct is already supported. It is native java unlike If, So it might work better. If probably fills up the stack or something.

No, I mean, say I have:

If(r0==0,0,If(r1==0,1…etc…))))))))))))))

How would I implement that using the syntax you describe?

	r0==0 ? 0 : r1==0 ? 1 	: r2==0 ? 2 :	r3==0 ? 3 :  etc

{If(R0==0,0,1)} is equivalent to {r0==0?0:1}

So, you need something like

{r0==0 ? 0 : (r1==0 ? 1 : (r2==0 ? 2 : (r3==0 ? 3 : 99)))}

This should give you significantly better performance. The main problem with the If function is that all of arguments are fully evaluated, so even if r0==0, the entire If statement gets evaluated. If is also implemented as a Beanshell ‘program’ so there are overheads in continually calling it.

I will be adding ? : to the expression builder and will probably remove If.

I can see the value in removing it, but surely that would break stuff. It would need to deprecated in 3.3.1 and removed in 3.4. And will there even be a 3.4? I should actually add removing “If” to my TODO list for teh current module and other modules.

I meant remove it from the Expression Builder. It will remain in Vassal for ever more.

Okay that makes total sense.

Wow, that makes a massive difference!

Right, time to go speed up my modules…

That little nugget in the Alert thread was priceless. I’ve eliminated entire swaths of Trigger Actions and Restrict Commands because one well constructed expression using ? is far cleaner and more efficient. Especially once I discoverd the power of using +"" when ? is false…

Alert Thread? Where is that one?

BTW, I was about to pose the same question, so this post saved me. Thanks.

[url=https://forum.vassalengine.org/t/using-alert/10638/14]

Sorry, I thought there was a special Alert folder/directory, not a discussion thread on a Vassal function called ‘alert’.

There is a bit of a trick to using the A?b:c though when there are arithmetic operations also performed between ‘groups of A?b:c’ (nested or otherwise).

Frex - a1?b1:(a2?b2:c2)+a3?b3:c3 fails - the proverbial illegal string operator. (a1?b1:(a2?b2:c2))+(a3?b3:c3) works.

Thus I would not remove the If,then,else from the expression builder as this too has its place.

Effectively the proposal was only to stop advertising it. A total removal would only break stuff for no gain.

That said I don’t follow your argument that if-then-else has value beyond backwards compatibility. It is much slower and has a limit before it breaks.

Your example was a little bit abstract, so I am concerned that if it broke for you it may have been user error rather than a fundamental insight. But a clearer example may change that suspicion.

Why does someone always assume it is a user error. For gods sake.

The original equation:
(Math.floor((float)(If(cfdefr1a==0,0,If(10.0cfatkr1a/cfdefr1a>=5,0,2-1.0cfdefr1a/cfatkr1a))+drm1d10atkra+numdefrflippeda+If(hexcitya==“yes”&&hexfactsa>0&&engra>0,100.0,0.0)-If(hexcitya==“yes”&&hexfactsa>0&&engra<0,100.0,0.0)+If(hexweathera==“Fine”&&hexcitya==“no”&&(hexterraina==“clear”||hexterraina==“desert”)&&combatchoicea==“Blitz”&&numatkrarm1a>(numdefrarm1a+numdefrmech1a+numdefrataaunitsa),100.0,0.0)-If(hexweathera==“Fine”&&hexcitya==“no”&&(hexterraina==“clear”||hexterraina==“desert”)&&numatkrarm1a<numdefrarm1a,100.0,0.0)-If(hexcitya==“yes”&&hexfactsa>0,100.0,0.0)+If(nummapatkr>1,-100.0,0.0)-If((hexweathera==“Snow”||hexweathera==“Blizzard”)&&numdefrwintunits1a/numdefrunitsa>0.5,100.0,0.0)-If(numterratkrout==0,0,If(numatkrunitsa==numterratkrout,100.0,0.0))-If(hexterraina==“jungle”&&10*numatkrjungle1a/numatkrunitsa<5.0,100.0,0.0))))/100.0

The a?b:c equation (post adding the extra () for each a?b:c part of the equation:
(Math.floor((float)((cfdefr1a==0||cfatkr1a/cfdefr1a>=0.5?0:2-1.0*cfdefr1a/cfatkr1a)+drm1d10atkra+numdefrflippeda+(hexcitya==“yes”&&hexfactsa>0&&engra>0?100:0)-(hexcitya==“yes”&&hexfactsa>0&&engra<0?100:0)+(hexweathera==“Fine”&&hexcitya==“no”&&(hexterraina==“clear”||hexterraina==“desert”)&&combatchoicea==“Blitz”&&numatkrarm1a>(numdefrarm1a+numdefrmech1a+numdefrataaunitsa)?100:0)-(hexweathera==“Fine”&&hexcitya==“no”&&(hexterraina==“clear”||hexterraina==“desert”)&&numatkrarm1a<numdefrarm1a?100:0)-(hexcitya==“yes”&&hexfactsa>0?100:0)-(nummapatkr>1?100:0)-((hexweathera==“Snow”||hexweathera==“Blizzard”)&&numdefrwintunits1a/numdefrunitsa>0.5?100:0)-(numterratkrout==0?0:(numatkrunitsa==numterratkrout?100:0))-(hexterraina==“jungle”&&numatkrjungle1a/numatkrunitsa<0.5?100:0))))/100.0

The If,then,else equation worked. I replaced it with the a?b:c construct and it failed. I deduced that each set of a?b:c between each +,-,*,/ must be separated, thus the added (). If I had left it as an If,then,else it would continue to work. My changes to a?b:c failed and required more work to solve.

Thus, to reiterate, developers need both cases to exist, not ‘stop advertising it’, but both must coexist as tools within Vassal.

This, as happenstance fortuitously exists, relates to my other post on ditching all the maths within vassal to use an excel or equivalent to do the maths. Slimy’s post on that thread is just SOOO negative.
https://forum.vassalengine.org/t/thought-bubble-for-future-version/10805/1

Dear Slimy, have you ever been exposed to kaizan? Incremental improvement to the process. A part of the overall quality improvement evolution that should always be a part of doing business. Do not, EVER, subscribe to ‘it works why change’ philosophy. There is ALWAYS a better way of doing it and I, for one, will ALWAYS endeavour to try and achieve that.

Further. I’m not a java person, not even close to understanding it, nor willing to do so. But I did find this site:

cafeaulait.org/course/week2/44.html

The conditional operator only works for assigning a value to a variable, using a value in a method invocation, or in some other way that indicates the type of its second and third arguments. For example, consider the following

if (name.equals(“Rumplestiltskin”)) {
System.out.println(“Give back child”);
}
else {
System.out.println(“Laugh”);
}
This may not be written like this:

name.equals(“Rumplestiltskin”)
? System.out.println(“Give back child”)
: System.out.println(“Laugh”);
First of all, both the second and third arguments are void. Secondly, no assignment is present to indicate the type that is expected for the second and third arguments (though you know void must be wrong).

The first argument to the conditional operator must have or return boolean type and the second and third arguments must return values compatible with the value the entire expression can be expected to return. You can never use a void method as an argument to the ? : operator.

So, the a?b:c does have some limits/problems of its own. Let us keep the baby and its bath water for now.

I think I found the mistake in your modified code. One possible short answer is I believe

(Math.floor((float)(cfdefr1a==0?0:10.0*cfatkr1a/cfdefr1a>=5?0:2-1.0*cfdefr1a/cfatkr1a)+drm1d10atkra+numdefrflippeda+(hexcitya=="yes"&&hexfactsa>0&&engra>0?100:0)-(hexcitya=="yes"&&hexfactsa>0&&engra<0?100:0)+(hexweathera=="Fine"&&hexcitya=="no"&&(hexterraina=="clear"||hexterraina=="desert")&&combatchoicea=="Blitz"&&numatkrarm1a>(numdefrarm1a+numdefrmech1a+numdefrataaunitsa)?100:0)-(hexweathera=="Fine"&&hexcitya=="no"&&(hexterraina=="clear"||hexterraina=="desert")&&numatkrarm1a<numdefrarm1a?100:0)-(hexcitya=="yes"&&hexfactsa>0?100:0)-(nummapatkr>1?100:0)-((hexweathera=="Snow"||hexweathera=="Blizzard")&&numdefrwintunits1a/numdefrunitsa>0.5?100:0)-(numterratkrout==0?0:(numatkrunitsa==numterratkrout?100:0))-(hexterraina=="jungle"&&numatkrjungle1a/numatkrunitsa<0.5?100:0))))/100.0

The root of the problem is I believe when you changed from “10.0*cfatkr1a/cfdefr1a>=5” to “cfatkr1a/cfdefr1a>=0.5”. The issue is that these variables are integers so you get slightly different answers. Another solution is to change them in that comparison to doubles or floats.

My method was to parse the two expressions so I could identify what was different. I then wrote some Java to test the the specific change you made rather than the whole expression. (I cannot be 100% certain I modified the above expression correctly but hopefully my analysis might be of use to you.)