ARC

迷路の自動生成

More than 5 years have passed since last update.

(main 大きさ) で迷路を自動生成してsvgをプリントする。

$ arc < maze.arc > maze.svg

のようにしてファイルに書き出せばブラウザで生成した迷路を見ることが出来る。

maze.arc
(def get-pos ((y . x)) (and (<= 0 y) (< y h) (<= 0 x) (< x w) ((maze y) x)))
(def dig-pos ((y . x)) (sref (maze y) nil x) (cons y x))

(def get-dir-pos ((y . x) d n)
  (case d
    a (cons (- y n) x) b (cons (+ y n) x)
    l (cons y (- x n)) r (cons y (+ x n))))

(def can-dig? (pos d) (get-pos (get-dir-pos pos d 2)))
(def dig (pos d) (dig-pos (get-dir-pos pos d 1)) (dig-pos (get-dir-pos pos d 2)))
(def rget (g) (let x (rand-elt g) (cons x (rem x g))))
(def cdir (d) (case d a 'b b 'a l 'r r 'l))
(def ndir (d) (rem (cdir d) all-dirs))

(= all-dirs '(a b l r))
(def iter (pos d digd)
  (if digd
      (if d
          (let d (rget d)
            (if (can-dig? pos (car d))
                (let np (dig pos (car d))
                  (iter np (ndir (car d)) (cons np digd)))
                (iter pos (cdr d) digd)))
          (let pg (rget digd)
            (iter (car pg) all-dirs (cdr pg))))))

(= box-size 5)
(def print-maze (x y)
  (each line maze
    (= x 0)
    (each itm line
      (if itm (pr "<svg:rect x=\"" (* x box-size) "px\" y=\"" (* y box-size)
                  "px\" width=\"" box-size "px\" height=\"" box-size
                  "px\" fill=\"black\" stroke=\"none\" />\n"))
      (= x (inc x)))
    (pr "\n")
    (= y (inc y))))

(def main (size)
  (= h size) (= w size)
  (= maze (n-of h (n-of w t)))
  (dig-pos '(1 . 1))
  (iter '(1 . 1) all-dirs '((1 . 1)))

  (pr "<?xml version=\"1.0\" encoding=\"utf-8\"?>")
  (pr "<svg:svg xmlns:svg=\"http://www.w3.org/2000/svg\" xmlns:si=\"http://xmlns.ticketstar.jp/2012/site-info\" version=\"1.1\" viewBox=\"0 0 "
      (* box-size w) " "
      (* box-size h) "\" preserveAspectRatio=\"xMinYMin meet\" si:version=\"0.0\">\n")
  (print-maze 0 0)
  (pr "</svg:svg>\n"))

(main 35)