SOLVED: Storing multiple values in 1 ds grid position

Discussion in 'Programming' started by Bentley, Nov 13, 2017.

Tags:
  1. Bentley

    Bentley Member

    Joined:
    Jun 18, 2017
    Posts:
    827
    Is there an easier way to store multiple values in one grid position than something like this:

    Code:
    //Pseudocode
    var grid_width = 10;
    var grid_height = 10;
    cell_type = ds_grid_create(grid_width, grid_height); //ds_grid of the cell's type
    cell_h = ds_grid_create(grid_width, grid_height); //ds_grid of that same cell's h value
    //etc. for other values I'd need the cell to have
    for (var xx = 0; xx < grid_width; xx++)
    {
        for (var yy = 0; yy < grid_height ; yy++)
        {
            cell_type[# xx, yy] = NULL;
            cell_h[# xx, yy] = point_distance(xx, yy, goal.x div CELL_SIZE, goal.y div CELL_SIZE);
        }
    }
    
    When browsing this forum, I came across these ideas: set each grid position to an object, to an array, or to a ds list. I was just curious if there's an easier way. I'd imagine the above code gets pretty messy, especially when you need to add up several values a cell has. I'd imagine a ds_list for each position would be messy too, because that's a lot of lists to destroy. Is setting each ds_grid position to an object, and then using that object to store that position's values the best way to go?

    I'm probably missing something obvious : ( Any ideas / suggestions are welcomed. Thanks for reading.
     
    Last edited: Dec 3, 2017
  2. DukeSoft

    DukeSoft Member

    Joined:
    Jun 20, 2016
    Posts:
    799
    You could use arrays to store multiple bits of information.

    You could use ENUM's to set the array indices :)
     
    ParodyKnaveBob and Bentley like this.
  3. PNelly

    PNelly Member

    Joined:
    Jun 20, 2016
    Posts:
    256
    If you want to store multiple values in one spot there's no getting around creating space for those multiple values. Your multiple grids/arrays approach does work, but will waste space if you have lots of empty cells (not really a concern if these are small grids and there aren't very many). Personally I'd find that approach annoying because there's a lot of grids you have to remember.

    I'd suggest pointing each entry in the grid to a ds_map. The key/value pairing makes it easy both to remember what you're doing and you don't have to concern yourself with the internal ordering of the elements.

    So something like:
    Code:
    grid_of_maps = ds_grid_create(width, height);
    
    var _x, _y, _cell_map;
    
    for(_x = 0; _x<width; _x++){
      for(_y = 0; _y<height; _y++){
        
        _cell_map = ds_map_create();
        grid_of_maps[# _x, _y] = _cell_map;
    
        _cell_map[? "type"] = "null";
        _cell_map[? "distance"] = point_distance(_x, _y, goal.x div cell_size, goal.y div cell_size);
        _cell_map[? "another_property"] = "whatever you want";
    
      }
    }
    
    I'd suggest you steer clear of pointing grid cells to objects representing the cell contents because it introduces unnecessary overhead for each of those instances that won't be doing you any good. And whether your grid points to objects, lists, or maps, you still have to tidy up or you'll be leaking memory.
     
    Bentley and DukeSoft like this.
  4. DukeSoft

    DukeSoft Member

    Joined:
    Jun 20, 2016
    Posts:
    799
    But that would create an entire map for every item in the grid. Maps aren't _that_ fast and you'd be better off using arrays - they are stored as pointers in memory and get automatically cleaned up. The ds_save functions also all work with arrays in the grids (tested this!) and in general they take up very little memory and are easy to access.
    Code:
    enum enumData{
        type = 0,
        distance = 1,
        another_property = 2
    }
    myGrid = ds_grid_create(width, height);
    var arrayPointer;
    for(var _x = 0; _x<width; _x++) {
      for(var _y = 0; _y<height; _y++) {
        arrayPointer = 0; //Reset to NO array, otherwise you'll keep the old array pointer in place
        arrayPointer[enumData.type] = 0;
        arrayPointer[enumData.distance] = point_distance(_x, _y, goal.x div cell_size, goal.y div cell_size);
        arrayPointer[enumData.another_property] = "Hodor";
       myGrid[# _x, _y] = arrayPointer;
      }
    }
    
    Please do note that if you want to _change_ data inside of the REAL array, you will need the array accessor:
    Code:
    var arrayThing = myGrid[# 2, 3];
    arrayThing[enumData.type] = 4; //Works for this arrayTHing reference only (its now a copy of the pointed array)
    arrayThing[@ enumData.type] = 4; //Changes the actual data in the real array
    
    EDIT: This is also why I'm hoping that stacked accessors will soon be available :) Then you could do;
    Code:
        var type = myGrid[# 2, 3][@enumData.type];
    
     
    31Nf4ChZ4H73N and Bentley like this.
  5. Bentley

    Bentley Member

    Joined:
    Jun 18, 2017
    Posts:
    827
    Thanks for the reply PNelly. I appreciate the explanation. You're right, "there is no getting around creating space for those multiple values".

    To be honest, I think I've only used a ds_map once haha. But now that you suggest it, I'll look into them and try the solution you offered. Thanks again.
     
  6. Bentley

    Bentley Member

    Joined:
    Jun 18, 2017
    Posts:
    827
    Hey DukeSoft, thanks for the replies. I like this code you posted:
    Code:
    enum enumData{
        type = 0,
        distance = 1,
        another_property = 2
    }
    myGrid = ds_grid_create(width, height);
    var arrayPointer;
    for(var _x = 0; _x<width; _x++) {
      for(var _y = 0; _y<height; _y++) {
        arrayPointer = 0; //Reset to NO array, otherwise you'll keep the old array pointer in place
        arrayPointer[enumData.type] = 0;
        arrayPointer[enumData.distance] = point_distance(_x, _y, goal.x div cell_size, goal.y div cell_size);
        arrayPointer[enumData.another_property] = "Hodor";
       myGrid[# _x, _y] = arrayPointer;
      }
    }
    So you're setting every grid position to an array and naming the positions in that array using an enumerator for readability? Sounds like a great solution. Forgive this silly question (I'm a beginner), but how would I access a grid position's array? Is that what you were showing me in the second block of code you posted? For ex, let's say I want to access grid 0,0's array:
    Code:
    var this_cells_array = my_grid[# 0, 0]; //This line brings up this grid position's array?
    if (this_cells_array[enum.type] == OPEN) //test this cell's value
    this_cells_array[@ enum.distance] = 20; //change this cell's value
    
    If so, that would be ideal. Thanks again for the replies.
     
    Last edited: Nov 14, 2017
  7. DukeSoft

    DukeSoft Member

    Joined:
    Jun 20, 2016
    Posts:
    799
    Exactly! Thats what I ment, and thats the way you can use it. Allthough it shouldn't make a difference on the outcome - I suggest you use the array acessor (@) as well for reading. I'm not sure what happens internally if you read without an accessor, but worst case it generates a copy of the array and then reads that.
    So indeed;
    var this_cells_array = my_grid[# 0, 0]; This returns an array pointer
    if (this_cells_array[@ enumname.enumvalue] == myvalue) Checks if the value from that array equals that
    this_cells_array[@ enum.distance] = 20; Writes 20 to that value

    If you have empty slots in the grid (e.g. an inventory system where there's nothing there) you won't need to add an array in to there. You could add a number (e.g. 0) there, and then use the is_array() function to check if there's an array at that position.
     
    Bentley likes this.
  8. Bentley

    Bentley Member

    Joined:
    Jun 18, 2017
    Posts:
    827
    Awesome : ) Problem solved. Thanks again.
     
  9. Bentley

    Bentley Member

    Joined:
    Jun 18, 2017
    Posts:
    827
    That's actually a really good idea (I know this post is way later): one grid holds all the maps. One map per grid position, and that map contains all the info for that grid position.

    So to clean up, something like this?

    Code:
    for (var i = 0; i < ds_grid_height(grid_of_maps); i++)
    {
     for (var j = 0; j < ds_grid_width(grid_of_maps); j++)
     {
      ds_map_destroy(grid_of_maps[# i, j]); 
     }
    }
    ds_grid_destroy(grid_of_maps);
    
    
     
    Last edited: Dec 3, 2017
  10. PNelly

    PNelly Member

    Joined:
    Jun 20, 2016
    Posts:
    256
    Looks good to me!
     
    Bentley likes this.

Share This Page

  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice