Stacked pieces

Hi,

is there a way to send a command to one piece inside a pile of stacked pieces and another command to all the other ones in the stack?

For example move one piece to Zone X and all the others to Zone Y.

Thanks,
Lesse

You should be able to do that with property filters …such as

BasicName = (name of the piece)

or you can place marker traits on the pieces and just move those with the marker trait. For example you can have 2 soldier pieces and 1 tank piece in the stack. On the soldier pieces, you can have a marker trait that states

PieceType = Soldier

The tank would be

PieceType = Tank

Then if you use that same expression as a Property filter, only the pieces that match the PieceType you wish to move will move.

Conversely, if you wish to move all pieces except the soldiers, you can use the expression

PieceType =! Soldier

The problem is, that most of the time the pieces in the zone will be of the same type, meaning that I can’t distinguish between their type (they even can have the same BasicName).

I managed to do it with properties (PieceId) for non-stacked pieces in a zone, but with stacked pieces I encountered the problem that if i select the top piece to apply a command, all other pieces in the stack are selected too (without double-clicking to unstack them - I’m trying to avoid this). So the command is sent to each piece and all of them are then removed.

Hmmm. I’ve haven’t worked much with stacked pieces so maybe there’s something going on that I’m not familiar with.

Perhaps someone else may be able to see something here that I’m not catching.

lesse, can you describe how the piece destinations are determined? That is, under what circumstances would you send some pieces to Zone X and the rest to Zone Y?

In my module this action symbolizes the defeat of the army in a zone.

Therfore one of the pieces is permanently defeated and therefore returned to the “box” (a specific deck, corresponding to the type of the piece). The other pieces are returned to the owning players hand.

This is planned to be done by setting a global property “RaceA_Player” to $playerSide$ and then sending the pieces to Location $RaceA_Player$ (player window) at the position (x/y) of the deck with the available troops.

It works fine… as long as only one piece is selected (but this is a major loss in usability because pieces are usually stacked).

How do you determin which piece is the one elminated? You should be able to accomplish this with a dynamic property, but it will require setting the dynamic property of the piece that gets eliminated.

At the moment it is done by looking if the piece is selected … this is why it won’t work with the stacked pieces, because all pieces in the stack are selected :frowning:

If you need to select a specific piece within the stack to eliminate, can’t you double-click on the stack to expand it, then select and eliminate the specific piece?

B.

*********** REPLY SEPARATOR ***********

On 18/02/2010 at 9:43 AM lesse wrote:


Messages mailing list
Messages@forums.vassalengine.org
forums.vassalengine.org/mailman/ … engine.org

Post generated using Mail2Forum (mail2forum.com)

I think he wants to be able to right click the stack without expanding it
and eliminate 1 piece and have the others go back to the player’s hand.
Problem is all pieces get selected when you click a stack and the key stroke
fires off against all pieces in the stack at the same time. If there was a
way to enumerate the top piece in a stack as a property then a trigger with
a filter could accomplish it. Of course if there are mixed unit types in the
stacks, that’s a whole different can of worms.

Chuck

Post generated using Mail2Forum (mail2forum.com)

correct.

It works with double clicking - selecting - and applying the action, but I’m trying to achieve it without this steps, making the play experience more comfortable (only one click).

Sorry to necro an old thread, but I have pretty much the same issue.

If I’m reading him correctly, I think the OP’s need has been misunderstood. The way it was presented left the impression that he wanted to treat certain “special” units in the stack differently, but I think he just wanted to treat a limited number of units differently, regardless of their characteristics. For example, there might be a game rule that says “one unit goes to the dead pile and the rest return to your camp”.

I have a very similar need in Cosmic Encounter, where there are stacks of identical ships all over the place but you often need to pop one (or some other number) of them off the top to send it somewhere. This is cumbersome for the user, since you have to double-click to expand the stack, drag the top ship(s) away from the stack, double-click again to reset your stack, then drag the isolated ship(s) where you want them to go. Over and over again. I want to build one-shot commands to do this work for the user, in two different contexts:

(I) Pull: Bring 1 ship “here” from the standard dead pile (called “the warp”).
(II) Push: Send 1 ship “there” (somewhere predefined) off the top of a stack.

Note: I can’t really use decks for this, for reasons I’ll omit in the interest of brevity.

“Pulling” is doable if you use a global counter of some kind. All the objects (pieces) that can be “here” destinations for the ship from the warp use a prototype that defines a Retrieve 1 Ship trigger (Ctrl-R) that

  • sets my global GenericCounter = 1
  • records the “here” object’s location in global properties GenericX and GenericY
  • issues a “Move” Global Key Command to all units of the appropriate color in the warp

The “Move” key is caught by a trigger on the ships that

  • checks to make sure GenericCounter > 0
  • sends the ship to GenericX,GenericY
  • performs a one-pixel “jog” using Move Fixed Distance to force the ship to jump onto any stack already at that location (this does not always work, btw)
  • increments global GenericCounter by -1

