Merge branch 'master' of ssh://goldsmith.journeyman.cc/srv/git/mw-engine

This commit is contained in:
Simon Brooke 2015-04-11 09:30:44 +01:00
commit 6b3f8730a6
3 changed files with 61 additions and 19 deletions

View file

@ -7,6 +7,9 @@
(def ^:dynamic *sealevel* 10) (def ^:dynamic *sealevel* 10)
;; forward declaration of flow, to allow for a wee bit of mutual recursion.
(declare flow)
(defn rain-world (defn rain-world
"Simulate rainfall on this `world`. TODO: Doesn't really work just now - should "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" rain more on west-facing slopes, and less to the east of high ground"
@ -26,24 +29,36 @@
:altitude :altitude
(or (:altitude cell) 0) >))))) (or (:altitude cell) 0) >)))))
(defn flood-hollow
"Raise the altitude of a copy of this `cell` of this `world` to one unit above the lowest of these `neighbours`, and reflow."
[cell world neighbours]
(let [lowest (get-least-cell neighbours :altitude)]
(flow (merge cell {:altitude (+ (:altitude lowest) 1)}))))
(def flow (def flow
"Compute the total flow upstream of this `cell` in this `world`, and return a cell identical "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 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 memoised because the consequence of mapping a recursive function across an array is that many
cells will be revisited - potentially many times. 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." Flow comes from a higher cell to a lower only if the lower is the lowest neighbour of the higher."
(memoize (memoize
(fn [world cell] (fn [world cell]
(cond (cond
(not (nil? (:flow cell))) cell (not (nil? (:flow cell))) cell
(<= (or (:altitude cell) 0) *sealevel*) cell (<= (or (:altitude cell) 0) *sealevel*) cell
true true
(merge cell (let [contributors (flow-contributors world cell)]
{:flow (+ (:rainfall cell) (if
(apply + (= (count contributors) 8)
(map (fn [neighbour] (:flow (flow world neighbour))) ;; local lowspot - lake bottom
(flow-contributors world cell))))}))))) (flood-hollow cell world contributors)
;; otherwise...
(merge cell
{:flow (+ (:rainfall cell)
(apply +
(map (fn [neighbour] (:flow (flow world neighbour)))
(flow-contributors world cell))))})))))))
(defn flow-world (defn flow-world
"Return a world like this `world`, but with cells tagged with the amount of "Return a world like this `world`, but with cells tagged with the amount of

View file

@ -13,7 +13,7 @@
[mikera.image.filters :as filters])) [mikera.image.filters :as filters]))
(defn- tag-property (defn tag-property
"Set the value of this `property` of this cell from the corresponding pixel of this `heightmap`. "Set the value of this `property` of this cell from the corresponding pixel of this `heightmap`.
If the heightmap you supply is smaller than the world, this will break. If the heightmap you supply is smaller than the world, this will break.
@ -36,7 +36,7 @@
(get-int cell :x) (get-int cell :x)
(get-int cell :y)) 256))))}))) (get-int cell :y)) 256))))})))
(defn- tag-gradient (defn tag-gradient
"Set the `gradient` property of this `cell` of this `world` to the difference in "Set the `gradient` property of this `cell` of this `world` to the difference in
altitude between its highest and lowest neghbours." altitude between its highest and lowest neghbours."
[world cell] [world cell]
@ -54,7 +54,7 @@
[world] [world]
(map-world world tag-gradient)) (map-world world tag-gradient))
(defn- tag-altitude (defn tag-altitude
"Set the altitude of this cell from the corresponding pixel of this heightmap. "Set the altitude of this cell from the corresponding pixel of this heightmap.
If the heightmap you supply is smaller than the world, this will break. If the heightmap you supply is smaller than the world, this will break.

View file

@ -29,6 +29,33 @@
[world x y] [world x y]
(and (>= x 0)(>= y 0)(< y (count world))(< x (count (first world))))) (and (>= x 0)(>= y 0)(< y (count world))(< x (count (first world)))))
(defn map-world-n-n
"Wholly non-parallel map world implementation"
([world function]
(map-world-n-n world function nil))
([world function additional-args]
(into []
(map (fn [row]
(into [] (map
#(apply function
(cons world (cons % additional-args)))
row)))
world))))
(defn map-world-p-p
"Wholly parallel map world implementation"
([world function]
(map-world-p-p world function nil))
([world function additional-args]
(into []
(pmap (fn [row]
(into [] (pmap
#(apply function
(cons world (cons % additional-args)))
row)))
world))))
(defn map-world (defn map-world
"Apply this `function` to each cell in this `world` to produce a new world. "Apply this `function` to each cell in this `world` to produce a new world.
the arguments to the function will be the world, the cell, and any the arguments to the function will be the world, the cell, and any