Heirukichi

Veteran
Veteran
Joined
Sep 24, 2015
Messages
1,461
Reaction score
625
First Language
Italian
Primarily Uses
RMVXA
I am sorry but the guide you linked is written in German, I can understand it to a certain extent, but I am not proficient enough to understand everything clearly (which is required when it comes to code requirements). Could you explain what you are trying to do in English?
 

mathmaster74

just...John
Veteran
Joined
Jun 12, 2016
Messages
285
Reaction score
195
First Language
English
Primarily Uses
RMMV
@Heirukichi The puzzle is a match 3 or more blocks in a line of the same color to make them disappear and figure out how to make them all disappear type of deal. The solution shown says first put three yellow blocks in line, then the remaining three yellow, then line up all 5 blue blocks as shown, then all 5 red. I think what the OP is asking is...how do you check if blocks in a line have adjacent blocks the same color, how do you determine the length of adjacent blocks that are the same color, and if there are three or more the same color together in line, how do you make sure they and only they get removed?
 

Feraleth

Veteran
Veteran
Joined
Jun 19, 2019
Messages
56
Reaction score
11
First Language
German
Primarily Uses
RMMV
[move]VXAce Support[/move]
Sorry, I thought, I'm right in the script forum, because I probably need a script for the solution. Thanks for the correction :)

@Heirukichi The puzzle is a match 3 or more blocks in a line of the same color to make them disappear and figure out how to make them all disappear type of deal. The solution shown says first put three yellow blocks in line, then the remaining three yellow, then line up all 5 blue blocks as shown, then all 5 red. I think what the OP is asking is...how do you check if blocks in a line have adjacent blocks the same color, how do you determine the length of adjacent blocks that are the same color, and if there are three or more the same color together in line, how do you make sure they and only they get removed?

Correct! The query is a problem because individual queries consume too much memory.
 

mathmaster74

just...John
Veteran
Joined
Jun 12, 2016
Messages
285
Reaction score
195
First Language
English
Primarily Uses
RMMV
@Feraleth What happens if you connect 3 of the 5 in line? Do you lose? (Since only 2 blocks would remain of that color.) Do you just not get something the puzzle unlocks? Or does the game only clear the blue and red when there's 5 in a row (preventing this scenario)?
 

Feraleth

Veteran
Veteran
Joined
Jun 19, 2019
Messages
56
Reaction score
11
First Language
German
Primarily Uses
RMMV
What happens if you connect 3 of the 5 in line? Do you lose? (Since only 2 blocks would remain of that color.) Do you just not get something the puzzle unlocks? Or does the game only clear the blue and red when there's 5 in a row (preventing this scenario)?

@mathmaster74 The blocks dissolve when 3 or more are in a row. If 2 are left, you have lost, yes. In this puzzle, there are 5 red, 5 purple and 6 orange blocks. If the puzzle is done, then you will continue to :)
 

mathmaster74

just...John
Veteran
Joined
Jun 12, 2016
Messages
285
Reaction score
195
First Language
English
Primarily Uses
RMMV
@Feraleth Okay. That does make the task harder. I really can't think of anything better than starting with the lowest numbered event and looking in all 4 directions around its coordinates at the adjacent squares...if no event, move on, if event present: does it match? If no, move on. If yes, then look 1 more away from original. If event present and matches, keep going until not. Then you have to check the opposite direction from the "start" of the link so you don't miss anything on the opposite side in case the original event is really in the middle of the lineup. Every time you find a match I would increase the value of a variable...maybe call it Tally. If Tally >= 3, then when no more matches, dissolve the blocks found to match. Of course, then you also have to somehow keep track of "the blocks found to match". I don't envy you the situation. It's tough.

Another approach might be to look across the map one row at a time and have variables that count Red, Purple, and Orange. If you don't get any counts above 3, you can move on to the next line. If you get any counts above 3, then you look at the first event of a color starting on the left (lowest X value) and move right 1 square at a time checking the adjacent squares. When you reach the end of a set of adjacent squares, if Tally < 3, then there's no match. If Tally = 3 you know to dissolve the original coordinate block and its X+1 and its X+2. If Tally = 4, you know to also dissolve X+3. If Tally = 5, you know to also dissolve X+4. If you dissolved anything, that was the only match this turn, so you can stop checking until the player moves another block. If you didn't dissolve the first color, check the second color the same way, then the third, then move to the next row. When you finish checking rows, you check columns the same way. That's about the best efficiency I can figure out.
 

Heirukichi

