Inexplicable piece movement

I’m using an excellent piece tracking method I lifted from Joel Toppen’s modules, but when I combine it with a return to first empty slot system of my own devising, pieces go where they shouldn’t.

So, the piece tracking works like this:
Global Properties
BitCurrent
BitOld
B1 (start value 1)
B2 etc.

Pieces have the traits
GKC map trigger +1_army to matching properties CurrentZone==$BitCurrent$
GKC map trigger -1_army to matching properties CurrentZone==$BitOld$
Set GP BitCurrent map trigger to value $CurrentZone$
Set GP BitOld map trigger to value $OldZone$

Zone counters have the trait
Set GP $CurrentZone$ +1_army increment by 1 -1_army increment by -1

Map Zones
B1
B2
B3
etc.

This all works fine.

The weirdness occurs when the pieces use the traits
Trigger Returnarmy
Trigger watch for Returnarmy perform moveb12 when B12==0
SendTo moveb12 to B12
Trigger watch for Returnarmy perform moveb11 when B12==1&&B11==0
SendTo moveb11 to B11
Trigger watch for Returnarmy perform moveb10 when B12==1&&B11==1&&B10==0
SendTo moveb10 to B10
etc.

This should work as you’d expect, and send the piece to the first empty Zone available (and did, before I plugged in Joel’s piece tracking), but instead it skips the first empty zone available and sends it to the second empty Zone available. Even stranger, once all the zones with lower numbers than the first empty zone are filled, the last piece to be returned does go to the one remaining (first) empty zone.

Can anyone explain this? I’ve been trying to troubleshoot it for hours, and nothing seems to work. I initially thought the piece tracking was firing first, causing the sendto to go to the next zone up, but that doesn’t explain the final returned piece going to the one remaining empty zone, and I don’t think it’s possible anyway, given the $CurrentZone$ dependency of the piece tracking.

My first question is: have you played around with the order of the piece traits? These can be tricky to get right, but without seeing the actual thing I can’t be sure if there is a potential problem here or not.

By way of bonafides, I put quite a bit of automated tracking and resulting piece movement into my Here I Stand and Virgin Queen modules. I suspect but can’t prove Joel T used them to some degree, since they pre-date his COIN modules…but he routinely gets all the glory. Which is fair enough I suppose, he’s done a great job!

I put together a test module to demonstrate the behaviour and it works as it should! So, probably some complication I just haven’t found yet.

I’m happy to give credit where it’s due, but it’s hard to know where trait combinations originated from! All I know is that the piece tracking I outlined above is very smart and not something I would have come up with on my own.

Ah, adding another zone+counter to the test module broke it. So drag and drop into an uncounted zone, and using Return works fine. But drag and drop into a counted zone and using Return goes wrong as explained in my first post.

Further clarification - whether or not a zone is counted is irrelevant.

I cannot even begin to understand what is going on here. The test module is airtight, as far as I can tell. It appears to be something funky going on under the hood.

Not trying to be a pest, but I took a quick look and I can’t even begin to understand what is meant to be happening, or where zones are or aren’t. As in, I just see a bunch of identical pink pieces and you can’t tell where a “counted zone” is or isn’t for purposes of drag and drop.

One thought is to add some dummy pieces with Text Labels that will in real-time display the values of all the global properties so you can verify that their values are what you expect them to be–since it looks like the movement is tightly linked to those.

Thank you for taking the time to take a look!

I have added textlabels to clarify as you suggested, and it was very informative. For some reason BitOld is changing to the zone the pieces should go to, and BitCurrent to where they end up. I still have no idea why.

Right-clicking a piece and selecting Return should send it to the first empty zone starting from the bottom of the column, but instead ends up sending the piece to the next empty zone (apparently via the first empty zone, as the BitOld BitCurrent textlabels indicate).

So, it appears that the “Return” trigger and the Map trigger is occurring twice? First Return probably sends the piece to its intended destination and first Map trigger updates the GPs accordingly, and the second time sends it to the next newly valid destination, and the second Map trigger updates the GPs again.

There are no traits that would make this happen twice though, as far as I can see.

I note that the new test.vmod has been downloaded twice, but no response twenty days on leads me to think that the problem is too tricky to troubleshoot. Maybe the text labels aren’t sufficient? Is there any explanation beyond what I’ve written already that I can add to clarify what should occur and what appears to be occurring? Is this a straight up bug in Vassal that I should report in the appropriate forum?

You really have a hornet’s nest of Triggers and some pretty complicated match expressions. I just looked for a few minutes and wonder if it’s worth attacking the problem from a different direction.

Instead of tracking a numerical value (am I empty? 0 or 1) for each of the 12 holding boxes, what if you tracked a single value–the highest numbered empty holding box?

You’ve already got a keystroke applied to all pieces ending movement on the map. If you’ve dragged a piece out of a holding box, use that keystroke to trigger a check of its previous zone. If that zone is numbered higher that the current global property indicating the highest-numbered empty box, update the property–if not, you do nothing. Then in your block prototype you only ever need one Send to Location and corresponding Trigger, not 12 of each. I’m probably not thinking it through all the way, as you probably need to track which is the 2nd-highest numbered empty box in order to do some updating when a piece is returned when multiple empty boxes exist.

It seems like there should also be a way to employ a Calculated Property here to eliminate some of those very long property match expressions, but I’m still noodling on it.

