Minor changes
This commit is contained in:
parent
977947d4b0
commit
0dc6aab59d
|
@ -1,5 +1,5 @@
|
||||||
(defproject mw-engine "0.1.0-SNAPSHOT"
|
(defproject mw-engine "0.1.0-SNAPSHOT"
|
||||||
:description "FIXME: write description"
|
:description "Cellular automaton world builder."
|
||||||
:url "http://example.com/FIXME"
|
:url "http://example.com/FIXME"
|
||||||
:license {:name "Eclipse Public License"
|
:license {:name "Eclipse Public License"
|
||||||
:url "http://www.eclipse.org/legal/epl-v10.html"}
|
:url "http://www.eclipse.org/legal/epl-v10.html"}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
(ns mw-engine.core
|
(ns mw-engine.core
|
||||||
(:use mw-engine.world
|
(:require mw-engine.world
|
||||||
|
mw-engine.natural-rules
|
||||||
mw-engine.utils))
|
mw-engine.utils))
|
||||||
|
|
||||||
;; every rule is a function of two arguments, a cell and a world. If the rule
|
;; every rule is a function of two arguments, a cell and a world. If the rule
|
||||||
|
@ -8,60 +9,6 @@
|
||||||
;;
|
;;
|
||||||
;; Rules are applied in turn until one matches.
|
;; Rules are applied in turn until one matches.
|
||||||
|
|
||||||
|
|
||||||
(def treeline 10)
|
|
||||||
|
|
||||||
(def natural-rules
|
|
||||||
(list
|
|
||||||
;; Randomly, birds plant tree seeds into pasture.
|
|
||||||
(fn [cell world] (cond (and (= (:state cell) :pasture)(< (rand 10) 1))(merge cell {:state :scrub})))
|
|
||||||
;; Scrub below the treeline grows gradually into forest
|
|
||||||
(fn [cell world]
|
|
||||||
(cond (and
|
|
||||||
(= (:state cell) :scrub)
|
|
||||||
(< (:altitude cell) treeline))
|
|
||||||
(merge cell {:state :scrub2})))
|
|
||||||
(fn [cell world] (cond (= (:state cell) :scrub2) (merge cell {:state :forest})))
|
|
||||||
;; Forest on fertile land at low altitude grows to climax
|
|
||||||
(fn [cell world]
|
|
||||||
(cond
|
|
||||||
(and
|
|
||||||
(= (:state cell) :forest)
|
|
||||||
(> (:fertility cell) 10))
|
|
||||||
(merge cell {:state :climax})))
|
|
||||||
;; Climax forest occasionally catches fire (e.g. lightning strikes)
|
|
||||||
(fn [cell world] (cond (and (= (:state cell) :climax)(< (rand 10) 1)) (merge cell {:state :fire})))
|
|
||||||
;; Climax forest neighbouring fires is likely to catch fire
|
|
||||||
(fn [cell world]
|
|
||||||
(cond
|
|
||||||
(and (= (:state cell) :climax)
|
|
||||||
(< (rand 3) 1)
|
|
||||||
(not (empty? (get-neighbours-with-state world (:x cell) (:y cell) 1 :fire))))
|
|
||||||
(merge cell {:state :fire})))
|
|
||||||
;; After fire we get waste
|
|
||||||
(fn [cell world] (cond (= (:state cell) :fire) (merge cell {:state :waste})))
|
|
||||||
;; And after waste we get pioneer species; if there's a woodland seed
|
|
||||||
;; source, it's going to be scrub, otherwise grassland.
|
|
||||||
(fn [cell world]
|
|
||||||
(cond
|
|
||||||
(and (= (:state cell) :waste)
|
|
||||||
(not
|
|
||||||
(empty?
|
|
||||||
(flatten
|
|
||||||
(list
|
|
||||||
(get-neighbours-with-state world (:x cell) (:y cell) 1 :scrub2)
|
|
||||||
(get-neighbours-with-state world (:x cell) (:y cell) 1 :forest)
|
|
||||||
(get-neighbours-with-state world (:x cell) (:y cell) 1 :climax))))))
|
|
||||||
(merge cell {:state :scrub})))
|
|
||||||
(fn [cell world]
|
|
||||||
(cond (= (:state cell) :waste)
|
|
||||||
(merge cell {:state :pasture})))
|
|
||||||
;; Forest increases soil fertility
|
|
||||||
(fn [cell world]
|
|
||||||
(cond (member? (:state cell) '(:forest :climax))
|
|
||||||
(merge cell {:fertility (+ (:fertility cell) 1)})))
|
|
||||||
))
|
|
||||||
|
|
||||||
(defn transform-cell
|
(defn transform-cell
|
||||||
"Derive a cell from this cell of this world by applying these rules."
|
"Derive a cell from this cell of this world by applying these rules."
|
||||||
[cell world rules]
|
[cell world rules]
|
||||||
|
@ -96,3 +43,10 @@
|
||||||
[world rules generations]
|
[world rules generations]
|
||||||
(let [state (list world rules)]
|
(let [state (list world rules)]
|
||||||
(take generations (iterate transform-world-state state))))
|
(take generations (iterate transform-world-state state))))
|
||||||
|
|
||||||
|
(defn animate-world
|
||||||
|
[world rules generations]
|
||||||
|
(let [state (list world rules)]
|
||||||
|
(dorun
|
||||||
|
(take generations (iterate transform-world-state state)))
|
||||||
|
nil))
|
|
@ -3,3 +3,9 @@
|
||||||
(defn member?
|
(defn member?
|
||||||
"True if elt is a member of col."
|
"True if elt is a member of col."
|
||||||
[elt col] (some #(= elt %) col))
|
[elt col] (some #(= elt %) col))
|
||||||
|
|
||||||
|
(defn population [cell species]
|
||||||
|
"Return the population of this species in this cell.
|
||||||
|
Species is assumed to be a keyword whose value in a cell should be an
|
||||||
|
integer."
|
||||||
|
(or (get cell species) 0))
|
|
@ -1,4 +1,5 @@
|
||||||
(ns mw-engine.world
|
(ns mw-engine.world
|
||||||
|
(:use mw-engine.utils)
|
||||||
(:require [clojure.math.combinatorics :as combo]))
|
(:require [clojure.math.combinatorics :as combo]))
|
||||||
|
|
||||||
(defn make-cell
|
(defn make-cell
|
||||||
|
@ -39,12 +40,19 @@
|
||||||
(nth (nth world y) x)))
|
(nth (nth world y) x)))
|
||||||
|
|
||||||
(defn get-neighbours
|
(defn get-neighbours
|
||||||
|
([world x y depth]
|
||||||
"Get the neighbours to distance depth of the cell at x, y in this world."
|
"Get the neighbours to distance depth of the cell at x, y in this world."
|
||||||
[world x y depth]
|
|
||||||
(map #(get-cell world (first %) (first (rest %)))
|
(map #(get-cell world (first %) (first (rest %)))
|
||||||
(combo/cartesian-product
|
(combo/cartesian-product
|
||||||
(range (- x depth) (+ x depth))
|
(range (- x depth) (+ x depth))
|
||||||
(range (- y depth) (+ y depth)))))
|
(range (- y depth) (+ y depth)))))
|
||||||
|
([world cell depth]
|
||||||
|
"Get the neighbours to distance depth of this cell in this world."
|
||||||
|
(get-neighbours world (:x cell) (:y cell) depth))
|
||||||
|
([world cell]
|
||||||
|
"Get the immediate neighbours of this cell in this world"
|
||||||
|
(get-neighbours world cell 1)))
|
||||||
|
|
||||||
|
|
||||||
(defn get-neighbours-with-state
|
(defn get-neighbours-with-state
|
||||||
"Get the neighbours to distance depth of the cell at x, y in this world which
|
"Get the neighbours to distance depth of the cell at x, y in this world which
|
||||||
|
@ -63,7 +71,10 @@
|
||||||
"Format one row in the state of a world for printing"
|
"Format one row in the state of a world for printing"
|
||||||
[row]
|
[row]
|
||||||
(apply str
|
(apply str
|
||||||
(map #(format "%10s" (truncate-state % 10)) row)))
|
(map #(format "%10s(%d/%d)"
|
||||||
|
(truncate-state % 10)
|
||||||
|
(population % :deer)
|
||||||
|
(population % :wolves)) row)))
|
||||||
|
|
||||||
(defn print-world
|
(defn print-world
|
||||||
"Print the current state of this world, and return nil"
|
"Print the current state of this world, and return nil"
|
||||||
|
|
Loading…
Reference in a new issue