CellularAutomata = { map_w = 0, map_h = 0, iterations = 0, } function CellularAutomata.get_neighbors(map, x, y) local min_x = math.max(0, x-1) local min_y = math.max(0, y-1) local max_x = math.min(x+1, map:get_width()-1) local max_y = math.min(y+1, map:get_height()-1) local result = {} for mx = min_x, max_x do for my = min_y, max_y do table.insert(result, {x = mx, y = my}) end end return result end function CellularAutomata:initialize(w, h) self.map_w = w self.map_h = h self.iterations = 3 math.randomseed() for mx = 0, w-1 do for my = 0, h-1 do local is_wall = math.random(0, 1) == 1 if is_wall then visualizer.map:draw_wall(mx, my) else visualizer.map:draw_floor(mx, my) end end end end function CellularAutomata:update() if self.iterations <= 0 then return true end local old_map = visualizer.map local new_map = old_map:clone() for mx = 0, self.map_w - 1 do for my = 0, self.map_h - 1 do local neighbors = self.get_neighbors(old_map, mx, my) local expected_neighbors = 9 local walls = expected_neighbors - #neighbors local required_walls = 5 --print(old_map:is_wall(mx, my)) --print(new_map:is_wall(mx, my)) for k,v in ipairs(neighbors) do if old_map:is_wall(v.x, v.y) then walls = walls + 1 end end if walls >= required_walls then new_map:draw_wall(mx, my) else new_map:draw_floor(mx, my) end --print(old_map:is_wall(mx, my)) --print(new_map:is_wall(mx, my)) end end -- Now draw the new map onto the existing one for mx = 0, self.map_w - 1 do for my = 0, self.map_h - 1 do if new_map:is_wall(mx, my) then old_map:draw_wall(mx, my) else old_map:draw_floor(mx, my) end end end self.iterations = self.iterations - 1 return false end visualizer.algorithm_manager:register_algorithm("Cellular Automata", function (w, h) CellularAutomata:initialize(w, h) end, function () return CellularAutomata:update() end, 1)