<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <link rel="stylesheet" href="../coverage.css"/> <title> mw_engine/utils.clj </title> </head> <body> <span class="covered" title="1 out of 1 forms covered"> 001 (ns ^{:doc " Utility functions needed by MicroWorld and, specifically, in the </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 002 interpretation of MicroWorld rule." </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 003 :author "Simon Brooke"} </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 004 mw-engine.utils </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 005 (:require [clojure.math.combinatorics :as combo] </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 006 [clojure.string :refer [join]])) </span><br/> <span class="blank" title="0 out of 0 forms covered"> 007 </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 008 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 009 ;;;; </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 010 ;;;; mw-engine: the state/transition engine of MicroWorld. </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 011 ;;;; </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 012 ;;;; This program is free software; you can redistribute it and/or </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 013 ;;;; modify it under the terms of the GNU General Public License </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 014 ;;;; as published by the Free Software Foundation; either version 2 </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 015 ;;;; of the License, or (at your option) any later version. </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 016 ;;;; </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 017 ;;;; This program is distributed in the hope that it will be useful, </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 018 ;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 019 ;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 020 ;;;; GNU General Public License for more details. </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 021 ;;;; </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 022 ;;;; You should have received a copy of the GNU General Public License </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 023 ;;;; along with this program; if not, write to the Free Software </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 024 ;;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 025 ;;;; USA. </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 026 ;;;; </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 027 ;;;; Copyright (C) 2014 Simon Brooke </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 028 ;;;; </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 029 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; </span><br/> <span class="blank" title="0 out of 0 forms covered"> 030 </span><br/> <span class="covered" title="1 out of 1 forms covered"> 031 (defn member? </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 032 "Return 'true' if elt is a member of col, else 'false'." </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 033 [elt col] </span><br/> <span class="not-covered" title="0 out of 6 forms covered"> 034 (contains? (set col) elt)) </span><br/> <span class="blank" title="0 out of 0 forms covered"> 035 </span><br/> <span class="covered" title="1 out of 1 forms covered"> 036 (defn get-int-or-zero </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 037 "Return the value of this `property` from this `map` if it is a integer; </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 038 otherwise return zero." </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 039 [map property] </span><br/> <span class="covered" title="4 out of 4 forms covered"> 040 (let [value (map property)] </span><br/> <span class="covered" title="6 out of 6 forms covered"> 041 (if (integer? value) value 0))) </span><br/> <span class="blank" title="0 out of 0 forms covered"> 042 </span><br/> <span class="covered" title="1 out of 1 forms covered"> 043 (defn init-generation </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 044 "Return a cell like this `cell`, but having a value for :generation, zero if </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 045 the cell passed had no integer value for generation, otherwise the value </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 046 taken from the cell passed. The `world` argument is present only for </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 047 consistency with the rule engine and is ignored." </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 048 [_ cell] </span><br/> <span class="not-covered" title="0 out of 9 forms covered"> 049 (merge cell {:generation (get-int-or-zero cell :generation)})) </span><br/> <span class="blank" title="0 out of 0 forms covered"> 050 </span><br/> <span class="covered" title="1 out of 1 forms covered"> 051 (defn in-bounds </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 052 "True if x, y are in bounds for this world (i.e., there is a cell at x, y) </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 053 else false. *DEPRECATED*: it's a predicate, prefer `in-bounds?`. </span><br/> <span class="blank" title="0 out of 0 forms covered"> 054 </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 055 * `world` a world as defined in [world.clj](mw-engine.world.html); </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 056 * `x` a number which may or may not be a valid x coordinate within that world; </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 057 * `y` a number which may or may not be a valid y coordinate within that world." </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 058 {:deprecated "1.1.7"} </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 059 [world x y] </span><br/> <span class="not-covered" title="0 out of 28 forms covered"> 060 (and (>= x 0) (>= y 0) (< y (count world)) (< x (count (first world))))) </span><br/> <span class="blank" title="0 out of 0 forms covered"> 061 </span><br/> <span class="covered" title="1 out of 1 forms covered"> 062 (defn in-bounds? </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 063 "True if x, y are in bounds for this world (i.e., there is a cell at x, y) </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 064 else false. </span><br/> <span class="blank" title="0 out of 0 forms covered"> 065 </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 066 * `world` a world as defined in [world.clj](mw-engine.world.html); </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 067 * `x` a number which may or may not be a valid x coordinate within that world; </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 068 * `y` a number which may or may not be a valid y coordinate within that world." </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 069 {:added "1.1.7"} </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 070 [world x y] </span><br/> <span class="covered" title="28 out of 28 forms covered"> 071 (and (>= x 0) (>= y 0) (< y (count world)) (< x (count (first world))))) </span><br/> <span class="blank" title="0 out of 0 forms covered"> 072 </span><br/> <span class="covered" title="1 out of 1 forms covered"> 073 (defn map-world-n-n </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 074 "Wholly non-parallel map world implementation; see documentation for `map-world`." </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 075 ([world function] </span><br/> <span class="not-covered" title="0 out of 5 forms covered"> 076 (map-world-n-n world function nil)) </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 077 ([world function additional-args] </span><br/> <span class="not-covered" title="0 out of 3 forms covered"> 078 (into [] </span><br/> <span class="not-covered" title="0 out of 3 forms covered"> 079 (map (fn [row] </span><br/> <span class="not-covered" title="0 out of 6 forms covered"> 080 (into [] (map </span><br/> <span class="not-covered" title="0 out of 3 forms covered"> 081 #(apply function </span><br/> <span class="not-covered" title="0 out of 7 forms covered"> 082 (cons world (cons % additional-args))) </span><br/> <span class="not-covered" title="0 out of 1 forms covered"> 083 row))) </span><br/> <span class="not-covered" title="0 out of 1 forms covered"> 084 world)))) </span><br/> <span class="blank" title="0 out of 0 forms covered"> 085 </span><br/> <span class="blank" title="0 out of 0 forms covered"> 086 </span><br/> <span class="covered" title="1 out of 1 forms covered"> 087 (defn map-world-p-p </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 088 "Wholly parallel map-world implementation; see documentation for `map-world`." </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 089 ([world function] </span><br/> <span class="not-covered" title="0 out of 5 forms covered"> 090 (map-world-p-p world function nil)) </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 091 ([world function additional-args] </span><br/> <span class="not-covered" title="0 out of 3 forms covered"> 092 (into [] </span><br/> <span class="not-covered" title="0 out of 3 forms covered"> 093 (pmap (fn [row] </span><br/> <span class="not-covered" title="0 out of 6 forms covered"> 094 (into [] (pmap </span><br/> <span class="not-covered" title="0 out of 3 forms covered"> 095 #(apply function </span><br/> <span class="not-covered" title="0 out of 7 forms covered"> 096 (cons world (cons % additional-args))) </span><br/> <span class="not-covered" title="0 out of 1 forms covered"> 097 row))) </span><br/> <span class="not-covered" title="0 out of 1 forms covered"> 098 world)))) </span><br/> <span class="blank" title="0 out of 0 forms covered"> 099 </span><br/> <span class="covered" title="1 out of 1 forms covered"> 100 (defn map-world </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 101 "Apply this `function` to each cell in this `world` to produce a new world. </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 102 the arguments to the function will be the world, the cell, and any </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 103 `additional-args` supplied. Note that we parallel map over rows but </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 104 just map over cells within a row. That's because it isn't worth starting </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 105 a new thread for each cell, but there may be efficiency gains in </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 106 running rows in parallel." </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 107 ([world function] </span><br/> <span class="covered" title="5 out of 5 forms covered"> 108 (map-world world function nil)) </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 109 ([world function additional-args] </span><br/> <span class="covered" title="3 out of 3 forms covered"> 110 (into [] </span><br/> <span class="covered" title="3 out of 3 forms covered"> 111 (pmap (fn [row] </span><br/> <span class="covered" title="6 out of 6 forms covered"> 112 (into [] (map </span><br/> <span class="covered" title="3 out of 3 forms covered"> 113 #(apply function </span><br/> <span class="covered" title="7 out of 7 forms covered"> 114 (cons world (cons % additional-args))) </span><br/> <span class="covered" title="1 out of 1 forms covered"> 115 row))) </span><br/> <span class="covered" title="1 out of 1 forms covered"> 116 world)))) </span><br/> <span class="blank" title="0 out of 0 forms covered"> 117 </span><br/> <span class="covered" title="1 out of 1 forms covered"> 118 (defn get-cell </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 119 "Return the cell a x, y in this world, if any. </span><br/> <span class="blank" title="0 out of 0 forms covered"> 120 </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 121 * `world` a world as defined in [world.clj](mw-engine.world.html); </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 122 * `x` a number which may or may not be a valid x coordinate within that world; </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 123 * `y` a number which may or may not be a valid y coordinate within that world." </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 124 [world x y] </span><br/> <span class="covered" title="7 out of 7 forms covered"> 125 (when (in-bounds? world x y) </span><br/> <span class="covered" title="5 out of 5 forms covered"> 126 (nth (nth world y) x))) </span><br/> <span class="blank" title="0 out of 0 forms covered"> 127 </span><br/> <span class="covered" title="1 out of 1 forms covered"> 128 (defn get-int </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 129 "Get the value of a property expected to be an integer from a map; if not </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 130 present (or not an integer) return 0. </span><br/> <span class="blank" title="0 out of 0 forms covered"> 131 </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 132 * `map` a map; </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 133 * `key` a symbol or keyword, presumed to be a key into the `map`." </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 134 [map key] </span><br/> <span class="covered" title="4 out of 4 forms covered"> 135 (if (map? map) </span><br/> <span class="covered" title="4 out of 4 forms covered"> 136 (let [v (map key)] </span><br/> <span class="covered" title="12 out of 12 forms covered"> 137 (cond (and v (integer? v)) v </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 138 :else 0)) </span><br/> <span class="not-covered" title="0 out of 3 forms covered"> 139 (throw (Exception. "No map passed?")))) </span><br/> <span class="blank" title="0 out of 0 forms covered"> 140 </span><br/> <span class="covered" title="136 out of 136 forms covered"> 141 (defmacro get-num </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 142 "Get the value of a property expected to be a number from a map; if not </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 143 present (or not a number) return 0. </span><br/> <span class="blank" title="0 out of 0 forms covered"> 144 </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 145 * `map` a map; </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 146 * `key` a symbol or keyword, presumed to be a key into the `map`." </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 147 [map key] </span><br/> <span class="covered" title="1 out of 1 forms covered"> 148 `(if (map? ~map) </span><br/> <span class="covered" title="2 out of 2 forms covered"> 149 (let [~'v (~map ~key)] </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 150 (cond (and ~'v (number? ~'v)) ~'v </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 151 :else 0)) </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 152 (throw (Exception. "No map passed?")))) </span><br/> <span class="blank" title="0 out of 0 forms covered"> 153 </span><br/> <span class="covered" title="1 out of 1 forms covered"> 154 (defn population </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 155 "Return the population of this species in this cell. Currently a synonym for </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 156 `get-int`, but may not always be (depending whether species are later </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 157 implemented as actors) </span><br/> <span class="blank" title="0 out of 0 forms covered"> 158 </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 159 * `cell` a map; </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 160 * `species` a keyword representing a species which may populate that cell." </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 161 [cell species] </span><br/> <span class="not-covered" title="0 out of 4 forms covered"> 162 (get-int cell species)) </span><br/> <span class="blank" title="0 out of 0 forms covered"> 163 </span><br/> <span class="covered" title="1 out of 1 forms covered"> 164 (def memo-get-neighbours </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 165 "Memoised get neighbours is more efficient when running deeply recursive </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 166 algorithms on the same world. But it's less efficient when running the </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 167 engine in its normal iterative style, because then we will rarely call </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 168 get naighbours on the same cell of the same world twice." </span><br/> <span class="covered" title="2 out of 2 forms covered"> 169 (memoize </span><br/> <span class="covered" title="1 out of 1 forms covered"> 170 (fn [world x y depth] </span><br/> <span class="covered" title="3 out of 3 forms covered"> 171 (remove nil? </span><br/> <span class="covered" title="14 out of 14 forms covered"> 172 (map #(get-cell world (first %) (first (rest %))) </span><br/> <span class="covered" title="9 out of 9 forms covered"> 173 (remove #(= % (list x y)) </span><br/> <span class="covered" title="2 out of 2 forms covered"> 174 (combo/cartesian-product </span><br/> <span class="covered" title="10 out of 10 forms covered"> 175 (range (- x depth) (+ x depth 1)) </span><br/> <span class="covered" title="10 out of 10 forms covered"> 176 (range (- y depth) (+ y depth 1))))))))) </span><br/> <span class="blank" title="0 out of 0 forms covered"> 177 </span><br/> <span class="covered" title="1 out of 1 forms covered"> 178 (defn get-neighbours </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 179 "Get the neighbours to distance depth of a cell in this world. </span><br/> <span class="blank" title="0 out of 0 forms covered"> 180 </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 181 Several overloads: </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 182 * `world` a world, as described in [world.clj](mw-engine.world.html); </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 183 * `cell` a cell within that world </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 184 Gets immediate neighbours of the specified cell. </span><br/> <span class="blank" title="0 out of 0 forms covered"> 185 </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 186 * `world` a world, as described in[world.clj](mw-engine.world.html); </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 187 * `cell` a cell within that world </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 188 * `depth` an integer representing the depth to search from the </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 189 `cell` </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 190 Gets neighbours within the specified distance of the cell. </span><br/> <span class="blank" title="0 out of 0 forms covered"> 191 </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 192 * `world` a world, as described in[world.clj](mw-engine.world.html); </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 193 * `x` an integer representing an x coordinate in that world; </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 194 * `y` an integer representing an y coordinate in that world; </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 195 * `depth` an integer representing the distance from [x,y] that </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 196 should be searched </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 197 Gets the neighbours within the specified distance of the cell at </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 198 coordinates [x,y] in this world." </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 199 ([world x y depth] </span><br/> <span class="covered" title="6 out of 6 forms covered"> 200 (memo-get-neighbours world x y depth)) </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 201 ([world cell depth] </span><br/> <span class="covered" title="10 out of 10 forms covered"> 202 (memo-get-neighbours world (:x cell) (:y cell) depth)) </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 203 ([world cell] </span><br/> <span class="covered" title="10 out of 10 forms covered"> 204 (memo-get-neighbours world (:x cell) (:y cell) 1))) </span><br/> <span class="blank" title="0 out of 0 forms covered"> 205 </span><br/> <span class="covered" title="1 out of 1 forms covered"> 206 (defn get-neighbours-with-property-value </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 207 "Get the neighbours to distance depth of the cell at x, y in this world which </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 208 have this value for this property. </span><br/> <span class="blank" title="0 out of 0 forms covered"> 209 </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 210 * `world` a world, as described in [world.clj](mw-engine.world.html); </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 211 * `cell` a cell within that world; </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 212 * `depth` an integer representing the distance from [x,y] that </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 213 should be searched (optional); </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 214 * `property` a keyword representing a property of the neighbours; </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 215 * `value` a value of that property (or, possibly, the name of another); </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 216 * `op` a comparator function to use in place of `=` (optional). </span><br/> <span class="blank" title="0 out of 0 forms covered"> 217 </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 218 It gets messy." </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 219 ([world x y depth property value op] </span><br/> <span class="covered" title="3 out of 3 forms covered"> 220 (filter </span><br/> <span class="covered" title="2 out of 2 forms covered"> 221 #(eval </span><br/> <span class="covered" title="3 out of 3 forms covered"> 222 (list op </span><br/> <span class="covered" title="11 out of 11 forms covered"> 223 (or (get % property) (get-int % property)) </span><br/> <span class="covered" title="1 out of 1 forms covered"> 224 value)) </span><br/> <span class="covered" title="6 out of 6 forms covered"> 225 (get-neighbours world x y depth))) </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 226 ([world x y depth property value] </span><br/> <span class="covered" title="9 out of 9 forms covered"> 227 (get-neighbours-with-property-value world x y depth property value =)) </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 228 ([world cell depth property value] </span><br/> <span class="not-covered" title="0 out of 10 forms covered"> 229 (get-neighbours-with-property-value world (:x cell) (:y cell) depth </span><br/> <span class="not-covered" title="0 out of 2 forms covered"> 230 property value)) </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 231 ([world cell property value] </span><br/> <span class="not-covered" title="0 out of 5 forms covered"> 232 (get-neighbours-with-property-value world cell 1 </span><br/> <span class="not-covered" title="0 out of 2 forms covered"> 233 property value))) </span><br/> <span class="blank" title="0 out of 0 forms covered"> 234 </span><br/> <span class="covered" title="1 out of 1 forms covered"> 235 (defn get-neighbours-with-state </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 236 "Get the neighbours to distance depth of the cell at x, y in this world which </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 237 have this state. </span><br/> <span class="blank" title="0 out of 0 forms covered"> 238 </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 239 * `world` a world, as described in [world.clj](mw-engine.world.html); </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 240 * `cell` a cell within that world; </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 241 * `depth` an integer representing the distance from [x,y] that </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 242 should be searched; </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 243 * `state` a keyword representing a state in the world." </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 244 ([world x y depth state] </span><br/> <span class="not-covered" title="0 out of 14 forms covered"> 245 (filter #(= (:state %) state) (get-neighbours world x y depth))) </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 246 ([world cell depth state] </span><br/> <span class="not-covered" title="0 out of 11 forms covered"> 247 (get-neighbours-with-state world (:x cell) (:y cell) depth state)) </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 248 ([world cell state] </span><br/> <span class="not-covered" title="0 out of 6 forms covered"> 249 (get-neighbours-with-state world cell 1 state))) </span><br/> <span class="blank" title="0 out of 0 forms covered"> 250 </span><br/> <span class="covered" title="1 out of 1 forms covered"> 251 (defn get-least-cell </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 252 "Return the cell from among these `cells` which has the lowest numeric value </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 253 for this `property`." </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 254 [cells property] </span><br/> <span class="covered" title="14 out of 14 forms covered"> 255 (first (sort-by property (filter #(number? (property %)) cells)))) </span><br/> <span class="blank" title="0 out of 0 forms covered"> 256 </span><br/> <span class="covered" title="1 out of 1 forms covered"> 257 (defn get-most-cell </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 258 "Return the cell from among these `cells` which has the highest numeric value </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 259 for this `property`." </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 260 [cells property] </span><br/> <span class="covered" title="14 out of 14 forms covered"> 261 (last (sort-by property (filter #(number? (property %)) cells)))) </span><br/> <span class="blank" title="0 out of 0 forms covered"> 262 </span><br/> <span class="covered" title="1 out of 1 forms covered"> 263 (defn- set-cell-property </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 264 "If this `cell`s x and y properties are equal to these `x` and `y` values, </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 265 return a cell like this cell but with the value of this `property` set to </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 266 this `value`. Otherwise, just return this `cell`." </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 267 [cell x y property value] </span><br/> <span class="covered" title="2 out of 2 forms covered"> 268 (cond </span><br/> <span class="covered" title="14 out of 14 forms covered"> 269 (and (= x (:x cell)) (= y (:y cell))) </span><br/> <span class="covered" title="8 out of 8 forms covered"> 270 (merge cell {property value :rule "Set by user"}) </span><br/> <span class="covered" title="1 out of 1 forms covered"> 271 :else cell)) </span><br/> <span class="blank" title="0 out of 0 forms covered"> 272 </span><br/> <span class="covered" title="1 out of 1 forms covered"> 273 (defn set-property </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 274 "Return a world like this `world` but with the value of exactly one `property` </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 275 of one `cell` changed to this `value`" </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 276 ([world cell property value] </span><br/> <span class="covered" title="11 out of 11 forms covered"> 277 (set-property world (:x cell) (:y cell) property value)) </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 278 ([world x y property value] </span><br/> <span class="covered" title="2 out of 2 forms covered"> 279 (apply </span><br/> <span class="covered" title="1 out of 1 forms covered"> 280 vector ;; we want a vector of vectors, not a list of lists, for efficiency </span><br/> <span class="covered" title="2 out of 2 forms covered"> 281 (map </span><br/> <span class="covered" title="1 out of 1 forms covered"> 282 (fn [row] </span><br/> <span class="covered" title="2 out of 2 forms covered"> 283 (apply </span><br/> <span class="covered" title="1 out of 1 forms covered"> 284 vector </span><br/> <span class="covered" title="10 out of 10 forms covered"> 285 (map #(set-cell-property % x y property value) </span><br/> <span class="covered" title="1 out of 1 forms covered"> 286 row))) </span><br/> <span class="covered" title="1 out of 1 forms covered"> 287 world)))) </span><br/> <span class="blank" title="0 out of 0 forms covered"> 288 </span><br/> <span class="covered" title="1 out of 1 forms covered"> 289 (defn merge-cell </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 290 "Return a world like this `world`, but merge the values from this `cell` with </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 291 those from the cell in the world with the same co-ordinates" </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 292 [world cell] </span><br/> <span class="covered" title="10 out of 10 forms covered"> 293 (if (in-bounds? world (:x cell) (:y cell)) </span><br/> <span class="covered" title="4 out of 4 forms covered"> 294 (map-world world </span><br/> <span class="covered" title="2 out of 2 forms covered"> 295 #(if </span><br/> <span class="covered" title="5 out of 5 forms covered"> 296 (and </span><br/> <span class="covered" title="7 out of 7 forms covered"> 297 (= (:x cell) (:x %2)) </span><br/> <span class="covered" title="6 out of 6 forms covered"> 298 (= (:y cell) (:y %2))) </span><br/> <span class="covered" title="4 out of 4 forms covered"> 299 (merge %2 cell) </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 300 %2)) </span><br/> <span class="covered" title="1 out of 1 forms covered"> 301 world)) </span><br/> <span class="blank" title="0 out of 0 forms covered"> 302 </span><br/> <span class="covered" title="1 out of 1 forms covered"> 303 (defn rule-type </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 304 "Return the rule-type of this compiled `rule`." </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 305 [rule] </span><br/> <span class="covered" title="5 out of 5 forms covered"> 306 (:rule-type (meta rule))) </span><br/> <span class="blank" title="0 out of 0 forms covered"> 307 </span><br/> <span class="covered" title="1 out of 1 forms covered"> 308 (defn add-history-event </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 309 "If `cell` is non-nil, expect it to be a map representing a cell; add </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 310 to its history an an event recording the firing of this rule. If </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 311 `detail` is passed, treat it as a map of additional data to be </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 312 added to the event." </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 313 ([cell rule] </span><br/> <span class="covered" title="8 out of 8 forms covered"> 314 (when cell (add-history-event cell rule {}))) </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 315 ([result rule detail] </span><br/> <span class="covered" title="3 out of 3 forms covered"> 316 (when result </span><br/> <span class="covered" title="4 out of 4 forms covered"> 317 (let [rule-meta (meta rule) </span><br/> <span class="covered" title="7 out of 7 forms covered"> 318 event {:rule (:source rule-meta) </span><br/> <span class="covered" title="3 out of 3 forms covered"> 319 :rule-type (:rule-type rule-meta) </span><br/> <span class="covered" title="3 out of 3 forms covered"> 320 :generation (get-int-or-zero </span><br/> <span class="covered" title="1 out of 1 forms covered"> 321 result </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 322 :generation)} </span><br/> <span class="partial" title="6 out of 7 forms covered"> 323 event' (if detail (merge event detail) event)] </span><br/> <span class="covered" title="3 out of 3 forms covered"> 324 (merge result </span><br/> <span class="covered" title="4 out of 4 forms covered"> 325 {:history (concat </span><br/> <span class="covered" title="3 out of 3 forms covered"> 326 (:history result) </span><br/> <span class="covered" title="3 out of 3 forms covered"> 327 (list event'))}))))) </span><br/> <span class="blank" title="0 out of 0 forms covered"> 328 </span><br/> <span class="covered" title="1 out of 1 forms covered"> 329 (defn- event-narrative [event] </span><br/> <span class="not-covered" title="0 out of 11 forms covered"> 330 (case (:rule-type event) </span><br/> <span class="not-covered" title="0 out of 3 forms covered"> 331 :production (:rule event) </span><br/> <span class="not-covered" title="0 out of 3 forms covered"> 332 :flow (format "%s %f units of %s %s %d,%d:\n %s" </span><br/> <span class="not-covered" title="0 out of 5 forms covered"> 333 (name (:direction event)) </span><br/> <span class="not-covered" title="0 out of 3 forms covered"> 334 (:quantity event) </span><br/> <span class="not-covered" title="0 out of 3 forms covered"> 335 (:property event) </span><br/> <span class="not-covered" title="0 out of 8 forms covered"> 336 (if (= :sent (:direction event)) "to" "from") </span><br/> <span class="not-covered" title="0 out of 5 forms covered"> 337 (:x (:other event)) </span><br/> <span class="not-covered" title="0 out of 5 forms covered"> 338 (:y (:other event)) </span><br/> <span class="not-covered" title="0 out of 3 forms covered"> 339 (:rule event)))) </span><br/> <span class="blank" title="0 out of 0 forms covered"> 340 </span><br/> <span class="covered" title="1 out of 1 forms covered"> 341 (defn history-string </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 342 "Return the history of this `cell` as a string for presentation to the user." </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 343 [cell] </span><br/> <span class="not-covered" title="0 out of 3 forms covered"> 344 (join "\n" </span><br/> <span class="not-covered" title="0 out of 12 forms covered"> 345 (map #(format "%6d: %s" (:generation %) (event-narrative %)) </span><br/> <span class="not-covered" title="0 out of 3 forms covered"> 346 (:history cell)))) </span><br/> <span class="blank" title="0 out of 0 forms covered"> 347 </span><br/> <span class="covered" title="1 out of 1 forms covered"> 348 (defn- extend-summary [summary rs rl event] </span><br/> <span class="not-covered" title="0 out of 3 forms covered"> 349 (str summary </span><br/> <span class="not-covered" title="0 out of 6 forms covered"> 350 (if rs (format "%d-%d (%d occurances): %s\n" rs </span><br/> <span class="not-covered" title="0 out of 3 forms covered"> 351 (:generation event) </span><br/> <span class="not-covered" title="0 out of 1 forms covered"> 352 rl </span><br/> <span class="not-covered" title="0 out of 3 forms covered"> 353 (event-narrative event)) </span><br/> <span class="not-covered" title="0 out of 6 forms covered"> 354 (format "%d: %s\n" (:generation event) </span><br/> <span class="not-covered" title="0 out of 3 forms covered"> 355 (event-narrative event))))) </span><br/> <span class="blank" title="0 out of 0 forms covered"> 356 </span><br/> <span class="covered" title="1 out of 1 forms covered"> 357 (defn summarise-history </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 358 "Return, as a string, a shorter summary of the history of this cell" </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 359 [cell] </span><br/> <span class="not-covered" title="0 out of 10 forms covered"> 360 (loop [history (rest (:history cell)) </span><br/> <span class="not-covered" title="0 out of 5 forms covered"> 361 event (first (:history cell)) </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 362 prev nil </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 363 rs nil </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 364 rl 0 </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 365 summary ""] </span><br/> <span class="not-covered" title="0 out of 12 forms covered"> 366 (cond (nil? event) (extend-summary summary rs rl prev) </span><br/> <span class="not-covered" title="0 out of 8 forms covered"> 367 (= (:rule event) (:rule prev)) (recur </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 368 (rest history) </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 369 (first history) </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 370 event </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 371 (or rs (:generation event)) </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 372 (inc rl) </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 373 summary) </span><br/> <span class="not-covered" title="0 out of 1 forms covered"> 374 :else (recur (rest history) </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 375 (first history) </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 376 event </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 377 nil </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 378 0 </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 379 (extend-summary summary rs (inc rl) event))))) </span><br/> </body> </html>