<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" xml:lang="en-US">
  <title>the { buckblogs :here } - Home</title>
  <id>tag:weblog.jamisbuck.org,2011:mephisto/</id>
  <generator uri="http://mephistoblog.com" version="0.8.0">Mephisto Drax</generator>
  
  <link href="http://weblog.jamisbuck.org/" rel="alternate" type="text/html" />
  <updated>2011-09-01T16:45:28Z</updated>
  <atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/buckblog" /><feedburner:info uri="buckblog" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><link rel="license" type="text/html" href="http://creativecommons.org/licenses/by-nc-sa/2.0/" /><feedburner:browserFriendly>This is an XML content feed. It is intended to be viewed in a newsreader or syndicated to another site, subject to copyright and fair use.</feedburner:browserFriendly><entry xml:base="http://weblog.jamisbuck.org/">
    <author>
      <name>Jamis</name>
    </author>
    <id>tag:weblog.jamisbuck.org,2011-09-01:8980</id>
    <published>2011-09-01T16:43:00Z</published>
    <updated>2011-09-01T16:45:28Z</updated>
    <category term="Metablog" />
    <link href="http://weblog.jamisbuck.org/2011/9/1/shutting-down" rel="alternate" type="text/html" />
    <title>Winding down...</title>
<content type="html">
            &lt;p&gt;It’s been a good run, but my thrill for blogging has ebbed. Most of my online conversation occurs on &lt;a href="http://twitter.com/jamis"&gt;Twitter&lt;/a&gt; these days, and my Buckblog has definitely felt the lack of attention.&lt;/p&gt;


	&lt;p&gt;So, it is with some sadness that I announce the end of the Buckblog. Nothing is actually going away: the articles and existing comments will all remain where they are, but I won’t be posting any more, and no more comments will be accepted on any of them. It’ll all be “read-only” from here on out.&lt;/p&gt;


	&lt;p&gt;I have no doubt that in coming months and years I’ll get the itch to post something that won’t fit on Twitter. I’m not sure yet how I’ll work that. Maybe I’ll create a &lt;a href="http://www.tumblr.com"&gt;Tumblr&lt;/a&gt; account for the purpose. Or maybe I’ll just post static &lt;span class="caps"&gt;HTML&lt;/span&gt; pages and link them up via Twitter. I figure I’ll cross that bridge when I come to it.&lt;/p&gt;


	&lt;p&gt;At any rate, here’s to the future!&lt;/p&gt;
          &lt;img src="http://feeds.feedburner.com/~r/buckblog/~4/KcfUcfQ_JYE" height="1" width="1"/&gt;</content>  </entry>
  <entry xml:base="http://weblog.jamisbuck.org/">
    <author>
      <name>Jamis</name>
    </author>
    <id>tag:weblog.jamisbuck.org,2011-06-07:8964</id>
    <published>2011-06-07T21:32:00Z</published>
    <updated>2011-06-07T21:34:20Z</updated>
    <category term="Essays and Rants" />
    <category term="rails" />
    <category term="ruby" />
    <link href="http://weblog.jamisbuck.org/2011/6/7/sharing-the-inheritance-hierarchy" rel="alternate" type="text/html" />
    <title>Sharing the Inheritance Hierarchy</title>
<content type="html">
            &lt;p&gt;I’ve been working more closely with Ruby 1.9 and Rails 3 lately, and while in general it’s been smooth going, there was one particularly disappointing road bump today.&lt;/p&gt;


	&lt;p&gt;Consider the following code, from a Rails functional test:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;12&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="r"&gt;class&lt;/span&gt; &lt;span class="cl"&gt;SessionControllerTest&lt;/span&gt; &amp;lt; &lt;span class="co"&gt;ActionController&lt;/span&gt;::&lt;span class="co"&gt;TestCase&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  tests &lt;span class="co"&gt;SessionController&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="c"&gt;# ...&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;class&lt;/span&gt; &lt;span class="cl"&gt;LoginTest&lt;/span&gt; &amp;lt; &lt;span class="co"&gt;SessionControllerTest&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="c"&gt;# ...&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;class&lt;/span&gt; &lt;span class="cl"&gt;LogoutTest&lt;/span&gt; &amp;lt; &lt;span class="co"&gt;SessionControllerTest&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="c"&gt;# ...&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;This works great with ruby 1.8.7. The &lt;code&gt;tests&lt;/code&gt; call sets the SessionController as the controller under test, and the subclasses gain access to that via the “inheritable attributes” feature of ActiveSupport.&lt;/p&gt;


	&lt;p&gt;Sadly, this does &lt;em&gt;not&lt;/em&gt; work in ruby 1.9. Those tests have errors now, saying that the controller instance variable needs to be set in the setup method, because the inheritable attribute of the parent is no longer being inherited.&lt;/p&gt;


	&lt;p&gt;Some digging and experimenting helped me pare this down to a simpler example:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;require &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;minitest/unit&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;require &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;./config/application&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;class&lt;/span&gt; &lt;span class="cl"&gt;A&lt;/span&gt; &amp;lt; &lt;span class="co"&gt;MiniTest&lt;/span&gt;::&lt;span class="co"&gt;Unit&lt;/span&gt;::&lt;span class="co"&gt;TestCase&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  write_inheritable_attribute &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;hi&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class="i"&gt;5&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;p &lt;span class="co"&gt;A&lt;/span&gt;.read_inheritable_attribute(&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;hi&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;class&lt;/span&gt; &lt;span class="cl"&gt;B&lt;/span&gt; &amp;lt; &lt;span class="co"&gt;A&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;p &lt;span class="co"&gt;B&lt;/span&gt;.read_inheritable_attribute(&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;hi&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;If you run this example with ruby 1.9, it will print “5”, and then “nil”. And the most telling bit: if you comment out the superclass from A’s definition, the program will then print “5” and “5”. It was obviously something that MiniTest was doing.&lt;/p&gt;


	&lt;p&gt;Another 30 minutes later, I had my answer. MiniTest::Unit::TestCase was defining an &lt;code&gt;inherited&lt;/code&gt; callback method, to be invoked every time it was subclassed:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="r"&gt;def&lt;/span&gt; &lt;span class="pc"&gt;self&lt;/span&gt;.inherited klass &lt;span class="c"&gt;# :nodoc:&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="cv"&gt;@@test_suites&lt;/span&gt;[klass] = &lt;span class="pc"&gt;true&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;ActiveSupport, too, is &lt;a href="https://github.com/rails/rails/blob/3-0-stable/activesupport/lib/active_support/core_ext/class/inheritable_attributes.rb#L155-170"&gt;defining a version of the inherited method&lt;/a&gt;, monkeypatching the Class object directly so that subclasses can get a copy of their parent’s inheritable attribute collection. And because MiniTest is descended from Class, MiniTest’s version was overriding ActiveSupport’s version, causing the inheritable attributes to never be copied on inheritance.&lt;/p&gt;


	&lt;p&gt;Frustrating!&lt;/p&gt;


	&lt;p&gt;All it takes is the addition of one line&amp;mdash;just a single word!&amp;mdash;to “fix” MiniTest’s version:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="r"&gt;def&lt;/span&gt; &lt;span class="pc"&gt;self&lt;/span&gt;.inherited klass &lt;span class="c"&gt;# :nodoc:&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="cv"&gt;@@test_suites&lt;/span&gt;[klass] = &lt;span class="pc"&gt;true&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;super&lt;/span&gt;  &lt;span class="c"&gt;# &amp;lt;-- THIS RIGHT HERE&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;You can argue that ActiveSupport shouldn’t be monkeypatching system classes like that. Maybe, maybe not. The point is, it is, and it actually does it in a pretty “good neighbor” way. It saves a reference to any prior “inherited” definition, and calls it from within its version, chaining the calls together.&lt;/p&gt;


	&lt;p&gt;Sadly, MiniTest’s assumption that it would be the only consumer of the inherited hook in its ancestor chain totally kills ActiveSupport’s attempts at working together. I’ve had to resort to calling the &lt;code&gt;tests&lt;/code&gt; helper in each test subclass, explicitly. Not a huge deal, but I’d sure love to have back the two hours I spent debugging this.&lt;/p&gt;


	&lt;p&gt;The lesson? &lt;strong&gt;Always be a good neighbor&lt;/strong&gt;. Never assume you are the only kid on the playset. Call super when you override a method. Create a call chain when you replace a method &lt;em&gt;in situ&lt;/em&gt;. Think of the children!&lt;/p&gt;
          &lt;img src="http://feeds.feedburner.com/~r/buckblog/~4/XyH2ptt3NUE" height="1" width="1"/&gt;</content>  </entry>
  <entry xml:base="http://weblog.jamisbuck.org/">
    <author>
      <name>Jamis</name>
    </author>
    <id>tag:weblog.jamisbuck.org,2011-03-17:8899</id>
    <published>2011-03-17T15:26:00Z</published>
    <updated>2011-03-17T15:26:27Z</updated>
    <category term="Under the Hood" />
    <category term="mazes" />
    <category term="ruby" />
    <link href="http://weblog.jamisbuck.org/2011/3/17/maze-generation-more-weave-mazes" rel="alternate" type="text/html" />
    <title>Maze Generation: More weave mazes</title>
<summary type="html">&lt;p&gt;My &lt;a href="http://weblog.jamisbuck.org/2011/3/4/maze-generation-weave-mazes"&gt;previous post&lt;/a&gt; showed one way to create “weave mazes”, or mazes in which the passages weave over and under one another. The technique I showed was flexible, and could be implemented using several different maze algorithms, but it has (at least) one big drawback: it’s not predictable. You don’t know how many over/under crossings you’ll get until the maze has been generated, and for small mazes (5×5, for instance) you may very often get no crossings at all.&lt;/p&gt;


	&lt;p&gt;In the &lt;a href="http://weblog.jamisbuck.org/2011/3/4/maze-generation-weave-mazes#comments"&gt;comment thread&lt;/a&gt; for that post, Robin Houston described an alternate algorithm. Instead of building the crossings as you generate the maze, you do it as a preprocessing step. You scatter crossings (either at random, or deliberately) across the maze, and then generate the maze so that they connect correctly.&lt;/p&gt;


	&lt;p&gt;Sounds like it could be tricky, yeah? You’ve got all these &lt;em&gt;independent connections&lt;/em&gt;, like little &lt;em&gt;graphs&lt;/em&gt; floating around, all &lt;em&gt;disjoint&lt;/em&gt;... If only there were a way to generate a maze by &lt;em&gt;connecting disjoint trees&lt;/em&gt; into a single graph…&lt;/p&gt;


	&lt;p&gt;What’s that? Oh, right! &lt;a href="http://weblog.jamisbuck.org/2011/1/3/maze-generation-kruskal-s-algorithm"&gt;Kruskal’s algorithm&lt;/a&gt; does just that! Let’s take a look at how easy Kruskal’s makes this.&lt;/p&gt;</summary><content type="html">
            &lt;p&gt;My &lt;a href="http://weblog.jamisbuck.org/2011/3/4/maze-generation-weave-mazes"&gt;previous post&lt;/a&gt; showed one way to create “weave mazes”, or mazes in which the passages weave over and under one another. The technique I showed was flexible, and could be implemented using several different maze algorithms, but it has (at least) one big drawback: it’s not predictable. You don’t know how many over/under crossings you’ll get until the maze has been generated, and for small mazes (5×5, for instance) you may very often get no crossings at all.&lt;/p&gt;


	&lt;p&gt;In the &lt;a href="http://weblog.jamisbuck.org/2011/3/4/maze-generation-weave-mazes#comments"&gt;comment thread&lt;/a&gt; for that post, Robin Houston described an alternate algorithm. Instead of building the crossings as you generate the maze, you do it as a preprocessing step. You scatter crossings (either at random, or deliberately) across the maze, and then generate the maze so that they connect correctly.&lt;/p&gt;


	&lt;p&gt;Sounds like it could be tricky, yeah? You’ve got all these &lt;em&gt;independent connections&lt;/em&gt;, like little &lt;em&gt;graphs&lt;/em&gt; floating around, all &lt;em&gt;disjoint&lt;/em&gt;... If only there were a way to generate a maze by &lt;em&gt;connecting disjoint trees&lt;/em&gt; into a single graph…&lt;/p&gt;


	&lt;p&gt;What’s that? Oh, right! &lt;a href="http://weblog.jamisbuck.org/2011/1/3/maze-generation-kruskal-s-algorithm"&gt;Kruskal’s algorithm&lt;/a&gt; does just that! Let’s take a look at how easy Kruskal’s makes this.&lt;/p&gt;
&lt;h2&gt;Weave mazes via preprocessing&lt;/h2&gt;


	&lt;p&gt;I’m not going to review Kruskal’s algorithm here. If you don’t remember the details, I strongly recommend you read (or re-read) my article on &lt;a href="http://weblog.jamisbuck.org/2011/1/3/maze-generation-kruskal-s-algorithm"&gt;Kruskal’s algorithm&lt;/a&gt;. Don’t worry, I’ll wait.&lt;/p&gt;


	&lt;p&gt;Seriously, read it. The rest of this post won’t make much sense unless you understand how Kruskal’s works.&lt;/p&gt;


	&lt;p&gt;Got it? Alright, let’s proceed.&lt;/p&gt;


	&lt;p&gt;So, let’s assume you’ve got your blank grid, and you’ve set it up (just like Kruskal’s wants) so that each cell is the root of its own (one-node) tree. You’re about to generate the maze…&lt;/p&gt;


	&lt;p&gt;First, though, we do the preprocessing step: let’s scatter over/under crossings about the grid. We have a few constraints:&lt;/p&gt;


	&lt;ol&gt;
	&lt;li&gt;no crossing can be placed on the edge of the grid (because that would imply a passage moving outside the grid).&lt;/li&gt;
		&lt;li&gt;no crossing can be placed immediately adjacent to another crossing (this just simplifies things&amp;mdash;allowing adjacent crossings appears to introduce a surprising amount of complexity).&lt;/li&gt;
		&lt;li&gt;if the y-1 and y+1 (north and south) cells are already connected (in the same set), the crossing must not be allowed (because it would create a loop).&lt;/li&gt;
		&lt;li&gt;similarly, if the x-1 and x+1 (west and east) cells are already connected, the crossing must not be allowed.&lt;/li&gt;
	&lt;/ol&gt;


	&lt;p&gt;So, we place a crossing. We randomly decide whether the over-passage is north/south or east/west, and then carve the appropriate values into the grid.&lt;/p&gt;



&lt;table&gt;
&lt;tr&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;img src="http://jamisbuck.org/mazes/tiles/2-large.png" height="64" width="64" /&gt;&lt;/td&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;img src="http://jamisbuck.org/mazes/tiles/4-large.png" height="64" width="64" /&gt;&lt;td&gt;&lt;img src="http://jamisbuck.org/mazes/tiles/10-large.png" height="64" width="64" /&gt;&lt;td&gt;&lt;img src="http://jamisbuck.org/mazes/tiles/8-large.png" height="64" width="64" /&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;img src="http://jamisbuck.org/mazes/tiles/1-large.png" height="64" width="64" /&gt;&lt;/td&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;


	&lt;p&gt;However, since we’re dealing with Kruskal’s algorithm, we also need to update the connection sets, and then remove the relevant edges from the edge set. Because we don’t allow adjacent crossings, we don’t ever have to worry about things connecting directly to the cross-over cells (this is why allowing adjacent crossings gets complicated). So, to update the sets, we just join the north/south cells, and the east/west cells. And then we remove the edges connecting the cross-over cell, and its adjacent cells.&lt;/p&gt;


	&lt;p&gt;A lot of words, but not so much work, in practice!&lt;/p&gt;


	&lt;p&gt;Once you’ve set all the over/under crossings, you’re ready to actually generate the maze. And the &lt;em&gt;ahem&lt;/em&gt; amazing thing about Kruskal’s algorithm is, if you’ve correctly handled the edges and connections in the preprocessing step, you can run it without modification at this stage. The result will be a perfect, weave maze!&lt;/p&gt;


	&lt;p&gt;For your enjoyment, here are some demos to play with. Try the different settings to see how the output changes: particularly, notice how Kruskal’s using the naive “weave as you go” approach generates far fewer crossings (on average) than the approach described here.&lt;/p&gt;



&amp;lt;link href="http://jamisbuck.org/mazes/css/mazes.css" /&gt;
&lt;p&gt;&lt;strong&gt;Recursive Backtracker (in-process weave):&lt;/strong&gt;&lt;/p&gt;
&lt;div class="row"&gt;
&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Kruskal's (in-process weave):&lt;/strong&gt;&lt;/p&gt;
&lt;div class="row"&gt;
&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Kruskal's (pre-processed weave):&lt;/strong&gt;&lt;br /&gt;
Density: &amp;lt;select&gt;&amp;lt;option&gt;very&amp;lt;/option&gt;&amp;lt;option&gt;moderate&amp;lt;/option&gt;&amp;lt;option&gt;light&amp;lt;/option&gt;&amp;lt;option&gt;very light&amp;lt;/option&gt;&amp;lt;/select&gt;&lt;/p&gt;
&lt;div class="row"&gt;
&lt;/div&gt;


	&lt;h2&gt;Implementation&lt;/h2&gt;


	&lt;p&gt;Since the only thing that changes between this weave technique and the non-weave &lt;a&gt;Kruskal’s algorithm&lt;/a&gt; is the pre-processing step, I’m just going to go over the pre-processing step here.&lt;/p&gt;


	&lt;p&gt;You will probably also want to use a rendering method that allows you to unambiguously show the over/under crossings, such as the method using unicode characters that I described &lt;a href="http://weblog.jamisbuck.org/2011/3/4/maze-generation-weave-mazes"&gt;in my previous article&lt;/a&gt;.&lt;/p&gt;


	&lt;p&gt;Now, there are a lot of ways you could go about scattering crossings across the grid. For simplicity, I’m going to just iterate over each cell and randomly decide whether a crossing should be placed there. (This makes it easier to parameterize the process, allowing you to provide a “density” parameter to control how many crossings get placed.)&lt;/p&gt;


	&lt;p&gt;So, the first thing I do is just iterate over the possible cells:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="i"&gt;1&lt;/span&gt;.upto(height&lt;span class="i"&gt;-2&lt;/span&gt;) &lt;span class="r"&gt;do&lt;/span&gt; |cy|&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="i"&gt;1&lt;/span&gt;.upto(width&lt;span class="i"&gt;-2&lt;/span&gt;) &lt;span class="r"&gt;do&lt;/span&gt; |cx|&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="c"&gt;# ...&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;We start at 1 and go to n-2, because of the first constraint: crossings cannot be placed on the grid boundary.&lt;/p&gt;


	&lt;p&gt;Within the loop, I then use the “density” parameter (an integer from 0 to 100) to determine whether to skip this cell or not:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="r"&gt;next&lt;/span&gt; &lt;span class="r"&gt;unless&lt;/span&gt; rand(&lt;span class="i"&gt;100&lt;/span&gt;) &amp;lt; density&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;Next, I compute the coordinates of the adjacent cells, and then check to make sure the cell really is eligible for a crossing:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;nx, ny = cx, cy&lt;span class="i"&gt;-1&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;wx, wy = cx&lt;span class="i"&gt;-1&lt;/span&gt;, cy&lt;tt&gt;
&lt;/tt&gt;ex, ey = cx&lt;span class="i"&gt;+1&lt;/span&gt;, cy&lt;tt&gt;
&lt;/tt&gt;sx, sy = cx, cy&lt;span class="i"&gt;+1&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;next&lt;/span&gt; &lt;span class="r"&gt;if&lt;/span&gt; grid[cy][cx] != &lt;span class="i"&gt;0&lt;/span&gt; ||&lt;tt&gt;
&lt;/tt&gt;  sets[ny][nx].connected?(sets[sy][sx]) ||&lt;tt&gt;
&lt;/tt&gt;  sets[ey][ex].connected?(sets[wy][wx])&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;(Remember that &lt;code&gt;sets&lt;/code&gt; is a two-dimensional array of Tree objects that allow us to quickly query and join sets.)&lt;/p&gt;


	&lt;p&gt;If the grid at the chosen point is non-zero, then (by implication) we are adjacent to another crossing, and that isn’t allowed. And if the north and south sets are already connected, or the east and west sets, then we can’t allow a crossing here either (lest we introduce a loop into the graph).&lt;/p&gt;


	&lt;p&gt;Now that the sets have been updated, we can carve the new passages into the grid:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="r"&gt;if&lt;/span&gt; rand(&lt;span class="i"&gt;2&lt;/span&gt;) == &lt;span class="i"&gt;0&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  grid[cy][cx] = &lt;span class="co"&gt;E&lt;/span&gt;|&lt;span class="co"&gt;W&lt;/span&gt;|&lt;span class="co"&gt;U&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;else&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  grid[cy][cx] = &lt;span class="co"&gt;N&lt;/span&gt;|&lt;span class="co"&gt;S&lt;/span&gt;|&lt;span class="co"&gt;U&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;grid[ny][nx] |= &lt;span class="co"&gt;S&lt;/span&gt; &lt;span class="r"&gt;if&lt;/span&gt; (grid[ny][nx] &amp;amp; &lt;span class="co"&gt;U&lt;/span&gt;) == &lt;span class="i"&gt;0&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;grid[wy][wx] |= &lt;span class="co"&gt;E&lt;/span&gt; &lt;span class="r"&gt;if&lt;/span&gt; (grid[wy][wx] &amp;amp; &lt;span class="co"&gt;U&lt;/span&gt;) == &lt;span class="i"&gt;0&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;grid[ey][ex] |= &lt;span class="co"&gt;W&lt;/span&gt; &lt;span class="r"&gt;if&lt;/span&gt; (grid[ey][ex] &amp;amp; &lt;span class="co"&gt;U&lt;/span&gt;) == &lt;span class="i"&gt;0&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;grid[sy][sx] |= &lt;span class="co"&gt;N&lt;/span&gt; &lt;span class="r"&gt;if&lt;/span&gt; (grid[sy][sx] &amp;amp; &lt;span class="co"&gt;U&lt;/span&gt;) == &lt;span class="i"&gt;0&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;Recall that the U constant is just used to indicate the presence of an “under” passage. Thus, “E|W|U” means an east/west passage with an implied north/south passage beneath it, and “N|S|U” means a north/south passage with an implied east/west passage beneath it.&lt;/p&gt;


	&lt;p&gt;Further, we only carve on an adjacent passage if it doesn’t already have the “under” bit set. (If it does, then it is already a four-way crossing, and the passage we’re trying to add is already present, either explicitly or implicitly.)&lt;/p&gt;


	&lt;p&gt;Finally, we just need to update the edge list, to account for the edges we’ve now implicitly processed by adding this crossing:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;edges.delete_if &lt;span class="r"&gt;do&lt;/span&gt; |x, y, dir|&lt;tt&gt;
&lt;/tt&gt;  (x == cx &amp;amp;&amp;amp; y == cy) ||&lt;tt&gt;
&lt;/tt&gt;  (x == ex &amp;amp;&amp;amp; y == ey &amp;amp;&amp;amp; dir == &lt;span class="co"&gt;W&lt;/span&gt;) ||&lt;tt&gt;
&lt;/tt&gt;  (x == sx &amp;amp;&amp;amp; y == sy &amp;amp;&amp;amp; dir == &lt;span class="co"&gt;N&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;Remember that the edge list is just a collection of 3-tuples, with each tuple consisting of the x and y coordinates of a cell, and the direction that the edge exits that cell. It only contains edges that exit cells to the west, or the north (otherwise, we’d get duplicate edges: west from cell x is the same edge as east from cell x+1).&lt;/p&gt;


	&lt;p&gt;Thus, we’re deleting any edge connecting to the crossing cell itself, the west-facing edge from the eastern cell, and the north-facing edge from the southern cell.&lt;/p&gt;


	&lt;p&gt;When these loops finish, you’ll have a grid containing randomly-scattered crossings, ready for Kruskal’s algorithm to finish up.&lt;/p&gt;


	&lt;h2&gt;Conclusion&lt;/h2&gt;


	&lt;p&gt;This approach allows you to have weave mazes with a much higher density of crossings than the in-process approach. However, while the in-process approach can generate weave mazes with adjacent crossings, the algorithm described here cannot. I’ve spent some time trying to fix this flaw, but quickly found myself mired in complexity: I’m hoping brighter minds than mine can find an elegant solution to this!&lt;/p&gt;


	&lt;p&gt;Still, the biggest lesson I took away from this experience is this: it pays to know multiple different ways to solve a problem. I’m not a big fan of Kruskal’s algorithm in general (I don’t like the esthetic of the mazes it generates), but if I had never bothered to learn how Kruskal’s operates, I would never have been able to recognize it’s suitability for connecting the pre-processed crossings.&lt;/p&gt;


	&lt;p&gt;Stated more generally: the key to appearing smart is not knowing &lt;em&gt;everything&lt;/em&gt;, but rather knowing the &lt;em&gt;right&lt;/em&gt; thing.&lt;/p&gt;


	&lt;p&gt;Just because an algorithm may not be your favorite way of solving a problem most times, does not mean it won’t eventually be the &lt;em&gt;best&lt;/em&gt; way to solve a problem. You just wait: one of these days I’ll encounter a problem while writing a web app that one of these maze algorithms will be perfect for!&lt;/p&gt;


	&lt;p&gt;So, give this algorithm a try, if for no other reason than it’s good exercise! And we all know exercise is good for you. ;) My own implementation is given below:&lt;/p&gt;



&amp;lt;noscript&gt;&lt;a href="https://gist.github.com/856138"&gt;kruskals-weave.rb&lt;/a&gt; on gist.github.com&amp;lt;/noscript&gt;


	&lt;p&gt;Enjoy!&lt;/p&gt;
          &lt;img src="http://feeds.feedburner.com/~r/buckblog/~4/32N367U-Syo" height="1" width="1"/&gt;</content>  </entry>
  <entry xml:base="http://weblog.jamisbuck.org/">
    <author>
      <name>Jamis</name>
    </author>
    <id>tag:weblog.jamisbuck.org,2011-03-04:8852</id>
    <published>2011-03-04T14:48:00Z</published>
    <updated>2011-03-10T13:47:23Z</updated>
    <category term="Under the Hood" />
    <category term="mazes" />
    <category term="ruby" />
    <link href="http://weblog.jamisbuck.org/2011/3/4/maze-generation-weave-mazes" rel="alternate" type="text/html" />
    <title>Maze Generation: Weave mazes</title>
<summary type="html">&lt;p&gt;This is a “weave” maze:&lt;/p&gt;


&lt;div&gt;&lt;img src="http://jamisbuck.org/images/maze7.png" height="204" alt="weave maze" width="204"&gt;&lt;/div&gt;

	&lt;p&gt;The name does not describe any specific algorithm for generating mazes, but rather simply identifies the class of maze, where some passages weave over or under other passages. It’s a type of 3D maze but it can be rendered nicely in 2D, as long as you conform to the following rules:&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;Passages may only move under or over each other when they are perpendicular to each other.&lt;/li&gt;
		&lt;li&gt;A passage may not terminate (dead-end) either under or over another passage.&lt;/li&gt;
		&lt;li&gt;Passages may not change direction either over or under another passage.&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;If you break any of those rules, you’ll wind up hidden or ambiguous corridors when viewed as a 2D projection, and we don’t want that!&lt;/p&gt;


	&lt;p&gt;Let’s take a closer look at how the algorithms need to be adapted to support weave mazes.&lt;/p&gt;</summary><content type="html">
            &lt;p&gt;This is a “weave” maze:&lt;/p&gt;


&lt;div&gt;&lt;img src="http://jamisbuck.org/images/maze7.png" height="204" alt="weave maze" width="204"&gt;&lt;/div&gt;

	&lt;p&gt;The name does not describe any specific algorithm for generating mazes, but rather simply identifies the class of maze, where some passages weave over or under other passages. It’s a type of 3D maze but it can be rendered nicely in 2D, as long as you conform to the following rules:&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;Passages may only move under or over each other when they are perpendicular to each other.&lt;/li&gt;
		&lt;li&gt;A passage may not terminate (dead-end) either under or over another passage.&lt;/li&gt;
		&lt;li&gt;Passages may not change direction either over or under another passage.&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;If you break any of those rules, you’ll wind up hidden or ambiguous corridors when viewed as a 2D projection, and we don’t want that!&lt;/p&gt;


	&lt;p&gt;Let’s take a closer look at how the algorithms need to be adapted to support weave mazes.&lt;/p&gt;
&lt;h2&gt;Weave maze adaptation&lt;/h2&gt;


	&lt;p&gt;The key change that needs to be made is that when you determine whether a particular move is valid, you no longer get to ignore a cell if it has already been visited. If the candidate cell has been visited, you need to compare it against the three rules above, and rule it out &lt;em&gt;only&lt;/em&gt; if it fails one of them.&lt;/p&gt;


	&lt;p&gt;Consider the following scenario:&lt;/p&gt;


&lt;table class="maze"&gt;
&lt;tr&gt;&lt;td class="n e w"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="s w"&gt;&lt;/td&gt;&lt;td class="n e"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n e w h"&gt;&lt;/td&gt;&lt;td class="e w"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="s w"&gt;&lt;/td&gt;&lt;td class="s e"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;

	&lt;p&gt;The highlighted cell is the current one, the one we need to move from. In a non-weave scenario this would be a deadend, and we’d be done with that cell, but with weaves to consider, we can’t be so hasty.&lt;/p&gt;


	&lt;p&gt;So, we slow down and check it out. North? No, because the northern passage is not perpendicular to that direction. We’d wind up with an ambiguous passage if we tried to weave in that direction.&lt;/p&gt;


	&lt;p&gt;West? Nope, that takes us out of bounds.&lt;/p&gt;


	&lt;p&gt;South? Again, nope, because the passage south is not perpendicular to that direction.&lt;/p&gt;


	&lt;p&gt;Alright, so: east, our last and best hope? Ah, this one passes the perpendicular test&amp;mdash;the corridor to the east moves north-to-south! The space on the far side of the corridor is empty, so we wouldn’t have to worry about deadending underneath the corridor, so again, we’re okay. And because we plan to just tunnel straight east, there’s no danger of changing direction mid-tunnel, either.&lt;/p&gt;


	&lt;p&gt;We have a winner! At this point, the algorithm would indicate that the passage moves under the north-south passage, and joins to the next cell over.&lt;/p&gt;


	&lt;p&gt;That’s really the gist of it. As long as the base maze algorithm can be adapted to accomodate this logic, you can implement weave mazes with it.&lt;/p&gt;


	&lt;p&gt;Try playing with this interactive demo (using the Growing Tree algorithm) to see how this approach to weave mazes works with different settings:&lt;/p&gt;



&amp;lt;link href="http://jamisbuck.org/mazes/css/mazes.css" /&gt;
&lt;p&gt;
Cell selection method: &amp;lt;select&gt;
&amp;lt;option&gt;Newest (Recursive Backtracker)&amp;lt;/option&gt;
&amp;lt;option&gt;Random (Prim's)&amp;lt;/option&gt;
&amp;lt;option&gt;Newest/Random, 75/25 split&amp;lt;/option&gt;
&amp;lt;option&gt;Newest/Random, 50/50 split&amp;lt;/option&gt;
&amp;lt;option&gt;Newest/Random, 25/75 split&amp;lt;/option&gt;
&amp;lt;option&gt;Oldest&amp;lt;/option&gt;
&amp;lt;option&gt;Middle&amp;lt;/option&gt;
&amp;lt;option&gt;Newest/Oldest, 50/50 split&amp;lt;/option&gt;
&amp;lt;option&gt;Oldest/Random, 50/50 split&amp;lt;/option&gt;
&amp;lt;/select&gt;
&lt;/p&gt;
&lt;div class="row"&gt;
&lt;/div&gt;


	&lt;p&gt;Now, let’s look at an implementation.&lt;/p&gt;


	&lt;h2&gt;Implementation&lt;/h2&gt;


	&lt;p&gt;I’m going to be sticking with the &lt;a href="http://weblog.jamisbuck.org/2011/1/27/maze-generation-growing-tree-algorithm"&gt;Growing Tree algorithm&lt;/a&gt;, but it ought to be possible to adapt most of the &lt;a href="http://weblog.jamisbuck.org/2011/2/7/maze-generation-algorithm-recap"&gt;maze algorithms I covered&lt;/a&gt; to generate weave mazes.&lt;/p&gt;


	&lt;p&gt;(I’ve not tried it with all of them, and some, like &lt;a href="http://weblog.jamisbuck.org/2010/12/29/maze-generation-eller-s-algorithm"&gt;Eller’s&lt;/a&gt;, might be difficult to adapt. Also, while you can probably adapt &lt;a href="http://weblog.jamisbuck.org/2011/1/17/maze-generation-aldous-broder-algorithm"&gt;Aldous-Broder&lt;/a&gt; or &lt;a href="http://weblog.jamisbuck.org/2011/1/20/maze-generation-wilson-s-algorithm"&gt;Wilson’s&lt;/a&gt; for this, you’ll probably no longer get a uniform spanning tree out of them, if that’s important to you.)&lt;/p&gt;


	&lt;p&gt;Now, what follows is just one way to implement a weave maze. I’m kind of a bit-twiddler at heart, so that’s the approach I took. If a passage moves under the cell, I just set another bit on that cell, indicating the presence of the tunnel.&lt;/p&gt;


	&lt;p&gt;The Growing Tree algorithm itself is exactly as I &lt;a href="http://weblog.jamisbuck.org/2011/1/27/maze-generation-growing-tree-algorithm"&gt;described before&lt;/a&gt;, but we add an else clause to check whether a weave is possible, and if so, to perform it:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;nx, ny = x + &lt;span class="co"&gt;DX&lt;/span&gt;[dir], y + &lt;span class="co"&gt;DY&lt;/span&gt;[dir]&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;if&lt;/span&gt; nx.between?(&lt;span class="i"&gt;0&lt;/span&gt;, width&lt;span class="i"&gt;-1&lt;/span&gt;) &amp;amp;&amp;amp; ny.between?(&lt;span class="i"&gt;0&lt;/span&gt;, height&lt;span class="i"&gt;-1&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;if&lt;/span&gt; grid[ny][nx] == &lt;span class="i"&gt;0&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="c"&gt;# here's the original case, carving into an unvisited neighbor&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="c"&gt;# ...&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;elsif&lt;/span&gt; can_weave?(grid, dir, nx, ny)&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="c"&gt;# here's where we perform the weave&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="c"&gt;# ...&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;The “can_weave?” helper method is straight-forward. It just checks whether it is allowable to move from the candidate cell (nx, ny) in the given direction. (Remember that nx and ny are the coordinates of the cell we want to tunnel under!)&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="r"&gt;def&lt;/span&gt; &lt;span class="fu"&gt;can_weave?&lt;/span&gt;(grid, dir, x, y)&lt;tt&gt;
&lt;/tt&gt;  cell = grid[y][x]&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;return&lt;/span&gt; &lt;span class="pc"&gt;false&lt;/span&gt; &lt;span class="r"&gt;unless&lt;/span&gt; cell == &lt;span class="co"&gt;CROSS&lt;/span&gt;[dir]&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  nx, ny = x + &lt;span class="co"&gt;DX&lt;/span&gt;[dir], y + &lt;span class="co"&gt;DY&lt;/span&gt;[dir]&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;return&lt;/span&gt; ny.between?(&lt;span class="i"&gt;0&lt;/span&gt;, grid.length&lt;span class="i"&gt;-1&lt;/span&gt;) &amp;amp;&amp;amp; nx.between?(&lt;span class="i"&gt;0&lt;/span&gt;, grid[ny].length&lt;span class="i"&gt;-1&lt;/span&gt;) &amp;amp;&amp;amp; grid[ny][nx] == &lt;span class="i"&gt;0&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;The first check we do is to see if the passages in the indicated cell are perpendicular to the given direction. (That’s what the &lt;span class="caps"&gt;CROSS&lt;/span&gt; variable is all about; it’s just a hash returning which directions are perpendicular to one another.)&lt;/p&gt;


	&lt;p&gt;If that test passes, we now need to make sure that the next cell over in that direction is both in bounds, and unvisited. If both of those conditions hold, then we have a winner.&lt;/p&gt;


	&lt;p&gt;Once we know that a cell can be weaved under, it’s time to perform the weave. At it’s simplest, this is just a matter of setting the “under” bit, and then setting the necessary directions on the origin and target cells:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;grid[y][x] |= dir&lt;tt&gt;
&lt;/tt&gt;grid[ny][nx] |= &lt;span class="co"&gt;U&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;nx, ny = nx + &lt;span class="co"&gt;DX&lt;/span&gt;[dir], ny + &lt;span class="co"&gt;DY&lt;/span&gt;[dir]&lt;tt&gt;
&lt;/tt&gt;grid[ny][nx] |= &lt;span class="co"&gt;OPP&lt;/span&gt;[dir]&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;To clarify: (x,y) is the originating cell, the one we’ve carving away from. The first (nx,ny) is the cell we want to carve under. Then, we compute the target cell, on the far side of the cell we’re carving under; that’s the cell we’re going to end up at, after tunneling.&lt;/p&gt;


	&lt;p&gt;That’s really all there is to it. However, for variation, it’s nice to sometimes carve &lt;em&gt;over&lt;/em&gt; the cell, instead of under it. This gives you some more interesting patterns, and it’s really not too hard to do. You just need to look at the cell to see which direction the passage is currently heading, and then change it so that the passage is rotated 90 degrees. Then you set the “under” bit. This has the effect of making the perpendicular passage (the one you’re adding) be the “over” passage, and the original passage the “under” passage.&lt;/p&gt;


	&lt;p&gt;Here it is in code:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="r"&gt;if&lt;/span&gt; rand(&lt;span class="i"&gt;2&lt;/span&gt;) == &lt;span class="i"&gt;0&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  grid[ny][nx] |= &lt;span class="co"&gt;U&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;elsif&lt;/span&gt; (grid[ny][nx] &amp;amp; &lt;span class="co"&gt;N&lt;/span&gt;) != &lt;span class="i"&gt;0&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  grid[ny][nx] = &lt;span class="co"&gt;E&lt;/span&gt;|&lt;span class="co"&gt;W&lt;/span&gt;|&lt;span class="co"&gt;U&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;else&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  grid[ny][nx] = &lt;span class="co"&gt;N&lt;/span&gt;|&lt;span class="co"&gt;S&lt;/span&gt;|&lt;span class="co"&gt;U&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;That’s really all there is to it! However, there’s one more interesting bit we need to consider, and that is how to render your weave maze.&lt;/p&gt;


	&lt;h2&gt;Rendering&lt;/h2&gt;


	&lt;p&gt;The display methods I used in my previous maze posts are not sufficient for rendering weave mazes. This is because there is no space between passages, the walls have no width. This makes it impossible to see whether a passage terminates at a given wall, or moves under it.&lt;/p&gt;


	&lt;p&gt;To work around this, my program uses unicode characters from the box drawing range (x2500&amp;mdash;x257F). The result is still not ideal (in larger mazes, the eye tends to lose track of what is a passage and what is the space between passages), but it lets us do a quick-and-dirty display.&lt;/p&gt;


	&lt;p&gt;For best results, we treat each cell as a 3×2 &lt;span class="caps"&gt;ASCII&lt;/span&gt; grid. For example, a N/S/E/W intersection would be rendered like this:&lt;/p&gt;


	&lt;p&gt;&amp;#x2518; &amp;#x2514;&lt;br /&gt;
&amp;#x2510; &amp;#x250C;&lt;/p&gt;


	&lt;p&gt;First, I define the set of tiles for each possible cell configuration:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;12&lt;tt&gt;
&lt;/tt&gt;13&lt;tt&gt;
&lt;/tt&gt;14&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;15&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;16&lt;tt&gt;
&lt;/tt&gt;17&lt;tt&gt;
&lt;/tt&gt;18&lt;tt&gt;
&lt;/tt&gt;19&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;20&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;21&lt;tt&gt;
&lt;/tt&gt;22&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="co"&gt;EW&lt;/span&gt;, &lt;span class="co"&gt;NS&lt;/span&gt;, &lt;span class="co"&gt;SE&lt;/span&gt;, &lt;span class="co"&gt;SW&lt;/span&gt;, &lt;span class="co"&gt;NE&lt;/span&gt;, &lt;span class="co"&gt;NW&lt;/span&gt; = [&lt;span class="i"&gt;0x80&lt;/span&gt;, &lt;span class="i"&gt;0x82&lt;/span&gt;, &lt;span class="i"&gt;0x8C&lt;/span&gt;, &lt;span class="i"&gt;0x90&lt;/span&gt;, &lt;span class="i"&gt;0x94&lt;/span&gt;, &lt;span class="i"&gt;0x98&lt;/span&gt;].map { |v| &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="ch"&gt;\xE2&lt;/span&gt;&lt;span class="ch"&gt;\x94&lt;/span&gt;&lt;span class="il"&gt;&lt;span class="dl"&gt;#{&lt;/span&gt;v.chr&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; }&lt;tt&gt;
&lt;/tt&gt;&lt;span class="co"&gt;NSE&lt;/span&gt;, &lt;span class="co"&gt;NSW&lt;/span&gt;, &lt;span class="co"&gt;EWS&lt;/span&gt;, &lt;span class="co"&gt;EWN&lt;/span&gt;     = [&lt;span class="i"&gt;0x9C&lt;/span&gt;, &lt;span class="i"&gt;0xA4&lt;/span&gt;, &lt;span class="i"&gt;0xAC&lt;/span&gt;, &lt;span class="i"&gt;0xB4&lt;/span&gt;].map { |v| &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="ch"&gt;\xE2&lt;/span&gt;&lt;span class="ch"&gt;\x94&lt;/span&gt;&lt;span class="il"&gt;&lt;span class="dl"&gt;#{&lt;/span&gt;v.chr&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; }&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="co"&gt;TILES&lt;/span&gt; = {&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="co"&gt;N&lt;/span&gt;       =&amp;gt; [&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="il"&gt;&lt;span class="dl"&gt;#{&lt;/span&gt;&lt;span class="co"&gt;NS&lt;/span&gt;&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="k"&gt; &lt;/span&gt;&lt;span class="il"&gt;&lt;span class="dl"&gt;#{&lt;/span&gt;&lt;span class="co"&gt;NS&lt;/span&gt;&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="il"&gt;&lt;span class="dl"&gt;#{&lt;/span&gt;&lt;span class="co"&gt;NE&lt;/span&gt;&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="il"&gt;&lt;span class="dl"&gt;#{&lt;/span&gt;&lt;span class="co"&gt;EW&lt;/span&gt;&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="il"&gt;&lt;span class="dl"&gt;#{&lt;/span&gt;&lt;span class="co"&gt;NW&lt;/span&gt;&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;],&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="co"&gt;S&lt;/span&gt;       =&amp;gt; [&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="il"&gt;&lt;span class="dl"&gt;#{&lt;/span&gt;&lt;span class="co"&gt;SE&lt;/span&gt;&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="il"&gt;&lt;span class="dl"&gt;#{&lt;/span&gt;&lt;span class="co"&gt;EW&lt;/span&gt;&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="il"&gt;&lt;span class="dl"&gt;#{&lt;/span&gt;&lt;span class="co"&gt;SW&lt;/span&gt;&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="il"&gt;&lt;span class="dl"&gt;#{&lt;/span&gt;&lt;span class="co"&gt;NS&lt;/span&gt;&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="k"&gt; &lt;/span&gt;&lt;span class="il"&gt;&lt;span class="dl"&gt;#{&lt;/span&gt;&lt;span class="co"&gt;NS&lt;/span&gt;&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;],&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="co"&gt;E&lt;/span&gt;       =&amp;gt; [&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="il"&gt;&lt;span class="dl"&gt;#{&lt;/span&gt;&lt;span class="co"&gt;SE&lt;/span&gt;&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="il"&gt;&lt;span class="dl"&gt;#{&lt;/span&gt;&lt;span class="co"&gt;EW&lt;/span&gt;&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="il"&gt;&lt;span class="dl"&gt;#{&lt;/span&gt;&lt;span class="co"&gt;EW&lt;/span&gt;&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="il"&gt;&lt;span class="dl"&gt;#{&lt;/span&gt;&lt;span class="co"&gt;NE&lt;/span&gt;&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="il"&gt;&lt;span class="dl"&gt;#{&lt;/span&gt;&lt;span class="co"&gt;EW&lt;/span&gt;&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="il"&gt;&lt;span class="dl"&gt;#{&lt;/span&gt;&lt;span class="co"&gt;EW&lt;/span&gt;&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;],&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="co"&gt;W&lt;/span&gt;       =&amp;gt; [&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="il"&gt;&lt;span class="dl"&gt;#{&lt;/span&gt;&lt;span class="co"&gt;EW&lt;/span&gt;&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="il"&gt;&lt;span class="dl"&gt;#{&lt;/span&gt;&lt;span class="co"&gt;EW&lt;/span&gt;&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="il"&gt;&lt;span class="dl"&gt;#{&lt;/span&gt;&lt;span class="co"&gt;SW&lt;/span&gt;&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="il"&gt;&lt;span class="dl"&gt;#{&lt;/span&gt;&lt;span class="co"&gt;EW&lt;/span&gt;&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="il"&gt;&lt;span class="dl"&gt;#{&lt;/span&gt;&lt;span class="co"&gt;EW&lt;/span&gt;&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="il"&gt;&lt;span class="dl"&gt;#{&lt;/span&gt;&lt;span class="co"&gt;NW&lt;/span&gt;&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;],&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="co"&gt;N&lt;/span&gt;|&lt;span class="co"&gt;S&lt;/span&gt;     =&amp;gt; [&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="il"&gt;&lt;span class="dl"&gt;#{&lt;/span&gt;&lt;span class="co"&gt;NS&lt;/span&gt;&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="k"&gt; &lt;/span&gt;&lt;span class="il"&gt;&lt;span class="dl"&gt;#{&lt;/span&gt;&lt;span class="co"&gt;NS&lt;/span&gt;&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="il"&gt;&lt;span class="dl"&gt;#{&lt;/span&gt;&lt;span class="co"&gt;NS&lt;/span&gt;&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="k"&gt; &lt;/span&gt;&lt;span class="il"&gt;&lt;span class="dl"&gt;#{&lt;/span&gt;&lt;span class="co"&gt;NS&lt;/span&gt;&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;],&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="co"&gt;N&lt;/span&gt;|&lt;span class="co"&gt;W&lt;/span&gt;     =&amp;gt; [&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="il"&gt;&lt;span class="dl"&gt;#{&lt;/span&gt;&lt;span class="co"&gt;NW&lt;/span&gt;&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="k"&gt; &lt;/span&gt;&lt;span class="il"&gt;&lt;span class="dl"&gt;#{&lt;/span&gt;&lt;span class="co"&gt;NS&lt;/span&gt;&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="il"&gt;&lt;span class="dl"&gt;#{&lt;/span&gt;&lt;span class="co"&gt;EW&lt;/span&gt;&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="il"&gt;&lt;span class="dl"&gt;#{&lt;/span&gt;&lt;span class="co"&gt;EW&lt;/span&gt;&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="il"&gt;&lt;span class="dl"&gt;#{&lt;/span&gt;&lt;span class="co"&gt;NW&lt;/span&gt;&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;],&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="co"&gt;N&lt;/span&gt;|&lt;span class="co"&gt;E&lt;/span&gt;     =&amp;gt; [&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="il"&gt;&lt;span class="dl"&gt;#{&lt;/span&gt;&lt;span class="co"&gt;NS&lt;/span&gt;&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="k"&gt; &lt;/span&gt;&lt;span class="il"&gt;&lt;span class="dl"&gt;#{&lt;/span&gt;&lt;span class="co"&gt;NE&lt;/span&gt;&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="il"&gt;&lt;span class="dl"&gt;#{&lt;/span&gt;&lt;span class="co"&gt;NE&lt;/span&gt;&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="il"&gt;&lt;span class="dl"&gt;#{&lt;/span&gt;&lt;span class="co"&gt;EW&lt;/span&gt;&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="il"&gt;&lt;span class="dl"&gt;#{&lt;/span&gt;&lt;span class="co"&gt;EW&lt;/span&gt;&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;],&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="co"&gt;S&lt;/span&gt;|&lt;span class="co"&gt;W&lt;/span&gt;     =&amp;gt; [&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="il"&gt;&lt;span class="dl"&gt;#{&lt;/span&gt;&lt;span class="co"&gt;EW&lt;/span&gt;&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="il"&gt;&lt;span class="dl"&gt;#{&lt;/span&gt;&lt;span class="co"&gt;EW&lt;/span&gt;&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="il"&gt;&lt;span class="dl"&gt;#{&lt;/span&gt;&lt;span class="co"&gt;SW&lt;/span&gt;&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="il"&gt;&lt;span class="dl"&gt;#{&lt;/span&gt;&lt;span class="co"&gt;SW&lt;/span&gt;&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="k"&gt; &lt;/span&gt;&lt;span class="il"&gt;&lt;span class="dl"&gt;#{&lt;/span&gt;&lt;span class="co"&gt;NS&lt;/span&gt;&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;],&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="co"&gt;S&lt;/span&gt;|&lt;span class="co"&gt;E&lt;/span&gt;     =&amp;gt; [&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="il"&gt;&lt;span class="dl"&gt;#{&lt;/span&gt;&lt;span class="co"&gt;SE&lt;/span&gt;&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="il"&gt;&lt;span class="dl"&gt;#{&lt;/span&gt;&lt;span class="co"&gt;EW&lt;/span&gt;&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="il"&gt;&lt;span class="dl"&gt;#{&lt;/span&gt;&lt;span class="co"&gt;EW&lt;/span&gt;&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="il"&gt;&lt;span class="dl"&gt;#{&lt;/span&gt;&lt;span class="co"&gt;NS&lt;/span&gt;&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="k"&gt; &lt;/span&gt;&lt;span class="il"&gt;&lt;span class="dl"&gt;#{&lt;/span&gt;&lt;span class="co"&gt;SE&lt;/span&gt;&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;],&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="co"&gt;E&lt;/span&gt;|&lt;span class="co"&gt;W&lt;/span&gt;     =&amp;gt; [&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="il"&gt;&lt;span class="dl"&gt;#{&lt;/span&gt;&lt;span class="co"&gt;EW&lt;/span&gt;&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="il"&gt;&lt;span class="dl"&gt;#{&lt;/span&gt;&lt;span class="co"&gt;EW&lt;/span&gt;&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="il"&gt;&lt;span class="dl"&gt;#{&lt;/span&gt;&lt;span class="co"&gt;EW&lt;/span&gt;&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="il"&gt;&lt;span class="dl"&gt;#{&lt;/span&gt;&lt;span class="co"&gt;EW&lt;/span&gt;&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="il"&gt;&lt;span class="dl"&gt;#{&lt;/span&gt;&lt;span class="co"&gt;EW&lt;/span&gt;&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="il"&gt;&lt;span class="dl"&gt;#{&lt;/span&gt;&lt;span class="co"&gt;EW&lt;/span&gt;&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;],&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="co"&gt;N&lt;/span&gt;|&lt;span class="co"&gt;S&lt;/span&gt;|&lt;span class="co"&gt;E&lt;/span&gt;   =&amp;gt; [&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="il"&gt;&lt;span class="dl"&gt;#{&lt;/span&gt;&lt;span class="co"&gt;NS&lt;/span&gt;&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="k"&gt; &lt;/span&gt;&lt;span class="il"&gt;&lt;span class="dl"&gt;#{&lt;/span&gt;&lt;span class="co"&gt;NE&lt;/span&gt;&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="il"&gt;&lt;span class="dl"&gt;#{&lt;/span&gt;&lt;span class="co"&gt;NS&lt;/span&gt;&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="k"&gt; &lt;/span&gt;&lt;span class="il"&gt;&lt;span class="dl"&gt;#{&lt;/span&gt;&lt;span class="co"&gt;SE&lt;/span&gt;&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;],&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="co"&gt;N&lt;/span&gt;|&lt;span class="co"&gt;S&lt;/span&gt;|&lt;span class="co"&gt;W&lt;/span&gt;   =&amp;gt; [&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="il"&gt;&lt;span class="dl"&gt;#{&lt;/span&gt;&lt;span class="co"&gt;NW&lt;/span&gt;&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="k"&gt; &lt;/span&gt;&lt;span class="il"&gt;&lt;span class="dl"&gt;#{&lt;/span&gt;&lt;span class="co"&gt;NS&lt;/span&gt;&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="il"&gt;&lt;span class="dl"&gt;#{&lt;/span&gt;&lt;span class="co"&gt;SW&lt;/span&gt;&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="k"&gt; &lt;/span&gt;&lt;span class="il"&gt;&lt;span class="dl"&gt;#{&lt;/span&gt;&lt;span class="co"&gt;NS&lt;/span&gt;&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;],&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="co"&gt;E&lt;/span&gt;|&lt;span class="co"&gt;W&lt;/span&gt;|&lt;span class="co"&gt;N&lt;/span&gt;   =&amp;gt; [&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="il"&gt;&lt;span class="dl"&gt;#{&lt;/span&gt;&lt;span class="co"&gt;NW&lt;/span&gt;&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="k"&gt; &lt;/span&gt;&lt;span class="il"&gt;&lt;span class="dl"&gt;#{&lt;/span&gt;&lt;span class="co"&gt;NE&lt;/span&gt;&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="il"&gt;&lt;span class="dl"&gt;#{&lt;/span&gt;&lt;span class="co"&gt;EW&lt;/span&gt;&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="il"&gt;&lt;span class="dl"&gt;#{&lt;/span&gt;&lt;span class="co"&gt;EW&lt;/span&gt;&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="il"&gt;&lt;span class="dl"&gt;#{&lt;/span&gt;&lt;span class="co"&gt;EW&lt;/span&gt;&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;],&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="co"&gt;E&lt;/span&gt;|&lt;span class="co"&gt;W&lt;/span&gt;|&lt;span class="co"&gt;S&lt;/span&gt;   =&amp;gt; [&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="il"&gt;&lt;span class="dl"&gt;#{&lt;/span&gt;&lt;span class="co"&gt;EW&lt;/span&gt;&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="il"&gt;&lt;span class="dl"&gt;#{&lt;/span&gt;&lt;span class="co"&gt;EW&lt;/span&gt;&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="il"&gt;&lt;span class="dl"&gt;#{&lt;/span&gt;&lt;span class="co"&gt;EW&lt;/span&gt;&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="il"&gt;&lt;span class="dl"&gt;#{&lt;/span&gt;&lt;span class="co"&gt;SW&lt;/span&gt;&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="k"&gt; &lt;/span&gt;&lt;span class="il"&gt;&lt;span class="dl"&gt;#{&lt;/span&gt;&lt;span class="co"&gt;SE&lt;/span&gt;&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;],&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="co"&gt;N&lt;/span&gt;|&lt;span class="co"&gt;S&lt;/span&gt;|&lt;span class="co"&gt;E&lt;/span&gt;|&lt;span class="co"&gt;W&lt;/span&gt; =&amp;gt; [&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="il"&gt;&lt;span class="dl"&gt;#{&lt;/span&gt;&lt;span class="co"&gt;NW&lt;/span&gt;&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="k"&gt; &lt;/span&gt;&lt;span class="il"&gt;&lt;span class="dl"&gt;#{&lt;/span&gt;&lt;span class="co"&gt;NE&lt;/span&gt;&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="il"&gt;&lt;span class="dl"&gt;#{&lt;/span&gt;&lt;span class="co"&gt;SW&lt;/span&gt;&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="k"&gt; &lt;/span&gt;&lt;span class="il"&gt;&lt;span class="dl"&gt;#{&lt;/span&gt;&lt;span class="co"&gt;SE&lt;/span&gt;&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;],&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="co"&gt;N&lt;/span&gt;|&lt;span class="co"&gt;S&lt;/span&gt;|&lt;span class="co"&gt;U&lt;/span&gt;   =&amp;gt; [&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="il"&gt;&lt;span class="dl"&gt;#{&lt;/span&gt;&lt;span class="co"&gt;NSW&lt;/span&gt;&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="k"&gt; &lt;/span&gt;&lt;span class="il"&gt;&lt;span class="dl"&gt;#{&lt;/span&gt;&lt;span class="co"&gt;NSE&lt;/span&gt;&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="il"&gt;&lt;span class="dl"&gt;#{&lt;/span&gt;&lt;span class="co"&gt;NSW&lt;/span&gt;&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="k"&gt; &lt;/span&gt;&lt;span class="il"&gt;&lt;span class="dl"&gt;#{&lt;/span&gt;&lt;span class="co"&gt;NSE&lt;/span&gt;&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;],&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="co"&gt;E&lt;/span&gt;|&lt;span class="co"&gt;W&lt;/span&gt;|&lt;span class="co"&gt;U&lt;/span&gt;   =&amp;gt; [&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="il"&gt;&lt;span class="dl"&gt;#{&lt;/span&gt;&lt;span class="co"&gt;EWN&lt;/span&gt;&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="il"&gt;&lt;span class="dl"&gt;#{&lt;/span&gt;&lt;span class="co"&gt;EW&lt;/span&gt;&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="il"&gt;&lt;span class="dl"&gt;#{&lt;/span&gt;&lt;span class="co"&gt;EWN&lt;/span&gt;&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="il"&gt;&lt;span class="dl"&gt;#{&lt;/span&gt;&lt;span class="co"&gt;EWS&lt;/span&gt;&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="il"&gt;&lt;span class="dl"&gt;#{&lt;/span&gt;&lt;span class="co"&gt;EW&lt;/span&gt;&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="il"&gt;&lt;span class="dl"&gt;#{&lt;/span&gt;&lt;span class="co"&gt;EWS&lt;/span&gt;&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;]&lt;tt&gt;
&lt;/tt&gt;}&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;Displaying the maze then becomes very straight-forward, just interating twice for each row so that each line of each tile gets drawn:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;height.times &lt;span class="r"&gt;do&lt;/span&gt; |y| &lt;tt&gt;
&lt;/tt&gt;  &lt;span class="i"&gt;2&lt;/span&gt;.times &lt;span class="r"&gt;do&lt;/span&gt; |row|&lt;tt&gt;
&lt;/tt&gt;    width.times { |x| print &lt;span class="co"&gt;TILES&lt;/span&gt;[grid[y][x]][row] }&lt;tt&gt;
&lt;/tt&gt;    puts&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;end&lt;/span&gt; &lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;The result:&lt;/p&gt;


&lt;pre&gt;
┌───────┐┌────┐┌───────┐┌────┐
│ ┌───┐ ││ ┌┐ ││ ┌───┐ ││ ┌┐ │
│ │┌──┴─┴┤ ├┘ ││ └───┤ ├┴─┴┘ │
│ ││ ┌┬─┬┤ ├──┘└─────┤ ├┬─┬──┘
│ └┘ ││ ││ │┌───────┐│ ││ │┌─┐
└────┘│ ││ │└──┐ ┌──┘│ ││ ││ │
┌─────┤ ├┘ │┌──┤ ├───┘ └┴─┴┘ │
│ ┌───┤ ├──┘│ ┌┤ ├──────┬─┬┐ │
│ └───┤ ├───┤ ├┘ │┌────┐│ ││ │
└─────┤ ├┐ ┌┤ ├──┘└──┐ ││ ││ │
┌─────┴─┴┘ ││ └─────┐│ ││ ││ │
│ ┌───┬─┬──┘└──┐ ┌──┘│ ││ │└─┘
│ └───┴─┴──┐┌──┤ ├──┐│ └┤ ├──┐
└─────┬─┬──┘│ ┌┤ ├┐ │└──┤ ├┐ │
┌────┐│ └───┴─┴┘ └┴─┴──┐│ ││ │
│ ┌┐ │└─────┬─┬┐ ┌┬─┬──┘│ ││ │
│ ││ └──────┘ ││ ││ └───┘ ││ │
│ │└──────────┘└─┘└───────┘│ │
│ └────────────────────────┘ │
└────────────────────────────┘
&lt;/pre&gt;

	&lt;h2&gt;Conclusion&lt;/h2&gt;


	&lt;p&gt;Weave mazes can produce some very pretty designs, but randomly generated ones are not generally practical for most applications. Because the generator can “escape” from many dead-end situations by moving over or under a neighbor, the mazes tend to have very long passages (with a high “river” factor, meaning they can be quite windy), and very few junctions. Solving such a maze is not really very difficult.&lt;/p&gt;


	&lt;p&gt;That said, they can look quite impressive! In general, I’ve found that algorithms that encourage longer passages produce the best weave mazes. Algorithms like &lt;a href="http://weblog.jamisbuck.org/2011/1/3/maze-generation-kruskal-s-algorithm"&gt;Kruskal’s&lt;/a&gt; and &lt;a href="http://weblog.jamisbuck.org/2011/1/10/maze-generation-prim-s-algorithm"&gt;Prim’s&lt;/a&gt; (which produce mazes with lots of short deadends) will have a harder time meeting the “passages must not deadend over or under another passage” criterion, and as a result will have fewer over/under passages.&lt;/p&gt;


	&lt;p&gt;Give weave mazes a shot in the language of your choice, and share what you come up with! My own implementation, in Ruby, is given below.&lt;/p&gt;



&amp;lt;noscript&gt;&lt;a href="https://gist.github.com/854218"&gt;weave.rb&lt;/a&gt; on gist.github.com&amp;lt;/noscript&gt;


	&lt;p&gt;Enjoy!&lt;/p&gt;
          &lt;img src="http://feeds.feedburner.com/~r/buckblog/~4/cOtXz-s158M" height="1" width="1"/&gt;</content>  </entry>
  <entry xml:base="http://weblog.jamisbuck.org/">
    <author>
      <name>Jamis</name>
    </author>
    <id>tag:weblog.jamisbuck.org,2011-02-28:8836</id>
    <published>2011-02-28T16:34:00Z</published>
    <updated>2011-02-28T16:35:22Z</updated>
    <category term="Under the Hood" />
    <category term="mazes" />
    <link href="http://weblog.jamisbuck.org/2011/2/28/weave-mazes-your-take" rel="alternate" type="text/html" />
    <title>Weave Mazes: Your Take?</title>
<content type="html">
            &lt;p&gt;Later this week I’m going to post an article about how you might implement “weave mazes”, like this one:&lt;/p&gt;


&lt;div&gt;&lt;img src="http://jamisbuck.org/images/maze7.png" height="204" alt="weave maze" width="204"&gt;&lt;/div&gt;

	&lt;p&gt;This is a maze where some of the passages “weave” over or under other passages. It’s a type of 3D maze, but very constrained (mostly for esthetic reasons):&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;Passages may only move under or over each other when they are perpendicular to each other.&lt;/li&gt;
		&lt;li&gt;A passage may not terminate (dead-end) either under or over another passage.&lt;/li&gt;
		&lt;li&gt;Passages may not change direction either over or under another passage.&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;Before I post my implementation, though, I wanted to get you thinking: how would &lt;em&gt;you&lt;/em&gt; implement a weave maze?&lt;/p&gt;
          &lt;img src="http://feeds.feedburner.com/~r/buckblog/~4/kEDERwzl6b4" height="1" width="1"/&gt;</content>  </entry>
  <entry xml:base="http://weblog.jamisbuck.org/">
    <author>
      <name>Jamis</name>
    </author>
    <id>tag:weblog.jamisbuck.org,2011-02-22:8803</id>
    <published>2011-02-22T14:44:00Z</published>
    <updated>2011-02-22T14:48:54Z</updated>
    <category term="Projects" />
    <category term="programming" />
    <category term="survey" />
    <link href="http://weblog.jamisbuck.org/2011/2/22/programming-language-survey-results" rel="alternate" type="text/html" />
    <title>Programming Language Survey Results</title>
<content type="html">
            &lt;p&gt;A couple of weeks ago (already!) I asked two simple questions of my Twitter followers: what are (up to) four programming languages that you know and love, and what are (up to) four programming languages that you would like to learn?&lt;/p&gt;


	&lt;p&gt;Around the time I asked the question, I had almost 4200 followers on Twitter. Of those 4200, 38 responded. That’s &lt;em&gt;almost&lt;/em&gt; one percent, and it is most definitely &lt;em&gt;not&lt;/em&gt; a large enough sample from which to draw meaningful conclusions! Even if all 4200 of my twitter followers responded, it would still have been a strongly biased survey: most people following me on twitter are (or were) Ruby/Rails programmers, or found me through some other Ruby/Rails programmer. Asking this group what their favorite languages are is &lt;em&gt;bound&lt;/em&gt; to have some strong biases.&lt;/p&gt;


	&lt;p&gt;And, sure enough, the top ten “know-and-love” languages among the 38 respondents were:&lt;/p&gt;


	&lt;ol&gt;
	&lt;li&gt;ruby (32)&lt;/li&gt;
		&lt;li&gt;javascript (25)&lt;/li&gt;
		&lt;li&gt;java (13)&lt;/li&gt;
		&lt;li&gt;python (9)&lt;/li&gt;
		&lt;li&gt;c (9)&lt;/li&gt;
		&lt;li&gt;c# (7)&lt;/li&gt;
		&lt;li&gt;php (6)&lt;/li&gt;
		&lt;li&gt;c++ (5)&lt;/li&gt;
		&lt;li&gt;perl (4)&lt;/li&gt;
		&lt;li&gt;lisp (4)&lt;/li&gt;
	&lt;/ol&gt;


	&lt;p&gt;Compare that to the top ten “want-to-learn” languages:&lt;/p&gt;


	&lt;ol&gt;
	&lt;li&gt;erlang (22)&lt;/li&gt;
		&lt;li&gt;objective-c (12)&lt;/li&gt;
		&lt;li&gt;clojure (12)&lt;/li&gt;
		&lt;li&gt;python (12)&lt;/li&gt;
		&lt;li&gt;lisp (10)&lt;/li&gt;
		&lt;li&gt;haskell (9)&lt;/li&gt;
		&lt;li&gt;scala (9)&lt;/li&gt;
		&lt;li&gt;lua (5)&lt;/li&gt;
		&lt;li&gt;r (5)&lt;/li&gt;
		&lt;li&gt;c (5)&lt;/li&gt;
	&lt;/ol&gt;


	&lt;p&gt;Ruby didn’t even make that list! (It actually came in at #11.)&lt;/p&gt;


	&lt;p&gt;So, what I’m trying to say is, the data is strongly slanted toward the preferences of Rails programmers who enjoy Ruby as a programming language. Still, there are some interesting tidbits to find here. I am definitely not a statistician, but here are four points that emerged that I found enlightening:&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;Every respondent included at least one object-oriented language among their know-and-love’s.&lt;/strong&gt; For most people, that was Ruby, but Java, Python, C++, Objective-C, and others were mentioned, too. 17 people mentioned two object-oriented languages, and 17 more mentioned three. Three people gave all four of their know-and-love languages as object-oriented languages. What do I take away from this? All we really know is that object-oriented languages are apparently widely taught/learned among my twitter followers. No surprise there!&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;Only 8 respondents indicated that they know-and-love a functional language.&lt;/strong&gt; Six people gave only a single functional language among their four know-and-loves, one more gave two, and one more gave three. Is this because people don’t love functional languages? Definitely not. There is simply not enough data to draw any conclusions about why this number is smaller than OO languages, but it does make you wonder, doesn’t it? Are programmers with predominantly OO backgrounds intimidated by functional paradigms? As you’ll see in the next question, it’s definitely not a lack of interest!&lt;/p&gt;


	&lt;p&gt;The four functional languages that people gave as “know-and-love” are:&lt;/p&gt;


	&lt;ol&gt;
	&lt;li&gt;lisp (4)&lt;/li&gt;
		&lt;li&gt;haskell (3)&lt;/li&gt;
		&lt;li&gt;erlang (3)&lt;/li&gt;
		&lt;li&gt;clojure (1)&lt;/li&gt;
	&lt;/ol&gt;


	&lt;p&gt;Now, compare that with the next point:&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;33 of the 38 respondents wanted to learn at least one functional language.&lt;/strong&gt; That’s almost 87%, versus only 21% that already knew a functional language. There is some serious curiosity there; people know OO, but want to learn functional. And what functional languages are people curious about?&lt;/p&gt;


	&lt;ol&gt;
	&lt;li&gt;erlang (22)&lt;/li&gt;
		&lt;li&gt;clojure (12)&lt;/li&gt;
		&lt;li&gt;lisp (10)&lt;/li&gt;
		&lt;li&gt;haskell (9)&lt;/li&gt;
		&lt;li&gt;scheme (2)&lt;/li&gt;
		&lt;li&gt;ocaml (2)&lt;/li&gt;
		&lt;li&gt;ml (1)&lt;/li&gt;
		&lt;li&gt;f# (1)&lt;/li&gt;
	&lt;/ol&gt;


	&lt;p&gt;Erlang, far and away, is the one most people are curious about. Interesting!&lt;/p&gt;


	&lt;p&gt;The last point: &lt;strong&gt;32 respondents included at least one object-oriented language in their want-to-learn list.&lt;/strong&gt; 12 people wanted to learn one OO language, 16 wanted to learn two, and four people wanted to learn three OO languages. Which languages?&lt;/p&gt;


	&lt;ol&gt;
	&lt;li&gt;python (12)&lt;/li&gt;
		&lt;li&gt;objective-c (12)&lt;/li&gt;
		&lt;li&gt;scala (9)&lt;/li&gt;
		&lt;li&gt;lua (5)&lt;/li&gt;
		&lt;li&gt;ruby (4)&lt;/li&gt;
		&lt;li&gt;c# (3)&lt;/li&gt;
		&lt;li&gt;smalltalk (3)&lt;/li&gt;
		&lt;li&gt;java (2)&lt;/li&gt;
		&lt;li&gt;javascript (2)&lt;/li&gt;
		&lt;li&gt;c++ (1)&lt;/li&gt;
		&lt;li&gt;io (1)&lt;/li&gt;
		&lt;li&gt;coffeescript (1)&lt;/li&gt;
		&lt;li&gt;groovy (1)&lt;/li&gt;
	&lt;/ol&gt;


	&lt;p&gt;Curiouser and curiouser! I love that a predominantly Ruby-centric group wants Python and Objective-C above all others. ObjC actually makes sense to me, even aside from the popularity of iOS as a platform. ObjC has many similarities to Ruby, and is a great language for Rubyists. Python, though…I love that it’s tied for #1. It shows a certain open-mindedness in the Ruby community, which gives me warm fuzzies.&lt;/p&gt;


	&lt;p&gt;Anyway, I’ll say it again: there really wasn’t a large enough sample set to draw meaningful conclusions here. But it’s still fun to look at seeming patterns in the data. Hopefull you’ve found something useful here, too!&lt;/p&gt;
          &lt;img src="http://feeds.feedburner.com/~r/buckblog/~4/TFCmmcRGQsY" height="1" width="1"/&gt;</content>  </entry>
  <entry xml:base="http://weblog.jamisbuck.org/">
    <author>
      <name>Jamis</name>
    </author>
    <id>tag:weblog.jamisbuck.org,2011-02-19:8794</id>
    <published>2011-02-19T18:48:00Z</published>
    <updated>2011-02-19T18:50:44Z</updated>
    <category term="Announcements" />
    <category term="Projects" />
    <category term="mazes" />
    <category term="ruby" />
    <category term="tilings" />
    <link href="http://weblog.jamisbuck.org/2011/2/19/kaleidoscope" rel="alternate" type="text/html" />
    <title>Kaleidoscope</title>
<summary type="html">&lt;p&gt;It’s funny how knowledge leads to knowledge. You start digging deeper into one thing, and discover threads leading off into related fields. I began by researching maze algorithms, decided I wanted to see what mazes in more complex tesselations would look like, and after one thing or anouther found myself learning about &lt;a href="http://en.wikipedia.org/wiki/Wythoff_construction"&gt;Wythoff constructions&lt;/a&gt;.&lt;/p&gt;


	&lt;p&gt;The result is &lt;a href="http://github.com/jamis/kaleidoscope"&gt;Kaleidoscope&lt;/a&gt;, a library for generating uniform tilings using Wythoff constructions.&lt;/p&gt;


	&lt;pre&gt;&lt;code&gt;gem install kaleidoscope&lt;/code&gt;&lt;/pre&gt;


	&lt;p&gt;A uniform tiling is a tesselation of a plane using regular polygons (with a few other constraints that I won’t go into here). What this means is that, in essense, you give Kaleidoscope a few input parameters, and it hands you a bunch of regular polygons.&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;require &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;kaleidoscope&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;pattern = &lt;span class="co"&gt;Kaleidoscope&lt;/span&gt;::&lt;span class="co"&gt;Pattern&lt;/span&gt;.new(&lt;span class="i"&gt;6&lt;/span&gt;, &lt;span class="i"&gt;3&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;pattern.generate! &lt;span class="r"&gt;do&lt;/span&gt; |point|&lt;tt&gt;
&lt;/tt&gt;  point.x * point.x + point.y * point.y &amp;lt; &lt;span class="i"&gt;10&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;pattern.polygons.each &lt;span class="r"&gt;do&lt;/span&gt; |polygon|&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="c"&gt;# ...&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;The polygons are generated around the origin of the plane, within a region you specify via the block to the generate! method. Once done, you can translate and scale the polygons to wherever you like, for rendering purposes. Kaleidoscope will even include basic tricoloring data for the polygons, to make it easy to decorate your pattern.&lt;/p&gt;


	&lt;p&gt;Some obligatory pretty pictures:&lt;/p&gt;</summary><content type="html">
            &lt;p&gt;It’s funny how knowledge leads to knowledge. You start digging deeper into one thing, and discover threads leading off into related fields. I began by researching maze algorithms, decided I wanted to see what mazes in more complex tesselations would look like, and after one thing or anouther found myself learning about &lt;a href="http://en.wikipedia.org/wiki/Wythoff_construction"&gt;Wythoff constructions&lt;/a&gt;.&lt;/p&gt;


	&lt;p&gt;The result is &lt;a href="http://github.com/jamis/kaleidoscope"&gt;Kaleidoscope&lt;/a&gt;, a library for generating uniform tilings using Wythoff constructions.&lt;/p&gt;


	&lt;pre&gt;&lt;code&gt;gem install kaleidoscope&lt;/code&gt;&lt;/pre&gt;


	&lt;p&gt;A uniform tiling is a tesselation of a plane using regular polygons (with a few other constraints that I won’t go into here). What this means is that, in essense, you give Kaleidoscope a few input parameters, and it hands you a bunch of regular polygons.&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;require &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;kaleidoscope&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;pattern = &lt;span class="co"&gt;Kaleidoscope&lt;/span&gt;::&lt;span class="co"&gt;Pattern&lt;/span&gt;.new(&lt;span class="i"&gt;6&lt;/span&gt;, &lt;span class="i"&gt;3&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;pattern.generate! &lt;span class="r"&gt;do&lt;/span&gt; |point|&lt;tt&gt;
&lt;/tt&gt;  point.x * point.x + point.y * point.y &amp;lt; &lt;span class="i"&gt;10&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;pattern.polygons.each &lt;span class="r"&gt;do&lt;/span&gt; |polygon|&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="c"&gt;# ...&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;The polygons are generated around the origin of the plane, within a region you specify via the block to the generate! method. Once done, you can translate and scale the polygons to wherever you like, for rendering purposes. Kaleidoscope will even include basic tricoloring data for the polygons, to make it easy to decorate your pattern.&lt;/p&gt;


	&lt;p&gt;Some obligatory pretty pictures:&lt;/p&gt;
&lt;p&gt;&lt;img src="http://jamisbuck.org/images/kaleidoscope/pattern1.png" height="400" width="400" /&gt;&lt;br /&gt;
&lt;img src="http://jamisbuck.org/images/kaleidoscope/pattern2.png" height="400" width="400" /&gt;&lt;br /&gt;
&lt;img src="http://jamisbuck.org/images/kaleidoscope/pattern3.png" height="400" width="400" /&gt;&lt;br /&gt;
&lt;img src="http://jamisbuck.org/images/kaleidoscope/pattern4.png" height="400" width="400" /&gt;&lt;br /&gt;
&lt;img src="http://jamisbuck.org/images/kaleidoscope/pattern5.png" height="400" width="400" /&gt;&lt;br /&gt;
&lt;img src="http://jamisbuck.org/images/kaleidoscope/pattern6.png" height="400" width="400" /&gt;&lt;br /&gt;
&lt;img src="http://jamisbuck.org/images/kaleidoscope/pattern7.png" height="400" width="400" /&gt;&lt;br /&gt;
&lt;img src="http://jamisbuck.org/images/kaleidoscope/pattern8.png" height="400" width="400" /&gt;&lt;/p&gt;


	&lt;p&gt;The real reason I got into all this, though, was to find interesting tesselations to build mazes in:&lt;/p&gt;


	&lt;p&gt;&lt;img src="http://jamisbuck.org/images/kaleidoscope/maze1.png" height="400" width="400" /&gt;&lt;br /&gt;
&lt;img src="http://jamisbuck.org/images/kaleidoscope/maze2.png" height="400" width="400" /&gt;&lt;br /&gt;
&lt;img src="http://jamisbuck.org/images/kaleidoscope/maze3.png" height="400" width="400" /&gt;&lt;br /&gt;
&lt;img src="http://jamisbuck.org/images/kaleidoscope/maze4.png" height="400" width="400" /&gt;&lt;/p&gt;


	&lt;p&gt;It was a fascinating a project, and I had a lot of fun. Oh, and I did it all test-first—a first for me! I learned a ton about &lt;span class="caps"&gt;TDD&lt;/span&gt;.&lt;/p&gt;


	&lt;p&gt;That said, I’m ready to move on to other projects. I don’t expect I’ll do much more with this library, although there is definitely more that &lt;em&gt;could&lt;/em&gt; be done. I’m releasing the code because others might find it interesting. If you do anything nifty with it, let me know!&lt;/p&gt;
          &lt;img src="http://feeds.feedburner.com/~r/buckblog/~4/9gObL9v9PRk" height="1" width="1"/&gt;</content>  </entry>
  <entry xml:base="http://weblog.jamisbuck.org/">
    <author>
      <name>Jamis</name>
    </author>
    <id>tag:weblog.jamisbuck.org,2011-02-09:8764</id>
    <published>2011-02-09T16:30:00Z</published>
    <updated>2011-02-09T16:32:04Z</updated>
    <category term="Announcements" />
    <category term="Projects" />
    <category term="coffeescript" />
    <category term="mazes" />
    <link href="http://weblog.jamisbuck.org/2011/2/9/mazes-in-coffeescript" rel="alternate" type="text/html" />
    <title>Mazes in CoffeeScript</title>
<content type="html">
            &lt;p&gt;Several people have asked how I did the Javascript demos in my &lt;a href="http://weblog.jamisbuck.org/2011/2/7/maze-generation-algorithm-recap"&gt;maze algorithm articles&lt;/a&gt;, and while I’ve answered them a couple of times in the comments, I thought it might be interesting enough to warrent its own post.&lt;/p&gt;


	&lt;p&gt;The demos are actually implemented in &lt;a href="http://www.coffeescript.org"&gt;CoffeeScript&lt;/a&gt;, a really elegant little language that compiles to Javascript. CoffeeScript lets you ignore (most of) Javascript’s warts, while still enjoying all of Javascript’s strengths. I like.&lt;/p&gt;


	&lt;p&gt;So, the CoffeeScript sources for my maze demos are at &lt;a href="https://github.com/jamis/csmazes"&gt;https://github.com/jamis/csmazes&lt;/a&gt;.&lt;/p&gt;


	&lt;p&gt;I’ve tried to anticipate most questions about building, installation, and usage in the &lt;a href="https://github.com/jamis/csmazes/blob/master/README.md"&gt;readme&lt;/a&gt;, but in a nutshell:&lt;/p&gt;


	&lt;ol&gt;
	&lt;li&gt;You’ll need to install &lt;a href="http://www.coffeescript.org"&gt;CoffeeScript&lt;/a&gt; if you want to do anything with the code.&lt;/li&gt;
		&lt;li&gt;“cake build” will compile the sources to Javascript.&lt;/li&gt;
		&lt;li&gt;“examples/index.html” has widgets for all the implemented algorithms for you to play with.&lt;/li&gt;
		&lt;li&gt;“Maze.createWidget” is the quick-and-easy way to embed a maze somewhere.&lt;/li&gt;
		&lt;li&gt;You can do it the hard way, too, if you need more control: instantiate a maze with the algorithm of your choice, then call Maze#step until the maze is generated (or Maze#generate to do it all at once).&lt;/li&gt;
	&lt;/ol&gt;


	&lt;p&gt;Note that the implementations there are optimized for animating the algorithms; the source code is &lt;em&gt;not&lt;/em&gt; a good place to learn how a typical maze implementation might look. Every algorithm is broken down so that it can be called piecewise, one step at a time. If you were going to implement any of these for any “serious” purpose, odds are you’d do it much more efficiently, and without all the ceremony that csMazes requires.&lt;/p&gt;


	&lt;p&gt;Still, if you just want to embed an animation of a maze algorithm on a web page, csMazes works quite well. Except for &lt;span class="caps"&gt;IE7&lt;/span&gt;. And probably other IE’s as well. (If you’re an IE guru, I’d appreciate patches, but please make sure your fixes don’t impact the animation performance on other browsers. I was able to make IE render the mazes okay, but then the animation performance on Chrome was abyssmal.)&lt;/p&gt;


	&lt;p&gt;The code is in the public domain, so do with it what you will. If you do something fun with it, let me know!&lt;/p&gt;
          &lt;img src="http://feeds.feedburner.com/~r/buckblog/~4/6OLMWKoQ5lE" height="1" width="1"/&gt;</content>  </entry>
  <entry xml:base="http://weblog.jamisbuck.org/">
    <author>
      <name>Jamis</name>
    </author>
    <id>tag:weblog.jamisbuck.org,2011-02-07:8744</id>
    <published>2011-02-07T18:02:00Z</published>
    <updated>2011-03-01T03:41:24Z</updated>
    <category term="Under the Hood" />
    <category term="mazes" />
    <link href="http://weblog.jamisbuck.org/2011/2/7/maze-generation-algorithm-recap" rel="alternate" type="text/html" />
    <title>Maze Generation: Algorithm Recap</title>
<summary type="html">&lt;p&gt;(Hello Minecrafters! If you’re looking for random mazes you can build in Minecraft, you might be better served by &lt;a href="http://jamisbuck.org/mazes/minecraft.html"&gt;this page I wrote&lt;/a&gt;. It’ll give you block-wise schematics for the maze, and will require less mental translation than the demos here. Just don’t use IE&amp;mdash;it won’t work right in that browser. If you want to learn more about random maze generation, though, read on!)&lt;/p&gt;


	&lt;p&gt;Over the last six weeks I documented eleven different maze generation algorithms. It’s been a blast. I’ve had so much fun researching and implementing these! It’s been great to see some of you taking my advice and applying these to learning a new programming language, as well; I really believe there is a lot of value to be had, there.&lt;/p&gt;


	&lt;p&gt;I intend to write more maze-related posts, too. Some possible topics include methods for rendering your mazes, ways to implement “weave” mazes (mazes where passages pass over and under other passages), non-rectangular tesselations, and so on. We’ll see where it all goes.&lt;/p&gt;


	&lt;p&gt;To wrap up the algorithm series, here’s a quick recap of each of the eleven algorithms:&lt;/p&gt;</summary><content type="html">
            &lt;p&gt;(Hello Minecrafters! If you’re looking for random mazes you can build in Minecraft, you might be better served by &lt;a href="http://jamisbuck.org/mazes/minecraft.html"&gt;this page I wrote&lt;/a&gt;. It’ll give you block-wise schematics for the maze, and will require less mental translation than the demos here. Just don’t use IE&amp;mdash;it won’t work right in that browser. If you want to learn more about random maze generation, though, read on!)&lt;/p&gt;


	&lt;p&gt;Over the last six weeks I documented eleven different maze generation algorithms. It’s been a blast. I’ve had so much fun researching and implementing these! It’s been great to see some of you taking my advice and applying these to learning a new programming language, as well; I really believe there is a lot of value to be had, there.&lt;/p&gt;


	&lt;p&gt;I intend to write more maze-related posts, too. Some possible topics include methods for rendering your mazes, ways to implement “weave” mazes (mazes where passages pass over and under other passages), non-rectangular tesselations, and so on. We’ll see where it all goes.&lt;/p&gt;


	&lt;p&gt;To wrap up the algorithm series, here’s a quick recap of each of the eleven algorithms:&lt;/p&gt;
&lt;p&gt;(Note: if you’re using a feed-reader, or reading this on a parasite-blog, you’ll probably be missing out on the Javascript demos. I’m not just trying to drive traffic, here, I really do think you’ll get more out of the article by reading it at the source!)&lt;/p&gt;


	&lt;p&gt;The &lt;a href="http://weblog.jamisbuck.org/2010/12/27/maze-generation-recursive-backtracking"&gt;recursive backtracker&lt;/a&gt; was my go-to algorithm for years. It’s fast, easy to implement, and generates mazes that are (to my eyes, at least) quite esthetically pleasing. Of all the algorithms, it generates the fewest dead-ends, and as a result has particularly long and winding passages. It’s especially hypnotic to watch the algorithm in action!&lt;/p&gt;



&amp;lt;link href="http://jamisbuck.org/mazes/css/mazes.css" /&gt;
&lt;div class="row"&gt;
&lt;/div&gt;


	&lt;p&gt;&lt;a href="http://weblog.jamisbuck.org/2010/12/29/maze-generation-eller-s-algorithm"&gt;Eller’s algorithm&lt;/a&gt; is perhaps the most challenging to understand and implement of the algorithms I covered. Its clever use of sets allow it to generate infinitely tall mazes while only needing to examine a single row at a time. Esthetically, it strikes a nice balance between “long and winding” and “lots of cul-de-sacs”.&lt;/p&gt;



&lt;div class="row"&gt;
&lt;/div&gt;


	&lt;p&gt;&lt;a href="http://weblog.jamisbuck.org/2011/1/3/maze-generation-kruskal-s-algorithm"&gt;Kruskal’s algorithm&lt;/a&gt; is actually an algorithm for generating a minimum spanning tree (MST) for a graph. What I covered is actually a variation on that, which selects edges at random instead of by weight. The resulting mazes tend to have a lot of short cul-de-sacs. Implementation-wise, this algorithm might rank second in difficulty, some distance behind Eller’s algorithm.&lt;/p&gt;



&lt;div class="row"&gt;
&lt;/div&gt;


	&lt;p&gt;&lt;a href="http://weblog.jamisbuck.org/2011/1/10/maze-generation-prim-s-algorithm"&gt;Prim’s algorithm&lt;/a&gt; is another &lt;span class="caps"&gt;MST&lt;/span&gt; algorithm. Like the variation I described for Kruskal’s, the Prim variant I covered also selects edges at random rather than by weight, allowing the creation of random mazes. Like Kruskal’s, the resulting mazes tend to be heavy on the cul-de-sacs, but the implementation is pretty straight-forward.&lt;/p&gt;



&lt;div class="row"&gt;
&lt;/div&gt;


	&lt;p&gt;The &lt;a href="http://weblog.jamisbuck.org/2011/1/12/maze-generation-recursive-division-algorithm"&gt;recursive division algorithm&lt;/a&gt; is novel in that it is the only one I covered that uses a “wall adding” technique, rather than a “passage carving” one. It is also novel in its fractal-like method of growing the maze. Theoretically, you could use this algorithm to generate infinitely large mazes by building sections on-demand, increasing the resolution as needed by repeating the algorithm on the currently focused area.&lt;/p&gt;



&lt;div class="row"&gt;
&lt;/div&gt;


	&lt;p&gt;I included the &lt;a href="http://weblog.jamisbuck.org/2011/1/17/maze-generation-aldous-broder-algorithm"&gt;Aldous-Broder algorithm&lt;/a&gt; mostly for completeness; the algorithm is optimized for generating “uniform spanning trees” (spanning trees selected at random, and uniformly, from the set of all possible spanning trees). Sadly, this constraint means the algorithm itself is very inefficient!&lt;/p&gt;



&lt;div class="row"&gt;
&lt;/div&gt;


	&lt;p&gt;&lt;a href="http://weblog.jamisbuck.org/2011/1/20/maze-generation-wilson-s-algorithm"&gt;Wilson’s algorithm&lt;/a&gt; is another method for generating uniform spanning trees. It converges more rapidly than Aldous-Broder, but still is much less effective as a general maze generator than any of the other algorithms I covered.&lt;/p&gt;



&lt;div class="row"&gt;
&lt;/div&gt;


	&lt;p&gt;The &lt;a href="http://weblog.jamisbuck.org/2011/1/24/maze-generation-hunt-and-kill-algorithm"&gt;Hunt-and-Kill algorithm&lt;/a&gt; is similar to the recursive backtracker (they both tend to generate long, winding passages), but this algorithm will search the grid, iteratively, looking for a new blank cell when it encounters a dead-end. A variation on this algorithm was my first introduction to maze generation, almost twenty years ago!&lt;/p&gt;



&lt;div class="row"&gt;
&lt;/div&gt;


	&lt;p&gt;My new favorite, the &lt;a href="http://weblog.jamisbuck.org/2011/1/27/maze-generation-growing-tree-algorithm"&gt;Growing Tree algorithm&lt;/a&gt;, can work identically to the recursive backtracker when implemented one way, and with another small tweak can be made to work very similarly to Prim’s algorithm. It all depends on how cells are selected from its set of active cells. In fact, attributes of both algorithms can be gained by clever combinations of cell selection methods! It’s quite a flexible algorithm.&lt;/p&gt;



&lt;p&gt; 
Cell selection method: &amp;lt;select&gt; 
&amp;lt;option&gt;Newest (Recursive Backtracker)&amp;lt;/option&gt; 
&amp;lt;option&gt;Random (Prim's)&amp;lt;/option&gt; 
&amp;lt;option&gt;Newest/Random, 75/25 split&amp;lt;/option&gt; 
&amp;lt;option&gt;Newest/Random, 50/50 split&amp;lt;/option&gt; 
&amp;lt;option&gt;Newest/Random, 25/75 split&amp;lt;/option&gt; 
&amp;lt;option&gt;Oldest&amp;lt;/option&gt; 
&amp;lt;option&gt;Middle&amp;lt;/option&gt; 
&amp;lt;option&gt;Newest/Oldest, 50/50 split&amp;lt;/option&gt; 
&amp;lt;option&gt;Oldest/Random, 50/50 split&amp;lt;/option&gt; 
&amp;lt;/select&gt; 
&lt;/p&gt; 
&lt;div class="row"&gt; 
&lt;/div&gt; 


	&lt;p&gt;The &lt;a href="http://weblog.jamisbuck.org/2011/2/1/maze-generation-binary-tree-algorithm"&gt;Binary Tree algorithm&lt;/a&gt; is an almost-trivially simple one, but you pay for that simplicity. The mazes it generates tend to have blemishes (long corridors spanning two sides) and a notable bias (routes tend to run diagonally). Still, for some applications this can be quite appropriate. Besides, with this algorithm you could theoretically have an infinitely large maze by generating only the area you need, on demand!&lt;/p&gt;



&lt;p&gt; 
  Bias: &amp;lt;select&gt; 
    &amp;lt;option&gt;Northwest&amp;lt;/option&gt; 
    &amp;lt;option&gt;Northeast&amp;lt;/option&gt; 
    &amp;lt;option&gt;Southwest&amp;lt;/option&gt; 
    &amp;lt;option&gt;Southeast&amp;lt;/option&gt; 
  &amp;lt;/select&gt; 
&lt;/p&gt; 
&lt;div class="row"&gt; 
&lt;/div&gt; 


	&lt;p&gt;The last algorithm I covered was the &lt;a href="http://weblog.jamisbuck.org/2011/2/3/maze-generation-sidewinder-algorithm"&gt;Sidewinder algorithm&lt;/a&gt;. This is related to the Binary Tree algorithm, but does not have as noticable a bias, and there is only one long passage across the top.&lt;/p&gt;



&lt;div class="row"&gt;
&lt;/div&gt;


	&lt;p&gt;Thanks to everyone who has followed along for the last six weeks. Thanks especially go to those who shared their own implementations; I love seeing how these algorithms translate into other languages.&lt;/p&gt;


	&lt;p&gt;So, that’s it for the algorithms, but stay tuned for more maze-related topics in the coming weeks!&lt;/p&gt;
          &lt;img src="http://feeds.feedburner.com/~r/buckblog/~4/zqyKc2zTXRc" height="1" width="1"/&gt;</content>  </entry>
  <entry xml:base="http://weblog.jamisbuck.org/">
    <author>
      <name>Jamis</name>
    </author>
    <id>tag:weblog.jamisbuck.org,2011-02-03:8725</id>
    <published>2011-02-03T14:20:00Z</published>
    <updated>2011-02-03T14:43:04Z</updated>
    <category term="Under the Hood" />
    <category term="mazes" />
    <category term="ruby" />
    <link href="http://weblog.jamisbuck.org/2011/2/3/maze-generation-sidewinder-algorithm" rel="alternate" type="text/html" />
    <title>Maze Generation: Sidewinder algorithm</title>
<summary type="html">&lt;p&gt;Last of the (eleven!) maze algorithms on my list is the Sidewinder algorithm. With a name like that, it’s got to be cool, right?&lt;/p&gt;


	&lt;p&gt;Well, possibly. It’s got its problems, but it’s quick and easy to implement, and allows arbitrarily tall mazes. It’s closely related to the &lt;a href="http://weblog.jamisbuck.org/2011/2/1/maze-generation-binary-tree-algorithm"&gt;Binary Tree algorithm&lt;/a&gt;, but manages to get away with only one side being spanned by a passage, instead of two.&lt;/p&gt;


	&lt;p&gt;In a nutshell, it goes like this:&lt;/p&gt;


	&lt;ol&gt;
	&lt;li&gt;Work through the grid row-wise, starting with the cell at 0,0. Initialize the “run” set to be empty.&lt;/li&gt;
		&lt;li&gt;Add the current cell to the “run” set.&lt;/li&gt;
		&lt;li&gt;For the current cell, randomly decide whether to carve east or not.&lt;/li&gt;
		&lt;li&gt;If a passage was carved, make the new cell the current cell and repeat steps 2-4.&lt;/li&gt;
		&lt;li&gt;If a passage was &lt;em&gt;not&lt;/em&gt; carved, choose any one of the cells in the run set and carve a passage north. Then empty the run set, set the next cell in the row to be the current cell, and repeat steps 2-5.&lt;/li&gt;
		&lt;li&gt;Continue until all rows have been processed.&lt;/li&gt;
	&lt;/ol&gt;


	&lt;p&gt;So, while it’s related to the Binary Tree algorithm, it’s a bit more complicated. However, words don’t do it justice; it really is a lot more straightforward than it sounds.&lt;/p&gt;


	&lt;p&gt;Let’s walk through an example.&lt;/p&gt;</summary><content type="html">
            &lt;p&gt;Last of the (eleven!) maze algorithms on my list is the Sidewinder algorithm. With a name like that, it’s got to be cool, right?&lt;/p&gt;


	&lt;p&gt;Well, possibly. It’s got its problems, but it’s quick and easy to implement, and allows arbitrarily tall mazes. It’s closely related to the &lt;a href="http://weblog.jamisbuck.org/2011/2/1/maze-generation-binary-tree-algorithm"&gt;Binary Tree algorithm&lt;/a&gt;, but manages to get away with only one side being spanned by a passage, instead of two.&lt;/p&gt;


	&lt;p&gt;In a nutshell, it goes like this:&lt;/p&gt;


	&lt;ol&gt;
	&lt;li&gt;Work through the grid row-wise, starting with the cell at 0,0. Initialize the “run” set to be empty.&lt;/li&gt;
		&lt;li&gt;Add the current cell to the “run” set.&lt;/li&gt;
		&lt;li&gt;For the current cell, randomly decide whether to carve east or not.&lt;/li&gt;
		&lt;li&gt;If a passage was carved, make the new cell the current cell and repeat steps 2-4.&lt;/li&gt;
		&lt;li&gt;If a passage was &lt;em&gt;not&lt;/em&gt; carved, choose any one of the cells in the run set and carve a passage north. Then empty the run set, set the next cell in the row to be the current cell, and repeat steps 2-5.&lt;/li&gt;
		&lt;li&gt;Continue until all rows have been processed.&lt;/li&gt;
	&lt;/ol&gt;


	&lt;p&gt;So, while it’s related to the Binary Tree algorithm, it’s a bit more complicated. However, words don’t do it justice; it really is a lot more straightforward than it sounds.&lt;/p&gt;


	&lt;p&gt;Let’s walk through an example.&lt;/p&gt;
&lt;h2&gt;An example&lt;/h2&gt;


	&lt;p&gt;I’ll use a 4×4 grid, and I’ll move fairly quickly, so pay attention. (You in the back! Eyes to the front!)&lt;/p&gt;


&lt;table class="maze"&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;

	&lt;p&gt;I’ll start with the first (top) row, although the algorithm works just fine if you start with the last one and work up. Starting at the top lets us get the one special case out of the way: the entire first row must be a single passage (because you can’t carve north from the northernmost row):&lt;/p&gt;


&lt;table class="maze"&gt;
&lt;tr&gt;&lt;td class="n s w"&gt;&lt;/td&gt;&lt;td class="n s"&gt;&lt;/td&gt;&lt;td class="n s"&gt;&lt;/td&gt;&lt;td class="n s e"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;

	&lt;p&gt;There, we’ve got that done with. Now, let’s get to the interesting bit. Let’s say we manage to carve 3/4 of the way across the row before we decide (randomly and arbitrarily) &lt;em&gt;not&lt;/em&gt; to carve eastward:&lt;/p&gt;


&lt;table class="maze"&gt;
&lt;tr&gt;&lt;td class="n s w"&gt;&lt;/td&gt;&lt;td class="n s"&gt;&lt;/td&gt;&lt;td class="n s"&gt;&lt;/td&gt;&lt;td class="n s e"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s w mark"&gt;&lt;/td&gt;&lt;td class="n s mark"&gt;&lt;/td&gt;&lt;td class="n s e mark"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;

	&lt;p&gt;The cells in red are the current “run set”. Since we’ve ended the current run of horizontal cells, we now choose one of these cells at random, and carve a passage north. Thus:&lt;/p&gt;


&lt;table class="maze"&gt;
&lt;tr&gt;&lt;td class="n s w"&gt;&lt;/td&gt;&lt;td class="n"&gt;&lt;/td&gt;&lt;td class="n s"&gt;&lt;/td&gt;&lt;td class="n s e"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s w mark"&gt;&lt;/td&gt;&lt;td class="s mark"&gt;&lt;/td&gt;&lt;td class="n s e mark"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;

	&lt;p&gt;Then we clear out the run set:&lt;/p&gt;


&lt;table class="maze"&gt;
&lt;tr&gt;&lt;td class="n s w"&gt;&lt;/td&gt;&lt;td class="n"&gt;&lt;/td&gt;&lt;td class="n s"&gt;&lt;/td&gt;&lt;td class="n s e"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s w"&gt;&lt;/td&gt;&lt;td class="s"&gt;&lt;/td&gt;&lt;td class="n s e"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;

	&lt;p&gt;Make the next cell the current cell:&lt;/p&gt;


&lt;table class="maze"&gt;
&lt;tr&gt;&lt;td class="n s w"&gt;&lt;/td&gt;&lt;td class="n"&gt;&lt;/td&gt;&lt;td class="n s"&gt;&lt;/td&gt;&lt;td class="n s e"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s w"&gt;&lt;/td&gt;&lt;td class="s"&gt;&lt;/td&gt;&lt;td class="n s e"&gt;&lt;/td&gt;&lt;td class="n s e w mark"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;

	&lt;p&gt;And try to decide whether to carve eastward or not. However, at this point, we &lt;em&gt;can’t&lt;/em&gt; carve east. It would take us outside the bounds of the maze, which is not allowed. So we have to end the run there, and choose one of the cells in the set to carve north from. The decision is out of our hands: with only a single cell in the set, we have to choose it. So we carve north:&lt;/p&gt;


&lt;table class="maze"&gt;
&lt;tr&gt;&lt;td class="n s w"&gt;&lt;/td&gt;&lt;td class="n"&gt;&lt;/td&gt;&lt;td class="n s"&gt;&lt;/td&gt;&lt;td class="n e"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s w"&gt;&lt;/td&gt;&lt;td class="s"&gt;&lt;/td&gt;&lt;td class="n s e"&gt;&lt;/td&gt;&lt;td class="s e w"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;

	&lt;p&gt;Then we start the next row. Notice how each row is independent of the row preceding it, much like &lt;a href="http://weblog.jamisbuck.org/2010/12/29/maze-generation-eller-s-algorithm"&gt;Eller’s algorithm&lt;/a&gt;.&lt;/p&gt;


	&lt;p&gt;For the next row, we decide immediately that we want to stop carving east on the very first cell:&lt;/p&gt;


&lt;table class="maze"&gt;
&lt;tr&gt;&lt;td class="n s w"&gt;&lt;/td&gt;&lt;td class="n"&gt;&lt;/td&gt;&lt;td class="n s"&gt;&lt;/td&gt;&lt;td class="n e"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s w"&gt;&lt;/td&gt;&lt;td class="s"&gt;&lt;/td&gt;&lt;td class="n s e"&gt;&lt;/td&gt;&lt;td class="s e w"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s e w mark"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;

	&lt;p&gt;So we stop, choose a cell from the run set (easy) and carve north:&lt;/p&gt;


&lt;table class="maze"&gt;
&lt;tr&gt;&lt;td class="n s w"&gt;&lt;/td&gt;&lt;td class="n"&gt;&lt;/td&gt;&lt;td class="n s"&gt;&lt;/td&gt;&lt;td class="n e"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n w"&gt;&lt;/td&gt;&lt;td class="s"&gt;&lt;/td&gt;&lt;td class="n s e"&gt;&lt;/td&gt;&lt;td class="s e w"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="s e w"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;

	&lt;p&gt;Continuing, we connect the next two cells:&lt;/p&gt;


&lt;table class="maze"&gt;
&lt;tr&gt;&lt;td class="n s w"&gt;&lt;/td&gt;&lt;td class="n"&gt;&lt;/td&gt;&lt;td class="n s"&gt;&lt;/td&gt;&lt;td class="n e"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n w"&gt;&lt;/td&gt;&lt;td class="s"&gt;&lt;/td&gt;&lt;td class="n s e"&gt;&lt;/td&gt;&lt;td class="s e w"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="s e w"&gt;&lt;/td&gt;&lt;td class="n s w mark"&gt;&lt;/td&gt;&lt;td class="n s e mark"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;

	&lt;p&gt;Randomly choose one of them to carve north from:&lt;/p&gt;


&lt;table class="maze"&gt;
&lt;tr&gt;&lt;td class="n s w"&gt;&lt;/td&gt;&lt;td class="n"&gt;&lt;/td&gt;&lt;td class="n s"&gt;&lt;/td&gt;&lt;td class="n e"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n w"&gt;&lt;/td&gt;&lt;td class="s"&gt;&lt;/td&gt;&lt;td class="n e"&gt;&lt;/td&gt;&lt;td class="s e w"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="s e w"&gt;&lt;/td&gt;&lt;td class="n s w"&gt;&lt;/td&gt;&lt;td class="s e"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;

	&lt;p&gt;And continue:&lt;/p&gt;


&lt;table class="maze"&gt;
&lt;tr&gt;&lt;td class="n s w"&gt;&lt;/td&gt;&lt;td class="n"&gt;&lt;/td&gt;&lt;td class="n s"&gt;&lt;/td&gt;&lt;td class="n e"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n w"&gt;&lt;/td&gt;&lt;td class="s"&gt;&lt;/td&gt;&lt;td class="n e"&gt;&lt;/td&gt;&lt;td class="s e w"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="s e w"&gt;&lt;/td&gt;&lt;td class="n s w"&gt;&lt;/td&gt;&lt;td class="s e"&gt;&lt;/td&gt;&lt;td class="n s e w mark"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;

	&lt;p&gt;And since we’re at the end of the row, we’re again forced to stop and carve north:&lt;/p&gt;


&lt;table class="maze"&gt;
&lt;tr&gt;&lt;td class="n s w"&gt;&lt;/td&gt;&lt;td class="n"&gt;&lt;/td&gt;&lt;td class="n s"&gt;&lt;/td&gt;&lt;td class="n e"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n w"&gt;&lt;/td&gt;&lt;td class="s"&gt;&lt;/td&gt;&lt;td class="n e"&gt;&lt;/td&gt;&lt;td class="e w"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="s e w"&gt;&lt;/td&gt;&lt;td class="n s w"&gt;&lt;/td&gt;&lt;td class="s e"&gt;&lt;/td&gt;&lt;td class="s e w"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;

	&lt;p&gt;For the last row, let’s say we connect the first two cells:&lt;/p&gt;


&lt;table class="maze"&gt;
&lt;tr&gt;&lt;td class="n s w"&gt;&lt;/td&gt;&lt;td class="n"&gt;&lt;/td&gt;&lt;td class="n s"&gt;&lt;/td&gt;&lt;td class="n e"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n w"&gt;&lt;/td&gt;&lt;td class="s"&gt;&lt;/td&gt;&lt;td class="n e"&gt;&lt;/td&gt;&lt;td class="e w"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="s e w"&gt;&lt;/td&gt;&lt;td class="n s w"&gt;&lt;/td&gt;&lt;td class="s e"&gt;&lt;/td&gt;&lt;td class="s e w"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s w mark"&gt;&lt;/td&gt;&lt;td class="n s e mark"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;

	&lt;p&gt;Carve north and clear the set:&lt;/p&gt;


&lt;table class="maze"&gt;
&lt;tr&gt;&lt;td class="n s w"&gt;&lt;/td&gt;&lt;td class="n"&gt;&lt;/td&gt;&lt;td class="n s"&gt;&lt;/td&gt;&lt;td class="n e"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n w"&gt;&lt;/td&gt;&lt;td class="s"&gt;&lt;/td&gt;&lt;td class="n e"&gt;&lt;/td&gt;&lt;td class="e w"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="s e w"&gt;&lt;/td&gt;&lt;td class="n w"&gt;&lt;/td&gt;&lt;td class="s e"&gt;&lt;/td&gt;&lt;td class="s e w"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s w"&gt;&lt;/td&gt;&lt;td class="s e"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;

	&lt;p&gt;Then connect the last two cells:&lt;/p&gt;


&lt;table class="maze"&gt;
&lt;tr&gt;&lt;td class="n s w"&gt;&lt;/td&gt;&lt;td class="n"&gt;&lt;/td&gt;&lt;td class="n s"&gt;&lt;/td&gt;&lt;td class="n e"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n w"&gt;&lt;/td&gt;&lt;td class="s"&gt;&lt;/td&gt;&lt;td class="n e"&gt;&lt;/td&gt;&lt;td class="e w"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="s e w"&gt;&lt;/td&gt;&lt;td class="n w"&gt;&lt;/td&gt;&lt;td class="s e"&gt;&lt;/td&gt;&lt;td class="s e w"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s w"&gt;&lt;/td&gt;&lt;td class="s e"&gt;&lt;/td&gt;&lt;td class="n s w mark"&gt;&lt;/td&gt;&lt;td class="n s e mark"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;

	&lt;p&gt;And finish it off by adding a final northward connection:&lt;/p&gt;


&lt;table class="maze"&gt;
&lt;tr&gt;&lt;td class="n s w"&gt;&lt;/td&gt;&lt;td class="n"&gt;&lt;/td&gt;&lt;td class="n s"&gt;&lt;/td&gt;&lt;td class="n e"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n w"&gt;&lt;/td&gt;&lt;td class="s"&gt;&lt;/td&gt;&lt;td class="n e"&gt;&lt;/td&gt;&lt;td class="e w"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="s e w"&gt;&lt;/td&gt;&lt;td class="n w"&gt;&lt;/td&gt;&lt;td class="e"&gt;&lt;/td&gt;&lt;td class="s e w"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s w"&gt;&lt;/td&gt;&lt;td class="s e"&gt;&lt;/td&gt;&lt;td class="s w"&gt;&lt;/td&gt;&lt;td class="n s e"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;

	&lt;p&gt;And that’s our maze, courtesty of the Sidewinder.&lt;/p&gt;


	&lt;p&gt;Feel free to play with the following demos, to get a feel for how the Sidewinder works on larger grids. The single corridor spanning the top row is hard to miss, but see if you can spot any other properties of the algorithm.&lt;/p&gt;



&amp;lt;link href="http://jamisbuck.org/mazes/css/mazes.css" /&gt;
&lt;div class="row"&gt;
&lt;/div&gt;


	&lt;h2&gt;Implementation&lt;/h2&gt;


	&lt;p&gt;All this talk of “run sets” might make you think you actually need to use a set. Well, you can, sure, if you want to. No one’s going to stop you, right? But if you notice that each set consists of consecutive cells, you can take a short-cut and just keep track of the cell that started the run. The “set” is then implied as the sequence of cells between the start of the run, and the current cell.&lt;/p&gt;


	&lt;p&gt;Aside from that, the algorithm has very few surprises. As you’d expect you need to iterate over each row:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;height.times &lt;span class="r"&gt;do&lt;/span&gt; |y|&lt;tt&gt;
&lt;/tt&gt;  run_start = &lt;span class="i"&gt;0&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="c"&gt;# ...&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;At the start of each row I initialize the beginning of the current run to the first cell.&lt;/p&gt;


	&lt;p&gt;Then, within that loop, I iterate over each cell in the current row:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;width.times &lt;span class="r"&gt;do&lt;/span&gt; |x|&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="c"&gt;# ...&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;Within &lt;em&gt;that&lt;/em&gt; loop is where the magic really happens. There are basically two conditions:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="r"&gt;if&lt;/span&gt; y &amp;gt; &lt;span class="i"&gt;0&lt;/span&gt; &amp;amp;&amp;amp; (x&lt;span class="i"&gt;+1&lt;/span&gt; == width || rand(&lt;span class="i"&gt;2&lt;/span&gt;) == &lt;span class="i"&gt;0&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="c"&gt;# end current run and carve north&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;elsif&lt;/span&gt; x&lt;span class="i"&gt;+1&lt;/span&gt; &amp;lt; width&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="c"&gt;# carve east&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;Remember how the first row is always a single corridor? That “y &amp;gt; 0” guard prevents us from ever ending the current run if we’re on the first row. Similarly, the “elsif” clause prevents us from carving east if we’re at the last cell in a row.&lt;/p&gt;


	&lt;p&gt;The second condition in the first clause makes sure that we always end the current run at the end of the current row (x+1 == width), but also allows us to randomly end the current run (rand(2) == 0).&lt;/p&gt;


	&lt;p&gt;Ending a run requires us to randomly choose a cell from the current run set, and carve north from it:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;cell = run_start + rand(x - run_start + &lt;span class="i"&gt;1&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;grid[y][cell] |= &lt;span class="co"&gt;N&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;grid[y&lt;span class="i"&gt;-1&lt;/span&gt;][cell] |= &lt;span class="co"&gt;S&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;run_start = x&lt;span class="i"&gt;+1&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;We also reset the run set to begin at the next cell.&lt;/p&gt;


	&lt;p&gt;The last bit of code, from the elsif clause, is simple: carving east is merely setting a bit:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;grid[y][x] |= &lt;span class="co"&gt;E&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;grid[y][x&lt;span class="i"&gt;+1&lt;/span&gt;] |= &lt;span class="co"&gt;W&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;And that’s all there is to it. Like I said, it’s easier to implement than describe.&lt;/p&gt;


	&lt;h2&gt;Conclusion&lt;/h2&gt;


	&lt;p&gt;With a name like “Sidewinder” you can’t help but wish the algorithm was cooler than it is. I’m actually not sure where the name comes from; a Google search reveals a routing algorithm with the same name, but I wasn’t able to find any solid information to compare with the one I describe here. (If anyone has more information, I’m definitely curious.)&lt;/p&gt;


	&lt;p&gt;The Sidewinder’s greatest “flaw”, if it can be called that, is that it is all but trivial to start at the bottom row of the maze, and work your way to the top. Any maze generated by the Sidewinder algorithm will never have any north-facing dead-ends, which means you can never get stuck when moving from south to north. (This is similar to the Binary Tree algorithm, which will never have any dead-ends in the direction of its bias.) And for quickly generating arbitrarily tall mazes, &lt;a href="http://weblog.jamisbuck.org/2010/12/29/maze-generation-eller-s-algorithm"&gt;Eller’s algorithm&lt;/a&gt; is probably better (with fewer drawbacks), but is harder to implement.&lt;/p&gt;


	&lt;p&gt;Would I actually use the Sidewinder algorithm for anything? I’m not sure. I hesitate to say “never”, but I certainly can’t think of anything I’d use it for that another algorithm wouldn’t do better! But it was fun to implement, so it has entertainment value, if nothing else.&lt;/p&gt;


	&lt;p&gt;Give it a try yourself and share how it goes! For reference, my complete implementation follows:&lt;/p&gt;



&amp;lt;noscript&gt;&lt;a href="https://gist.github.com/761547"&gt;sidewinder.rb&lt;/a&gt; on gist.github.com&amp;lt;/noscript&gt;


	&lt;p&gt;Enjoy!&lt;/p&gt;
          &lt;img src="http://feeds.feedburner.com/~r/buckblog/~4/V4hqe_7gx2Y" height="1" width="1"/&gt;</content>  </entry>
  <entry xml:base="http://weblog.jamisbuck.org/">
    <author>
      <name>Jamis</name>
    </author>
    <id>tag:weblog.jamisbuck.org,2011-02-01:8715</id>
    <published>2011-02-01T14:47:00Z</published>
    <updated>2011-02-01T14:47:06Z</updated>
    <category term="Under the Hood" />
    <category term="mazes" />
    <category term="ruby" />
    <link href="http://weblog.jamisbuck.org/2011/2/1/maze-generation-binary-tree-algorithm" rel="alternate" type="text/html" />
    <title>Maze Generation: Binary Tree algorithm</title>
<summary type="html">&lt;p&gt;This next algorithm is crazy, crazy simple. It also is the only one of the algorithms I’ve covered with the ability to generate a perfect maze without keeping any state at all. It can build the entire maze by looking at only a single cell at a time.&lt;/p&gt;


	&lt;p&gt;Here’s how it works: for every cell in the grid, randomly carve a passage either north, or west.&lt;/p&gt;


	&lt;p&gt;That’s it. You can mix it up if you want, and choose between other diagonal sets: north/east, south/west, or south/east, but whichever diagonal set you select must be used consistently throughout the entire maze.&lt;/p&gt;


	&lt;p&gt;There’s another nifty attribute of this algorithm: if you can guarantee that for any given cell, you will always carve a particular direction, then you never need to keep any of the maze in memory. When you need to display some portion of the maze, you just “rebuild” it, trivially. This means you could create infinitely large mazes in very little memory.&lt;/p&gt;


	&lt;p&gt;It’s not all roses, though. A side-effect of this algorithm is that it has a strong diagonal &lt;em&gt;bias&lt;/em&gt;. Also, two of the four sides of the maze will be spanned by a single corridor. But for some applications, that might be acceptable.&lt;/p&gt;


	&lt;p&gt;It’s almost too simple to bother, but let’s take a quick look at the algorithm in practice.&lt;/p&gt;</summary><content type="html">
            &lt;p&gt;This next algorithm is crazy, crazy simple. It also is the only one of the algorithms I’ve covered with the ability to generate a perfect maze without keeping any state at all. It can build the entire maze by looking at only a single cell at a time.&lt;/p&gt;


	&lt;p&gt;Here’s how it works: for every cell in the grid, randomly carve a passage either north, or west.&lt;/p&gt;


	&lt;p&gt;That’s it. You can mix it up if you want, and choose between other diagonal sets: north/east, south/west, or south/east, but whichever diagonal set you select must be used consistently throughout the entire maze.&lt;/p&gt;


	&lt;p&gt;There’s another nifty attribute of this algorithm: if you can guarantee that for any given cell, you will always carve a particular direction, then you never need to keep any of the maze in memory. When you need to display some portion of the maze, you just “rebuild” it, trivially. This means you could create infinitely large mazes in very little memory.&lt;/p&gt;


	&lt;p&gt;It’s not all roses, though. A side-effect of this algorithm is that it has a strong diagonal &lt;em&gt;bias&lt;/em&gt;. Also, two of the four sides of the maze will be spanned by a single corridor. But for some applications, that might be acceptable.&lt;/p&gt;


	&lt;p&gt;It’s almost too simple to bother, but let’s take a quick look at the algorithm in practice.&lt;/p&gt;
&lt;h2&gt;An example&lt;/h2&gt;


	&lt;p&gt;I’ll use a trivial 3×3 grid.&lt;/p&gt;


&lt;table class="maze"&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;

	&lt;p&gt;Because this algorithm doesn’t need to consider the state of any adjacent cells, we can start from and proceed to anywhere we want; let’s begin with the bottom-right corner:&lt;/p&gt;


&lt;table class="maze"&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;

	&lt;p&gt;Then, we randomly carve a passage either north, or west. Let’s choose…north!&lt;/p&gt;


&lt;table class="maze"&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n e w out2"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="s e w"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;

	&lt;p&gt;Let’s work through the rest of that bottom row similarly, carving west from the middle cell, and north from the south-west corner:&lt;/p&gt;


&lt;table class="maze"&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n e w out2"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n e w out2"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="s w"&gt;&lt;/td&gt;&lt;td class="n s e"&gt;&lt;/td&gt;&lt;td class="s e w"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;

	&lt;p&gt;Note that for the bottom-left (south-west) corner, “west” was not an option, since it would take us outside the bounds of the grid. Thus, our hand was forced and we had to choose north. But we’re okay with that, right?&lt;/p&gt;


	&lt;p&gt;Let’s move on and process the second row:&lt;/p&gt;


&lt;table class="maze"&gt;
&lt;tr&gt;&lt;td class="n e w out2"&gt;&lt;/td&gt;&lt;td class="n e w out2"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="e w"&gt;&lt;/td&gt;&lt;td class="s w"&gt;&lt;/td&gt;&lt;td class="n e"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="s w"&gt;&lt;/td&gt;&lt;td class="n s e"&gt;&lt;/td&gt;&lt;td class="s e w"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;

	&lt;p&gt;Again, we were limited in our choices in the western-most cell: all we could choose was north, so we did.&lt;/p&gt;


	&lt;p&gt;Now, look what happens for the final row:&lt;/p&gt;


&lt;table class="maze"&gt;
&lt;tr&gt;&lt;td class="n w"&gt;&lt;/td&gt;&lt;td class="n"&gt;&lt;/td&gt;&lt;td class="n s e"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="e w"&gt;&lt;/td&gt;&lt;td class="s w"&gt;&lt;/td&gt;&lt;td class="n e"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="s w"&gt;&lt;/td&gt;&lt;td class="n s e"&gt;&lt;/td&gt;&lt;td class="s e w"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;

	&lt;p&gt;Because we can’t go north in any of those, we have to choose west. And for the north-west corner, we can’t choose either north, or west! So we simply mark it visited and trust that the algorithm will connect it by other means.&lt;/p&gt;


	&lt;p&gt;Notice the corridors spanning the north and west boundaries. This is one of the side-effects I mentioned. Also, while it’s not so visible in a maze this size, the maze has a strong north-west bias; there are no dead-ends (and never will be any dead-ends) facing either north or west. Thus, if you start at the south-east corner, getting to the north-west corner is trivial—you’ll never hit a dead-end. (Going the other direction is harder; it’s like carving wood with the grain, versus against the grain.)&lt;/p&gt;


	&lt;p&gt;Play around a bit with the following demo to see what I mean. You can also select a different bias here, to see how that changes things.&lt;/p&gt;



&amp;lt;link href="http://jamisbuck.org/mazes/css/mazes.css" /&gt;
&lt;p&gt;
  Bias: &amp;lt;select&gt;
    &amp;lt;option&gt;Northwest&amp;lt;/option&gt;
    &amp;lt;option&gt;Northeast&amp;lt;/option&gt;
    &amp;lt;option&gt;Southwest&amp;lt;/option&gt;
    &amp;lt;option&gt;Southeast&amp;lt;/option&gt;
  &amp;lt;/select&gt;
&lt;/p&gt;
&lt;div class="row"&gt;
&lt;/div&gt;


	&lt;h2&gt;Implementation&lt;/h2&gt;


	&lt;p&gt;The implementation of this algorithm is as trivially simple as you might think. You only need to cover every cell of the grid. One way to do that is to simply iterate over every row and column, in order:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;height.times &lt;span class="r"&gt;do&lt;/span&gt; |y|&lt;tt&gt;
&lt;/tt&gt;  width.times &lt;span class="r"&gt;do&lt;/span&gt; |x|&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="c"&gt;# ...&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;Within the loops, you determine which directions are valid:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;dirs = []&lt;tt&gt;
&lt;/tt&gt;dirs &amp;lt;&amp;lt; &lt;span class="co"&gt;N&lt;/span&gt; &lt;span class="r"&gt;if&lt;/span&gt; y &amp;gt; &lt;span class="i"&gt;0&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;dirs &amp;lt;&amp;lt; &lt;span class="co"&gt;W&lt;/span&gt; &lt;span class="r"&gt;if&lt;/span&gt; x &amp;gt; &lt;span class="i"&gt;0&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;And then you randomly select one:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="r"&gt;if&lt;/span&gt; (dir = dirs[rand(dirs.length)])&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="c"&gt;# ...&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;Once you’ve selected your direction, you just carve a passage between the two cells:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;nx, ny = x + &lt;span class="co"&gt;DX&lt;/span&gt;[dir], y + &lt;span class="co"&gt;DY&lt;/span&gt;[dir]&lt;tt&gt;
&lt;/tt&gt;grid[y][x] |= dir&lt;tt&gt;
&lt;/tt&gt;grid[ny][nx] |= &lt;span class="co"&gt;OPPOSITE&lt;/span&gt;[dir]&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;And you’re done!&lt;/p&gt;


	&lt;h2&gt;Conclusion&lt;/h2&gt;


	&lt;p&gt;The sharp-eyed among you might have noticed the connection between the name of the algorithm, and its output. Yes, the “Binary Tree” algorithm creates a random binary tree! Imagine that.&lt;/p&gt;


	&lt;p&gt;Every cell has one connection toward the “root” (in the direction of the bias, e.g. north or west), and zero, one, or two connections in the other direction (south or east). The root is, in this case, the north-west corner. If you could reach in and pluck up the north-west corner, giving it a good tug, it would uproot its children, and their children, and their children, until you’re left with a binary tree dangling downward like the knobbly roots of some tenacious weed.&lt;/p&gt;


	&lt;p&gt;Now, there are obviously other ways to build mazes based on binary trees. A particularly fun one is to make a variation of the &lt;a href="http://weblog.jamisbuck.org/2011/1/27/maze-generation-growing-tree-algorithm"&gt;Growing Tree algorithm&lt;/a&gt;: select a root node anywhere in the grid and add it to the list. Then, while the list is not empty, you remove a node from the list, add up to two passages leading away from it, and add those neighbors to the list. (I call this the “Growing Binary Tree algorithm”.) You’ll end up with another random binary tree, but without the obvious blemishes of the Binary Tree algorithm.&lt;/p&gt;


	&lt;p&gt;Nevertheless, the Binary Tree algorithm is fun to implement, and can be perfectly suitable for some applications (for instance, if you’re inside the maze, the biases will be less obvious). And if you need stupendously enormous mazes that can’t exist entirely in memory, why, this is an excellent algorithm as well.&lt;/p&gt;


	&lt;p&gt;My full implementation is below. Give it a try yourself, and share what you come up with!&lt;/p&gt;



&amp;lt;noscript&gt;&lt;a href="https://gist.github.com/761534"&gt;binary-tree.rb&lt;/a&gt; on gist.github.com&amp;lt;/noscript&gt;


	&lt;p&gt;Enjoy!&lt;/p&gt;
          &lt;img src="http://feeds.feedburner.com/~r/buckblog/~4/HmHUWPCtSnE" height="1" width="1"/&gt;</content>  </entry>
  <entry xml:base="http://weblog.jamisbuck.org/">
    <author>
      <name>Jamis</name>
    </author>
    <id>tag:weblog.jamisbuck.org,2011-01-27:8641</id>
    <published>2011-01-27T14:48:00Z</published>
    <updated>2011-01-27T14:48:36Z</updated>
    <category term="Under the Hood" />
    <category term="mazes" />
    <category term="ruby" />
    <link href="http://weblog.jamisbuck.org/2011/1/27/maze-generation-growing-tree-algorithm" rel="alternate" type="text/html" />
    <title>Maze Generation: Growing Tree algorithm</title>
<summary type="html">&lt;p&gt;Remember way back in the &lt;a href="http://weblog.jamisbuck.org/2010/12/27/maze-generation-recursive-backtracking"&gt;first article of this series&lt;/a&gt;, where I said that Recursive Backtracking was my favorite for generating mazes? Well, I changed my mind. My new favorite is the Growing Tree algorithm.&lt;/p&gt;


	&lt;p&gt;This algorithm is pretty cool. Configured one way, it mimics the behavior of the &lt;a href="http://weblog.jamisbuck.org/2010/12/27/maze-generation-recursive-backtracking"&gt;Recursive Backtracking algorithm&lt;/a&gt;. Configured another, it works almost exactly like &lt;a href="http://weblog.jamisbuck.org/2011/1/10/maze-generation-prim-s-algorithm"&gt;Prim’s algorithm&lt;/a&gt;. Another trivial change, and you can generate mazes with attributes of both.&lt;/p&gt;


	&lt;p&gt;It’s really pretty slick. Here’s how it works:&lt;/p&gt;


	&lt;ol&gt;
	&lt;li&gt;Let C be a list of cells, initially empty. Add one cell to C, at random.&lt;/li&gt;
		&lt;li&gt;Choose a cell from C, and carve a passage to any unvisited neighbor of that cell, adding that neighbor to C as well. If there are no unvisited neighbors, remove the cell from C.&lt;/li&gt;
		&lt;li&gt;Repeat #2 until C is empty.&lt;/li&gt;
	&lt;/ol&gt;


	&lt;p&gt;Pretty straight-forward, really. But the fun lies in how you choose the cells from C, in step #2. If you always choose the newest cell (the one most recently added), you’ll get the recursive backtracker. If you always choose a cell at random, you get Prim’s. It’s remarkably fun to experiment with other ways to choose cells from C.&lt;/p&gt;


	&lt;p&gt;Let’s look at a simple example.&lt;/p&gt;</summary><content type="html">
            &lt;p&gt;Remember way back in the &lt;a href="http://weblog.jamisbuck.org/2010/12/27/maze-generation-recursive-backtracking"&gt;first article of this series&lt;/a&gt;, where I said that Recursive Backtracking was my favorite for generating mazes? Well, I changed my mind. My new favorite is the Growing Tree algorithm.&lt;/p&gt;


	&lt;p&gt;This algorithm is pretty cool. Configured one way, it mimics the behavior of the &lt;a href="http://weblog.jamisbuck.org/2010/12/27/maze-generation-recursive-backtracking"&gt;Recursive Backtracking algorithm&lt;/a&gt;. Configured another, it works almost exactly like &lt;a href="http://weblog.jamisbuck.org/2011/1/10/maze-generation-prim-s-algorithm"&gt;Prim’s algorithm&lt;/a&gt;. Another trivial change, and you can generate mazes with attributes of both.&lt;/p&gt;


	&lt;p&gt;It’s really pretty slick. Here’s how it works:&lt;/p&gt;


	&lt;ol&gt;
	&lt;li&gt;Let C be a list of cells, initially empty. Add one cell to C, at random.&lt;/li&gt;
		&lt;li&gt;Choose a cell from C, and carve a passage to any unvisited neighbor of that cell, adding that neighbor to C as well. If there are no unvisited neighbors, remove the cell from C.&lt;/li&gt;
		&lt;li&gt;Repeat #2 until C is empty.&lt;/li&gt;
	&lt;/ol&gt;


	&lt;p&gt;Pretty straight-forward, really. But the fun lies in how you choose the cells from C, in step #2. If you always choose the newest cell (the one most recently added), you’ll get the recursive backtracker. If you always choose a cell at random, you get Prim’s. It’s remarkably fun to experiment with other ways to choose cells from C.&lt;/p&gt;


	&lt;p&gt;Let’s look at a simple example.&lt;/p&gt;
&lt;h2&gt;An example&lt;/h2&gt;


	&lt;p&gt;I’ll demonstrate the “choose newest” cell selection method, which will hopefully be enlightening enough that you can imagine on your own how the “choose random” method might proceed.&lt;/p&gt;


	&lt;p&gt;The algorithm begins by adding an arbitrary cell to the list. We mark the cell as “in”; I’m also going to assign the cell a number, visually, to help keep track of the relative age of each cell. Also, cells in red are in the list of “live” cells; they’ll go white once they’ve been removed from the list.&lt;/p&gt;


	&lt;p&gt;So, onward!&lt;/p&gt;


&lt;table class="maze"&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w mark"&gt;1&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;

	&lt;p&gt;Next step: we choose the newest cell from the list, randomly select one of its unvisited neighbors, carve a path to it, and add the neighbor to the list:&lt;/p&gt;


&lt;table class="maze"&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n e w mark"&gt;1&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="s e w mark"&gt;2&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;

	&lt;p&gt;Let’s do it again, once more choosing the newest cell from the list:&lt;/p&gt;


&lt;table class="maze"&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n e w mark"&gt;1&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s w mark"&gt;3&lt;/td&gt;&lt;td class="s e mark"&gt;2&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;

	&lt;p&gt;See the pattern? By always choosing the cell most recently added to the list, each subsequent step simply extends the passage one more step, effectively doing a random walk. But how does the algorithm behave when the passage cannot be extended any further?&lt;/p&gt;


	&lt;p&gt;Let’s fast forward a bit and see what the behavior is. Here we are now, six iterations further along, and we’ve hit a dead-end at cell #9.&lt;/p&gt;


&lt;table class="maze"&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n e w mark"&gt;1&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n w mark"&gt;3&lt;/td&gt;&lt;td class="s e mark"&gt;2&lt;/td&gt;&lt;td class="n w mark"&gt;7&lt;/td&gt;&lt;td class="n e mark"&gt;8&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="s w mark"&gt;4&lt;/td&gt;&lt;td class="n s mark"&gt;5&lt;/td&gt;&lt;td class="s e mark"&gt;6&lt;/td&gt;&lt;td class="s e w mark"&gt;9&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;

	&lt;p&gt;At this point, the algorithm would select the newest cell (#9), and then try to find an unvisited neighbor cell. Alas, there isn’t one! So cell #9 is &lt;del&gt;voted off the island&lt;/del&gt; removed from the list:&lt;/p&gt;


&lt;table class="maze"&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n e w mark"&gt;1&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n w mark"&gt;3&lt;/td&gt;&lt;td class="s e mark"&gt;2&lt;/td&gt;&lt;td class="n w mark"&gt;7&lt;/td&gt;&lt;td class="n e mark"&gt;8&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="s w mark"&gt;4&lt;/td&gt;&lt;td class="n s mark"&gt;5&lt;/td&gt;&lt;td class="s e mark"&gt;6&lt;/td&gt;&lt;td class="s e w"&gt;9&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;

	&lt;p&gt;Then the algorithm goes around again, grabbing the newest cell from the list. This time, that’s #8, and sure enough, there is an unvisited adjacent cell that we can move to:&lt;/p&gt;


&lt;table class="maze"&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n e w mark"&gt;1&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n e w mark"&gt;10&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n w mark"&gt;3&lt;/td&gt;&lt;td class="s e mark"&gt;2&lt;/td&gt;&lt;td class="n w mark"&gt;7&lt;/td&gt;&lt;td class="e mark"&gt;8&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="s w mark"&gt;4&lt;/td&gt;&lt;td class="n s mark"&gt;5&lt;/td&gt;&lt;td class="s e mark"&gt;6&lt;/td&gt;&lt;td class="s e w"&gt;9&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;

	&lt;p&gt;Did you see that?! It backtracked!&lt;/p&gt;


	&lt;p&gt;Not really. It wasn’t intentionally backtracking; it just happened that the algorithm’s choice of cell was the same one that the backtracking algorithm would have chosen. And it will continue to choose identically to the backtracker, clear up until every cell has been visited and it has to “backtrack” all the way back to the original cell. At that point, the list of cells will be empty, and the algorithm will terminate.&lt;/p&gt;


	&lt;p&gt;Pretty cool!&lt;/p&gt;


	&lt;p&gt;Take a moment and think about how the algorithm would change if, instead of choosing the newest cell each time, we chose one at random. I’ve already told you it would behave like Prim’s algorithm in this case, but can you see why? I hope so, because I’m not going to draw any more diagrams tonight. :)&lt;/p&gt;


	&lt;p&gt;Instead, you can play with the following demo, which has presets for several different cell-selection methods. Choose a few different ones and compare how they behave.&lt;/p&gt;



&amp;lt;link href="http://jamisbuck.org/mazes/css/mazes.css" /&gt;
&lt;p&gt;
Cell selection method: &amp;lt;select&gt;
&amp;lt;option&gt;Newest (Recursive Backtracker)&amp;lt;/option&gt;
&amp;lt;option&gt;Random (Prim's)&amp;lt;/option&gt;
&amp;lt;option&gt;Newest/Random, 75/25 split&amp;lt;/option&gt;
&amp;lt;option&gt;Newest/Random, 50/50 split&amp;lt;/option&gt;
&amp;lt;option&gt;Newest/Random, 25/75 split&amp;lt;/option&gt;
&amp;lt;option&gt;Oldest&amp;lt;/option&gt;
&amp;lt;option&gt;Middle&amp;lt;/option&gt;
&amp;lt;option&gt;Newest/Oldest, 50/50 split&amp;lt;/option&gt;
&amp;lt;option&gt;Oldest/Random, 50/50 split&amp;lt;/option&gt;
&amp;lt;/select&gt;
&lt;/p&gt;
&lt;div class="row"&gt;
&lt;/div&gt;


	&lt;h2&gt;Implementation&lt;/h2&gt;


	&lt;p&gt;Implementation-wise, this is one of the simplest algorithms (another reason to love it!). In fact, in my own implementation, the most complex part came from code that I added that lets you specify the cell-selection method when the script is executed!&lt;/p&gt;


	&lt;p&gt;It starts by selecting a random cell and adding it to the list:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;x, y = rand(width), rand(height)&lt;tt&gt;
&lt;/tt&gt;cells &amp;lt;&amp;lt; [x, y]&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;The program them simply loops until the list is empty:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="r"&gt;until&lt;/span&gt; cells.empty?&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="c"&gt;# ...&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;Within the loop, we first select the cell to operate on. I’m going to mask my own program’s complexity here behind a simple “choose_index” method; it takes a number and returns a number less than that.&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;index = choose_index(cells.length)&lt;tt&gt;
&lt;/tt&gt;x, y = cells[index]&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;Next, we iterate over a randomized list of directions, looking for an unvisited neighbor. If no such neighbor is found, we delete the given cell from the list before continuing.&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;[&lt;span class="co"&gt;N&lt;/span&gt;, &lt;span class="co"&gt;S&lt;/span&gt;, &lt;span class="co"&gt;E&lt;/span&gt;, &lt;span class="co"&gt;W&lt;/span&gt;].shuffle.each &lt;span class="r"&gt;do&lt;/span&gt; |dir|&lt;tt&gt;
&lt;/tt&gt;  nx, ny = x + &lt;span class="co"&gt;DX&lt;/span&gt;[dir], y + &lt;span class="co"&gt;DY&lt;/span&gt;[dir]&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;if&lt;/span&gt; nx &amp;gt;= &lt;span class="i"&gt;0&lt;/span&gt; &amp;amp;&amp;amp; ny &amp;gt;= &lt;span class="i"&gt;0&lt;/span&gt; &amp;amp;&amp;amp; nx &amp;lt; width &amp;amp;&amp;amp; ny &amp;lt; height &amp;amp;&amp;amp; grid[ny][nx] == &lt;span class="i"&gt;0&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="c"&gt;# ...&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;cells.delete_at(index) &lt;span class="r"&gt;if&lt;/span&gt; index&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;When a valid, unvisited neighbor is located, we carve a passage between the current cell and that neighbor, add the neighbor to the list, set &lt;code&gt;index&lt;/code&gt; to nil (to indicate that an unvisited neighbor was found), and then break out of the innermost loop.&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;grid[y][x] |= dir&lt;tt&gt;
&lt;/tt&gt;grid[ny][nx] |= &lt;span class="co"&gt;OPPOSITE&lt;/span&gt;[dir]&lt;tt&gt;
&lt;/tt&gt;cells &amp;lt;&amp;lt; [nx, ny]&lt;tt&gt;
&lt;/tt&gt;index = &lt;span class="pc"&gt;nil&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;break&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;And that’s really all there is to it. Some possible implementations of the &lt;code&gt;choose_index&lt;/code&gt; method might be:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="r"&gt;def&lt;/span&gt; &lt;span class="fu"&gt;choose_index&lt;/span&gt;(ceil)&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;return&lt;/span&gt; ceil&lt;span class="i"&gt;-1&lt;/span&gt; &lt;span class="r"&gt;if&lt;/span&gt; choose_newest?&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;return&lt;/span&gt; &lt;span class="i"&gt;0&lt;/span&gt; &lt;span class="r"&gt;if&lt;/span&gt; choose_oldest?&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;return&lt;/span&gt; rand(ceil) &lt;span class="r"&gt;if&lt;/span&gt; choose_random?&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="c"&gt;# or implement your own!&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;Try it out and see what new cell selection methods you discover!&lt;/p&gt;


	&lt;h2&gt;Conclusion&lt;/h2&gt;


	&lt;p&gt;Personally, I love the flexibility of this algorithm. It’s surprisingly easy&amp;mdash;and addicting!&amp;mdash;to try crazy new ideas for selecting cells, and the algorithm itself is almost trivially simple to implement. Performance-wise, the algorithm is one of the faster ones (assuming you can make removing a cell from the list reasonably fast), and while memory use is proportional to the size of the maze itself, that’s not unusual for most of these algorithms.&lt;/p&gt;


	&lt;p&gt;Seriously, what’s not to like?!&lt;/p&gt;


	&lt;p&gt;Give it a try and link to your implementations in the comments. Share your ideas for new cell selection methods, too—I’d love to see what you come up with!&lt;/p&gt;


	&lt;p&gt;For reference, the complete source of my implementation, in Ruby, is below. Remember that most of the code in my implementation is for cell selection and displaying the maze; the algorithm itself is only the tiny bit at the end!&lt;/p&gt;



&amp;lt;noscript&gt;&lt;a href="https://gist.github.com/760749"&gt;growing-tree.rb&lt;/a&gt; on gist.github.com&amp;lt;/noscript&gt;


	&lt;p&gt;Enjoy!&lt;/p&gt;
          &lt;img src="http://feeds.feedburner.com/~r/buckblog/~4/otDwINkIsuU" height="1" width="1"/&gt;</content>  </entry>
  <entry xml:base="http://weblog.jamisbuck.org/">
    <author>
      <name>Jamis</name>
    </author>
    <id>tag:weblog.jamisbuck.org,2011-01-24:8634</id>
    <published>2011-01-24T14:24:00Z</published>
    <updated>2011-01-24T14:25:04Z</updated>
    <category term="Under the Hood" />
    <category term="mazes" />
    <category term="ruby" />
    <link href="http://weblog.jamisbuck.org/2011/1/24/maze-generation-hunt-and-kill-algorithm" rel="alternate" type="text/html" />
    <title>Maze Generation: Hunt-and-Kill algorithm</title>
<summary type="html">&lt;p&gt;(Note: if you’re reading this in a feed reader, you’re going to be missing out on the illustrations and demonstrations.)&lt;/p&gt;


	&lt;p&gt;Alright, so the theme last week was “algorithms for generating uniform spanning trees.” If this week has a theme, it might be something like “algorithms that sometimes act like the &lt;a href="http://weblog.jamisbuck.org/2010/12/27/maze-generation-recursive-backtracking"&gt;recursive backtracker&lt;/a&gt;, but only kind of.”&lt;/p&gt;


	&lt;p&gt;Today’s algorithm is the “hunt-and-kill algorithm”. Sounds violent, doesn’t it? It’s actually quite tame. In a nutshell, it works like this:&lt;/p&gt;


	&lt;ol&gt;
	&lt;li&gt;Choose a starting location.&lt;/li&gt;
		&lt;li&gt;Perform a random walk, carving passages to unvisited neighbors, until the current cell has no unvisited neighbors.&lt;/li&gt;
		&lt;li&gt;Enter “hunt” mode, where you scan the grid looking for an unvisited cell that is adjacent to a visited cell. If found, carve a passage between the two and let the formerly unvisited cell be the new starting location.&lt;/li&gt;
		&lt;li&gt;Repeat steps 2 and 3 until the hunt mode scans the entire grid and finds no unvisited cells.&lt;/li&gt;
	&lt;/ol&gt;


	&lt;p&gt;Let’s walk through an example.&lt;/p&gt;</summary><content type="html">
            &lt;p&gt;(Note: if you’re reading this in a feed reader, you’re going to be missing out on the illustrations and demonstrations.)&lt;/p&gt;


	&lt;p&gt;Alright, so the theme last week was “algorithms for generating uniform spanning trees.” If this week has a theme, it might be something like “algorithms that sometimes act like the &lt;a href="http://weblog.jamisbuck.org/2010/12/27/maze-generation-recursive-backtracking"&gt;recursive backtracker&lt;/a&gt;, but only kind of.”&lt;/p&gt;


	&lt;p&gt;Today’s algorithm is the “hunt-and-kill algorithm”. Sounds violent, doesn’t it? It’s actually quite tame. In a nutshell, it works like this:&lt;/p&gt;


	&lt;ol&gt;
	&lt;li&gt;Choose a starting location.&lt;/li&gt;
		&lt;li&gt;Perform a random walk, carving passages to unvisited neighbors, until the current cell has no unvisited neighbors.&lt;/li&gt;
		&lt;li&gt;Enter “hunt” mode, where you scan the grid looking for an unvisited cell that is adjacent to a visited cell. If found, carve a passage between the two and let the formerly unvisited cell be the new starting location.&lt;/li&gt;
		&lt;li&gt;Repeat steps 2 and 3 until the hunt mode scans the entire grid and finds no unvisited cells.&lt;/li&gt;
	&lt;/ol&gt;


	&lt;p&gt;Let’s walk through an example.&lt;/p&gt;
&lt;h2&gt;An example&lt;/h2&gt;


	&lt;p&gt;I’ll just use a basic 4×4 grid:&lt;/p&gt;


&lt;table class="maze"&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;

	&lt;p&gt;Now, I’ll give you the walk phase as a sequence of frames here; it’s not that interesting, really, until it reaches a dead-end.&lt;/p&gt;


&lt;table&gt;&lt;tr&gt;&lt;td&gt;
  &lt;table class="maze"&gt;
  &lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td class="n s e w"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;&lt;td&gt;
  &lt;table class="maze"&gt;
  &lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td class="n e w"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td class="s e w"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;&lt;td&gt;
  &lt;table class="maze"&gt;
  &lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td class="n e w"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td class="e w"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td class="s e w"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/tr&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;
  &lt;table class="maze"&gt;
  &lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td class="n w"&gt;&lt;/td&gt;&lt;td class="n s e"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td class="e w"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td class="s e w"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;&lt;td&gt;
  &lt;table class="maze"&gt;
  &lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td class="n w"&gt;&lt;/td&gt;&lt;td class="n e"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td class="e w"&gt;&lt;/td&gt;&lt;td class="s e w"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td class="s e w"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;&lt;td&gt;
  &lt;table class="maze"&gt;
  &lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td class="n w"&gt;&lt;/td&gt;&lt;td class="n e"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td class="e w"&gt;&lt;/td&gt;&lt;td class="s w"&gt;&lt;/td&gt;&lt;td class="n s e"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td class="s e w"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/tr&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;
  &lt;table class="maze"&gt;
  &lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td class="n w"&gt;&lt;/td&gt;&lt;td class="n e"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td class="e w"&gt;&lt;/td&gt;&lt;td class="s w"&gt;&lt;/td&gt;&lt;td class="n e"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td class="s e w"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="s e w"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;&lt;td&gt;
  &lt;table class="maze"&gt;
  &lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td class="n w"&gt;&lt;/td&gt;&lt;td class="n e"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td class="e w"&gt;&lt;/td&gt;&lt;td class="s w"&gt;&lt;/td&gt;&lt;td class="n e"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td class="s e w"&gt;&lt;/td&gt;&lt;td class="n s w"&gt;&lt;/td&gt;&lt;td class="s e"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;&lt;td&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;

	&lt;p&gt;And there our liesurely inebriated stroll comes to a screeching halt. All possible directions lead either out of bounds, or into an already-visited neighbor. At this point, the recursive backtracker would begin backtracking, looking for a previously visited cell in the stack that had unvisited neighbors. The hunt-and-kill algorithm is not nearly so sophisticated: stuck? Go hunting.&lt;/p&gt;


	&lt;p&gt;And so we hunt. Beginning at the first row, we begin scanning each row for an unvisited cell with a visited neighbor. It turns out to be our lucky day: our very first cell is a match: unvisited, with a visited neighbor. We connect the two:&lt;/p&gt;


&lt;table class="maze"&gt;
&lt;tr&gt;&lt;td class="n e w"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="w"&gt;&lt;/td&gt;&lt;td class="n e"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="e w"&gt;&lt;/td&gt;&lt;td class="s w"&gt;&lt;/td&gt;&lt;td class="n e"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="s e w"&gt;&lt;/td&gt;&lt;td class="n s w"&gt;&lt;/td&gt;&lt;td class="s e"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;

	&lt;p&gt;And then we start a random walk from our new starting point:&lt;/p&gt;


&lt;table&gt;&lt;tr&gt;&lt;td&gt;
  &lt;table class="maze"&gt;
  &lt;tr&gt;&lt;td class="n w"&gt;&lt;/td&gt;&lt;td class="n s e"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td class="w"&gt;&lt;/td&gt;&lt;td class="n e"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td class="e w"&gt;&lt;/td&gt;&lt;td class="s w"&gt;&lt;/td&gt;&lt;td class="n e"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td class="s e w"&gt;&lt;/td&gt;&lt;td class="n s w"&gt;&lt;/td&gt;&lt;td class="s e"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;&lt;td&gt;
  &lt;table class="maze"&gt;
  &lt;tr&gt;&lt;td class="n w"&gt;&lt;/td&gt;&lt;td class="n s"&gt;&lt;/td&gt;&lt;td class="n s e"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td class="w"&gt;&lt;/td&gt;&lt;td class="n e"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td class="e w"&gt;&lt;/td&gt;&lt;td class="s w"&gt;&lt;/td&gt;&lt;td class="n e"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td class="s e w"&gt;&lt;/td&gt;&lt;td class="n s w"&gt;&lt;/td&gt;&lt;td class="s e"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;&lt;td&gt;
  &lt;table class="maze"&gt;
  &lt;tr&gt;&lt;td class="n w"&gt;&lt;/td&gt;&lt;td class="n s"&gt;&lt;/td&gt;&lt;td class="n e"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td class="w"&gt;&lt;/td&gt;&lt;td class="n e"&gt;&lt;/td&gt;&lt;td class="s e w"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td class="e w"&gt;&lt;/td&gt;&lt;td class="s w"&gt;&lt;/td&gt;&lt;td class="n e"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td class="s e w"&gt;&lt;/td&gt;&lt;td class="n s w"&gt;&lt;/td&gt;&lt;td class="s e"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;
  &lt;table class="maze"&gt;
  &lt;tr&gt;&lt;td class="n w"&gt;&lt;/td&gt;&lt;td class="n s"&gt;&lt;/td&gt;&lt;td class="n e"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td class="w"&gt;&lt;/td&gt;&lt;td class="n e"&gt;&lt;/td&gt;&lt;td class="s w"&gt;&lt;/td&gt;&lt;td class="n s e"&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td class="e w"&gt;&lt;/td&gt;&lt;td class="s w"&gt;&lt;/td&gt;&lt;td class="n e"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td class="s e w"&gt;&lt;/td&gt;&lt;td class="n s w"&gt;&lt;/td&gt;&lt;td class="s e"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;&lt;td&gt;
  &lt;table class="maze"&gt;
  &lt;tr&gt;&lt;td class="n w"&gt;&lt;/td&gt;&lt;td class="n s"&gt;&lt;/td&gt;&lt;td class="n e"&gt;&lt;/td&gt;&lt;td class="n e w"&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td class="w"&gt;&lt;/td&gt;&lt;td class="n e"&gt;&lt;/td&gt;&lt;td class="s w"&gt;&lt;/td&gt;&lt;td class="s e"&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td class="e w"&gt;&lt;/td&gt;&lt;td class="s w"&gt;&lt;/td&gt;&lt;td class="n e"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td class="s e w"&gt;&lt;/td&gt;&lt;td class="n s w"&gt;&lt;/td&gt;&lt;td class="s e"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;&lt;td&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;

	&lt;p&gt;Stuck again, so we go hunting. There are no cells in the first row that match:&lt;/p&gt;


&lt;table class="maze"&gt;
&lt;tr&gt;&lt;td class="n w h"&gt;&lt;/td&gt;&lt;td class="n s h"&gt;&lt;/td&gt;&lt;td class="n e h"&gt;&lt;/td&gt;&lt;td class="n e w h"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="w"&gt;&lt;/td&gt;&lt;td class="n e"&gt;&lt;/td&gt;&lt;td class="s w"&gt;&lt;/td&gt;&lt;td class="s e"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="e w"&gt;&lt;/td&gt;&lt;td class="s w"&gt;&lt;/td&gt;&lt;td class="n e"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="s e w"&gt;&lt;/td&gt;&lt;td class="n s w"&gt;&lt;/td&gt;&lt;td class="s e"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;

	&lt;p&gt;And no matches in the second row, either. (Remember, we’re looking for &lt;em&gt;unvisited&lt;/em&gt; cells with &lt;em&gt;visited&lt;/em&gt; neighbors.)&lt;/p&gt;


&lt;table class="maze"&gt;
&lt;tr&gt;&lt;td class="n w"&gt;&lt;/td&gt;&lt;td class="n s"&gt;&lt;/td&gt;&lt;td class="n e"&gt;&lt;/td&gt;&lt;td class="n e w"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="w h"&gt;&lt;/td&gt;&lt;td class="n e h"&gt;&lt;/td&gt;&lt;td class="s w h"&gt;&lt;/td&gt;&lt;td class="s e h"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="e w"&gt;&lt;/td&gt;&lt;td class="s w"&gt;&lt;/td&gt;&lt;td class="n e"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="s e w"&gt;&lt;/td&gt;&lt;td class="n s w"&gt;&lt;/td&gt;&lt;td class="s e"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;

	&lt;p&gt;The third row, however, has a match in its last cell:&lt;/p&gt;


&lt;table class="maze"&gt;
&lt;tr&gt;&lt;td class="n w"&gt;&lt;/td&gt;&lt;td class="n s"&gt;&lt;/td&gt;&lt;td class="n e"&gt;&lt;/td&gt;&lt;td class="n e w"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="w"&gt;&lt;/td&gt;&lt;td class="n e"&gt;&lt;/td&gt;&lt;td class="s w"&gt;&lt;/td&gt;&lt;td class="s e"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="e w h"&gt;&lt;/td&gt;&lt;td class="s w h"&gt;&lt;/td&gt;&lt;td class="n e h"&gt;&lt;/td&gt;&lt;td class="n s e w out h"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="s e w"&gt;&lt;/td&gt;&lt;td class="n s w"&gt;&lt;/td&gt;&lt;td class="s e"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;

	&lt;p&gt;So, we connect that unvisited cell to any one of its visited neighbors (at random), and do our random walk:&lt;/p&gt;


&lt;table&gt;&lt;tr&gt;&lt;td&gt;
  &lt;table class="maze"&gt;
  &lt;tr&gt;&lt;td class="n w"&gt;&lt;/td&gt;&lt;td class="n s"&gt;&lt;/td&gt;&lt;td class="n e"&gt;&lt;/td&gt;&lt;td class="n e w"&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td class="w"&gt;&lt;/td&gt;&lt;td class="n e"&gt;&lt;/td&gt;&lt;td class="s w"&gt;&lt;/td&gt;&lt;td class="s e"&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td class="e w"&gt;&lt;/td&gt;&lt;td class="s w"&gt;&lt;/td&gt;&lt;td class="n"&gt;&lt;/td&gt;&lt;td class="n s e"&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td class="s e w"&gt;&lt;/td&gt;&lt;td class="n s w"&gt;&lt;/td&gt;&lt;td class="s e"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;&lt;td&gt;
  &lt;table class="maze"&gt;
  &lt;tr&gt;&lt;td class="n w"&gt;&lt;/td&gt;&lt;td class="n s"&gt;&lt;/td&gt;&lt;td class="n e"&gt;&lt;/td&gt;&lt;td class="n e w"&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td class="w"&gt;&lt;/td&gt;&lt;td class="n e"&gt;&lt;/td&gt;&lt;td class="s w"&gt;&lt;/td&gt;&lt;td class="s e"&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td class="e w"&gt;&lt;/td&gt;&lt;td class="s w"&gt;&lt;/td&gt;&lt;td class="n"&gt;&lt;/td&gt;&lt;td class="n e"&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td class="s e w"&gt;&lt;/td&gt;&lt;td class="n s w"&gt;&lt;/td&gt;&lt;td class="s e"&gt;&lt;/td&gt;&lt;td class="s e w"&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;&lt;td&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;

	&lt;p&gt;And we again stub our digital toes (see what I did there?) on another dead-end. We’re stuck, so we go hunting again, looking row-by-row for an unvisited cell.&lt;/p&gt;


&lt;table&gt;&lt;tr&gt;&lt;td&gt;
  &lt;table class="maze"&gt;
  &lt;tr&gt;&lt;td class="n w h"&gt;&lt;/td&gt;&lt;td class="n s h"&gt;&lt;/td&gt;&lt;td class="n e h"&gt;&lt;/td&gt;&lt;td class="n e w h"&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td class="w"&gt;&lt;/td&gt;&lt;td class="n e"&gt;&lt;/td&gt;&lt;td class="s w"&gt;&lt;/td&gt;&lt;td class="s e"&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td class="e w"&gt;&lt;/td&gt;&lt;td class="s w"&gt;&lt;/td&gt;&lt;td class="n"&gt;&lt;/td&gt;&lt;td class="n e"&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td class="s e w"&gt;&lt;/td&gt;&lt;td class="n s w"&gt;&lt;/td&gt;&lt;td class="s e"&gt;&lt;/td&gt;&lt;td class="s e w"&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;&lt;td&gt;
  &lt;table class="maze"&gt;
  &lt;tr&gt;&lt;td class="n w"&gt;&lt;/td&gt;&lt;td class="n s"&gt;&lt;/td&gt;&lt;td class="n e"&gt;&lt;/td&gt;&lt;td class="n e w"&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td class="w h"&gt;&lt;/td&gt;&lt;td class="n e h"&gt;&lt;/td&gt;&lt;td class="s w h"&gt;&lt;/td&gt;&lt;td class="s e h"&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td class="e w"&gt;&lt;/td&gt;&lt;td class="s w"&gt;&lt;/td&gt;&lt;td class="n"&gt;&lt;/td&gt;&lt;td class="n e"&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td class="s e w"&gt;&lt;/td&gt;&lt;td class="n s w"&gt;&lt;/td&gt;&lt;td class="s e"&gt;&lt;/td&gt;&lt;td class="s e w"&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;&lt;td&gt;
  &lt;table class="maze"&gt;
  &lt;tr&gt;&lt;td class="n w"&gt;&lt;/td&gt;&lt;td class="n s"&gt;&lt;/td&gt;&lt;td class="n e"&gt;&lt;/td&gt;&lt;td class="n e w"&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td class="w"&gt;&lt;/td&gt;&lt;td class="n e"&gt;&lt;/td&gt;&lt;td class="s w"&gt;&lt;/td&gt;&lt;td class="s e"&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td class="e w h"&gt;&lt;/td&gt;&lt;td class="s w h"&gt;&lt;/td&gt;&lt;td class="n h"&gt;&lt;/td&gt;&lt;td class="n e h"&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td class="s e w"&gt;&lt;/td&gt;&lt;td class="n s w"&gt;&lt;/td&gt;&lt;td class="s e"&gt;&lt;/td&gt;&lt;td class="s e w"&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;
  &lt;table class="maze"&gt;
  &lt;tr&gt;&lt;td class="n w"&gt;&lt;/td&gt;&lt;td class="n s"&gt;&lt;/td&gt;&lt;td class="n e"&gt;&lt;/td&gt;&lt;td class="n e w"&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td class="w"&gt;&lt;/td&gt;&lt;td class="n e"&gt;&lt;/td&gt;&lt;td class="s w"&gt;&lt;/td&gt;&lt;td class="s e"&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td class="e w"&gt;&lt;/td&gt;&lt;td class="s w"&gt;&lt;/td&gt;&lt;td class="n"&gt;&lt;/td&gt;&lt;td class="n e"&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td class="s e w h"&gt;&lt;/td&gt;&lt;td class="n s w h"&gt;&lt;/td&gt;&lt;td class="s e h"&gt;&lt;/td&gt;&lt;td class="s e w h"&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;&lt;td&gt;
  &lt;table class="maze"&gt;
  &lt;tr&gt;&lt;td class="n w"&gt;&lt;/td&gt;&lt;td class="n s"&gt;&lt;/td&gt;&lt;td class="n e"&gt;&lt;/td&gt;&lt;td class="n e w"&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td class="w"&gt;&lt;/td&gt;&lt;td class="n e"&gt;&lt;/td&gt;&lt;td class="s w"&gt;&lt;/td&gt;&lt;td class="s e"&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td class="e w"&gt;&lt;/td&gt;&lt;td class="s w"&gt;&lt;/td&gt;&lt;td class="n"&gt;&lt;/td&gt;&lt;td class="n e"&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td class="s e w"&gt;&lt;/td&gt;&lt;td class="n s w"&gt;&lt;/td&gt;&lt;td class="s e"&gt;&lt;/td&gt;&lt;td class="s e w"&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;&lt;td&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;

	&lt;p&gt;The scan completed without finding any unvisited cells, so the algorithm terminates and leaves us with our maze.&lt;/p&gt;


	&lt;p&gt;Try the following demonstrations to see how the algorithm behaves at larger resolutions:&lt;/p&gt;



&amp;lt;link href="http://jamisbuck.org/mazes/css/mazes.css" /&gt;
&lt;div class="row"&gt;
&lt;/div&gt;


	&lt;h2&gt;Implementation&lt;/h2&gt;


	&lt;p&gt;This algorithm is pretty straightforward to implement. It even has a few simple optimizations that you can do, though I won’t touch on those here.&lt;/p&gt;


	&lt;p&gt;My implementation begins by choosing a random starting point, and then looping over the two phases, “walk” and “hunt”, until the hunt phase terminates without finding any new location. My walk and hunt implementations both return either a two-element array (indicating the coordinates of the next starting location), or a nil (indicating that the phase in question has terminated).&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;x, y = rand(width), rand(height)&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;loop &lt;span class="r"&gt;do&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  x, y = walk(grid, x, y)&lt;tt&gt;
&lt;/tt&gt;  x, y = hunt(grid) &lt;span class="r"&gt;unless&lt;/span&gt; x&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;break&lt;/span&gt; &lt;span class="r"&gt;unless&lt;/span&gt; x&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;The walk implementation is straightforward. It just iterates over a randomized list of directions, and returns nil if none of the directions are valid:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="r"&gt;def&lt;/span&gt; &lt;span class="fu"&gt;walk&lt;/span&gt;(grid, x, y)&lt;tt&gt;
&lt;/tt&gt;  [&lt;span class="co"&gt;N&lt;/span&gt;, &lt;span class="co"&gt;S&lt;/span&gt;, &lt;span class="co"&gt;E&lt;/span&gt;, &lt;span class="co"&gt;W&lt;/span&gt;].shuffle.each &lt;span class="r"&gt;do&lt;/span&gt; |dir|&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="c"&gt;# ...&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="pc"&gt;nil&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;For each direction, it computes the neighbor in that direction, and then tests it to see if it is within the bounds of the maze and unvisited:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;nx, ny = x + &lt;span class="co"&gt;DX&lt;/span&gt;[dir], y + &lt;span class="co"&gt;DY&lt;/span&gt;[dir]&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;if&lt;/span&gt; nx &amp;gt;= &lt;span class="i"&gt;0&lt;/span&gt; &amp;amp;&amp;amp; ny &amp;gt;= &lt;span class="i"&gt;0&lt;/span&gt; &amp;amp;&amp;amp; ny &amp;lt; grid.length &amp;amp;&amp;amp; nx &amp;lt; grid[ny].length &amp;amp;&amp;amp; grid[ny][nx] == &lt;span class="i"&gt;0&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="c"&gt;# ..&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;When a neighbor is found that fits the bill, the neighbor and the current cell are connected, and the neighbor is returned as the new current cell:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;grid[y][x] |= dir&lt;tt&gt;
&lt;/tt&gt;grid[ny][nx] |= &lt;span class="co"&gt;OPPOSITE&lt;/span&gt;[dir]&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;return&lt;/span&gt; [nx, ny]&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;The hunt phase, on the other hand, is a little more involved (but not much). It iterates over each cell in the grid, row-wise, skipping visited cells, and returning nil if it does not find any unvisited cellls:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="r"&gt;def&lt;/span&gt; &lt;span class="fu"&gt;hunt&lt;/span&gt;(grid)&lt;tt&gt;
&lt;/tt&gt;  grid.each_with_index &lt;span class="r"&gt;do&lt;/span&gt; |row, y|&lt;tt&gt;
&lt;/tt&gt;    row.each_with_index &lt;span class="r"&gt;do&lt;/span&gt; |cell, x|&lt;tt&gt;
&lt;/tt&gt;      &lt;span class="r"&gt;next&lt;/span&gt; &lt;span class="r"&gt;unless&lt;/span&gt; cell == &lt;span class="i"&gt;0&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;      &lt;span class="c"&gt;# ...&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="pc"&gt;nil&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;Within that innermost loop, if the cell is unvisited, we compute a list of neighbors that are already part of the maze:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;neighbors = []&lt;tt&gt;
&lt;/tt&gt;neighbors &amp;lt;&amp;lt; &lt;span class="co"&gt;N&lt;/span&gt; &lt;span class="r"&gt;if&lt;/span&gt; y &amp;gt; &lt;span class="i"&gt;0&lt;/span&gt; &amp;amp;&amp;amp; grid[y&lt;span class="i"&gt;-1&lt;/span&gt;][x] != &lt;span class="i"&gt;0&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;neighbors &amp;lt;&amp;lt; &lt;span class="co"&gt;W&lt;/span&gt; &lt;span class="r"&gt;if&lt;/span&gt; x &amp;gt; &lt;span class="i"&gt;0&lt;/span&gt; &amp;amp;&amp;amp; grid[y][x&lt;span class="i"&gt;-1&lt;/span&gt;] != &lt;span class="i"&gt;0&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;neighbors &amp;lt;&amp;lt; &lt;span class="co"&gt;E&lt;/span&gt; &lt;span class="r"&gt;if&lt;/span&gt; x&lt;span class="i"&gt;+1&lt;/span&gt; &amp;lt; grid[y].length &amp;amp;&amp;amp; grid[y][x&lt;span class="i"&gt;+1&lt;/span&gt;] != &lt;span class="i"&gt;0&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;neighbors &amp;lt;&amp;lt; &lt;span class="co"&gt;S&lt;/span&gt; &lt;span class="r"&gt;if&lt;/span&gt; y&lt;span class="i"&gt;+1&lt;/span&gt; &amp;lt; grid.length &amp;amp;&amp;amp; grid[y&lt;span class="i"&gt;+1&lt;/span&gt;][x] != &lt;span class="i"&gt;0&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;Then, we randomly choose one of them (skipping to the next cell if there are no neighbors to select):&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;direction = neighbors[rand(neighbors.length)] &lt;span class="r"&gt;or&lt;/span&gt; &lt;span class="r"&gt;next&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;Then, we compute the coordinates of the neighbor in the chosen direction, carve a passage to it, and then return the new current coordinates:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;nx, ny = x + &lt;span class="co"&gt;DX&lt;/span&gt;[direction], y + &lt;span class="co"&gt;DY&lt;/span&gt;[direction]&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;grid[y][x] |= direction&lt;tt&gt;
&lt;/tt&gt;grid[ny][nx] |= &lt;span class="co"&gt;OPPOSITE&lt;/span&gt;[direction]&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;return&lt;/span&gt; [x, y]&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;And there’s your hunt-and-kill algorithm!&lt;/p&gt;


	&lt;h2&gt;Conclusion&lt;/h2&gt;


	&lt;p&gt;The random walk phase tends to produce long, windy passages that are reminiscent of the recursive backtracking algorithm, so if you like the aesthetic of one, you’ll probably enjoy the other, too. Both algorithms produce mazes with fewer dead-ends than most of the other algorithms.&lt;/p&gt;


	&lt;p&gt;The hunt-and-kill algorithm will always have a place in my heart, because it was a variation on it that introduced me to maze generation back in high school. It was first shown to me by &lt;a href="http://twitter.com/#!/stefanomaz"&gt;Stefano Mazzocchi&lt;/a&gt; when he was an exchange student at my alma mater (Siuslaw High School, in tiny Florence, Oregon). In fact, it was this variation on the hunt-and-kill that I used when I wrote a (somewhat popular) random dungeon generator for D&amp;D back in 2001! (All that remains now is some &lt;a href="https://github.com/jamis/dnd-dungeon"&gt;C source code on GitHub&lt;/a&gt;, alas.)&lt;/p&gt;


	&lt;p&gt;Anyway, enough nostalgic wallowing. Have a go at the hunt-and-kill algorithm, and share links to your creations in the comments. For reference, the complete source for my own implementation is here:&lt;/p&gt;



&amp;lt;noscript&gt;&lt;a href="https://gist.github.com/760739"&gt;hunt-and-kill.rb&lt;/a&gt; on gist.github.com&amp;lt;/noscript&gt;


	&lt;p&gt;Enjoy!&lt;/p&gt;
          &lt;img src="http://feeds.feedburner.com/~r/buckblog/~4/hGSK1ck98AU" height="1" width="1"/&gt;</content>  </entry>
  <entry xml:base="http://weblog.jamisbuck.org/">
    <author>
      <name>Jamis</name>
    </author>
    <id>tag:weblog.jamisbuck.org,2011-01-20:8615</id>
    <published>2011-01-20T14:15:00Z</published>
    <updated>2011-01-20T14:21:39Z</updated>
    <category term="Under the Hood" />
    <category term="mazes" />
    <category term="ruby" />
    <link href="http://weblog.jamisbuck.org/2011/1/20/maze-generation-wilson-s-algorithm" rel="alternate" type="text/html" />
    <title>Maze Generation: Wilson's algorithm</title>
<summary type="html">&lt;p&gt;The last algorithm I mentioned, &lt;a href="http://weblog.jamisbuck.org/2011/1/17/maze-generation-aldous-broder-algorithm"&gt;Aldous-Broder&lt;/a&gt;, was (if you’ll recall) originally devised as a way to generate &lt;em&gt;uniform spanning trees&lt;/em&gt; (UST). (Review: a &lt;em&gt;spanning tree&lt;/em&gt; is a tree that connects all the vertices of a graph. A &lt;em&gt;uniform&lt;/em&gt; spanning tree is any one of the possible spanning trees of a graph, selected randomly and with equal probability.)&lt;/p&gt;


	&lt;p&gt;Aldous-Broder was effective, but inefficient. For this (the seventh!) article in my series on maze algorithms, I’ll focus on Wilson’s algorithm for selecting uniform spanning trees.&lt;/p&gt;


	&lt;p&gt;The algorithm goes something like this:&lt;/p&gt;


	&lt;ol&gt;
	&lt;li&gt;Choose any vertex at random and add it to the &lt;span class="caps"&gt;UST&lt;/span&gt;.&lt;/li&gt;
		&lt;li&gt;Select any vertex that is not already in the &lt;span class="caps"&gt;UST&lt;/span&gt; and perform a random walk until you encounter a vertex that is in the &lt;span class="caps"&gt;UST&lt;/span&gt;.&lt;/li&gt;
		&lt;li&gt;Add the vertices and edges touched in the random walk to the &lt;span class="caps"&gt;UST&lt;/span&gt;.&lt;/li&gt;
		&lt;li&gt;Repeat 2 and 3 until all vertices have been added to the &lt;span class="caps"&gt;UST&lt;/span&gt;.&lt;/li&gt;
	&lt;/ol&gt;


	&lt;p&gt;So, it’s still doing the random walk, but I think you’ll see that this algorithm converges much more rapidly than Aldous-Broder. It’s still annoying to watch an animation of the early stages of the process, but not nearly as bad as the other.&lt;/p&gt;


	&lt;p&gt;As before, here’s a simple example of the algorithm in action.&lt;/p&gt;</summary><content type="html">
            &lt;p&gt;The last algorithm I mentioned, &lt;a href="http://weblog.jamisbuck.org/2011/1/17/maze-generation-aldous-broder-algorithm"&gt;Aldous-Broder&lt;/a&gt;, was (if you’ll recall) originally devised as a way to generate &lt;em&gt;uniform spanning trees&lt;/em&gt; (UST). (Review: a &lt;em&gt;spanning tree&lt;/em&gt; is a tree that connects all the vertices of a graph. A &lt;em&gt;uniform&lt;/em&gt; spanning tree is any one of the possible spanning trees of a graph, selected randomly and with equal probability.)&lt;/p&gt;


	&lt;p&gt;Aldous-Broder was effective, but inefficient. For this (the seventh!) article in my series on maze algorithms, I’ll focus on Wilson’s algorithm for selecting uniform spanning trees.&lt;/p&gt;


	&lt;p&gt;The algorithm goes something like this:&lt;/p&gt;


	&lt;ol&gt;
	&lt;li&gt;Choose any vertex at random and add it to the &lt;span class="caps"&gt;UST&lt;/span&gt;.&lt;/li&gt;
		&lt;li&gt;Select any vertex that is not already in the &lt;span class="caps"&gt;UST&lt;/span&gt; and perform a random walk until you encounter a vertex that is in the &lt;span class="caps"&gt;UST&lt;/span&gt;.&lt;/li&gt;
		&lt;li&gt;Add the vertices and edges touched in the random walk to the &lt;span class="caps"&gt;UST&lt;/span&gt;.&lt;/li&gt;
		&lt;li&gt;Repeat 2 and 3 until all vertices have been added to the &lt;span class="caps"&gt;UST&lt;/span&gt;.&lt;/li&gt;
	&lt;/ol&gt;


	&lt;p&gt;So, it’s still doing the random walk, but I think you’ll see that this algorithm converges much more rapidly than Aldous-Broder. It’s still annoying to watch an animation of the early stages of the process, but not nearly as bad as the other.&lt;/p&gt;


	&lt;p&gt;As before, here’s a simple example of the algorithm in action.&lt;/p&gt;
&lt;h2&gt;An example&lt;/h2&gt;


	&lt;p&gt;A 4×4 grid will suffice for this demo.&lt;/p&gt;


&lt;table class="maze"&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;

	&lt;p&gt;We begin by randomly adding a cell to the maze:&lt;/p&gt;


&lt;table class="maze"&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;

	&lt;p&gt;Then, we pick another unvisited cell at random and do a random walk until we encounter that first cell. Note that this random walk has a few constraints: although it can cross cells it has already walked (as long as they are not already in the maze), we don’t want to allow the final path to have any loops in it. Thus, we also record the direction most recently used to exit each cell, and will use those directions to form the final path once the walk encounters an “in” cell.&lt;/p&gt;


&lt;table&gt;&lt;tr&gt;&lt;td&gt;
&lt;table class="maze"&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w h"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;/td&gt;&lt;td&gt;
&lt;table class="maze"&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w h"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w mark"&gt;&amp;uarr;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;/td&gt;&lt;td&gt;
&lt;table class="maze"&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s e w h"&gt;&lt;/td&gt;&lt;td class="n s e w mark"&gt;&amp;larr;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w mark"&gt;&amp;uarr;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;
&lt;table class="maze"&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s e w h"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s e w mark"&gt;&amp;uarr;&lt;/td&gt;&lt;td class="n s e w mark"&gt;&amp;larr;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w mark"&gt;&amp;uarr;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;/td&gt;&lt;td&gt;
&lt;table class="maze"&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s e w mark"&gt;&amp;rarr;&lt;/td&gt;&lt;td class="n s e w h"&gt;&lt;/td&gt;&lt;td class="n s e w"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s e w mark"&gt;&amp;uarr;&lt;/td&gt;&lt;td class="n s e w mark"&gt;&amp;larr;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w mark"&gt;&amp;uarr;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;/td&gt;&lt;td&gt;
&lt;table class="maze"&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s e w mark"&gt;&amp;rarr;&lt;/td&gt;&lt;td class="n s e w mark"&gt;&amp;darr;&lt;/td&gt;&lt;td class="n s e w"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s e w mark"&gt;&amp;uarr;&lt;/td&gt;&lt;td class="n s e w h"&gt;&amp;larr;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w mark"&gt;&amp;uarr;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;
&lt;table class="maze"&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s e w mark"&gt;&amp;rarr;&lt;/td&gt;&lt;td class="n s e w mark"&gt;&amp;darr;&lt;/td&gt;&lt;td class="n s e w"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s e w mark"&gt;&amp;uarr;&lt;/td&gt;&lt;td class="n s e w mark"&gt;&amp;rarr;&lt;/td&gt;&lt;td class="n s e w h"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w mark"&gt;&amp;uarr;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;/td&gt;&lt;td&gt;
&lt;table class="maze"&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s e w mark"&gt;&amp;rarr;&lt;/td&gt;&lt;td class="n s e w mark"&gt;&amp;darr;&lt;/td&gt;&lt;td class="n s e w h"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s e w mark"&gt;&amp;uarr;&lt;/td&gt;&lt;td class="n s e w mark"&gt;&amp;rarr;&lt;/td&gt;&lt;td class="n s e w mark"&gt;&amp;uarr;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w mark"&gt;&amp;uarr;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;/td&gt;&lt;td&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;

	&lt;p&gt;Once we reach a cell that is already part of the maze, the walk terminates. The next phase simply goes back to the cell at the beginning of the walk, and follows the arrows, adding vertices and edges to the maze as we go, until we reach the final cell of the walk.&lt;/p&gt;


&lt;table class="maze"&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s e w mark"&gt;&amp;rarr;&lt;/td&gt;&lt;td class="n s e w mark"&gt;&amp;darr;&lt;/td&gt;&lt;td class="n e w"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s e w mark"&gt;&amp;uarr;&lt;/td&gt;&lt;td class="n w"&gt;&lt;/td&gt;&lt;td class="s e"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="s e w"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;

	&lt;p&gt;All the other cells that were visited during the walk, but which did not make the “final cut”, as it were, are simply reset to “out”.&lt;/p&gt;


&lt;table class="maze"&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n e w"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n w"&gt;&lt;/td&gt;&lt;td class="s e"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="s e w"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;

	&lt;p&gt;Now, we do it again. Notice that this time there are four cells in the maze, rather than just one, giving us many more targets for the walk to hit. This is what lets the algorithm converge more rapidly than Aldous-Broder: each pass through the algorithm increases the odds that the next pass will terminate sooner.&lt;/p&gt;


	&lt;p&gt;Here we go, another pass. I’m going to “cheat” and let this one consume more cells than it might (probabalistically) do otherwise. Just to keep the article shorter. :)&lt;/p&gt;


&lt;table&gt;&lt;tr&gt;&lt;td&gt;
&lt;table class="maze"&gt;
&lt;tr&gt;&lt;td class="n s e w h"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n e w"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n w"&gt;&lt;/td&gt;&lt;td class="s e"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="s e w"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;/td&gt;&lt;td&gt;
&lt;table class="maze"&gt;
&lt;tr&gt;&lt;td class="n s e w mark"&gt;&amp;rarr;&lt;/td&gt;&lt;td class="n s e w h"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n e w"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n w"&gt;&lt;/td&gt;&lt;td class="s e"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="s e w"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;/td&gt;&lt;td&gt;
&lt;table class="maze"&gt;
&lt;tr&gt;&lt;td class="n s e w mark"&gt;&amp;rarr;&lt;/td&gt;&lt;td class="n s e w mark"&gt;&amp;darr;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w h"&gt;&lt;/td&gt;&lt;td class="n e w"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n w"&gt;&lt;/td&gt;&lt;td class="s e"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="s e w"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;
&lt;table class="maze"&gt;
&lt;tr&gt;&lt;td class="n s e w mark"&gt;&amp;rarr;&lt;/td&gt;&lt;td class="n s e w mark"&gt;&amp;darr;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s e w h"&gt;&lt;/td&gt;&lt;td class="n s e w mark"&gt;&amp;larr;&lt;/td&gt;&lt;td class="n e w"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n w"&gt;&lt;/td&gt;&lt;td class="s e"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="s e w"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;/td&gt;&lt;td&gt;
&lt;table class="maze"&gt;
&lt;tr&gt;&lt;td class="n s e w mark"&gt;&amp;rarr;&lt;/td&gt;&lt;td class="n s e w mark"&gt;&amp;darr;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s e w mark"&gt;&amp;darr;&lt;/td&gt;&lt;td class="n s e w mark"&gt;&amp;larr;&lt;/td&gt;&lt;td class="n e w"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s e w h"&gt;&lt;/td&gt;&lt;td class="n w"&gt;&lt;/td&gt;&lt;td class="s e"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="s e w"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;/td&gt;&lt;td&gt;
&lt;table class="maze"&gt;
&lt;tr&gt;&lt;td class="n s e w mark"&gt;&amp;rarr;&lt;/td&gt;&lt;td class="n s e w mark"&gt;&amp;darr;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s e w mark"&gt;&amp;darr;&lt;/td&gt;&lt;td class="n s e w mark"&gt;&amp;larr;&lt;/td&gt;&lt;td class="n e w"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s e w mark"&gt;&amp;rarr;&lt;/td&gt;&lt;td class="n w h"&gt;&lt;/td&gt;&lt;td class="s e"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="s e w"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;

	&lt;p&gt;Then we walk the path and add the vertices and edges to the maze, again:&lt;/p&gt;


&lt;table class="maze"&gt;
&lt;tr&gt;&lt;td class="n s w"&gt;&lt;/td&gt;&lt;td class="n e"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n w"&gt;&lt;/td&gt;&lt;td class="s e"&gt;&lt;/td&gt;&lt;td class="n e w"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="s w"&gt;&lt;/td&gt;&lt;td class="n"&gt;&lt;/td&gt;&lt;td class="s e"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="s e w"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;

	&lt;p&gt;By now you should be able to see the pattern emerging. Each pass would add another random “branch” to the tree, proceeding until all cells have been added to the maze.&lt;/p&gt;


	&lt;p&gt;Try the following demos if you’d like to see an animation of the algorithm in action, or step through it more carefully:&lt;/p&gt;



&amp;lt;link href="http://jamisbuck.org/mazes/css/mazes.css" /&gt;
&lt;div class="row"&gt;
&lt;/div&gt;


	&lt;h2&gt;Implementation&lt;/h2&gt;


	&lt;p&gt;Personally, I found Wilson’s algorithm to be one of the messiest to implement, mostly due to the necessity of keeping track of directions while doing the random walk. I’m sure there are cleaner ways to implement this. Yes, that is a challenge! (Admittedly, some of the complexity of my implementation is due to it trying to animate the algorithm; feel free to simplify your own attempt.)&lt;/p&gt;


	&lt;p&gt;The algorithm begins by setting a random cell as “in”, and recording how many cells still remain outside:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;grid[rand(height)][rand(width)] = &lt;span class="co"&gt;IN&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;remaining = width * height - &lt;span class="i"&gt;1&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;Then, I simply loop until there are no more cells that are outside the maze:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="r"&gt;while&lt;/span&gt; remaining &amp;gt; &lt;span class="i"&gt;0&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="c"&gt;# ...&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;Within the loop, the random walk is performed. For now, I’m going to wave my hands and we’ll move on, but I’ll describe the &lt;code&gt;walk&lt;/code&gt; method more closely in a bit. It returns the path that was taken as an array of (x, y, direction) tuples:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;walk(grid).each &lt;span class="r"&gt;do&lt;/span&gt; |x, y, dir|&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="c"&gt;# ...&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;For each cell in the random walk, we add it to the maze (by applying the given direction bit to each cell in the path), and then decrement the number of remaining cells:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;nx, ny = x + &lt;span class="co"&gt;DX&lt;/span&gt;[dir], y + &lt;span class="co"&gt;DY&lt;/span&gt;[dir]&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;grid[y][x] |= dir&lt;tt&gt;
&lt;/tt&gt;grid[ny][nx] |= &lt;span class="co"&gt;OPPOSITE&lt;/span&gt;[dir]&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;remaining -= &lt;span class="i"&gt;1&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;Now, the &lt;code&gt;walk&lt;/code&gt; method itself is the messy bit. It begins by looping until a random cell is selected that is not in the maze:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="r"&gt;def&lt;/span&gt; &lt;span class="fu"&gt;walk&lt;/span&gt;(grid)&lt;tt&gt;
&lt;/tt&gt;  loop &lt;span class="r"&gt;do&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    cx, cy = rand(grid[&lt;span class="i"&gt;0&lt;/span&gt;].length), rand(grid.length)&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="r"&gt;next&lt;/span&gt; &lt;span class="r"&gt;if&lt;/span&gt; grid[cy][cx] != &lt;span class="i"&gt;0&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="c"&gt;# ...&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;Once a starting point is found, I initialize a hash of visited cells (where I will record both the coordinates of each cell in the walk, as well as the direction last used to exit the cell). And then I start walking:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;visits = { [cx, cy] =&amp;gt; &lt;span class="i"&gt;0&lt;/span&gt; }&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;start_x, start_y = cx, cy &lt;span class="c"&gt;# where the random walk started&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;walking = &lt;span class="pc"&gt;true&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;while&lt;/span&gt; walking&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="c"&gt;# ...&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;Now, inside the walking loop, I first set &lt;code&gt;walking&lt;/code&gt; to false (since I’m going to be optimistic and assume that the next move will hit an “in” cell). Then, I look at a randomized list of directions:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;walking = &lt;span class="pc"&gt;false&lt;/span&gt; &lt;span class="c"&gt;# cross fingers!&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;[&lt;span class="co"&gt;N&lt;/span&gt;,&lt;span class="co"&gt;S&lt;/span&gt;,&lt;span class="co"&gt;E&lt;/span&gt;,&lt;span class="co"&gt;W&lt;/span&gt;].shuffle.each &lt;span class="r"&gt;do&lt;/span&gt; |dir|&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="c"&gt;# ...&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;For each direction in the randomized list, we’ll compute the neighbor in that direction and then check that the neighbor is actually a valid cell (within the boundaries of the grid):&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;nx, ny = cx + &lt;span class="co"&gt;DX&lt;/span&gt;[dir], cy + &lt;span class="co"&gt;DY&lt;/span&gt;[dir]&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;if&lt;/span&gt; nx &amp;gt;= &lt;span class="i"&gt;0&lt;/span&gt; &amp;amp;&amp;amp; ny &amp;gt;= &lt;span class="i"&gt;0&lt;/span&gt; &amp;amp;&amp;amp; ny &amp;lt; grid.length &amp;amp;&amp;amp; nx &amp;lt; grid[ny].length&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="c"&gt;# ...&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;Once a valid neighbor is found, we immediately record that direction as the exit vector from the current cell.&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;visits[[cx, cy]] = dir&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;Then, if the neighbor cell is already in the maze, we get to break out of the loop (because we’ve finished the walk). Otherwise, we set the neighbor to be our current cell, and we continue walking:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="r"&gt;if&lt;/span&gt; grid[ny][nx] != &lt;span class="i"&gt;0&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;break&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;else&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  cx, cy = nx, ny&lt;tt&gt;
&lt;/tt&gt;  walking = &lt;span class="pc"&gt;true&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;break&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;Once we’re done walking, we still need to convert the &lt;code&gt;visits&lt;/code&gt; hash to a valid path, which we’ll return. I do this by following the visits from the start cell, through the direction used to exit visited cell, until the path ends:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;path = []&lt;tt&gt;
&lt;/tt&gt;x, y = start_x, start_y&lt;tt&gt;
&lt;/tt&gt;loop &lt;span class="r"&gt;do&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  dir = visits[[x, y]] &lt;span class="r"&gt;or&lt;/span&gt; &lt;span class="r"&gt;break&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  path &amp;lt;&amp;lt; [x, y, dir]&lt;tt&gt;
&lt;/tt&gt;  x, y = x + &lt;span class="co"&gt;DX&lt;/span&gt;[dir], y + &lt;span class="co"&gt;DY&lt;/span&gt;[dir]&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;Finally, we return the path, which the top-level loop uses to add the cells to the maze:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="r"&gt;return&lt;/span&gt; path&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;Whew!&lt;/p&gt;


	&lt;h2&gt;Conclusion&lt;/h2&gt;


	&lt;p&gt;Wilson’s is still not a very efficient algorithm: on large grids, the first walk can be excruciatingly slow. However, it’s much nicer than Aldous-Broder, and is still guaranteed to return a uniform spanning tree.&lt;/p&gt;


	&lt;p&gt;I’m sure any of you could do a better job implementing this than I’ve presented here. In fact, I’d love for you to prove it. :) Give it a try and link to your implementations in the comments!&lt;/p&gt;


	&lt;p&gt;For reference, the complete source for my own (Ruby) implementation is here:&lt;/p&gt;



&amp;lt;noscript&gt;&lt;a href="https://gist.github.com/760704"&gt;wilsons.rb&lt;/a&gt; on gist.github.com&amp;lt;/noscript&gt;


	&lt;p&gt;Enjoy!&lt;/p&gt;
          &lt;img src="http://feeds.feedburner.com/~r/buckblog/~4/wt0eBipxXXs" height="1" width="1"/&gt;</content>  </entry>
  <entry xml:base="http://weblog.jamisbuck.org/">
    <author>
      <name>Jamis</name>
    </author>
    <id>tag:weblog.jamisbuck.org,2011-01-17:8603</id>
    <published>2011-01-17T14:33:00Z</published>
    <updated>2011-01-17T14:35:41Z</updated>
    <category term="Under the Hood" />
    <category term="mazes" />
    <category term="ruby" />
    <link href="http://weblog.jamisbuck.org/2011/1/17/maze-generation-aldous-broder-algorithm" rel="alternate" type="text/html" />
    <title>Maze Generation: Aldous-Broder algorithm</title>
<summary type="html">&lt;p&gt;The next maze algorithm I’m going to cover, the Aldous-Broder algorithm, is one of the simplest imaginable. It’s also one of the least efficient. In fact, it is so inefficient that you might wonder why anyone would even bother implementing it, let alone discovering it and having their name attached to it.&lt;/p&gt;


	&lt;p&gt;D. Aldous and A. Broder were two researchers, working independently, who were investigating &lt;em&gt;uniform spanning trees&lt;/em&gt;. A spanning tree, as you may or may not already know, is any tree that connects all the vertexes in a graph. A &lt;em&gt;uniform&lt;/em&gt; spanning tree is one chosen randomly (and with equal probability) among all the possible spanning trees of a given graph.&lt;/p&gt;


	&lt;p&gt;Riveting, isn’t it?&lt;/p&gt;


	&lt;p&gt;There are actually applications for this. Outside of recreational maze generation, I mean. I don’t know what they are myself, but Wikipedia informs me that they are in probability and mathematical physics. (If you know more specifically how uniform spanning trees are being applied in research, please share in a comment!)&lt;/p&gt;


	&lt;p&gt;Anyway: Aldous and Broder were researching these uniform spanning trees, and independently arrived at the following algorithm:&lt;/p&gt;


	&lt;ol&gt;
	&lt;li&gt;Choose a vertex. Any vertex.&lt;/li&gt;
		&lt;li&gt;Choose a connected neighbor of the vertex and travel to it. If the neighbor has not yet been visited, add the traveled edge to the spanning tree.&lt;/li&gt;
		&lt;li&gt;Repeat step 2 until all vertexes have been visited.&lt;/li&gt;
	&lt;/ol&gt;


	&lt;p&gt;Remember: this algorithm is notable in that it selects from all possible spanning trees (i.e. mazes) of a given graph (i.e. field) with equal probability. The other algorithms I’ve covered don’t have this property.&lt;/p&gt;


	&lt;p&gt;Let’s walk through a trivial example. If you haven’t spotted yet why the algorithm is so ineffecient, hopefully the example will demonstrate it.&lt;/p&gt;</summary><content type="html">
            &lt;p&gt;The next maze algorithm I’m going to cover, the Aldous-Broder algorithm, is one of the simplest imaginable. It’s also one of the least efficient. In fact, it is so inefficient that you might wonder why anyone would even bother implementing it, let alone discovering it and having their name attached to it.&lt;/p&gt;


	&lt;p&gt;D. Aldous and A. Broder were two researchers, working independently, who were investigating &lt;em&gt;uniform spanning trees&lt;/em&gt;. A spanning tree, as you may or may not already know, is any tree that connects all the vertexes in a graph. A &lt;em&gt;uniform&lt;/em&gt; spanning tree is one chosen randomly (and with equal probability) among all the possible spanning trees of a given graph.&lt;/p&gt;


	&lt;p&gt;Riveting, isn’t it?&lt;/p&gt;


	&lt;p&gt;There are actually applications for this. Outside of recreational maze generation, I mean. I don’t know what they are myself, but Wikipedia informs me that they are in probability and mathematical physics. (If you know more specifically how uniform spanning trees are being applied in research, please share in a comment!)&lt;/p&gt;


	&lt;p&gt;Anyway: Aldous and Broder were researching these uniform spanning trees, and independently arrived at the following algorithm:&lt;/p&gt;


	&lt;ol&gt;
	&lt;li&gt;Choose a vertex. Any vertex.&lt;/li&gt;
		&lt;li&gt;Choose a connected neighbor of the vertex and travel to it. If the neighbor has not yet been visited, add the traveled edge to the spanning tree.&lt;/li&gt;
		&lt;li&gt;Repeat step 2 until all vertexes have been visited.&lt;/li&gt;
	&lt;/ol&gt;


	&lt;p&gt;Remember: this algorithm is notable in that it selects from all possible spanning trees (i.e. mazes) of a given graph (i.e. field) with equal probability. The other algorithms I’ve covered don’t have this property.&lt;/p&gt;


	&lt;p&gt;Let’s walk through a trivial example. If you haven’t spotted yet why the algorithm is so ineffecient, hopefully the example will demonstrate it.&lt;/p&gt;
&lt;h2&gt;An example&lt;/h2&gt;


	&lt;p&gt;For this demonstration, we’ll use a 3×3 grid. Any bigger than that and we could be here all day.&lt;/p&gt;


&lt;table class="maze"&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;

	&lt;p&gt;We choose a cell at random:&lt;/p&gt;


&lt;table class="maze"&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w h"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;

	&lt;p&gt;And travel to a random neighbor:&lt;/p&gt;


&lt;table class="maze"&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w h"&gt;&lt;/td&gt;&lt;td class="n s e w"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;

	&lt;p&gt;And since the neighbor had not been visited before, we carve a passage between the two:&lt;/p&gt;


&lt;table class="maze"&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s w h"&gt;&lt;/td&gt;&lt;td class="n s e"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;

	&lt;p&gt;Simple enough! Let’s do a few more quick iterations: choose a random neighbor, and carve a passage to it (but only if it hasn’t been visited before):&lt;/p&gt;


&lt;table&gt;&lt;tr&gt;&lt;td&gt;
&lt;table class="maze"&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w h"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s w"&gt;&lt;/td&gt;&lt;td class="n s e"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;/td&gt;&lt;td&gt;
&lt;table class="maze"&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n e w h"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="s w"&gt;&lt;/td&gt;&lt;td class="n s e"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;/td&gt;&lt;td&gt;
&lt;table class="maze"&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n e w"&gt;&lt;/td&gt;&lt;td class="n s e w h"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="s w"&gt;&lt;/td&gt;&lt;td class="n s e"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;/td&gt;&lt;td&gt;
&lt;table class="maze"&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n w"&gt;&lt;/td&gt;&lt;td class="n s e h"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="s w"&gt;&lt;/td&gt;&lt;td class="n s e"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;

	&lt;p&gt;Now, watch what happens next. We choose a neighbor at random, but two of the three neighbors are already visisted, which means there’s a very good chance of one of them being picked. Sure enough:&lt;/p&gt;


&lt;table class="maze"&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n w"&gt;&lt;/td&gt;&lt;td class="n s e"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="s w"&gt;&lt;/td&gt;&lt;td class="n s e h"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;

	&lt;p&gt;That neighbor’s already been visited! However, this move is allowed by the algorithm; the only constraint is that because the neighbor has been visited before, we don’t carve a passage to it from the previous cell.&lt;/p&gt;


	&lt;p&gt;Sure, alright. So, we’ll go with it. I think you’re seeing the pattern here, so I’ll just march through the rest of the process:&lt;/p&gt;


&lt;table&gt;&lt;tr&gt;&lt;td&gt;
&lt;table class="maze"&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n w"&gt;&lt;/td&gt;&lt;td class="n s e"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="s w h"&gt;&lt;/td&gt;&lt;td class="n s e"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;/td&gt;&lt;td&gt;
&lt;table class="maze"&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n w"&gt;&lt;/td&gt;&lt;td class="n s e"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s e w h"&gt;&lt;/td&gt;&lt;td class="s w"&gt;&lt;/td&gt;&lt;td class="n s e"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;/td&gt;&lt;td&gt;
&lt;table class="maze"&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n w"&gt;&lt;/td&gt;&lt;td class="n s e"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s w h"&gt;&lt;/td&gt;&lt;td class="s"&gt;&lt;/td&gt;&lt;td class="n s e"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;/td&gt;&lt;td&gt;
&lt;table class="maze"&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n w"&gt;&lt;/td&gt;&lt;td class="n s e"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s w"&gt;&lt;/td&gt;&lt;td class="s h"&gt;&lt;/td&gt;&lt;td class="n s e"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;
&lt;table class="maze"&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n w h"&gt;&lt;/td&gt;&lt;td class="n s e"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s w"&gt;&lt;/td&gt;&lt;td class="s"&gt;&lt;/td&gt;&lt;td class="n s e"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;/td&gt;&lt;td&gt;
&lt;table class="maze"&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s e w h"&gt;&lt;/td&gt;&lt;td class="n w"&gt;&lt;/td&gt;&lt;td class="n s e"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s w"&gt;&lt;/td&gt;&lt;td class="s"&gt;&lt;/td&gt;&lt;td class="n s e"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;/td&gt;&lt;td&gt;
&lt;table class="maze"&gt;
&lt;tr&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s w h"&gt;&lt;/td&gt;&lt;td class="n"&gt;&lt;/td&gt;&lt;td class="n s e"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s w"&gt;&lt;/td&gt;&lt;td class="s"&gt;&lt;/td&gt;&lt;td class="n s e"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;/td&gt;&lt;td&gt;
&lt;table class="maze"&gt;
&lt;tr&gt;&lt;td class="n s e w h"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s w"&gt;&lt;/td&gt;&lt;td class="n"&gt;&lt;/td&gt;&lt;td class="n s e"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s w"&gt;&lt;/td&gt;&lt;td class="s"&gt;&lt;/td&gt;&lt;td class="n s e"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;
&lt;table class="maze"&gt;
&lt;tr&gt;&lt;td class="n e w h"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="s w"&gt;&lt;/td&gt;&lt;td class="n"&gt;&lt;/td&gt;&lt;td class="n s e"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s w"&gt;&lt;/td&gt;&lt;td class="s"&gt;&lt;/td&gt;&lt;td class="n s e"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;/td&gt;&lt;td&gt;
&lt;table class="maze"&gt;
&lt;tr&gt;&lt;td class="n e w"&gt;&lt;/td&gt;&lt;td class="n s e w h"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="s w"&gt;&lt;/td&gt;&lt;td class="n"&gt;&lt;/td&gt;&lt;td class="n s e"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s w"&gt;&lt;/td&gt;&lt;td class="s"&gt;&lt;/td&gt;&lt;td class="n s e"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;/td&gt;&lt;td&gt;
&lt;table class="maze"&gt;
&lt;tr&gt;&lt;td class="n w"&gt;&lt;/td&gt;&lt;td class="n s e h"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="s w"&gt;&lt;/td&gt;&lt;td class="n"&gt;&lt;/td&gt;&lt;td class="n s e"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s w"&gt;&lt;/td&gt;&lt;td class="s"&gt;&lt;/td&gt;&lt;td class="n s e"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;/td&gt;&lt;td&gt;
&lt;table class="maze"&gt;
&lt;tr&gt;&lt;td class="n w"&gt;&lt;/td&gt;&lt;td class="n s e"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="s w"&gt;&lt;/td&gt;&lt;td class="n h"&gt;&lt;/td&gt;&lt;td class="n s e"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s w"&gt;&lt;/td&gt;&lt;td class="s"&gt;&lt;/td&gt;&lt;td class="n s e"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;
&lt;table class="maze"&gt;
&lt;tr&gt;&lt;td class="n w"&gt;&lt;/td&gt;&lt;td class="n s e"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="s w"&gt;&lt;/td&gt;&lt;td class="n"&gt;&lt;/td&gt;&lt;td class="n s e"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s w"&gt;&lt;/td&gt;&lt;td class="s h"&gt;&lt;/td&gt;&lt;td class="n s e"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;/td&gt;&lt;td&gt;
&lt;table class="maze"&gt;
&lt;tr&gt;&lt;td class="n w"&gt;&lt;/td&gt;&lt;td class="n s e"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="s w"&gt;&lt;/td&gt;&lt;td class="n"&gt;&lt;/td&gt;&lt;td class="n s e"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s w"&gt;&lt;/td&gt;&lt;td class="s"&gt;&lt;/td&gt;&lt;td class="n s e h"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;/td&gt;&lt;td&gt;
&lt;table class="maze"&gt;
&lt;tr&gt;&lt;td class="n w"&gt;&lt;/td&gt;&lt;td class="n s e"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="s w"&gt;&lt;/td&gt;&lt;td class="n"&gt;&lt;/td&gt;&lt;td class="n s e h"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s w"&gt;&lt;/td&gt;&lt;td class="s"&gt;&lt;/td&gt;&lt;td class="n s e"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;/td&gt;&lt;td&gt;
&lt;table class="maze"&gt;
&lt;tr&gt;&lt;td class="n w"&gt;&lt;/td&gt;&lt;td class="n s e"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="s w"&gt;&lt;/td&gt;&lt;td class="n h"&gt;&lt;/td&gt;&lt;td class="n s e"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s w"&gt;&lt;/td&gt;&lt;td class="s"&gt;&lt;/td&gt;&lt;td class="n s e"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;
&lt;table class="maze"&gt;
&lt;tr&gt;&lt;td class="n w"&gt;&lt;/td&gt;&lt;td class="n s e h"&gt;&lt;/td&gt;&lt;td class="n s e w out"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="s w"&gt;&lt;/td&gt;&lt;td class="n"&gt;&lt;/td&gt;&lt;td class="n s e"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s w"&gt;&lt;/td&gt;&lt;td class="s"&gt;&lt;/td&gt;&lt;td class="n s e"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;/td&gt;&lt;td&gt;
&lt;table class="maze"&gt;
&lt;tr&gt;&lt;td class="n w"&gt;&lt;/td&gt;&lt;td class="n s e"&gt;&lt;/td&gt;&lt;td class="n s e w h"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="s w"&gt;&lt;/td&gt;&lt;td class="n"&gt;&lt;/td&gt;&lt;td class="n s e"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s w"&gt;&lt;/td&gt;&lt;td class="s"&gt;&lt;/td&gt;&lt;td class="n s e"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;/td&gt;&lt;td&gt;
&lt;table class="maze"&gt;
&lt;tr&gt;&lt;td class="n w"&gt;&lt;/td&gt;&lt;td class="n s"&gt;&lt;/td&gt;&lt;td class="n s e h"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="s w"&gt;&lt;/td&gt;&lt;td class="n"&gt;&lt;/td&gt;&lt;td class="n s e"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s w"&gt;&lt;/td&gt;&lt;td class="s"&gt;&lt;/td&gt;&lt;td class="n s e"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;/td&gt;&lt;td&gt;
&lt;table class="maze"&gt;
&lt;tr&gt;&lt;td class="n w"&gt;&lt;/td&gt;&lt;td class="n s"&gt;&lt;/td&gt;&lt;td class="n s e"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="s w"&gt;&lt;/td&gt;&lt;td class="n"&gt;&lt;/td&gt;&lt;td class="n s e"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="n s w"&gt;&lt;/td&gt;&lt;td class="s"&gt;&lt;/td&gt;&lt;td class="n s e"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;

	&lt;p&gt;I hope you noticed how the cursor seemed to meander a bit, there at the end. If you run an animation of Aldous-Broder, you’ll probably find yourself shouting “JUST &lt;span class="caps"&gt;GO OVER THERE&lt;/span&gt;” to the cursor, once or twice. This is because Aldous-Broder, while easy to implement, lacks any real heuristics. And you can’t really &lt;em&gt;add&lt;/em&gt; any heuristics without changing the probability curve.&lt;/p&gt;


	&lt;p&gt;Try the following demo to see just how frustrating Aldous-Broder can be to watch:&lt;/p&gt;



&amp;lt;link href="http://jamisbuck.org/mazes/css/mazes.css" /&gt;
&lt;div class="row"&gt;
&lt;/div&gt;


	&lt;p&gt;I guess it really comes down to what you want out of a maze generator. If you absolutely must have a perfectly uniform spanning tree, then your options are limited.&lt;/p&gt;


	&lt;h2&gt;Implementation&lt;/h2&gt;


	&lt;p&gt;One of the really &lt;em&gt;nice&lt;/em&gt; things about Aldous-Broder is how trivial it is to implement. If you can implement the grid data structure, the algorithm itself is almost hardly worth mentioning.&lt;/p&gt;


	&lt;p&gt;But I’ll mention it anyway.&lt;/p&gt;


	&lt;p&gt;My implementation begins by choosing a random point, and then computing the number of cells in the grid that remain unvisited:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;x, y = rand(width), rand(height)&lt;tt&gt;
&lt;/tt&gt;remaining = width * height - &lt;span class="i"&gt;1&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;Then, we just loop until all cells have been visited:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="r"&gt;while&lt;/span&gt; remaining &amp;gt; &lt;span class="i"&gt;0&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="c"&gt;# ...&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;Within the loop, we just iterate over a list of random directions, until we find one that doesn’t take us outside the maze:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;[&lt;span class="co"&gt;N&lt;/span&gt;,&lt;span class="co"&gt;S&lt;/span&gt;,&lt;span class="co"&gt;E&lt;/span&gt;,&lt;span class="co"&gt;W&lt;/span&gt;].shuffle.each &lt;span class="r"&gt;do&lt;/span&gt; |dir|&lt;tt&gt;
&lt;/tt&gt;  nx, ny = x + &lt;span class="co"&gt;DX&lt;/span&gt;[dir], y + &lt;span class="co"&gt;DY&lt;/span&gt;[dir]&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;if&lt;/span&gt; nx &amp;gt;= &lt;span class="i"&gt;0&lt;/span&gt; &amp;amp;&amp;amp; ny &amp;gt;= &lt;span class="i"&gt;0&lt;/span&gt; &amp;amp;&amp;amp; nx &amp;lt; width &amp;amp;&amp;amp; ny &amp;lt; height&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="c"&gt;# ...&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;Once a valid direction is found, we check to see if the new cell is unvisited:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="r"&gt;if&lt;/span&gt; grid[ny][nx] == &lt;span class="i"&gt;0&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="c"&gt;# ...&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;If so, we carve a path, and decrement the remaining number of visited cells:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;grid[y][x] |= dir&lt;tt&gt;
&lt;/tt&gt;grid[ny][nx] |= &lt;span class="co"&gt;OPPOSITE&lt;/span&gt;[dir]&lt;tt&gt;
&lt;/tt&gt;remaining -= &lt;span class="i"&gt;1&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;Regardless of whether the cell has been visited or not, we then make the new cell the current cell, and break out of the innermost loop (the one where we look for a valid direction):&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;x, y = nx, ny&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;break&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;And that’s it. All that remains is to fire it off and sit back while it does it’s little drunkard’s walk all over our nice clean grid.&lt;/p&gt;


	&lt;h2&gt;Conclusion&lt;/h2&gt;


	&lt;p&gt;Aldous-Broder isn’t the most efficient algorithm on the block, or the smartest, but it is definitely well-suited for the problem domain that it was created for: finding uniform spanning trees. However, even there, there are more efficient algorithms. Next time, I’ll demonstrate Wilson’s algorithm, a (slightly) more efficient way to find a uniform spanning tree.&lt;/p&gt;


	&lt;p&gt;In the meantime, try your hand at Aldous-Broder. It shouldn’t set you back more than a couple of minutes, and it really is pretty fun.&lt;/p&gt;


	&lt;p&gt;For reference, here is my own (Ruby) implementation of Aldous-Broder:&lt;/p&gt;



&amp;lt;noscript&gt;&lt;a href="https://gist.github.com/760675"&gt;aldous-broder.rb&lt;/a&gt; on gist.github.com&amp;lt;/noscript&gt;


	&lt;p&gt;Enjoy!&lt;/p&gt;
          &lt;img src="http://feeds.feedburner.com/~r/buckblog/~4/YlUNpbFNpSE" height="1" width="1"/&gt;</content>  </entry>
</feed>