Veteran
Veteran
Joined
Sep 24, 2015
Messages
1,461
Reaction score
625
First Language
Italian
Primarily Uses
RMVXA
@Faraleth if you have a total of 16 block, that means that the player has to remove all the red blocks together, then all the purple blocks together and he or she can remove the orange blocks 3 by 3 (the order doesn't have to be like this, it can be a different one).

  • Step 1: Set up your blocks based on their color.
I would do it by storing blocks ID in a variable using a script call, this way you can use that variable to see if a certain event is a block of a certain color or not.
Code:
# Add more block IDs in their respective square brackets.
# Separate block IDs with commas.
$game_variables[pick_an_id_and_put_it_here] = {
  "red" => [red_block1_event_id, red_block2_event_id, red_block3_event_id], # add more block IDs here
  "purple" => [purple_block1_id, purple_block2_id], # etc. Same as the previous, put more IDs here
  "orange" => [orange_block1_id, orange_block2_id], # etc. Same as the previous ones.
} # do not remove this

Now you can see if a block is red or green by using the following script call:
Code:
$game_variables[same_id_you_used_before]["red"].include?(event_id_goes_here)
I used "red", but it works for any color mentioned in the previous script call. It tells you if the event with the given ID is part of the blocks of that color. If it is not, it returns false. If checking an event ID returns false for every single color, that event is not a movable block.


  • Step 2: check if three blocks are aligned
This is a little tricky and can be achieved with different implementations. The basic idea is that, only for the moved block, you check every possible direction and see if there are three blocks of the same color in that direction. You can round coordinates with direction (2, 4, 6 or 8 in VX Ace) with a built-in method like this:
Code:
x2 = $game_map.round_x_with_dir(x, y, direction)
y2 = $game_map.round_y_with_dir(x, y, dir)
Do not forget that you could align blocks in a(n) L shape, so you should not stop checking them when you find three of them in a row, check other directions as well and see if there are three blocks in that direction as well.

NOTE: I am not going to provide an implementation for this because the code is quite long and I do not know which implementation you want to use.


  • Step 3: check if there are 2 blocks left of the same color
To remove blocks you could set their self switch A (or any other self switch) on. Then you could check, for each block color, how many blocks of that color don't have their self switch ON. Once again, you need a script call for this.
Code:
lost = pick_a_switch_id
blocks = $game_variables[always_the_same_variable]
blocks.each_key do |k|
  available_blocks = 0
  blocks[k].each do |b|
    available_blocks += 1 unless $game_self_switches[[$game_map.map_id, b, 'A']]
  end
  $game_switches[lost] = ((available_blocks < 3) && (available_blocks > 0))
  break if $game_switches[lost]
end
SceneManager.call(Scene_Gameover) if $game_switches[lost]
This covers pretty much everything except for the implementation on how you want to check if blocks are aligned.

What @mathmaster74 said is true, except for the fact that events are not stored in the map as flags in a matrix, but they are separate arrays. This means that you cannot check them row by row, but you have to use the variable where you stored them to see if the coordinates of any block match the rounded ones (which is incredibly inefficient). If you want to use a matrix for that, you have to create one on your own, only then can you check blocks position efficiently.
 

mathmaster74

just...John
Veteran
Joined
Jun 12, 2016
Messages
285
Reaction score
195
First Language
English
Primarily Uses
RMMV
The basic idea is that, only for the moved block, you check every possible direction and see if there are three blocks of the same color in that direction.

@Heirukichi Derp! How could I have missed such an obvious point?! :oops: Yes! :biggrin: @Feraleth You only need to start with the moved block, so you need a way to know which one that is. Once you know that, you only need to check 3 directions around it (because the player should occupy the 4th, having just pushed the block from that side). Also, you should only need ever check 2 spaces in each of these 3 directions (because if you find a third space out that's the same color as the first two, then something should have already been cleared! :rolleyes:)

Do not forget that you could align blocks in a(n) L shape, so you should not stop checking them when you find three of them in a row, check other directions as well and see if there are three blocks in that direction as well.

NOTE: I am not going to provide an implementation for this because the code is quite long and I do not know which implementation you want to use.

Actually, I think the puzzle is to only dissolve when 3 or more are "in line". Otherwise things take on a serious order of complexity. Example: It's no longer necessary to have 3 in a row to have 3 adjacent. The 3 could be in an L-shape already. If "just adjacent" is what you're going for, then 4 blocks touching could look like a line segment, an L, a T, even an S (think pretty much every shape in Tetris except the 2x2 square). I came up with 18 configurations for 4 blocks touching, and some of these could be "completed" multiple ways, but only 2 configurations exist where they are all in line. Now extend that to 5 blocks touching and you can get a staircase pattern or a U-shape along with the L's, T's, S's, straight lines, etc. but again...only 2 configurations that are just straight lines. Hence, Feraleth, I think you want to stick to in-line checks...which are a lot easier now because you only need to look in 3 directions from the 1 block that was moved, and you only need look at most two spaces in any 1 direction. Checking those 3 directions from the block moved will actually still have the potential to catch L's and T's in case they are made such that they have 3 in a row going both horizontally and vertically using the perpendicular meeting block (the one that was moved). You just want to make sure that if you find 3 in a row going in 1 direction (say the X direction) you still want to check in the Y direction for 3 in a row also before clearing.

Step 3: check if there are 2 blocks left of the same color

I don't think you need to do this. If the player can't finish the puzzle because they have insufficient blocks of a color, they should figure that out before too long, and as was said...

If the puzzle is done, then you will continue to :)

Instead, step 3 would be to check if all blocks are dissolved, in which case, you supply the win reward.

EDIT: I also just realized there's an even more efficient way (possibly) to do this. First determine the player position relative to the moved block (say below), Then you check 1 space left, right, and above. If none of these are the same color, end the check and you've only looked at 3 squares before giving control back to the player, helping performance. If some matched but all didn't, still cut the directions that don't match from the search as it extends two spaces out. This way you're checking at most 6 map grid squares for matching colors, at most 5 if a branch gets cut, and at most 4 if 2 branches get cut. You will only have to check from 3 to 6 grid squares for matching colors using this method.
 
Last edited:

Heirukichi

Veteran
Veteran
Joined
Sep 24, 2015
Messages
1,461
Reaction score
625
First Language
Italian
Primarily Uses
RMVXA
Actually, I think the puzzle is to only dissolve when 3 or more are "in line". Otherwise things take on a serious order of complexity.
First of all, I think you missed the most obvious L shape: 5 blocks of the same color, that is the main reason why I mentioned checking other directions. If three blocks make a single row, and one of them is shared with another row of 3, that means the same block is part of two different rows, and that is the only way to remove 5 blocks at once. That allows for both T shapes and L shapes, and it can all be checked in the same way. The two rows being actually aligned to form a single row is just a particular case, there is 80% chance of them being not aligned, and only 20% chance of them being effectively aligned. Not considering the L and T shapes here would greatly reduce the amount of possible solutions.

The complexity does not change since you have to loop the checks for each direction, and using a break or not using it has no effect on the overall complexity (O(NX) = O(2X) = O(X)). Even checking just one square does not affect complexity. As I mentioned, VX Ace does not store events in a multi dimensional array; they are stored in a hash that takes IDs as keys. This means that, in order to check if an event is occupying a certain spot, you have to check all the events in the map (you can limit this to just blocks if you create a new array containing blocks).

The complexity of this algorithm is quite high. However, it can be reduced by initializing an array of blocks and modifying it later. Of course, if you do that, there is no point in checking tiles whose distance from the moved block is greater than 1 if there is no adjacent block of the same color.

If 2 are left, you have lost, yes.
To me "you lost" means Game Over, I don't know if the OP meant something else, but if you need a Game Over screen, you have to check if there are less than 3 blocks left of any color.
 
Last edited:

mathmaster74

just...John
Veteran
Joined
Jun 12, 2016
Messages
285
Reaction score
195
First Language
English
Primarily Uses
RMMV
I think you missed the most obvious L shape: 5 blocks of the same color
o_O

Checking those 3 directions from the block moved will actually still have the potential to catch L's and T's in case they are made such that they have 3 in a row going both horizontally and vertically using the perpendicular meeting block (the one that was moved). You just want to make sure that if you find 3 in a row going in 1 direction (say the X direction) you still want to check in the Y direction for 3 in a row also before clearing.

@Heirukichi Actually, the 5 block L-shape gets covered in my quote here, not missed. The 5 block T-shape gets caught too. :smile:

there is no point in checking tiles whose distance from the moved block is greater than 1 if there is no adjacent block of the same color.

Agreed. That's why I said:

First determine the player position relative to the moved block (say below), Then you check 1 space left, right, and above. If none of these are the same color, end the check and you've only looked at 3 squares before giving control back to the player, helping performance.
:wink:

The complexity does not change since you have to loop the checks for each direction

If you have to check for 5 adjacent blocks in a staircase formation, U-shape, S-shape, etc. on top of the simple method we've arrived at, there will be a potential (and probable) increase in checks needed where matches occur. In this case, you need to start with the block moved and check all 3 directions away from the player, then check from each matching block in all 3 directions away from the moved block. This could require up to 12 checks, and a more complex "loop" structure. 12 checks doesn't actually sound terrible, so if @Feraleth is willing to set up a 3-way check with 3 branching 3-way checks from there, then yes...all configurations of "3 or more adjacent" matches could be found. This could even catch a "7 block matching T" if there were 7 blocks of the same color. Of course, if any block adjacent to the first is not a match, then the 3-way branch from there need not be checked, so 12 checks could get cut to 9, then to 6, and even down to 3...matching the best case scenario of my previous solution to check only for the 5 block L, 5 block T, and 3-5 block in-line straight connections by simply looking up to 2 squares in each of the 3 directions going straight out around the block from the player.
 

Feraleth

Veteran
Veteran
Joined
Jun 19, 2019
Messages
56
Reaction score
11
First Language
German
Primarily Uses
RMMV
@mathmaster74 @Heirukichi

First of all, I would like to thank you very much for your efforts! Unfortunately, much of what you have written is difficult for me to understand.

I've tried to implement Heirukichi's guide. Unfortunately, I did not manage that.

Can you help me a bit with the implementation? It is very helpful if you can give me specific examples or templates. Unfortunately, I am not capable of scripting.

However, if I know how to insert something (similar to Heirukichi's instructions) then I will manage it for sure.

I am very thankful for the help :) Thank you!
 

Heirukichi

Veteran
Veteran
Joined
Sep 24, 2015
Messages
1,461
Reaction score
625
First Language
Italian
Primarily Uses
RMVXA
@mathmaster74 as I mentioned, since events are stored in a hash, you are forced to loop the check for each block regardless of when you stop. Stopping earlier because you are not going to check a certain shape does not reduce complexity and, in the worst case scenario, it does not reduce the number of checks either (as the adjacent one could be the last block you check). I have already said this twice, but VX Ace does not store events in a multi-dimensional array, you cannot access events using their coordinates, you can only perform a linear check, and compare the coordinates of the event you found to the coordinates you need.

On a side note, a staircase shape is a shape that does not contain 3 boxes of the same color aligned in the same row, they are just adjacent, and that is why I mentioned continuing to check in a certain direction, without changing it. And theories about 7 blocks or more are not useful in this situation, we already know that the maximum amount of possible blocks of the same color is 6. And, btw, in your post, you mentioned an L shape made of 3 blocks, that is not exactly what the OP asked for, as there are not 3 blocks in a line. Anyway, since this is not relevant to the topic, I am going to stop it here, we have already cleared up any misunderstanding.

@Feraleth the implementation takes quite a long time to be written, on top of it, there are two different ways to implement it: one that uses less memory, while being slower; the other that uses more memory, while being faster. Without knowing which one you want to use, I cannot help you here. I am not going to write a code that might prove to be useless later.

That said, depending on how much memory your game uses, I would recommend using the fast implementation and use up a bit more memory. This implementation takes a bit more time to be initialized because it requires you to create a multi-dimensional array for the whole map to be able to access events in T = O(1) based on their coordinates. Doing so means that you have to create a virtual copy of your map (like storing the map in your memory twice), but not doing it means using the default VX Ace way of handling events, resulting in a very ugly algorithm with a complexity of T = O(N^2). There are not so many blocks in your puzzle, but 16 * 16 = 256, and 256 is not exactly a small number of checks. Not to mention that you have to check everything more than twice, which increases that to at least 768 checks.

However, if your game already uses a lot of memory, you might want to go for this ugly method. After all it only happens once when a block is moved, it does not happen continuously.
 

Trihan

Speedy Scripter
Veteran
Joined
Apr 12, 2012
Messages
5,038
Reaction score
4,650
First Language
English
Primarily Uses
RMMZ
@mathmaster74 as I mentioned, since events are stored in a hash, you are forced to loop the check for each block regardless of when you stop. Stopping earlier because you are not going to check a certain shape does not reduce complexity and, in the worst case scenario, it does not reduce the number of checks either (as the adjacent one could be the last block you check). I have already said this twice, but VX Ace does not store events in a multi-dimensional array, you cannot access events using their coordinates, you can only perform a linear check, and compare the coordinates of the event you found to the coordinates you need.

On a side note, a staircase shape is a shape that does not contain 3 boxes of the same color aligned in the same row, they are just adjacent, and that is why I mentioned continuing to check in a certain direction, without changing it. And theories about 7 blocks or more are not useful in this situation, we already know that the maximum amount of possible blocks of the same color is 6. And, btw, in your post, you mentioned an L shape made of 3 blocks, that is not exactly what the OP asked for, as there are not 3 blocks in a line. Anyway, since this is not relevant to the topic, I am going to stop it here, we have already cleared up any misunderstanding.

@Feraleth the implementation takes quite a long time to be written, on top of it, there are two different ways to implement it: one that uses less memory, while being slower; the other that uses more memory, while being faster. Without knowing which one you want to use, I cannot help you here. I am not going to write a code that might prove to be useless later.

That said, depending on how much memory your game uses, I would recommend using the fast implementation and use up a bit more memory. This implementation takes a bit more time to be initialized because it requires you to create a multi-dimensional array for the whole map to be able to access events in T = O(1) based on their coordinates. Doing so means that you have to create a virtual copy of your map (like storing the map in your memory twice), but not doing it means using the default VX Ace way of handling events, resulting in a very ugly algorithm with a complexity of T = O(N^2). There are not so many blocks in your puzzle, but 16 * 16 = 256, and 256 is not exactly a small number of checks. Not to mention that you have to check everything more than twice, which increases that to at least 768 checks.

However, if your game already uses a lot of memory, you might want to go for this ugly method. After all it only happens once when a block is moved, it does not happen continuously.

Just a quick note on what you said about the way VX Ace stores events; $game_map.events_xy can access events using coordinates (or events_xy_nt if you want to exclude pass-through events).
 

Heirukichi

Veteran
Veteran
Joined
Sep 24, 2015
Messages
1,461
Reaction score
625
First Language
Italian
Primarily Uses
RMVXA
@Trihan that method calls the select method, which is a linear check. It does not allow you to directly access events with coordinates (T = O(1)).
 

Trihan

Speedy Scripter
Veteran
Joined
Apr 12, 2012
Messages
5,038
Reaction score
4,650
First Language
English
Primarily Uses
RMMZ
Why would you need to do that though? All you need to do is check up to 2 tiles to the left, right, above and below the one that was moved. If the event on that tile is a matching block, or the tile doesn't contain a matching block but the previous one does, add the previous one to an array of blocks to be removed in that direction (which starts out containing the moved block). For any array with 3 or more elements in it, remove those blocks.

This will also factor in the L or T shape matches.
 

Heirukichi

Veteran
Veteran
Joined
Sep 24, 2015
Messages
1,461
Reaction score
625
First Language
Italian
Primarily Uses
RMVXA
All you need to do is check up to 2 tiles to the left, right, above and below the one that was moved. If the event on that tile is a matching block, add the previous one to an array of blocks to be removed in that direction. For any array with 3 or more elements in it, remove those blocks.
Because performing those 8 checks with that method means performing 8*N checks (N is the number of events in the map). It is not exactly efficient in my opinion especially if the map is big and there are a lot of events.

EDIT: not to mention that, for each event, you have to check if it is a block and return its color (eventually). This makes the best case scenario have a complexity of T = 8N * B = O(N*B) = O(B^2). B is the number of blocks in this case. And in the end, with 16 blocks, you have to perform a total of (8 * N * 16 = 128 * N) checks. Once again, I do not call that efficient.

EDIT2: Please note that N is greater than or equal to 16, leading to at least 2048 checks.
 
Last edited:

Trihan

Speedy Scripter
Veteran
Joined
Apr 12, 2012
Messages
5,038
Reaction score
4,650
First Language
English
Primarily Uses
RMMZ
If it helps you don't need to do any computational checks to get which event was moved. In the event code, if you use

Code:
$game_map.events[@event_id]

you'll get the Game_Event instance corresponding to the one you just interacted with.
 

Heirukichi

Veteran
Veteran
Joined
Sep 24, 2015
Messages
1,461
Reaction score
625
First Language
Italian
Primarily Uses
RMVXA
@Trihan I know that, as a matter of fact I only mentioned 8 checks for each block and not 9, since the moved one is not included, but you still need to perform at least 2048 checks if you use that method. The same can be achieved with a mere 128 checks if you initialize a multi-dimensional array. It is at least 16 times faster.

Of course, the difference is even greater if you have more than just block events in the map.
 

Latest Threads

Latest Posts

Latest Profile Posts

The game's already out there. Now what?
It has now gotten to the point where I need detailed excel spreadsheets to track where every individual enemy on the map is, what type of enemy they are and how many rooms you need to pass through to make them respawn.

I'm simultaneously proud of my diligence and would never wish this torture on even my worst enemies. :kaoswt2:
Variation two of my nameless protagonist- now with color!!
WIN_20220815_21_48_46_Pro.jpg
thoughts?
Fun question - how do you manage the scope of your projects? All of my projects seem to balloon until they pop and they are suddenly nonexistent!

Forum statistics

Threads
124,573
Messages
1,164,479
Members
163,393
Latest member
MayShouE
Top