1+ local Event = require ' utils.event'
2+ local Generate = require ' map_gen.shared.generate'
3+ local Global = require ' utils.global'
4+ local RS = require ' map_gen.shared.redmew_surface'
5+ local math = require ' utils.math'
6+ local table = require ' utils.table'
7+
8+ local insert = table.insert
9+ local shuffle = table .shuffle_table
10+ local math_max = math.max
11+ local math_floor = math.floor
12+ local math_random = math.random
13+
14+ return function (config )
15+ local MAZE_SIZE = config .size
16+ local WALL_THICKNESS = config .wall_thickness
17+ local CELL_SIZE = config .cell_size
18+ local WALL_DELTA = math_floor ((CELL_SIZE - WALL_THICKNESS ) / 2 )
19+ local DIRECTIONS = {
20+ { x = 0 , y = - 2 }, -- north
21+ { x = 2 , y = 0 }, -- east
22+ { x = - 2 , y = 0 }, -- west
23+ { x = 0 , y = 2 }, -- south
24+ }
25+
26+ local pixels = {}
27+ local cells = {}
28+ local maze_walls = {}
29+ local primitives = {
30+ max = 0 ,
31+ walk_seed_w = 0 ,
32+ walk_seed_h = 0 ,
33+ }
34+
35+ Global .register ({
36+ maze_walls = maze_walls ,
37+ primitives = primitives ,
38+ },
39+ function (tbl )
40+ maze_walls = tbl .maze_walls
41+ primitives = tbl .primitives
42+ end
43+ )
44+
45+ local function add_tile (x , y , width , height , add_cell )
46+ if add_cell then
47+ if cells [x ] == nil then
48+ cells [x ] = {}
49+ end
50+ cells [x ][y ] = 1
51+ end
52+ for x_pos = x , x + width - 1 do
53+ for y_pos = y , y + height - 1 do
54+ if pixels [x_pos ] == nil then
55+ pixels [x_pos ] = {}
56+ end
57+ pixels [x_pos ][y_pos ] = 1
58+ end
59+ end
60+ end
61+
62+ local function render ()
63+ local y_max = 0
64+ for x , _ in pairs (pixels ) do
65+ for y , _ in pairs (pixels [x ]) do
66+ if y * 32 > primitives .max and y % 2 == 0 then
67+ y_max = math_max (y_max , y )
68+ end
69+ end
70+ end
71+ primitives .max = y_max * 32
72+
73+ for x = 1 , y_max do
74+ for y = 1 , WALL_DELTA do
75+ if not pixels [x ] then
76+ pixels [x ] = {}
77+ end
78+ pixels [x ][y ] = 1
79+ end
80+ end
81+ for x = 1 , WALL_DELTA do
82+ for y = 1 , y_max do
83+ if not pixels [x ] then
84+ pixels [x ] = {}
85+ end
86+ pixels [x ][y ] = 1
87+ end
88+ end
89+
90+ for x = 1 , y_max do
91+ for y = 1 , y_max do
92+ if not (pixels [x ] and pixels [x ][y ]) then
93+ maze_walls [x * 32 .. ' /' .. y * 32 ] = true
94+ end
95+ end
96+ end
97+ end
98+
99+ -- builds a width-by-height grid
100+ local function initialize_grid (w , h )
101+ local a = {}
102+ for i = 1 , h do
103+ insert (a , {})
104+ for j = 1 , w do
105+ insert (a [i ], true )
106+ end
107+ end
108+ return a
109+ end
110+
111+ -- average of a and b
112+ local function avg (a , b )
113+ return (a + b ) / 2
114+ end
115+
116+ local function make_maze (w , h )
117+ local map = initialize_grid (w * 2 + 1 , h * 2 + 1 )
118+
119+ local walk
120+ walk = function (x , y )
121+ map [y ][x ] = false
122+
123+ local d = { 1 , 2 , 3 , 4 }
124+ shuffle (d )
125+ for i , dir_num in pairs (d ) do
126+ local xx = x + DIRECTIONS [dir_num ].x
127+ local yy = y + DIRECTIONS [dir_num ].y
128+ if map [yy ] and map [yy ][xx ] then
129+ map [avg (y , yy )][avg (x , xx )] = false
130+ walk (xx , yy )
131+ end
132+ end
133+ end
134+ walk (primitives .walk_seed_w , primitives .walk_seed_h )
135+
136+ for i = 1 , h * 2 + 1 do
137+ for j = 1 , w * 2 + 1 do
138+ if map [i ][j ] then
139+ add_tile (i * CELL_SIZE , j * CELL_SIZE , CELL_SIZE , CELL_SIZE , true )
140+ end
141+ end
142+ end
143+ end
144+
145+ local function is_map (x , y )
146+ return cells [x ] and cells [x ][y ] == 1
147+ end
148+
149+ local function is_wall (x , y )
150+ return not is_map (x , y )
151+ end
152+
153+ local function reduce_walls ()
154+ for x , _ in pairs (cells ) do
155+ for y , _ in pairs (cells [x ]) do
156+ -- Left
157+ if is_wall (x - CELL_SIZE , y ) then
158+ add_tile (x - WALL_DELTA , y , WALL_DELTA , CELL_SIZE , false )
159+ end
160+ -- Right
161+ if is_wall (x + CELL_SIZE , y ) then
162+ add_tile (x + CELL_SIZE , y , WALL_DELTA , CELL_SIZE , false )
163+ end
164+ -- Above
165+ if is_wall (x , y - CELL_SIZE ) then
166+ add_tile (x - WALL_DELTA , y - WALL_DELTA , CELL_SIZE + 2 * WALL_DELTA , WALL_DELTA , false )
167+ end
168+ -- Below
169+ if is_wall (x , y + CELL_SIZE ) then
170+ add_tile (x - WALL_DELTA , y + CELL_SIZE , CELL_SIZE + 2 * WALL_DELTA , WALL_DELTA , false )
171+ end
172+ end
173+ end
174+ end
175+
176+ local function remove_chunk (surface , area )
177+ local tiles = {}
178+ for x = area .left_top .x , area .right_bottom .x - 1 do
179+ for y = area .left_top .y , area .right_bottom .y - 1 do
180+ insert (tiles , { name = ' out-of-map' , position = { x = x , y = y } })
181+ end
182+ end
183+ surface .set_tiles (tiles )
184+ end
185+
186+ local set_wall_tiles = function (surface , area )
187+ if not config .enabled then
188+ return
189+ end
190+
191+ local pos = area .left_top
192+ if maze_walls [pos .x + primitives .max / 2 .. ' /' .. pos .y + primitives .max / 2 ] then
193+ remove_chunk (surface , area )
194+ return true
195+ end
196+ return
197+ end
198+
199+ Event .on_init (function ()
200+ if not config .enabled then
201+ return
202+ end
203+
204+ primitives .walk_seed_w = math_random (1 , MAZE_SIZE ) * 2
205+ primitives .walk_seed_h = math_random (1 , MAZE_SIZE ) * 2
206+ make_maze (MAZE_SIZE , MAZE_SIZE )
207+ reduce_walls ()
208+ render ()
209+ end )
210+
211+ Event .add (Generate .events .on_chunk_generated , function (event )
212+ local surface , area = event .surface , event .area
213+ if surface ~= RS .get_surface () then
214+ return
215+ end
216+ -- Make maze walls
217+ set_wall_tiles (surface , area )
218+ end )
219+ end
0 commit comments