Picking question when trying to match instances through IV

Get help using Construct 2

Post » Wed Jan 11, 2017 10:47 pm

@Ashley
Please consider this capx.

The idea is that each NPC instance has a Target instance variable that allows to match with a destination Waypoint thanks to a "Compare instance variable value" condition.
Each Waypoint has an ID instance variable that is used for the picking/determining the target of the NPC and is the instance variable compared in the condition.

A single condition event is used.
We know that C2 will implicitly loop through all the instances of the "main" object type referenced (in our code: "Waypoint") as if there was a "For each Waypoint" (implicit).
We also know that to actually achieve what we are willing to do, having the condition "For each NPC" (explicit) will loop through all the instances of the NPC (and has to be placed before the comparison in order to work, otherwise the looping would happen only to the picked instances after the comparison).
This condition is disabled for now though, in order to try it with a single event and determine a theory on how the picking is working and how the "second reference" object (NPC) is being picked.

As the capx is set by default, our goal is still reached, each NPC is going toward the Waypoint it is supposed to (each NPC instance is reaching for a unique Waypoint instance).
We could then assume that under the hood, C2 is still looping through the NPC instances to find a match for the condition.

Now take NPC instance NPC 1 (currently of Target value 1), and modify its Target value to 2.
Expected NPC 0 going to WP0; both NPC 1 and NPC 2 instances to go towards Waypoint WP 2; NP 3 going toward WP 3; NP 4 going toward WP 4.
Happening : The NPC 1 goes towards Waypoint WP2 instance, NPC 2 instance goes towards Waypoint WP3 instance, NPC 3 goes towards WP4; NPC 4 goes towards WP0 (ID = 0)

Theory : When a "second reference" (our NPC object type) instance is a match, the looping stops.
For the reminding instances though, it seems the destination Waypoint is Destination + 1 (with the last instance going back to the "default"/first waypoint instance).

(Might have to see with the IID stack)

---
Now modify the NPC1 instance so that its Target is 0.
"General expectation", would be both NPC0 and NPC1 going to the WP 0, NPC 2 going to the WP2, NPC3 going to WP3, NPC4 going to NPC4.
Although, according to our previous theory, we could expect NPC0 going to WP0, NPC 1 going to WP1 (destination + 1), NPC 2 going to WP3, NPC3 going to WP4; NPC4 going to WP 0. (Theory expectation)

Happening : Same result as previously.
So a difference with our "Expected theory" is that NPC1 is not going to destination + 1.

---
Let's try something else.
NPC0 to Target0, NPC1 Target to 0, NPC2 target to 2, NPC 3 target to 4 and NPC4 Target to 4.
We have two pairs of instances set to go to the same waypoint.

"General expectation" would be NPC0 to WP0, NPC1 to WP0, NPC2 to WP2, NPC3 to WP4, NPC4 to WP4.
"Theory expectation" would be NPC0 to WP0, NPC1 to WP1, NPC2 to WP3, NPC3 to WP4, NPC4 to WP0.

Happening : NPC0 to WPO; NPC3 to WP0; NPC1 to WP2; NPC4 to WP2; NPC2 to WP4.
From there I must admit I have no more theory to what's going on and how NPC instances destination's Waypoint instance is being picked in that case.

---
Let's try even further
Reset each NPC to have a single destination, in order as it was originally.
NPC0 Target 0; NPC1 Target 1; NPC2 Target 2; NPC3 Target 3; NPC4 Target 4.

Now let's change WP2's ID from 2 to 6.

"General Expectation" : NPC 0 to WP0; NPC1 to WP1; NPC 2 to not move; NPC3 to WP3; NPC 4 to WP4
"Theory Expectation" : NPC0 to WP0; NPC1 to WP1; NPC2 could go to WP 3; NPC3 to WP4; NPC4 to WP0

Happening : The Theory expectation is happening. So our first observation/guess was not that bad.

---

Modify NPC 1 Target to 6
"General expectation" : NPC0 to WP0; NPC1 to WP2; NPC2 to not move; NPC3 to WP3; NPC4 to WP4
"Theory expectation" : NPC0 to WP0; NPC1 to WP2; NPC2 could go to WP 3; NPC3 to WP4; NPC4 to WP0

Happening : NPC0 to WP0; NCPC3 to WP0; NPC1 to WP3; NPC 4 to WP3; NPC2 to WP4

