137 lines
4.8 KiB
Plaintext
137 lines
4.8 KiB
Plaintext
Enumeration
|
|
;indexes for types of offsets from maze coordinates (x,y)
|
|
#visited ;used to index visited(x,y) in a given direction from current maze cell
|
|
#maze ;used to index maze() in a given direction from current maze cell
|
|
#wall ;used to index walls in maze() in a given direction from current maze cell
|
|
#numOffsets = #wall
|
|
;direction indexes
|
|
#dir_ID = 0 ;identity value, produces no changes
|
|
#firstDir
|
|
#dir_N = #firstDir
|
|
#dir_E
|
|
#dir_S
|
|
#dir_W
|
|
#numDirs = #dir_W
|
|
EndEnumeration
|
|
|
|
DataSection
|
|
;maze(x,y) offsets for visited, maze, & walls for each direction
|
|
Data.i 1, 1, 0, 0, 0, 0 ;ID
|
|
Data.i 1, 0, 0, -1, 0, 0 ;N
|
|
Data.i 2, 1, 1, 0, 1, 0 ;E
|
|
Data.i 1, 2, 0, 1, 0, 1 ;S
|
|
Data.i 0, 1, -1, 0, 0, 0 ;W
|
|
Data.i %00, %01, %10, %01, %10 ;wall values for ID, N, E, S, W
|
|
EndDataSection
|
|
|
|
#cellDWidth = 4
|
|
|
|
Structure mazeOutput
|
|
vWall.s
|
|
hWall.s
|
|
EndStructure
|
|
|
|
|
|
;setup reference values indexed by type and direction from current map cell
|
|
Global Dim offset.POINT(#numOffsets, #numDirs)
|
|
Define i, j
|
|
For i = 0 To #numDirs
|
|
For j = 0 To #numOffsets
|
|
Read.i offset(j, i)\x: Read.i offset(j, i)\y
|
|
Next
|
|
Next
|
|
|
|
Global Dim wallvalue(#numDirs)
|
|
For i = 0 To #numDirs: Read.i wallvalue(i): Next
|
|
|
|
|
|
Procedure makeDisplayMazeRow(Array mazeRow.mazeOutput(1), Array maze(2), y)
|
|
;modify mazeRow() to produce output of 2 strings showing the vertical walls above and horizontal walls across a given maze row
|
|
Protected x, vWall.s, hWall.s
|
|
Protected mazeWidth = ArraySize(maze(), 1), mazeHeight = ArraySize(maze(), 2)
|
|
|
|
vWall = "": hWall = ""
|
|
For x = 0 To mazeWidth
|
|
If maze(x, y) & wallvalue(#dir_N): vWall + "+ ": Else: vWall + "+---": EndIf
|
|
If maze(x, y) & wallvalue(#dir_W): hWall + " ": Else: hWall + "| ": EndIf
|
|
Next
|
|
mazeRow(0)\vWall = Left(vWall, mazeWidth * #cellDWidth + 1)
|
|
If y <> mazeHeight: mazeRow(0)\hWall = Left(hWall, mazeWidth * #cellDWidth + 1): Else: mazeRow(0)\hWall = "": EndIf
|
|
EndProcedure
|
|
|
|
Procedure displayMaze(Array maze(2))
|
|
Protected x, y, vWall.s, hWall.s, mazeHeight = ArraySize(maze(), 2)
|
|
Protected Dim mazeRow.mazeOutput(0)
|
|
|
|
For y = 0 To mazeHeight
|
|
makeDisplayMazeRow(mazeRow(), maze(), y)
|
|
PrintN(mazeRow(0)\vWall): PrintN(mazeRow(0)\hWall)
|
|
Next
|
|
EndProcedure
|
|
|
|
Procedure generateMaze(Array maze(2), mazeWidth, mazeHeight)
|
|
Dim maze(mazeWidth, mazeHeight) ;Each cell specifies walls present above and to the left of it,
|
|
;array includes an extra row and column for the right and bottom walls
|
|
Dim visited(mazeWidth + 1, mazeHeight + 1) ;Each cell represents a cell of the maze, an extra line of cells are included
|
|
;as padding around the representative cells for easy border detection
|
|
|
|
Protected i
|
|
;mark outside border as already visited (off limits)
|
|
For i = 0 To mazeWidth
|
|
visited(i + offset(#visited, #dir_N)\x, 0 + offset(#visited, #dir_N)\y) = #True
|
|
visited(i + offset(#visited, #dir_S)\x, mazeHeight - 1 + offset(#visited, #dir_S)\y) = #True
|
|
Next
|
|
For i = 0 To mazeHeight
|
|
visited(0 + offset(#visited, #dir_W)\x, i + offset(#visited, #dir_W)\y) = #True
|
|
visited(mazeWidth - 1 + offset(#visited, #dir_E)\x, i + offset(#visited, #dir_E)\y) = #True
|
|
Next
|
|
|
|
;generate maze
|
|
Protected x = Random(mazeWidth - 1), y = Random (mazeHeight - 1), cellCount, nextCell
|
|
visited(x + offset(#visited, #dir_ID)\x, y + offset(#visited, #dir_ID)\y) = #True
|
|
PrintN("Maze of size " + Str(mazeWidth) + " x " + Str(mazeHeight) + ", generation started at " + Str(x) + " x " + Str(y))
|
|
|
|
NewList stack.POINT()
|
|
Dim unvisited(#numDirs - #firstDir)
|
|
Repeat
|
|
cellCount = 0
|
|
For i = #firstDir To #numDirs
|
|
If Not visited(x + offset(#visited, i)\x, y + offset(#visited, i)\y)
|
|
unvisited(cellCount) = i: cellCount + 1
|
|
EndIf
|
|
Next
|
|
|
|
If cellCount
|
|
nextCell = unvisited(Random(cellCount - 1))
|
|
visited(x + offset(#visited, nextCell)\x, y + offset(#visited, nextCell)\y) = #True
|
|
maze(x + offset(#wall, nextCell)\x, y + offset(#wall, nextCell)\y) | wallvalue(nextCell)
|
|
|
|
If cellCount > 1
|
|
AddElement(stack())
|
|
stack()\x = x: stack()\y = y
|
|
EndIf
|
|
x + offset(#maze, nextCell)\x: y + offset(#maze, nextCell)\y
|
|
ElseIf ListSize(stack()) > 0
|
|
x = stack()\x: y = stack()\y
|
|
DeleteElement(stack())
|
|
Else
|
|
Break ;end maze generation
|
|
EndIf
|
|
ForEver
|
|
|
|
; ;mark random entry and exit point
|
|
; x = Random(mazeWidth - 1): y = Random(mazeHeight - 1)
|
|
; maze(x, 0) | wallvalue(#dir_N): maze(mazeWidth, y) | wallvalue(#dir_E)
|
|
ProcedureReturn
|
|
EndProcedure
|
|
|
|
If OpenConsole()
|
|
Dim maze(0, 0)
|
|
Define mazeWidth = Random(5) + 7: mazeHeight = Random(5) + 3
|
|
generateMaze(maze(), mazeWidth, mazeHeight)
|
|
displayMaze(maze())
|
|
|
|
Print(#CRLF$ + #CRLF$ + "Press ENTER to exit"): Input()
|
|
CloseConsole()
|
|
EndIf
|