Illogic behavior here with min(a,min(b,c)) in condition

Here is a simple code to illustrate what I encountered: pressing 1 2 or 3 substract 1 to the z variable of object 1 2 or 3 respectively. At each step I have one event with condition z of the objects = min(z1,(min(z2,z3)) and one event with condition z of the objects = min(z2,(min(z1,z3)). The actions for both is to print in the text box z1 z2 z3 and the id of the object satisfying the condition.

The results are in the white box after pressing 3 2 1 3 1 2 etc… The left column shows z1 z2 z3 at all steps. The 2 right columns shows the 2 events with the above conditions.

This is a bit long but I wanted to try to explain it the best I could.

I tried your events. There are a couple of problems. First, the last 2 events where you’re checking the value of z for the Group. If multiple objects match the condition(s), multiple objects are being picked. You can verify that by adding + ToString(PickedInstancesCount(Group)) to the text add actions. It will show how many instances are picked.

If you wanted to read each picked object, you would need to use a for each object as a subevent of the variable equals condition. Although, that would cause the same issue because the for each object would only select 1 object at a time.

The other issue is connected to the 1st. When the condition checks for the value of z for the group the objects that aren’t picked can’t be read, so Gdevelop is reading zero for their values.

So, if there’s a zero in the 2nd or 3rd column then it means the objects didn’t match the condition so they weren’t picked. If you want to read all 3 objects on the same lines with the limiting conditions, you would have to add pick all instance of Group before the actions. If you have the instance count it will show 3 are picked.

If you replaced all of the object variables with scene variable, it should be accurate. Although, your last lines would have to compare each variable separately instead of as a group. Unless you used an array and for each child

Instances can be confusing. It took me a while to fully understand them.

edit: since multiple objects are being picked, the “id=” is displaying the last matching id number. IE if 1,2,3 matched it would show id=3.

Thank you for your time and detailed explanations!

What about the line 767 and 656 not validating the conditions for min value changing from id =3 to id=2?

but the action specifies object1 object2 and object3 literally. If it gives a 0 value nonetheless to me it’s clearly misbehaving. Would it also gives 0 for other variables (other than z) of these objects as well?

also I don’t think it is exactly right. Look at the change from line 887 to 787.
I assumed it picks the id that are changing. But then line 767 to 766 no event triggered… total mystery

I need to think about the first. As to the 2nd.

Suppose you had values 1,2 and 3 if you used

Object variable = 2 whether you use the group name or the actual name it only picks the objects which match the condition(s). Just like if you had the action of delete, it would only delete the picked objects, it can only read the object variables of the picked objects. The group name acts just like you used the object names. It picks the objects not the group name.

I can’t explain why the event isn’t triggering. I think it has to do with the way groups handle variables or something. I need to test some more. When I saved the formulas ahead of time in a variable and then compare the object variable to the scene variable, it seems to work. I don’t know why.

Ok, I did a lot of testing to try and understand it. I created a simple expression that took 3 numbers and I passed it the objects 1, 2 and 3. I had it return the number 1. Here’s what I learned.

When the object values were 1, 2 and 3 and I compared it to group.Variable(z)
It runs the expression 3 times. Once for each object in the group. But, if the expression is false, the object value doesn’t carry over to the next pass. The value becomes zero. So, when you try to use object 2 and 3 in the formula. It fails.

checking if value equals 1
pass 1: 1,2,3
pass 2: 1,2,3
pass 3: 1,0,3

checking if value equals 1
pass 1: 2, 2, 2
pass 2: 0, 2, 2
pass 3: 0, 0, 2

I’m probably not explaining this clearly. Honestly, it’s not completely clear to me. It seems to check each object one at a time and unpicks it if it’s false. So, when it checks the next it returns zero when it checks the previous objects value and it continues for the other objects.

Edit:
I guess it makes sense. Suppose you use the group objects X() value is less than 100. It goes thru the group one at a time and unpicks the objects that are greater than 100. In the end, you’re only left with the objects whose X() <100.

I guess the safe way is to calculate the formula outside of the comparison otherwise it recalculates each time but the objects that fail the comparison are removed.

I understand your last edit and if it’s true then it’s a bug or a very weird mysterious logic. The variable is the object of the group or the instances depending if you use a condition on a group or on a object (in my case it was a group). The condition selects some variables. But we should be able to use an expression with explicit variables anywhere. That’s just math.

It does seem weird. You should still be able to get an object’s value. At least for the same condition. It runs the group comparison as a group but still sequentially and sort of like subevents. The problem is made worse with groups because each object in a group can have their own instances.

Most conditions don’t reference other objects within the group. It’s usually things like is z>11.

When doing a group it isn’t
If Obj1.x < (obj1.x + obj2.x + obj3.x)
If Obj2.x < (obj1.x + obj2.x + obj3.x)
If Obj3.x < (obj1.x + obj2.x + obj3.x)

Unless my test is flawed, it seems to be

If Obj1.x < (obj1.x + obj2.x + obj3.x)
---If Obj2.x < ((obj1.x or 0) + obj2.x + obj3.x)
-----If Obj3.x < ((obj1.x or 0) + (obj2.x or 0) + obj3.x)

It seems to carry over the result from each comparison into the next test but they don’t all have to be true for the condition to be true. But if the result depends on the previous object(s) then the calculation is going to be flawed.

I need to do more testing. I’m wondering how it works if it’s a group of objects that have instances. Instead of a group of 3 objects it could be a group of 3, 8 and 14 instances. There’s zero chance of that being reliable to test as a group.

I just did a little test from my phone.
Group.Variable(z) equals obj1.Variable(z) + obj2.Variable(z) + obj3.Variable(z)

With the values 1, 2 and 3 this should always be false because the answer is 6. But each time the condition passed with the last comparison.

1+2+3 (6)
0+2+3 (5)
0+0+3 (3)

The third test is a match.

I couldn’t believe it so I did the test… wow. This is messed up.

To be fair. Nobody is likely to use this formula although maybe something similar. The easiest solution is to save the calculation to a variable ahead of time. You would just compare the group value to the variable. It should then work as expected.

I was curious to understand the engine. It would be better if someone who wrote the source code could explain how these things work instead of us reverse-engineering it. I’m going to try to pass the object’s variables in an extension and see. Maybe they’re passed into an extension they’re copied. This would avoid writing some lines of code.

Using an extension does not help. Objects that are not the picked one have all their variables equaled to 0.