I don't know what's happening.

In all those permutations though, if you enable the "For each NPC" condition, the "General expectation" scenario is happening, as expected, and as we know it should/has been the solution for these kind of picking for years.

Nonetheless, what is the actual picking scenario that is going on inside C2 when only a single condition is applied and that would explain all those observations ?
My original assumption was that only the first instance of the object type was picked.
Nonetheless, on trial, it seems it wasn't the case in a specific set of use.
And through those observations, I must admit I don't have a working theory that would allow for a valid expectation when only using the single condition in whatever setup.
New to Construct ? Where to start

Image Image

Image Image

Please attach a capx to any help request or bug report !
Moderator
B
292
S
115
G
96
Posts: 7,295
Reputation: 70,795

Post » Thu Jan 12, 2017 12:07 am

I think that unless it's specifically paired with another instance it should default to the 0 index when no picking is happening.
Like so:
Image

Let me add that the way the capx is with the waypoint in the condition, rather than the npc, should do no picking.
It should be the npc doing the comparison, and doing the action to qualify as being picked correctly.
Image ImageImage
B
169
S
50
G
174
Posts: 8,328
Reputation: 110,800

Post » Thu Jan 12, 2017 12:41 am

I haven't opened the capx, and I skimmed your post. It sounds like the question is how objects are paired when when no picking is done.

Take this event as an example that does that pairing when there are multiple instances of sprite1 and sprite2.

Every tick
--- sprite1: set position to Sprite2

That is equivelent to the more verbose event here:

Repeat sprite1.count times
Pick sprite1 instance loopindex
Pick sprite2 instance loopindex%sprite2.count
--- sprite1: set position to sprite2

You can replace count with pickedCount instead and that will show what's happening when only some of the objects are picked. Anyways I hope this helps, I thought it was cool when I realized it. If I completely misunderstood then I'll be sure to look at the capx and Re-read your post when I get a chance.

Cheers
B
92
S
32
G
109
Posts: 5,294
Reputation: 70,999

Post » Thu Jan 12, 2017 1:03 am

Hey Kyatric/all,

Just a heads up, WP 0 needs to have its id variable changed from 6 to 0 in order to follow the steps properly.

I remember having a similar issue a few years ago trying to comprehend why my logic was failing without a 'for each' when it seemed to be working previously.

I think a clearer example of what you are talking about is when you change the condition to : NPC.Target = Waypoint.ID
(This way when it hasn't picked properly it is more obvious because the NPC's simply wont move).


The answer I got from @Ramones back in 2013 was :

"I think it's working as intended. I'll try to explain. When you have "Sprite2.number = Sprite.number" it loops through each Sprite2 and each Sprite and compares them.

In your first example it's comparing them like this:
Compare Sprite2(number 3) to Sprite(number 1)
Compare Sprite2(number 2) to Sprite(number 2)
Compare Sprite2(number 1) to Sprite(number 3)

You see it's looping through them both in different orders so only Sprite number 2 matches and it's the only one that moves. If you swap the numbers 1 and 3 on Sprite2 then they will all move."


So it seems it makes one pass without the 'for each'. If they are lucky enough to match up it works but it wont check against each object - just one of them.
ImageImage
B
123
S
23
G
7
Posts: 1,071
Reputation: 13,091

Post » Thu Jan 12, 2017 9:27 am

@GenkiGenka: Thanks for the notification, I've modified the capx so that WP0 ID is 0 when downloaded now.
I guess I was still messing in the file while writing my description and making permutations before providing the capx.

Now the download should work as intended.

@GenkiGenka, @newt: I agree that a better picking order should be to have NPC as "main object", but I actually was asked the problem in this very way and couldn't come up with an actual explanation that made sense.
The assumption that it "picks" the default waypoint instance by default is logical, but actually do not match the observations, otherwise, when having "pairs" and/or two NPCs targeting the same Waypoint, they all should end up targeting WP0, which is absolutely not the case.

@R0j0hound interesting "translation" into more verbose events.
"Pick sprite2 instance loopindex%sprite2.count" would actually make a good explanation of what is going on with some of the actual results observed and why it makes it difficult to anticipate some of the results.
Still a bit esoteric, but at the same time it feels close to the behavior observed.

Thanks for your weighing in guys.
This is more a "philosophical" issue here and again, I agree that the correct way to do correct picking is to have the NPCs comparing their instance variable (being cycled through by the implicit "For each") and have another explicit "For each Waypoint".

