Legacy GM [SOLVED] Trying to update ds_grid diagonally

T

Tyrolean Dairy Co.

Guest
I have a ds_grid that I sometimes need to update in a diagonal fashion and I wondered if anyone could suggest a method.

The attached image shows what I'm trying to do (the actual grid is larger). First the red diagonal (1 cell) is updated, then the yellow (2 cells), then the green (3 cells) and so on. In the pic I'm working from the North-West to the South-East but I'd like to be able to adapt the code for the three other diagonal directions too.

I'm using versions of the following code to update the ds_grid horizontally and vertically:

for (zwc = 0; zwc < w; zwc++) { // cycle through width of grid
for (zhc = 0; zhc < h; zhc++) { // cycle through height of grid
///MAGIC HERE// }}

..but can't work out how to adapt it for diagonals.

All suggestions much appreciated. Thanks.dsgridproblem.jpg

(the numbers in the grid cells are to show order only. The actual values will vary)

[
 
Last edited by a moderator:
Code:
h = 6;
w = 6;
grid = ds_grid_create(h,w);
for (var no=h-1;no>0;no--) {
   var xx=0;
   var yy = no;
   var repeats = h-yy;
   repeat(repeats) {
      grid[# xx,yy]++;
      xx += 1;
      yy += 1;
   }
}
This loops through the grid, adding 1 to each grid spot in a diagonal fashion. Haven't tested it yet so it might need a little tweaking.
 
T

Tyrolean Dairy Co.

Guest
Thanks a lot. Your code is beyond my expertise/comprehension level but I'll give it a try and report back.
 

NightFrost

Member
RefresherTowel has the correct idea, but the code fills only part of the grid. This code walks it all the way through and works on both wide and tall grids.
Code:
Width = 11;
Height = 5;
Diagonals = Width + Height - 1;
Counter = 1;
Grid = ds_grid_create(Width, Height);
for(var Position = 0; Position < Diagonals; Position++){
   var xx = max(0, Position - (Height - 1));
   var yy = max(0, Height - Position - 1);
   repeat(min(min(Position + 1, min(Width, Height)), Diagonals - Position)){
       Grid[# xx++, yy++] = Counter++;
   }
}
Edit: just filling the grid with x and y loops would be a lot easier, but this walks through the grid cells in diagonal order as requested.
 
Last edited:
T

Tyrolean Dairy Co.

Guest
That's very helpful, thanks. I intend to implement this tomorrow and will let you know how I get on.
 
T

Tyrolean Dairy Co.

Guest
NightFrost, your diagonal code works beautifully, but my rudimentary GM skills mean I'm struggling to adapt it for situations when the updating of a particular grid cell is conditional on the value already assigned to that cell.

If you're happy to help further, where in the above should I put my "if ds_grid_get(Grid,xx,yy) < 5 {ds_grid set(Grid,xx,yy, newnumber}" -type statement so that it runs once for each cell and doesn't disrupt the code?
 

NightFrost

Member
I assume the order in which the cells are checked for update doesn't matter? I mean, you don't need to run them diagonally for this, just check each cell once and update its value if necessary? In that case you can do with a simple height and width loop:
Code:
for(var yy = 0; yy < Height; yy++){
    for(var xx = 0; xx < Width; xx++){
        if(Grid[# xx, yy] < 5) Grid[# xx, yy] = newnumber;
    }
}
Note that you can use the #-accessor to both read and write to the grid, it is faster than typing out the getter and setter.
 
T

Tyrolean Dairy Co.

Guest
Thanks. Diagonal runs incorporating cell checks/changes is what I'm hoping to achieve. It's a little difficult to explain, but I reset a variable at the start of each diagonal then use this variable to alter the cells on the diagonal. It's not dissimilar to a Line-of-Sight/Line-of-Fire system - cells at the start of a diagonal can, in effect, block/shield cells towards the end.
 

NightFrost

Member
Oh, okay. The code is structured this way: the for-loop goes through the diagonals by counting from zero up to the maximum count of diagonals on your grid (thus width + height - 1). The calculations for xx and yy determine where the diagonal starts. The repeat-loop goes through the cells belonging to currently operated diagonal. There's some number-wrangling in the command, it checks how many cells there are to that diagonal based on the width and height of the grid. So when you want to reset variables for each diagonal, you do it right before repeat and apply to each cell inside the loop. So if your newnumber is in some manner based on current diagonal, for example calculated in a script, you'd write the central loop something like:
Code:
var newnumber = getmynewnumber(Position);
repeat(min(min(Position + 1, min(Width, Height)), Diagonals - Position)){
    if(Grid[# xx, yy] < 5) Grid[# xx, yy] = newnumber;
    xx++;
    yy++;
}
Note how the xx and yy advancement is now separated so it doesn't mess up the get-set process.
 
T

Tyrolean Dairy Co.

Guest
Immensely helpful. Thank you for talking me through the code.
 
T

Tyrolean Dairy Co.

Guest
NightFrost, if it isn't too much trouble could you explain how to adapt your code for NE-to-SW, SE-to-NW, and SW-to-NE grid updating? The code above works perfectly for NW-to-SE diagonals but repurposing it for the three other diagonal directions is, I now realise, beyond me.
 

NightFrost

Member
The calculations depend on what is the start position for each. In the first case, you are starting in lower left corner and work towards southeast. What would be starts for other three directions?
 
T

Tyrolean Dairy Co.

Guest
Thanks. The start location isn't crucial but in order to keep things fairly consistent I was thinking of starting southwest checks in the lower-right corner, northwest checks in the upper-right, and northeast checks in the upper-left corner....

diagonalchecks.jpg
 
Top