117 lines
4.3 KiB
Clojure
117 lines
4.3 KiB
Clojure
;; Utility functions needed by MicroWorld and, specifically, in the interpretation of MicroWorld rule.
|
|
|
|
(ns mw-engine.utils
|
|
(:require [clojure.math.combinatorics :as combo]))
|
|
|
|
(defn member?
|
|
"True if elt is a member of col."
|
|
[elt col] (some #(= elt %) col))
|
|
|
|
(defn in-bounds
|
|
"True if x, y are in bounds for this world (i.e., there is a cell at x, y)
|
|
else false.
|
|
|
|
* `world` a world as defined above;
|
|
* `x` a number which may or may not be a valid x coordinate within that world;
|
|
* `y` a number which may or may not be a valid y coordinate within that world."
|
|
[world x y]
|
|
(and (>= x 0)(>= y 0)(< y (count world))(< x (count (first world)))))
|
|
|
|
(defn get-cell
|
|
"Return the cell a x, y in this world, if any.
|
|
|
|
* `world` a world as defined above;
|
|
* `x` a number which may or may not be a valid x coordinate within that world;
|
|
* `y` a number which may or may not be a valid y coordinate within that world."
|
|
[world x y]
|
|
(cond (in-bounds world x y)
|
|
(nth (nth world y) x)))
|
|
|
|
(defn get-int
|
|
"Get the value of a property expected to be an integer from a map; if not present (or not an integer) return 0.
|
|
|
|
* `map` a map;
|
|
* `key` a symbol or keyword, presumed to be a key into the `map`."
|
|
[map key]
|
|
(cond map
|
|
(let [v (map key)]
|
|
(cond (and v (integer? v)) v
|
|
true 0))
|
|
true (throw (Exception. "No map passed?"))))
|
|
|
|
(defn population
|
|
"Return the population of this species in this cell. Currently a synonym for
|
|
`get-int`, but may not always be (depending whether species are later
|
|
implemented as actors)
|
|
|
|
* `cell` a map;
|
|
* `species` a keyword representing a species which may populate that cell."
|
|
[cell species]
|
|
(get-int cell species))
|
|
|
|
|
|
(defn get-neighbours
|
|
([world x y depth]
|
|
"Get the neighbours to distance depth of the cell at x, y in this world.
|
|
|
|
* `world` a world, as described in world.clj;
|
|
* `x` an integer representing an x coordinate in that world;
|
|
* `y` an integer representing an y coordinate in that world;
|
|
* `depth` an integer representing the distance from [x,y] that
|
|
should be searched."
|
|
(remove nil?
|
|
(map #(get-cell world (first %) (first (rest %)))
|
|
(remove #(= % (list x y))
|
|
(combo/cartesian-product
|
|
(range (- x depth) (+ x depth 1))
|
|
(range (- y depth) (+ y depth 1)))))))
|
|
([world cell depth]
|
|
"Get the neighbours to distance depth of this cell in this world.
|
|
|
|
* `world` a world, as described in world.clj;
|
|
* `cell` a cell within that world;
|
|
* `depth` an integer representing the distance from [x,y] that
|
|
should be searched."
|
|
(get-neighbours world (:x cell) (:y cell) depth))
|
|
([world cell]
|
|
"Get the immediate neighbours of this cell in this world
|
|
|
|
* `world` a world, as described in world.clj;
|
|
* `cell` a cell within that world."
|
|
(get-neighbours world cell 1)))
|
|
|
|
(defn get-neighbours-with-property-value
|
|
"Get the neighbours to distance depth of the cell at x, y in this world which
|
|
have this value for this property.
|
|
|
|
* `world` a world, as described in `world.clj`;
|
|
* `cell` a cell within that world;
|
|
* `depth` an integer representing the distance from [x,y] that
|
|
should be searched;
|
|
* `property` a keyword representing a property of the neighbours.
|
|
* `value` a value of that property"
|
|
([world x y depth property value]
|
|
(filter #(= (get % property) value) (get-neighbours world x y depth)))
|
|
([world cell depth property value]
|
|
(get-neighbours-with-property-value world (:x cell) (:y cell) depth
|
|
property value))
|
|
([world cell property value]
|
|
(get-neighbours-with-property-value world cell 1
|
|
property value)))
|
|
|
|
(defn get-neighbours-with-state
|
|
"Get the neighbours to distance depth of the cell at x, y in this world which
|
|
have this state.
|
|
|
|
* `world` a world, as described in `world.clj`;
|
|
* `cell` a cell within that world;
|
|
* `depth` an integer representing the distance from [x,y] that
|
|
should be searched;
|
|
* `state` a keyword representing a state in the world."
|
|
([world x y depth state]
|
|
(filter #(= (:state %) state) (get-neighbours world x y depth)))
|
|
([world cell depth state]
|
|
(get-neighbours-with-state world (:x cell) (:y cell) depth state))
|
|
([world cell state]
|
|
(get-neighbours-with-state world cell 1 state)))
|