title: Game Maker GML Flood Fill Method - at a dead end
body: <p>I'm trying to implement a flood fill script in Game Maker's GML and have hit a dead end. After trying for 3 hours to fix what I thought would be a simple solution to filling in floor blocks, I'm begging for help on this issue. I'm testing for whether a tile has already been added to the tile list and whether or not it would collide with a wall (hence the 10-line collision_rectangle functions; those are just testing for whether a floor tile would overlap a wall or not). Sorry these take up a lot of unnecessary space and clunk up the code, I couldn't find another way to do it in GML. If anyone here is familiar with the data structures in GML and knows what I'm doing wrong, please speak up! You would save my project!</p>
  
  <p>Code:</p>
  
  <pre><code>// 2 arrays: one with x values of each tile, one with y values of each
  
  tile_locations_x = ds_list_create();
  tile_locations_y = ds_list_create();
  
  tile_stack_x = ds_stack_create();
  tile_stack_y = ds_stack_create();
  
  ds_stack_push(tile_stack_x, obj_player.x);
  ds_stack_push(tile_stack_y, obj_player.y);
  
  // iterator for "for" loops
  var i;
  
  while (!ds_stack_empty(tile_stack_x)) {
      test_location_x = ds_stack_pop(tile_stack_x);
      test_location_y = ds_stack_pop(tile_stack_y);
      ds_list_add(tile_locations_x, test_location_x);
      ds_list_add(tile_locations_y, test_location_y);
      tile_add(bg_floortiles, 0, 0, 16, 16, test_location_x, test_location_y, 99999);
  
      // Add the 4 cardinal directions to the stack after checking if they're already in the list
  
      // left of point
      testpoint_x = test_location_x - 16;
      testpoint_y = test_location_y;
      // Check point testpoint_x, testpoint_y is valid
      valid = true;
      // Check added location list first, then check stack because the same location stackd multiple times doesn't work
      for (i = 0; i &lt; ds_list_size(tile_locations_x); i += 1) {
          if (ds_list_find_value(tile_locations_x, i) == testpoint_x &amp;&amp; ds_list_find_value(tile_locations_y, i) == testpoint_y) {
              valid = false;
              break;
          }
      }
      if (valid) {
          precise_collision_check = true;
          if (    collision_rectangle(testpoint_x, testpoint_y, testpoint_x + 16, testpoint_y + 16,  obj_horizontal, precise_collision_check, true) == noone &amp;&amp; 
                  collision_rectangle(testpoint_x, testpoint_y, testpoint_x + 16, testpoint_y + 16,  obj_vertical, precise_collision_check, true) == noone &amp;&amp; 
                  collision_rectangle(testpoint_x, testpoint_y, testpoint_x + 16, testpoint_y + 16,  obj_diagonal1, precise_collision_check, true) == noone &amp;&amp; 
                  collision_rectangle(testpoint_x, testpoint_y, testpoint_x + 16, testpoint_y + 16,  obj_diagonal2, precise_collision_check, true) == noone &amp;&amp; 
                  collision_rectangle(testpoint_x, testpoint_y, testpoint_x + 16, testpoint_y + 16,  obj_diagonal3, precise_collision_check, true) == noone &amp;&amp; 
                  collision_rectangle(testpoint_x, testpoint_y, testpoint_x + 16, testpoint_y + 16,  obj_diagonal4, precise_collision_check, true) == noone &amp;&amp; 
                  collision_rectangle(testpoint_x, testpoint_y, testpoint_x + 16, testpoint_y + 16,  obj_diagonalconnector1, precise_collision_check, true) == noone &amp;&amp; 
                  collision_rectangle(testpoint_x, testpoint_y, testpoint_x + 16, testpoint_y + 16,  obj_diagonalconnector2, precise_collision_check, true) == noone &amp;&amp; 
                  collision_rectangle(testpoint_x, testpoint_y, testpoint_x + 16, testpoint_y + 16,  obj_diagonalconnector3, precise_collision_check, true) == noone &amp;&amp; 
                  collision_rectangle(testpoint_x, testpoint_y, testpoint_x + 16, testpoint_y + 16,  obj_diagonalconnector4, precise_collision_check, true) == noone) {
              ds_stack_push(tile_stack_x, testpoint_x);
              ds_stack_push(tile_stack_y, testpoint_y);
          }
      }
  
      // right of point
      testpoint_x = test_location_x + 16;
      testpoint_y = test_location_y;
      // Check point testpoint_x, testpoint_y is valid
      valid = true;
      // Check added location list first, then check stack because the same location stackd multiple times doesn't work
      for (i = 0; i &lt; ds_list_size(tile_locations_x); i += 1) {
          if (ds_list_find_value(tile_locations_x, i) == testpoint_x &amp;&amp; ds_list_find_value(tile_locations_y, i) == testpoint_y) {
              valid = false;
              break;
          }
      }
      if (valid) {
          precise_collision_check = true;
          if (    collision_rectangle(testpoint_x, testpoint_y, testpoint_x + 16, testpoint_y + 16,  obj_horizontal, precise_collision_check, true) == noone &amp;&amp; 
                  collision_rectangle(testpoint_x, testpoint_y, testpoint_x + 16, testpoint_y + 16,  obj_vertical, precise_collision_check, true) == noone &amp;&amp; 
                  collision_rectangle(testpoint_x, testpoint_y, testpoint_x + 16, testpoint_y + 16,  obj_diagonal1, precise_collision_check, true) == noone &amp;&amp; 
                  collision_rectangle(testpoint_x, testpoint_y, testpoint_x + 16, testpoint_y + 16,  obj_diagonal2, precise_collision_check, true) == noone &amp;&amp; 
                  collision_rectangle(testpoint_x, testpoint_y, testpoint_x + 16, testpoint_y + 16,  obj_diagonal3, precise_collision_check, true) == noone &amp;&amp; 
                  collision_rectangle(testpoint_x, testpoint_y, testpoint_x + 16, testpoint_y + 16,  obj_diagonal4, precise_collision_check, true) == noone &amp;&amp; 
                  collision_rectangle(testpoint_x, testpoint_y, testpoint_x + 16, testpoint_y + 16,  obj_diagonalconnector1, precise_collision_check, true) == noone &amp;&amp; 
                  collision_rectangle(testpoint_x, testpoint_y, testpoint_x + 16, testpoint_y + 16,  obj_diagonalconnector2, precise_collision_check, true) == noone &amp;&amp; 
                  collision_rectangle(testpoint_x, testpoint_y, testpoint_x + 16, testpoint_y + 16,  obj_diagonalconnector3, precise_collision_check, true) == noone &amp;&amp; 
                  collision_rectangle(testpoint_x, testpoint_y, testpoint_x + 16, testpoint_y + 16,  obj_diagonalconnector4, precise_collision_check, true) == noone) {
              ds_stack_push(tile_stack_x, testpoint_x);
              ds_stack_push(tile_stack_y, testpoint_y);
          }
      }
  
      // above point
      testpoint_x = test_location_x;
      testpoint_y = test_location_y - 16;
      // Check point testpoint_x, testpoint_y is valid
      valid = true;
      // Check added location list first, then check stack because the same location stackd multiple times doesn't work
      for (i = 0; i &lt; ds_list_size(tile_locations_x); i += 1) {
          if (ds_list_find_value(tile_locations_x, i) == testpoint_x &amp;&amp; ds_list_find_value(tile_locations_y, i) == testpoint_y) {
              valid = false;
              break;
          }
      }
      if (valid) {
          precise_collision_check = true;
          if (    collision_rectangle(testpoint_x, testpoint_y, testpoint_x + 16, testpoint_y + 16,  obj_horizontal, precise_collision_check, true) == noone &amp;&amp; 
                  collision_rectangle(testpoint_x, testpoint_y, testpoint_x + 16, testpoint_y + 16,  obj_vertical, precise_collision_check, true) == noone &amp;&amp; 
                  collision_rectangle(testpoint_x, testpoint_y, testpoint_x + 16, testpoint_y + 16,  obj_diagonal1, precise_collision_check, true) == noone &amp;&amp; 
                  collision_rectangle(testpoint_x, testpoint_y, testpoint_x + 16, testpoint_y + 16,  obj_diagonal2, precise_collision_check, true) == noone &amp;&amp; 
                  collision_rectangle(testpoint_x, testpoint_y, testpoint_x + 16, testpoint_y + 16,  obj_diagonal3, precise_collision_check, true) == noone &amp;&amp; 
                  collision_rectangle(testpoint_x, testpoint_y, testpoint_x + 16, testpoint_y + 16,  obj_diagonal4, precise_collision_check, true) == noone &amp;&amp; 
                  collision_rectangle(testpoint_x, testpoint_y, testpoint_x + 16, testpoint_y + 16,  obj_diagonalconnector1, precise_collision_check, true) == noone &amp;&amp; 
                  collision_rectangle(testpoint_x, testpoint_y, testpoint_x + 16, testpoint_y + 16,  obj_diagonalconnector2, precise_collision_check, true) == noone &amp;&amp; 
                  collision_rectangle(testpoint_x, testpoint_y, testpoint_x + 16, testpoint_y + 16,  obj_diagonalconnector3, precise_collision_check, true) == noone &amp;&amp; 
                  collision_rectangle(testpoint_x, testpoint_y, testpoint_x + 16, testpoint_y + 16,  obj_diagonalconnector4, precise_collision_check, true) == noone) {
              ds_stack_push(tile_stack_x, testpoint_x);
              ds_stack_push(tile_stack_y, testpoint_y);
          }
      }
  
      // below point
      testpoint_x = test_location_x;
      testpoint_y = test_location_y + 16;
      // Check point testpoint_x, testpoint_y is valid
      valid = true;
      // Check added location list first, then check stack because the same location stackd multiple times doesn't work
      for (i = 0; i &lt; ds_list_size(tile_locations_x); i += 1) {
          if (ds_list_find_value(tile_locations_x, i) == testpoint_x &amp;&amp; ds_list_find_value(tile_locations_y, i) == testpoint_y) {
              valid = false;
              break;
          }
      }
      if (valid) {
          precise_collision_check = true;
          if (    collision_rectangle(testpoint_x, testpoint_y, testpoint_x + 16, testpoint_y + 16,  obj_horizontal, precise_collision_check, true) == noone &amp;&amp; 
                  collision_rectangle(testpoint_x, testpoint_y, testpoint_x + 16, testpoint_y + 16,  obj_vertical, precise_collision_check, true) == noone &amp;&amp; 
                  collision_rectangle(testpoint_x, testpoint_y, testpoint_x + 16, testpoint_y + 16,  obj_diagonal1, precise_collision_check, true) == noone &amp;&amp; 
                  collision_rectangle(testpoint_x, testpoint_y, testpoint_x + 16, testpoint_y + 16,  obj_diagonal2, precise_collision_check, true) == noone &amp;&amp; 
                  collision_rectangle(testpoint_x, testpoint_y, testpoint_x + 16, testpoint_y + 16,  obj_diagonal3, precise_collision_check, true) == noone &amp;&amp; 
                  collision_rectangle(testpoint_x, testpoint_y, testpoint_x + 16, testpoint_y + 16,  obj_diagonal4, precise_collision_check, true) == noone &amp;&amp; 
                  collision_rectangle(testpoint_x, testpoint_y, testpoint_x + 16, testpoint_y + 16,  obj_diagonalconnector1, precise_collision_check, true) == noone &amp;&amp; 
                  collision_rectangle(testpoint_x, testpoint_y, testpoint_x + 16, testpoint_y + 16,  obj_diagonalconnector2, precise_collision_check, true) == noone &amp;&amp; 
                  collision_rectangle(testpoint_x, testpoint_y, testpoint_x + 16, testpoint_y + 16,  obj_diagonalconnector3, precise_collision_check, true) == noone &amp;&amp; 
                  collision_rectangle(testpoint_x, testpoint_y, testpoint_x + 16, testpoint_y + 16,  obj_diagonalconnector4, precise_collision_check, true) == noone) {
              ds_stack_push(tile_stack_x, testpoint_x);
              ds_stack_push(tile_stack_y, testpoint_y);
          }
      }
  }
  ds_list_destroy(tile_locations_x);
  ds_list_destroy(tile_locations_y);
  ds_stack_destroy(tile_stack_x);
  ds_stack_destroy(tile_stack_y);
  </code></pre>
  
  <p>It's probably something minor I'm overlooking; I just want a second opinion. Thank you in advance for you help!</p>
  
  <p>-Neil</p>