(local state (require :state)) ; ; ### Use seed to randomize stuff (love.math.setRandomSeed (state.getSeed)) ; Cell Stuff ; The "cell-num" is the number of cells across; it is then squared to make the ; grid. Each cell has a "cell-size" of walls ("wall-width") and hallways ; ("hall-width"). (var map-meta (state.getMap)) (var cell-num (. map-meta :n)) (var (hall-width wall-width) (values (. map-meta :h) (. map-meta :w))) (var cell-size (+ hall-width wall-width)) ; (fn wall-seg [] (+ 10 (math.random 1 3))) (fn wall-seg [] (love.math.random 11 13)) ; Helper functions for dealing with the cell list (fn cell-row [i] (+ 1 (math.floor (/ (- i 1) cell-num)))) (fn map-index [i] (var cell-col (if (= 0 (% i cell-num)) cell-num (% i cell-num))) (+ (* cell-size cell-size cell-num (- (cell-row i) 1)) (- (* cell-col cell-size) (- cell-size 1)))) ; Meta-Cells is the data before the digits (var spawn-cell (love.math.random 1 cell-num)) (var leave-cell (love.math.random (+ (* cell-num (- cell-num 1)) 1) (* cell-num cell-num))) (var spawn-spot {:x cell-size :y (+ (- (* spawn-cell cell-size) (- cell-size 1)) cell-size)}) (fn default-meta-cells [] (var meta-cells {}) (for [c 1 (* cell-num cell-num)] (table.insert meta-cells {:e false :s false :v false})) (tset meta-cells leave-cell :s true) meta-cells) ; Cells is the 0's and 1's (fn convert-cells [meta-cells leave-cell] (var cells {}) (each [k v (ipairs meta-cells)] (var cell []) (var row-limit (if (. v :e) (+ hall-width wall-width) hall-width)) (var col-limit (if (. v :s) (+ hall-width wall-width) hall-width)) (for [i 1 cell-size] (for [j 1 cell-size] (var cell-index (+ j (* (- i 1) cell-size))) (if (and (< i (+ col-limit 1)) (< j (+ row-limit 1))) (tset cell cell-index 0) (tset cell cell-index (wall-seg))) (if (and (> i hall-width) (> j hall-width)) (tset cell cell-index (wall-seg))) (if (= k leave-cell) (tset cell cell-index 0)))) (table.insert cells cell)) cells) (fn generate-maze [meta-cells spawn-cell] ; Maze Generation ; 1. Push the starting cell to the stack ; 2. Pop the top of the stack, mark that cell visited ; 3. If there are any unvisited neighbors: ; a. Push the current cell to the stack ; b. Choose a random un-visited neighbor ; c. Adjust walls accordingly ; d. Push chosen neighbor to the stack (var cell-stack [spawn-cell]) (while (> (length cell-stack) 0) (var current-cell (table.remove cell-stack)) (var next-cells {}) (tset meta-cells current-cell :v true) ; Check if any of the current cell's neighbors are viable ; North - ; if current-cell <= cell-num, then north is a map-side/barrier (when (> current-cell cell-num) (var n-cell (- current-cell cell-num)) (if (not (. meta-cells n-cell :v)) (table.insert next-cells {:c n-cell :d 1}))) ; South - ; if current-cell > (- (* cell-num cell-num) cell-num), ; then south is a map-side/barrier (when (< current-cell (- (* cell-num cell-num) cell-num)) (var s-cell (+ current-cell cell-num)) (if (not (. meta-cells s-cell :v)) (table.insert next-cells {:c s-cell :d 3}))) ; East - ; if current-cell % cell-num = 0, then east is a map-side/barrier (when (not (= 0 (% current-cell cell-num))) (var e-cell (+ current-cell 1)) (if (not (. meta-cells e-cell :v)) (table.insert next-cells {:c e-cell :d 2}))) ; West - ; if current-cell % cell-num = 1, then west is a map-side/barrier (when (not (= 1 (% current-cell cell-num))) (var w-cell (- current-cell 1)) (if (not (. meta-cells w-cell :v)) (table.insert next-cells {:c w-cell :d 4}))) ; Randomly choose a viable neighbor, if possible (var chosen-next-cell {}) (when (> (length next-cells) 0) (table.insert cell-stack current-cell) (set chosen-next-cell (. next-cells (love.math.random 1 (length next-cells)))) ; Adjust walls accordingly (case chosen-next-cell {:d 1} (tset meta-cells (. chosen-next-cell :c) :s true) {:d 2} (tset meta-cells current-cell :e true) {:d 3} (tset meta-cells current-cell :s true) {:d 4} (tset meta-cells (. chosen-next-cell :c) :e true)) (table.insert cell-stack (. chosen-next-cell :c))) ) meta-cells ) (fn generate_cell_map [cells] (var cell_map []) (for [c 1 (length cells)] (var (mi ci) (values (map-index c) 1)) (for [i 1 cell-size] (for [j 1 cell-size] (var new-map-index (+ mi (+ (- i 1) (* (- j 1) (* cell-num cell-size))))) (var new-cell-index (+ ci (+ (- i 1) (* (- j 1) cell-size)))) (tset cell_map new-map-index (. cells c new-cell-index))))) cell_map) (fn generate-north-spawn [spawn-cell] (var (map map-row) (values [] [])) (for [i 1 cell-size] (set map-row []) (for [j 1 (- (* (+ 2 cell-num) cell-size) hall-width)] (table.insert map-row (wall-seg))) (table.insert map map-row)) (var spawn (+ (- (* spawn-cell cell-size) (- cell-size 1)) cell-size)) (tset map cell-size spawn 0) (tset map cell-size (+ spawn 1) 22) (tset map cell-size (- spawn 1) 22) (tset map (- cell-size 1) spawn 33) map) (fn generate-south-exit [cells leave-cell] (var (map map-row) (values [] [])) (for [i 1 (- cell-size hall-width)] (set map-row []) (for [j 1 (- (* (+ 2 cell-num) cell-size) hall-width)] (table.insert map-row (wall-seg))) (table.insert map map-row)) (var escape (+ (* (- leave-cell (* cell-num (- cell-num 1))) cell-size) 1)) (for [i 1 cell-size] (tset map 1 (+ escape (- i 1)) 33)) map) (fn generate_map [cells spawn-cell leave-cell] (var map []) ; Generate the northern feature - spawn point (each [_ row (ipairs (generate-north-spawn spawn-cell))] (table.insert map row)) ; Pad the east and west sides of the map (for [c 1 (* cell-num cell-size)] (var map-row []) (for [i 1 cell-size] (table.insert map-row (wall-seg))) ; (table.move cells ; (+ (* (- c 1) (* cell-num cell-size)) 1) ; (* c (* cell-num cell-size)) ; (+ cell-size 1) map-row) (for [i (+ (* (- c 1) (* cell-num cell-size)) 1) (* c (* cell-num cell-size))] (table.insert map-row (. cells i))) (for [i 1 (- cell-size hall-width)] (table.insert map-row (wall-seg))) (table.insert map map-row)) ; Generate the northern feature - spawn point (each [_ row (ipairs (generate-south-exit cells leave-cell))] (table.insert map row)) map) (fn print_cell_map [cells] (var output "") (for [i 1 (length cells)] (set output (.. output " " (. cells i))) (if (= 0 (% i (* cell-num cell-size))) (set output (.. output "\n")))) (print output)) (fn print_map [map] (for [i 1 (length map)] (var (r o) (values "" "")) (for [j 1 (length (. map i))] (set o (if (= 0 (. map i j)) "00" (. map i j))) (set r (.. r " " o))) (print r))) (fn generate [] (var meta-maze (generate-maze (default-meta-cells) spawn-cell)) (var data-maze (convert-cells meta-maze leave-cell)) (var data-map (generate_cell_map data-maze)) (var map (generate_map data-map spawn-cell leave-cell)) ; (print_map map) (values map spawn-spot)) ; (print (.. "SPAWN: " spawn-cell "(" (. spawn-spot :x) "," (. spawn-spot :y) ")")) ; (print (.. "END: " leave-cell)) ; (print (.. "Escape: " (- leave-cell (* cell-num (- cell-num 1))))) {: generate}