6 |
6 |
7 procedure GenMaze; |
7 procedure GenMaze; |
8 |
8 |
9 implementation |
9 implementation |
10 |
10 |
11 uses uRandom, uLandOutline, uLandTemplates, uVariables, uFloat, uConsts; |
11 uses uRandom, uLandOutline, uLandTemplates, uVariables, uFloat, uConsts, uLandGenTemplateBased, uUtils; |
12 |
12 |
13 type direction = record x, y: LongInt; end; |
13 type direction = record x, y: LongInt; end; |
14 const DIR_N: direction = (x: 0; y: -1); |
14 const DIR_N: direction = (x: 0; y: -1); |
15 DIR_E: direction = (x: 1; y: 0); |
15 DIR_E: direction = (x: 1; y: 0); |
16 DIR_S: direction = (x: 0; y: 1); |
16 DIR_S: direction = (x: 0; y: 1); |
17 DIR_W: direction = (x: -1; y: 0); |
17 DIR_W: direction = (x: -1; y: 0); |
18 |
18 |
19 |
|
20 operator = (const a, b: direction) c: Boolean; |
19 operator = (const a, b: direction) c: Boolean; |
21 begin |
20 begin |
22 c := (a.x = b.x) and (a.y = b.y); |
21 c := (a.x = b.x) and (a.y = b.y); |
23 end; |
22 end; |
24 |
23 |
25 const small_cell_size = 128; |
24 const small_cell_size = 128; |
26 medium_cell_size = 192; |
25 medium_cell_size = 192; |
27 large_cell_size = 256; |
26 large_cell_size = 256; |
28 braidness = 10; |
27 braidness = 10; |
29 |
28 |
30 var x, y: LongInt; |
29 type |
31 cellsize: LongInt; //selected by the user in the gui |
30 cell_t = record x,y : LongInt |
32 seen_cells_x, seen_cells_y: LongInt; //number of cells that can be visited by the generator, that is every second cell in x and y direction. the cells between there are walls that will be removed when we move from one cell to another |
31 end; |
33 num_edges_x, num_edges_y: LongInt; //number of resulting edges that need to be vertexificated |
32 |
34 num_cells_x, num_cells_y: LongInt; //actual number of cells, depending on cell size |
33 var x, y : LongInt; |
35 seen_list: array of array of LongInt; |
34 cellsize : LongInt; //selected by the user in the gui |
36 xwalls: array of array of Boolean; |
35 seen_cells_x, seen_cells_y : LongInt; //number of cells that can be visited by the generator, that is every second cell in x and y direction. the cells between there are walls that will be removed when we move from one cell to another |
37 ywalls: array of array of Boolean; |
36 num_edges_x, num_edges_y : LongInt; //number of resulting edges that need to be vertexificated |
38 x_edge_list: array of array of Boolean; |
37 num_cells_x, num_cells_y : LongInt; //actual number of cells, depending on cell size |
39 y_edge_list: array of array of Boolean; |
38 |
40 maze: array of array of Boolean; |
39 |
41 pa: TPixAr; |
40 seen_list : array of array of LongInt; |
42 num_vertices: LongInt; |
41 xwalls : array of array of Boolean; |
43 off_y: LongInt; |
42 ywalls : array of array of Boolean; |
44 num_steps: LongInt; |
43 x_edge_list : array of array of Boolean; |
45 current_step: LongInt; |
44 y_edge_list : array of array of Boolean; |
46 step_done: array of Boolean; |
45 maze : array of array of Boolean; |
47 done: Boolean; |
46 |
48 last_cell: array of record x, y: LongInt; end; |
47 pa : TPixAr; |
49 came_from: array of array of record x, y: LongInt; end; |
48 num_vertices : LongInt; |
|
49 off_y : LongInt; |
|
50 num_steps : LongInt; |
|
51 current_step : LongInt; |
|
52 |
|
53 step_done : array of Boolean; |
|
54 |
|
55 done : Boolean; |
|
56 |
|
57 { last_cell : array 0..3 of record x, y :LongInt ; end; |
|
58 came_from : array of array of record x, y: LongInt; end; |
|
59 came_from_pos : array of LongInt; |
|
60 } |
|
61 last_cell : array of cell_t; |
|
62 came_from : array of array of cell_t; |
50 came_from_pos: array of LongInt; |
63 came_from_pos: array of LongInt; |
51 maze_inverted: Boolean; |
64 |
|
65 maze_inverted : Boolean; |
52 |
66 |
53 function when_seen(x: LongInt; y: LongInt): LongInt; |
67 function when_seen(x: LongInt; y: LongInt): LongInt; |
54 begin |
68 begin |
55 if (x < 0) or (x >= seen_cells_x) or (y < 0) or (y >= seen_cells_y) then |
69 if (x < 0) or (x >= seen_cells_x) or (y < 0) or (y >= seen_cells_y) then |
56 when_seen := current_step |
70 when_seen := current_step |
176 if not found_cell then |
190 if not found_cell then |
177 begin |
191 begin |
178 last_cell[current_step].x := came_from[current_step, came_from_pos[current_step]].x; |
192 last_cell[current_step].x := came_from[current_step, came_from_pos[current_step]].x; |
179 last_cell[current_step].y := came_from[current_step, came_from_pos[current_step]].y; |
193 last_cell[current_step].y := came_from[current_step, came_from_pos[current_step]].y; |
180 came_from_pos[current_step] := came_from_pos[current_step] - 1; |
194 came_from_pos[current_step] := came_from_pos[current_step] - 1; |
181 |
195 |
182 if came_from_pos[current_step] >= 0 then |
196 if came_from_pos[current_step] >= 0 then |
183 see_cell |
197 see_cell() |
184 |
198 |
185 else |
199 else |
186 step_done[current_step] := true; |
200 step_done[current_step] := true; |
187 end; |
201 end; |
188 end; |
202 end; |
189 |
203 |
190 procedure add_vertex(x, y: LongInt); |
204 procedure add_vertex(x, y: LongInt); |
191 var tmp_x, tmp_y: LongInt; |
205 var tmp_x, tmp_y, nx, ny: LongInt; |
192 begin |
206 begin |
193 if x = NTPX then |
207 if x = NTPX then |
194 begin |
208 begin |
195 if pa.ar[num_vertices - 6].x = NTPX then |
209 if pa.ar[num_vertices - 6].x = NTPX then |
196 begin |
210 begin |
197 num_vertices := num_vertices - 6; |
211 num_vertices := num_vertices - 6; |
|
212 end |
|
213 else |
|
214 begin |
|
215 pa.ar[num_vertices].x := NTPX; |
|
216 pa.ar[num_vertices].y := 0; |
|
217 end |
198 end |
218 end |
199 else |
219 else |
200 begin |
220 begin |
201 pa.ar[num_vertices].x := NTPX; |
221 if maze_inverted or (x mod 2 = 0) then |
202 pa.ar[num_vertices].y := 0; |
222 tmp_x := cellsize |
203 end |
223 else |
204 end |
224 tmp_x := cellsize * 2 div 3; |
205 else |
225 |
206 begin |
226 if maze_inverted or (y mod 2 = 0) then |
207 if maze_inverted or (x mod 2 = 0) then |
227 tmp_y := cellsize |
208 tmp_x := cellsize |
228 else |
209 else |
229 tmp_y := cellsize * 2 div 3; |
210 tmp_x := cellsize * 2 div 3; |
230 |
211 |
231 nx:= (x-1)*cellsize + tmp_x; |
212 if maze_inverted or (y mod 2 = 0) then |
232 ny:= (y-1)*cellsize + tmp_y + off_y; |
213 tmp_y := cellsize |
233 |
214 else |
234 if num_vertices > 2 then |
215 tmp_y := cellsize * 2 div 3; |
235 if ((pa.ar[num_vertices - 2].x = pa.ar[num_vertices - 1].x) and (pa.ar[num_vertices - 1].x = nx)) |
216 |
236 or ((pa.ar[num_vertices - 2].y = pa.ar[num_vertices - 1].y) and (pa.ar[num_vertices - 1].y = ny)) |
217 pa.ar[num_vertices].x := (x-1)*cellsize + tmp_x; |
237 then |
218 pa.ar[num_vertices].y := (y-1)*cellsize + tmp_y + off_y; |
238 dec(num_vertices); |
219 end; |
239 |
220 num_vertices := num_vertices + 1; |
240 pa.ar[num_vertices].x := nx; |
|
241 pa.ar[num_vertices].y := ny; |
|
242 end; |
|
243 |
|
244 num_vertices := num_vertices + 1; |
221 end; |
245 end; |
222 |
246 |
223 procedure add_edge(x, y: LongInt; dir: direction); |
247 procedure add_edge(x, y: LongInt; dir: direction); |
224 var i: LongInt; |
248 var i: LongInt; |
225 begin |
249 begin |
249 else if dir = DIR_S then |
273 else if dir = DIR_S then |
250 dir := DIR_W |
274 dir := DIR_W |
251 else |
275 else |
252 dir := DIR_N; |
276 dir := DIR_N; |
253 |
277 |
254 if (dir = DIR_N) and is_x_edge(x, y) then |
278 if (dir = DIR_N) and is_x_edge(x, y) then |
255 begin |
279 begin |
256 x_edge_list[x, y] := false; |
280 x_edge_list[x, y] := false; |
257 add_vertex(x+1, y); |
281 add_vertex(x+1, y); |
258 add_edge(x, y-1, DIR_N); |
282 add_edge(x, y-1, DIR_N); |
259 break; |
283 break; |
260 end; |
284 end; |
261 |
285 |
262 if (dir = DIR_E) and is_y_edge(x+1, y) then |
286 if (dir = DIR_E) and is_y_edge(x+1, y) then |
263 begin |
287 begin |
264 y_edge_list[x+1, y] := false; |
288 y_edge_list[x+1, y] := false; |
265 add_vertex(x+2, y+1); |
289 add_vertex(x+2, y+1); |
266 add_edge(x+1, y, DIR_E); |
290 add_edge(x+1, y, DIR_E); |
267 break; |
291 break; |
268 end; |
292 end; |
269 |
293 |
270 if (dir = DIR_S) and is_x_edge(x, y+1) then |
294 if (dir = DIR_S) and is_x_edge(x, y+1) then |
271 begin |
295 begin |
272 x_edge_list[x, y+1] := false; |
296 x_edge_list[x, y+1] := false; |
273 add_vertex(x+1, y+2); |
297 add_vertex(x+1, y+2); |
274 add_edge(x, y+1, DIR_S); |
298 add_edge(x, y+1, DIR_S); |
275 break; |
299 break; |
276 end; |
300 end; |
277 |
301 |
278 if (dir = DIR_W) and is_y_edge(x, y) then |
302 if (dir = DIR_W) and is_y_edge(x, y) then |
279 begin |
303 begin |
280 y_edge_list[x, y] := false; |
304 y_edge_list[x, y] := false; |
281 add_vertex(x, y+1); |
305 add_vertex(x, y+1); |
282 add_edge(x-1, y, DIR_W); |
306 add_edge(x-1, y, DIR_W); |
283 break; |
307 break; |
284 end; |
308 end; |
285 end; |
309 end; |
286 |
310 |
287 end; |
311 end; |
288 |
312 |
289 procedure GenMaze; |
313 procedure GenMaze; |
|
314 var i: Longword; |
290 begin |
315 begin |
291 case cTemplateFilter of |
316 case cTemplateFilter of |
292 0: begin |
317 0: begin |
293 cellsize := small_cell_size; |
318 cellsize := small_cell_size; |
294 maze_inverted := false; |
319 maze_inverted := false; |
295 end; |
320 minDistance:= max(cFeatureSize*8,32); |
|
321 dabDiv:= 150; |
|
322 end; |
296 1: begin |
323 1: begin |
297 cellsize := medium_cell_size; |
324 cellsize := medium_cell_size; |
298 maze_inverted := false; |
325 minDistance:= max(cFeatureSize*6,20); |
299 end; |
326 maze_inverted := false; |
|
327 dabDiv:= 100; |
|
328 end; |
300 2: begin |
329 2: begin |
301 cellsize := large_cell_size; |
330 cellsize := large_cell_size; |
302 maze_inverted := false; |
331 minDistance:= max(cFeatureSize*5,12); |
303 end; |
332 maze_inverted := false; |
|
333 dabDiv:= 90; |
|
334 end; |
304 3: begin |
335 3: begin |
305 cellsize := small_cell_size; |
336 cellsize := small_cell_size; |
306 maze_inverted := true; |
337 minDistance:= max(cFeatureSize*8,32); |
307 end; |
338 maze_inverted := true; |
|
339 dabDiv:= 130; |
|
340 end; |
308 4: begin |
341 4: begin |
309 cellsize := medium_cell_size; |
342 cellsize := medium_cell_size; |
310 maze_inverted := true; |
343 minDistance:= max(cFeatureSize*6,20); |
311 end; |
344 maze_inverted := true; |
|
345 dabDiv:= 100; |
|
346 end; |
312 5: begin |
347 5: begin |
313 cellsize := large_cell_size; |
348 cellsize := large_cell_size; |
314 maze_inverted := true; |
349 minDistance:= max(cFeatureSize*5,12); |
315 end; |
350 maze_inverted := true; |
316 end; |
351 dabDiv:= 85; |
|
352 end; |
|
353 end; |
317 |
354 |
318 num_cells_x := LAND_WIDTH div cellsize; |
355 num_cells_x := LAND_WIDTH div cellsize; |
319 if not odd(num_cells_x) then |
356 if not odd(num_cells_x) then |
320 num_cells_x := num_cells_x - 1; //needs to be odd |
357 num_cells_x := num_cells_x - 1; //needs to be odd |
321 |
358 |
322 num_cells_y := LAND_HEIGHT div cellsize; |
359 num_cells_y := LAND_HEIGHT div cellsize; |
323 if not odd(num_cells_y) then |
360 if not odd(num_cells_y) then |
324 num_cells_y := num_cells_y - 1; |
361 num_cells_y := num_cells_y - 1; |
325 |
362 |
326 num_edges_x := num_cells_x - 1; |
363 num_edges_x := num_cells_x - 1; |
327 num_edges_y := num_cells_y - 1; |
364 num_edges_y := num_cells_y - 1; |
328 |
365 |
329 seen_cells_x := num_cells_x div 2; |
366 seen_cells_x := num_cells_x div 2; |
330 seen_cells_y := num_cells_y div 2; |
367 seen_cells_y := num_cells_y div 2; |
331 |
368 |
332 if maze_inverted then |
369 if maze_inverted then |
333 num_steps := 3 //TODO randomize, between 3 and 5? |
370 num_steps := 3 //TODO randomize, between 3 and 5? |
334 else |
371 else |
335 num_steps := 1; |
372 num_steps := 1; |
336 |
373 |
337 SetLength(step_done, num_steps); |
374 SetLength(step_done, num_steps); |
338 SetLength(last_cell, num_steps); |
375 SetLength(last_cell, num_steps); |
339 SetLength(came_from_pos, num_steps); |
376 SetLength(came_from_pos, num_steps); |
340 SetLength(came_from, num_steps, num_cells_x*num_cells_y); |
377 SetLength(came_from, num_steps, num_cells_x*num_cells_y); |
|
378 |
341 done := false; |
379 done := false; |
342 |
380 |
343 for current_step := 0 to num_steps - 1 do |
381 for current_step := 0 to num_steps - 1 do |
|
382 begin |
344 step_done[current_step] := false; |
383 step_done[current_step] := false; |
345 came_from_pos[current_step] := 0; |
384 came_from_pos[current_step] := 0; |
346 |
385 end; |
|
386 |
347 current_step := 0; |
387 current_step := 0; |
|
388 |
348 |
389 |
349 SetLength(seen_list, seen_cells_x, seen_cells_y); |
390 SetLength(seen_list, seen_cells_x, seen_cells_y); |
350 SetLength(xwalls, seen_cells_x, seen_cells_y - 1); |
391 SetLength(xwalls, seen_cells_x, seen_cells_y - 1); |
351 SetLength(ywalls, seen_cells_x - 1, seen_cells_y); |
392 SetLength(ywalls, seen_cells_x - 1, seen_cells_y); |
352 SetLength(x_edge_list, num_edges_x, num_cells_y); |
393 SetLength(x_edge_list, num_edges_x, num_cells_y); |
353 SetLength(y_edge_list, num_cells_x, num_edges_y); |
394 SetLength(y_edge_list, num_cells_x, num_edges_y); |
354 SetLength(maze, num_cells_x, num_cells_y); |
395 SetLength(maze, num_cells_x, num_cells_y); |
355 |
396 |
|
397 |
356 num_vertices := 0; |
398 num_vertices := 0; |
357 |
399 |
358 playHeight := num_cells_y * cellsize; |
400 playHeight := num_cells_y * cellsize; |
359 playWidth := num_cells_x * cellsize; |
401 playWidth := num_cells_x * cellsize; |
360 off_y := LAND_HEIGHT - playHeight; |
402 off_y := LAND_HEIGHT - playHeight; |