OK, I have a module that does what you want.

The key parts are as follows:

The test piece you added with the label to track your variables remains, and it stores a Calculated Property–series of nested IF statements–identifying the highest-numbered open box at any point in time. It also has a SGP in order to copy this value to a Global Property (when requested) in order that individual army pieces can “see” it (otherwise this information is confined to the invisible piece and the army pieces can’t get at it).

We just dispense with GPs to store current and old location entirely. Get rid of the nested prototype situation on the blocks and simply block traits quite a bit. We only need a single Send to Location now–sent to the zone whose name we retrieve out of the global property ID-ing the highest open box. There are 2 triggers relating to army piece movement: did this move from a holding box to offboard? Or did this move from offboard into a holding box? Update values accordingly via SGP.

When you want to return a piece to the highest-open box, a GKC is despatched to your hidden piece telling it to copy the Calculated Property value to the Global Property to “store” it for all pieces to see, then perform the Send to Location.

Let me know if you have any questions.

Thank you for your work!

Unfortunately, your system seems to break if a player moves a block from anywhere other than the topmost zone first. The zones do not switch from 1 to 0, and you get a Bad Data in Module: British coalition block [Send to Location - Return to Highest Open] - Zone not found Zone[{OpenBox}]=None error when you try to return a piece.

If I could somehow guarantee players would always take from the correct spot, this would be great, but in my experience that is not something I can rely on.

Also, the piece tracking is not intended only for this one purpose, and which zone the pieces are moved to, and subsequently removed from, must be tracked.

Hmm, fascinating.

Although I’m at a loss to articulate precisely why, I still can’t make out how the approach you started with is going to end up working. The keystroke applied to pieces ending movement on the map seems to be listened to in only 2 places, and that’s in a nested prototype where a GKC and SGP seem to be acting simultaneously. I felt like a dog chasing my tail trying to work out what goes before which.

It’s been a few hours so I would have to refresh my memory of which parts are involved, but it looked like there was an unnecessarily complex chain of Triggers, particularly the “Watch for this keystroke” part. I’ve been tripped up on this before years ago in modules.

I can’t promise it, but perhaps I can take another look tomorrow. I’m confident there is a more streamlined approach that can work.

I’m particularly intrigued by this part–I just downloaded the test module on my Macbook here at home (on which it has never been used), and dragged the block 4th from the top away first, then the 8th from the top. The “Return” function worked flawlessly on both.

I’ve tried dragging 4 or more blocks off, the labels update to 0 next to each holding box, and even returning them in a different order than how they were removed…again, all works for me.

Here’s a log started from a fresh load of the module that demonstrates the problem. I will note that sometimes - only sometimes - it works as you intended. More often than not it breaks.

EDIT: Oh, I see the problem. You even pointed it out in your first post. It requires that the pieces only be moved “offboard”. Another zone breaks it.

Anyway, as already noted I need to track where the pieces are, and where they came from, not just in relation to the 12 specific zones.

About my test module, the BitOld/BitCurrent system works fine in isolation, and the return triggers work fine in isolation. Only when combined does the return appear to be triggered twice (or more likely into an infinite loop that only works twice).

So, here’s what should happen:

A GP, BitOld gets set to OldZone, then another GP, BitCurrent gets set to CurrentZone, then the map trigger applies a GKC -1br to a piece in Zone BitOld, then the map trigger applies a GKC +1 to a piece in Zone BitCurrent.

The zones each have a tracker that responds to the GKC by incrementing or decrementing the GP that matches the zone the tracker is in.

There’s nothing arcane about any of that, is there? It works fine, and is the most elegant way I have found to track pieces across multiple zones.

Then the “blocks” have a Return menu command that triggers one of the 12 triggers with the conditions based on the GPs incremented/decremented above. Only one trigger can fire, and it activates Send To the appropriate zone.

Somehow, this Return triggers AGAIN, after the Send To, and the BitOld BitCurrent +1br, -1br updates.

Oh, now I took the time to explain it, the problem was obvious.

The triggers 1 to 12 were in descending order instead of ascending, and triggers are checked from top to bottom unlike other traits that are checked from bottom to top.

So, for example, after trigger 2, the new GPs were correct for trigger 1, and the piece “Returned” again.

Then the Trigger logic would merely need to be adjusted to be broader–I only made it as specific as it was because the only defined zones I saw were the holding boxes. I have used a single zone containing an irregular grid with named regions to good effect, this ends up making property match expression composition easier.

I don’t really understand, but I’m probably at the end of my usefulness without knowing all the details. Anyway, you can take or leave the ideas as you see fit. Good luck.

I’m not trying to cause offense by saying I had a hard time sussing out the order of operations. I’m used to my methods which derive from how my brain approaches a problem. Someone trying to wrap their head around Protestant space tracking and political control in my VQ module would probably be bamboozled for awhile.

I got pretty close to a solution (only found wanting because of overly-specific match logic) using 1 StL and 1 Trigger instead of 12 of each, but whichever method one hits upon to get the effect, there’s no better or worse way (unless you do stuff that results in ever-increasing memory consumption)–no one’s ever going to get under the hood and critique.

Oh, I didn’t mean to sound defensive. The piece tracking is not even something I came up with myself, so I have no personal stake in it. I’m just happy to see that the piece tracking+return system can work together, so I can use the piece tracking more extensively in my module to replace the slower process I have been using.