#rem Wilson's Algorithm - Maze From the book - Mazes for programmers - #end Import mojo Class cell Field x:Int,y:Int Field north:Bool,east:Bool Field south:Bool,west:Bool Field visited:Bool=False Method New(x:Int,y:Int) Self.x = x Self.y = y End Method End Class Class wilsonmaze Field width:Int,height:Int Field tilewidth:Float,tileheight:Float Field map:cell[][] Method New(mazewidth:Int,mazeheight:Int,sw:Int,sh:Int) Self.width = mazewidth Self.height = mazeheight map = New cell[width][] For Local i=0 Until width map[i] = New cell[height] Next For Local y=0 Until height For Local x=0 Until width map[x][y] = New cell Next Next tilewidth = Float(sw)/Float(mazewidth) tileheight = Float(sh)/Float(mazeheight) makewilsonmaze End Method ' ' This method creates the maze ' ' The Wilson method of making a maze works by ' using the random walk method to create ' paths on unvisited parts on the map. It starts ' at a random position and moves around. If ' its path overlaps then start over again. This until the ' path reaches a visited cell. Then carve the ' path out. ' ' Method makewilsonmaze() ' tool for adding/subtracting directions Local mx:Int[] = [0,1,0,-1] Local my:Int[] = [-1,0,1,0] ' one cell must be visited on the map Local x:Int=Rnd(0,width) Local y:Int=Rnd(0,height) map[x][y].visited = True ' temp cell location Local nx:Int,ny:Int ' starting state Local state:String="makepath" ' here we select the starting cell ' an unvisited cell. Local exitloop:Bool=False While exitloop = False ' create random pos x = Rnd(0,width) y = Rnd(0,height) ' if unvisited then exit loop and set temp ' position variables If map[x][y].visited = False exitloop = True nx = x ny = y End If Wend ' create stack list Local path:Stack<cell> = New Stack<cell> ' push first cell on the stack list path.Push(New cell(x,y)) ' if leftover = false then map is done Local leftover:Bool=True While leftover=True ' here we make the path If state="makepath" ' select a diagonal direction Local dir:Int dir=Rnd(0,4) ' if inside of the map If nx+mx[dir]>=0 And ny+my[dir]>=0 And nx+mx[dir]<width And ny+my[dir]<height ' set new position nx+=mx[dir] ny+=my[dir] Local go:Bool=True For Local i=0 Until path.Length ' if we already have that position then start over If path.Get(i).x = nx And path.Get(i).y = ny path = New Stack<cell> nx = x ny = y path.Push(New cell(x,y)) go = False Exit End If Next ' add new position to list and see ' if we have reached a visited cell. If go=True path.Push(New cell(nx,ny)) If map[nx][ny].visited = True ' if we reached a visited cell then ' carve out the path state = "carvepath" End If End If End If End If ' ' Here we carve the path we created If state="carvepath" ' for getting the direction between the ' data on the stack list Local dir:Int ' get the first cell from the stack ' list and mark it visited Local x1:Int,y1:Int x1 = path.Get(0).x y1 = path.Get(0).y map[x1][y1].visited = True ' loop through the stack starting with the ' second cell on the stack list For Local i=1 Until path.Length ' copy the cell from the stack ' list into vars and mark visited on map Local x2:Int=path.Get(i).x Local y2:Int=path.Get(i).y map[x2][y2].visited = True ' find the direction between previous ' and current cell from stack If x2=x1 And y2<y1 Then dir=0 If x2>x1 And y2=y1 Then dir=1 If x2=x1 And y2>y1 Then dir=2 If x2<x1 And y2=y1 Then dir=3 ' carve out the path Select dir Case 0'up map[x1][y1].north = True map[x2][y2].south = True Case 1'right map[x1][y1].east = True map[x2][y2].west = True Case 2'down map[x1][y1].south = True map[x2][y2].north = True Case 3'left map[x1][y1].west = True map[x2][y2].east = True End Select ' the last cell from the stack list ' becomes the first cell x1 = x2 y1 = y2 Next 'we no longer need the path list 'so erase it path = New Stack<cell> ' here we check if there are unvisited cells ' left leftover = False For Local i=0 Until height For Local ii=0 Until width If map[ii][i].visited = False Then leftover = True Exit End If Next Next ' if there are unvisited cells left ' then find a new cell to work with Local exitloop:Bool=False While exitloop = False And leftover = True Local x3:Int=Rnd(0,width) Local y3:Int=Rnd(0,height) If map[x3][y3].visited = False x = x3 y = y3 nx = x3 ny = y3 exitloop = True End If Wend ' put the new cell on the path path.Push(New cell(x,y)) ' back to making the path state = "makepath" End If Wend End Method ' ' Draw the maze ' Method draw() For Local y=0 Until height For Local x=0 Until width Local x1:Int=x*tilewidth Local y1:Int=y*tileheight SetColor 255,255,255 If map[x][y].north = False DrawLine x1,y1,x1+tilewidth,y1 End If If map[x][y].east = False DrawLine x1+tilewidth,y1,x1+tilewidth,y1+tileheight End If If map[x][y].south = False DrawLine x1,y1+tileheight,x1+tilewidth,y1+tileheight End If If map[x][y].west = False DrawLine x1,y1,x1,y1+tileheight End If Next Next End Method End Class Global maze:wilsonmaze Class MyGame Extends App Method OnCreate() SetUpdateRate(1) maze = New wilsonmaze(10,10,500,400) End Method Method OnUpdate() If MouseHit(MOUSE_LEFT) maze = New wilsonmaze(10,10,500,400) End If End Method Method OnRender() Cls 0,0,0 SetColor 255,255,255 maze.draw DrawText "Wilson Maze",0,480-40 DrawText "Press Mouse or Touch to create new maze",0,480-20 End Method End Class Function Main() New MyGame() End Function
Artificial intelligence/templates/examples/rts/rpg/strategy ect. in MonkeyX/CerberusX language. You can download the free version of MonkeyX from itch.io or Cerberus-x.com The Flash applets will stop working in around 2020.
Friday, April 7, 2017
Monkey-X - Maze - Wilsons Algorithm - code example
Subscribe to:
Post Comments (Atom)
No comments:
Post a Comment
Note: Only a member of this blog may post a comment.