Sync
This commit is contained in:
parent
6f050a029e
commit
776bba907c
3887 changed files with 59894 additions and 7280 deletions
|
|
@ -11,7 +11,7 @@ void main() {
|
|||
vis[y][x] = true;
|
||||
static struct P { immutable uint x, y; } // Will wrap-around.
|
||||
auto d = [P(x-1, y), P(x, y+1), P(x+1, y), P(x, y-1)];
|
||||
foreach (p; d.randomCover(unpredictableSeed.Random)) {
|
||||
foreach (p; d.randomCover) {
|
||||
if (p.x >= w || p.y >= h || vis[p.y][p.x]) continue;
|
||||
if (p.x == x) hor[max(y, p.y)][x] = "+ ";
|
||||
if (p.y == y) ver[y][max(x, p.x)] = " ";
|
||||
|
|
|
|||
143
Task/Maze-generation/Erlang/maze-generation.erl
Normal file
143
Task/Maze-generation/Erlang/maze-generation.erl
Normal file
|
|
@ -0,0 +1,143 @@
|
|||
-module( maze ).
|
||||
|
||||
-export( [cell_accessible_neighbours/1, cell_content/1, cell_content_set/2, cell_pid/3, cell_position/1, display/1, generation/2, stop/1, task/0] ).
|
||||
|
||||
-record( maze, {dict, max_x, max_y, start} ).
|
||||
-record( state, {content=" ", controller, is_dug=false, max_x, max_y, neighbours=[], position, walls=[north, south, east, west], walk_done} ).
|
||||
|
||||
cell_accessible_neighbours( Pid ) -> read( Pid, accessible_neighbours ).
|
||||
|
||||
cell_content( Pid ) -> read( Pid, content ).
|
||||
|
||||
cell_content_set( Pid, Content ) -> Pid ! {content, Content, erlang:self()}.
|
||||
|
||||
cell_pid( X, Y, Maze ) -> dict:fetch( {X, Y}, Maze#maze.dict ).
|
||||
|
||||
cell_position( Pid ) -> read( Pid, position ).
|
||||
|
||||
display( #maze{dict=Dict, max_x=Max_x, max_y=Max_y} ) ->
|
||||
Position_pids = dict:to_list( Dict ),
|
||||
display( Max_x, Max_y, reads(Position_pids, content), reads(Position_pids, walls) ).
|
||||
|
||||
generation( Max_x, Max_y ) ->
|
||||
Controller = erlang:self(),
|
||||
Position_pids = cells_create( Controller, Max_x, Max_y ),
|
||||
Pids = [Y || {_X, Y} <- Position_pids],
|
||||
[X ! {position_pids, Position_pids} || X <- Pids],
|
||||
{Position, Pid} = lists:nth( random:uniform(Max_x * Max_y), Position_pids ),
|
||||
Pid ! {dig, Controller},
|
||||
receive
|
||||
{dig_done} -> ok
|
||||
end,
|
||||
#maze{dict=dict:from_list(Position_pids), max_x=Max_x, max_y=Max_y, start=Position}.
|
||||
|
||||
stop( #maze{dict=Dict} ) ->
|
||||
Controller = erlang:self(),
|
||||
Pids = [Y || {_X, Y} <- dict:to_list(Dict)],
|
||||
[X ! {stop, Controller} || X <- Pids],
|
||||
ok.
|
||||
|
||||
task() ->
|
||||
Maze = generation( 16, 8 ),
|
||||
io:fwrite( "Starting at ~p~n", [Maze#maze.start] ),
|
||||
display( Maze ),
|
||||
stop( Maze ).
|
||||
|
||||
|
||||
|
||||
cells_create( Controller, Max_x, Max_y ) -> [{{X, Y}, cell_create(Controller, Max_x, Max_y, {X, Y})} || X <- lists:seq(1, Max_x), Y<- lists:seq(1, Max_y)].
|
||||
|
||||
cell_create( Controller, Max_x, Max_y, {X, Y} ) -> erlang:spawn_link( fun() -> random:seed( X*1000, Y*1000, (X+Y)*1000 ), loop( #state{controller=Controller, max_x=Max_x, max_y=Max_y, position={X, Y}} ) end ).
|
||||
|
||||
display( Max_x, Max_y, Position_contents, Position_walls ) ->
|
||||
All_rows = [display_row( Max_x, Y, Position_contents, Position_walls ) || Y <- lists:seq(Max_y, 1, -1)],
|
||||
[io:fwrite("~s+~n~s|~n", [North, West]) || {North, West} <- All_rows],
|
||||
io:fwrite("~s+~n", [lists:flatten(lists:duplicate(Max_x, display_row_north(true)))] ).
|
||||
|
||||
display_row( Max_x, Y, Position_contents, Position_walls ) ->
|
||||
North_wests = [display_row_walls(proplists:get_value({X,Y}, Position_contents), proplists:get_value({X,Y}, Position_walls)) || X <- lists:seq(1, Max_x)],
|
||||
North = lists:append( [North || {North, _West} <- North_wests] ),
|
||||
West = lists:append( [West || {_X, West} <- North_wests] ),
|
||||
{North, West}.
|
||||
|
||||
display_row_walls( Content, Walls ) -> {display_row_north( lists:member(north, Walls) ), display_row_west( lists:member(west, Walls), Content )}.
|
||||
|
||||
display_row_north( true ) -> "+---";
|
||||
display_row_north( false ) -> "+ ".
|
||||
|
||||
display_row_west( true, Content ) -> "| " ++ Content ++ " ";
|
||||
display_row_west( false, Content ) -> " " ++ Content ++ " ".
|
||||
|
||||
loop( State ) ->
|
||||
receive
|
||||
{accessible_neighbours, Pid} ->
|
||||
Pid ! {accessible_neighbours, loop_accessible_neighbours( State#state.neighbours, State#state.walls ), erlang:self()},
|
||||
loop( State );
|
||||
{content, Pid} ->
|
||||
Pid ! {content, State#state.content, erlang:self()},
|
||||
loop( State );
|
||||
{content, Content, _Pid} ->
|
||||
loop( State#state{content=Content} );
|
||||
{dig, Pid} ->
|
||||
Not_dug_neighbours = loop_not_dug( State#state.neighbours ),
|
||||
New_walls = loop_dig( Not_dug_neighbours, lists:delete( loop_wall_from_pid(Pid, State#state.neighbours), State#state.walls), Pid ),
|
||||
loop( State#state{is_dug=true, walls=New_walls, walk_done=Pid} );
|
||||
{dig_done} ->
|
||||
Not_dug_neighbours = loop_not_dug( State#state.neighbours ),
|
||||
New_walls = loop_dig( Not_dug_neighbours, State#state.walls, State#state.walk_done ),
|
||||
loop( State#state{walls=New_walls} );
|
||||
{is_dug, Pid} ->
|
||||
Pid ! {is_dug, State#state.is_dug, erlang:self()},
|
||||
loop( State );
|
||||
{position, Pid} ->
|
||||
Pid ! {position, State#state.position, erlang:self()},
|
||||
loop( State );
|
||||
{position_pids, Position_pids} ->
|
||||
{_My_position, Neighbours} = lists:foldl( fun loop_neighbours/2, {State#state.position, []}, Position_pids ),
|
||||
erlang:garbage_collect(), % Shrink process after using large Pid_positions. For memory starved systems.
|
||||
loop( State#state{neighbours=Neighbours} );
|
||||
{stop, Controller} when Controller =:= State#state.controller ->
|
||||
ok;
|
||||
{walls, Pid} ->
|
||||
Pid ! {walls, State#state.walls, erlang:self()},
|
||||
loop( State )
|
||||
end.
|
||||
|
||||
loop_accessible_neighbours( Neighbours, Walls ) -> [Pid || {Direction, Pid} <- Neighbours, not lists:member(Direction, Walls)].
|
||||
|
||||
loop_dig( [], Walls, Pid ) ->
|
||||
Pid ! {dig_done},
|
||||
Walls;
|
||||
loop_dig( Not_dug_neighbours, Walls, _Pid ) ->
|
||||
{Dig_pid, Dig_direction} = lists:nth( random:uniform(erlang:length(Not_dug_neighbours)), Not_dug_neighbours ),
|
||||
Dig_pid ! {dig, erlang:self()},
|
||||
lists:delete( Dig_direction, Walls ).
|
||||
|
||||
loop_neighbours( {{X, Y}, Pid}, {{X, My_y}, Acc} ) when Y =:= My_y + 1 -> {{X, My_y}, [{north, Pid} | Acc]};
|
||||
loop_neighbours( {{X, Y}, Pid}, {{X, My_y}, Acc} ) when Y =:= My_y - 1 -> {{X, My_y}, [{south, Pid} | Acc]};
|
||||
loop_neighbours( {{X, Y}, Pid}, {{My_x, Y}, Acc} ) when X =:= My_x + 1 -> {{My_x, Y}, [{east, Pid} | Acc]};
|
||||
loop_neighbours( {{X, Y}, Pid}, {{My_x, Y}, Acc} ) when X =:= My_x - 1 -> {{My_x, Y}, [{west, Pid} | Acc]};
|
||||
loop_neighbours( _Position_pid, Acc ) -> Acc.
|
||||
|
||||
loop_not_dug( Neighbours ) ->
|
||||
My_pid = erlang:self(),
|
||||
[Pid ! {is_dug, My_pid} || {_Direction, Pid} <- Neighbours],
|
||||
[{Pid, Direction} || {Direction, Pid} <- Neighbours, not read_receive(Pid, is_dug)].
|
||||
|
||||
loop_wall_from_pid( Pid, Neighbours ) -> loop_wall_from_pid_result( lists:keyfind(Pid, 2, Neighbours) ).
|
||||
loop_wall_from_pid_result( {Direction, _Pid} ) -> Direction;
|
||||
loop_wall_from_pid_result( false ) -> controller.
|
||||
|
||||
read( Pid, Key ) ->
|
||||
Pid ! {Key, erlang:self()},
|
||||
read_receive( Pid, Key ).
|
||||
|
||||
read_receive( Pid, Key ) ->
|
||||
receive
|
||||
{Key, Value, Pid} -> Value
|
||||
end.
|
||||
|
||||
reads( Position_pids, Key ) ->
|
||||
My_pid = erlang:self(),
|
||||
[Pid ! {Key, My_pid} || {_Position, Pid} <- Position_pids],
|
||||
[{Position, read_receive(Pid, Key)} || {Position, Pid} <- Position_pids].
|
||||
|
|
@ -1,36 +1,36 @@
|
|||
function maze(x,y) {
|
||||
var n=x*y-1;
|
||||
if (n<0) {alert("illegal maze dimensions");return;}
|
||||
var horiz=[]; for (var j= 0; j<x+1; j++) horiz[j]= [];
|
||||
var verti=[]; for (var j= 0; j<y+1; j++) verti[j]= [];
|
||||
var here= [Math.floor(Math.random()*x), Math.floor(Math.random()*y)];
|
||||
var path= [here];
|
||||
var unvisited= [];
|
||||
for (var j= 0; j<x+2; j++) {
|
||||
unvisited[j]= [];
|
||||
var horiz =[]; for (var j= 0; j<x+1; j++) horiz[j]= [],
|
||||
verti =[]; for (var j= 0; j<y+1; j++) verti[j]= [],
|
||||
here = [Math.floor(Math.random()*x), Math.floor(Math.random()*y)],
|
||||
path = [here],
|
||||
unvisited = [];
|
||||
for (var j = 0; j<x+2; j++) {
|
||||
unvisited[j] = [];
|
||||
for (var k= 0; k<y+1; k++)
|
||||
unvisited[j].push(j>0 && j<x+1 && k>0 && (j != here[0]+1 || k != here[1]+1));
|
||||
}
|
||||
while (0<n) {
|
||||
var potential= [[here[0]+1, here[1]], [here[0],here[1]+1],
|
||||
var potential = [[here[0]+1, here[1]], [here[0],here[1]+1],
|
||||
[here[0]-1, here[1]], [here[0],here[1]-1]];
|
||||
var neighbors= [];
|
||||
for (var j= 0; j < 4; j++)
|
||||
var neighbors = [];
|
||||
for (var j = 0; j < 4; j++)
|
||||
if (unvisited[potential[j][0]+1][potential[j][1]+1])
|
||||
neighbors.push(potential[j]);
|
||||
if (neighbors.length) {
|
||||
n= n-1;
|
||||
n = n-1;
|
||||
next= neighbors[Math.floor(Math.random()*neighbors.length)];
|
||||
unvisited[next[0]+1][next[1]+1]= false;
|
||||
if (next[0] == here[0])
|
||||
horiz[next[0]][(next[1]+here[1]-1)/2]= true;
|
||||
else
|
||||
verti[(next[0]+here[0]-1)/2][next[1]]= true;
|
||||
path.push(here= next);
|
||||
path.push(here = next);
|
||||
} else
|
||||
here= path.pop();
|
||||
here = path.pop();
|
||||
}
|
||||
return ({x: x, y: y, horiz: horiz, verti: verti});
|
||||
return {x: x, y: y, horiz: horiz, verti: verti};
|
||||
}
|
||||
|
||||
function display(m) {
|
||||
|
|
|
|||
26
Task/Maze-generation/Julia/maze-generation.julia
Normal file
26
Task/Maze-generation/Julia/maze-generation.julia
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
function walk(maze, cell, visited = {})
|
||||
push!(visited, cell)
|
||||
for neigh in shuffle(neighbors(cell, size(maze)))
|
||||
if !(neigh in visited)
|
||||
maze[int((cell+neigh)/2)...] = 0
|
||||
walk(maze, neigh, visited)
|
||||
end
|
||||
end
|
||||
maze
|
||||
end
|
||||
|
||||
neighbors(c,b,d=2) = filter(check(b),map(m->c+d*m, {[0,1],[-1,0],[0,-1],[1,0]}))
|
||||
|
||||
check(bound) = cell -> all([1,1] .<= cell .<= [bound...])
|
||||
|
||||
maze(w, h) = walk([i%2|j%2 for i=1:2w+1,j=1:2h+1], 2*[rand(1:w),rand(1:h)])
|
||||
|
||||
pprint(maze) = print(mapslices(x-> [join(x)], maze, [2]))
|
||||
|
||||
function mprint(maze, wall = CharString("╹╸┛╺┗━┻╻┃┓┫┏┣┳╋"...))
|
||||
pprint([ maze[i,j] == 0 ? ' ' :
|
||||
wall[sum(c-> 2.0^.5(3c[1]+c[2]+3),
|
||||
filter(x -> maze[x...] != 0,
|
||||
neighbors([i,j],[size(maze)...],1)) .- {[i,j]})]
|
||||
for i = 1:2:size(maze,1), j = 1:size(maze,2)])
|
||||
end
|
||||
|
|
@ -1,11 +1,11 @@
|
|||
MazeGraph[m_, n_] :=
|
||||
Block[{$RecursionLimit = Infinity, grid = GridGraph[{m, n}],
|
||||
visited = {}},
|
||||
Graph[Range[m n], Reap[{AppendTo[visited, #];
|
||||
Do[
|
||||
If[FreeQ[visited, neighbor],
|
||||
Sow[# <-> neighbor]; #0@neighbor], {neighbor,
|
||||
RandomSample@AdjacencyList[grid, #]}]} &@
|
||||
RandomChoice@VertexList@grid][[2, 1]],
|
||||
GraphLayout -> {"GridEmbedding", "Dimension" -> {m, n}}]];
|
||||
Block[{$RecursionLimit = Infinity, grid = GridGraph[{m, n}],
|
||||
unvisitedQ}, unvisitedQ[_] := True;
|
||||
Graph[Range[m n], Reap[{unvisitedQ[#] = False;
|
||||
Do[
|
||||
If[unvisitedQ[neighbor],
|
||||
Sow[# <-> neighbor]; #0@neighbor], {neighbor,
|
||||
RandomSample@AdjacencyList[grid, #]}]} &@
|
||||
RandomChoice@VertexList@grid][[2, 1]],
|
||||
GraphLayout -> {"GridEmbedding", "Dimension" -> {m, n}}]];
|
||||
maze = MazeGraph[13, 21]
|
||||
|
|
|
|||
217
Task/Maze-generation/PL-I/maze-generation.pli
Normal file
217
Task/Maze-generation/PL-I/maze-generation.pli
Normal file
|
|
@ -0,0 +1,217 @@
|
|||
*process source attributes xref or(!);
|
||||
mgg: Proc Options(main);
|
||||
/* REXX ***************************************************************
|
||||
* 04.09.2013 Walter Pachl translated from REXX version 2
|
||||
**********************************************************************/
|
||||
Dcl (MIN,MOD,RANDOM,REPEAT,SUBSTR) Builtin;
|
||||
Dcl SYSIN STREAM INPUT;
|
||||
Dcl print Print;
|
||||
Dcl imax Bin Fixed(31) init(10);
|
||||
Dcl jmax Bin Fixed(31) init(15);
|
||||
Dcl seed Bin Fixed(31) init(4711);
|
||||
Get File(sysin) Data(imax,jmax,seed);
|
||||
Dcl ii Bin Fixed(31);
|
||||
Dcl jj Bin Fixed(31);
|
||||
Dcl id Bin Fixed(31);
|
||||
Dcl jd Bin Fixed(31);
|
||||
id=2*imax+1; /* vertical dimension of a.i.j */
|
||||
jd=2*jmax+1; /* horizontal dimension of a.i.j */
|
||||
Dcl c Char(2000) Var;
|
||||
c=repeat('123456789'!!'abcdefghijklmnopqrstuvwxyz'!!
|
||||
'ABCDEFGHIJKLMNOPQRSTUVWXYZ',20);
|
||||
Dcl x Bin Float(53);
|
||||
x=random(seed);
|
||||
Dcl ps Bin Fixed(31) Init(1); /* first position */
|
||||
Dcl na Bin Fixed(31) Init(1); /* number of points used */
|
||||
Dcl si Bin Fixed(31); /* loop to compute paths */
|
||||
Begin;
|
||||
Dcl a(id,jd) Bin Fixed(15);
|
||||
Dcl p(imax,jmax) Char(1);
|
||||
Dcl 1 pl(imax*jmax),
|
||||
2 ic Bin Fixed(15),
|
||||
2 jc Bin Fixed(15);
|
||||
Dcl 1 np(imax*jmax),
|
||||
2 ic Bin Fixed(15),
|
||||
2 jc Bin Fixed(15);
|
||||
Dcl 1 pos(imax*jmax),
|
||||
2 ic Bin Fixed(15),
|
||||
2 jc Bin Fixed(15);
|
||||
Dcl npl Bin Fixed(31) Init(0);
|
||||
a=1; /* mark all borders present */
|
||||
p='.'; /* Initialize all grid points */
|
||||
ii=rnd(imax); /* find a start position */
|
||||
jj=rnd(jmax);
|
||||
Do si=1 To 1000; /* Do Forever - see Leave */
|
||||
Call path(ii,jj); /* compute a path starting at ii/jj */
|
||||
If na=imax*jmax Then /* all points used */
|
||||
Leave; /* we are done */
|
||||
Call select_next(ii,jj); /* get a new start from a path*/
|
||||
End;
|
||||
Call show;
|
||||
Return;
|
||||
|
||||
path: Procedure(ii,jj);
|
||||
/**********************************************************************
|
||||
* compute a path starting from point (ii,jj)
|
||||
**********************************************************************/
|
||||
Dcl ii Bin Fixed(31);
|
||||
Dcl jj Bin Fixed(31);
|
||||
Dcl nb Bin Fixed(31);
|
||||
Dcl ch Bin Fixed(31);
|
||||
Dcl pp Bin Fixed(31);
|
||||
p(ii,jj)='1';
|
||||
pos.ic(ps)=ii;
|
||||
pos.jc(ps)=jj;
|
||||
Do pp=1 to 50; /* compute a path of maximum length 50*/
|
||||
nb=neighbors(ii,jj); /* number of free neighbors */
|
||||
Select;
|
||||
When(nb=1) /* just one */
|
||||
Call advance((1),ii,jj); /* go for it */
|
||||
When(nb>0) Do; /* more Than 1 */
|
||||
ch=rnd(nb); /* choose one possibility */
|
||||
Call advance(ch,ii,jj); /* and go for that */
|
||||
End;
|
||||
Otherwise /* none available */
|
||||
Leave;
|
||||
End;
|
||||
End;
|
||||
End;
|
||||
|
||||
neighbors: Procedure(i,j) Returns(Bin Fixed(31));
|
||||
/**********************************************************************
|
||||
* count the number of free neighbors of point (i,j)
|
||||
**********************************************************************/
|
||||
Dcl i Bin Fixed(31);
|
||||
Dcl j Bin Fixed(31);
|
||||
Dcl in Bin Fixed(31);
|
||||
Dcl jn Bin Fixed(31);
|
||||
Dcl nb Bin Fixed(31) Init(0);
|
||||
in=i-1; If in>0 Then Call check(in,j,nb);
|
||||
in=i+1; If in<=imax Then Call check(in,j,nb);
|
||||
jn=j-1; If jn>0 Then Call check(i,jn,nb);
|
||||
jn=j+1; If jn<=jmax Then Call check(i,jn,nb);
|
||||
Return(nb);
|
||||
End;
|
||||
|
||||
check: Procedure(i,j,n);
|
||||
/**********************************************************************
|
||||
* check if point (i,j) is free and note it as possible successor
|
||||
**********************************************************************/
|
||||
Dcl i Bin Fixed(31);
|
||||
Dcl j Bin Fixed(31);
|
||||
Dcl n Bin Fixed(31);
|
||||
If p(i,j)='.' Then Do; /* point is free */
|
||||
n+=1; /* number of free neighbors */
|
||||
np.ic(n)=i; /* note it as possible choice */
|
||||
np.jc(n)=j;
|
||||
End;
|
||||
End;
|
||||
|
||||
advance: Procedure(ch,ii,jj);
|
||||
/**********************************************************************
|
||||
* move to the next point of the current path
|
||||
**********************************************************************/
|
||||
Dcl ch Bin Fixed(31);
|
||||
Dcl ii Bin Fixed(31);
|
||||
Dcl jj Bin Fixed(31);
|
||||
Dcl ai Bin Fixed(31);
|
||||
Dcl aj Bin Fixed(31);
|
||||
Dcl pii Bin Fixed(31) Init((ii));
|
||||
Dcl pjj Bin Fixed(31) Init((jj));
|
||||
Dcl z Bin Fixed(31);
|
||||
ii=np.ic(ch);
|
||||
jj=np.jc(ch);
|
||||
ps+=1; /* position number */
|
||||
pos.ic(ps)=ii; /* note its coordinates */
|
||||
pos.jc(ps)=jj;
|
||||
p(ii,jj)=substr(c,ps,1); /* mark the point as used */
|
||||
ai=pii+ii; /* vertical border position */
|
||||
aj=pjj+jj; /* horizontal border position */
|
||||
a(ai,aj)=0; /* tear the border down */
|
||||
na+=1; /* number of used positions */
|
||||
z=npl+1; /* add the point to the list */
|
||||
pl.ic(z)=ii; /* of follow-up start pos. */
|
||||
pl.jc(z)=jj;
|
||||
npl=z;
|
||||
End;
|
||||
|
||||
show: Procedure;
|
||||
/*********************************************************************
|
||||
* Show the resulting maze
|
||||
*********************************************************************/
|
||||
Dcl i Bin Fixed(31);
|
||||
Dcl j Bin Fixed(31);
|
||||
Dcl ol Char(300) Var;
|
||||
Put File(print) Edit('mgg',imax,jmax,seed)(Skip,a,3(f(4)));
|
||||
Put File(print) Skip Data(na);
|
||||
Do i=1 To id;
|
||||
ol='';
|
||||
Do j=1 To jd;
|
||||
If mod(i,2)=1 Then Do; /* odd lines */
|
||||
If a(i,j)=1 Then Do; /* border to be drawn */
|
||||
If mod(j,2)=0 Then
|
||||
ol=ol!!'---'; /* draw the border */
|
||||
Else
|
||||
ol=ol!!'+';
|
||||
End;
|
||||
Else Do; /* border was torn down */
|
||||
If mod(j,2)=0 Then
|
||||
ol=ol!!' '; /* blanks instead of border */
|
||||
Else
|
||||
ol=ol!!'+';
|
||||
End;
|
||||
End;
|
||||
Else Do; /* even line */
|
||||
If a(i,j)=1 Then Do;
|
||||
If mod(j,2)=0 Then /* even column */
|
||||
ol=ol!!' '; /* moving space */
|
||||
Else /* odd column */
|
||||
ol=ol!!'!'; /* draw the border */
|
||||
End;
|
||||
Else /* border was torn down */
|
||||
ol=ol!!' '; /* blank instead of border */
|
||||
End;
|
||||
End;
|
||||
Select;
|
||||
When(i=6) substr(ol,11,1)='A';
|
||||
When(i=8) substr(ol, 3,1)='B';
|
||||
Otherwise;
|
||||
End;
|
||||
Put File(print) Edit(ol,i)(Skip,a,f(3));
|
||||
End;
|
||||
End;
|
||||
|
||||
select_next: Procedure(is,js);
|
||||
/**********************************************************************
|
||||
* look for a point to start the nnext path
|
||||
**********************************************************************/
|
||||
Dcl is Bin Fixed(31);
|
||||
Dcl js Bin Fixed(31);
|
||||
Dcl n Bin Fixed(31);
|
||||
Dcl nb Bin Fixed(31);
|
||||
Dcl s Bin Fixed(31);
|
||||
Do Until(nb>0); /* loop until one is found */
|
||||
n=npl; /* number of points recorded */
|
||||
s=rnd(n); /* pick a random index */
|
||||
is=pl.ic(s); /* its coordinates */
|
||||
js=pl.jc(s);
|
||||
nb=neighbors(is,js); /* count free neighbors */
|
||||
If nb=0 Then Do; /* if there is none */
|
||||
pl.ic(s)=pl.ic(n); /* remove this point */
|
||||
pl.jc(s)=pl.jc(n);
|
||||
npl-=1;
|
||||
End;
|
||||
End;
|
||||
End;
|
||||
|
||||
rnd: Proc(n) Returns(Bin Fixed(31));
|
||||
/*********************************************************************
|
||||
* return a pseudo-random integer between 1 and n
|
||||
*********************************************************************/
|
||||
dcl (r,n) Bin Fixed(31);
|
||||
r=min(random()*n+1,n);
|
||||
Return(r);
|
||||
End;
|
||||
|
||||
End;
|
||||
End;
|
||||
102
Task/Maze-generation/REXX/maze-generation-1.rexx
Normal file
102
Task/Maze-generation/REXX/maze-generation-1.rexx
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
/*REXX program generates and displays a (rectangular) solvable maze. */
|
||||
height=0; @.=0 /*default for all cells visited.*/
|
||||
parse arg rows cols seed . /*allow user to specify maze size*/
|
||||
if rows='' | rows==',' then rows=19 /*No rows given? Use the default*/
|
||||
if cols='' | cols==',' then cols=19 /*No cols given? Use the default*/
|
||||
if seed\=='' then call random ,,seed /*use a seed for repeatability. */
|
||||
call buildRow '┌'copies('~┬',cols-1)'~┐' /*build the top edge of maze.*/
|
||||
/*(below) build the maze's grid.*/
|
||||
do r=1 for rows; _=; __=; hp= '|'; hj='├'
|
||||
do c=1 for cols; _= _||hp'1'; __=__||hj'~'; hj='┼'; hp='│'
|
||||
end /*c*/
|
||||
call buildRow _'│' /*build right edge of cells.*/
|
||||
if r\==rows then call buildRow __'┤' /* " " " " maze.*/
|
||||
end /*r*/
|
||||
|
||||
call buildRow '└'copies('~┴',cols-1)'~┘' /*build the bottom maze edge.*/
|
||||
r!=random(1,rows)*2; c!=random(1,cols)*2; @.r!.c!=0 /*choose 1st cell*/
|
||||
/* [↓] traipse through the maze.*/
|
||||
do forever; n=hood(r!,c!); if n==0 then if \fcell() then leave
|
||||
call ?; @._r._c=0 /*get the (next) direction to go.*/
|
||||
ro=r!; co=c!; r!=_r; c!=_c /*save original cell coordinates.*/
|
||||
?.zr=?.zr%2; ?.zc=?.zc%2 /*get the row and cell directions*/
|
||||
rw=ro+?.zr; cw=co+?.zc /*calculate the next row and col.*/
|
||||
@.rw.cw='·' /*mark the cell as being visited.*/
|
||||
end /*forever*/
|
||||
|
||||
do r=1 for height; _= /*display the maze. */
|
||||
do c=1 for cols*2 + 1; _=_ || @.r.c; end /*c*/
|
||||
if \(r//2) then _=translate(_, '\', "·") /*trans to backslash*/
|
||||
@.r=_ /*save the row in @.*/
|
||||
end /*r*/
|
||||
|
||||
do #=1 for height; _=@.# /*display maze to the terminal. */
|
||||
call makeNice /*make some cell corners prettier*/
|
||||
_=changestr(1,_,111) /*these four ────────────────────*/
|
||||
_=changestr(0,_,000) /*─── statements are ────────────*/
|
||||
_=changestr('·',_," ") /*──────── used for preserving ──*/
|
||||
_=changestr('~',_,"───") /*──────────── the aspect ratio. */
|
||||
say translate(_, '─│', "═|\10") /*make it presentable for screen.*/
|
||||
end /*#*/
|
||||
exit /*stick a fork in it, we're done.*/
|
||||
/*──────────────────────────────────@ subroutine────────────────────────*/
|
||||
@: parse arg _r,_c; return @._r._c /*a fast way to reference a cell.*/
|
||||
/*──────────────────────────────────? subroutine────────────────────────*/
|
||||
?: do forever; ?.=0; ?=random(1,4); if ?==1 then ?.zc=-2 /*north*/
|
||||
if ?==2 then ?.zr=+2 /* east*/
|
||||
if ?==3 then ?.zc=+2 /*south*/
|
||||
if ?==4 then ?.zr=-2 /* west*/
|
||||
_r=r!+?.zr; _c=c!+?.zc; if @._r._c==1 then return
|
||||
end /*forever*/
|
||||
/*──────────────────────────────────BUILDROW subroutine─────────────────*/
|
||||
buildRow: parse arg z; height=height+1; width=length(z)
|
||||
do c=1 for width; @.height.c=substr(z,c,1); end; return
|
||||
/*──────────────────────────────────FCELL subroutine────────────────────*/
|
||||
fcell: do r=1 for rows; r2=r+r
|
||||
do c=1 for cols; c2=c+c
|
||||
if hood(r2,c2)==1 then do; r!=r2; c!=c2; @.r!.c!=0; return 1;end
|
||||
end /*c*/
|
||||
end /*r*/
|
||||
return 0
|
||||
/*──────────────────────────────────HOOD subroutine─────────────────────*/
|
||||
hood: parse arg rh,ch; return @(rh+2,ch)+@(rh-2,ch)+@(rh,ch-2)+@(rh,ch+2)
|
||||
/*──────────────────────────────────MAKENICE subroutine─────────────────*/
|
||||
makeNice: width=length(_); old=#-1; new=#+1; old_=@.old; new_=@.new
|
||||
if left(_,2) =='├·' then _=translate(_, '|', "├")
|
||||
if right(_,2)=='·┤' then _=translate(_, '|', "┤")
|
||||
/* [↓] handle the top grid row.*/
|
||||
do k=1 for width while #==1; z=substr(_,k,1) /*maze top row.*/
|
||||
if z\=='┬' then iterate
|
||||
if substr(new_,k,1)=='\' then _=overlay('═',_,k)
|
||||
end /*k*/
|
||||
|
||||
do k=1 for width while #==height; z=substr(_,k,1) /*maze bot row.*/
|
||||
if z\=='┴' then iterate
|
||||
if substr(old_,k,1)=='\' then _=overlay('═',_,k)
|
||||
end /*k*/
|
||||
/* [↓] handle the mid grid rows*/
|
||||
do k=3 to width-2 by 2 while #//2; z=substr(_,k,1) /*maze mid rows*/
|
||||
if z\=='┼' then iterate
|
||||
le=substr(_,k-1,1)
|
||||
ri=substr(_,k+1,1)
|
||||
up=substr(old_,k,1)
|
||||
dw=substr(new_,k,1)
|
||||
select
|
||||
when le=='·' & ri=='·' & up=='│' & dw=='│' then _=overlay('|',_,k)
|
||||
when le=='~' & ri=='~' & up=='\' & dw=='\' then _=overlay('═',_,k)
|
||||
when le=='~' & ri=='~' & up=='\' & dw=='│' then _=overlay('┬',_,k)
|
||||
when le=='~' & ri=='~' & up=='│' & dw=='\' then _=overlay('┴',_,k)
|
||||
when le=='~' & ri=='·' & up=='\' & dw=='\' then _=overlay('═',_,k)
|
||||
when le=='·' & ri=='~' & up=='\' & dw=='\' then _=overlay('═',_,k)
|
||||
when le=='·' & ri=='·' & up=='│' & dw=='\' then _=overlay('|',_,k)
|
||||
when le=='·' & ri=='·' & up=='\' & dw=='│' then _=overlay('|',_,k)
|
||||
when le=='·' & ri=='~' & up=='\' & dw=='│' then _=overlay('┌',_,k)
|
||||
when le=='·' & ri=='~' & up=='│' & dw=='\' then _=overlay('└',_,k)
|
||||
when le=='~' & ri=='·' & up=='\' & dw=='│' then _=overlay('┐',_,k)
|
||||
when le=='~' & ri=='·' & up=='│' & dw=='\' then _=overlay('┘',_,k)
|
||||
when le=='~' & ri=='·' & up=='│' & dw=='│' then _=overlay('┤',_,k)
|
||||
when le=='·' & ri=='~' & up=='│' & dw=='│' then _=overlay('├',_,k)
|
||||
otherwise nop
|
||||
end /*select*/
|
||||
end /*k*/
|
||||
return
|
||||
57
Task/Maze-generation/REXX/maze-generation-2.rexx
Normal file
57
Task/Maze-generation/REXX/maze-generation-2.rexx
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
/*REXX program generates and displays a (rectangular) solvable maze. */
|
||||
height=0; @.=0 /*default for all cells visited.*/
|
||||
parse arg rows cols seed . /*allow user to specify maze size*/
|
||||
if rows='' | rows==',' then rows=19 /*No rows given? Use the default*/
|
||||
if cols='' | cols==',' then cols=19 /*No cols given? Use the default*/
|
||||
if seed\=='' then call random ,,seed /*use a seed for repeatability. */
|
||||
call buildRow '┌'copies('─┬',cols-1)'─┐' /*build the top edge of maze.*/
|
||||
/*(below) build the maze's grid.*/
|
||||
do r=1 for rows; _=; __=; hp= '|'; hj='├'
|
||||
do c=1 for cols; _= _||hp'1'; __=__||hj'─'; hj='┼'; hp='│'
|
||||
end /*c*/
|
||||
call buildRow _'│' /*build right edge of cells.*/
|
||||
if r\==rows then call buildRow __'┤' /* " " " " maze.*/
|
||||
end /*r*/
|
||||
|
||||
call buildRow '└'copies('─┴',cols-1)'─┘' /*build the bottom maze edge.*/
|
||||
r!=random(1,rows)*2; c!=random(1,cols)*2; @.r!.c!=0 /*choose 1st cell*/
|
||||
/* [↓] traipse through the maze.*/
|
||||
do forever; n=hood(r!,c!); if n==0 then if \fcell() then leave
|
||||
call ?; @._r._c=0 /*get the (next) direction to go.*/
|
||||
ro=r!; co=c!; r!=_r; c!=_c /*save original cell coordinates.*/
|
||||
?.zr=?.zr%2; ?.zc=?.zc%2 /*get the row and cell directions*/
|
||||
rw=ro+?.zr; cw=co+?.zc /*calculate the next row and col.*/
|
||||
@.rw.cw='·' /*mark the cell as being visited.*/
|
||||
end /*forever*/
|
||||
|
||||
do r=1 for height; _= /*display the maze. */
|
||||
do c=1 for cols*2 + 1; _=_ || @.r.c; end /*c*/
|
||||
if \(r//2) then _=translate(_, '\', "·") /*trans to backslash*/
|
||||
_=changestr(1,_,111) /*these four ────────────────────*/
|
||||
_=changestr(0,_,000) /*─── statements are ────────────*/
|
||||
_=changestr('·',_," ") /*──────── used for preserving ──*/
|
||||
_=changestr('─',_,"───") /*──────────── the aspect ratio. */
|
||||
say translate(_,'│',"|\10") /*make it presentable for screen.*/
|
||||
end /*r*/
|
||||
exit /*stick a fork in it, we're done.*/
|
||||
/*──────────────────────────────────@ subroutine────────────────────────*/
|
||||
@: parse arg _r,_c; return @._r._c /*a fast way to reference a cell.*/
|
||||
/*──────────────────────────────────? subroutine────────────────────────*/
|
||||
?: do forever; ?.=0; ?=random(1,4); if ?==1 then ?.zc=-2 /*north*/
|
||||
if ?==2 then ?.zr=+2 /* east*/
|
||||
if ?==3 then ?.zc=+2 /*south*/
|
||||
if ?==4 then ?.zr=-2 /* west*/
|
||||
_r=r!+?.zr; _c=c!+?.zc; if @._r._c==1 then return
|
||||
end /*forever*/
|
||||
/*──────────────────────────────────BUILDROW subroutine─────────────────*/
|
||||
buildRow: parse arg z; height=height+1; width=length(z)
|
||||
do c=1 for width; @.height.c=substr(z,c,1); end; return
|
||||
/*──────────────────────────────────FCELL subroutine────────────────────*/
|
||||
fcell: do r=1 for rows; r2=r+r
|
||||
do c=1 for cols; c2=c+c
|
||||
if hood(r2,c2)==1 then do; r!=r2; c!=c2; @.r!.c!=0; return 1;end
|
||||
end /*c*/
|
||||
end /*r*/
|
||||
return 0
|
||||
/*──────────────────────────────────HOOD subroutine─────────────────────*/
|
||||
hood: parse arg rh,ch; return @(rh+2,ch)+@(rh-2,ch)+@(rh,ch-2)+@(rh,ch+2)
|
||||
168
Task/Maze-generation/REXX/maze-generation-3.rexx
Normal file
168
Task/Maze-generation/REXX/maze-generation-3.rexx
Normal file
|
|
@ -0,0 +1,168 @@
|
|||
/* REXX ***************************************************************
|
||||
* 04.09.2013 Walter Pachl
|
||||
**********************************************************************/
|
||||
Parse Arg imax jmax seed
|
||||
If imax='' Then imax=10
|
||||
If jmax='' Then jmax=15
|
||||
If seed='' Then seed=4711
|
||||
c='123456789'||,
|
||||
'abcdefghijklmnopqrstuvwxyz'||,
|
||||
translate('abcdefghijklmnopqrstuvwxyz')
|
||||
c=copies(c,10)
|
||||
call random 1,10,seed
|
||||
id=2*imax+1 /* vertical dimension of a.i.j */
|
||||
jd=2*jmax+1 /* horizontal dimension of a.i.j */
|
||||
a.=1 /* mark all borders present */
|
||||
p.='.' /* Initialize all grid points */
|
||||
pl.=0 /* path list */
|
||||
ii=random(1,imax) /* find a start position */
|
||||
jj=random(1,jmax)
|
||||
p=1 /* first position */
|
||||
na=1 /* number of points used */
|
||||
Do si=1 To 1000 /* Do Forever - see Leave */
|
||||
/* Say 'loop' si na show progress */
|
||||
Call path ii,jj /* compute a path starting at ii/jj */
|
||||
If na=imax*jmax Then /* all points used */
|
||||
Leave /* we are done */
|
||||
Parse Value select_next() With ii jj /* get a new start from a path*/
|
||||
End
|
||||
|
||||
/***************
|
||||
Do i=1 To imax
|
||||
ol=''
|
||||
Do j=1 To jmax
|
||||
ol=ol||p.i.j
|
||||
End
|
||||
Say ol
|
||||
End
|
||||
Say ' '
|
||||
***************/
|
||||
Call show
|
||||
/***********************
|
||||
Do pi=1 To imax*jmax
|
||||
Say right(pi,3) pos.pi
|
||||
End
|
||||
***********************/
|
||||
Exit
|
||||
|
||||
path: Procedure Expose p. np. p pl. c a. na imax jmax id jd pos.
|
||||
/**********************************************************************
|
||||
* compute a path starting from point (ii,jj)
|
||||
**********************************************************************/
|
||||
Parse Arg ii,jj
|
||||
p.ii.jj='1'
|
||||
pos.p=ii jj
|
||||
Do pp=1 to 50 /* compute a path of maximum length 50*/
|
||||
neighbors=neighbors(ii,jj) /* number of free neighbors */
|
||||
Select
|
||||
When neighbors=1 Then /* just one */
|
||||
Call advance 1,ii,jj /* go for it */
|
||||
When neighbors>0 Then Do /* more Than 1 */
|
||||
ch=random(1,neighbors) /* choose one possibility */
|
||||
Call advance ch,ii,jj /* and go for that */
|
||||
End
|
||||
Otherwise /* none available */
|
||||
Leave
|
||||
End
|
||||
End
|
||||
Return
|
||||
|
||||
neighbors: Procedure Expose p. np. imax jmax neighbors pl.
|
||||
/**********************************************************************
|
||||
* count the number of free neighbors of point (i,j)
|
||||
**********************************************************************/
|
||||
Parse Arg i,j
|
||||
neighbors=0
|
||||
in=i-1; If in>0 Then Call check in,j
|
||||
in=i+1; If in<=imax Then Call check in,j
|
||||
jn=j-1; If jn>0 Then Call check i,jn
|
||||
jn=j+1; If jn<=jmax Then Call check i,jn
|
||||
Return neighbors
|
||||
|
||||
check: Procedure Expose p. imax jmax np. neighbors pl.
|
||||
/**********************************************************************
|
||||
* check if point (i,j) is free and note it as possible successor
|
||||
**********************************************************************/
|
||||
Parse Arg i,j
|
||||
If p.i.j='.' Then Do /* point is free */
|
||||
neighbors=neighbors+1 /* number of free neighbors */
|
||||
np.neighbors=i j /* note it as possible choice */
|
||||
End
|
||||
Return
|
||||
|
||||
advance: Procedure Expose p pos. np. p. c ii jj a. na pl. pos.
|
||||
/**********************************************************************
|
||||
* move to the next point of the current path
|
||||
**********************************************************************/
|
||||
Parse Arg ch,pii,pjj
|
||||
Parse Var np.ch ii jj
|
||||
p=p+1 /* position number */
|
||||
pos.p=ii jj /* note its coordinates */
|
||||
p.ii.jj=substr(c,p,1) /* mark the point as used */
|
||||
ai=pii+ii /* vertical border position */
|
||||
aj=pjj+jj /* horizontal border position */
|
||||
a.ai.aj=0 /* tear the border down */
|
||||
na=na+1 /* number of used positions */
|
||||
z=pl.0+1 /* add the point to the list */
|
||||
pl.z=ii jj /* of follow-up start pos. */
|
||||
pl.0=z
|
||||
Return
|
||||
|
||||
show: Procedure Expose id jd a. na
|
||||
/*********************************************************************
|
||||
* Show the resulting maze
|
||||
*********************************************************************/
|
||||
say 'mgg 6 18 4711'
|
||||
say 'show na='na
|
||||
Do i=1 To id
|
||||
ol=''
|
||||
Do j=1 To jd
|
||||
If i//2=1 Then Do /* odd lines */
|
||||
If a.i.j=1 Then Do /* border to be drawn */
|
||||
If j//2=0 Then
|
||||
ol=ol||'---' /* draw the border */
|
||||
Else
|
||||
ol=ol'+'
|
||||
End
|
||||
Else Do /* border was torn down */
|
||||
If j//2=0 Then
|
||||
ol=ol||' ' /* blanks instead of border */
|
||||
Else
|
||||
ol=ol||'+'
|
||||
End
|
||||
End
|
||||
Else Do /* even line */
|
||||
If a.i.j=1 Then Do
|
||||
If j//2=0 Then /* even column */
|
||||
ol=ol||' ' /* moving space */
|
||||
Else /* odd column */
|
||||
ol=ol||'|' /* draw the border */
|
||||
End
|
||||
Else /* border was torn down */
|
||||
ol=ol||' ' /* blank instead of border */
|
||||
End
|
||||
End
|
||||
Select
|
||||
When i=6 Then ol=overlay('A',ol,11)
|
||||
When i=8 Then ol=overlay('B',ol, 3)
|
||||
Otherwise Nop
|
||||
End
|
||||
Say ol format(i,2)
|
||||
End
|
||||
Return
|
||||
|
||||
select_next: Procedure Expose p. pl. imax jmax
|
||||
/*********************************************************************
|
||||
* look for a point to start the nnext path
|
||||
*********************************************************************/
|
||||
Do Until neighbors>0 /* loop until one is found */
|
||||
n=pl.0 /* number of points recorded */
|
||||
s=random(1,n) /* pick a random index */
|
||||
Parse Var pl.s is js /* its coordinates */
|
||||
neighbors=neighbors(is,js) /* count free neighbors */
|
||||
If neighbors=0 Then Do /* if there is none */
|
||||
pl.s=pl.n /* remove this point */
|
||||
pl.0=pl.0-1
|
||||
End
|
||||
End
|
||||
Return is js /* return the new start point*/
|
||||
|
|
@ -2,27 +2,24 @@ class Maze
|
|||
DIRECTIONS = [ [1, 0], [-1, 0], [0, 1], [0, -1] ]
|
||||
|
||||
def initialize(width, height)
|
||||
@width = width
|
||||
@height = height
|
||||
@width = width
|
||||
@height = height
|
||||
@start_x = rand(width)
|
||||
@start_y = 0
|
||||
@end_x = rand(width)
|
||||
@end_y = height - 1
|
||||
@end_x = rand(width)
|
||||
@end_y = height - 1
|
||||
|
||||
# Which walls do exist? Default to "true". Both arrays are
|
||||
# one element bigger than they need to be. For example, the
|
||||
# @vertical_walls[y][x] is true if there is a wall between
|
||||
# (x,y) and (x+1,y). The additional entry makes printing
|
||||
# easier.
|
||||
@vertical_walls = Array.new(height) { Array.new(width, true) }
|
||||
@horizontal_walls = Array.new(height) { Array.new(width, true) }
|
||||
# @vertical_walls[x][y] is true if there is a wall between
|
||||
# (x,y) and (x+1,y). The additional entry makes printing easier.
|
||||
@vertical_walls = Array.new(width) { Array.new(height, true) }
|
||||
@horizontal_walls = Array.new(width) { Array.new(height, true) }
|
||||
# Path for the solved maze.
|
||||
@path = Array.new(height) { Array.new(width) }
|
||||
@path = Array.new(width) { Array.new(height) }
|
||||
|
||||
# "Hack" to print the exit.
|
||||
@horizontal_walls[@end_y][@end_x] = false
|
||||
|
||||
reset_visiting_state
|
||||
@horizontal_walls[@end_x][@end_y] = false
|
||||
|
||||
# Generate the maze.
|
||||
generate
|
||||
|
|
@ -31,26 +28,16 @@ class Maze
|
|||
# Print a nice ASCII maze.
|
||||
def print
|
||||
# Special handling: print the top line.
|
||||
line = "+"
|
||||
for x in (0...@width)
|
||||
line.concat(x == @start_x ? " +" : "---+")
|
||||
end
|
||||
puts line
|
||||
puts @width.times.inject("+") {|str, x| str << (x == @start_x ? " +" : "---+")}
|
||||
|
||||
# For each cell, print the right and bottom wall, if it exists.
|
||||
for y in (0...@height)
|
||||
line = "|"
|
||||
for x in (0...@width)
|
||||
line.concat(@path[y][x] ? " o " : " ")
|
||||
line.concat(@vertical_walls[y][x] ? "|" : " ")
|
||||
@height.times do |y|
|
||||
line = @width.times.inject("|") do |str, x|
|
||||
str << (@path[x][y] ? " * " : " ") << (@vertical_walls[x][y] ? "|" : " ")
|
||||
end
|
||||
puts line
|
||||
|
||||
line = "+"
|
||||
for x in (0...@width)
|
||||
line.concat(@horizontal_walls[y][x] ? "---+" : " +")
|
||||
end
|
||||
puts line
|
||||
puts @width.times.inject("+") {|str, x| str << (@horizontal_walls[x][y] ? "---+" : " +")}
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -58,58 +45,47 @@ class Maze
|
|||
|
||||
# Reset the VISITED state of all cells.
|
||||
def reset_visiting_state
|
||||
@visited = Array.new(@height) { Array.new(@width) }
|
||||
end
|
||||
|
||||
# Check whether the given coordinate is within the valid range.
|
||||
def coordinate_valid?(x, y)
|
||||
(x >= 0) && (y >= 0) && (x < @width) && (y < @height)
|
||||
@visited = Array.new(@width) { Array.new(@height) }
|
||||
end
|
||||
|
||||
# Is the given coordinate valid and the cell not yet visited?
|
||||
def move_valid?(x, y)
|
||||
coordinate_valid?(x, y) && !@visited[y][x]
|
||||
(0...@width).cover?(x) && (0...@height).cover?(y) && !@visited[x][y]
|
||||
end
|
||||
|
||||
# Generate the maze.
|
||||
def generate
|
||||
generate_visit_cell @start_x, @start_y
|
||||
reset_visiting_state
|
||||
generate_visit_cell(@start_x, @start_y)
|
||||
end
|
||||
|
||||
# Depth-first maze generation.
|
||||
def generate_visit_cell(x, y)
|
||||
# Mark cell as visited.
|
||||
@visited[y][x] = true
|
||||
@visited[x][y] = true
|
||||
|
||||
# Randomly get coordinates of surrounding cells (may be outside
|
||||
# of the maze range, will be sorted out later).
|
||||
coordinates = []
|
||||
for dir in DIRECTIONS.shuffle
|
||||
coordinates << [ x + dir[0], y + dir[1] ]
|
||||
end
|
||||
coordinates = DIRECTIONS.shuffle.map { |dx, dy| [x + dx, y + dy] }
|
||||
|
||||
for new_x, new_y in coordinates
|
||||
next unless move_valid?(new_x, new_y)
|
||||
|
||||
# Recurse if it was possible to connect the current
|
||||
# and the the cell (this recursion is the "depth-first"
|
||||
# part).
|
||||
# Recurse if it was possible to connect the current and
|
||||
# the cell (this recursion is the "depth-first" part).
|
||||
connect_cells(x, y, new_x, new_y)
|
||||
generate_visit_cell new_x, new_y
|
||||
generate_visit_cell(new_x, new_y)
|
||||
end
|
||||
end
|
||||
|
||||
# Try to connect two cells. Returns whether it was valid to do so.
|
||||
def connect_cells(x1, y1, x2, y2)
|
||||
if x1 == x2
|
||||
# Cells must be above each other, remove a horizontal
|
||||
# wall.
|
||||
@horizontal_walls[ [y1, y2].min ][x1] = false
|
||||
# Cells must be above each other, remove a horizontal wall.
|
||||
@horizontal_walls[x1][ [y1, y2].min ] = false
|
||||
else
|
||||
# Cells must be next to each other, remove a vertical
|
||||
# wall.
|
||||
@vertical_walls[y1][ [x1, x2].min ] = false
|
||||
# Cells must be next to each other, remove a vertical wall.
|
||||
@vertical_walls[ [x1, x2].min ][y1] = false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue