This post follows the Mazes for Programmers book - if you haven’t gone through the book/written the suggested code, you can find the required sources on this page.
Note: you’ll need to have gone through Chapter 2 for the code - those are the exercises at the end of Chapter 1, but it only really makes sense to implement them once you have completed Chapter 2 (so you can visualise the changes)
Note 2: I don’t use ruby
much, if at all. If there’s a more idiomatic way to do something, let me know!
BinaryTree
This is (roughly) the code you should have by the end of Chapter 2:
And it generates mazes like:
❯ ruby -I. binary_tree_demo.rb
+---+---+---+---+---+---+---+---+---+---+---+---+
| |
+ +---+ + + +---+---+---+---+ + + +
| | | | | | | |
+ +---+ + + + +---+---+---+ +---+ +
| | | | | | | |
+---+---+ +---+ +---+ + +---+ + + +
| | | | | | | |
+ +---+ +---+ +---+---+ + + + + +
| | | | | | | | |
+ + + + +---+ + +---+---+ + + +
| | | | | | | | | |
+---+ + + + + +---+ + +---+---+ +
| | | | | | | | |
+---+---+---+---+---+ + + +---+---+---+ +
| | | | |
+---+ +---+ + + + +---+ +---+ + +
| | | | | | | | |
+ +---+---+ + +---+ +---+---+ + + +
| | | | | | | |
+ +---+---+ +---+ +---+ + +---+---+ +
| | | | | | |
+ +---+---+ + +---+---+ +---+---+ + +
| | | | | | |
+---+---+---+---+---+---+---+---+---+---+---+---+
Reorient the Passages
The logic selecting passages to link together is hard-coded in the tree itself - namely:
Let’s start by abstracting that away such that we take a variable number of biases. On a square grid the options are limited but if we had something hexagonal, you can see how it scale:
Side note, see the use of public_send
- it’s one of those things that show ruby
’s roots in oop
languages like smalltalk
.
Just for kicks, let’s create a tree with :north
and :south
biases:
yielding:
❯ ruby -I. binary_tree_demo.rb
+---+---+---+---+---+---+---+---+---+---+---+---+
| | | | | | | | | | | | |
+---+ + +---+ + +---+ +---+ + + +
| | | | | | | | | | | | |
+ + + + + + + +---+ + +---+ +
| | | | | | | | | | | | |
+---+---+ + +---+ +---+ + +---+ + +
| | | | | | | | | | | | |
+ + +---+---+ + + + + + + +---+
| | | | | | | | | | | | |
+---+ + + + +---+ +---+ + + + +
| | | | | | | | | | | | |
+ + + + +---+ + + + + + +---+
| | | | | | | | | | | | |
+---+ + + + + + + + + + + +
| | | | | | | | | | | | |
+ +---+---+ + + + + + + + + +
| | | | | | | | | | | | |
+---+ + +---+ +---+ + +---+ +---+---+
| | | | | | | | | | | | |
+ + +---+ + + + +---+ +---+ + +
| | | | | | | | | | | | |
+ + + +---+ + + + +---+ + + +
| | | | | | | | | | | | |
+---+---+---+---+---+---+---+---+---+---+---+---+
Changing the Bias
How do we bias our BinaryTree
towards maybe more horizontal or vertical pages? As it stands we sample the biases with uniform probability. That is, if the choice is between :north
and :east
, both are equally likely to be chosen.
Let’s try assigning weights to each bias - for instance, we may want the likelihood of a passage extending vertically to be twice as much as horizontally. We could represent this as {:north => 2, :east => 1}
.
Sampling because a case of (1) generating a random number with 0 <-> total weight (3 in the above) and (2) building the relevant intervals (so here, [0-2] => :north
and (2-3] => :east
). Depending on where the sample falls within that range, it will dictate the direction we take.
I didn’t find an elegant way to do a running sum, but we can be explicit:
Running it:
and there we have it:
❯ ruby -I. binary_tree_demo.rb
+---+---+---+---+---+---+---+---+---+---+---+---+
| | | | | | | | | | | |
+ +---+ + + +---+ +---+ + + + +
| | | | | | | | | |
+ + + + + +---+ + + +---+ +---+
| | | | | | | | | | |
+---+ +---+ + + + + + + +---+---+
| | | | | | | | | |
+ + + + + + + + +---+ + + +
| | | | | | | | | | | |
+ +---+ + + +---+ + + + + + +
| | | | | | | | | | |
+ + + + + + + + +---+ + + +
| | | | | | | | | | | |
+ + + + +---+ + +---+ + + +---+
| | | | | | | | | | |
+ + + + + +---+---+ + + +---+ +
| | | | | | | | | |
+---+ + + +---+ + +---+ + + + +
| | | | | | | | | |
+ +---+ + + +---+ + + +---+ + +
| | | | | | | | | |
+ + + +---+---+ + +---+---+ + + +
| | | | | | | | |
+---+---+---+---+---+---+---+---+---+---+---+---+
Fancy!