;;; maze.el --- Maze Generator ;; ;;; Copyright (C) 2013 Kyle W T Sherman ;; ;; Author: Kyle W T Sherman <kylewsherman at gmail dot com> ;; Created: 2013-06-25 ;; Version: 0.1 ;; Keywords: maze generator ;; ;; This file is not part of GNU Emacs. ;; ;; This is free software; you can redistribute it and/or modify it under the ;; terms of the GNU General Public License as published by the Free Software ;; Foundation; either version 2, or (at your option) any later version. ;; ;; This is distributed in the hope that it will be useful, but WITHOUT ANY ;; WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS ;; FOR A PARTICULAR PURPOSE. See the GNU General Public License for more ;; details. ;; ;; You should have received a copy of the GNU General Public License along ;; with GNU Emacs; see the file COPYING. If not, write to the Free Software ;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;; ;;; Commentary: ;; ;; ;;; Installation: ;; ;; Put `maze.el' where you keep your elisp files and add something like the ;; following to your .emacs file: ;; ;; (autoload 'maze "maze" "Maze generator." t) ;; ;;; Usage: ;; ;; (maze) ;;; Code: ;; original C code found here: http://homepages.cwi.nl/~tromp/maze.html ;; char M[3]; /* holds the 2 characters printed for each cell */ ;; int H, /* height of the maze */ ;; C, /* current cell */ ;; E, /* temporary pointer used in the updating */ ;; L[40],R[40]; /* left and right pointers */ ;; main() ;; { ;; L[0] = scanf("%d",&H); /* reads height and sets L[0] to 1 */ ;; for (E = 40; --E; L[E] = R[E] = E) ;; printf("._"); /* close top of maze */ ;; printf("\n|"); ;; while (--H) /* more rows to do */ ;; { for (C = 40; --C; printf(M)) /* visit cells from left to right */ ;; { if (C != (E=L[C-1]) && 6<<27<rand()) /* make right-connection ? */ ;; { R[E] = R[C]; /* link E */ ;; L[R[C]] = E; /* to R[C] */ ;; R[C] = C-1; /* link C */ ;; L[C-1] = C; /* to C-1 */ ;; M[1] = '.'; /* no wall to the right */ ;; } ;; else M[1] = '|'; /* wall to the right */ ;; if (C != (E=L[C]) && 6<<27<rand()) /* omit down-connection ? */ ;; { R[E] = R[C]; /* link E */ ;; L[R[C]] = E; /* to R[C] */ ;; L[C] = C; /* link C */ ;; R[C] = C; /* to C */ ;; M[0] = '_'; /* wall downward */ ;; } ;; else M[0] = ' '; /* no wall downward */ ;; } ;; printf("\n|"); ;; } ;; M[0] = '_'; /* close bottom of maze */ ;; for (C = 40; --C; printf(M)) /* bottom row */ ;; { if (C != (E=L[C-1]) && (C == R[C] || 6<<27<rand())) ;; { L[R[E]=R[C]]=E; ;; L[R[C]=C-1]=C; ;; M[1] = '.'; ;; } ;; else M[1] = '|'; ;; E = L[C]; ;; R[E] = R[C]; ;; L[R[C]] = E; ;; L[C] = C; ;; R[C] = C; ;; } ;; printf("\n"); ;; } ;; maze output buffer name (defconst maze-output-buffer-name "*maze-output*" "Buffer name to use for maze output.") (defmacro maze-random-check () "Return non-nil if random check passes, otherwise return nil." (< (lsh 6 27) (random 2147483648))) ;; maze ;;;###autoload (defun maze (&optional width height) "Generate a maze of size WIDTH and HEIGHT." (interactive) (let ((output-buffer (get-buffer-create maze-output-buffer-name))) ; output buffer (save-current-buffer (set-buffer output-buffer) (erase-buffer) (let ((width (1+ (or width (/ (window-width) 2)))) (height (1- (or height (- (window-height) 5))))) (let ((m (make-vector 2 " ")) (left (make-vector width 0)) (right (make-vector width 0))) ;; top (dotimes (x (1- width)) (aset left x x) (aset right x x) (insert "._")) (insert ".\n|") ;; middle (aset right (1- width) width) (while (plusp height) (dotimes (x (1- width)) (let ((e (aref left (1+ x)))) (if (and (/= x e) (maze-random-check)) (progn (aset right e (aref right x)) (aset left (aref right x) e) (aset right x (1+ x)) (aset left (1+ x) x) (aset m 1 ".")) (aset m 1 "|"))) (let ((e (aref left x))) (if (and (/= x e) (maze-random-check)) (progn (aset right e (aref right x)) (aset left (aref right x) e) (aset left x x) (aset right x x) (aset m 0 "_")) (aset m 0 " "))) (insert (cl-reduce #'concat m))) (insert "\n|") (setq height (1- height))) ;; bottom (aset m 0 "_") (dotimes (x (1- width)) (let ((e (aref left (1+ x)))) (if (and (/= x e) (or (= x (aref right x)) (maze-random-check))) (progn (aset right e (aref right x)) (aset left (aref right x) e) (aset right x (1+ x)) (aset left (1+ x) x) (aset m 1 ".")) (aset m 1 "|")) (setq e (aref left x)) (aset right e (aref right x)) (aset left (aref right x) e) (aset left x x) (aset right x x)) (insert (cl-reduce #'concat m))) (insert "\n")))) (switch-to-buffer output-buffer))) (provide 'maze) ;;; maze.el ends here