198 lines
7.1 KiB
Fennel
198 lines
7.1 KiB
Fennel
(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}
|