cf49d1035bcd

Add comments to generation algorithms, clean up `active` code
[view raw] [browse files]
author Steve Losh <steve@stevelosh.com>
date Sun, 26 Jun 2016 17:52:37 +0000
parents 84b8c9cf94df
children e897732c9b71
branches/tags (none)
files src/demo.lisp src/generation.lisp

Changes

--- a/src/demo.lisp	Wed Jun 08 13:37:43 2016 +0000
+++ b/src/demo.lisp	Sun Jun 26 17:52:37 2016 +0000
@@ -15,6 +15,7 @@
 (defvar *show-colors* nil)
 (defvar *cell-size* nil)
 
+
 ;;;; Globals
 (defvar *shift* nil)
 (defvar *control* nil)
--- a/src/generation.lisp	Wed Jun 08 13:37:43 2016 +0000
+++ b/src/generation.lisp	Sun Jun 26 17:52:37 2016 +0000
@@ -7,21 +7,40 @@
      (setf (cell-active ,cell-place) nil)))
 
 
+;;;; Binary Tree
+;;; The Binary Tree generation algorithm works by looping through each cell,
+;;; choosing either the north or east neighbor at random, and carving out the
+;;; wall to it.
+;;;
+;;; For the north and east edges of the map the only viable neighbor is always
+;;; picked, which results in signature long corridors on those edges.
+
 (defgenerator binary-tree-generator (grid)
   (grid-loop-cells cell grid
-    (setf (cell-active cell) t)
-    (let ((other (random-elt (full-list (cell-north cell)
-                                        (cell-east cell)))))
-      (when other
-        (cell-link cell other)))
-    (yield)
-    (setf (cell-active cell) nil)))
+    (with-cell-active cell
+      (let ((other (random-elt (full-list (cell-north cell)
+                                          (cell-east cell)))))
+        (when other
+          (cell-link cell other)))
+      (yield))))
 
 (defun binary-tree (grid)
   (do-generator (_ (binary-tree-generator grid)))
   grid)
 
 
+;;;; Sidewinder
+;;; The Sidewinder algorithm works by looping over each row.
+;;;
+;;; For each row it loops over the cells to form "runs" of consecutive
+;;; horizontal neighbors, randomly deciding when to end a particular run.  Once
+;;; a run is ended ("closed") it picks a random cell in the run and carves out
+;;; a passage north.
+;;;
+;;; For the top row of the map we never want to carve out to the north wall, so
+;;; we never allow the top row to close -- it'll always be a single run.  This
+;;; results in a signature long corridor along the top of the maze.
+
 (defgenerator sidewinder-generator (grid)
   (grid-loop-rows row grid
     (loop :with run = nil
@@ -32,9 +51,8 @@
                                   (and (not at-north-bound)
                                        (randomp)))
           :do
-          (progn
-            (setf (cell-active-group cell) t
-                  (cell-active cell) t)
+          (with-cell-active cell
+            (setf (cell-active-group cell) t)
             (push cell run)
             (if should-close
               (let* ((member (random-elt run))
@@ -48,14 +66,20 @@
                 (setf run nil))
               (progn
                 (cell-link cell (cell-east cell))
-                (yield)))
-            (setf (cell-active cell) nil)))))
+                (yield)))))))
 
 (defun sidewinder (grid)
   (do-generator (_ (sidewinder-generator grid)))
   grid)
 
 
+;;;; Aldous-Broder
+;;; The Aldous-Broder algorithm picks a random cell and walks to a random
+;;; neighbor at each step.  If that neighbor has not been visited yet it carves
+;;; out the wall back to the previous cell.
+;;;
+;;; This produces really nice, unbiased mazes but is *really* slow.
+
 (defgenerator aldous-broder-generator (grid)
   (let ((cell (grid-random-cell grid))
         (unvisited (1- (grid-size grid))))