local function coord_string(x, y) local str = tostring(x) .. '_' str = str .. tostring(y) return str end local function draw_cell(surface, cell, cell_size, wall_entity_name, force_name) local r = math.floor(cell_size * 0.5) local entities = {} if cell.north then for x = r * -1, r, 1 do entities[#entities + 1] = {position = {cell.position.x + x, cell.position.y - r}, name = wall_entity_name, force = force_name} end end if cell.south then for x = r * -1, r, 1 do entities[#entities + 1] = {position = {cell.position.x + x, cell.position.y + r}, name = wall_entity_name, force = force_name} end end if cell.east then for y = r * -1, r, 1 do entities[#entities + 1] = {position = {cell.position.x + r, cell.position.y + y}, name = wall_entity_name, force = force_name} end end if cell.west then for y = r * -1, r, 1 do entities[#entities + 1] = {position = {cell.position.x - r, cell.position.y - y}, name = wall_entity_name, force = force_name} end end for _, e in pairs(entities) do if surface.can_place_entity(e) then surface.create_entity(e) end end end local function draw_maze(maze_cells, surface, _, _, cell_size, wall_entity_name, force_name) for _, cell in pairs(maze_cells) do draw_cell(surface, cell, cell_size, wall_entity_name, force_name) end end local function get_random_occupied_cell(maze_cells) local occupied_cells = {} for c, cell in pairs(maze_cells) do if cell.occupied then if not cell.dead then occupied_cells[#occupied_cells + 1] = c end end end if not occupied_cells[1] then return end return occupied_cells[math.random(1, #occupied_cells)] end local function set_dead_cells(maze_cells) local directions = { {0, -1}, {0, 1}, {1, 0}, {-1, 0} } for c, cell in pairs(maze_cells) do if not cell.dead then maze_cells[c].dead = true for i = 1, 4, 1 do local cell_string = coord_string(cell.cell_position.x + directions[i][1], cell.cell_position.y + directions[i][2]) if maze_cells[cell_string] then if not maze_cells[cell_string].occupied then maze_cells[c].dead = false break end end end end end end local function expand_cell(maze_cells, current_cell) local expansion_raffle = { {0, -1, 'north', 'south'}, {0, 1, 'south', 'north'}, {1, 0, 'east', 'west'}, {-1, 0, 'west', 'east'} } table.shuffle_table(expansion_raffle) for i = 1, 4, 1 do local direction = expansion_raffle[i] local cell_canditate = coord_string(current_cell.cell_position.x + direction[1], current_cell.cell_position.y + direction[2]) if maze_cells[cell_canditate] then if not maze_cells[cell_canditate].occupied then maze_cells[cell_canditate].occupied = true current_cell[direction[3]] = false maze_cells[cell_canditate][direction[4]] = false return maze_cells[cell_canditate] end end end return false end local function expand(maze_cells) local current_cell = maze_cells[get_random_occupied_cell(maze_cells)] while true do current_cell = expand_cell(maze_cells, current_cell) if not current_cell then set_dead_cells(maze_cells) current_cell = maze_cells[get_random_occupied_cell()] end if not current_cell then break end end end local function disable_borders(maze_cells, size) for s = size * -1, size, 1 do maze_cells[coord_string(s, size * -1)].north = false maze_cells[coord_string(s, size)].south = false maze_cells[coord_string(size, s)].east = false maze_cells[coord_string(size * -1, s)].west = false end end local function create_maze(surface, position, size, cell_size, wall_entity_name, force_name, borderless) if not surface then game.print('No surface given.') return end if not position then game.print('No position given.') return end if not size then game.print('No size given.') return end if not cell_size then game.print('No cell_size given.') return end if not wall_entity_name then game.print('No wall_entity_name given.') return end local maze_cells = {} for x = size * -1, size, 1 do for y = size * -1, size, 1 do maze_cells[coord_string(x, y)] = { position = {x = position.x + x * (cell_size - 1), y = position.y + y * (cell_size - 1)}, cell_position = {x = x, y = y}, occupied = false, dead = false, north = true, south = true, east = true, west = true } end end maze_cells[coord_string(size * -1, 0)].occupied = true maze_cells[coord_string(size * -1, 0)].west = false maze_cells[coord_string(size, 0)].east = false if borderless then disable_borders(maze_cells, size) end expand(maze_cells) draw_maze(maze_cells, surface, position, size, cell_size, wall_entity_name, force_name) end return create_maze