Index: binaries/data/mods/public/maps/random/rmgen/math.js =================================================================== --- binaries/data/mods/public/maps/random/rmgen/math.js +++ binaries/data/mods/public/maps/random/rmgen/math.js @@ -118,6 +118,57 @@ } /** + * Flood fill algorithm to verify if all the points are connected against the given list of tileClass. + * @param {Vector2D[]} points All the points to test for. + * @param {TileClass[]} tileClasses All the tileClasses to flood fill for. + * @returns {boolean} True if all given points are reachable within the given tileclasses. + */ +function arePointsReachable(points, tileClasses) +{ + let processedPoints = new Uint8Array(mapSize * mapSize); + let initialPos = pickRandom(points); + let tilesStack = [initialPos]; + let connectionAmount = 0; + + while (tilesStack.length > 0) + { + let position = tilesStack.pop(); + + if (!g_Map.validTile(position)) + continue; + + let idx = position.x * mapSize + position.y; // The above check enforces that this would never be out of bounds. + + if (processedPoints[idx] != 0) + continue; + + if (tileClasses.some(tc => tc.has(position))) + { + processedPoints[idx] = 1; + continue; + } + + processedPoints[idx] = 1; + for (let point of points) + { + if (position.x == point.x && position.y == point.y) + { + connectionAmount++; + if (connectionAmount == points.length) + return true; + } + } + + tilesStack.push(new Vector2D(position.x + 1, position.y)); + tilesStack.push(new Vector2D(position.x - 1, position.y)); + tilesStack.push(new Vector2D(position.x, position.y + 1)); + tilesStack.push(new Vector2D(position.x, position.y - 1)); + } + + return false; +} + +/** * Get the order of the given points to get the shortest closed path (similar to the traveling salesman problem). * @param {Vectro2D[]} points - Points the path should go through * @returns {number[]} Ordered indices, same length as points