Rule language now working cleanly with no errors showing. Very occasional
null pointer exception during parsing, not yet diagnosed.
This commit is contained in:
parent
a61ace1694
commit
91310af2d8
|
@ -19,8 +19,6 @@ if state is forest and fertility is more than 5 then state should be climax
|
||||||
if state is climax then 1 chance in 500 state should be fire
|
if state is climax then 1 chance in 500 state should be fire
|
||||||
|
|
||||||
;; Climax forest neighbouring fires is likely to catch fire
|
;; Climax forest neighbouring fires is likely to catch fire
|
||||||
;; TODO: this rule, and specifically the 'some neighbours' clause, seems to give
|
|
||||||
;; rise to the 'Keyword cannot be cast to Number' bug.
|
|
||||||
if state is climax and some neighbours are fire then 1 chance in 3 state should be fire
|
if state is climax and some neighbours are fire then 1 chance in 3 state should be fire
|
||||||
|
|
||||||
;; After fire we get waste
|
;; After fire we get waste
|
||||||
|
@ -35,24 +33,19 @@ if state is waste and some neighbours are forest then state should be heath
|
||||||
if state is waste and some neighbours are climax then state should be heath
|
if state is waste and some neighbours are climax then state should be heath
|
||||||
if state is waste then state should be grassland
|
if state is waste then state should be grassland
|
||||||
|
|
||||||
;; Forest increases soil fertility. TODO: this rule compiles to what looks like
|
|
||||||
;; the right code but it never fires.
|
|
||||||
if state is in forest or climax then fertility should be fertility + 1
|
|
||||||
|
|
||||||
## Herbivore rules
|
## Herbivore rules
|
||||||
|
|
||||||
;; rules describing the impact of herbivores on the environment
|
;; rules describing the impact of herbivores on the environment
|
||||||
|
|
||||||
;; if there are too many deer for the fertility of the area to sustain,
|
;; if there are too many deer for the fertility of the area to sustain,
|
||||||
;; some die or move on.
|
;; some die or move on.
|
||||||
if deer are more than fertility then deer should be fertility / 2
|
;; if deer are more than fertility then deer should be fertility / 2
|
||||||
|
|
||||||
;; deer arrive occasionally at the edge of the map.
|
;; deer arrive occasionally at the edge of the map.
|
||||||
|
|
||||||
if x is 0 or y is 0 and deer are 0 then 1 chance in 50 deer should be 2
|
if x is 0 or y is 0 and deer are 0 then 1 chance in 50 deer should be 2
|
||||||
|
|
||||||
;; deer gradually spread through the world by breeding or migrating.
|
;; deer gradually spread through the world by breeding or migrating.
|
||||||
|
|
||||||
if fertility is more than 10 and deer is 0 and some neighbours have deer more than 2 then deer should be 2
|
if fertility is more than 10 and deer is 0 and some neighbours have deer more than 2 then deer should be 2
|
||||||
|
|
||||||
;; deer breed.
|
;; deer breed.
|
||||||
|
@ -68,7 +61,7 @@ if deer are more than wolves then deer should be deer - wolves
|
||||||
;; if there are not enough deer to sustain the population of wolves,
|
;; if there are not enough deer to sustain the population of wolves,
|
||||||
;; some wolves die or move on.
|
;; some wolves die or move on.
|
||||||
|
|
||||||
if wolves are more than deer then deer should be 0 and wolves should be deer
|
if wolves are more than deer then deer should be 0 and wolves should be deer + 0
|
||||||
|
|
||||||
;; wolves arrive occasionally at the edge of the map.
|
;; wolves arrive occasionally at the edge of the map.
|
||||||
|
|
||||||
|
@ -82,6 +75,12 @@ if state is not water and wolves is 0 and some neighbours have wolves more than
|
||||||
|
|
||||||
if wolves are more than 1 then wolves should be wolves * 2
|
if wolves are more than 1 then wolves should be wolves * 2
|
||||||
|
|
||||||
|
## Potential blockers
|
||||||
|
|
||||||
|
;; Forest increases soil fertility.
|
||||||
|
if state is in forest or climax then fertility should be fertility + 1
|
||||||
|
|
||||||
|
|
||||||
## Initialisation rules
|
## Initialisation rules
|
||||||
|
|
||||||
;; Rules which deal with state 'new' will waste less time if they're near the
|
;; Rules which deal with state 'new' will waste less time if they're near the
|
||||||
|
|
|
@ -30,22 +30,10 @@
|
||||||
"Compile each non-comment line of this `string` into an executable anonymous
|
"Compile each non-comment line of this `string` into an executable anonymous
|
||||||
function, and return the sequence of such functions."
|
function, and return the sequence of such functions."
|
||||||
[string]
|
[string]
|
||||||
(map #(compile-rule % true) (remove comment? (split string #"\n"))))
|
(map #(compile-rule % true) (remove comment? (trim (split string #"\n")))))
|
||||||
|
|
||||||
(defn compile-file
|
(defn compile-file
|
||||||
"Compile each non-comment line of the file indicated by this `filename` into
|
"Compile each non-comment line of the file indicated by this `filename` into
|
||||||
an executable anonymous function, and return the sequence of such functions."
|
an executable anonymous function, and return the sequence of such functions."
|
||||||
[filename]
|
[filename]
|
||||||
(compile-string (slurp filename)))
|
(compile-string (slurp filename)))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
;; (let [lines
|
|
||||||
;; (doall (with-open [rdr (reader filename)] (line-seq rdr)))]
|
|
||||||
;; (map parse-line lines)))
|
|
||||||
|
|
||||||
;;(defn parse-string
|
|
||||||
;; "Parse rules from successive lines in this `string`"
|
|
||||||
;; [string]
|
|
||||||
;; (parse-from-reader (BufferedReader. (StringReader. string))))
|
|
|
@ -118,7 +118,7 @@
|
||||||
([tokens expect-int]
|
([tokens expect-int]
|
||||||
(or
|
(or
|
||||||
(parse-disjunct-value tokens expect-int)
|
(parse-disjunct-value tokens expect-int)
|
||||||
(parse-simple-value tokens)))
|
(parse-simple-value tokens expect-int)))
|
||||||
([tokens]
|
([tokens]
|
||||||
(parse-value tokens false)))
|
(parse-value tokens false)))
|
||||||
|
|
||||||
|
|
|
@ -107,6 +107,14 @@
|
||||||
(is (nil? (apply afn (list {:altitude 200} nil)))
|
(is (nil? (apply afn (list {:altitude 200} nil)))
|
||||||
"Rule does not fire when condition is not met")))
|
"Rule does not fire when condition is not met")))
|
||||||
|
|
||||||
|
(testing "Property is more than property"
|
||||||
|
(let [afn (compile-rule "if wolves are more than deer then deer should be 0")]
|
||||||
|
(is (= (apply afn (list {:deer 2 :wolves 3} nil))
|
||||||
|
{:deer 0 :wolves 3})
|
||||||
|
"Rule fires when condition is met")
|
||||||
|
(is (nil? (apply afn (list {:deer 3 :wolves 2} nil)))
|
||||||
|
"Rule does not fire when condition is not met")))
|
||||||
|
|
||||||
(testing "Property is less than numeric-value"
|
(testing "Property is less than numeric-value"
|
||||||
(let [afn (compile-rule "if altitude is less than 10 then state should be water")]
|
(let [afn (compile-rule "if altitude is less than 10 then state should be water")]
|
||||||
(is (= (apply afn (list {:altitude 9} nil))
|
(is (= (apply afn (list {:altitude 9} nil))
|
||||||
|
@ -115,6 +123,14 @@
|
||||||
(is (nil? (apply afn (list {:altitude 10} nil)))
|
(is (nil? (apply afn (list {:altitude 10} nil)))
|
||||||
"Rule does not fire when condition is not met")))
|
"Rule does not fire when condition is not met")))
|
||||||
|
|
||||||
|
(testing "Property is less than property"
|
||||||
|
(let [afn (compile-rule "if wolves are less than deer then deer should be deer - wolves")]
|
||||||
|
(is (= (apply afn (list {:deer 3 :wolves 2} nil))
|
||||||
|
{:deer 1 :wolves 2})
|
||||||
|
"Rule fires when condition is met")
|
||||||
|
(is (nil? (apply afn (list {:deer 2 :wolves 3} nil)))
|
||||||
|
"Rule does not fire when condition is not met")))
|
||||||
|
|
||||||
(testing "Number neighbours have property equal to value"
|
(testing "Number neighbours have property equal to value"
|
||||||
(let [afn (compile-rule "if 3 neighbours have state equal to new then state should be water")
|
(let [afn (compile-rule "if 3 neighbours have state equal to new then state should be water")
|
||||||
world (make-world 3 3)]
|
world (make-world 3 3)]
|
||||||
|
@ -396,7 +412,4 @@
|
||||||
(is (= (:state (apply afn (list {:x 2 :y 2} world))) :beach)
|
(is (= (:state (apply afn (list {:x 2 :y 2} world))) :beach)
|
||||||
"Rule fires when condition is met (strip of altitude 11 down right hand side)")
|
"Rule fires when condition is met (strip of altitude 11 down right hand side)")
|
||||||
(is (nil? (apply afn (list {:x 0 :y 1} world)))
|
(is (nil? (apply afn (list {:x 0 :y 1} world)))
|
||||||
"Middle cell of the strip has only two high neighbours, so rule should not fire.")))
|
"Middle cell of the strip has only two high neighbours, so rule should not fire."))))
|
||||||
|
|
||||||
|
|
||||||
)
|
|
||||||
|
|
Loading…
Reference in a new issue