Skip to content

Commit

Permalink
wilson's algorithm
Browse files Browse the repository at this point in the history
  • Loading branch information
jamis committed Jan 8, 2011
1 parent 81321c5 commit a629d9b
Show file tree
Hide file tree
Showing 4 changed files with 130 additions and 5 deletions.
18 changes: 15 additions & 3 deletions examples/maze.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@
<title>Maze Algorithms</title>
<script src="../lib/mersenne.js" type="text/javascript"></script>
<script src="../lib/maze.js" type="text/javascript"></script>
<script src="../lib/widget.js" type="text/javascript"></script>

<script src="../lib/aldous_broder.js" type="text/javascript"></script>
<script src="../lib/backtracker.js" type="text/javascript"></script>
<script src="../lib/division.js" type="text/javascript"></script>
<script src="../lib/eller.js" type="text/javascript"></script>
<script src="../lib/kruskal.js" type="text/javascript"></script>
<script src="../lib/prim.js" type="text/javascript"></script>
<script src="../lib/division.js" type="text/javascript"></script>
<script src="../lib/aldous_broder.js" type="text/javascript"></script>
<script src="../lib/widget.js" type="text/javascript"></script>
<script src="../lib/wilson.js" type="text/javascript"></script>

<style type="text/css">
* { font-family: sans-serif; }
Expand Down Expand Up @@ -38,6 +40,8 @@

.maze .grid div.in { background: #fff; }
.maze .grid div.f { background: #faa; }
.maze .grid div.cursor { background: #ffa; }

.maze .grid div.e { border-right: none; padding-right: 1px; }
.maze .grid div.w { border-left: none; padding-left: 1px; }
.maze .grid div.n { border-top: none; padding-top: 1px; }
Expand Down Expand Up @@ -102,5 +106,13 @@ <h1>Aldous-Broder Algorithm</h1>
<script type="text/javascript">Maze.createWidget("AldousBroder", 15, 15, { "class": "medium", id: "abroder_bigger", interval: 25 });</script>
<script type="text/javascript">Maze.createWidget("AldousBroder", 30, 30, { "class": "large", id: "abroder_biggest", interval: 10 });</script>
</div>
<hr />

<h1>Wilson's Algorithm</h1>
<div class="row">
<script type="text/javascript">Maze.createWidget("Wilson", 5, 5, { "class": "small" });</script>
<script type="text/javascript">Maze.createWidget("Wilson", 15, 15, { "class": "medium", id: "wilson_bigger", interval: 25 });</script>
<script type="text/javascript">Maze.createWidget("Wilson", 30, 30, { "class": "large", id: "wilson_biggest", interval: 10 });</script>
</div>
</body>
</html>
2 changes: 1 addition & 1 deletion src/maze.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ class Maze
carve: (x, y, dir) -> @grid.mark(x, y, dir)
uncarve: (x, y, dir) -> @grid.clear(x, y, dir)
isSet: (x, y, dir) -> @grid.isMarked(x, y, dir)
isBlank: (x, y, dir) -> @grid.at(x, y, dir) == 0
isBlank: (x, y) -> @grid.at(x, y) == 0

Maze.Direction =
N: 1
Expand Down
12 changes: 11 additions & 1 deletion src/widget.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ Maze.createWidget = (algorithm, width, height, options) ->
ACTIONS =
AldousBroder: (maze, x, y, classes) ->
if maze.isCurrent(x, y)
classes.push "f"
classes.push "cursor"
else if not maze.isBlank(x, y)
classes.push "in"
updateWalls maze, x, y, classes
Expand All @@ -40,6 +40,16 @@ Maze.createWidget = (algorithm, width, height, options) ->
RecursiveDivision: (maze, x, y, classes) ->
updateWalls(maze, x, y, classes)

Wilson: (maze, x, y, classes) ->
if maze.isCurrent(x, y)
classes.push "cursor"
updateWalls maze, x, y, classes
else if not maze.isBlank(x, y)
classes.push "in"
updateWalls maze, x, y, classes
else if maze.isVisited(x, y)
classes.push "f"

default: (maze, x, y, classes) ->
unless maze.isBlank(x, y)
classes.push "in"
Expand Down
103 changes: 103 additions & 0 deletions src/wilson.coffee
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
###
Author: Jamis Buck <jamis@jamisbuck.org>
License: Public domain, baby. Knock yourself out.
The original CoffeeScript sources are always available on GitHub:
http://github.com/jamis/csmazes
###

class Maze.Wilson extends Maze
IN: 0x10

constructor: (width, height, options) ->
super
@state = 0
@remaining = @width * @height
@visits = {}

isCurrent: (x, y) -> @x == x && @y == y
isVisited: (x, y) -> @visits["#{x}:#{y}"]?

addVisit: (x, y, dir) -> @visits["#{x}:#{y}"] = dir ? 0
exitTaken: (x, y) -> @visits["#{x}:#{y}"]

startStep: ->
x = @rand.nextInteger(@width)
y = @rand.nextInteger(@height)
@carve x, y, @IN
@callback this, x, y
@remaining--
@state = 1

startWalkStep: ->
@visits = {}

loop
@x = @rand.nextInteger(@width)
@y = @rand.nextInteger(@height)
if @isBlank(@x, @y)
@state = 2
@start = x: @x, y: @y
@addVisit @x, @y
@callback this, @x, @y
break

walkStep: ->
for direction in @randomDirections()
nx = @x + Maze.Direction.dx[direction]
ny = @y + Maze.Direction.dy[direction]

if @isValid(nx, ny)
[x, y, @x, @y] = [@x, @y, nx, ny]
@addVisit x, y, direction
@callback this, x, y
@callback this, nx, ny

unless @isBlank(nx, ny)
@x = @start.x
@y = @start.y
@state = 3

break

resetVisits: ->
for key, dir of @visits
[x, y] = key.split(":")
delete @visits[key]
@callback this, x, y

runStep: ->
if @remaining > 0
dir = @exitTaken(@x, @y)
nx = @x + Maze.Direction.dx[dir]
ny = @y + Maze.Direction.dy[dir]

unless @isBlank(nx, ny)
@resetVisits()
@state = 1

@carve @x, @y, dir
@carve nx, ny, Maze.Direction.opposite[dir]

[x, y, @x, @y] = [@x, @y, nx, ny]

if @state == 1
delete @x
delete @y

@callback this, x, y
@callback this, nx, ny

@remaining--

return @remaining > 0

step: ->
if @remaining > 0
switch @state
when 0 then @startStep()
when 1 then @startWalkStep()
when 2 then @walkStep()
when 3 then @runStep()

return @remaining > 0

0 comments on commit a629d9b

Please sign in to comment.