MINESWEEPER FLAGS
Posts
Pages:
1
This is a very specific coding problem, so I'll break it down:
Setup
OK, so I am working on a minesweeper-esque mini-game in rm2k3/ I have everything coded exactly as I want it, but the flagging is giving me some trouble.
Basically, I have ambiguous tiled events, that can be called as flags, bombs or normal cells, each corresponding to their own action, since you can make any cell on the grid flagged. The max amount of flags is 5. I use a counter var on a loop to decide when you place a flag, which number are you placing, and then record those vars to the corresponding flag X and Y. Each flag is mapped to 2 switches, 1 turns on when you hover over its position with the cursor, the other one tests if there is a flag open in the loc of your cursor, it turns off that flag.
Problem
That much works fine so far. But the problem arises because of the linear creation of the flag placement. For example, if you place flags |1|-|2|-|3| and then erase flag 2, the code will be unsure which flag to place next because there is a gap. (even if flags aren't next to each other, all flags after the gap need to be erased to have the order/hierarchy stay intact.)
Tried Solutions
I have tried 2 solutions to this. The first one simply adds +1 or -1 at the end of each turn flag off case, which is fine for counting the amount of flags you have left/flags you have placed, but doesn't help the integrity of ordered hierarchy.
The 2nd solution I tried was a bit more complex. I basically used pointer vars, set them depending on which flag the cursor was on, and used temp vars to roll back the pointers by 2 (to hit the x/y of previous flag in var list) and test if those coords were 0, indicating a gap, that I could fill by branching. This theoretically should work but in testing has not helped.
Question
How do I make it so the flags can be placed/erased in any order? For ex. Placing flag 1-2-3-4, erasing 2-3 and then have the next flag placed be 2, then 3, then 5?
Setup
OK, so I am working on a minesweeper-esque mini-game in rm2k3/ I have everything coded exactly as I want it, but the flagging is giving me some trouble.
Basically, I have ambiguous tiled events, that can be called as flags, bombs or normal cells, each corresponding to their own action, since you can make any cell on the grid flagged. The max amount of flags is 5. I use a counter var on a loop to decide when you place a flag, which number are you placing, and then record those vars to the corresponding flag X and Y. Each flag is mapped to 2 switches, 1 turns on when you hover over its position with the cursor, the other one tests if there is a flag open in the loc of your cursor, it turns off that flag.
Problem
That much works fine so far. But the problem arises because of the linear creation of the flag placement. For example, if you place flags |1|-|2|-|3| and then erase flag 2, the code will be unsure which flag to place next because there is a gap. (even if flags aren't next to each other, all flags after the gap need to be erased to have the order/hierarchy stay intact.)
Tried Solutions
I have tried 2 solutions to this. The first one simply adds +1 or -1 at the end of each turn flag off case, which is fine for counting the amount of flags you have left/flags you have placed, but doesn't help the integrity of ordered hierarchy.
The 2nd solution I tried was a bit more complex. I basically used pointer vars, set them depending on which flag the cursor was on, and used temp vars to roll back the pointers by 2 (to hit the x/y of previous flag in var list) and test if those coords were 0, indicating a gap, that I could fill by branching. This theoretically should work but in testing has not helped.
Question
How do I make it so the flags can be placed/erased in any order? For ex. Placing flag 1-2-3-4, erasing 2-3 and then have the next flag placed be 2, then 3, then 5?
Solution no.1 seems simple and fine.
Why would you want to keep track of flag "order hierarchy"? I think getting rid of it would solve the problem.
Why would you want to keep track of flag "order hierarchy"? I think getting rid of it would solve the problem.
You're right in that I was probably over thinking my solution. Solution 1 does work to some extent, but sometimes you'll have to press shift multiple times to make a flag, and sometimes the same problem occurs of not being able to place a flag despite having flags left on the counter.
Here is ze code:
But with 4 more cases on either side for all 5 flags, this shows only 1 flag for the sake of simplicity.
This is run on a pp event that deals with all the other button presses too.
But with 4 more cases on either side for all 5 flags, this shows only 1 flag for the sake of simplicity.
This is run on a pp event that deals with all the other button presses too.
That looks awfully complicated :P
How about something along the lines of this:
Parallel Process event:
If Shift is pressed,
> If "counter" is less than 5,
>> Check cursor position/tile...
>> If position/tile is not on an already flagged tile,
>>> (put a flag) "counter" +1
>> Else: (remove flag) "counter" -1
> Else: ("You can't put anymore flags!")
Would this work for you?
Make sure you use separate events to code the effects of every key pressed. It's easier to approach that way.
How about something along the lines of this:
Parallel Process event:
If Shift is pressed,
> If "counter" is less than 5,
>> Check cursor position/tile...
>> If position/tile is not on an already flagged tile,
>>> (put a flag) "counter" +1
>> Else: (remove flag) "counter" -1
> Else: ("You can't put anymore flags!")
Would this work for you?
Make sure you use separate events to code the effects of every key pressed. It's easier to approach that way.
Yeah I can do that, it's basically what I was doing, just combining them into one branch with an else case instead of 2 separate branches. Not sure if that will change much, but will try.
Also separate events for each key? How inefficient.
EDIT: As expected, it yields the same results, because it only reorganizes the code but doesn't change/fix the problem.
Also separate events for each key? How inefficient.
EDIT: As expected, it yields the same results, because it only reorganizes the code but doesn't change/fix the problem.
The problem with the gaps isn't all that hard to fix efficiently. You can do that by swapping the positions of the flags upon trying to remove a flag. Imagine having placed all 5 flags and you want to remove flag #2
Swapping the positions of the flags and then removing the flag of highest value ensures that the counter will always point to the next flag, while all other flags will stay at the same positions.
Swapping the positions of the flags and then removing the flag of highest value ensures that the counter will always point to the next flag, while all other flags will stay at the same positions.
Brilliant concept. I just have to translate it into code. So basically, for this example:
-branch if switch to erase flag 2 is on and shift is pressed
-branch if counter is 5
--set vars flag 5 X and Y to flag 2 X and Y
--set vars flag 2 X and Y to flag 5 X and Y
--erase flag 5
--counter +1
Wouldn't a lot of branches be needed to determine which flag is getting switched with which?
-branch if switch to erase flag 2 is on and shift is pressed
-branch if counter is 5
--set vars flag 5 X and Y to flag 2 X and Y
--set vars flag 2 X and Y to flag 5 X and Y
--erase flag 5
--counter +1
Wouldn't a lot of branches be needed to determine which flag is getting switched with which?
Just use another variable to store the number of the highest flag and then use that to determine which flag is being switched with.
Not entirely certain how your setup is working in detail. Do you put a "flag event" onto the tiles you mark? or is the flag contained within the tile event itself?
I'm pretty certain that you can avoid a hell of a lot of branches by using pointers or similar means, but exactly how depends on exactly how it works of course.
if the flag event is on of it's own, then it could be as simple as
- geteventID of tile with flag
- use eventID to determine which flag it is
- use the counter to determine the highest valued flag in the field
- set the coordinates of the flag you want to delete to that of the highest valued flag, and move it there
- move the highest value flag out of visibility and reduce the counter by one.
using the eventID, you could also figure what to add/subtract from that value to point the variables storing their coordinates to handle it more elegantly as well.
i.e. flag 1 has ID 31 and flag 1 x is stored in variable 11 and flag 1 y in variables 21. you can then take the ID, subtract by 10, store the y coordinate into where the variable is pointing, subtract by 10 again and store the x coordinate the same way.
I'm pretty certain that you can avoid a hell of a lot of branches by using pointers or similar means, but exactly how depends on exactly how it works of course.
if the flag event is on of it's own, then it could be as simple as
- geteventID of tile with flag
- use eventID to determine which flag it is
- use the counter to determine the highest valued flag in the field
- set the coordinates of the flag you want to delete to that of the highest valued flag, and move it there
- move the highest value flag out of visibility and reduce the counter by one.
using the eventID, you could also figure what to add/subtract from that value to point the variables storing their coordinates to handle it more elegantly as well.
i.e. flag 1 has ID 31 and flag 1 x is stored in variable 11 and flag 1 y in variables 21. you can then take the ID, subtract by 10, store the y coordinate into where the variable is pointing, subtract by 10 again and store the x coordinate the same way.
Well, the way it's setup is that any cell can be flagged, so I have events with 4 pages. 1st page changes "this event" graphic to flag, the 4th page changes "this event" to normal tile. Page 2 and 3 are for bomb or normal cell. The main process stores the event ID of the tile below the cursor and then calls that event by setting page ID to whatever's necessary.
I could set it up with separate flag events that set to the cursor's position when you turn them on, and then follow the method outlined above.
Maybe this is misunderstanding but I don't see the point of intertwining pointers with the event ID to store the coords. Is this just for the sake of efficiency?
I could set it up with separate flag events that set to the cursor's position when you turn them on, and then follow the method outlined above.
Maybe this is misunderstanding but I don't see the point of intertwining pointers with the event ID to store the coords. Is this just for the sake of efficiency?
depends if you actually have any use for the coordinates themselves. I don't know how you handle every aspect of the minigame so hard to tell, as in the regular mine sweeper, flags are pretty much only there for the ease of using the shortcut buttons to open all the nearby cells which you've implicit told can't be mines.
If there's no need to store the coordinates, I'm unsure if there'd be any need to "give the flags" specific numbers, since you could make the "flag event" trigger on switch 1 to 25 (for a grid of 5x5) and then address the switch by a pointer to on or of directly by relating it to the eventID. This would mean you wouldn't have to worry about any gaps, since the only thing mattering would be the counter preventing you from setting too many flags.
If there's no need to store the coordinates, I'm unsure if there'd be any need to "give the flags" specific numbers, since you could make the "flag event" trigger on switch 1 to 25 (for a grid of 5x5) and then address the switch by a pointer to on or of directly by relating it to the eventID. This would mean you wouldn't have to worry about any gaps, since the only thing mattering would be the counter preventing you from setting too many flags.
You're right in that I don't need to store the flag coords. So to do the switch method, I would have to trace the cursor movement with a switch pointer? So if the cursor starts, on a 5x5 grid to the topmost leftmost cell, the pointer is set to to that switch number, so it would be set to 1, since it's the first cell, the added to or subtracted to depending on where the cursor is so that it is synced.
Or am I calling the event ID of the event under the cursor when shift is pressed, and then turning on a flag switch (1-25) depending on that ID? So if ID is 25, then turn on the 25th switch, which puts a flag on that 25th cell.
Or am I calling the event ID of the event under the cursor when shift is pressed, and then turning on a flag switch (1-25) depending on that ID? So if ID is 25, then turn on the 25th switch, which puts a flag on that 25th cell.
The easiest way would be to use the eventID, yes. by using events of ID 1 to 25 and switches 1 to 25 for flags, you could simply use get event ID and the "switch on" by variable reference, yes.
Doing it the other way is perfectly possible as well, but requires more branches and stuff. i.e. add 1 to pointer if going right (if possible), add 5 to pointer if going down (if possible) and so on.
Either way, for practicality, you might want to make a page in each event which allows you to check if "their switch" is on, since you can unfortunatly not reference a switch to find out it's value for a branch.
Doing it the other way is perfectly possible as well, but requires more branches and stuff. i.e. add 1 to pointer if going right (if possible), add 5 to pointer if going down (if possible) and so on.
Either way, for practicality, you might want to make a page in each event which allows you to check if "their switch" is on, since you can unfortunatly not reference a switch to find out it's value for a branch.
I got it working! I did the trading method that you suggested earlier with separate flag events. Probably could have made it more efficient with pointers but as long as it works I can sleep easy. Finally made use of the "trade 2 event locations" command. Thanks for saving my hide again, Kazesui. Also was that trading method a variation of fisher-yates algorithm?
And for the sake of hypothetical theory about the switch method, do you mean each event would be called to check if it's switch was on and then change the pointer value depending on that?
And for the sake of hypothetical theory about the switch method, do you mean each event would be called to check if it's switch was on and then change the pointer value depending on that?
Good to hear that you got it working
From skimming through the wiki definition of fisher-yates algorithm, it doesn't really sound like a variation of it, with it rather just being a shuffling method which use the same trick. There are other algorithms which use the same trick as well, so one cannot exactly attribute it to fisher-yates.
and yeah, let's say event on tile 1 checks if switch 1 is on and if yes turn a temporary switch on, while event on tile 2 does checks if switch 2 is on and if so turns the same temporary switch on. By doing this, you could use "call event" to figure out if one of the events has it's switch activated, which saves you for tons of branching.
From skimming through the wiki definition of fisher-yates algorithm, it doesn't really sound like a variation of it, with it rather just being a shuffling method which use the same trick. There are other algorithms which use the same trick as well, so one cannot exactly attribute it to fisher-yates.
and yeah, let's say event on tile 1 checks if switch 1 is on and if yes turn a temporary switch on, while event on tile 2 does checks if switch 2 is on and if so turns the same temporary switch on. By doing this, you could use "call event" to figure out if one of the events has it's switch activated, which saves you for tons of branching.
Pages:
1