Ways to store and retrieve values from arbitrarily long strings, or other solutions

First, what I have done:

I have implemented a unit shuffling system for a block wargame, where you select X pieces, and shuffle them so your opponent no longer knows which is which. That was relatively simple: store the cursor coordinates as global properties, send all selected pieces to shuffle deck, send them back to the coordinates one by one with an incrementing loop increasing the y-coordinate value.

What I want to do:

The same thing, but return each of the pieces to a different one of the set of coordinates that they started at.

One problem:

I don’t really want to arbitrarily cap the number of pieces this can be done with, so I don’t want to have X * 2 global properties to store all the coordinate sets. So I was thinking maybe the initial command can have each selected piece write its coordinates to a single global property using string functions somehow? But I have no idea how to approach this or whether it is feasible.

Anyone have any solutions? Not necessarily restricted to the vague idea I had. Or just tell me it’s impossible without custom code. Any contribution would be appreciated!

OK, I figured this out, no-one else needs spend time on it =)

Using a Global Property “Positions”, the selected pieces each write {Positions + CurrentX + "," + CurrentY + ";"}.

They all get sent to the shuffle deck.

The first one out gets sent to {Positions.substring(0, Positions.indexOf(","))} for X and {Positions.substring(Positions.indexOf(",") + 1, Positions.indexOf(";"))} for Y then writes {Positions.substring(Positions.indexOf(";") + 1)} to delete the first coordinate set.

There’s some more shenanigans to make sure all the pieces do some of the sequence and only one does the whole sequence, but that’s basically all there is to it. I had no idea strings could be so handy, or easy to use. After figuring this out, I feel like I’ve been using Vassal with blinkers on…

You know, I would have tried something different. I would have created an invisible piece that contained x and y plus machinery to get a block and place it. I would put all these pieces in a special deck that I could shuffle or not. I could then pop pieces off this stack to place the blocks.

I’m not sure if you are solving the same problem. Sounds similar to how I did the initial command (shuffle and tidy) though, returning to cursor coordinates, though again I didn’t use a control piece for that. With a hard limit on the number of blocks in the game, there didn’t seem to be much benefit in keeping the pieces themselves as simple as possible.

It sounded like you were using global properties and strings to store an array of coordinates. I’m suggesting an alternative where I store each coordinate as a piece in a deck. I’ve done something like this before where pieces weren’t pieces in the classic sense, I’m not suggesting you change anything. I’m just talking.

I don’t fully understand the details from that description. If you feel like detailing your solution, please do.

The conditions it would have to satisfy are:

X pieces anywhere on a ~3000 x 3000 pixel board, no grid, each piece having a unique XY coordinate.
Command executable from a right-click menu or keypress activated on one of the selected pieces itself, and no further input required.
To the user, the X pieces do not appear to move at all, they just get rearranged/shuffled in place.

As you say, I already have my solution, so I’m not likely to change anything, but it never hurts to learn new tricks.

Okay, it’s possible I won’t do what you want, but who cares.
I load a scenario, and it has 12 blocks scattered on the map. They could be masked; I don’t care. There may be more or less than 12; I don’t care. Everybody knows what’s where. Each block has a right click command. If I right click any block, it first sends the GKC “alpha” to every block. Then it sends “beta.” This causes all blocks to shuffle so everybody is (probably) in a different block spot, but no one will know it happened. It’s magic.

An overview of how it works: When each block gets the alpha command, it does place-marker. It creates a piece I call a “bogus” piece because it’s not like a real piece. A bogus piece saves its (x,y) location and then sends itself to a special always-shuffle bogus deck. When done, the deck will have 12 pieces.

When each block gets the beta command, it summons a random piece from the bogus deck at the same time loading its UniqueID into the bogus piece. The bogus piece tells its summoner (via the UniqueID) its (x,y). The bogus guy deletes itself, and the block goes to this new (x,y). Below are the gory details.

First, I create a deck called BogusDeck. It always shuffles.

I create a prototype called Bogus. It defines an invisible piece that is not like the pieces we know and love. It is simply an information container. Here’s what it looks like.

prototype Bogus
Dynamic property myX command set = $CurrentX$
Dynamic property myY command set = $CurrentY$
return-to-deck BogusDeck
Trigger STORE
…set
…return-to-deck BogusDeck
//
Dynamic property caller
Trigger SUMMON
…set-piece-property
…Delete
Set-piece-property
Delete trait.

Block has 2 new dynamic properties: newBlockX and newBlockY.
When it gets the alpha GKC, it does place-marker. The marker is a new piece, no image, prototype Bogus. It sends STORE to the bogus piece. The bogus piece stores its (x,y) location, which is the block’s location. It then goes to BogusDeck. Every other block does the same thing, so BogusDeck has 12 bogus pieces with each holding a unique (x,y).

Then the right-clicked block sends a beta GKC to all blocks. A block that receives beta sends SUMMON to BogusDeck. It says get one piece, and it also downloads its property UniqueID into the bogus piece’s “caller” dynamic property.

The bogus piece does set-piece-property with the matching expression:
{ UniqueID == “$caller$” }. It sets newBlockX=myX and newBlockY=myY. i..e. it’s downloading a new (x,y) into the block. The block then simply goes to (newBlockX, newBlockY).

When it’s all done, all blocks will have changed places, and BogusDeck is empty. BTW, I would either restrict what goes into BogusDeck or move it to (-1,0) because otherwise someone could drop a piece on it and have it disappear forever.

Sounds like it would work, thanks for indulging my curiosity!

(It also sounds way more convoluted and cumbersome, but I guess it would have been a way to get things to work before all the beanshell strings functions were added.)

The point I make is I’m showing a technique where I treat a piece not as a classic piece but as a container. I can store containers in a deck, which becomes a pushdown stack or even an array if I’m careful. I’ve used containers in the past to do some really wild things. I don’t think it’s cumbersome or convoluted because I’m accustomed to it. And this may sound weird, but it’s a fun thing to implement too.

Definitely the “I not only passed, I also have a good understanding of the material taught in my Data Structures and Algorithms course” solution. It’s indirect, but probably much fewer CPU cycles.

Take a course from a good university (or a free online course from a good university) on the subject of Data Structures and Algorithms. If all else fails, I believe O’ Reily has a book devoted to the subject.

Or look through this list:

Learning DS&A will open your eyes and make obvious how a lot of apparently difficult things are actually done in applications, libraries, and operating systems code.

Once you do that, and if you’re familiar with any assembly language, you might even be brave enough to try a course in which you actually have to write a multi-user*, multi-tasking** operating system for a microprocessor. (I had 13-week ONE CREDIT HOUR systems programming lab (using lowly 8-bit 6809 microprocessor-based single board computers… with a very primative bare-bones system monitor in the ROM) in which we had, as a mere 4-week project (so essentially 1/3 of a credit hour) to write an operating system on the 6809 with multi-user, multi-tasking AND inter-process communication (data passing between separate processes run by the same user, or between different users). By the time I was done with that project, I had lost ALL respect of Microsoft and what they were charging for the very crippled excuse for an operating system they sold under the name MS-DOS. This was in 1988.

_* timesharing, not the microsoft fraudulent use of the term of different usernames, but only one person can be logged in at a time

** each user could spawn multiple processes

Hah, I think I’ll take your word for it instead! I’m quite willing to accept I was mistaken. I don’t understand how or why, but I accept it.

I will continue to enjoy my new understanding of string functions for a while though, before venturing into throwing “bogus pieces” around as data containers.

Understand that your approach to use strings is nothing to snicker at. It as legitimate as any other approach. In fact, I’m thinking there are ways I could use it myself.

When it comes down to it, all memory is just a string, interpreted in different ways defined by the CPU, further defined in the language, and extended by new type definitions in languages that allow it (such as “struct” in C, and classes in C++ and Java), and whatever weird and downright unholy chicken-waving ceremonies occur in the Javascript interpreter and (pseudo?)libraries.