hedgewars/uLandGenMaze.pas
changeset 10015 4feced261c68
parent 9127 e350500c4edb
child 10189 875607ce793d
equal deleted inserted replaced
10014:56d2f2d5aad8 10015:4feced261c68
    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
   102 begin
   116 begin
   103     if when_seen(x + dir.x, y + dir.y) = current_step then //we are seeing ourselves, try another direction
   117     if when_seen(x + dir.x, y + dir.y) = current_step then //we are seeing ourselves, try another direction
   104     begin
   118     begin
   105         //we have already seen the target cell, decide if we should remove the wall anyway
   119         //we have already seen the target cell, decide if we should remove the wall anyway
   106         //(or put a wall there if maze_inverted, but we are not doing that right now)
   120         //(or put a wall there if maze_inverted, but we are not doing that right now)
   107         if not maze_inverted and (GetRandom(braidness) = 0) then
   121         if (not maze_inverted) and (GetRandom(braidness) = 0) then
   108         //or just warn that inverted+braid+indestructible terrain != good idea
   122         //or just warn that inverted+braid+indestructible terrain != good idea
   109         begin
   123         begin
   110             case dir.x of
   124             case dir.x of
   111             
   125 
   112                 -1:
   126                 -1:
   113                 if x > 0 then
   127                 if x > 0 then
   114                     ywalls[x-1, y] := false;
   128                     ywalls[x-1, y] := false;
   115                 1:
   129                 1:
   116                 if x < seen_cells_x - 1 then
   130                 if x < seen_cells_x - 1 then
   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 
   206 begin
   220 begin
   207     if maze_inverted or (x mod 2 = 0) then
   221     if maze_inverted or (x mod 2 = 0) then
   208         tmp_x := cellsize
   222         tmp_x := cellsize
   209     else
   223     else
   210         tmp_x := cellsize * 2 div 3;
   224         tmp_x := cellsize * 2 div 3;
   211         
   225 
   212     if maze_inverted or (y mod 2 = 0) then
   226     if maze_inverted or (y mod 2 = 0) then
   213         tmp_y := cellsize
   227         tmp_y := cellsize
   214     else
   228     else
   215         tmp_y := cellsize * 2 div 3;
   229         tmp_y := cellsize * 2 div 3;
   216 
   230 
   316 end;
   330 end;
   317 
   331 
   318 num_cells_x := LAND_WIDTH div cellsize;
   332 num_cells_x := LAND_WIDTH div cellsize;
   319 if not odd(num_cells_x) then
   333 if not odd(num_cells_x) then
   320     num_cells_x := num_cells_x - 1; //needs to be odd
   334     num_cells_x := num_cells_x - 1; //needs to be odd
   321     
   335 
   322 num_cells_y := LAND_HEIGHT div cellsize;
   336 num_cells_y := LAND_HEIGHT div cellsize;
   323 if not odd(num_cells_y) then
   337 if not odd(num_cells_y) then
   324     num_cells_y := num_cells_y - 1;
   338     num_cells_y := num_cells_y - 1;
   325     
   339 
   326 num_edges_x := num_cells_x - 1;
   340 num_edges_x := num_cells_x - 1;
   327 num_edges_y := num_cells_y - 1;
   341 num_edges_y := num_cells_y - 1;
   328 
   342 
   329 seen_cells_x := num_cells_x div 2;
   343 seen_cells_x := num_cells_x div 2;
   330 seen_cells_y := num_cells_y div 2;
   344 seen_cells_y := num_cells_y div 2;
   331 
   345 
   332 if maze_inverted then
   346 if maze_inverted then
   333     num_steps := 3 //TODO randomize, between 3 and 5?
   347     num_steps := 3 //TODO randomize, between 3 and 5?
   334 else
   348 else
   335     num_steps := 1;
   349     num_steps := 1;
   336     
   350 
   337 SetLength(step_done, num_steps);
   351 SetLength(step_done, num_steps);
   338 SetLength(last_cell, num_steps);
   352 SetLength(last_cell, num_steps);
   339 SetLength(came_from_pos, num_steps);
   353 SetLength(came_from_pos, num_steps);
   340 SetLength(came_from, num_steps, num_cells_x*num_cells_y);
   354 SetLength(came_from, num_steps, num_cells_x*num_cells_y);
       
   355 
   341 done := false;
   356 done := false;
   342 
   357 
   343 for current_step := 0 to num_steps - 1 do
   358 for current_step := 0 to num_steps - 1 do
       
   359 begin
   344     step_done[current_step] := false;
   360     step_done[current_step] := false;
   345     came_from_pos[current_step] := 0;
   361     came_from_pos[current_step] := 0;
   346     
   362 end;
       
   363 
   347 current_step := 0;
   364 current_step := 0;
       
   365 
   348 
   366 
   349 SetLength(seen_list, seen_cells_x, seen_cells_y);
   367 SetLength(seen_list, seen_cells_x, seen_cells_y);
   350 SetLength(xwalls, seen_cells_x, seen_cells_y - 1);
   368 SetLength(xwalls, seen_cells_x, seen_cells_y - 1);
   351 SetLength(ywalls, seen_cells_x - 1, seen_cells_y);
   369 SetLength(ywalls, seen_cells_x - 1, seen_cells_y);
   352 SetLength(x_edge_list, num_edges_x, num_cells_y);
   370 SetLength(x_edge_list, num_edges_x, num_cells_y);
   353 SetLength(y_edge_list, num_cells_x, num_edges_y);
   371 SetLength(y_edge_list, num_cells_x, num_edges_y);
   354 SetLength(maze, num_cells_x, num_cells_y);
   372 SetLength(maze, num_cells_x, num_cells_y);
       
   373 
   355 
   374 
   356 num_vertices := 0;
   375 num_vertices := 0;
   357 
   376 
   358 playHeight := num_cells_y * cellsize;
   377 playHeight := num_cells_y * cellsize;
   359 playWidth := num_cells_x * cellsize;
   378 playWidth := num_cells_x * cellsize;