Advertisement
Carcigenicate

Game of Life Enviro New

Mar 24th, 2017
126
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. (ns game-of-life.color.environment
  2.   (:require [helpers.general-helpers :as g]
  3.             [clojure.string :as s]))
  4.  
  5. (declare string-format-env)
  6.  
  7. (defrecord Enviroment [cells dimensions]
  8.   Object
  9.   (toString [self] (string-format-env self)))
  10.  
  11. (def dead-state ::dead)
  12.  
  13. (defn index-of [area-width x y]
  14.   (+ (* y area-width)
  15.      x))
  16.  
  17. (defn env-index-of [env x y]
  18.   (let [w (-> env :dimensions (get 0))]
  19.     (index-of w x y)))
  20.  
  21. (defn checked-index-of [area-dimensions x y]
  22.   (let [[w h] area-dimensions]
  23.     (if (and (<= 0 x w)
  24.              (<= 0 y h))
  25.       (index-of w x y)
  26.  
  27.       (throw (IndexOutOfBoundsException. (str "["x " " y
  28.                                               "] out of bounds. Dimensions: ["
  29.                                               w " " h "]"))))))
  30.  
  31. (defn random-cells [dimensions cell-states chance-of-life rand-gen]
  32.   (let [[w h] dimensions
  33.         len (* w h)]
  34.     (vec
  35.       (for [_ (range len)]
  36.         (if (g/random-perc chance-of-life rand-gen)
  37.           (g/random-from-collection cell-states rand-gen)
  38.           dead-state)))))
  39.  
  40. (defn state-at [env x y]
  41.   ((:cells env) (env-index-of env x y)))
  42.  
  43. (defn alive-at? [env x y]
  44.   (not= (state-at env x y)
  45.         dead-state))
  46.  
  47. (defn set-state-at [env x y new-state]
  48.   (assoc-in env
  49.             [:cells (env-index-of env x y)]
  50.             new-state))
  51.  
  52. (defn coords-surrounding [env depth x y]
  53.   (let [{[w h] :dimensions} env
  54.         ; Bound checks to ensure oob cells aren't checked
  55.         x-min (max 0 (- x depth)) ; TODO: Eww
  56.         x-max (min w (inc (+ x depth)))
  57.         y-min (max 0 (- y depth))
  58.         y-max (min h (inc (+ y depth)))]
  59.     (for [ry (range y-min y-max)
  60.           rx (range x-min x-max)
  61.           :when (not (and (= x rx) (= y ry)))]
  62.       [rx ry])))
  63.  
  64. (defn wrap-dimension [dimension-length position]
  65.   (g/wrap position 0 (dec dimension-length)))
  66.  
  67. (defn wrapping-coords-surrounding [env depth x y]
  68.   (let [{[w h] :dimensions} env
  69.         ; Bound checks to ensure oob cells aren't checked
  70.         x-min (- x depth) ; TODO: Eww
  71.         x-max (inc (+ x depth))
  72.         y-min (- y depth)
  73.         y-max (inc (+ y depth))]
  74.     (for [ry (range y-min y-max)
  75.           rx (range x-min x-max)
  76.           :when (not (and (= x rx) (= y ry)))]
  77.       [(wrap-dimension w rx)
  78.        (wrap-dimension h ry)])))
  79.  
  80. (defn cell-states-surrounding [env depth x y]
  81.   (vec
  82.     (for [[rx ry] (wrapping-coords-surrounding env depth x y)]
  83.       (state-at env rx ry))))
  84.  
  85. (defn count-alive-neighbors [neighbors]
  86.   (->> neighbors
  87.       (remove #(= dead-state %))
  88.       (count)))
  89.  
  90. (defn cell-should-live? [env neighbors x y]
  91.   (let [n (count-alive-neighbors neighbors)
  92.         alive? (alive-at? env x y)]
  93.     (or (and (not alive?) (= n 3))
  94.         (and (<= 2 n 3) alive?))))
  95.  
  96. (defn decide-child-state [neighbors]
  97.   (let [state-freqs (frequencies neighbors)
  98.         alive-freqs (dissoc state-freqs dead-state)]
  99.     (key
  100.       (apply max-key val alive-freqs))))
  101.  
  102. (defn advance-environment [env]
  103.   (let [{[w h] :dimensions} env
  104.         cells (for [y (range 0 h)
  105.                     x (range 0 w)]
  106.                 [x y])]
  107.     (reduce
  108.       (fn [acc-env [x y]]
  109.         (let [neighbors (cell-states-surrounding env 1 x y)]
  110.           (set-state-at acc-env x y
  111.             (if (cell-should-live? env neighbors x y)
  112.               (decide-child-state neighbors)
  113.               dead-state))))
  114.       env
  115.       cells)))
  116.  
  117. (defn kill-all-cells [env]
  118.   (update env :cells
  119.     #(mapv (constantly dead-state) %)))
  120.  
  121. (defn random-environment [cell-states dimensions chance-of-life rand-gen]
  122.   (->Enviroment
  123.     (random-cells dimensions cell-states chance-of-life rand-gen)
  124.     dimensions))
  125.  
  126. (defn dead-environment [dimensions]
  127.   (->Enviroment (vec (repeat (apply * dimensions) dead-state))
  128.                 dimensions))
  129.  
  130. (defn string-format-env [env]
  131.   (let [{cells :cells [w] :dimensions} env
  132.         neat-cells (map #(if (= % dead-state) " " %) cells)
  133.         part-cells (map #(s/join " " %) (partition w neat-cells))
  134.         joined (s/join "\n" part-cells)]
  135.     joined))
  136.  
  137. (defn select-pop-env [dims position-map]
  138.   (let [env (dead-environment dims)]
  139.     (reduce
  140.       (fn [e [[x y] cell-state]]
  141.         (set-state-at e x y cell-state))
  142.       env
  143.       position-map)))
  144.  
  145. (defn select-pop-env-rand-states [dims cells-states rand-gen positions]
  146.   (let [pos-map (reduce #(assoc % %2
  147.                            (g/random-from-collection cells-states rand-gen))
  148.                         {} positions)]
  149.     (select-pop-env dims pos-map)))
  150.  
  151. (def simple-env
  152.   (select-pop-env-rand-states [5 5] #{\A \B \C} (g/new-rand-gen 99)
  153.     [[2 0]
  154.      [0 1] [1 1] [2 1]
  155.      [2 2]
  156.      [1 3] [3 3] [4 3]
  157.      [3 4]]))
  158.  
  159. (def struct-env
  160.   (select-pop-env-rand-states [25 25] #{\A \B \C} (g/new-rand-gen 99)
  161.     [; Blinker
  162.      [2 2]
  163.      [2 3]
  164.      [2 4]
  165.  
  166.      ; Toad
  167.      [3 7]
  168.      [4 7]
  169.      [5 7]
  170.      [2 8]
  171.      [3 8]
  172.      [4 8]
  173.  
  174.      ; Glider
  175.      [6 2]
  176.      [7 2]
  177.      [8 2]
  178.      [8 1]
  179.      [7 0]
  180.  
  181.      ; Beacon
  182.      [9 9]
  183.      [9 10]
  184.      [10 9]
  185.      [10 10]
  186.      [11 11]
  187.      [11 12]
  188.      [12 11]
  189.      [12 12]]))
  190.  
  191.  
  192. (def test-env
  193.   (let [dims [5 5]
  194.         rand-gen (g/new-rand-gen 99)
  195.         cell-states #{\A \B \C \D}
  196.         a #(set-state-at % %2 %3 (g/random-from-collection cell-states rand-gen))
  197.         env (->Enviroment
  198.               (dead-environment dims)
  199.               dims)]
  200.     ; Simple [5 5]
  201.     (-> env)
  202.  
  203.  
  204.  
  205.  
  206.     ; Stable shapes [25 25]
  207.     #_
  208.     (-> env
  209.         ; Blinker
  210.         (a 2 2)
  211.         (a 2 3)
  212.         (a 2 4)
  213.  
  214.         ; Toad
  215.         (a 3 7)
  216.         (a 4 7)
  217.         (a 5 7)
  218.         (a 2 8)
  219.         (a 3 8)
  220.         (a 4 8)
  221.  
  222.         ; Glider
  223.         (a 6 2)
  224.         (a 7 2)
  225.         (a 8 2)
  226.         (a 8 1)
  227.         (a 7 0)
  228.  
  229.         ; Beacon
  230.         (a 9 9)
  231.         (a 9 10)
  232.         (a 10 9)
  233.         (a 10 10)
  234.         (a 11 11)
  235.         (a 11 12)
  236.         (a 12 11)
  237.         (a 12 12))))
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement