Maze generation: Difference between revisions

Line 4,189:
 
=={{header|M2000 Interpreter}}==
===Random Generation===
{{trans|BASIC}}
For Next is not the same as basic. In M2000 always a loop perform once. Step converted to absolute value if start<>end. To go down we have to place start>end. If start=end then the value after the loop is equal to start+step and here step used as is (with no conversion to absolute value).
Line 4,259 ⟶ 4,260:
}
Maze
</lang>
 
===Depth-first search===
We use here the stack of values (it is heap based), which used for calls. Each module get the parent stack. A function has always a fresh stack. Using statement Stack New { } we use a new stack for that block, and at the exit the old stack return as current stack. Identifier [] is the stack as a stack object and work as command and do a swap of a fresh stack with the current one, so Array([]) leave current stack empty and return an array with all elements of stack.
!arraypointer in a module place a copy of items to current stack, so when we call NewForChoose(!entry) we pass to stack by value all elements of entry (has always two).
Subs have same scope with module, so we use local statement for local variables. Module's variables are local by default. A inner module has own scope, and can't see parent modules variables. Modules call other modules with same stack of values. Functions in expressions have own stack of variables. Modules ans subs can return values to stack of values.
A Push 10 write 10 to top of stack. A Read X read the top of stack to X. A Data 10 write to the end of stack, so a stack can be used as FIFO also.
A lambda function also has own scope, so we have to include w and h as closures, which are mutable copies of h and w.
 
 
<lang M2000 Interpreter>
Module Maze2 {
\\ depth-first search
Profiler
Form 80,50
let w=60, h=40
Double
\\center proportional text double size
Report 2, Format$("Maze {0}x{1}",w,h)
Normal
Refresh
Set Fast !
Dim maze$(1 to w+1, 1 to h+1)="#"
Include=Lambda w,h (a,b) ->a>=1 and a<=w and b>=1 and b<=h
pMaze=maze$()
Flush ' empty stack
if random(1,2)=1 then {
entry=(if(random(1,2)=1->2, w),Random(1, h/2)*2)
} else {
entry=(random(1,w/2)*2,If(Random(1,2)=1->2,h))
}
maze$(entry#val(0), entry#val(1))=" "
forchoose=(,)
do {
do {
NewForChoose(!entry)
status=len(forchoose)
if status>0 then {
status--
forchoose=forchoose#val(random(0,status))
if status>0 then push forchoose
OpenDoor(!Entry, !forchoose)
Rem : ShowMaze()
} else exit
entry=forchoose
} Always
if empty then exit
Read entry
} Always
ShowMaze()
Print timecount/1000
Sub NewForChoose(x,y)
Local x1=x-2, x2=x+2, y1=y-2, y2=y+2, arr=(,)
Stack New {
if include(x1,y) then if Maze$(x1,y)<>" " Then push (x1, y)
if include(x2,y) then if Maze$(x2,y)<>" " Then push (x2, y)
if include(x,y1) then if Maze$(x,y1)<>" " Then push (x, y1)
if include(x,y2) then if Maze$(x,y2)<>" " Then push (x, y2)
forchoose= Array([])
}
End Sub
Sub OpenDoor(x1,y1, x2,y2)
Local i
if x1=x2 then {
y1+=y2<=>y1
for i=y1 to y2 {maze$(x1, i)=" " }
} Else {
x1+=x2<=>x1
for i=x1 to x2 {maze$(i, y1)=" "}
}
End Sub
Sub ShowMaze()
Refresh 5000
cls ,4 ' split screen - preserve lines form 0 to 3
Local i, j
For j=1 to h+1 { Print @(10) : for i=1 to w+1 {Print maze$(i,j);}:Print}
Print
Refresh 100
End Sub
}
Maze2
</lang>
 
Anonymous user