Rule language now working cleanly with no errors showing. Very occasional

null pointer exception during parsing, not yet diagnosed.
This commit is contained in:
Simon Brooke 2014-07-20 15:15:12 +01:00
parent a61ace1694
commit 91310af2d8
4 changed files with 27 additions and 27 deletions

View file

@ -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
;; 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
;; 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 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
;; rules describing the impact of herbivores on the environment
;; if there are too many deer for the fertility of the area to sustain,
;; 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.
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.
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.
@ -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,
;; 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.
@ -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
## Potential blockers
;; Forest increases soil fertility.
if state is in forest or climax then fertility should be fertility + 1
## Initialisation rules
;; Rules which deal with state 'new' will waste less time if they're near the

View file

@ -30,22 +30,10 @@
"Compile each non-comment line of this `string` into an executable anonymous
function, and return the sequence of such functions."
[string]
(map #(compile-rule % true) (remove comment? (split string #"\n"))))
(map #(compile-rule % true) (remove comment? (trim (split string #"\n")))))
(defn compile-file
"Compile each non-comment line of the file indicated by this `filename` into
an executable anonymous function, and return the sequence of such functions."
[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))))

View file

@ -118,7 +118,7 @@
([tokens expect-int]
(or
(parse-disjunct-value tokens expect-int)
(parse-simple-value tokens)))
(parse-simple-value tokens expect-int)))
([tokens]
(parse-value tokens false)))

View file

@ -107,6 +107,14 @@
(is (nil? (apply afn (list {:altitude 200} nil)))
"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"
(let [afn (compile-rule "if altitude is less than 10 then state should be water")]
(is (= (apply afn (list {:altitude 9} nil))
@ -114,6 +122,14 @@
"Rule fires when condition is met")
(is (nil? (apply afn (list {:altitude 10} nil)))
"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"
(let [afn (compile-rule "if 3 neighbours have state equal to new then state should be water")
@ -396,7 +412,4 @@
(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)")
(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."))))