I'm still waiting on @Ashley to have some confirmation though and possibly a "clean" explanation as he knows how to provide them.
New to Construct ? Where to start

Image Image

Image Image

Please attach a capx to any help request or bug report !
Moderator
B
292
S
115
G
96
Posts: 7,295
Reputation: 70,795

Post » Thu Jan 12, 2017 1:36 pm

This is actually pretty complicated to explain. There's a sort of paradox in the event engine that in order to make events "just work" intuitively, there's actually a lot of pretty complex code!

@newt is in the right direction with the "every tick" example. By default if you say "Sprite1: set X to Sprite2.X", it pairs them up. The event engine does this by what is internally called the SOL index. Think of this like the IID, but instead of being the index within all the instances, it's really the index within the currently picked instances only (aka the SOL).

So in the "Sprite1: set X to Sprite2.X" example, the event engine really runs an algorithm like this:

for each SOL1index in Sprite1 SOL:
--- get Sprite1 instance at SOL1index
--- get Sprite2 instance at SOL1index
--- set Sprite1 instance X to Sprite2 instance X

A similar algorithm is used for conditions, except the last step is "run condition using Sprite1 instance and Sprite2 instance". Note it only compares one instance against one other instance.

The key thing to note is SOL1index is also used as an index in to Sprite2's SOL (aka SOL2). When all instances are picked (as in the Every Tick example), SOL indices are effectively IIDs, and everything pairs up. However when you start picking instances, they no longer pair up.

The interesting thing about the capx is the condition is sort of backwards: in my mind I'd write "NPC: compare Target = Waypoint.ID", but instead it has "Waypoint: compare ID = NPC.Target". This means if any Waypoint does not have an NPC set to move towards it, it's not picked - and is removed from the SOL.

So in your first example you set NPC 1 target to 2. This means the waypoint with ID 1 fails the condition. It's also important to note that each instance only compares itself to one other instance, as per the algorithm above. So it fails the condition not because there are no NPCs with target value 1, but because the single paired NPC 1 instance did not match.

So waypoint ID 1 fails the condition and is un-picked, and no conditions mentioned NPC so they all remain picked. The NPC actions now run with pairing like this:

0: NPC0 - WP0
1: NPC1 - WP2
2: NPC2 - WP3
3: NPC3 - WP4
4: NPC4 - nothing

There are two interesting consequences of this:

1) surprisingly, NPC2 goes to WP3 even though its target value is 2. This is because:
a) all NPCs are picked - they all "met the condition" because no condition referenced them
b) WP1 was filtered out, and it ends up paired with WP3 via the SOL index - note the engine is ignoring instance values here, this is what's left behind by the condition

2) NPC4 goes to WP0. This is because the event engine implements wraparound for the SOL index - if it goes off the end, it wraps around back to the start.

Similarly if you edit NPC1 to have a Target of 0, WP1 fails the condition again, and the SOL ends up:

0: NPC0 - WP0
1: NPC1 - WP2
2: NPC2 - WP3
3: NPC3 - WP4
4: NPC4 - nothing

This is actually identical to the previous result. The reason is it's just another case where WP1 fails the condition, and everything else is the same.

Basically the best way to think about this is the event engine tries to pair instances together, but if you start picking instances, all bets are off - the pairing won't make sense any more. Also it might help to realise that once the condition has finished running, the instance variable values have no effect.

When you add "for each NPC", you force the event to run repeatedly with just one NPC picked. Since it forces the whole event to run repeatedly with just one NPC instance, it works as expected. Note since the Waypoint condition runs an implicit for-each loop, this actually acts as a nested loop comparing every instance of NPC against every instance of Waypoint. So you actually compare all combinations, whereas before it only compares against a paired instance - which is more or less a random instance if you have conditions picking them.
Scirra Founder
B
398
S
236
G
88
Posts: 24,433
Reputation: 194,635

Post » Thu Jan 12, 2017 1:50 pm

Thank you very much !
New to Construct ? Where to start

Image Image

Image Image

Please attach a capx to any help request or bug report !
Moderator
B
292
S
115
G
96
Posts: 7,295
Reputation: 70,795


Return to How do I....?

Who is online

Users browsing this forum: Euduardo, Kin, mikehive, ratboy3, tinhofiel and 37 guests