53 lines
2.1 KiB
Clojure
53 lines
2.1 KiB
Clojure
;; Experimental, probably of no interest to anyone else; attempt to compute drainage on a world,
|
|
;; assumed to have altitudes already set from a heighmap.
|
|
|
|
(ns mw-engine.drainage
|
|
(:use mw-engine.utils
|
|
mw-engine.world))
|
|
|
|
(def ^:dynamic *sealevel* 10)
|
|
|
|
(defn rain-world
|
|
"Simulate rainfall on this `world`. TODO: Doesn't really work just now - should
|
|
rain more on west-facing slopes, and less to the east of high ground"
|
|
[world]
|
|
(map-world world (fn [world cell] (merge cell {:rainfall 1}))))
|
|
|
|
(defn flow-contributors
|
|
"Return a list of the cells in this `world` which are higher than this
|
|
`cell` and for which this cell is the lowest neighbour"
|
|
[world cell]
|
|
(remove nil?
|
|
(into []
|
|
(map
|
|
(fn [n]
|
|
(cond (= cell (get-least-cell (get-neighbours world n) :altitude)) n))
|
|
(get-neighbours-with-property-value world (:x cell) (:y cell) 1
|
|
:altitude
|
|
(or (:altitude cell) 0) >)))))
|
|
|
|
(def flow
|
|
"Compute the total flow upstream of this `cell` in this `world`, and return a cell identical
|
|
to this one but having a value of its flow property set from that computation. The function is
|
|
memoised because the consequence of mapping a recursive function across an array is that many
|
|
cells will be revisited - potentially many times.
|
|
|
|
Flow comes from a higher cell to a lower only if the lower is the lowest neighbour of the higher."
|
|
(memoize
|
|
(fn [world cell]
|
|
(cond
|
|
(not (nil? (:flow cell))) cell
|
|
(<= (or (:altitude cell) 0) *sealevel*) cell
|
|
true
|
|
(merge cell
|
|
{:flow (+ (:rainfall cell)
|
|
(apply +
|
|
(map (fn [neighbour] (:flow (flow world neighbour)))
|
|
(flow-contributors world cell))))})))))
|
|
|
|
(defn flow-world
|
|
"Return a world like this `world`, but with cells tagged with the amount of
|
|
water flowing through them."
|
|
[world]
|
|
(map-world (rain-world world) flow))
|