diff --git a/.lein-repl-history b/.lein-repl-history index bbcf12a..c6daaea 100644 --- a/.lein-repl-history +++ b/.lein-repl-history @@ -1 +1,11 @@ (quit) +(clojure.set/difference [1 2 3] [1 2]) +(clojure.set/difference (set [1 2 3]) (set [1 2])) +(vent) +(use 'agents.vent) +(use 'pucks.agents.vent) +(vent) +(keys (vent)) +(use 'pucks.agents.active) +(keys (active)) +(quit) diff --git a/.settings/ccw.repl.cmdhistory.prefs b/.settings/ccw.repl.cmdhistory.prefs index be9f06e..60c949a 100644 --- a/.settings/ccw.repl.cmdhistory.prefs +++ b/.settings/ccw.repl.cmdhistory.prefs @@ -1,2 +1,2 @@ -cmdhistory=["(run-pucks (agents) (settings))" "(user-proposals (active))" "(let [p (active)]\\n (println \\"puck\:\\" p)\\n (println \\"proposals\:\\" (user-proposals p)))" "(user)" "(relativize-position {\:position [700 400]} [100 400]})" "(relativize-position {\:position [700 400]} [100 400])" "(-v [700 400] [100 400])" "(-v [100 400] [700 400])" "(abs -2)" "(relativize-position {\:position [700 400]} [100 400])" "(range 100 701 200)" "(for [x (range 100 701 200)\\n y (range 100 701 200)]\\n (merge (beacon) {\:position [x y]\\n \:id [x y]}))" "(for [x (range 100 701 200)\\n y (range 100 701 200)]\\n {\:position [x y]\\n \:id [x y]})" "(abs 1)" "(distance [100 400] [700 400])" "(relativize-position {\:position [100 100]} [0 0])" "(relativize-position {\:position [100 100]} [50 50])" "(relativize-position {\:position [100 100]} [25 25])" "(active)" "(+ 1 2)" "(type (filter even? (take 20 (range 50))))" "(type (apply list (filter even? (take 20 (range 50)))))" "(\:energy 1.2)" "(filter \:foo nil)" "(run-pucks (agents) (settings))" "(torpedo)" "(filter (fn [[k v]] (\=\= v true)) (torpedo))" "(filter (fn [[k v]] (\= v true)) (torpedo))" "(defn types [p]\\n (map first (filter (fn [[k v]] (\= v true)) p)))" "(types (torpedo))" "(remove \:foo [\:bar \:foo \:baz \:foo])" "(defn remove-one\\n \\"Returns sequence s without the first item for which predicate p is true.\\"\\n [s p]\\n (let [[without-item with-item] (split-with \#(not (p %)) s)]\\n (concat without-item (rest with-item))))" "(defn remove-one\\n \\"Returns sequence s without the first instance of item.\\"\\n [s item]\\n (let [[without-item with-item] (split-with \#(not (\= item %)) s)]\\n (concat without-item (rest with-item))))" "(remove-one \:foo [\:bar \:foo \:baz \:foo \:bingo \:foo \:blah])" "(defn remove-one\\n \\"Returns sequence s without the first instance of item.\\"\\n [item s]\\n (let [[without-item with-item] (split-with \#(not (\= item %)) s)]\\n (concat without-item (rest with-item))))" "(remove-one \:foo [\:bar \:foo \:baz \:foo \:bingo \:foo \:blah])" "(remove-one \:fool [\:bar \:foo \:baz \:foo \:bingo \:foo \:blah])" "(avgv [0 0] [1 1])" "(use 'pucks.vec2D)" "(avgv [0 0] [1 1])" "(avgv [0 0])" "(count \#{})" "(count \#{1 2 3})" "(into \#{} [1 2 3])" "(direction->rotation nil)" "(use 'pucks.util)" "(direction->rotation nil)" "grid" "@grid" "grid-size" "(repeat grid-size (repeat grid-size []))" "(to-array-2d (repeat grid-size (repeat grid-size [])))" "(aset @grid 2 2 [1 2 3])" "(aget @grid 2 2)" "(quot 10 3)" "(int (/ 10 3))" "@pucks-settings" "grid-size" "(def foo (vec (repeat 4 (vec (repeat 4 [])))))" "foo" "(update-in foo [1 1] conj 5)" "(get-in foo [1 1])" "(get-in (update-in foo [1 1] conj 5) [1 1])" "(vent)" "(concat (repeat 3 (nursery linear))\\n (repeat 3 (nursery swarmer))\\n (repeat 3 (nursery zigzag))\\n (repeat 8 (vent))\\n (repeat 8 (zapper)))" "(clojure.inspector/inspect (concat (repeat 3 (nursery linear))\\n (repeat 3 (nursery swarmer))\\n (repeat 3 (nursery zigzag))\\n (repeat 8 (vent))\\n (repeat 8 (zapper))))" "(clojure.inspector/inspect-tree (concat (repeat 3 (nursery linear))\\n (repeat 3 (nursery swarmer))\\n (repeat 3 (nursery zigzag))\\n (repeat 8 (vent))\\n (repeat 8 (zapper))))" "(clojure.inspector/inspect-tree (vec (concat (repeat 3 (nursery linear))\\n (repeat 3 (nursery swarmer))\\n (repeat 3 (nursery zigzag))\\n (repeat 8 (vent))\\n (repeat 8 (zapper)))))" "(map \:position (vec (concat (repeat 3 (nursery linear))\\n (repeat 3 (nursery swarmer))\\n (repeat 3 (nursery zigzag))\\n (repeat 8 (vent))\\n (repeat 8 (zapper)))))" "(map \:position (mapv (fn [p loc]\\n (merge p {\:position loc}))\\n (vec (concat (repeat 3 (nursery linear))\\n (repeat 3 (nursery swarmer))\\n (repeat 3 (nursery zigzag))\\n (repeat 8 (vent))\\n (repeat 8 (zapper))))\\n (shuffle (for [x [100 300 500 700 900 1100 1300 1500]\\n y [100 300 500 700 900 1100 1300 1500]]\\n [x y]))))" "(count (mapv (fn [p loc]\\n (merge p {\:position loc}))\\n (vec (concat (repeat 3 (nursery linear))\\n (repeat 3 (nursery swarmer))\\n (repeat 3 (nursery zigzag))\\n (repeat 8 (vent))\\n (repeat 8 (zapper))))\\n (vec (shuffle (for [x [100 300 500 700 900 1100 1300 1500]\\n y [100 300 500 700 900 1100 1300 1500]]\\n [x y])))))" "(map \:position (mapv (fn [p loc]\\n (merge p {\:position loc}))\\n (vec (concat (repeat 3 (nursery linear))\\n (repeat 3 (nursery swarmer))\\n (repeat 3 (nursery zigzag))\\n (repeat 8 (vent))\\n (repeat 8 (zapper))))\\n (vec (shuffle (for [x [100 300 500 700 900 1100 1300 1500]\\n y [100 300 500 700 900 1100 1300 1500]]\\n [x y])))))" "@pucks-settings" "(mapv inc [])" "(if (mapv inc []) 1 0)" "(merge {\:foo 2} nil {\:bar 3})" "(mutate-urge 0.4)" "(if nil 1 2)" "(mutate-color [100 100 100])" "(hash {\:foo 2 \:bar 3})" "(run-pucks (agents) (settings))" "(def foo [{\:rotation 4.118058161261986, \:color [139 0 0], \:solid true, \:nursery true, \:steps 49, \:energy 1, \:radius 50, \:proposals {}, \:just-collided false, \:id puck-1078, \:position [700 700], \:mobile false, \:velocity [0 0]} {\:rotation -2.3451359272003174, \:color [128 255 0], \:solid true, \:steps 19, \:energy 0.8619999999999999, \:radius 20, \:proposals {\:acceleration 1, \:rotation -2.345136, \:transfer [{\:self puck-1082, \:other puck-1078, \:bid {}, \:ask \#}]}, \:just-collided false, \:active true, \:id puck-1082, \:core-color [0 255 0], \:position [652.2886938139176 736.3236466351844], \:eye-color [255 255 0], \:mobile true, \:velocity [-2.8596007328491666 2.7969060850676613]} {\:rotation 1.855639934539795, \:color [128 255 0], \:solid true, \:steps 39, \:energy 0.8019999999999998, \:radius 20, \:proposals {\:acceleration 1, \:rotation 1.8556399, \:transfer []}, \:just-collided false, \:active true, \:id puck-1080, \:core-color [0 255 0], \:position [5.384725944599863 753.7339998389651], \:eye-color [255 255 0], \:mobile true, \:velocity [3.838822449948592 1.124029447021157]} {\:vent true, \:rotation 0.623824165640358, \:color [255 255 255], \:solid true, \:steps 49, \:energy 1, \:radius 50, \:proposals {\:transfer []}, \:just-collided false, \:id puck-1075, \:position [700 500], \:mobile false, \:velocity [0 0]} {\:rotation 4.045812706401674, \:color [207 19 200], \:solid true, \:zapper true, \:steps 49, \:energy 1, \:radius 50, \:proposals {\:transfer []}, \:just-collided false, \:id puck-1076, \:position [100 500], \:mobile false, \:velocity [0 0]} {\:rotation 3.9483649032752286, \:color [139 0 0], \:solid true, \:nursery true, \:steps 49, \:energy 1, \:radius 50, \:proposals {}, \:just-collided false, \:id puck-1077, \:position [700 300], \:mobile false, \:velocity [0 0]}])"] +cmdhistory=["(run-pucks (agents) (settings))" "(user-proposals (active))" "(let [p (active)]\\n (println \\"puck\:\\" p)\\n (println \\"proposals\:\\" (user-proposals p)))" "(user)" "(relativize-position {\:position [700 400]} [100 400]})" "(relativize-position {\:position [700 400]} [100 400])" "(-v [700 400] [100 400])" "(-v [100 400] [700 400])" "(abs -2)" "(relativize-position {\:position [700 400]} [100 400])" "(range 100 701 200)" "(for [x (range 100 701 200)\\n y (range 100 701 200)]\\n (merge (beacon) {\:position [x y]\\n \:id [x y]}))" "(for [x (range 100 701 200)\\n y (range 100 701 200)]\\n {\:position [x y]\\n \:id [x y]})" "(abs 1)" "(distance [100 400] [700 400])" "(relativize-position {\:position [100 100]} [0 0])" "(relativize-position {\:position [100 100]} [50 50])" "(relativize-position {\:position [100 100]} [25 25])" "(active)" "(+ 1 2)" "(type (filter even? (take 20 (range 50))))" "(type (apply list (filter even? (take 20 (range 50)))))" "(\:energy 1.2)" "(filter \:foo nil)" "(run-pucks (agents) (settings))" "(torpedo)" "(filter (fn [[k v]] (\=\= v true)) (torpedo))" "(filter (fn [[k v]] (\= v true)) (torpedo))" "(defn types [p]\\n (map first (filter (fn [[k v]] (\= v true)) p)))" "(types (torpedo))" "(remove \:foo [\:bar \:foo \:baz \:foo])" "(defn remove-one\\n \\"Returns sequence s without the first item for which predicate p is true.\\"\\n [s p]\\n (let [[without-item with-item] (split-with \#(not (p %)) s)]\\n (concat without-item (rest with-item))))" "(defn remove-one\\n \\"Returns sequence s without the first instance of item.\\"\\n [s item]\\n (let [[without-item with-item] (split-with \#(not (\= item %)) s)]\\n (concat without-item (rest with-item))))" "(remove-one \:foo [\:bar \:foo \:baz \:foo \:bingo \:foo \:blah])" "(defn remove-one\\n \\"Returns sequence s without the first instance of item.\\"\\n [item s]\\n (let [[without-item with-item] (split-with \#(not (\= item %)) s)]\\n (concat without-item (rest with-item))))" "(remove-one \:foo [\:bar \:foo \:baz \:foo \:bingo \:foo \:blah])" "(remove-one \:fool [\:bar \:foo \:baz \:foo \:bingo \:foo \:blah])" "(avgv [0 0] [1 1])" "(use 'pucks.vec2D)" "(avgv [0 0] [1 1])" "(avgv [0 0])" "(count \#{})" "(count \#{1 2 3})" "(into \#{} [1 2 3])" "(direction->rotation nil)" "(use 'pucks.util)" "(direction->rotation nil)" "grid" "@grid" "grid-size" "(repeat grid-size (repeat grid-size []))" "(to-array-2d (repeat grid-size (repeat grid-size [])))" "(aset @grid 2 2 [1 2 3])" "(aget @grid 2 2)" "(quot 10 3)" "(int (/ 10 3))" "@pucks-settings" "grid-size" "(def foo (vec (repeat 4 (vec (repeat 4 [])))))" "foo" "(update-in foo [1 1] conj 5)" "(get-in foo [1 1])" "(get-in (update-in foo [1 1] conj 5) [1 1])" "(vent)" "(concat (repeat 3 (nursery linear))\\n (repeat 3 (nursery swarmer))\\n (repeat 3 (nursery zigzag))\\n (repeat 8 (vent))\\n (repeat 8 (zapper)))" "(clojure.inspector/inspect (concat (repeat 3 (nursery linear))\\n (repeat 3 (nursery swarmer))\\n (repeat 3 (nursery zigzag))\\n (repeat 8 (vent))\\n (repeat 8 (zapper))))" "(clojure.inspector/inspect-tree (concat (repeat 3 (nursery linear))\\n (repeat 3 (nursery swarmer))\\n (repeat 3 (nursery zigzag))\\n (repeat 8 (vent))\\n (repeat 8 (zapper))))" "(clojure.inspector/inspect-tree (vec (concat (repeat 3 (nursery linear))\\n (repeat 3 (nursery swarmer))\\n (repeat 3 (nursery zigzag))\\n (repeat 8 (vent))\\n (repeat 8 (zapper)))))" "(map \:position (vec (concat (repeat 3 (nursery linear))\\n (repeat 3 (nursery swarmer))\\n (repeat 3 (nursery zigzag))\\n (repeat 8 (vent))\\n (repeat 8 (zapper)))))" "(map \:position (mapv (fn [p loc]\\n (merge p {\:position loc}))\\n (vec (concat (repeat 3 (nursery linear))\\n (repeat 3 (nursery swarmer))\\n (repeat 3 (nursery zigzag))\\n (repeat 8 (vent))\\n (repeat 8 (zapper))))\\n (shuffle (for [x [100 300 500 700 900 1100 1300 1500]\\n y [100 300 500 700 900 1100 1300 1500]]\\n [x y]))))" "(count (mapv (fn [p loc]\\n (merge p {\:position loc}))\\n (vec (concat (repeat 3 (nursery linear))\\n (repeat 3 (nursery swarmer))\\n (repeat 3 (nursery zigzag))\\n (repeat 8 (vent))\\n (repeat 8 (zapper))))\\n (vec (shuffle (for [x [100 300 500 700 900 1100 1300 1500]\\n y [100 300 500 700 900 1100 1300 1500]]\\n [x y])))))" "(map \:position (mapv (fn [p loc]\\n (merge p {\:position loc}))\\n (vec (concat (repeat 3 (nursery linear))\\n (repeat 3 (nursery swarmer))\\n (repeat 3 (nursery zigzag))\\n (repeat 8 (vent))\\n (repeat 8 (zapper))))\\n (vec (shuffle (for [x [100 300 500 700 900 1100 1300 1500]\\n y [100 300 500 700 900 1100 1300 1500]]\\n [x y])))))" "@pucks-settings" "(mapv inc [])" "(if (mapv inc []) 1 0)" "(merge {\:foo 2} nil {\:bar 3})" "(mutate-urge 0.4)" "(if nil 1 2)" "(mutate-color [100 100 100])" "(hash {\:foo 2 \:bar 3})" "(run-pucks (agents) (settings))" "(def foo [{\:rotation 4.118058161261986, \:color [139 0 0], \:solid true, \:nursery true, \:steps 49, \:energy 1, \:radius 50, \:proposals {}, \:just-collided false, \:id puck-1078, \:position [700 700], \:mobile false, \:velocity [0 0]} {\:rotation -2.3451359272003174, \:color [128 255 0], \:solid true, \:steps 19, \:energy 0.8619999999999999, \:radius 20, \:proposals {\:acceleration 1, \:rotation -2.345136, \:transfer [{\:self puck-1082, \:other puck-1078, \:bid {}, \:ask \#}]}, \:just-collided false, \:active true, \:id puck-1082, \:core-color [0 255 0], \:position [652.2886938139176 736.3236466351844], \:eye-color [255 255 0], \:mobile true, \:velocity [-2.8596007328491666 2.7969060850676613]} {\:rotation 1.855639934539795, \:color [128 255 0], \:solid true, \:steps 39, \:energy 0.8019999999999998, \:radius 20, \:proposals {\:acceleration 1, \:rotation 1.8556399, \:transfer []}, \:just-collided false, \:active true, \:id puck-1080, \:core-color [0 255 0], \:position [5.384725944599863 753.7339998389651], \:eye-color [255 255 0], \:mobile true, \:velocity [3.838822449948592 1.124029447021157]} {\:vent true, \:rotation 0.623824165640358, \:color [255 255 255], \:solid true, \:steps 49, \:energy 1, \:radius 50, \:proposals {\:transfer []}, \:just-collided false, \:id puck-1075, \:position [700 500], \:mobile false, \:velocity [0 0]} {\:rotation 4.045812706401674, \:color [207 19 200], \:solid true, \:zapper true, \:steps 49, \:energy 1, \:radius 50, \:proposals {\:transfer []}, \:just-collided false, \:id puck-1076, \:position [100 500], \:mobile false, \:velocity [0 0]} {\:rotation 3.9483649032752286, \:color [139 0 0], \:solid true, \:nursery true, \:steps 49, \:energy 1, \:radius 50, \:proposals {}, \:just-collided false, \:id puck-1077, \:position [700 300], \:mobile false, \:velocity [0 0]}])" "(def foo (pusher))" "(\:plush foo)" "(\:plush (\:genome (\:memory foo)))" "(def bar (\:plush (\:genome (\:memory foo))))" "(def baz (\:genome (clojush.pushgp.genetic-operators/uniform-mutation \\n {\:genome (\:plush genome)} \\n @clojush.pushgp.pushgp/push-argmap)))" "(def baz (\:genome (clojush.pushgp.genetic-operators/uniform-mutation \\n {\:genome bar} \\n @clojush.pushgp.pushgp/push-argmap)))" "baz" "(first bar)" "(first baz)" "(clojush.pushstate/registered-for-stacks [\:integer \:float \:boolean \:exec])" "(count (clojush.pushstate/registered-for-stacks [\:integer \:float \:boolean \:exec]))" "(Math/abs 1.2)" "(Math/abs 2)" "(pusher)" "@args/push-argmap" "(\:max-points (args/push-argmap))" "(\:max-points (@args/push-argmap))" "(\:max-points @args/push-argmap)"] eclipse.preferences.version=1 diff --git a/bin/pucks/agents/vent.clj b/bin/pucks/agents/vent.clj index 70edc98..3de2a1b 100644 --- a/bin/pucks/agents/vent.clj +++ b/bin/pucks/agents/vent.clj @@ -28,7 +28,8 @@ (defn vent-proposals [p] {:transfer (into [] (for [recipient (filter (complement :torpedo) - (filter :mobile (:overlaps p)))] + (filter (complement :stone) + (filter :mobile (:overlaps p))))] {:self (:id p) :other (:id recipient) :bid {:energy 0.01} diff --git a/bin/pucks/util.clj b/bin/pucks/util.clj index acf55ad..c62baeb 100644 --- a/bin/pucks/util.clj +++ b/bin/pucks/util.clj @@ -121,8 +121,9 @@ size." [a] (-> a (assoc :neighbors (mapv #(do {:abbrev (:id %)}) (:neighbors a))) - (dissoc :sensed (mapv #(do {:abbrev (:id %)}) (:sensed a))) - (dissoc :overlaps (mapv #(do {:abbrev (:id %)}) (:overlaps a))))) + (assoc :sensed (mapv #(do {:abbrev (:id %)}) (:sensed a))) + (assoc :overlaps (mapv #(do {:abbrev (:id %)}) (:overlaps a))) + (assoc :proposals (assoc (:proposals a) :spawn :abbrev)))) (defn print-stats [] "Prints a statistics about the state of the world." diff --git a/project.clj b/project.clj index 2d33b96..c0454b1 100644 --- a/project.clj +++ b/project.clj @@ -3,8 +3,9 @@ :url "http://example.com/FIXME" :license {:name "Eclipse Public License" :url "https://github.com/lspector/pucks"} - :dependencies [[org.clojure/clojure "1.6.0"] - [quil "2.2.2"]] + :dependencies [[org.clojure/clojure "1.7.0"] + [quil "2.4.0"] + [clojush "2.8.0"]] :main pucks.core :target-path "target/%s" :profiles {:uberjar {:aot :all}} diff --git a/src/pucks/agents/pusher.clj b/src/pucks/agents/pusher.clj new file mode 100644 index 0000000..bbf06c8 --- /dev/null +++ b/src/pucks/agents/pusher.clj @@ -0,0 +1,247 @@ + +;; Definitions for pusher agents. + +(ns pucks.agents.pusher + (:use [pucks globals util vec2D] + pucks.agents.active) + (:require [clojush.interpreter :as interpreter] + [clojush.pushstate :as pushstate] + [clojush.pushgp.genetic-operators :as genetic-operators] + [clojush.args :as args] + [clojush.random :as random] + [clojush.translate :as translate] + [clojush.instructions.tag :as tag])) + +(args/reset-globals + {:max-points 100 + :evalpush-limit 200 + :uniform-mutation-rate 0.1 + :atom-generators (concat (pushstate/registered-for-stacks [:integer :float :boolean :exec]) + (repeat 100 (fn [] (- 100.0 (random/lrand 201.0)))) + (repeat 100 (fn [] (- 100 (random/lrand-int 201)))) + ['tag_float_5000 ;; enrich concentration of tags for actions + 'tagged_5000 + 'tag_float_6000 + 'tagged_6000 + 'tag_float_7000 + 'tagged_7000 + 'tag_float_8000 + 'tagged_8000 + 'tag_float_8100 + 'tagged_8100 + 'tag_float_8200 + 'tagged_8200 + 'tag_float_8300 + 'tagged_8300 + 'tag_float_8400 + 'tagged_8400 + 'tag_float_8500 + 'tagged_8500 + 'tag_float_8600 + 'tagged_8600 + 'tag_float_8700 + 'tagged_8700 + 'tag_float_8800 + 'tagged_8800 + (tag/tag-instruction-erc [:float] 10000) + ;(tag/untag-instruction-erc 10000) + (tag/tagged-instruction-erc 10000)])}) + +(defn self [p1 p2 tolerance color-key] + "Returns true if puck p1 would consider puck p2 to be 'self' rather than +'other', meaning that each color component is within p1's color difference +tolerance." + (let [[r1 g1 b1] (color-key p1) + [r2 g2 b2] (color-key p2)] + (and (< (Math/abs (float (- r1 r2))) tolerance) + (< (Math/abs (float (- g1 g2))) tolerance) + (< (Math/abs (float (- b1 b2))) tolerance)))) + +(defn top-with-default + [type default pushstate] + (let [t (pushstate/top-item type pushstate)] + (if (= t :no-stack-item) + default + t))) + +(defn keep-number-reasonable + "Returns a version of n that obeys limit parameters. LOCAL VERSION WITH ITS OWN LIMITS." + [n] + (let [max-number-magnitude 1000000 + min-number-magnitude 0.0000001] + (cond + (integer? n) + (cond + (> n max-number-magnitude) max-number-magnitude + (< n (- max-number-magnitude)) (- max-number-magnitude) + :else n) + :else + (cond + (> n max-number-magnitude) (* 1.0 max-number-magnitude) + (< n (- max-number-magnitude)) (* 1.0 (- max-number-magnitude)) + (and (< n min-number-magnitude) (> n (- min-number-magnitude))) 0.0 + :else n)))) + +(defn tagged-float [tag push-state] + (let [tagged-value (second (tag/closest-association tag push-state))] + (keep-number-reasonable + (cond (float? tagged-value) tagged-value + (integer? tagged-value) (float (keep-number-reasonable tagged-value)) + :else 1.0)))) + +(defn tagged-integer [tag push-state] + (let [tagged-value (second (tag/closest-association tag push-state))] + (keep-number-reasonable + (cond (integer? tagged-value) tagged-value + (float? tagged-value) (int (keep-number-reasonable tagged-value)) + :else 1)))) + +(defn pusher-proposals [p] + (if-let [g (:genome (:memory p))] + (let [;; neighboring puck info + selves (filter #(self p % 0.1 :color) + (filter :mobile (:sensed p))) + average-selves-velocity (apply avgv (map :velocity selves)) + average-selves-position (apply avgv (map :position selves)) + others (vec (clojure.set/difference (set (filter :mobile (:sensed p))) + (set selves))) + average-others-velocity (apply avgv (map :velocity others)) + average-others-position (apply avgv (map :position others)) + vents (filter :vent (:sensed p)) + average-vents-position (apply avgv (map :position vents)) + zappers (filter :zapper (:sensed p)) + average-zappers-position (apply avgv (map :position zappers)) + stones (filter :stone (:sensed p)) + average-stones-position (apply avgv (map :position stones)) + ;; ==== sensor info to be made available in tag space ==== + ;; selves + average-selves-speed (length average-selves-velocity) + average-selves-rotation (relative-position->rotation average-selves-velocity) + average-selves-direction (relative-position->rotation average-selves-position) + average-selves-distance (length average-selves-position) + ;; others + average-others-speed (length average-others-velocity) + average-others-rotation (relative-position->rotation average-others-velocity) + average-others-direction (relative-position->rotation average-others-position) + average-others-distance (length average-others-position) + ;; vents + average-vents-direction (relative-position->rotation average-vents-position) + average-vents-distance (length average-vents-position) + ;; zappers + average-zappers-direction (relative-position->rotation average-zappers-position) + average-zappers-distance (length average-zappers-position) + ;; stones + average-stones-direction (relative-position->rotation average-stones-position) + average-stones-distance (length average-stones-position) + ;; self properties + rotation (:rotation p) + thrust-angle (:thrust-angle p) + steps (:steps p) + energy (:energy p) + [red green blue] (:color p) + [eye-red eye-green eye-blue] (:eye-color p) + [core-red core-green core-blue] (:core-color p) + speed (length (:velocity p)) + direction-of-motion (relative-position->rotation (:velocity p)) + ;; ==== program result ==== + push-result (interpreter/run-push + (:push g) + (merge (pushstate/make-push-state) + {:tag (merge (into (sorted-map) (:tag (:memory p))) + (let [to-tag [average-vents-direction + average-vents-distance + average-zappers-direction + average-zappers-distance + average-stones-direction + average-stones-distance + average-selves-speed + average-selves-rotation + average-selves-direction + average-selves-distance + average-others-speed + average-others-rotation + average-others-direction + average-others-distance + rotation + thrust-angle + steps + energy + red + green + blue + eye-red + eye-green + eye-blue + core-red + core-green + core-blue + speed + direction-of-motion]] + (zipmap (iterate (partial + (quot 5000 (count to-tag))) 0) + to-tag)))}))] + (merge {:acceleration (tagged-float 5000 push-result) + :rotation (tagged-float 6000 push-result) + :thrust-angle (tagged-float 7000 push-result) + :properties {:color [(tagged-integer 8000 push-result) + (tagged-integer 8100 push-result) + (tagged-integer 8200 push-result)] + :eye-color [(tagged-integer 8300 push-result) + (tagged-integer 8400 push-result) + (tagged-integer 8500 push-result)] + :core-color [(tagged-integer 8600 push-result) + (tagged-integer 8700 push-result) + (tagged-integer 8800 push-result)] + } + :memory {:tag (:tag push-result)} + } + (if (zero? (mod (:steps p) 20)) + {:spawn [((:spawn-function p) p)]} + {:transfer (concat (for [binder (filter :pusher (:overlaps p))] + {:self (:id p) + :other (:id binder) + :bid {:bound-to (:id p)} + :ask {:bound-to (:id binder)}}) + (for [weaker (filter #(< (:energy %) + (:energy p)) + (filter :pusher (:overlaps p)))] + {:self (:id p) + :other (:id weaker) + :bid {:energy 0.01} + :ask {}}))}))))) + +(defn mutate + "Returns a mutated version of the provided genome." + [plush-genome] + (let [new-plush-genome (:genome (genetic-operators/alternation + (genetic-operators/uniform-mutation + {:genome plush-genome} + @args/push-argmap) + (genetic-operators/uniform-mutation + {:genome plush-genome} + @args/push-argmap) + @args/push-argmap))] + {:plush new-plush-genome + :push (translate/translate-plush-genome-to-push-program + {:genome new-plush-genome} + @args/push-argmap)})) + +(defn pusher + "Returns a random pusher puck." + [] + (let [plush-genome (random/random-plush-genome + (/ (:max-points @args/push-argmap) 4) + (:atom-generators @args/push-argmap))] + (merge (active) + {:color [0 0 255] + :pusher true + :proposal-function pusher-proposals + :memory {:genome {:plush plush-genome + :push (translate/translate-plush-genome-to-push-program + {:genome plush-genome} + @args/push-argmap)}} + :spawn-function #(merge % + {:velocity [(* 10 (- (rand) 0.5)) (* 10 (- (rand) 0.5))] + :rotation (* two-pi (rand)) + ;; position will be relative to position of parent + :position [(* 10 (- (rand-int 3) 1)) (* 10 (- (rand-int 3) 1))] + :memory {:genome (mutate (:plush (:genome (:memory %))))}})}))) diff --git a/src/pucks/agents/spanner.clj b/src/pucks/agents/spanner.clj new file mode 100644 index 0000000..60083ac --- /dev/null +++ b/src/pucks/agents/spanner.clj @@ -0,0 +1,170 @@ + +;; Definitions for spanner agents. + +(ns pucks.agents.spanner + (:use [pucks globals util vec2D] + pucks.agents.active)) + +(defn rand-relative-position + "Returns a random relative-position vector." + [] + (rotation->relative-position (- (rand two-pi) pi))) + +(defn rand-urge + "Returns a random urge level, which will be between -1.0 and 1.0." + [] + (- (rand 2.0) 1.0)) + +(defn rand-probability + "Returns a random probability between 0 and 1.0." + [] + (rand 1.0)) + +(defn rand-color + "Returns a random color." + [] + [(rand-int 256) (rand-int 256) (rand-int 256)]) + +(defn rand-color-difference + "Returns a random color difference (an integer between 0 and 255)." + [] + (rand-int 256)) + +(defn self [p1 p2 tolerance color-key] + "Returns true if puck p1 would consider puck p2 to be 'self' rather than +'other', meaning that each color component is within p1's color difference +tolerance." + (let [[r1 g1 b1] (color-key p1) + [r2 g2 b2] (color-key p2)] + (and (< (Math/abs (- r1 r2)) tolerance) + (< (Math/abs (- g1 g2)) tolerance) + (< (Math/abs (- b1 b2)) tolerance)))) + +(defn facing [p1 p2] + "Returns true if puck p1 is facing puck p2, assuming p1 is sensing p2 +and that p2's position is relative to p1's." + (< (rotational-difference (:rotation p1) + (relative-position->rotation (:position p2))) + quarter-pi)) + +(defn spanner-proposals [p] + (if-let [g (:genome (:memory p))] + (let [selves (filter #(self p % (:color-difference g) :color) + (filter :mobile (:sensed p))) + others (filter #(not (self p % (:color-difference g) :color)) + (filter :mobile (:sensed p))) + vents (filter :vent (:sensed p)) + zappers (filter :zapper (:sensed p))] + (merge {:acceleration 0.1 + :properties {:color (:color g) + :eye-color (:eye-color g) + :core-color (:core-color g)} + :rotation (relative-position->rotation + (+v (rotation->relative-position (:rotation p)) + (if (empty? selves) + [0 0] + (*v (:self-flock-urge g) + (limit1 (apply avgv (map :velocity selves))))) + (if (empty? others) + [0 0] + (*v (:other-flock-urge g) + (limit1 (apply avgv (map :velocity others))))) + (if (empty? selves) + [0 0] + (*v (:self-cluster-urge g) + (limit1 (apply avgv (map :position selves))))) + (if (empty? others) + [0 0] + (*v (:other-cluster-urge g) + (limit1 (apply avgv (map :position others))))) + (if (empty? vents) + [0 0] + (*v (:vent-urge g) + (limit1 (apply avgv (map :position vents))))) + (if (empty? zappers) + [0 0] + (*v (:zapper-urge g) + (limit1 (apply avgv (map :position zappers))))) + (*v (:random-urge g) + (rand-relative-position))))} + (if (> (* (:spawn-probability g) 0.1) + (rand)) + {:spawn [((:spawn-function p) p)]} + {}) + {:transfer (concat (for [binder + (filter #(self p % (:color-difference g) :eye-color) + (filter :spanner (:overlaps p)))] + {:self (:id p) + :other (:id binder) + :bid {:bound-to (:id p)} + :ask {:bound-to (:id binder)}}) + (for [weaker (filter #(< (:energy %) + (:energy p)) + (filter #(self p % (:color-difference g) :core-color) + (filter :spanner (:overlaps p))))] + {:self (:id p) + :other (:id weaker) + :bid {:energy 0.01} + :ask {}}))})))) + +(defn mutate-color + "Returns a mutated version of color vector c." + [c] + (mapv #(mod (+ % (- (rand-int 33) 16)) 256) c)) + +(defn mutate-urge + "Returns a mutated version of urge value u." + [u] + (max -1.0 (min 1.0 (+ u (- (rand 0.1) 0.05))))) + +(defn mutate-probability + "Returns a mutated version of probability value p." + [p] + (max 0.0 (min 1.0 (+ p (- (rand 0.05) 0.025))))) + +(defn mutate-color-difference + "Returns a mutated version of color-difference value d." + [d] + (max 0 (min 255 (+ d (- (rand-int 17) 8))))) + +(defn mutate + "Returns a mutated version of the provided genome." + [genome] + (-> genome + (assoc :color (mutate-color (:color genome))) + (assoc :eye-color (mutate-color (:eye-color genome))) + (assoc :core-color (mutate-color (:core-color genome))) + (assoc :self-flock-urge (mutate-urge (:self-flock-urge genome))) + (assoc :other-flock-urge (mutate-urge (:other-flock-urge genome))) + (assoc :self-cluster-urge (mutate-urge (:self-cluster-urge genome))) + (assoc :other-cluster-urge (mutate-urge (:other-cluster-urge genome))) + (assoc :color-difference (mutate-color-difference (:color-difference genome))) + (assoc :random-urge (mutate-urge (:random-urge genome))) + (assoc :vent-urge (mutate-urge (:vent-urge genome))) + (assoc :zapper-urge (mutate-urge (:zapper-urge genome))) + (assoc :spawn-probability (mutate-probability (:spawn-probability genome))))) + +(defn spanner + "Returns a random spanner puck." + [] + (merge (active) + {:spanner true + :proposal-function spanner-proposals + :memory {:genome {:color (rand-color) + :eye-color (rand-color) + :core-color (rand-color) + :self-flock-urge (rand-urge) + :other-flock-urge (rand-urge) + :self-cluster-urge (rand-urge) + :other-cluster-urge (rand-urge) + :color-difference (rand-color-difference) + :random-urge (rand-urge) + :vent-urge (rand-urge) + :zapper-urge (rand-urge) + :spawn-probability (rand-probability)}} + :spawn-function #(merge % + {:velocity [(* 5 (- (rand) 0.5)) (* 5 (- (rand) 0.5))] + :rotation (* two-pi (rand)) + ;; position will be relative to position of parent + :position [(- (rand-int 3) 1) (- (rand-int 3) 1)] + :memory {:genome (mutate (:genome (:memory %)))}})})) diff --git a/src/pucks/agents/vent.clj b/src/pucks/agents/vent.clj index 70edc98..3de2a1b 100644 --- a/src/pucks/agents/vent.clj +++ b/src/pucks/agents/vent.clj @@ -28,7 +28,8 @@ (defn vent-proposals [p] {:transfer (into [] (for [recipient (filter (complement :torpedo) - (filter :mobile (:overlaps p)))] + (filter (complement :stone) + (filter :mobile (:overlaps p))))] {:self (:id p) :other (:id recipient) :bid {:energy 0.01} diff --git a/src/pucks/core.clj b/src/pucks/core.clj index 106a79f..63960f8 100644 --- a/src/pucks/core.clj +++ b/src/pucks/core.clj @@ -62,7 +62,8 @@ GUI interactions." scaled-y (int (/ (mouse-y) (:scale @pucks-settings)))] ;(pprint (mapv abbreviate-embedded-agents ; (objects-overlapping-xy scaled-x scaled-y))) - (inspect-tree (objects-overlapping-xy scaled-x scaled-y))))) + ;(inspect-tree (objects-overlapping-xy scaled-x scaled-y)) + (inspect-tree (mapv abbreviate-embedded-agents (objects-overlapping-xy scaled-x scaled-y)))))) (defn run-pucks [agents settings] "Run a pucks simulation with the provided agents and settings (which will @@ -77,7 +78,8 @@ be merged with the defaults)." :title "pucks" :setup setup :draw draw - :size [scaled-screen-size scaled-screen-size]))) + :size [scaled-screen-size scaled-screen-size] + :features [:exit-on-close]))) (defn -main "This main function allows simulations to be run from the command line with: diff --git a/src/pucks/physics.clj b/src/pucks/physics.clj index af7a2b7..6632f23 100644 --- a/src/pucks/physics.clj +++ b/src/pucks/physics.clj @@ -273,7 +273,10 @@ changes to the world." (mapv -v (mapv :position colliding-neighbors))))) [0 0]) - just-collided (not (zero? (length anti-collision-a))) + just-collided (and mobile + (not (zero? (length anti-collision-a))) + (some (fn [neigh] (not (some #{(:id neigh)} (:bound-to agent)))) + colliding-neighbors)) new-a (limit-vec2D (+v proposed-a anti-collision-a) (* (if just-collided 10 1) (:max-acceleration @pucks-settings))) @@ -391,8 +394,16 @@ changes to the world." (min 1 (max 0 (- energy - (if mobile (:cost-of-living @pucks-settings) 0) - (if just-collided (:cost-of-collision @pucks-settings) 0) + (if (and mobile + (not (:stone agent))) + (:cost-of-living @pucks-settings) + 0) + (if (and just-collided + (not (:vent agent)) + (not (:nursery agent)) + (not (:stone agent))) + (:cost-of-collision @pucks-settings) + 0) (if (:vent agent) -0.005 0) (if (and (:fire-torpedo proposals) (> energy 0.1)) diff --git a/src/pucks/reap.clj b/src/pucks/reap.clj index dfe6d35..623506c 100644 --- a/src/pucks/reap.clj +++ b/src/pucks/reap.clj @@ -12,6 +12,7 @@ (let [with-corpses (mapv #(if (and (:mobile %) (not (pos? (:energy %)))) (merge % {:corpse true + :solid false :death-step (:steps %) :mobile false :color [100 100 100] diff --git a/src/pucks/util.clj b/src/pucks/util.clj index acf55ad..c62baeb 100644 --- a/src/pucks/util.clj +++ b/src/pucks/util.clj @@ -121,8 +121,9 @@ size." [a] (-> a (assoc :neighbors (mapv #(do {:abbrev (:id %)}) (:neighbors a))) - (dissoc :sensed (mapv #(do {:abbrev (:id %)}) (:sensed a))) - (dissoc :overlaps (mapv #(do {:abbrev (:id %)}) (:overlaps a))))) + (assoc :sensed (mapv #(do {:abbrev (:id %)}) (:sensed a))) + (assoc :overlaps (mapv #(do {:abbrev (:id %)}) (:overlaps a))) + (assoc :proposals (assoc (:proposals a) :spawn :abbrev)))) (defn print-stats [] "Prints a statistics about the state of the world." diff --git a/src/pucks/worlds/dev/world21.clj b/src/pucks/worlds/dev/world21.clj new file mode 100644 index 0000000..fabf50e --- /dev/null +++ b/src/pucks/worlds/dev/world21.clj @@ -0,0 +1,29 @@ +(ns pucks.worlds.dev.world21 + (:use [pucks core globals] + [pucks.agents vent nursery zapper spanner])) + +(defn agents [] + [(assoc (vent) :position [100 100]) + (assoc (vent) :position [100 300]) + (assoc (vent) :position [300 100]) + (assoc (vent) :position [300 300]) + (assoc (nursery spanner) :position [200 200])]) + +(defn agents [] + (vec (concat + (for [x (range 100 600 200) + y (range 100 600 200)] + (assoc (vent) :position [x y])) + [(assoc (nursery spanner) :position [200 200])]))) + +(defn settings [] + {:screen-size 400 + :scale 1.5 + :single-thread-mode false + :nursery-threshold 25 + :neighborhood-size 150 + :max-velocity 40 + :cost-of-living 0.0001 + :cost-of-collision 0.01}) + +;(run-pucks (agents) (settings)) \ No newline at end of file diff --git a/src/pucks/worlds/dev/world22.clj b/src/pucks/worlds/dev/world22.clj new file mode 100644 index 0000000..166beb6 --- /dev/null +++ b/src/pucks/worlds/dev/world22.clj @@ -0,0 +1,32 @@ +(ns pucks.worlds.dev.world22 + (:use [pucks core globals] + [pucks.agents stone vent nursery zapper pusher linear shooter startstop zigzag])) + +(defn horizontal-wall [[x-min x-max] y] + (for [x (range x-min x-max 20)] + (merge (stone) {:position [x y]}))) + +(defn vertical-wall [x [y-min y-max]] + (for [y (range y-min y-max 20)] + (merge (stone) {:position [x y]}))) + +(defn agents [] + (vec (concat + (for [x (range 100 1200 200) + y (range 100 1200 200)] + (assoc (vent) :position [x y] :mobile false :solid false)) + (for [x (range 50 1200 100) + y (range 50 1200 100)] + (assoc (stone) :position [x y] :mobile false)) + [(assoc (nursery pusher) :position [600 600] :solid false)]))) + +(defn settings [] + {:screen-size 1200 + :scale 0.6 + :single-thread-mode false + :nursery-threshold 1 ;20 ;1000 + :neighborhood-size 150 + :cost-of-collision 0.01 + }) + +;(run-pucks (agents) (settings)) \ No newline at end of file diff --git a/src/pucks/worlds/dev/world23.clj b/src/pucks/worlds/dev/world23.clj new file mode 100644 index 0000000..81dfeec --- /dev/null +++ b/src/pucks/worlds/dev/world23.clj @@ -0,0 +1,39 @@ +(ns pucks.worlds.dev.world23 + (:use [pucks core globals] + [pucks.agents stone vent nursery zapper pusher linear shooter startstop zigzag])) + +(defn horizontal-wall [[x-min x-max] y] + (for [x (range x-min x-max 20)] + (merge (stone) {:position [x y]}))) + +(defn vertical-wall [x [y-min y-max]] + (for [y (range y-min y-max 20)] + (merge (stone) {:position [x y]}))) + +(defn agents [] + [(assoc (nursery pusher) :position [200 200] :solid false) + (assoc (vent) :position [400 400] :solid false) + (assoc (vent) :position [500 100] :solid false) + (assoc (vent) :position [100 500] :solid false) + (assoc (vent) :position [266 466] :solid false) + (assoc (vent) :position [466 266] :solid false) + ] + #_(vec (concat + #_(for [x (range 100 600 400 #_200) + y (range 100 600 400 #_200)] + (assoc (vent) :position [x y] :mobile false :solid false)) + #_(for [x (range 50 600 100) + y (range 50 600 100)] + (assoc (stone) :position [x y] :mobile false)) + [(assoc (nursery pusher) :position [200 200] :solid false)]))) + +(defn settings [] + {:screen-size 600 + :scale 1.0 + :single-thread-mode false + :nursery-threshold 1000 + :neighborhood-size 150 + :cost-of-collision 0.01 + }) + +;(run-pucks (agents) (settings)) \ No newline at end of file diff --git a/target/base+system+user+dev+repl/classes/META-INF/maven/pucks/pucks/pom.properties b/target/base+system+user+dev+repl/classes/META-INF/maven/pucks/pucks/pom.properties index 86f6b84..bd1c3c9 100644 --- a/target/base+system+user+dev+repl/classes/META-INF/maven/pucks/pucks/pom.properties +++ b/target/base+system+user+dev+repl/classes/META-INF/maven/pucks/pucks/pom.properties @@ -1,6 +1,6 @@ #Leiningen -#Sat Sep 27 09:35:01 EDT 2014 -version=0.1.1 -revision=4824218700c24f12cca5e928682a5ec31b90fd06\n +#Tue Nov 03 22:48:49 EST 2015 +version=0.1.25 +revision=3827505bda5961f4c6d4dd5c261d429ac79d5d09 groupId=pucks artifactId=pucks diff --git a/target/base+system+user+dev+repl/stale/extract-native.dependencies b/target/base+system+user+dev+repl/stale/extract-native.dependencies index 038e871..179f776 100644 --- a/target/base+system+user+dev+repl/stale/extract-native.dependencies +++ b/target/base+system+user+dev+repl/stale/extract-native.dependencies @@ -1 +1 @@ -([:dependencies ([org.clojure/clojure "1.5.1"] [quil/quil "2.2.2"] [org.clojure/tools.nrepl "0.2.6" :exclusions ([org.clojure/clojure]) :scope "test"] [clojure-complete/clojure-complete "0.2.3" :exclusions ([org.clojure/clojure]) :scope "test"])]) \ No newline at end of file +([:dependencies ([ccw/ccw.server "0.1.1"] [org.clojure/clojure "1.7.0"] [quil/quil "2.2.2"] [clojush/clojush "2.0.40"] [org.clojure/tools.nrepl "0.2.6" :exclusions [org.clojure/clojure] :scope "test"] [clojure-complete "0.2.3" :exclusions [org.clojure/clojure] :scope "test"])]) \ No newline at end of file diff --git a/target/base+system+user+dev/stale/extract-native.dependencies b/target/base+system+user+dev/stale/extract-native.dependencies index 96dbb46..7cb774c 100644 --- a/target/base+system+user+dev/stale/extract-native.dependencies +++ b/target/base+system+user+dev/stale/extract-native.dependencies @@ -1 +1 @@ -([:dependencies ([org.clojure/clojure "1.6.0"] [quil/quil "2.2.2"] [org.clojure/tools.nrepl "0.2.6" :exclusions ([org.clojure/clojure]) :scope "test"] [clojure-complete/clojure-complete "0.2.3" :exclusions ([org.clojure/clojure]) :scope "test"])]) \ No newline at end of file +([:dependencies ([cider/cider-nrepl "0.8.1"] [org.clojure/clojure "1.7.0"] [quil/quil "2.4.0"] [clojush/clojush "2.8.0"] [org.clojure/tools.nrepl "0.2.10" :exclusions ([org.clojure/clojure])] [clojure-complete/clojure-complete "0.2.3" :exclusions ([org.clojure/clojure])])]) \ No newline at end of file