In this way, I can easily implement “bring 4 ships here” by initially setting GenericCounter to 4 instead of 1. The first n ships processed move as desired, and the remaining ships do nothing since GenericCounter has now wound down to zero.

“Pushing,” though, I’m finding impossible. The method outlined above requires either setting or clearing a global either before or after all of the incremental actions, so you can really only do it when it’s triggered by something external to the pieces being moved, such as another piece that wants to receive them, a global hotkey sending them to a known location, etc. What Scenario II really wants is for the user to be able to right-click on the top piece of a stack, or left-click on the entire stack, and have the chosen key command (not an external button) send the top n pieces from that stack regardless of how many are selected. Basically, I’m trying to define a stack-level command by attaching it to the pieces in the stack. As best I can tell, this is not doable since in a “push” context every action that will happen will be sent to each of the pieces in the stack, and I have no way to initialize my GenericCounter to 1 or 4 without the initialization being repeated right before each selected piece is processed. (I am assuming the “command stack” in Vassal works by identifying all pieces that should receive a keystroke and then queuing up the keystrokes against those pieces; at least my empirical results seem to suggest this.)

Even using a deck doesn’t seem to help. I could move the pieces to a hidden deck, draw the top 1 or 4 cards from that deck, senbd them somewhere, and then move the rest of the deck back to the original spot — but without an external initiation point, I can only issue the “Draw 1” or “Draw 4” command from the pieces themselves, which would cause it to happen an unpredictable number of times. So I’m baffled about how to implement this in a way that doesn’t require two or more steps (select your pieces, then move your mouse to a toolbar and click a button).

What would make this all a lot simpler would be some way to define action X as a stack-level action and then define whether it applies to the entire stack or the top n pieces that meet whatever filter criteria are supplied. (And maybe specify the minimum total stack size for the action to apply in the first place: specifying “2” would mean the action is ignored if the piece isn’t actually in a stack.) If this were just implemented for Triggers I think that would be sufficient for most needs, since a trigger can fire anything else. The idea is that it wouldn’t matter if the user left-clicked the whole stack or right-clicked the top piece, or if a piece that had been sent to the bottom was still selected; in all cases the Trigger would be applied as if the user had manually selected the top n pieces that meet the filter criteria and then performed the command.

Alternatively, what I need is a module-level setting to make stacks work more like decks in the sense that you can grab and drag the top piece off in one smooth action without moving the whole stack. Basically, a global option that I can check that says the default drag on the top of a stack applies to the top piece instead of the whole stack; thus, to move an entire stack I would have to left-click it first. This would save users TONS of extra clicking in my Cosmic Encounter module. Basically, Vassal assumes all stacks are “sticky” but non-wargames often need them to be “non-sticky”.

Hmm, so I just stumbled onto a pretty simple solution that should work most of the time.

Let’s say you have an existing ‘result’ command, Ctrl-R, that ‘does something’ with a piece, but you want to automatically apply that command to only one piece from every selected stack; that is, you want to choose multiple stacks, invoke something like Ctrl-1 (possibly from a right-click on one of the selected pieces), and have it apply Ctrl-R to only one piece per stack, without having to initiate this using something external to the pieces themselves (like a global Action Button). (In the OP’s case he also wanted to ‘do something else’ with the remaining pieces in the stack, but it should be obvious how to extend what I’m about to say to accomplish that.)

This method exploits the fact that when you select multiple stacks and invoke a Trigger Action, Vassal appears to apply that action stack-by-stack, meaning it applies it to each piece in stack 1, then each piece in stack 2, and so on. This discovery, combined with the knowledge that all the pieces in a given stack have the same X and Y coordinate, allows us to write traits that perform the action when the piece currently being considered has a different location than the piece previously moved.

Ctrl-R - ‘Do Something’ result command

Ctrl-X - Set Global Property - sets GenericX = $CurrentX$
Ctrl-X - Set Global Property - sets GenericY = $CurrentY$ (so a single invocation of Ctrl-X copies the piece’s location)

Ctrl-1 - Trigger - Do Something to 1 Piece Per Stack
Trigger when Properties Match: CurrentX != $GenericX$ || CurrentY != $GenericY$
Perform these Keystrokes: Ctrl-X Ctrl-R

That’s it. Each time a piece is processed, if either its X location or its Y location is different from the piece previously affected, it must be in a different stack and is therefore given the result action (right after copying its own location for subsequent comparisons).

The reason I say this will work most of the time is because there’s a risk of overlap from a previous use of the command. If the first stack processed this time around happens to be the last stack processed last time around, then a piece from that stack will not be affected like it should be. You’ll have to analyze that risk in the context of your specific game implementation to determine whether it’s a show-stopper for you or not. If you know that some other action or type of action will always occur in between two different Ctrl-1 uses, then you can have that other action set GenericX and GenericY to wacky values to ensure that a fresh comparison will always be performed. If not, then you will have to move this functionality to something invoked from somewhere other than the pieces themselves, so you can begin by initializing GenericX and GenericY with unusual values before any comparisons are performed.